]> err.no Git - linux-2.6/blob - net/netlabel/netlabel_unlabeled.c
[NETLABEL]: Don't produce unused variables when IPv6 is off.
[linux-2.6] / net / netlabel / netlabel_unlabeled.c
1 /*
2  * NetLabel Unlabeled Support
3  *
4  * This file defines functions for dealing with unlabeled packets for the
5  * NetLabel system.  The NetLabel system manages static and dynamic label
6  * mappings for network protocols such as CIPSO and RIPSO.
7  *
8  * Author: Paul Moore <paul.moore@hp.com>
9  *
10  */
11
12 /*
13  * (c) Copyright Hewlett-Packard Development Company, L.P., 2006 - 2007
14  *
15  * This program is free software;  you can redistribute it and/or modify
16  * it under the terms of the GNU General Public License as published by
17  * the Free Software Foundation; either version 2 of the License, or
18  * (at your option) any later version.
19  *
20  * This program is distributed in the hope that it will be useful,
21  * but WITHOUT ANY WARRANTY;  without even the implied warranty of
22  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
23  * the GNU General Public License for more details.
24  *
25  * You should have received a copy of the GNU General Public License
26  * along with this program;  if not, write to the Free Software
27  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
28  *
29  */
30
31 #include <linux/types.h>
32 #include <linux/rcupdate.h>
33 #include <linux/list.h>
34 #include <linux/spinlock.h>
35 #include <linux/socket.h>
36 #include <linux/string.h>
37 #include <linux/skbuff.h>
38 #include <linux/audit.h>
39 #include <linux/in.h>
40 #include <linux/in6.h>
41 #include <linux/ip.h>
42 #include <linux/ipv6.h>
43 #include <linux/notifier.h>
44 #include <linux/netdevice.h>
45 #include <linux/security.h>
46 #include <net/sock.h>
47 #include <net/netlink.h>
48 #include <net/genetlink.h>
49 #include <net/ip.h>
50 #include <net/ipv6.h>
51 #include <net/net_namespace.h>
52 #include <net/netlabel.h>
53 #include <asm/bug.h>
54 #include <asm/atomic.h>
55
56 #include "netlabel_user.h"
57 #include "netlabel_domainhash.h"
58 #include "netlabel_unlabeled.h"
59 #include "netlabel_mgmt.h"
60
61 /* NOTE: at present we always use init's network namespace since we don't
62  *       presently support different namespaces even though the majority of
63  *       the functions in this file are "namespace safe" */
64
65 /* The unlabeled connection hash table which we use to map network interfaces
66  * and addresses of unlabeled packets to a user specified secid value for the
67  * LSM.  The hash table is used to lookup the network interface entry
68  * (struct netlbl_unlhsh_iface) and then the interface entry is used to
69  * lookup an IP address match from an ordered list.  If a network interface
70  * match can not be found in the hash table then the default entry
71  * (netlbl_unlhsh_def) is used.  The IP address entry list
72  * (struct netlbl_unlhsh_addr) is ordered such that the entries with a
73  * larger netmask come first.
74  */
75 struct netlbl_unlhsh_tbl {
76         struct list_head *tbl;
77         u32 size;
78 };
79 struct netlbl_unlhsh_addr4 {
80         __be32 addr;
81         __be32 mask;
82         u32 secid;
83
84         u32 valid;
85         struct list_head list;
86         struct rcu_head rcu;
87 };
88 struct netlbl_unlhsh_addr6 {
89         struct in6_addr addr;
90         struct in6_addr mask;
91         u32 secid;
92
93         u32 valid;
94         struct list_head list;
95         struct rcu_head rcu;
96 };
97 struct netlbl_unlhsh_iface {
98         int ifindex;
99         struct list_head addr4_list;
100         struct list_head addr6_list;
101
102         u32 valid;
103         struct list_head list;
104         struct rcu_head rcu;
105 };
106
107 /* Argument struct for netlbl_unlhsh_walk() */
108 struct netlbl_unlhsh_walk_arg {
109         struct netlink_callback *nl_cb;
110         struct sk_buff *skb;
111         u32 seq;
112 };
113
114 /* Unlabeled connection hash table */
115 /* updates should be so rare that having one spinlock for the entire
116  * hash table should be okay */
117 static DEFINE_SPINLOCK(netlbl_unlhsh_lock);
118 static struct netlbl_unlhsh_tbl *netlbl_unlhsh = NULL;
119 static struct netlbl_unlhsh_iface *netlbl_unlhsh_def = NULL;
120
121 /* Accept unlabeled packets flag */
122 static u8 netlabel_unlabel_acceptflg = 0;
123
124 /* NetLabel Generic NETLINK unlabeled family */
125 static struct genl_family netlbl_unlabel_gnl_family = {
126         .id = GENL_ID_GENERATE,
127         .hdrsize = 0,
128         .name = NETLBL_NLTYPE_UNLABELED_NAME,
129         .version = NETLBL_PROTO_VERSION,
130         .maxattr = NLBL_UNLABEL_A_MAX,
131 };
132
133 /* NetLabel Netlink attribute policy */
134 static const struct nla_policy netlbl_unlabel_genl_policy[NLBL_UNLABEL_A_MAX + 1] = {
135         [NLBL_UNLABEL_A_ACPTFLG] = { .type = NLA_U8 },
136         [NLBL_UNLABEL_A_IPV6ADDR] = { .type = NLA_BINARY,
137                                       .len = sizeof(struct in6_addr) },
138         [NLBL_UNLABEL_A_IPV6MASK] = { .type = NLA_BINARY,
139                                       .len = sizeof(struct in6_addr) },
140         [NLBL_UNLABEL_A_IPV4ADDR] = { .type = NLA_BINARY,
141                                       .len = sizeof(struct in_addr) },
142         [NLBL_UNLABEL_A_IPV4MASK] = { .type = NLA_BINARY,
143                                       .len = sizeof(struct in_addr) },
144         [NLBL_UNLABEL_A_IFACE] = { .type = NLA_NUL_STRING,
145                                    .len = IFNAMSIZ - 1 },
146         [NLBL_UNLABEL_A_SECCTX] = { .type = NLA_BINARY }
147 };
148
149 /*
150  * Audit Helper Functions
151  */
152
153 /**
154  * netlbl_unlabel_audit_addr4 - Audit an IPv4 address
155  * @audit_buf: audit buffer
156  * @dev: network interface
157  * @addr: IP address
158  * @mask: IP address mask
159  *
160  * Description:
161  * Write the IPv4 address and address mask, if necessary, to @audit_buf.
162  *
163  */
164 static void netlbl_unlabel_audit_addr4(struct audit_buffer *audit_buf,
165                                      const char *dev,
166                                      __be32 addr, __be32 mask)
167 {
168         u32 mask_val = ntohl(mask);
169
170         if (dev != NULL)
171                 audit_log_format(audit_buf, " netif=%s", dev);
172         audit_log_format(audit_buf, " src=" NIPQUAD_FMT, NIPQUAD(addr));
173         if (mask_val != 0xffffffff) {
174                 u32 mask_len = 0;
175                 while (mask_val > 0) {
176                         mask_val <<= 1;
177                         mask_len++;
178                 }
179                 audit_log_format(audit_buf, " src_prefixlen=%d", mask_len);
180         }
181 }
182
183 /**
184  * netlbl_unlabel_audit_addr6 - Audit an IPv6 address
185  * @audit_buf: audit buffer
186  * @dev: network interface
187  * @addr: IP address
188  * @mask: IP address mask
189  *
190  * Description:
191  * Write the IPv6 address and address mask, if necessary, to @audit_buf.
192  *
193  */
194 static void netlbl_unlabel_audit_addr6(struct audit_buffer *audit_buf,
195                                      const char *dev,
196                                      const struct in6_addr *addr,
197                                      const struct in6_addr *mask)
198 {
199         if (dev != NULL)
200                 audit_log_format(audit_buf, " netif=%s", dev);
201         audit_log_format(audit_buf, " src=" NIP6_FMT, NIP6(*addr));
202         if (ntohl(mask->s6_addr32[3]) != 0xffffffff) {
203                 u32 mask_len = 0;
204                 u32 mask_val;
205                 int iter = -1;
206                 while (ntohl(mask->s6_addr32[++iter]) == 0xffffffff)
207                         mask_len += 32;
208                 mask_val = ntohl(mask->s6_addr32[iter]);
209                 while (mask_val > 0) {
210                         mask_val <<= 1;
211                         mask_len++;
212                 }
213                 audit_log_format(audit_buf, " src_prefixlen=%d", mask_len);
214         }
215 }
216
217 /*
218  * Unlabeled Connection Hash Table Functions
219  */
220
221 /**
222  * netlbl_unlhsh_free_addr4 - Frees an IPv4 address entry from the hash table
223  * @entry: the entry's RCU field
224  *
225  * Description:
226  * This function is designed to be used as a callback to the call_rcu()
227  * function so that memory allocated to a hash table address entry can be
228  * released safely.
229  *
230  */
231 static void netlbl_unlhsh_free_addr4(struct rcu_head *entry)
232 {
233         struct netlbl_unlhsh_addr4 *ptr;
234
235         ptr = container_of(entry, struct netlbl_unlhsh_addr4, rcu);
236         kfree(ptr);
237 }
238
239 #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
240 /**
241  * netlbl_unlhsh_free_addr6 - Frees an IPv6 address entry from the hash table
242  * @entry: the entry's RCU field
243  *
244  * Description:
245  * This function is designed to be used as a callback to the call_rcu()
246  * function so that memory allocated to a hash table address entry can be
247  * released safely.
248  *
249  */
250 static void netlbl_unlhsh_free_addr6(struct rcu_head *entry)
251 {
252         struct netlbl_unlhsh_addr6 *ptr;
253
254         ptr = container_of(entry, struct netlbl_unlhsh_addr6, rcu);
255         kfree(ptr);
256 }
257 #endif /* IPv6 */
258
259 /**
260  * netlbl_unlhsh_free_iface - Frees an interface entry from the hash table
261  * @entry: the entry's RCU field
262  *
263  * Description:
264  * This function is designed to be used as a callback to the call_rcu()
265  * function so that memory allocated to a hash table interface entry can be
266  * released safely.  It is important to note that this function does not free
267  * the IPv4 and IPv6 address lists contained as part of an interface entry.  It
268  * is up to the rest of the code to make sure an interface entry is only freed
269  * once it's address lists are empty.
270  *
271  */
272 static void netlbl_unlhsh_free_iface(struct rcu_head *entry)
273 {
274         struct netlbl_unlhsh_iface *iface;
275         struct netlbl_unlhsh_addr4 *iter4;
276         struct netlbl_unlhsh_addr4 *tmp4;
277         struct netlbl_unlhsh_addr6 *iter6;
278         struct netlbl_unlhsh_addr6 *tmp6;
279
280         iface = container_of(entry, struct netlbl_unlhsh_iface, rcu);
281
282         /* no need for locks here since we are the only one with access to this
283          * structure */
284
285         list_for_each_entry_safe(iter4, tmp4, &iface->addr4_list, list)
286                 if (iter4->valid) {
287                         list_del_rcu(&iter4->list);
288                         kfree(iter4);
289                 }
290         list_for_each_entry_safe(iter6, tmp6, &iface->addr6_list, list)
291                 if (iter6->valid) {
292                         list_del_rcu(&iter6->list);
293                         kfree(iter6);
294                 }
295         kfree(iface);
296 }
297
298 /**
299  * netlbl_unlhsh_hash - Hashing function for the hash table
300  * @ifindex: the network interface/device to hash
301  *
302  * Description:
303  * This is the hashing function for the unlabeled hash table, it returns the
304  * bucket number for the given device/interface.  The caller is responsible for
305  * calling the rcu_read_[un]lock() functions.
306  *
307  */
308 static u32 netlbl_unlhsh_hash(int ifindex)
309 {
310         /* this is taken _almost_ directly from
311          * security/selinux/netif.c:sel_netif_hasfn() as they do pretty much
312          * the same thing */
313         return ifindex & (rcu_dereference(netlbl_unlhsh)->size - 1);
314 }
315
316 /**
317  * netlbl_unlhsh_search_addr4 - Search for a matching IPv4 address entry
318  * @addr: IPv4 address
319  * @iface: the network interface entry
320  *
321  * Description:
322  * Searches the IPv4 address list of the network interface specified by @iface.
323  * If a matching address entry is found it is returned, otherwise NULL is
324  * returned.  The caller is responsible for calling the rcu_read_[un]lock()
325  * functions.
326  *
327  */
328 static struct netlbl_unlhsh_addr4 *netlbl_unlhsh_search_addr4(
329                                        __be32 addr,
330                                        const struct netlbl_unlhsh_iface *iface)
331 {
332         struct netlbl_unlhsh_addr4 *iter;
333
334         list_for_each_entry_rcu(iter, &iface->addr4_list, list)
335                 if (iter->valid && (addr & iter->mask) == iter->addr)
336                         return iter;
337
338         return NULL;
339 }
340
341 #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
342 /**
343  * netlbl_unlhsh_search_addr6 - Search for a matching IPv6 address entry
344  * @addr: IPv6 address
345  * @iface: the network interface entry
346  *
347  * Description:
348  * Searches the IPv6 address list of the network interface specified by @iface.
349  * If a matching address entry is found it is returned, otherwise NULL is
350  * returned.  The caller is responsible for calling the rcu_read_[un]lock()
351  * functions.
352  *
353  */
354 static struct netlbl_unlhsh_addr6 *netlbl_unlhsh_search_addr6(
355                                        const struct in6_addr *addr,
356                                        const struct netlbl_unlhsh_iface *iface)
357 {
358         struct netlbl_unlhsh_addr6 *iter;
359
360         list_for_each_entry_rcu(iter, &iface->addr6_list, list)
361                 if (iter->valid &&
362                     ipv6_masked_addr_cmp(&iter->addr, &iter->mask, addr) == 0)
363                 return iter;
364
365         return NULL;
366 }
367 #endif /* IPv6 */
368
369 /**
370  * netlbl_unlhsh_search_iface - Search for a matching interface entry
371  * @ifindex: the network interface
372  *
373  * Description:
374  * Searches the unlabeled connection hash table and returns a pointer to the
375  * interface entry which matches @ifindex, otherwise NULL is returned.  The
376  * caller is responsible for calling the rcu_read_[un]lock() functions.
377  *
378  */
379 static struct netlbl_unlhsh_iface *netlbl_unlhsh_search_iface(int ifindex)
380 {
381         u32 bkt;
382         struct netlbl_unlhsh_iface *iter;
383
384         bkt = netlbl_unlhsh_hash(ifindex);
385         list_for_each_entry_rcu(iter,
386                                 &rcu_dereference(netlbl_unlhsh)->tbl[bkt],
387                                 list)
388                 if (iter->valid && iter->ifindex == ifindex)
389                         return iter;
390
391         return NULL;
392 }
393
394 /**
395  * netlbl_unlhsh_search_iface_def - Search for a matching interface entry
396  * @ifindex: the network interface
397  *
398  * Description:
399  * Searches the unlabeled connection hash table and returns a pointer to the
400  * interface entry which matches @ifindex.  If an exact match can not be found
401  * and there is a valid default entry, the default entry is returned, otherwise
402  * NULL is returned.  The caller is responsible for calling the
403  * rcu_read_[un]lock() functions.
404  *
405  */
406 static struct netlbl_unlhsh_iface *netlbl_unlhsh_search_iface_def(int ifindex)
407 {
408         struct netlbl_unlhsh_iface *entry;
409
410         entry = netlbl_unlhsh_search_iface(ifindex);
411         if (entry != NULL)
412                 return entry;
413
414         entry = rcu_dereference(netlbl_unlhsh_def);
415         if (entry != NULL && entry->valid)
416                 return entry;
417
418         return NULL;
419 }
420
421 /**
422  * netlbl_unlhsh_add_addr4 - Add a new IPv4 address entry to the hash table
423  * @iface: the associated interface entry
424  * @addr: IPv4 address in network byte order
425  * @mask: IPv4 address mask in network byte order
426  * @secid: LSM secid value for entry
427  *
428  * Description:
429  * Add a new address entry into the unlabeled connection hash table using the
430  * interface entry specified by @iface.  On success zero is returned, otherwise
431  * a negative value is returned.  The caller is responsible for calling the
432  * rcu_read_[un]lock() functions.
433  *
434  */
435 static int netlbl_unlhsh_add_addr4(struct netlbl_unlhsh_iface *iface,
436                                    const struct in_addr *addr,
437                                    const struct in_addr *mask,
438                                    u32 secid)
439 {
440         struct netlbl_unlhsh_addr4 *entry;
441         struct netlbl_unlhsh_addr4 *iter;
442
443         entry = kzalloc(sizeof(*entry), GFP_ATOMIC);
444         if (entry == NULL)
445                 return -ENOMEM;
446
447         entry->addr = addr->s_addr & mask->s_addr;
448         entry->mask = mask->s_addr;
449         entry->secid = secid;
450         entry->valid = 1;
451         INIT_RCU_HEAD(&entry->rcu);
452
453         spin_lock(&netlbl_unlhsh_lock);
454         iter = netlbl_unlhsh_search_addr4(entry->addr, iface);
455         if (iter != NULL &&
456             iter->addr == addr->s_addr && iter->mask == mask->s_addr) {
457                 spin_unlock(&netlbl_unlhsh_lock);
458                 kfree(entry);
459                 return -EEXIST;
460         }
461         /* in order to speed up address searches through the list (the common
462          * case) we need to keep the list in order based on the size of the
463          * address mask such that the entry with the widest mask (smallest
464          * numerical value) appears first in the list */
465         list_for_each_entry_rcu(iter, &iface->addr4_list, list)
466                 if (iter->valid &&
467                     ntohl(entry->mask) > ntohl(iter->mask)) {
468                         __list_add_rcu(&entry->list,
469                                        iter->list.prev,
470                                        &iter->list);
471                         spin_unlock(&netlbl_unlhsh_lock);
472                         return 0;
473                 }
474         list_add_tail_rcu(&entry->list, &iface->addr4_list);
475         spin_unlock(&netlbl_unlhsh_lock);
476         return 0;
477 }
478
479 #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
480 /**
481  * netlbl_unlhsh_add_addr6 - Add a new IPv6 address entry to the hash table
482  * @iface: the associated interface entry
483  * @addr: IPv6 address in network byte order
484  * @mask: IPv6 address mask in network byte order
485  * @secid: LSM secid value for entry
486  *
487  * Description:
488  * Add a new address entry into the unlabeled connection hash table using the
489  * interface entry specified by @iface.  On success zero is returned, otherwise
490  * a negative value is returned.  The caller is responsible for calling the
491  * rcu_read_[un]lock() functions.
492  *
493  */
494 static int netlbl_unlhsh_add_addr6(struct netlbl_unlhsh_iface *iface,
495                                    const struct in6_addr *addr,
496                                    const struct in6_addr *mask,
497                                    u32 secid)
498 {
499         struct netlbl_unlhsh_addr6 *entry;
500         struct netlbl_unlhsh_addr6 *iter;
501
502         entry = kzalloc(sizeof(*entry), GFP_ATOMIC);
503         if (entry == NULL)
504                 return -ENOMEM;
505
506         ipv6_addr_copy(&entry->addr, addr);
507         entry->addr.s6_addr32[0] &= mask->s6_addr32[0];
508         entry->addr.s6_addr32[1] &= mask->s6_addr32[1];
509         entry->addr.s6_addr32[2] &= mask->s6_addr32[2];
510         entry->addr.s6_addr32[3] &= mask->s6_addr32[3];
511         ipv6_addr_copy(&entry->mask, mask);
512         entry->secid = secid;
513         entry->valid = 1;
514         INIT_RCU_HEAD(&entry->rcu);
515
516         spin_lock(&netlbl_unlhsh_lock);
517         iter = netlbl_unlhsh_search_addr6(&entry->addr, iface);
518         if (iter != NULL &&
519             (ipv6_addr_equal(&iter->addr, addr) &&
520              ipv6_addr_equal(&iter->mask, mask))) {
521                 spin_unlock(&netlbl_unlhsh_lock);
522                 kfree(entry);
523                 return -EEXIST;
524         }
525         /* in order to speed up address searches through the list (the common
526          * case) we need to keep the list in order based on the size of the
527          * address mask such that the entry with the widest mask (smallest
528          * numerical value) appears first in the list */
529         list_for_each_entry_rcu(iter, &iface->addr6_list, list)
530                 if (iter->valid &&
531                     ipv6_addr_cmp(&entry->mask, &iter->mask) > 0) {
532                         __list_add_rcu(&entry->list,
533                                        iter->list.prev,
534                                        &iter->list);
535                         spin_unlock(&netlbl_unlhsh_lock);
536                         return 0;
537                 }
538         list_add_tail_rcu(&entry->list, &iface->addr6_list);
539         spin_unlock(&netlbl_unlhsh_lock);
540         return 0;
541 }
542 #endif /* IPv6 */
543
544 /**
545  * netlbl_unlhsh_add_iface - Adds a new interface entry to the hash table
546  * @ifindex: network interface
547  *
548  * Description:
549  * Add a new, empty, interface entry into the unlabeled connection hash table.
550  * On success a pointer to the new interface entry is returned, on failure NULL
551  * is returned.  The caller is responsible for calling the rcu_read_[un]lock()
552  * functions.
553  *
554  */
555 static struct netlbl_unlhsh_iface *netlbl_unlhsh_add_iface(int ifindex)
556 {
557         u32 bkt;
558         struct netlbl_unlhsh_iface *iface;
559
560         iface = kzalloc(sizeof(*iface), GFP_ATOMIC);
561         if (iface == NULL)
562                 return NULL;
563
564         iface->ifindex = ifindex;
565         INIT_LIST_HEAD(&iface->addr4_list);
566         INIT_LIST_HEAD(&iface->addr6_list);
567         iface->valid = 1;
568         INIT_RCU_HEAD(&iface->rcu);
569
570         spin_lock(&netlbl_unlhsh_lock);
571         if (ifindex > 0) {
572                 bkt = netlbl_unlhsh_hash(ifindex);
573                 if (netlbl_unlhsh_search_iface(ifindex) != NULL)
574                         goto add_iface_failure;
575                 list_add_tail_rcu(&iface->list,
576                                   &rcu_dereference(netlbl_unlhsh)->tbl[bkt]);
577         } else {
578                 INIT_LIST_HEAD(&iface->list);
579                 if (rcu_dereference(netlbl_unlhsh_def) != NULL)
580                         goto add_iface_failure;
581                 rcu_assign_pointer(netlbl_unlhsh_def, iface);
582         }
583         spin_unlock(&netlbl_unlhsh_lock);
584
585         return iface;
586
587 add_iface_failure:
588         spin_unlock(&netlbl_unlhsh_lock);
589         kfree(iface);
590         return NULL;
591 }
592
593 /**
594  * netlbl_unlhsh_add - Adds a new entry to the unlabeled connection hash table
595  * @net: network namespace
596  * @dev_name: interface name
597  * @addr: IP address in network byte order
598  * @mask: address mask in network byte order
599  * @addr_len: length of address/mask (4 for IPv4, 16 for IPv6)
600  * @secid: LSM secid value for the entry
601  * @audit_info: NetLabel audit information
602  *
603  * Description:
604  * Adds a new entry to the unlabeled connection hash table.  Returns zero on
605  * success, negative values on failure.
606  *
607  */
608 static int netlbl_unlhsh_add(struct net *net,
609                              const char *dev_name,
610                              const void *addr,
611                              const void *mask,
612                              u32 addr_len,
613                              u32 secid,
614                              struct netlbl_audit *audit_info)
615 {
616         int ret_val;
617         int ifindex;
618         struct net_device *dev;
619         struct netlbl_unlhsh_iface *iface;
620         struct audit_buffer *audit_buf = NULL;
621         char *secctx = NULL;
622         u32 secctx_len;
623
624         if (addr_len != sizeof(struct in_addr) &&
625             addr_len != sizeof(struct in6_addr))
626                 return -EINVAL;
627
628         rcu_read_lock();
629         if (dev_name != NULL) {
630                 dev = dev_get_by_name(net, dev_name);
631                 if (dev == NULL) {
632                         ret_val = -ENODEV;
633                         goto unlhsh_add_return;
634                 }
635                 ifindex = dev->ifindex;
636                 dev_put(dev);
637                 iface = netlbl_unlhsh_search_iface(ifindex);
638         } else {
639                 ifindex = 0;
640                 iface = rcu_dereference(netlbl_unlhsh_def);
641         }
642         if (iface == NULL) {
643                 iface = netlbl_unlhsh_add_iface(ifindex);
644                 if (iface == NULL) {
645                         ret_val = -ENOMEM;
646                         goto unlhsh_add_return;
647                 }
648         }
649         audit_buf = netlbl_audit_start_common(AUDIT_MAC_UNLBL_STCADD,
650                                               audit_info);
651         switch (addr_len) {
652         case sizeof(struct in_addr): {
653                 struct in_addr *addr4, *mask4;
654
655                 addr4 = (struct in_addr *)addr;
656                 mask4 = (struct in_addr *)mask;
657                 ret_val = netlbl_unlhsh_add_addr4(iface, addr4, mask4, secid);
658                 if (audit_buf != NULL)
659                         netlbl_unlabel_audit_addr4(audit_buf,
660                                                    dev_name,
661                                                    addr4->s_addr,
662                                                    mask4->s_addr);
663                 break;
664         }
665 #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
666         case sizeof(struct in6_addr): {
667                 struct in6_addr *addr6, *mask6;
668
669                 addr6 = (struct in6_addr *)addr;
670                 mask6 = (struct in6_addr *)mask;
671                 ret_val = netlbl_unlhsh_add_addr6(iface, addr6, mask6, secid);
672                 if (audit_buf != NULL)
673                         netlbl_unlabel_audit_addr6(audit_buf,
674                                                    dev_name,
675                                                    addr6, mask6);
676                 break;
677         }
678 #endif /* IPv6 */
679         default:
680                 ret_val = -EINVAL;
681         }
682         if (ret_val == 0)
683                 atomic_inc(&netlabel_mgmt_protocount);
684
685 unlhsh_add_return:
686         rcu_read_unlock();
687         if (audit_buf != NULL) {
688                 if (security_secid_to_secctx(secid,
689                                              &secctx,
690                                              &secctx_len) == 0) {
691                         audit_log_format(audit_buf, " sec_obj=%s", secctx);
692                         security_release_secctx(secctx, secctx_len);
693                 }
694                 audit_log_format(audit_buf, " res=%u", ret_val == 0 ? 1 : 0);
695                 audit_log_end(audit_buf);
696         }
697         return ret_val;
698 }
699
700 /**
701  * netlbl_unlhsh_remove_addr4 - Remove an IPv4 address entry
702  * @net: network namespace
703  * @iface: interface entry
704  * @addr: IP address
705  * @mask: IP address mask
706  * @audit_info: NetLabel audit information
707  *
708  * Description:
709  * Remove an IP address entry from the unlabeled connection hash table.
710  * Returns zero on success, negative values on failure.  The caller is
711  * responsible for calling the rcu_read_[un]lock() functions.
712  *
713  */
714 static int netlbl_unlhsh_remove_addr4(struct net *net,
715                                       struct netlbl_unlhsh_iface *iface,
716                                       const struct in_addr *addr,
717                                       const struct in_addr *mask,
718                                       struct netlbl_audit *audit_info)
719 {
720         int ret_val = -ENOENT;
721         struct netlbl_unlhsh_addr4 *entry;
722         struct audit_buffer *audit_buf = NULL;
723         struct net_device *dev;
724         char *secctx = NULL;
725         u32 secctx_len;
726
727         spin_lock(&netlbl_unlhsh_lock);
728         entry = netlbl_unlhsh_search_addr4(addr->s_addr, iface);
729         if (entry != NULL &&
730             entry->addr == addr->s_addr && entry->mask == mask->s_addr) {
731                 entry->valid = 0;
732                 list_del_rcu(&entry->list);
733                 ret_val = 0;
734         }
735         spin_unlock(&netlbl_unlhsh_lock);
736
737         audit_buf = netlbl_audit_start_common(AUDIT_MAC_UNLBL_STCDEL,
738                                               audit_info);
739         if (audit_buf != NULL) {
740                 dev = dev_get_by_index(net, iface->ifindex);
741                 netlbl_unlabel_audit_addr4(audit_buf,
742                                            (dev != NULL ? dev->name : NULL),
743                                            entry->addr, entry->mask);
744                 if (dev != NULL)
745                         dev_put(dev);
746                 if (security_secid_to_secctx(entry->secid,
747                                              &secctx,
748                                              &secctx_len) == 0) {
749                         audit_log_format(audit_buf, " sec_obj=%s", secctx);
750                         security_release_secctx(secctx, secctx_len);
751                 }
752                 audit_log_format(audit_buf, " res=%u", ret_val == 0 ? 1 : 0);
753                 audit_log_end(audit_buf);
754         }
755
756         if (ret_val == 0)
757                 call_rcu(&entry->rcu, netlbl_unlhsh_free_addr4);
758         return ret_val;
759 }
760
761 #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
762 /**
763  * netlbl_unlhsh_remove_addr6 - Remove an IPv6 address entry
764  * @net: network namespace
765  * @iface: interface entry
766  * @addr: IP address
767  * @mask: IP address mask
768  * @audit_info: NetLabel audit information
769  *
770  * Description:
771  * Remove an IP address entry from the unlabeled connection hash table.
772  * Returns zero on success, negative values on failure.  The caller is
773  * responsible for calling the rcu_read_[un]lock() functions.
774  *
775  */
776 static int netlbl_unlhsh_remove_addr6(struct net *net,
777                                       struct netlbl_unlhsh_iface *iface,
778                                       const struct in6_addr *addr,
779                                       const struct in6_addr *mask,
780                                       struct netlbl_audit *audit_info)
781 {
782         int ret_val = -ENOENT;
783         struct netlbl_unlhsh_addr6 *entry;
784         struct audit_buffer *audit_buf = NULL;
785         struct net_device *dev;
786         char *secctx = NULL;
787         u32 secctx_len;
788
789         spin_lock(&netlbl_unlhsh_lock);
790         entry = netlbl_unlhsh_search_addr6(addr, iface);
791         if (entry != NULL &&
792             (ipv6_addr_equal(&entry->addr, addr) &&
793              ipv6_addr_equal(&entry->mask, mask))) {
794                 entry->valid = 0;
795                 list_del_rcu(&entry->list);
796                 ret_val = 0;
797         }
798         spin_unlock(&netlbl_unlhsh_lock);
799
800         audit_buf = netlbl_audit_start_common(AUDIT_MAC_UNLBL_STCDEL,
801                                               audit_info);
802         if (audit_buf != NULL) {
803                 dev = dev_get_by_index(net, iface->ifindex);
804                 netlbl_unlabel_audit_addr6(audit_buf,
805                                            (dev != NULL ? dev->name : NULL),
806                                            addr, mask);
807                 if (dev != NULL)
808                         dev_put(dev);
809                 if (security_secid_to_secctx(entry->secid,
810                                              &secctx,
811                                              &secctx_len) == 0) {
812                         audit_log_format(audit_buf, " sec_obj=%s", secctx);
813                         security_release_secctx(secctx, secctx_len);
814                 }
815                 audit_log_format(audit_buf, " res=%u", ret_val == 0 ? 1 : 0);
816                 audit_log_end(audit_buf);
817         }
818
819         if (ret_val == 0)
820                 call_rcu(&entry->rcu, netlbl_unlhsh_free_addr6);
821         return ret_val;
822 }
823 #endif /* IPv6 */
824
825 /**
826  * netlbl_unlhsh_condremove_iface - Remove an interface entry
827  * @iface: the interface entry
828  *
829  * Description:
830  * Remove an interface entry from the unlabeled connection hash table if it is
831  * empty.  An interface entry is considered to be empty if there are no
832  * address entries assigned to it.
833  *
834  */
835 static void netlbl_unlhsh_condremove_iface(struct netlbl_unlhsh_iface *iface)
836 {
837         struct netlbl_unlhsh_addr4 *iter4;
838         struct netlbl_unlhsh_addr6 *iter6;
839
840         spin_lock(&netlbl_unlhsh_lock);
841         list_for_each_entry_rcu(iter4, &iface->addr4_list, list)
842                 if (iter4->valid)
843                         goto unlhsh_condremove_failure;
844         list_for_each_entry_rcu(iter6, &iface->addr6_list, list)
845                 if (iter6->valid)
846                         goto unlhsh_condremove_failure;
847         iface->valid = 0;
848         if (iface->ifindex > 0)
849                 list_del_rcu(&iface->list);
850         else
851                 rcu_assign_pointer(netlbl_unlhsh_def, NULL);
852         spin_unlock(&netlbl_unlhsh_lock);
853
854         call_rcu(&iface->rcu, netlbl_unlhsh_free_iface);
855         return;
856
857 unlhsh_condremove_failure:
858         spin_unlock(&netlbl_unlhsh_lock);
859         return;
860 }
861
862 /**
863  * netlbl_unlhsh_remove - Remove an entry from the unlabeled hash table
864  * @net: network namespace
865  * @dev_name: interface name
866  * @addr: IP address in network byte order
867  * @mask: address mask in network byte order
868  * @addr_len: length of address/mask (4 for IPv4, 16 for IPv6)
869  * @audit_info: NetLabel audit information
870  *
871  * Description:
872  * Removes and existing entry from the unlabeled connection hash table.
873  * Returns zero on success, negative values on failure.
874  *
875  */
876 static int netlbl_unlhsh_remove(struct net *net,
877                                 const char *dev_name,
878                                 const void *addr,
879                                 const void *mask,
880                                 u32 addr_len,
881                                 struct netlbl_audit *audit_info)
882 {
883         int ret_val;
884         struct net_device *dev;
885         struct netlbl_unlhsh_iface *iface;
886
887         if (addr_len != sizeof(struct in_addr) &&
888             addr_len != sizeof(struct in6_addr))
889                 return -EINVAL;
890
891         rcu_read_lock();
892         if (dev_name != NULL) {
893                 dev = dev_get_by_name(net, dev_name);
894                 if (dev == NULL) {
895                         ret_val = -ENODEV;
896                         goto unlhsh_remove_return;
897                 }
898                 iface = netlbl_unlhsh_search_iface(dev->ifindex);
899                 dev_put(dev);
900         } else
901                 iface = rcu_dereference(netlbl_unlhsh_def);
902         if (iface == NULL) {
903                 ret_val = -ENOENT;
904                 goto unlhsh_remove_return;
905         }
906         switch (addr_len) {
907         case sizeof(struct in_addr):
908                 ret_val = netlbl_unlhsh_remove_addr4(net,
909                                                      iface, addr, mask,
910                                                      audit_info);
911                 break;
912 #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
913         case sizeof(struct in6_addr):
914                 ret_val = netlbl_unlhsh_remove_addr6(net,
915                                                      iface, addr, mask,
916                                                      audit_info);
917                 break;
918 #endif /* IPv6 */
919         default:
920                 ret_val = -EINVAL;
921         }
922         if (ret_val == 0) {
923                 netlbl_unlhsh_condremove_iface(iface);
924                 atomic_dec(&netlabel_mgmt_protocount);
925         }
926
927 unlhsh_remove_return:
928         rcu_read_unlock();
929         return ret_val;
930 }
931
932 /*
933  * General Helper Functions
934  */
935
936 /**
937  * netlbl_unlhsh_netdev_handler - Network device notification handler
938  * @this: notifier block
939  * @event: the event
940  * @ptr: the network device (cast to void)
941  *
942  * Description:
943  * Handle network device events, although at present all we care about is a
944  * network device going away.  In the case of a device going away we clear any
945  * related entries from the unlabeled connection hash table.
946  *
947  */
948 static int netlbl_unlhsh_netdev_handler(struct notifier_block *this,
949                                         unsigned long event,
950                                         void *ptr)
951 {
952         struct net_device *dev = ptr;
953         struct netlbl_unlhsh_iface *iface = NULL;
954
955         if (dev->nd_net != &init_net)
956                 return NOTIFY_DONE;
957
958         /* XXX - should this be a check for NETDEV_DOWN or _UNREGISTER? */
959         if (event == NETDEV_DOWN) {
960                 spin_lock(&netlbl_unlhsh_lock);
961                 iface = netlbl_unlhsh_search_iface(dev->ifindex);
962                 if (iface != NULL && iface->valid) {
963                         iface->valid = 0;
964                         list_del_rcu(&iface->list);
965                 } else
966                         iface = NULL;
967                 spin_unlock(&netlbl_unlhsh_lock);
968         }
969
970         if (iface != NULL)
971                 call_rcu(&iface->rcu, netlbl_unlhsh_free_iface);
972
973         return NOTIFY_DONE;
974 }
975
976 /**
977  * netlbl_unlabel_acceptflg_set - Set the unlabeled accept flag
978  * @value: desired value
979  * @audit_info: NetLabel audit information
980  *
981  * Description:
982  * Set the value of the unlabeled accept flag to @value.
983  *
984  */
985 static void netlbl_unlabel_acceptflg_set(u8 value,
986                                          struct netlbl_audit *audit_info)
987 {
988         struct audit_buffer *audit_buf;
989         u8 old_val;
990
991         old_val = netlabel_unlabel_acceptflg;
992         netlabel_unlabel_acceptflg = value;
993         audit_buf = netlbl_audit_start_common(AUDIT_MAC_UNLBL_ALLOW,
994                                               audit_info);
995         if (audit_buf != NULL) {
996                 audit_log_format(audit_buf,
997                                  " unlbl_accept=%u old=%u", value, old_val);
998                 audit_log_end(audit_buf);
999         }
1000 }
1001
1002 /**
1003  * netlbl_unlabel_addrinfo_get - Get the IPv4/6 address information
1004  * @info: the Generic NETLINK info block
1005  * @addr: the IP address
1006  * @mask: the IP address mask
1007  * @len: the address length
1008  *
1009  * Description:
1010  * Examine the Generic NETLINK message and extract the IP address information.
1011  * Returns zero on success, negative values on failure.
1012  *
1013  */
1014 static int netlbl_unlabel_addrinfo_get(struct genl_info *info,
1015                                        void **addr,
1016                                        void **mask,
1017                                        u32 *len)
1018 {
1019         u32 addr_len;
1020
1021         if (info->attrs[NLBL_UNLABEL_A_IPV4ADDR]) {
1022                 addr_len = nla_len(info->attrs[NLBL_UNLABEL_A_IPV4ADDR]);
1023                 if (addr_len != sizeof(struct in_addr) &&
1024                     addr_len != nla_len(info->attrs[NLBL_UNLABEL_A_IPV4MASK]))
1025                         return -EINVAL;
1026                 *len = addr_len;
1027                 *addr = nla_data(info->attrs[NLBL_UNLABEL_A_IPV4ADDR]);
1028                 *mask = nla_data(info->attrs[NLBL_UNLABEL_A_IPV4MASK]);
1029                 return 0;
1030         } else if (info->attrs[NLBL_UNLABEL_A_IPV6ADDR]) {
1031                 addr_len = nla_len(info->attrs[NLBL_UNLABEL_A_IPV6ADDR]);
1032                 if (addr_len != sizeof(struct in6_addr) &&
1033                     addr_len != nla_len(info->attrs[NLBL_UNLABEL_A_IPV6MASK]))
1034                         return -EINVAL;
1035                 *len = addr_len;
1036                 *addr = nla_data(info->attrs[NLBL_UNLABEL_A_IPV6ADDR]);
1037                 *mask = nla_data(info->attrs[NLBL_UNLABEL_A_IPV6MASK]);
1038                 return 0;
1039         }
1040
1041         return -EINVAL;
1042 }
1043
1044 /*
1045  * NetLabel Command Handlers
1046  */
1047
1048 /**
1049  * netlbl_unlabel_accept - Handle an ACCEPT message
1050  * @skb: the NETLINK buffer
1051  * @info: the Generic NETLINK info block
1052  *
1053  * Description:
1054  * Process a user generated ACCEPT message and set the accept flag accordingly.
1055  * Returns zero on success, negative values on failure.
1056  *
1057  */
1058 static int netlbl_unlabel_accept(struct sk_buff *skb, struct genl_info *info)
1059 {
1060         u8 value;
1061         struct netlbl_audit audit_info;
1062
1063         if (info->attrs[NLBL_UNLABEL_A_ACPTFLG]) {
1064                 value = nla_get_u8(info->attrs[NLBL_UNLABEL_A_ACPTFLG]);
1065                 if (value == 1 || value == 0) {
1066                         netlbl_netlink_auditinfo(skb, &audit_info);
1067                         netlbl_unlabel_acceptflg_set(value, &audit_info);
1068                         return 0;
1069                 }
1070         }
1071
1072         return -EINVAL;
1073 }
1074
1075 /**
1076  * netlbl_unlabel_list - Handle a LIST message
1077  * @skb: the NETLINK buffer
1078  * @info: the Generic NETLINK info block
1079  *
1080  * Description:
1081  * Process a user generated LIST message and respond with the current status.
1082  * Returns zero on success, negative values on failure.
1083  *
1084  */
1085 static int netlbl_unlabel_list(struct sk_buff *skb, struct genl_info *info)
1086 {
1087         int ret_val = -EINVAL;
1088         struct sk_buff *ans_skb;
1089         void *data;
1090
1091         ans_skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
1092         if (ans_skb == NULL)
1093                 goto list_failure;
1094         data = genlmsg_put_reply(ans_skb, info, &netlbl_unlabel_gnl_family,
1095                                  0, NLBL_UNLABEL_C_LIST);
1096         if (data == NULL) {
1097                 ret_val = -ENOMEM;
1098                 goto list_failure;
1099         }
1100
1101         ret_val = nla_put_u8(ans_skb,
1102                              NLBL_UNLABEL_A_ACPTFLG,
1103                              netlabel_unlabel_acceptflg);
1104         if (ret_val != 0)
1105                 goto list_failure;
1106
1107         genlmsg_end(ans_skb, data);
1108
1109         ret_val = genlmsg_reply(ans_skb, info);
1110         if (ret_val != 0)
1111                 goto list_failure;
1112         return 0;
1113
1114 list_failure:
1115         kfree_skb(ans_skb);
1116         return ret_val;
1117 }
1118
1119 /**
1120  * netlbl_unlabel_staticadd - Handle a STATICADD message
1121  * @skb: the NETLINK buffer
1122  * @info: the Generic NETLINK info block
1123  *
1124  * Description:
1125  * Process a user generated STATICADD message and add a new unlabeled
1126  * connection entry to the hash table.  Returns zero on success, negative
1127  * values on failure.
1128  *
1129  */
1130 static int netlbl_unlabel_staticadd(struct sk_buff *skb,
1131                                     struct genl_info *info)
1132 {
1133         int ret_val;
1134         char *dev_name;
1135         void *addr;
1136         void *mask;
1137         u32 addr_len;
1138         u32 secid;
1139         struct netlbl_audit audit_info;
1140
1141         /* Don't allow users to add both IPv4 and IPv6 addresses for a
1142          * single entry.  However, allow users to create two entries, one each
1143          * for IPv4 and IPv4, with the same LSM security context which should
1144          * achieve the same result. */
1145         if (!info->attrs[NLBL_UNLABEL_A_SECCTX] ||
1146             !info->attrs[NLBL_UNLABEL_A_IFACE] ||
1147             !((!info->attrs[NLBL_UNLABEL_A_IPV4ADDR] ||
1148                !info->attrs[NLBL_UNLABEL_A_IPV4MASK]) ^
1149               (!info->attrs[NLBL_UNLABEL_A_IPV6ADDR] ||
1150                !info->attrs[NLBL_UNLABEL_A_IPV6MASK])))
1151                 return -EINVAL;
1152
1153         netlbl_netlink_auditinfo(skb, &audit_info);
1154
1155         ret_val = netlbl_unlabel_addrinfo_get(info, &addr, &mask, &addr_len);
1156         if (ret_val != 0)
1157                 return ret_val;
1158         dev_name = nla_data(info->attrs[NLBL_UNLABEL_A_IFACE]);
1159         ret_val = security_secctx_to_secid(
1160                                   nla_data(info->attrs[NLBL_UNLABEL_A_SECCTX]),
1161                                   nla_len(info->attrs[NLBL_UNLABEL_A_SECCTX]),
1162                                   &secid);
1163         if (ret_val != 0)
1164                 return ret_val;
1165
1166         return netlbl_unlhsh_add(&init_net,
1167                                  dev_name, addr, mask, addr_len, secid,
1168                                  &audit_info);
1169 }
1170
1171 /**
1172  * netlbl_unlabel_staticadddef - Handle a STATICADDDEF message
1173  * @skb: the NETLINK buffer
1174  * @info: the Generic NETLINK info block
1175  *
1176  * Description:
1177  * Process a user generated STATICADDDEF message and add a new default
1178  * unlabeled connection entry.  Returns zero on success, negative values on
1179  * failure.
1180  *
1181  */
1182 static int netlbl_unlabel_staticadddef(struct sk_buff *skb,
1183                                        struct genl_info *info)
1184 {
1185         int ret_val;
1186         void *addr;
1187         void *mask;
1188         u32 addr_len;
1189         u32 secid;
1190         struct netlbl_audit audit_info;
1191
1192         /* Don't allow users to add both IPv4 and IPv6 addresses for a
1193          * single entry.  However, allow users to create two entries, one each
1194          * for IPv4 and IPv6, with the same LSM security context which should
1195          * achieve the same result. */
1196         if (!info->attrs[NLBL_UNLABEL_A_SECCTX] ||
1197             !((!info->attrs[NLBL_UNLABEL_A_IPV4ADDR] ||
1198                !info->attrs[NLBL_UNLABEL_A_IPV4MASK]) ^
1199               (!info->attrs[NLBL_UNLABEL_A_IPV6ADDR] ||
1200                !info->attrs[NLBL_UNLABEL_A_IPV6MASK])))
1201                 return -EINVAL;
1202
1203         netlbl_netlink_auditinfo(skb, &audit_info);
1204
1205         ret_val = netlbl_unlabel_addrinfo_get(info, &addr, &mask, &addr_len);
1206         if (ret_val != 0)
1207                 return ret_val;
1208         ret_val = security_secctx_to_secid(
1209                                   nla_data(info->attrs[NLBL_UNLABEL_A_SECCTX]),
1210                                   nla_len(info->attrs[NLBL_UNLABEL_A_SECCTX]),
1211                                   &secid);
1212         if (ret_val != 0)
1213                 return ret_val;
1214
1215         return netlbl_unlhsh_add(&init_net,
1216                                  NULL, addr, mask, addr_len, secid,
1217                                  &audit_info);
1218 }
1219
1220 /**
1221  * netlbl_unlabel_staticremove - Handle a STATICREMOVE message
1222  * @skb: the NETLINK buffer
1223  * @info: the Generic NETLINK info block
1224  *
1225  * Description:
1226  * Process a user generated STATICREMOVE message and remove the specified
1227  * unlabeled connection entry.  Returns zero on success, negative values on
1228  * failure.
1229  *
1230  */
1231 static int netlbl_unlabel_staticremove(struct sk_buff *skb,
1232                                        struct genl_info *info)
1233 {
1234         int ret_val;
1235         char *dev_name;
1236         void *addr;
1237         void *mask;
1238         u32 addr_len;
1239         struct netlbl_audit audit_info;
1240
1241         /* See the note in netlbl_unlabel_staticadd() about not allowing both
1242          * IPv4 and IPv6 in the same entry. */
1243         if (!info->attrs[NLBL_UNLABEL_A_IFACE] ||
1244             !((!info->attrs[NLBL_UNLABEL_A_IPV4ADDR] ||
1245                !info->attrs[NLBL_UNLABEL_A_IPV4MASK]) ^
1246               (!info->attrs[NLBL_UNLABEL_A_IPV6ADDR] ||
1247                !info->attrs[NLBL_UNLABEL_A_IPV6MASK])))
1248                 return -EINVAL;
1249
1250         netlbl_netlink_auditinfo(skb, &audit_info);
1251
1252         ret_val = netlbl_unlabel_addrinfo_get(info, &addr, &mask, &addr_len);
1253         if (ret_val != 0)
1254                 return ret_val;
1255         dev_name = nla_data(info->attrs[NLBL_UNLABEL_A_IFACE]);
1256
1257         return netlbl_unlhsh_remove(&init_net,
1258                                     dev_name, addr, mask, addr_len,
1259                                     &audit_info);
1260 }
1261
1262 /**
1263  * netlbl_unlabel_staticremovedef - Handle a STATICREMOVEDEF message
1264  * @skb: the NETLINK buffer
1265  * @info: the Generic NETLINK info block
1266  *
1267  * Description:
1268  * Process a user generated STATICREMOVEDEF message and remove the default
1269  * unlabeled connection entry.  Returns zero on success, negative values on
1270  * failure.
1271  *
1272  */
1273 static int netlbl_unlabel_staticremovedef(struct sk_buff *skb,
1274                                           struct genl_info *info)
1275 {
1276         int ret_val;
1277         void *addr;
1278         void *mask;
1279         u32 addr_len;
1280         struct netlbl_audit audit_info;
1281
1282         /* See the note in netlbl_unlabel_staticadd() about not allowing both
1283          * IPv4 and IPv6 in the same entry. */
1284         if (!((!info->attrs[NLBL_UNLABEL_A_IPV4ADDR] ||
1285                !info->attrs[NLBL_UNLABEL_A_IPV4MASK]) ^
1286               (!info->attrs[NLBL_UNLABEL_A_IPV6ADDR] ||
1287                !info->attrs[NLBL_UNLABEL_A_IPV6MASK])))
1288                 return -EINVAL;
1289
1290         netlbl_netlink_auditinfo(skb, &audit_info);
1291
1292         ret_val = netlbl_unlabel_addrinfo_get(info, &addr, &mask, &addr_len);
1293         if (ret_val != 0)
1294                 return ret_val;
1295
1296         return netlbl_unlhsh_remove(&init_net,
1297                                     NULL, addr, mask, addr_len,
1298                                     &audit_info);
1299 }
1300
1301
1302 /**
1303  * netlbl_unlabel_staticlist_gen - Generate messages for STATICLIST[DEF]
1304  * @cmd: command/message
1305  * @iface: the interface entry
1306  * @addr4: the IPv4 address entry
1307  * @addr6: the IPv6 address entry
1308  * @arg: the netlbl_unlhsh_walk_arg structure
1309  *
1310  * Description:
1311  * This function is designed to be used to generate a response for a
1312  * STATICLIST or STATICLISTDEF message.  When called either @addr4 or @addr6
1313  * can be specified, not both, the other unspecified entry should be set to
1314  * NULL by the caller.  Returns the size of the message on success, negative
1315  * values on failure.
1316  *
1317  */
1318 static int netlbl_unlabel_staticlist_gen(u32 cmd,
1319                                        const struct netlbl_unlhsh_iface *iface,
1320                                        const struct netlbl_unlhsh_addr4 *addr4,
1321                                        const struct netlbl_unlhsh_addr6 *addr6,
1322                                        void *arg)
1323 {
1324         int ret_val = -ENOMEM;
1325         struct netlbl_unlhsh_walk_arg *cb_arg = arg;
1326         struct net_device *dev;
1327         void *data;
1328         u32 secid;
1329         char *secctx;
1330         u32 secctx_len;
1331
1332         data = genlmsg_put(cb_arg->skb, NETLINK_CB(cb_arg->nl_cb->skb).pid,
1333                            cb_arg->seq, &netlbl_unlabel_gnl_family,
1334                            NLM_F_MULTI, cmd);
1335         if (data == NULL)
1336                 goto list_cb_failure;
1337
1338         if (iface->ifindex > 0) {
1339                 dev = dev_get_by_index(&init_net, iface->ifindex);
1340                 ret_val = nla_put_string(cb_arg->skb,
1341                                          NLBL_UNLABEL_A_IFACE, dev->name);
1342                 dev_put(dev);
1343                 if (ret_val != 0)
1344                         goto list_cb_failure;
1345         }
1346
1347         if (addr4) {
1348                 struct in_addr addr_struct;
1349
1350                 addr_struct.s_addr = addr4->addr;
1351                 ret_val = nla_put(cb_arg->skb,
1352                                   NLBL_UNLABEL_A_IPV4ADDR,
1353                                   sizeof(struct in_addr),
1354                                   &addr_struct);
1355                 if (ret_val != 0)
1356                         goto list_cb_failure;
1357
1358                 addr_struct.s_addr = addr4->mask;
1359                 ret_val = nla_put(cb_arg->skb,
1360                                   NLBL_UNLABEL_A_IPV4MASK,
1361                                   sizeof(struct in_addr),
1362                                   &addr_struct);
1363                 if (ret_val != 0)
1364                         goto list_cb_failure;
1365
1366                 secid = addr4->secid;
1367         } else {
1368                 ret_val = nla_put(cb_arg->skb,
1369                                   NLBL_UNLABEL_A_IPV6ADDR,
1370                                   sizeof(struct in6_addr),
1371                                   &addr6->addr);
1372                 if (ret_val != 0)
1373                         goto list_cb_failure;
1374
1375                 ret_val = nla_put(cb_arg->skb,
1376                                   NLBL_UNLABEL_A_IPV6MASK,
1377                                   sizeof(struct in6_addr),
1378                                   &addr6->mask);
1379                 if (ret_val != 0)
1380                         goto list_cb_failure;
1381
1382                 secid = addr6->secid;
1383         }
1384
1385         ret_val = security_secid_to_secctx(secid, &secctx, &secctx_len);
1386         if (ret_val != 0)
1387                 goto list_cb_failure;
1388         ret_val = nla_put(cb_arg->skb,
1389                           NLBL_UNLABEL_A_SECCTX,
1390                           secctx_len,
1391                           secctx);
1392         security_release_secctx(secctx, secctx_len);
1393         if (ret_val != 0)
1394                 goto list_cb_failure;
1395
1396         cb_arg->seq++;
1397         return genlmsg_end(cb_arg->skb, data);
1398
1399 list_cb_failure:
1400         genlmsg_cancel(cb_arg->skb, data);
1401         return ret_val;
1402 }
1403
1404 /**
1405  * netlbl_unlabel_staticlist - Handle a STATICLIST message
1406  * @skb: the NETLINK buffer
1407  * @cb: the NETLINK callback
1408  *
1409  * Description:
1410  * Process a user generated STATICLIST message and dump the unlabeled
1411  * connection hash table in a form suitable for use in a kernel generated
1412  * STATICLIST message.  Returns the length of @skb.
1413  *
1414  */
1415 static int netlbl_unlabel_staticlist(struct sk_buff *skb,
1416                                      struct netlink_callback *cb)
1417 {
1418         struct netlbl_unlhsh_walk_arg cb_arg;
1419         u32 skip_bkt = cb->args[0];
1420         u32 skip_chain = cb->args[1];
1421         u32 skip_addr4 = cb->args[2];
1422         u32 skip_addr6 = cb->args[3];
1423         u32 iter_bkt;
1424         u32 iter_chain = 0, iter_addr4 = 0, iter_addr6 = 0;
1425         struct netlbl_unlhsh_iface *iface;
1426         struct netlbl_unlhsh_addr4 *addr4;
1427         struct netlbl_unlhsh_addr6 *addr6;
1428
1429         cb_arg.nl_cb = cb;
1430         cb_arg.skb = skb;
1431         cb_arg.seq = cb->nlh->nlmsg_seq;
1432
1433         rcu_read_lock();
1434         for (iter_bkt = skip_bkt;
1435              iter_bkt < rcu_dereference(netlbl_unlhsh)->size;
1436              iter_bkt++, iter_chain = 0, iter_addr4 = 0, iter_addr6 = 0) {
1437                 list_for_each_entry_rcu(iface,
1438                                 &rcu_dereference(netlbl_unlhsh)->tbl[iter_bkt],
1439                                 list) {
1440                         if (!iface->valid ||
1441                             iter_chain++ < skip_chain)
1442                                 continue;
1443                         list_for_each_entry_rcu(addr4,
1444                                                 &iface->addr4_list,
1445                                                 list) {
1446                                 if (!addr4->valid || iter_addr4++ < skip_addr4)
1447                                         continue;
1448                                 if (netlbl_unlabel_staticlist_gen(
1449                                                      NLBL_UNLABEL_C_STATICLIST,
1450                                                      iface,
1451                                                      addr4,
1452                                                      NULL,
1453                                                      &cb_arg) < 0) {
1454                                         iter_addr4--;
1455                                         iter_chain--;
1456                                         goto unlabel_staticlist_return;
1457                                 }
1458                         }
1459                         list_for_each_entry_rcu(addr6,
1460                                                 &iface->addr6_list,
1461                                                 list) {
1462                                 if (!addr6->valid || iter_addr6++ < skip_addr6)
1463                                         continue;
1464                                 if (netlbl_unlabel_staticlist_gen(
1465                                                      NLBL_UNLABEL_C_STATICLIST,
1466                                                      iface,
1467                                                      NULL,
1468                                                      addr6,
1469                                                      &cb_arg) < 0) {
1470                                         iter_addr6--;
1471                                         iter_chain--;
1472                                         goto unlabel_staticlist_return;
1473                                 }
1474                         }
1475                 }
1476         }
1477
1478 unlabel_staticlist_return:
1479         rcu_read_unlock();
1480         cb->args[0] = skip_bkt;
1481         cb->args[1] = skip_chain;
1482         cb->args[2] = skip_addr4;
1483         cb->args[3] = skip_addr6;
1484         return skb->len;
1485 }
1486
1487 /**
1488  * netlbl_unlabel_staticlistdef - Handle a STATICLISTDEF message
1489  * @skb: the NETLINK buffer
1490  * @cb: the NETLINK callback
1491  *
1492  * Description:
1493  * Process a user generated STATICLISTDEF message and dump the default
1494  * unlabeled connection entry in a form suitable for use in a kernel generated
1495  * STATICLISTDEF message.  Returns the length of @skb.
1496  *
1497  */
1498 static int netlbl_unlabel_staticlistdef(struct sk_buff *skb,
1499                                         struct netlink_callback *cb)
1500 {
1501         struct netlbl_unlhsh_walk_arg cb_arg;
1502         struct netlbl_unlhsh_iface *iface;
1503         u32 skip_addr4 = cb->args[0];
1504         u32 skip_addr6 = cb->args[1];
1505         u32 iter_addr4 = 0, iter_addr6 = 0;
1506         struct netlbl_unlhsh_addr4 *addr4;
1507         struct netlbl_unlhsh_addr6 *addr6;
1508
1509         cb_arg.nl_cb = cb;
1510         cb_arg.skb = skb;
1511         cb_arg.seq = cb->nlh->nlmsg_seq;
1512
1513         rcu_read_lock();
1514         iface = rcu_dereference(netlbl_unlhsh_def);
1515         if (iface == NULL || !iface->valid)
1516                 goto unlabel_staticlistdef_return;
1517
1518         list_for_each_entry_rcu(addr4, &iface->addr4_list, list) {
1519                 if (!addr4->valid || iter_addr4++ < skip_addr4)
1520                         continue;
1521                 if (netlbl_unlabel_staticlist_gen(NLBL_UNLABEL_C_STATICLISTDEF,
1522                                            iface,
1523                                            addr4,
1524                                            NULL,
1525                                            &cb_arg) < 0) {
1526                         iter_addr4--;
1527                         goto unlabel_staticlistdef_return;
1528                 }
1529         }
1530         list_for_each_entry_rcu(addr6, &iface->addr6_list, list) {
1531                 if (addr6->valid || iter_addr6++ < skip_addr6)
1532                         continue;
1533                 if (netlbl_unlabel_staticlist_gen(NLBL_UNLABEL_C_STATICLISTDEF,
1534                                            iface,
1535                                            NULL,
1536                                            addr6,
1537                                            &cb_arg) < 0) {
1538                         iter_addr6--;
1539                         goto unlabel_staticlistdef_return;
1540                 }
1541         }
1542
1543 unlabel_staticlistdef_return:
1544         rcu_read_unlock();
1545         cb->args[0] = skip_addr4;
1546         cb->args[1] = skip_addr6;
1547         return skb->len;
1548 }
1549
1550 /*
1551  * NetLabel Generic NETLINK Command Definitions
1552  */
1553
1554 static struct genl_ops netlbl_unlabel_genl_c_staticadd = {
1555         .cmd = NLBL_UNLABEL_C_STATICADD,
1556         .flags = GENL_ADMIN_PERM,
1557         .policy = netlbl_unlabel_genl_policy,
1558         .doit = netlbl_unlabel_staticadd,
1559         .dumpit = NULL,
1560 };
1561
1562 static struct genl_ops netlbl_unlabel_genl_c_staticremove = {
1563         .cmd = NLBL_UNLABEL_C_STATICREMOVE,
1564         .flags = GENL_ADMIN_PERM,
1565         .policy = netlbl_unlabel_genl_policy,
1566         .doit = netlbl_unlabel_staticremove,
1567         .dumpit = NULL,
1568 };
1569
1570 static struct genl_ops netlbl_unlabel_genl_c_staticlist = {
1571         .cmd = NLBL_UNLABEL_C_STATICLIST,
1572         .flags = 0,
1573         .policy = netlbl_unlabel_genl_policy,
1574         .doit = NULL,
1575         .dumpit = netlbl_unlabel_staticlist,
1576 };
1577
1578 static struct genl_ops netlbl_unlabel_genl_c_staticadddef = {
1579         .cmd = NLBL_UNLABEL_C_STATICADDDEF,
1580         .flags = GENL_ADMIN_PERM,
1581         .policy = netlbl_unlabel_genl_policy,
1582         .doit = netlbl_unlabel_staticadddef,
1583         .dumpit = NULL,
1584 };
1585
1586 static struct genl_ops netlbl_unlabel_genl_c_staticremovedef = {
1587         .cmd = NLBL_UNLABEL_C_STATICREMOVEDEF,
1588         .flags = GENL_ADMIN_PERM,
1589         .policy = netlbl_unlabel_genl_policy,
1590         .doit = netlbl_unlabel_staticremovedef,
1591         .dumpit = NULL,
1592 };
1593
1594 static struct genl_ops netlbl_unlabel_genl_c_staticlistdef = {
1595         .cmd = NLBL_UNLABEL_C_STATICLISTDEF,
1596         .flags = 0,
1597         .policy = netlbl_unlabel_genl_policy,
1598         .doit = NULL,
1599         .dumpit = netlbl_unlabel_staticlistdef,
1600 };
1601
1602 static struct genl_ops netlbl_unlabel_genl_c_accept = {
1603         .cmd = NLBL_UNLABEL_C_ACCEPT,
1604         .flags = GENL_ADMIN_PERM,
1605         .policy = netlbl_unlabel_genl_policy,
1606         .doit = netlbl_unlabel_accept,
1607         .dumpit = NULL,
1608 };
1609
1610 static struct genl_ops netlbl_unlabel_genl_c_list = {
1611         .cmd = NLBL_UNLABEL_C_LIST,
1612         .flags = 0,
1613         .policy = netlbl_unlabel_genl_policy,
1614         .doit = netlbl_unlabel_list,
1615         .dumpit = NULL,
1616 };
1617
1618 /*
1619  * NetLabel Generic NETLINK Protocol Functions
1620  */
1621
1622 /**
1623  * netlbl_unlabel_genl_init - Register the Unlabeled NetLabel component
1624  *
1625  * Description:
1626  * Register the unlabeled packet NetLabel component with the Generic NETLINK
1627  * mechanism.  Returns zero on success, negative values on failure.
1628  *
1629  */
1630 int netlbl_unlabel_genl_init(void)
1631 {
1632         int ret_val;
1633
1634         ret_val = genl_register_family(&netlbl_unlabel_gnl_family);
1635         if (ret_val != 0)
1636                 return ret_val;
1637
1638         ret_val = genl_register_ops(&netlbl_unlabel_gnl_family,
1639                                     &netlbl_unlabel_genl_c_staticadd);
1640         if (ret_val != 0)
1641                 return ret_val;
1642
1643         ret_val = genl_register_ops(&netlbl_unlabel_gnl_family,
1644                                     &netlbl_unlabel_genl_c_staticremove);
1645         if (ret_val != 0)
1646                 return ret_val;
1647
1648         ret_val = genl_register_ops(&netlbl_unlabel_gnl_family,
1649                                     &netlbl_unlabel_genl_c_staticlist);
1650         if (ret_val != 0)
1651                 return ret_val;
1652
1653         ret_val = genl_register_ops(&netlbl_unlabel_gnl_family,
1654                                     &netlbl_unlabel_genl_c_staticadddef);
1655         if (ret_val != 0)
1656                 return ret_val;
1657
1658         ret_val = genl_register_ops(&netlbl_unlabel_gnl_family,
1659                                     &netlbl_unlabel_genl_c_staticremovedef);
1660         if (ret_val != 0)
1661                 return ret_val;
1662
1663         ret_val = genl_register_ops(&netlbl_unlabel_gnl_family,
1664                                     &netlbl_unlabel_genl_c_staticlistdef);
1665         if (ret_val != 0)
1666                 return ret_val;
1667
1668         ret_val = genl_register_ops(&netlbl_unlabel_gnl_family,
1669                                     &netlbl_unlabel_genl_c_accept);
1670         if (ret_val != 0)
1671                 return ret_val;
1672
1673         ret_val = genl_register_ops(&netlbl_unlabel_gnl_family,
1674                                     &netlbl_unlabel_genl_c_list);
1675         if (ret_val != 0)
1676                 return ret_val;
1677
1678         return 0;
1679 }
1680
1681 /*
1682  * NetLabel KAPI Hooks
1683  */
1684
1685 static struct notifier_block netlbl_unlhsh_netdev_notifier = {
1686         .notifier_call = netlbl_unlhsh_netdev_handler,
1687 };
1688
1689 /**
1690  * netlbl_unlabel_init - Initialize the unlabeled connection hash table
1691  * @size: the number of bits to use for the hash buckets
1692  *
1693  * Description:
1694  * Initializes the unlabeled connection hash table and registers a network
1695  * device notification handler.  This function should only be called by the
1696  * NetLabel subsystem itself during initialization.  Returns zero on success,
1697  * non-zero values on error.
1698  *
1699  */
1700 int netlbl_unlabel_init(u32 size)
1701 {
1702         u32 iter;
1703         struct netlbl_unlhsh_tbl *hsh_tbl;
1704
1705         if (size == 0)
1706                 return -EINVAL;
1707
1708         hsh_tbl = kmalloc(sizeof(*hsh_tbl), GFP_KERNEL);
1709         if (hsh_tbl == NULL)
1710                 return -ENOMEM;
1711         hsh_tbl->size = 1 << size;
1712         hsh_tbl->tbl = kcalloc(hsh_tbl->size,
1713                                sizeof(struct list_head),
1714                                GFP_KERNEL);
1715         if (hsh_tbl->tbl == NULL) {
1716                 kfree(hsh_tbl);
1717                 return -ENOMEM;
1718         }
1719         for (iter = 0; iter < hsh_tbl->size; iter++)
1720                 INIT_LIST_HEAD(&hsh_tbl->tbl[iter]);
1721
1722         rcu_read_lock();
1723         spin_lock(&netlbl_unlhsh_lock);
1724         rcu_assign_pointer(netlbl_unlhsh, hsh_tbl);
1725         spin_unlock(&netlbl_unlhsh_lock);
1726         rcu_read_unlock();
1727
1728         register_netdevice_notifier(&netlbl_unlhsh_netdev_notifier);
1729
1730         return 0;
1731 }
1732
1733 /**
1734  * netlbl_unlabel_getattr - Get the security attributes for an unlabled packet
1735  * @skb: the packet
1736  * @family: protocol family
1737  * @secattr: the security attributes
1738  *
1739  * Description:
1740  * Determine the security attributes, if any, for an unlabled packet and return
1741  * them in @secattr.  Returns zero on success and negative values on failure.
1742  *
1743  */
1744 int netlbl_unlabel_getattr(const struct sk_buff *skb,
1745                            u16 family,
1746                            struct netlbl_lsm_secattr *secattr)
1747 {
1748         struct netlbl_unlhsh_iface *iface;
1749
1750         rcu_read_lock();
1751         iface = netlbl_unlhsh_search_iface_def(skb->iif);
1752         if (iface == NULL)
1753                 goto unlabel_getattr_nolabel;
1754         switch (family) {
1755         case PF_INET: {
1756                 struct iphdr *hdr4;
1757                 struct netlbl_unlhsh_addr4 *addr4;
1758
1759                 hdr4 = ip_hdr(skb);
1760                 addr4 = netlbl_unlhsh_search_addr4(hdr4->saddr, iface);
1761                 if (addr4 == NULL)
1762                         goto unlabel_getattr_nolabel;
1763                 secattr->attr.secid = addr4->secid;
1764                 break;
1765         }
1766 #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
1767         case PF_INET6: {
1768                 struct ipv6hdr *hdr6;
1769                 struct netlbl_unlhsh_addr6 *addr6;
1770
1771                 hdr6 = ipv6_hdr(skb);
1772                 addr6 = netlbl_unlhsh_search_addr6(&hdr6->saddr, iface);
1773                 if (addr6 == NULL)
1774                         goto unlabel_getattr_nolabel;
1775                 secattr->attr.secid = addr6->secid;
1776                 break;
1777         }
1778 #endif /* IPv6 */
1779         default:
1780                 goto unlabel_getattr_nolabel;
1781         }
1782         rcu_read_unlock();
1783
1784         secattr->flags |= NETLBL_SECATTR_SECID;
1785         secattr->type = NETLBL_NLTYPE_UNLABELED;
1786         return 0;
1787
1788 unlabel_getattr_nolabel:
1789         rcu_read_unlock();
1790         if (netlabel_unlabel_acceptflg == 0)
1791                 return -ENOMSG;
1792         secattr->type = NETLBL_NLTYPE_UNLABELED;
1793         return 0;
1794 }
1795
1796 /**
1797  * netlbl_unlabel_defconf - Set the default config to allow unlabeled packets
1798  *
1799  * Description:
1800  * Set the default NetLabel configuration to allow incoming unlabeled packets
1801  * and to send unlabeled network traffic by default.
1802  *
1803  */
1804 int netlbl_unlabel_defconf(void)
1805 {
1806         int ret_val;
1807         struct netlbl_dom_map *entry;
1808         struct netlbl_audit audit_info;
1809
1810         /* Only the kernel is allowed to call this function and the only time
1811          * it is called is at bootup before the audit subsystem is reporting
1812          * messages so don't worry to much about these values. */
1813         security_task_getsecid(current, &audit_info.secid);
1814         audit_info.loginuid = 0;
1815
1816         entry = kzalloc(sizeof(*entry), GFP_KERNEL);
1817         if (entry == NULL)
1818                 return -ENOMEM;
1819         entry->type = NETLBL_NLTYPE_UNLABELED;
1820         ret_val = netlbl_domhsh_add_default(entry, &audit_info);
1821         if (ret_val != 0)
1822                 return ret_val;
1823
1824         netlbl_unlabel_acceptflg_set(1, &audit_info);
1825
1826         return 0;
1827 }