NetLabel: Add auditing to the static labeling mechanism
[safe/jmp/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 in_addr *addr4, *mask4;
621         struct in6_addr *addr6, *mask6;
622         struct audit_buffer *audit_buf = NULL;
623         char *secctx = NULL;
624         u32 secctx_len;
625
626         if (addr_len != sizeof(struct in_addr) &&
627             addr_len != sizeof(struct in6_addr))
628                 return -EINVAL;
629
630         rcu_read_lock();
631         if (dev_name != NULL) {
632                 dev = dev_get_by_name(net, dev_name);
633                 if (dev == NULL) {
634                         ret_val = -ENODEV;
635                         goto unlhsh_add_return;
636                 }
637                 ifindex = dev->ifindex;
638                 dev_put(dev);
639                 iface = netlbl_unlhsh_search_iface(ifindex);
640         } else {
641                 ifindex = 0;
642                 iface = rcu_dereference(netlbl_unlhsh_def);
643         }
644         if (iface == NULL) {
645                 iface = netlbl_unlhsh_add_iface(ifindex);
646                 if (iface == NULL) {
647                         ret_val = -ENOMEM;
648                         goto unlhsh_add_return;
649                 }
650         }
651         audit_buf = netlbl_audit_start_common(AUDIT_MAC_UNLBL_STCADD,
652                                               audit_info);
653         switch (addr_len) {
654         case sizeof(struct in_addr):
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 #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
665         case sizeof(struct in6_addr):
666                 addr6 = (struct in6_addr *)addr;
667                 mask6 = (struct in6_addr *)mask;
668                 ret_val = netlbl_unlhsh_add_addr6(iface, addr6, mask6, secid);
669                 if (audit_buf != NULL)
670                         netlbl_unlabel_audit_addr6(audit_buf,
671                                                    dev_name,
672                                                    addr6, mask6);
673                 break;
674 #endif /* IPv6 */
675         default:
676                 ret_val = -EINVAL;
677         }
678         if (ret_val == 0)
679                 atomic_inc(&netlabel_mgmt_protocount);
680
681 unlhsh_add_return:
682         rcu_read_unlock();
683         if (audit_buf != NULL) {
684                 if (security_secid_to_secctx(secid,
685                                              &secctx,
686                                              &secctx_len) == 0) {
687                         audit_log_format(audit_buf, " sec_obj=%s", secctx);
688                         security_release_secctx(secctx, secctx_len);
689                 }
690                 audit_log_format(audit_buf, " res=%u", ret_val == 0 ? 1 : 0);
691                 audit_log_end(audit_buf);
692         }
693         return ret_val;
694 }
695
696 /**
697  * netlbl_unlhsh_remove_addr4 - Remove an IPv4 address entry
698  * @net: network namespace
699  * @iface: interface entry
700  * @addr: IP address
701  * @mask: IP address mask
702  * @audit_info: NetLabel audit information
703  *
704  * Description:
705  * Remove an IP address entry from the unlabeled connection hash table.
706  * Returns zero on success, negative values on failure.  The caller is
707  * responsible for calling the rcu_read_[un]lock() functions.
708  *
709  */
710 static int netlbl_unlhsh_remove_addr4(struct net *net,
711                                       struct netlbl_unlhsh_iface *iface,
712                                       const struct in_addr *addr,
713                                       const struct in_addr *mask,
714                                       struct netlbl_audit *audit_info)
715 {
716         int ret_val = -ENOENT;
717         struct netlbl_unlhsh_addr4 *entry;
718         struct audit_buffer *audit_buf = NULL;
719         struct net_device *dev;
720         char *secctx = NULL;
721         u32 secctx_len;
722
723         spin_lock(&netlbl_unlhsh_lock);
724         entry = netlbl_unlhsh_search_addr4(addr->s_addr, iface);
725         if (entry != NULL &&
726             entry->addr == addr->s_addr && entry->mask == mask->s_addr) {
727                 entry->valid = 0;
728                 list_del_rcu(&entry->list);
729                 ret_val = 0;
730         }
731         spin_unlock(&netlbl_unlhsh_lock);
732
733         audit_buf = netlbl_audit_start_common(AUDIT_MAC_UNLBL_STCDEL,
734                                               audit_info);
735         if (audit_buf != NULL) {
736                 dev = dev_get_by_index(net, iface->ifindex);
737                 netlbl_unlabel_audit_addr4(audit_buf,
738                                            (dev != NULL ? dev->name : NULL),
739                                            entry->addr, entry->mask);
740                 if (dev != NULL)
741                         dev_put(dev);
742                 if (security_secid_to_secctx(entry->secid,
743                                              &secctx,
744                                              &secctx_len) == 0) {
745                         audit_log_format(audit_buf, " sec_obj=%s", secctx);
746                         security_release_secctx(secctx, secctx_len);
747                 }
748                 audit_log_format(audit_buf, " res=%u", ret_val == 0 ? 1 : 0);
749                 audit_log_end(audit_buf);
750         }
751
752         if (ret_val == 0)
753                 call_rcu(&entry->rcu, netlbl_unlhsh_free_addr4);
754         return ret_val;
755 }
756
757 #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
758 /**
759  * netlbl_unlhsh_remove_addr6 - Remove an IPv6 address entry
760  * @net: network namespace
761  * @iface: interface entry
762  * @addr: IP address
763  * @mask: IP address mask
764  * @audit_info: NetLabel audit information
765  *
766  * Description:
767  * Remove an IP address entry from the unlabeled connection hash table.
768  * Returns zero on success, negative values on failure.  The caller is
769  * responsible for calling the rcu_read_[un]lock() functions.
770  *
771  */
772 static int netlbl_unlhsh_remove_addr6(struct net *net,
773                                       struct netlbl_unlhsh_iface *iface,
774                                       const struct in6_addr *addr,
775                                       const struct in6_addr *mask,
776                                       struct netlbl_audit *audit_info)
777 {
778         int ret_val = -ENOENT;
779         struct netlbl_unlhsh_addr6 *entry;
780         struct audit_buffer *audit_buf = NULL;
781         struct net_device *dev;
782         char *secctx = NULL;
783         u32 secctx_len;
784
785         spin_lock(&netlbl_unlhsh_lock);
786         entry = netlbl_unlhsh_search_addr6(addr, iface);
787         if (entry != NULL &&
788             (ipv6_addr_equal(&entry->addr, addr) &&
789              ipv6_addr_equal(&entry->mask, mask))) {
790                 entry->valid = 0;
791                 list_del_rcu(&entry->list);
792                 ret_val = 0;
793         }
794         spin_unlock(&netlbl_unlhsh_lock);
795
796         audit_buf = netlbl_audit_start_common(AUDIT_MAC_UNLBL_STCDEL,
797                                               audit_info);
798         if (audit_buf != NULL) {
799                 dev = dev_get_by_index(net, iface->ifindex);
800                 netlbl_unlabel_audit_addr6(audit_buf,
801                                            (dev != NULL ? dev->name : NULL),
802                                            addr, mask);
803                 if (dev != NULL)
804                         dev_put(dev);
805                 if (security_secid_to_secctx(entry->secid,
806                                              &secctx,
807                                              &secctx_len) == 0) {
808                         audit_log_format(audit_buf, " sec_obj=%s", secctx);
809                         security_release_secctx(secctx, secctx_len);
810                 }
811                 audit_log_format(audit_buf, " res=%u", ret_val == 0 ? 1 : 0);
812                 audit_log_end(audit_buf);
813         }
814
815         if (ret_val == 0)
816                 call_rcu(&entry->rcu, netlbl_unlhsh_free_addr6);
817         return ret_val;
818 }
819 #endif /* IPv6 */
820
821 /**
822  * netlbl_unlhsh_condremove_iface - Remove an interface entry
823  * @iface: the interface entry
824  *
825  * Description:
826  * Remove an interface entry from the unlabeled connection hash table if it is
827  * empty.  An interface entry is considered to be empty if there are no
828  * address entries assigned to it.
829  *
830  */
831 static void netlbl_unlhsh_condremove_iface(struct netlbl_unlhsh_iface *iface)
832 {
833         struct netlbl_unlhsh_addr4 *iter4;
834         struct netlbl_unlhsh_addr6 *iter6;
835
836         spin_lock(&netlbl_unlhsh_lock);
837         list_for_each_entry_rcu(iter4, &iface->addr4_list, list)
838                 if (iter4->valid)
839                         goto unlhsh_condremove_failure;
840         list_for_each_entry_rcu(iter6, &iface->addr6_list, list)
841                 if (iter6->valid)
842                         goto unlhsh_condremove_failure;
843         iface->valid = 0;
844         if (iface->ifindex > 0)
845                 list_del_rcu(&iface->list);
846         else
847                 rcu_assign_pointer(netlbl_unlhsh_def, NULL);
848         spin_unlock(&netlbl_unlhsh_lock);
849
850         call_rcu(&iface->rcu, netlbl_unlhsh_free_iface);
851         return;
852
853 unlhsh_condremove_failure:
854         spin_unlock(&netlbl_unlhsh_lock);
855         return;
856 }
857
858 /**
859  * netlbl_unlhsh_remove - Remove an entry from the unlabeled hash table
860  * @net: network namespace
861  * @dev_name: interface name
862  * @addr: IP address in network byte order
863  * @mask: address mask in network byte order
864  * @addr_len: length of address/mask (4 for IPv4, 16 for IPv6)
865  * @audit_info: NetLabel audit information
866  *
867  * Description:
868  * Removes and existing entry from the unlabeled connection hash table.
869  * Returns zero on success, negative values on failure.
870  *
871  */
872 static int netlbl_unlhsh_remove(struct net *net,
873                                 const char *dev_name,
874                                 const void *addr,
875                                 const void *mask,
876                                 u32 addr_len,
877                                 struct netlbl_audit *audit_info)
878 {
879         int ret_val;
880         struct net_device *dev;
881         struct netlbl_unlhsh_iface *iface;
882
883         if (addr_len != sizeof(struct in_addr) &&
884             addr_len != sizeof(struct in6_addr))
885                 return -EINVAL;
886
887         rcu_read_lock();
888         if (dev_name != NULL) {
889                 dev = dev_get_by_name(net, dev_name);
890                 if (dev == NULL) {
891                         ret_val = -ENODEV;
892                         goto unlhsh_remove_return;
893                 }
894                 iface = netlbl_unlhsh_search_iface(dev->ifindex);
895                 dev_put(dev);
896         } else
897                 iface = rcu_dereference(netlbl_unlhsh_def);
898         if (iface == NULL) {
899                 ret_val = -ENOENT;
900                 goto unlhsh_remove_return;
901         }
902         switch (addr_len) {
903         case sizeof(struct in_addr):
904                 ret_val = netlbl_unlhsh_remove_addr4(net,
905                                                      iface, addr, mask,
906                                                      audit_info);
907                 break;
908 #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
909         case sizeof(struct in6_addr):
910                 ret_val = netlbl_unlhsh_remove_addr6(net,
911                                                      iface, addr, mask,
912                                                      audit_info);
913                 break;
914 #endif /* IPv6 */
915         default:
916                 ret_val = -EINVAL;
917         }
918         if (ret_val == 0) {
919                 netlbl_unlhsh_condremove_iface(iface);
920                 atomic_dec(&netlabel_mgmt_protocount);
921         }
922
923 unlhsh_remove_return:
924         rcu_read_unlock();
925         return ret_val;
926 }
927
928 /*
929  * General Helper Functions
930  */
931
932 /**
933  * netlbl_unlhsh_netdev_handler - Network device notification handler
934  * @this: notifier block
935  * @event: the event
936  * @ptr: the network device (cast to void)
937  *
938  * Description:
939  * Handle network device events, although at present all we care about is a
940  * network device going away.  In the case of a device going away we clear any
941  * related entries from the unlabeled connection hash table.
942  *
943  */
944 static int netlbl_unlhsh_netdev_handler(struct notifier_block *this,
945                                         unsigned long event,
946                                         void *ptr)
947 {
948         struct net_device *dev = ptr;
949         struct netlbl_unlhsh_iface *iface = NULL;
950
951         if (dev->nd_net != &init_net)
952                 return NOTIFY_DONE;
953
954         /* XXX - should this be a check for NETDEV_DOWN or _UNREGISTER? */
955         if (event == NETDEV_DOWN) {
956                 spin_lock(&netlbl_unlhsh_lock);
957                 iface = netlbl_unlhsh_search_iface(dev->ifindex);
958                 if (iface != NULL && iface->valid) {
959                         iface->valid = 0;
960                         list_del_rcu(&iface->list);
961                 } else
962                         iface = NULL;
963                 spin_unlock(&netlbl_unlhsh_lock);
964         }
965
966         if (iface != NULL)
967                 call_rcu(&iface->rcu, netlbl_unlhsh_free_iface);
968
969         return NOTIFY_DONE;
970 }
971
972 /**
973  * netlbl_unlabel_acceptflg_set - Set the unlabeled accept flag
974  * @value: desired value
975  * @audit_info: NetLabel audit information
976  *
977  * Description:
978  * Set the value of the unlabeled accept flag to @value.
979  *
980  */
981 static void netlbl_unlabel_acceptflg_set(u8 value,
982                                          struct netlbl_audit *audit_info)
983 {
984         struct audit_buffer *audit_buf;
985         u8 old_val;
986
987         old_val = netlabel_unlabel_acceptflg;
988         netlabel_unlabel_acceptflg = value;
989         audit_buf = netlbl_audit_start_common(AUDIT_MAC_UNLBL_ALLOW,
990                                               audit_info);
991         if (audit_buf != NULL) {
992                 audit_log_format(audit_buf,
993                                  " unlbl_accept=%u old=%u", value, old_val);
994                 audit_log_end(audit_buf);
995         }
996 }
997
998 /**
999  * netlbl_unlabel_addrinfo_get - Get the IPv4/6 address information
1000  * @info: the Generic NETLINK info block
1001  * @addr: the IP address
1002  * @mask: the IP address mask
1003  * @len: the address length
1004  *
1005  * Description:
1006  * Examine the Generic NETLINK message and extract the IP address information.
1007  * Returns zero on success, negative values on failure.
1008  *
1009  */
1010 static int netlbl_unlabel_addrinfo_get(struct genl_info *info,
1011                                        void **addr,
1012                                        void **mask,
1013                                        u32 *len)
1014 {
1015         u32 addr_len;
1016
1017         if (info->attrs[NLBL_UNLABEL_A_IPV4ADDR]) {
1018                 addr_len = nla_len(info->attrs[NLBL_UNLABEL_A_IPV4ADDR]);
1019                 if (addr_len != sizeof(struct in_addr) &&
1020                     addr_len != nla_len(info->attrs[NLBL_UNLABEL_A_IPV4MASK]))
1021                         return -EINVAL;
1022                 *len = addr_len;
1023                 *addr = nla_data(info->attrs[NLBL_UNLABEL_A_IPV4ADDR]);
1024                 *mask = nla_data(info->attrs[NLBL_UNLABEL_A_IPV4MASK]);
1025                 return 0;
1026         } else if (info->attrs[NLBL_UNLABEL_A_IPV6ADDR]) {
1027                 addr_len = nla_len(info->attrs[NLBL_UNLABEL_A_IPV6ADDR]);
1028                 if (addr_len != sizeof(struct in6_addr) &&
1029                     addr_len != nla_len(info->attrs[NLBL_UNLABEL_A_IPV6MASK]))
1030                         return -EINVAL;
1031                 *len = addr_len;
1032                 *addr = nla_data(info->attrs[NLBL_UNLABEL_A_IPV6ADDR]);
1033                 *mask = nla_data(info->attrs[NLBL_UNLABEL_A_IPV6MASK]);
1034                 return 0;
1035         }
1036
1037         return -EINVAL;
1038 }
1039
1040 /*
1041  * NetLabel Command Handlers
1042  */
1043
1044 /**
1045  * netlbl_unlabel_accept - Handle an ACCEPT message
1046  * @skb: the NETLINK buffer
1047  * @info: the Generic NETLINK info block
1048  *
1049  * Description:
1050  * Process a user generated ACCEPT message and set the accept flag accordingly.
1051  * Returns zero on success, negative values on failure.
1052  *
1053  */
1054 static int netlbl_unlabel_accept(struct sk_buff *skb, struct genl_info *info)
1055 {
1056         u8 value;
1057         struct netlbl_audit audit_info;
1058
1059         if (info->attrs[NLBL_UNLABEL_A_ACPTFLG]) {
1060                 value = nla_get_u8(info->attrs[NLBL_UNLABEL_A_ACPTFLG]);
1061                 if (value == 1 || value == 0) {
1062                         netlbl_netlink_auditinfo(skb, &audit_info);
1063                         netlbl_unlabel_acceptflg_set(value, &audit_info);
1064                         return 0;
1065                 }
1066         }
1067
1068         return -EINVAL;
1069 }
1070
1071 /**
1072  * netlbl_unlabel_list - Handle a LIST message
1073  * @skb: the NETLINK buffer
1074  * @info: the Generic NETLINK info block
1075  *
1076  * Description:
1077  * Process a user generated LIST message and respond with the current status.
1078  * Returns zero on success, negative values on failure.
1079  *
1080  */
1081 static int netlbl_unlabel_list(struct sk_buff *skb, struct genl_info *info)
1082 {
1083         int ret_val = -EINVAL;
1084         struct sk_buff *ans_skb;
1085         void *data;
1086
1087         ans_skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
1088         if (ans_skb == NULL)
1089                 goto list_failure;
1090         data = genlmsg_put_reply(ans_skb, info, &netlbl_unlabel_gnl_family,
1091                                  0, NLBL_UNLABEL_C_LIST);
1092         if (data == NULL) {
1093                 ret_val = -ENOMEM;
1094                 goto list_failure;
1095         }
1096
1097         ret_val = nla_put_u8(ans_skb,
1098                              NLBL_UNLABEL_A_ACPTFLG,
1099                              netlabel_unlabel_acceptflg);
1100         if (ret_val != 0)
1101                 goto list_failure;
1102
1103         genlmsg_end(ans_skb, data);
1104
1105         ret_val = genlmsg_reply(ans_skb, info);
1106         if (ret_val != 0)
1107                 goto list_failure;
1108         return 0;
1109
1110 list_failure:
1111         kfree_skb(ans_skb);
1112         return ret_val;
1113 }
1114
1115 /**
1116  * netlbl_unlabel_staticadd - Handle a STATICADD message
1117  * @skb: the NETLINK buffer
1118  * @info: the Generic NETLINK info block
1119  *
1120  * Description:
1121  * Process a user generated STATICADD message and add a new unlabeled
1122  * connection entry to the hash table.  Returns zero on success, negative
1123  * values on failure.
1124  *
1125  */
1126 static int netlbl_unlabel_staticadd(struct sk_buff *skb,
1127                                     struct genl_info *info)
1128 {
1129         int ret_val;
1130         char *dev_name;
1131         void *addr;
1132         void *mask;
1133         u32 addr_len;
1134         u32 secid;
1135         struct netlbl_audit audit_info;
1136
1137         /* Don't allow users to add both IPv4 and IPv6 addresses for a
1138          * single entry.  However, allow users to create two entries, one each
1139          * for IPv4 and IPv4, with the same LSM security context which should
1140          * achieve the same result. */
1141         if (!info->attrs[NLBL_UNLABEL_A_SECCTX] ||
1142             !info->attrs[NLBL_UNLABEL_A_IFACE] ||
1143             !((!info->attrs[NLBL_UNLABEL_A_IPV4ADDR] ||
1144                !info->attrs[NLBL_UNLABEL_A_IPV4MASK]) ^
1145               (!info->attrs[NLBL_UNLABEL_A_IPV6ADDR] ||
1146                !info->attrs[NLBL_UNLABEL_A_IPV6MASK])))
1147                 return -EINVAL;
1148
1149         netlbl_netlink_auditinfo(skb, &audit_info);
1150
1151         ret_val = netlbl_unlabel_addrinfo_get(info, &addr, &mask, &addr_len);
1152         if (ret_val != 0)
1153                 return ret_val;
1154         dev_name = nla_data(info->attrs[NLBL_UNLABEL_A_IFACE]);
1155         ret_val = security_secctx_to_secid(
1156                                   nla_data(info->attrs[NLBL_UNLABEL_A_SECCTX]),
1157                                   nla_len(info->attrs[NLBL_UNLABEL_A_SECCTX]),
1158                                   &secid);
1159         if (ret_val != 0)
1160                 return ret_val;
1161
1162         return netlbl_unlhsh_add(&init_net,
1163                                  dev_name, addr, mask, addr_len, secid,
1164                                  &audit_info);
1165 }
1166
1167 /**
1168  * netlbl_unlabel_staticadddef - Handle a STATICADDDEF message
1169  * @skb: the NETLINK buffer
1170  * @info: the Generic NETLINK info block
1171  *
1172  * Description:
1173  * Process a user generated STATICADDDEF message and add a new default
1174  * unlabeled connection entry.  Returns zero on success, negative values on
1175  * failure.
1176  *
1177  */
1178 static int netlbl_unlabel_staticadddef(struct sk_buff *skb,
1179                                        struct genl_info *info)
1180 {
1181         int ret_val;
1182         void *addr;
1183         void *mask;
1184         u32 addr_len;
1185         u32 secid;
1186         struct netlbl_audit audit_info;
1187
1188         /* Don't allow users to add both IPv4 and IPv6 addresses for a
1189          * single entry.  However, allow users to create two entries, one each
1190          * for IPv4 and IPv6, with the same LSM security context which should
1191          * achieve the same result. */
1192         if (!info->attrs[NLBL_UNLABEL_A_SECCTX] ||
1193             !((!info->attrs[NLBL_UNLABEL_A_IPV4ADDR] ||
1194                !info->attrs[NLBL_UNLABEL_A_IPV4MASK]) ^
1195               (!info->attrs[NLBL_UNLABEL_A_IPV6ADDR] ||
1196                !info->attrs[NLBL_UNLABEL_A_IPV6MASK])))
1197                 return -EINVAL;
1198
1199         netlbl_netlink_auditinfo(skb, &audit_info);
1200
1201         ret_val = netlbl_unlabel_addrinfo_get(info, &addr, &mask, &addr_len);
1202         if (ret_val != 0)
1203                 return ret_val;
1204         ret_val = security_secctx_to_secid(
1205                                   nla_data(info->attrs[NLBL_UNLABEL_A_SECCTX]),
1206                                   nla_len(info->attrs[NLBL_UNLABEL_A_SECCTX]),
1207                                   &secid);
1208         if (ret_val != 0)
1209                 return ret_val;
1210
1211         return netlbl_unlhsh_add(&init_net,
1212                                  NULL, addr, mask, addr_len, secid,
1213                                  &audit_info);
1214 }
1215
1216 /**
1217  * netlbl_unlabel_staticremove - Handle a STATICREMOVE message
1218  * @skb: the NETLINK buffer
1219  * @info: the Generic NETLINK info block
1220  *
1221  * Description:
1222  * Process a user generated STATICREMOVE message and remove the specified
1223  * unlabeled connection entry.  Returns zero on success, negative values on
1224  * failure.
1225  *
1226  */
1227 static int netlbl_unlabel_staticremove(struct sk_buff *skb,
1228                                        struct genl_info *info)
1229 {
1230         int ret_val;
1231         char *dev_name;
1232         void *addr;
1233         void *mask;
1234         u32 addr_len;
1235         struct netlbl_audit audit_info;
1236
1237         /* See the note in netlbl_unlabel_staticadd() about not allowing both
1238          * IPv4 and IPv6 in the same entry. */
1239         if (!info->attrs[NLBL_UNLABEL_A_IFACE] ||
1240             !((!info->attrs[NLBL_UNLABEL_A_IPV4ADDR] ||
1241                !info->attrs[NLBL_UNLABEL_A_IPV4MASK]) ^
1242               (!info->attrs[NLBL_UNLABEL_A_IPV6ADDR] ||
1243                !info->attrs[NLBL_UNLABEL_A_IPV6MASK])))
1244                 return -EINVAL;
1245
1246         netlbl_netlink_auditinfo(skb, &audit_info);
1247
1248         ret_val = netlbl_unlabel_addrinfo_get(info, &addr, &mask, &addr_len);
1249         if (ret_val != 0)
1250                 return ret_val;
1251         dev_name = nla_data(info->attrs[NLBL_UNLABEL_A_IFACE]);
1252
1253         return netlbl_unlhsh_remove(&init_net,
1254                                     dev_name, addr, mask, addr_len,
1255                                     &audit_info);
1256 }
1257
1258 /**
1259  * netlbl_unlabel_staticremovedef - Handle a STATICREMOVEDEF message
1260  * @skb: the NETLINK buffer
1261  * @info: the Generic NETLINK info block
1262  *
1263  * Description:
1264  * Process a user generated STATICREMOVEDEF message and remove the default
1265  * unlabeled connection entry.  Returns zero on success, negative values on
1266  * failure.
1267  *
1268  */
1269 static int netlbl_unlabel_staticremovedef(struct sk_buff *skb,
1270                                           struct genl_info *info)
1271 {
1272         int ret_val;
1273         void *addr;
1274         void *mask;
1275         u32 addr_len;
1276         struct netlbl_audit audit_info;
1277
1278         /* See the note in netlbl_unlabel_staticadd() about not allowing both
1279          * IPv4 and IPv6 in the same entry. */
1280         if (!((!info->attrs[NLBL_UNLABEL_A_IPV4ADDR] ||
1281                !info->attrs[NLBL_UNLABEL_A_IPV4MASK]) ^
1282               (!info->attrs[NLBL_UNLABEL_A_IPV6ADDR] ||
1283                !info->attrs[NLBL_UNLABEL_A_IPV6MASK])))
1284                 return -EINVAL;
1285
1286         netlbl_netlink_auditinfo(skb, &audit_info);
1287
1288         ret_val = netlbl_unlabel_addrinfo_get(info, &addr, &mask, &addr_len);
1289         if (ret_val != 0)
1290                 return ret_val;
1291
1292         return netlbl_unlhsh_remove(&init_net,
1293                                     NULL, addr, mask, addr_len,
1294                                     &audit_info);
1295 }
1296
1297
1298 /**
1299  * netlbl_unlabel_staticlist_gen - Generate messages for STATICLIST[DEF]
1300  * @cmd: command/message
1301  * @iface: the interface entry
1302  * @addr4: the IPv4 address entry
1303  * @addr6: the IPv6 address entry
1304  * @arg: the netlbl_unlhsh_walk_arg structure
1305  *
1306  * Description:
1307  * This function is designed to be used to generate a response for a
1308  * STATICLIST or STATICLISTDEF message.  When called either @addr4 or @addr6
1309  * can be specified, not both, the other unspecified entry should be set to
1310  * NULL by the caller.  Returns the size of the message on success, negative
1311  * values on failure.
1312  *
1313  */
1314 static int netlbl_unlabel_staticlist_gen(u32 cmd,
1315                                        const struct netlbl_unlhsh_iface *iface,
1316                                        const struct netlbl_unlhsh_addr4 *addr4,
1317                                        const struct netlbl_unlhsh_addr6 *addr6,
1318                                        void *arg)
1319 {
1320         int ret_val = -ENOMEM;
1321         struct netlbl_unlhsh_walk_arg *cb_arg = arg;
1322         struct net_device *dev;
1323         void *data;
1324         u32 secid;
1325         char *secctx;
1326         u32 secctx_len;
1327
1328         data = genlmsg_put(cb_arg->skb, NETLINK_CB(cb_arg->nl_cb->skb).pid,
1329                            cb_arg->seq, &netlbl_unlabel_gnl_family,
1330                            NLM_F_MULTI, cmd);
1331         if (data == NULL)
1332                 goto list_cb_failure;
1333
1334         if (iface->ifindex > 0) {
1335                 dev = dev_get_by_index(&init_net, iface->ifindex);
1336                 ret_val = nla_put_string(cb_arg->skb,
1337                                          NLBL_UNLABEL_A_IFACE, dev->name);
1338                 dev_put(dev);
1339                 if (ret_val != 0)
1340                         goto list_cb_failure;
1341         }
1342
1343         if (addr4) {
1344                 struct in_addr addr_struct;
1345
1346                 addr_struct.s_addr = addr4->addr;
1347                 ret_val = nla_put(cb_arg->skb,
1348                                   NLBL_UNLABEL_A_IPV4ADDR,
1349                                   sizeof(struct in_addr),
1350                                   &addr_struct);
1351                 if (ret_val != 0)
1352                         goto list_cb_failure;
1353
1354                 addr_struct.s_addr = addr4->mask;
1355                 ret_val = nla_put(cb_arg->skb,
1356                                   NLBL_UNLABEL_A_IPV4MASK,
1357                                   sizeof(struct in_addr),
1358                                   &addr_struct);
1359                 if (ret_val != 0)
1360                         goto list_cb_failure;
1361
1362                 secid = addr4->secid;
1363         } else {
1364                 ret_val = nla_put(cb_arg->skb,
1365                                   NLBL_UNLABEL_A_IPV6ADDR,
1366                                   sizeof(struct in6_addr),
1367                                   &addr6->addr);
1368                 if (ret_val != 0)
1369                         goto list_cb_failure;
1370
1371                 ret_val = nla_put(cb_arg->skb,
1372                                   NLBL_UNLABEL_A_IPV6MASK,
1373                                   sizeof(struct in6_addr),
1374                                   &addr6->mask);
1375                 if (ret_val != 0)
1376                         goto list_cb_failure;
1377
1378                 secid = addr6->secid;
1379         }
1380
1381         ret_val = security_secid_to_secctx(secid, &secctx, &secctx_len);
1382         if (ret_val != 0)
1383                 goto list_cb_failure;
1384         ret_val = nla_put(cb_arg->skb,
1385                           NLBL_UNLABEL_A_SECCTX,
1386                           secctx_len,
1387                           secctx);
1388         security_release_secctx(secctx, secctx_len);
1389         if (ret_val != 0)
1390                 goto list_cb_failure;
1391
1392         cb_arg->seq++;
1393         return genlmsg_end(cb_arg->skb, data);
1394
1395 list_cb_failure:
1396         genlmsg_cancel(cb_arg->skb, data);
1397         return ret_val;
1398 }
1399
1400 /**
1401  * netlbl_unlabel_staticlist - Handle a STATICLIST message
1402  * @skb: the NETLINK buffer
1403  * @cb: the NETLINK callback
1404  *
1405  * Description:
1406  * Process a user generated STATICLIST message and dump the unlabeled
1407  * connection hash table in a form suitable for use in a kernel generated
1408  * STATICLIST message.  Returns the length of @skb.
1409  *
1410  */
1411 static int netlbl_unlabel_staticlist(struct sk_buff *skb,
1412                                      struct netlink_callback *cb)
1413 {
1414         struct netlbl_unlhsh_walk_arg cb_arg;
1415         u32 skip_bkt = cb->args[0];
1416         u32 skip_chain = cb->args[1];
1417         u32 skip_addr4 = cb->args[2];
1418         u32 skip_addr6 = cb->args[3];
1419         u32 iter_bkt;
1420         u32 iter_chain = 0, iter_addr4 = 0, iter_addr6 = 0;
1421         struct netlbl_unlhsh_iface *iface;
1422         struct netlbl_unlhsh_addr4 *addr4;
1423         struct netlbl_unlhsh_addr6 *addr6;
1424
1425         cb_arg.nl_cb = cb;
1426         cb_arg.skb = skb;
1427         cb_arg.seq = cb->nlh->nlmsg_seq;
1428
1429         rcu_read_lock();
1430         for (iter_bkt = skip_bkt;
1431              iter_bkt < rcu_dereference(netlbl_unlhsh)->size;
1432              iter_bkt++, iter_chain = 0, iter_addr4 = 0, iter_addr6 = 0) {
1433                 list_for_each_entry_rcu(iface,
1434                                 &rcu_dereference(netlbl_unlhsh)->tbl[iter_bkt],
1435                                 list) {
1436                         if (!iface->valid ||
1437                             iter_chain++ < skip_chain)
1438                                 continue;
1439                         list_for_each_entry_rcu(addr4,
1440                                                 &iface->addr4_list,
1441                                                 list) {
1442                                 if (!addr4->valid || iter_addr4++ < skip_addr4)
1443                                         continue;
1444                                 if (netlbl_unlabel_staticlist_gen(
1445                                                      NLBL_UNLABEL_C_STATICLIST,
1446                                                      iface,
1447                                                      addr4,
1448                                                      NULL,
1449                                                      &cb_arg) < 0) {
1450                                         iter_addr4--;
1451                                         iter_chain--;
1452                                         goto unlabel_staticlist_return;
1453                                 }
1454                         }
1455                         list_for_each_entry_rcu(addr6,
1456                                                 &iface->addr6_list,
1457                                                 list) {
1458                                 if (!addr6->valid || iter_addr6++ < skip_addr6)
1459                                         continue;
1460                                 if (netlbl_unlabel_staticlist_gen(
1461                                                      NLBL_UNLABEL_C_STATICLIST,
1462                                                      iface,
1463                                                      NULL,
1464                                                      addr6,
1465                                                      &cb_arg) < 0) {
1466                                         iter_addr6--;
1467                                         iter_chain--;
1468                                         goto unlabel_staticlist_return;
1469                                 }
1470                         }
1471                 }
1472         }
1473
1474 unlabel_staticlist_return:
1475         rcu_read_unlock();
1476         cb->args[0] = skip_bkt;
1477         cb->args[1] = skip_chain;
1478         cb->args[2] = skip_addr4;
1479         cb->args[3] = skip_addr6;
1480         return skb->len;
1481 }
1482
1483 /**
1484  * netlbl_unlabel_staticlistdef - Handle a STATICLISTDEF message
1485  * @skb: the NETLINK buffer
1486  * @cb: the NETLINK callback
1487  *
1488  * Description:
1489  * Process a user generated STATICLISTDEF message and dump the default
1490  * unlabeled connection entry in a form suitable for use in a kernel generated
1491  * STATICLISTDEF message.  Returns the length of @skb.
1492  *
1493  */
1494 static int netlbl_unlabel_staticlistdef(struct sk_buff *skb,
1495                                         struct netlink_callback *cb)
1496 {
1497         struct netlbl_unlhsh_walk_arg cb_arg;
1498         struct netlbl_unlhsh_iface *iface;
1499         u32 skip_addr4 = cb->args[0];
1500         u32 skip_addr6 = cb->args[1];
1501         u32 iter_addr4 = 0, iter_addr6 = 0;
1502         struct netlbl_unlhsh_addr4 *addr4;
1503         struct netlbl_unlhsh_addr6 *addr6;
1504
1505         cb_arg.nl_cb = cb;
1506         cb_arg.skb = skb;
1507         cb_arg.seq = cb->nlh->nlmsg_seq;
1508
1509         rcu_read_lock();
1510         iface = rcu_dereference(netlbl_unlhsh_def);
1511         if (iface == NULL || !iface->valid)
1512                 goto unlabel_staticlistdef_return;
1513
1514         list_for_each_entry_rcu(addr4, &iface->addr4_list, list) {
1515                 if (!addr4->valid || iter_addr4++ < skip_addr4)
1516                         continue;
1517                 if (netlbl_unlabel_staticlist_gen(NLBL_UNLABEL_C_STATICLISTDEF,
1518                                            iface,
1519                                            addr4,
1520                                            NULL,
1521                                            &cb_arg) < 0) {
1522                         iter_addr4--;
1523                         goto unlabel_staticlistdef_return;
1524                 }
1525         }
1526         list_for_each_entry_rcu(addr6, &iface->addr6_list, list) {
1527                 if (addr6->valid || iter_addr6++ < skip_addr6)
1528                         continue;
1529                 if (netlbl_unlabel_staticlist_gen(NLBL_UNLABEL_C_STATICLISTDEF,
1530                                            iface,
1531                                            NULL,
1532                                            addr6,
1533                                            &cb_arg) < 0) {
1534                         iter_addr6--;
1535                         goto unlabel_staticlistdef_return;
1536                 }
1537         }
1538
1539 unlabel_staticlistdef_return:
1540         rcu_read_unlock();
1541         cb->args[0] = skip_addr4;
1542         cb->args[1] = skip_addr6;
1543         return skb->len;
1544 }
1545
1546 /*
1547  * NetLabel Generic NETLINK Command Definitions
1548  */
1549
1550 static struct genl_ops netlbl_unlabel_genl_c_staticadd = {
1551         .cmd = NLBL_UNLABEL_C_STATICADD,
1552         .flags = GENL_ADMIN_PERM,
1553         .policy = netlbl_unlabel_genl_policy,
1554         .doit = netlbl_unlabel_staticadd,
1555         .dumpit = NULL,
1556 };
1557
1558 static struct genl_ops netlbl_unlabel_genl_c_staticremove = {
1559         .cmd = NLBL_UNLABEL_C_STATICREMOVE,
1560         .flags = GENL_ADMIN_PERM,
1561         .policy = netlbl_unlabel_genl_policy,
1562         .doit = netlbl_unlabel_staticremove,
1563         .dumpit = NULL,
1564 };
1565
1566 static struct genl_ops netlbl_unlabel_genl_c_staticlist = {
1567         .cmd = NLBL_UNLABEL_C_STATICLIST,
1568         .flags = 0,
1569         .policy = netlbl_unlabel_genl_policy,
1570         .doit = NULL,
1571         .dumpit = netlbl_unlabel_staticlist,
1572 };
1573
1574 static struct genl_ops netlbl_unlabel_genl_c_staticadddef = {
1575         .cmd = NLBL_UNLABEL_C_STATICADDDEF,
1576         .flags = GENL_ADMIN_PERM,
1577         .policy = netlbl_unlabel_genl_policy,
1578         .doit = netlbl_unlabel_staticadddef,
1579         .dumpit = NULL,
1580 };
1581
1582 static struct genl_ops netlbl_unlabel_genl_c_staticremovedef = {
1583         .cmd = NLBL_UNLABEL_C_STATICREMOVEDEF,
1584         .flags = GENL_ADMIN_PERM,
1585         .policy = netlbl_unlabel_genl_policy,
1586         .doit = netlbl_unlabel_staticremovedef,
1587         .dumpit = NULL,
1588 };
1589
1590 static struct genl_ops netlbl_unlabel_genl_c_staticlistdef = {
1591         .cmd = NLBL_UNLABEL_C_STATICLISTDEF,
1592         .flags = 0,
1593         .policy = netlbl_unlabel_genl_policy,
1594         .doit = NULL,
1595         .dumpit = netlbl_unlabel_staticlistdef,
1596 };
1597
1598 static struct genl_ops netlbl_unlabel_genl_c_accept = {
1599         .cmd = NLBL_UNLABEL_C_ACCEPT,
1600         .flags = GENL_ADMIN_PERM,
1601         .policy = netlbl_unlabel_genl_policy,
1602         .doit = netlbl_unlabel_accept,
1603         .dumpit = NULL,
1604 };
1605
1606 static struct genl_ops netlbl_unlabel_genl_c_list = {
1607         .cmd = NLBL_UNLABEL_C_LIST,
1608         .flags = 0,
1609         .policy = netlbl_unlabel_genl_policy,
1610         .doit = netlbl_unlabel_list,
1611         .dumpit = NULL,
1612 };
1613
1614 /*
1615  * NetLabel Generic NETLINK Protocol Functions
1616  */
1617
1618 /**
1619  * netlbl_unlabel_genl_init - Register the Unlabeled NetLabel component
1620  *
1621  * Description:
1622  * Register the unlabeled packet NetLabel component with the Generic NETLINK
1623  * mechanism.  Returns zero on success, negative values on failure.
1624  *
1625  */
1626 int netlbl_unlabel_genl_init(void)
1627 {
1628         int ret_val;
1629
1630         ret_val = genl_register_family(&netlbl_unlabel_gnl_family);
1631         if (ret_val != 0)
1632                 return ret_val;
1633
1634         ret_val = genl_register_ops(&netlbl_unlabel_gnl_family,
1635                                     &netlbl_unlabel_genl_c_staticadd);
1636         if (ret_val != 0)
1637                 return ret_val;
1638
1639         ret_val = genl_register_ops(&netlbl_unlabel_gnl_family,
1640                                     &netlbl_unlabel_genl_c_staticremove);
1641         if (ret_val != 0)
1642                 return ret_val;
1643
1644         ret_val = genl_register_ops(&netlbl_unlabel_gnl_family,
1645                                     &netlbl_unlabel_genl_c_staticlist);
1646         if (ret_val != 0)
1647                 return ret_val;
1648
1649         ret_val = genl_register_ops(&netlbl_unlabel_gnl_family,
1650                                     &netlbl_unlabel_genl_c_staticadddef);
1651         if (ret_val != 0)
1652                 return ret_val;
1653
1654         ret_val = genl_register_ops(&netlbl_unlabel_gnl_family,
1655                                     &netlbl_unlabel_genl_c_staticremovedef);
1656         if (ret_val != 0)
1657                 return ret_val;
1658
1659         ret_val = genl_register_ops(&netlbl_unlabel_gnl_family,
1660                                     &netlbl_unlabel_genl_c_staticlistdef);
1661         if (ret_val != 0)
1662                 return ret_val;
1663
1664         ret_val = genl_register_ops(&netlbl_unlabel_gnl_family,
1665                                     &netlbl_unlabel_genl_c_accept);
1666         if (ret_val != 0)
1667                 return ret_val;
1668
1669         ret_val = genl_register_ops(&netlbl_unlabel_gnl_family,
1670                                     &netlbl_unlabel_genl_c_list);
1671         if (ret_val != 0)
1672                 return ret_val;
1673
1674         return 0;
1675 }
1676
1677 /*
1678  * NetLabel KAPI Hooks
1679  */
1680
1681 static struct notifier_block netlbl_unlhsh_netdev_notifier = {
1682         .notifier_call = netlbl_unlhsh_netdev_handler,
1683 };
1684
1685 /**
1686  * netlbl_unlabel_init - Initialize the unlabeled connection hash table
1687  * @size: the number of bits to use for the hash buckets
1688  *
1689  * Description:
1690  * Initializes the unlabeled connection hash table and registers a network
1691  * device notification handler.  This function should only be called by the
1692  * NetLabel subsystem itself during initialization.  Returns zero on success,
1693  * non-zero values on error.
1694  *
1695  */
1696 int netlbl_unlabel_init(u32 size)
1697 {
1698         u32 iter;
1699         struct netlbl_unlhsh_tbl *hsh_tbl;
1700
1701         if (size == 0)
1702                 return -EINVAL;
1703
1704         hsh_tbl = kmalloc(sizeof(*hsh_tbl), GFP_KERNEL);
1705         if (hsh_tbl == NULL)
1706                 return -ENOMEM;
1707         hsh_tbl->size = 1 << size;
1708         hsh_tbl->tbl = kcalloc(hsh_tbl->size,
1709                                sizeof(struct list_head),
1710                                GFP_KERNEL);
1711         if (hsh_tbl->tbl == NULL) {
1712                 kfree(hsh_tbl);
1713                 return -ENOMEM;
1714         }
1715         for (iter = 0; iter < hsh_tbl->size; iter++)
1716                 INIT_LIST_HEAD(&hsh_tbl->tbl[iter]);
1717
1718         rcu_read_lock();
1719         spin_lock(&netlbl_unlhsh_lock);
1720         rcu_assign_pointer(netlbl_unlhsh, hsh_tbl);
1721         spin_unlock(&netlbl_unlhsh_lock);
1722         rcu_read_unlock();
1723
1724         register_netdevice_notifier(&netlbl_unlhsh_netdev_notifier);
1725
1726         return 0;
1727 }
1728
1729 /**
1730  * netlbl_unlabel_getattr - Get the security attributes for an unlabled packet
1731  * @skb: the packet
1732  * @family: protocol family
1733  * @secattr: the security attributes
1734  *
1735  * Description:
1736  * Determine the security attributes, if any, for an unlabled packet and return
1737  * them in @secattr.  Returns zero on success and negative values on failure.
1738  *
1739  */
1740 int netlbl_unlabel_getattr(const struct sk_buff *skb,
1741                            u16 family,
1742                            struct netlbl_lsm_secattr *secattr)
1743 {
1744         struct iphdr *hdr4;
1745         struct ipv6hdr *hdr6;
1746         struct netlbl_unlhsh_addr4 *addr4;
1747         struct netlbl_unlhsh_addr6 *addr6;
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                 hdr4 = ip_hdr(skb);
1757                 addr4 = netlbl_unlhsh_search_addr4(hdr4->saddr, iface);
1758                 if (addr4 == NULL)
1759                         goto unlabel_getattr_nolabel;
1760                 secattr->attr.secid = addr4->secid;
1761                 break;
1762 #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
1763         case PF_INET6:
1764                 hdr6 = ipv6_hdr(skb);
1765                 addr6 = netlbl_unlhsh_search_addr6(&hdr6->saddr, iface);
1766                 if (addr6 == NULL)
1767                         goto unlabel_getattr_nolabel;
1768                 secattr->attr.secid = addr6->secid;
1769                 break;
1770 #endif /* IPv6 */
1771         default:
1772                 goto unlabel_getattr_nolabel;
1773         }
1774         rcu_read_unlock();
1775
1776         secattr->flags |= NETLBL_SECATTR_SECID;
1777         secattr->type = NETLBL_NLTYPE_UNLABELED;
1778         return 0;
1779
1780 unlabel_getattr_nolabel:
1781         rcu_read_unlock();
1782         if (netlabel_unlabel_acceptflg == 0)
1783                 return -ENOMSG;
1784         secattr->type = NETLBL_NLTYPE_UNLABELED;
1785         return 0;
1786 }
1787
1788 /**
1789  * netlbl_unlabel_defconf - Set the default config to allow unlabeled packets
1790  *
1791  * Description:
1792  * Set the default NetLabel configuration to allow incoming unlabeled packets
1793  * and to send unlabeled network traffic by default.
1794  *
1795  */
1796 int netlbl_unlabel_defconf(void)
1797 {
1798         int ret_val;
1799         struct netlbl_dom_map *entry;
1800         struct netlbl_audit audit_info;
1801
1802         /* Only the kernel is allowed to call this function and the only time
1803          * it is called is at bootup before the audit subsystem is reporting
1804          * messages so don't worry to much about these values. */
1805         security_task_getsecid(current, &audit_info.secid);
1806         audit_info.loginuid = 0;
1807
1808         entry = kzalloc(sizeof(*entry), GFP_KERNEL);
1809         if (entry == NULL)
1810                 return -ENOMEM;
1811         entry->type = NETLBL_NLTYPE_UNLABELED;
1812         ret_val = netlbl_domhsh_add_default(entry, &audit_info);
1813         if (ret_val != 0)
1814                 return ret_val;
1815
1816         netlbl_unlabel_acceptflg_set(1, &audit_info);
1817
1818         return 0;
1819 }