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