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