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  */
netlbl_unlhsh_free_iface(struct rcu_head * entry)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  */
netlbl_unlhsh_hash(int ifindex)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  */
netlbl_unlhsh_search_iface(int ifindex)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  */
netlbl_unlhsh_add_addr4(struct netlbl_unlhsh_iface * iface,const struct in_addr * addr,const struct in_addr * mask,u32 secid)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  */
netlbl_unlhsh_add_addr6(struct netlbl_unlhsh_iface * iface,const struct in6_addr * addr,const struct in6_addr * mask,u32 secid)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  */
netlbl_unlhsh_add_iface(int ifindex)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  */
netlbl_unlhsh_add(struct net * net,const char * dev_name,const void * addr,const void * mask,u32 addr_len,u32 secid,struct netlbl_audit * audit_info)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  */
netlbl_unlhsh_remove_addr4(struct net * net,struct netlbl_unlhsh_iface * iface,const struct in_addr * addr,const struct in_addr * mask,struct netlbl_audit * audit_info)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 		dev_put(dev);
496 		if (entry != NULL &&
497 		    security_secid_to_secctx(entry->secid,
498 					     &secctx, &secctx_len) == 0) {
499 			audit_log_format(audit_buf, " sec_obj=%s", secctx);
500 			security_release_secctx(secctx, secctx_len);
501 		}
502 		audit_log_format(audit_buf, " res=%u", entry != NULL ? 1 : 0);
503 		audit_log_end(audit_buf);
504 	}
505 
506 	if (entry == NULL)
507 		return -ENOENT;
508 
509 	kfree_rcu(entry, rcu);
510 	return 0;
511 }
512 
513 #if IS_ENABLED(CONFIG_IPV6)
514 /**
515  * netlbl_unlhsh_remove_addr6 - Remove an IPv6 address entry
516  * @net: network namespace
517  * @iface: interface entry
518  * @addr: IP address
519  * @mask: IP address mask
520  * @audit_info: NetLabel audit information
521  *
522  * Description:
523  * Remove an IP address entry from the unlabeled connection hash table.
524  * Returns zero on success, negative values on failure.
525  *
526  */
netlbl_unlhsh_remove_addr6(struct net * net,struct netlbl_unlhsh_iface * iface,const struct in6_addr * addr,const struct in6_addr * mask,struct netlbl_audit * audit_info)527 static int netlbl_unlhsh_remove_addr6(struct net *net,
528 				      struct netlbl_unlhsh_iface *iface,
529 				      const struct in6_addr *addr,
530 				      const struct in6_addr *mask,
531 				      struct netlbl_audit *audit_info)
532 {
533 	struct netlbl_af6list *list_entry;
534 	struct netlbl_unlhsh_addr6 *entry;
535 	struct audit_buffer *audit_buf;
536 	struct net_device *dev;
537 	char *secctx;
538 	u32 secctx_len;
539 
540 	spin_lock(&netlbl_unlhsh_lock);
541 	list_entry = netlbl_af6list_remove(addr, mask, &iface->addr6_list);
542 	spin_unlock(&netlbl_unlhsh_lock);
543 	if (list_entry != NULL)
544 		entry = netlbl_unlhsh_addr6_entry(list_entry);
545 	else
546 		entry = NULL;
547 
548 	audit_buf = netlbl_audit_start_common(AUDIT_MAC_UNLBL_STCDEL,
549 					      audit_info);
550 	if (audit_buf != NULL) {
551 		dev = dev_get_by_index(net, iface->ifindex);
552 		netlbl_af6list_audit_addr(audit_buf, 1,
553 					  (dev != NULL ? dev->name : NULL),
554 					  addr, mask);
555 		dev_put(dev);
556 		if (entry != NULL &&
557 		    security_secid_to_secctx(entry->secid,
558 					     &secctx, &secctx_len) == 0) {
559 			audit_log_format(audit_buf, " sec_obj=%s", secctx);
560 			security_release_secctx(secctx, secctx_len);
561 		}
562 		audit_log_format(audit_buf, " res=%u", entry != NULL ? 1 : 0);
563 		audit_log_end(audit_buf);
564 	}
565 
566 	if (entry == NULL)
567 		return -ENOENT;
568 
569 	kfree_rcu(entry, rcu);
570 	return 0;
571 }
572 #endif /* IPv6 */
573 
574 /**
575  * netlbl_unlhsh_condremove_iface - Remove an interface entry
576  * @iface: the interface entry
577  *
578  * Description:
579  * Remove an interface entry from the unlabeled connection hash table if it is
580  * empty.  An interface entry is considered to be empty if there are no
581  * address entries assigned to it.
582  *
583  */
netlbl_unlhsh_condremove_iface(struct netlbl_unlhsh_iface * iface)584 static void netlbl_unlhsh_condremove_iface(struct netlbl_unlhsh_iface *iface)
585 {
586 	struct netlbl_af4list *iter4;
587 #if IS_ENABLED(CONFIG_IPV6)
588 	struct netlbl_af6list *iter6;
589 #endif /* IPv6 */
590 
591 	spin_lock(&netlbl_unlhsh_lock);
592 	netlbl_af4list_foreach_rcu(iter4, &iface->addr4_list)
593 		goto unlhsh_condremove_failure;
594 #if IS_ENABLED(CONFIG_IPV6)
595 	netlbl_af6list_foreach_rcu(iter6, &iface->addr6_list)
596 		goto unlhsh_condremove_failure;
597 #endif /* IPv6 */
598 	iface->valid = 0;
599 	if (iface->ifindex > 0)
600 		list_del_rcu(&iface->list);
601 	else
602 		RCU_INIT_POINTER(netlbl_unlhsh_def, NULL);
603 	spin_unlock(&netlbl_unlhsh_lock);
604 
605 	call_rcu(&iface->rcu, netlbl_unlhsh_free_iface);
606 	return;
607 
608 unlhsh_condremove_failure:
609 	spin_unlock(&netlbl_unlhsh_lock);
610 }
611 
612 /**
613  * netlbl_unlhsh_remove - Remove an entry from the unlabeled hash table
614  * @net: network namespace
615  * @dev_name: interface name
616  * @addr: IP address in network byte order
617  * @mask: address mask in network byte order
618  * @addr_len: length of address/mask (4 for IPv4, 16 for IPv6)
619  * @audit_info: NetLabel audit information
620  *
621  * Description:
622  * Removes and existing entry from the unlabeled connection hash table.
623  * Returns zero on success, negative values on failure.
624  *
625  */
netlbl_unlhsh_remove(struct net * net,const char * dev_name,const void * addr,const void * mask,u32 addr_len,struct netlbl_audit * audit_info)626 int netlbl_unlhsh_remove(struct net *net,
627 			 const char *dev_name,
628 			 const void *addr,
629 			 const void *mask,
630 			 u32 addr_len,
631 			 struct netlbl_audit *audit_info)
632 {
633 	int ret_val;
634 	struct net_device *dev;
635 	struct netlbl_unlhsh_iface *iface;
636 
637 	if (addr_len != sizeof(struct in_addr) &&
638 	    addr_len != sizeof(struct in6_addr))
639 		return -EINVAL;
640 
641 	rcu_read_lock();
642 	if (dev_name != NULL) {
643 		dev = dev_get_by_name_rcu(net, dev_name);
644 		if (dev == NULL) {
645 			ret_val = -ENODEV;
646 			goto unlhsh_remove_return;
647 		}
648 		iface = netlbl_unlhsh_search_iface(dev->ifindex);
649 	} else
650 		iface = rcu_dereference(netlbl_unlhsh_def);
651 	if (iface == NULL) {
652 		ret_val = -ENOENT;
653 		goto unlhsh_remove_return;
654 	}
655 	switch (addr_len) {
656 	case sizeof(struct in_addr):
657 		ret_val = netlbl_unlhsh_remove_addr4(net,
658 						     iface, addr, mask,
659 						     audit_info);
660 		break;
661 #if IS_ENABLED(CONFIG_IPV6)
662 	case sizeof(struct in6_addr):
663 		ret_val = netlbl_unlhsh_remove_addr6(net,
664 						     iface, addr, mask,
665 						     audit_info);
666 		break;
667 #endif /* IPv6 */
668 	default:
669 		ret_val = -EINVAL;
670 	}
671 	if (ret_val == 0) {
672 		netlbl_unlhsh_condremove_iface(iface);
673 		atomic_dec(&netlabel_mgmt_protocount);
674 	}
675 
676 unlhsh_remove_return:
677 	rcu_read_unlock();
678 	return ret_val;
679 }
680 
681 /*
682  * General Helper Functions
683  */
684 
685 /**
686  * netlbl_unlhsh_netdev_handler - Network device notification handler
687  * @this: notifier block
688  * @event: the event
689  * @ptr: the netdevice notifier info (cast to void)
690  *
691  * Description:
692  * Handle network device events, although at present all we care about is a
693  * network device going away.  In the case of a device going away we clear any
694  * related entries from the unlabeled connection hash table.
695  *
696  */
netlbl_unlhsh_netdev_handler(struct notifier_block * this,unsigned long event,void * ptr)697 static int netlbl_unlhsh_netdev_handler(struct notifier_block *this,
698 					unsigned long event, void *ptr)
699 {
700 	struct net_device *dev = netdev_notifier_info_to_dev(ptr);
701 	struct netlbl_unlhsh_iface *iface = NULL;
702 
703 	if (!net_eq(dev_net(dev), &init_net))
704 		return NOTIFY_DONE;
705 
706 	/* XXX - should this be a check for NETDEV_DOWN or _UNREGISTER? */
707 	if (event == NETDEV_DOWN) {
708 		spin_lock(&netlbl_unlhsh_lock);
709 		iface = netlbl_unlhsh_search_iface(dev->ifindex);
710 		if (iface != NULL && iface->valid) {
711 			iface->valid = 0;
712 			list_del_rcu(&iface->list);
713 		} else
714 			iface = NULL;
715 		spin_unlock(&netlbl_unlhsh_lock);
716 	}
717 
718 	if (iface != NULL)
719 		call_rcu(&iface->rcu, netlbl_unlhsh_free_iface);
720 
721 	return NOTIFY_DONE;
722 }
723 
724 /**
725  * netlbl_unlabel_acceptflg_set - Set the unlabeled accept flag
726  * @value: desired value
727  * @audit_info: NetLabel audit information
728  *
729  * Description:
730  * Set the value of the unlabeled accept flag to @value.
731  *
732  */
netlbl_unlabel_acceptflg_set(u8 value,struct netlbl_audit * audit_info)733 static void netlbl_unlabel_acceptflg_set(u8 value,
734 					 struct netlbl_audit *audit_info)
735 {
736 	struct audit_buffer *audit_buf;
737 	u8 old_val;
738 
739 	old_val = netlabel_unlabel_acceptflg;
740 	netlabel_unlabel_acceptflg = value;
741 	audit_buf = netlbl_audit_start_common(AUDIT_MAC_UNLBL_ALLOW,
742 					      audit_info);
743 	if (audit_buf != NULL) {
744 		audit_log_format(audit_buf,
745 				 " unlbl_accept=%u old=%u", value, old_val);
746 		audit_log_end(audit_buf);
747 	}
748 }
749 
750 /**
751  * netlbl_unlabel_addrinfo_get - Get the IPv4/6 address information
752  * @info: the Generic NETLINK info block
753  * @addr: the IP address
754  * @mask: the IP address mask
755  * @len: the address length
756  *
757  * Description:
758  * Examine the Generic NETLINK message and extract the IP address information.
759  * Returns zero on success, negative values on failure.
760  *
761  */
netlbl_unlabel_addrinfo_get(struct genl_info * info,void ** addr,void ** mask,u32 * len)762 static int netlbl_unlabel_addrinfo_get(struct genl_info *info,
763 				       void **addr,
764 				       void **mask,
765 				       u32 *len)
766 {
767 	u32 addr_len;
768 
769 	if (info->attrs[NLBL_UNLABEL_A_IPV4ADDR] &&
770 	    info->attrs[NLBL_UNLABEL_A_IPV4MASK]) {
771 		addr_len = nla_len(info->attrs[NLBL_UNLABEL_A_IPV4ADDR]);
772 		if (addr_len != sizeof(struct in_addr) &&
773 		    addr_len != nla_len(info->attrs[NLBL_UNLABEL_A_IPV4MASK]))
774 			return -EINVAL;
775 		*len = addr_len;
776 		*addr = nla_data(info->attrs[NLBL_UNLABEL_A_IPV4ADDR]);
777 		*mask = nla_data(info->attrs[NLBL_UNLABEL_A_IPV4MASK]);
778 		return 0;
779 	} else if (info->attrs[NLBL_UNLABEL_A_IPV6ADDR]) {
780 		addr_len = nla_len(info->attrs[NLBL_UNLABEL_A_IPV6ADDR]);
781 		if (addr_len != sizeof(struct in6_addr) &&
782 		    addr_len != nla_len(info->attrs[NLBL_UNLABEL_A_IPV6MASK]))
783 			return -EINVAL;
784 		*len = addr_len;
785 		*addr = nla_data(info->attrs[NLBL_UNLABEL_A_IPV6ADDR]);
786 		*mask = nla_data(info->attrs[NLBL_UNLABEL_A_IPV6MASK]);
787 		return 0;
788 	}
789 
790 	return -EINVAL;
791 }
792 
793 /*
794  * NetLabel Command Handlers
795  */
796 
797 /**
798  * netlbl_unlabel_accept - Handle an ACCEPT message
799  * @skb: the NETLINK buffer
800  * @info: the Generic NETLINK info block
801  *
802  * Description:
803  * Process a user generated ACCEPT message and set the accept flag accordingly.
804  * Returns zero on success, negative values on failure.
805  *
806  */
netlbl_unlabel_accept(struct sk_buff * skb,struct genl_info * info)807 static int netlbl_unlabel_accept(struct sk_buff *skb, struct genl_info *info)
808 {
809 	u8 value;
810 	struct netlbl_audit audit_info;
811 
812 	if (info->attrs[NLBL_UNLABEL_A_ACPTFLG]) {
813 		value = nla_get_u8(info->attrs[NLBL_UNLABEL_A_ACPTFLG]);
814 		if (value == 1 || value == 0) {
815 			netlbl_netlink_auditinfo(&audit_info);
816 			netlbl_unlabel_acceptflg_set(value, &audit_info);
817 			return 0;
818 		}
819 	}
820 
821 	return -EINVAL;
822 }
823 
824 /**
825  * netlbl_unlabel_list - Handle a LIST message
826  * @skb: the NETLINK buffer
827  * @info: the Generic NETLINK info block
828  *
829  * Description:
830  * Process a user generated LIST message and respond with the current status.
831  * Returns zero on success, negative values on failure.
832  *
833  */
netlbl_unlabel_list(struct sk_buff * skb,struct genl_info * info)834 static int netlbl_unlabel_list(struct sk_buff *skb, struct genl_info *info)
835 {
836 	int ret_val = -EINVAL;
837 	struct sk_buff *ans_skb;
838 	void *data;
839 
840 	ans_skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
841 	if (ans_skb == NULL)
842 		goto list_failure;
843 	data = genlmsg_put_reply(ans_skb, info, &netlbl_unlabel_gnl_family,
844 				 0, NLBL_UNLABEL_C_LIST);
845 	if (data == NULL) {
846 		ret_val = -ENOMEM;
847 		goto list_failure;
848 	}
849 
850 	ret_val = nla_put_u8(ans_skb,
851 			     NLBL_UNLABEL_A_ACPTFLG,
852 			     netlabel_unlabel_acceptflg);
853 	if (ret_val != 0)
854 		goto list_failure;
855 
856 	genlmsg_end(ans_skb, data);
857 	return genlmsg_reply(ans_skb, info);
858 
859 list_failure:
860 	kfree_skb(ans_skb);
861 	return ret_val;
862 }
863 
864 /**
865  * netlbl_unlabel_staticadd - Handle a STATICADD message
866  * @skb: the NETLINK buffer
867  * @info: the Generic NETLINK info block
868  *
869  * Description:
870  * Process a user generated STATICADD message and add a new unlabeled
871  * connection entry to the hash table.  Returns zero on success, negative
872  * values on failure.
873  *
874  */
netlbl_unlabel_staticadd(struct sk_buff * skb,struct genl_info * info)875 static int netlbl_unlabel_staticadd(struct sk_buff *skb,
876 				    struct genl_info *info)
877 {
878 	int ret_val;
879 	char *dev_name;
880 	void *addr;
881 	void *mask;
882 	u32 addr_len;
883 	u32 secid;
884 	struct netlbl_audit audit_info;
885 
886 	/* Don't allow users to add both IPv4 and IPv6 addresses for a
887 	 * single entry.  However, allow users to create two entries, one each
888 	 * for IPv4 and IPv6, with the same LSM security context which should
889 	 * achieve the same result. */
890 	if (!info->attrs[NLBL_UNLABEL_A_SECCTX] ||
891 	    !info->attrs[NLBL_UNLABEL_A_IFACE] ||
892 	    !((!info->attrs[NLBL_UNLABEL_A_IPV4ADDR] ||
893 	       !info->attrs[NLBL_UNLABEL_A_IPV4MASK]) ^
894 	      (!info->attrs[NLBL_UNLABEL_A_IPV6ADDR] ||
895 	       !info->attrs[NLBL_UNLABEL_A_IPV6MASK])))
896 		return -EINVAL;
897 
898 	netlbl_netlink_auditinfo(&audit_info);
899 
900 	ret_val = netlbl_unlabel_addrinfo_get(info, &addr, &mask, &addr_len);
901 	if (ret_val != 0)
902 		return ret_val;
903 	dev_name = nla_data(info->attrs[NLBL_UNLABEL_A_IFACE]);
904 	ret_val = security_secctx_to_secid(
905 		                  nla_data(info->attrs[NLBL_UNLABEL_A_SECCTX]),
906 				  nla_len(info->attrs[NLBL_UNLABEL_A_SECCTX]),
907 				  &secid);
908 	if (ret_val != 0)
909 		return ret_val;
910 
911 	return netlbl_unlhsh_add(&init_net,
912 				 dev_name, addr, mask, addr_len, secid,
913 				 &audit_info);
914 }
915 
916 /**
917  * netlbl_unlabel_staticadddef - Handle a STATICADDDEF message
918  * @skb: the NETLINK buffer
919  * @info: the Generic NETLINK info block
920  *
921  * Description:
922  * Process a user generated STATICADDDEF message and add a new default
923  * unlabeled connection entry.  Returns zero on success, negative values on
924  * failure.
925  *
926  */
netlbl_unlabel_staticadddef(struct sk_buff * skb,struct genl_info * info)927 static int netlbl_unlabel_staticadddef(struct sk_buff *skb,
928 				       struct genl_info *info)
929 {
930 	int ret_val;
931 	void *addr;
932 	void *mask;
933 	u32 addr_len;
934 	u32 secid;
935 	struct netlbl_audit audit_info;
936 
937 	/* Don't allow users to add both IPv4 and IPv6 addresses for a
938 	 * single entry.  However, allow users to create two entries, one each
939 	 * for IPv4 and IPv6, with the same LSM security context which should
940 	 * achieve the same result. */
941 	if (!info->attrs[NLBL_UNLABEL_A_SECCTX] ||
942 	    !((!info->attrs[NLBL_UNLABEL_A_IPV4ADDR] ||
943 	       !info->attrs[NLBL_UNLABEL_A_IPV4MASK]) ^
944 	      (!info->attrs[NLBL_UNLABEL_A_IPV6ADDR] ||
945 	       !info->attrs[NLBL_UNLABEL_A_IPV6MASK])))
946 		return -EINVAL;
947 
948 	netlbl_netlink_auditinfo(&audit_info);
949 
950 	ret_val = netlbl_unlabel_addrinfo_get(info, &addr, &mask, &addr_len);
951 	if (ret_val != 0)
952 		return ret_val;
953 	ret_val = security_secctx_to_secid(
954 		                  nla_data(info->attrs[NLBL_UNLABEL_A_SECCTX]),
955 				  nla_len(info->attrs[NLBL_UNLABEL_A_SECCTX]),
956 				  &secid);
957 	if (ret_val != 0)
958 		return ret_val;
959 
960 	return netlbl_unlhsh_add(&init_net,
961 				 NULL, addr, mask, addr_len, secid,
962 				 &audit_info);
963 }
964 
965 /**
966  * netlbl_unlabel_staticremove - Handle a STATICREMOVE message
967  * @skb: the NETLINK buffer
968  * @info: the Generic NETLINK info block
969  *
970  * Description:
971  * Process a user generated STATICREMOVE message and remove the specified
972  * unlabeled connection entry.  Returns zero on success, negative values on
973  * failure.
974  *
975  */
netlbl_unlabel_staticremove(struct sk_buff * skb,struct genl_info * info)976 static int netlbl_unlabel_staticremove(struct sk_buff *skb,
977 				       struct genl_info *info)
978 {
979 	int ret_val;
980 	char *dev_name;
981 	void *addr;
982 	void *mask;
983 	u32 addr_len;
984 	struct netlbl_audit audit_info;
985 
986 	/* See the note in netlbl_unlabel_staticadd() about not allowing both
987 	 * IPv4 and IPv6 in the same entry. */
988 	if (!info->attrs[NLBL_UNLABEL_A_IFACE] ||
989 	    !((!info->attrs[NLBL_UNLABEL_A_IPV4ADDR] ||
990 	       !info->attrs[NLBL_UNLABEL_A_IPV4MASK]) ^
991 	      (!info->attrs[NLBL_UNLABEL_A_IPV6ADDR] ||
992 	       !info->attrs[NLBL_UNLABEL_A_IPV6MASK])))
993 		return -EINVAL;
994 
995 	netlbl_netlink_auditinfo(&audit_info);
996 
997 	ret_val = netlbl_unlabel_addrinfo_get(info, &addr, &mask, &addr_len);
998 	if (ret_val != 0)
999 		return ret_val;
1000 	dev_name = nla_data(info->attrs[NLBL_UNLABEL_A_IFACE]);
1001 
1002 	return netlbl_unlhsh_remove(&init_net,
1003 				    dev_name, addr, mask, addr_len,
1004 				    &audit_info);
1005 }
1006 
1007 /**
1008  * netlbl_unlabel_staticremovedef - Handle a STATICREMOVEDEF message
1009  * @skb: the NETLINK buffer
1010  * @info: the Generic NETLINK info block
1011  *
1012  * Description:
1013  * Process a user generated STATICREMOVEDEF message and remove the default
1014  * unlabeled connection entry.  Returns zero on success, negative values on
1015  * failure.
1016  *
1017  */
netlbl_unlabel_staticremovedef(struct sk_buff * skb,struct genl_info * info)1018 static int netlbl_unlabel_staticremovedef(struct sk_buff *skb,
1019 					  struct genl_info *info)
1020 {
1021 	int ret_val;
1022 	void *addr;
1023 	void *mask;
1024 	u32 addr_len;
1025 	struct netlbl_audit audit_info;
1026 
1027 	/* See the note in netlbl_unlabel_staticadd() about not allowing both
1028 	 * IPv4 and IPv6 in the same entry. */
1029 	if (!((!info->attrs[NLBL_UNLABEL_A_IPV4ADDR] ||
1030 	       !info->attrs[NLBL_UNLABEL_A_IPV4MASK]) ^
1031 	      (!info->attrs[NLBL_UNLABEL_A_IPV6ADDR] ||
1032 	       !info->attrs[NLBL_UNLABEL_A_IPV6MASK])))
1033 		return -EINVAL;
1034 
1035 	netlbl_netlink_auditinfo(&audit_info);
1036 
1037 	ret_val = netlbl_unlabel_addrinfo_get(info, &addr, &mask, &addr_len);
1038 	if (ret_val != 0)
1039 		return ret_val;
1040 
1041 	return netlbl_unlhsh_remove(&init_net,
1042 				    NULL, addr, mask, addr_len,
1043 				    &audit_info);
1044 }
1045 
1046 
1047 /**
1048  * netlbl_unlabel_staticlist_gen - Generate messages for STATICLIST[DEF]
1049  * @cmd: command/message
1050  * @iface: the interface entry
1051  * @addr4: the IPv4 address entry
1052  * @addr6: the IPv6 address entry
1053  * @arg: the netlbl_unlhsh_walk_arg structure
1054  *
1055  * Description:
1056  * This function is designed to be used to generate a response for a
1057  * STATICLIST or STATICLISTDEF message.  When called either @addr4 or @addr6
1058  * can be specified, not both, the other unspecified entry should be set to
1059  * NULL by the caller.  Returns the size of the message on success, negative
1060  * values on failure.
1061  *
1062  */
netlbl_unlabel_staticlist_gen(u32 cmd,const struct netlbl_unlhsh_iface * iface,const struct netlbl_unlhsh_addr4 * addr4,const struct netlbl_unlhsh_addr6 * addr6,void * arg)1063 static int netlbl_unlabel_staticlist_gen(u32 cmd,
1064 				       const struct netlbl_unlhsh_iface *iface,
1065 				       const struct netlbl_unlhsh_addr4 *addr4,
1066 				       const struct netlbl_unlhsh_addr6 *addr6,
1067 				       void *arg)
1068 {
1069 	int ret_val = -ENOMEM;
1070 	struct netlbl_unlhsh_walk_arg *cb_arg = arg;
1071 	struct net_device *dev;
1072 	void *data;
1073 	u32 secid;
1074 	char *secctx;
1075 	u32 secctx_len;
1076 
1077 	data = genlmsg_put(cb_arg->skb, NETLINK_CB(cb_arg->nl_cb->skb).portid,
1078 			   cb_arg->seq, &netlbl_unlabel_gnl_family,
1079 			   NLM_F_MULTI, cmd);
1080 	if (data == NULL)
1081 		goto list_cb_failure;
1082 
1083 	if (iface->ifindex > 0) {
1084 		dev = dev_get_by_index(&init_net, iface->ifindex);
1085 		if (!dev) {
1086 			ret_val = -ENODEV;
1087 			goto list_cb_failure;
1088 		}
1089 		ret_val = nla_put_string(cb_arg->skb,
1090 					 NLBL_UNLABEL_A_IFACE, dev->name);
1091 		dev_put(dev);
1092 		if (ret_val != 0)
1093 			goto list_cb_failure;
1094 	}
1095 
1096 	if (addr4) {
1097 		struct in_addr addr_struct;
1098 
1099 		addr_struct.s_addr = addr4->list.addr;
1100 		ret_val = nla_put_in_addr(cb_arg->skb,
1101 					  NLBL_UNLABEL_A_IPV4ADDR,
1102 					  addr_struct.s_addr);
1103 		if (ret_val != 0)
1104 			goto list_cb_failure;
1105 
1106 		addr_struct.s_addr = addr4->list.mask;
1107 		ret_val = nla_put_in_addr(cb_arg->skb,
1108 					  NLBL_UNLABEL_A_IPV4MASK,
1109 					  addr_struct.s_addr);
1110 		if (ret_val != 0)
1111 			goto list_cb_failure;
1112 
1113 		secid = addr4->secid;
1114 	} else {
1115 		ret_val = nla_put_in6_addr(cb_arg->skb,
1116 					   NLBL_UNLABEL_A_IPV6ADDR,
1117 					   &addr6->list.addr);
1118 		if (ret_val != 0)
1119 			goto list_cb_failure;
1120 
1121 		ret_val = nla_put_in6_addr(cb_arg->skb,
1122 					   NLBL_UNLABEL_A_IPV6MASK,
1123 					   &addr6->list.mask);
1124 		if (ret_val != 0)
1125 			goto list_cb_failure;
1126 
1127 		secid = addr6->secid;
1128 	}
1129 
1130 	ret_val = security_secid_to_secctx(secid, &secctx, &secctx_len);
1131 	if (ret_val != 0)
1132 		goto list_cb_failure;
1133 	ret_val = nla_put(cb_arg->skb,
1134 			  NLBL_UNLABEL_A_SECCTX,
1135 			  secctx_len,
1136 			  secctx);
1137 	security_release_secctx(secctx, secctx_len);
1138 	if (ret_val != 0)
1139 		goto list_cb_failure;
1140 
1141 	cb_arg->seq++;
1142 	genlmsg_end(cb_arg->skb, data);
1143 	return 0;
1144 
1145 list_cb_failure:
1146 	genlmsg_cancel(cb_arg->skb, data);
1147 	return ret_val;
1148 }
1149 
1150 /**
1151  * netlbl_unlabel_staticlist - Handle a STATICLIST message
1152  * @skb: the NETLINK buffer
1153  * @cb: the NETLINK callback
1154  *
1155  * Description:
1156  * Process a user generated STATICLIST message and dump the unlabeled
1157  * connection hash table in a form suitable for use in a kernel generated
1158  * STATICLIST message.  Returns the length of @skb.
1159  *
1160  */
netlbl_unlabel_staticlist(struct sk_buff * skb,struct netlink_callback * cb)1161 static int netlbl_unlabel_staticlist(struct sk_buff *skb,
1162 				     struct netlink_callback *cb)
1163 {
1164 	struct netlbl_unlhsh_walk_arg cb_arg;
1165 	u32 skip_bkt = cb->args[0];
1166 	u32 skip_chain = cb->args[1];
1167 	u32 skip_addr4 = cb->args[2];
1168 	u32 iter_bkt, iter_chain = 0, iter_addr4 = 0, iter_addr6 = 0;
1169 	struct netlbl_unlhsh_iface *iface;
1170 	struct list_head *iter_list;
1171 	struct netlbl_af4list *addr4;
1172 #if IS_ENABLED(CONFIG_IPV6)
1173 	u32 skip_addr6 = cb->args[3];
1174 	struct netlbl_af6list *addr6;
1175 #endif
1176 
1177 	cb_arg.nl_cb = cb;
1178 	cb_arg.skb = skb;
1179 	cb_arg.seq = cb->nlh->nlmsg_seq;
1180 
1181 	rcu_read_lock();
1182 	for (iter_bkt = skip_bkt;
1183 	     iter_bkt < rcu_dereference(netlbl_unlhsh)->size;
1184 	     iter_bkt++) {
1185 		iter_list = &rcu_dereference(netlbl_unlhsh)->tbl[iter_bkt];
1186 		list_for_each_entry_rcu(iface, iter_list, list) {
1187 			if (!iface->valid ||
1188 			    iter_chain++ < skip_chain)
1189 				continue;
1190 			netlbl_af4list_foreach_rcu(addr4,
1191 						   &iface->addr4_list) {
1192 				if (iter_addr4++ < skip_addr4)
1193 					continue;
1194 				if (netlbl_unlabel_staticlist_gen(
1195 					      NLBL_UNLABEL_C_STATICLIST,
1196 					      iface,
1197 					      netlbl_unlhsh_addr4_entry(addr4),
1198 					      NULL,
1199 					      &cb_arg) < 0) {
1200 					iter_addr4--;
1201 					iter_chain--;
1202 					goto unlabel_staticlist_return;
1203 				}
1204 			}
1205 			iter_addr4 = 0;
1206 			skip_addr4 = 0;
1207 #if IS_ENABLED(CONFIG_IPV6)
1208 			netlbl_af6list_foreach_rcu(addr6,
1209 						   &iface->addr6_list) {
1210 				if (iter_addr6++ < skip_addr6)
1211 					continue;
1212 				if (netlbl_unlabel_staticlist_gen(
1213 					      NLBL_UNLABEL_C_STATICLIST,
1214 					      iface,
1215 					      NULL,
1216 					      netlbl_unlhsh_addr6_entry(addr6),
1217 					      &cb_arg) < 0) {
1218 					iter_addr6--;
1219 					iter_chain--;
1220 					goto unlabel_staticlist_return;
1221 				}
1222 			}
1223 			iter_addr6 = 0;
1224 			skip_addr6 = 0;
1225 #endif /* IPv6 */
1226 		}
1227 		iter_chain = 0;
1228 		skip_chain = 0;
1229 	}
1230 
1231 unlabel_staticlist_return:
1232 	rcu_read_unlock();
1233 	cb->args[0] = iter_bkt;
1234 	cb->args[1] = iter_chain;
1235 	cb->args[2] = iter_addr4;
1236 	cb->args[3] = iter_addr6;
1237 	return skb->len;
1238 }
1239 
1240 /**
1241  * netlbl_unlabel_staticlistdef - Handle a STATICLISTDEF message
1242  * @skb: the NETLINK buffer
1243  * @cb: the NETLINK callback
1244  *
1245  * Description:
1246  * Process a user generated STATICLISTDEF message and dump the default
1247  * unlabeled connection entry in a form suitable for use in a kernel generated
1248  * STATICLISTDEF message.  Returns the length of @skb.
1249  *
1250  */
netlbl_unlabel_staticlistdef(struct sk_buff * skb,struct netlink_callback * cb)1251 static int netlbl_unlabel_staticlistdef(struct sk_buff *skb,
1252 					struct netlink_callback *cb)
1253 {
1254 	struct netlbl_unlhsh_walk_arg cb_arg;
1255 	struct netlbl_unlhsh_iface *iface;
1256 	u32 iter_addr4 = 0, iter_addr6 = 0;
1257 	struct netlbl_af4list *addr4;
1258 #if IS_ENABLED(CONFIG_IPV6)
1259 	struct netlbl_af6list *addr6;
1260 #endif
1261 
1262 	cb_arg.nl_cb = cb;
1263 	cb_arg.skb = skb;
1264 	cb_arg.seq = cb->nlh->nlmsg_seq;
1265 
1266 	rcu_read_lock();
1267 	iface = rcu_dereference(netlbl_unlhsh_def);
1268 	if (iface == NULL || !iface->valid)
1269 		goto unlabel_staticlistdef_return;
1270 
1271 	netlbl_af4list_foreach_rcu(addr4, &iface->addr4_list) {
1272 		if (iter_addr4++ < cb->args[0])
1273 			continue;
1274 		if (netlbl_unlabel_staticlist_gen(NLBL_UNLABEL_C_STATICLISTDEF,
1275 					      iface,
1276 					      netlbl_unlhsh_addr4_entry(addr4),
1277 					      NULL,
1278 					      &cb_arg) < 0) {
1279 			iter_addr4--;
1280 			goto unlabel_staticlistdef_return;
1281 		}
1282 	}
1283 #if IS_ENABLED(CONFIG_IPV6)
1284 	netlbl_af6list_foreach_rcu(addr6, &iface->addr6_list) {
1285 		if (iter_addr6++ < cb->args[1])
1286 			continue;
1287 		if (netlbl_unlabel_staticlist_gen(NLBL_UNLABEL_C_STATICLISTDEF,
1288 					      iface,
1289 					      NULL,
1290 					      netlbl_unlhsh_addr6_entry(addr6),
1291 					      &cb_arg) < 0) {
1292 			iter_addr6--;
1293 			goto unlabel_staticlistdef_return;
1294 		}
1295 	}
1296 #endif /* IPv6 */
1297 
1298 unlabel_staticlistdef_return:
1299 	rcu_read_unlock();
1300 	cb->args[0] = iter_addr4;
1301 	cb->args[1] = iter_addr6;
1302 	return skb->len;
1303 }
1304 
1305 /*
1306  * NetLabel Generic NETLINK Command Definitions
1307  */
1308 
1309 static const struct genl_small_ops netlbl_unlabel_genl_ops[] = {
1310 	{
1311 	.cmd = NLBL_UNLABEL_C_STATICADD,
1312 	.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
1313 	.flags = GENL_ADMIN_PERM,
1314 	.doit = netlbl_unlabel_staticadd,
1315 	.dumpit = NULL,
1316 	},
1317 	{
1318 	.cmd = NLBL_UNLABEL_C_STATICREMOVE,
1319 	.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
1320 	.flags = GENL_ADMIN_PERM,
1321 	.doit = netlbl_unlabel_staticremove,
1322 	.dumpit = NULL,
1323 	},
1324 	{
1325 	.cmd = NLBL_UNLABEL_C_STATICLIST,
1326 	.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
1327 	.flags = 0,
1328 	.doit = NULL,
1329 	.dumpit = netlbl_unlabel_staticlist,
1330 	},
1331 	{
1332 	.cmd = NLBL_UNLABEL_C_STATICADDDEF,
1333 	.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
1334 	.flags = GENL_ADMIN_PERM,
1335 	.doit = netlbl_unlabel_staticadddef,
1336 	.dumpit = NULL,
1337 	},
1338 	{
1339 	.cmd = NLBL_UNLABEL_C_STATICREMOVEDEF,
1340 	.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
1341 	.flags = GENL_ADMIN_PERM,
1342 	.doit = netlbl_unlabel_staticremovedef,
1343 	.dumpit = NULL,
1344 	},
1345 	{
1346 	.cmd = NLBL_UNLABEL_C_STATICLISTDEF,
1347 	.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
1348 	.flags = 0,
1349 	.doit = NULL,
1350 	.dumpit = netlbl_unlabel_staticlistdef,
1351 	},
1352 	{
1353 	.cmd = NLBL_UNLABEL_C_ACCEPT,
1354 	.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
1355 	.flags = GENL_ADMIN_PERM,
1356 	.doit = netlbl_unlabel_accept,
1357 	.dumpit = NULL,
1358 	},
1359 	{
1360 	.cmd = NLBL_UNLABEL_C_LIST,
1361 	.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
1362 	.flags = 0,
1363 	.doit = netlbl_unlabel_list,
1364 	.dumpit = NULL,
1365 	},
1366 };
1367 
1368 static struct genl_family netlbl_unlabel_gnl_family __ro_after_init = {
1369 	.hdrsize = 0,
1370 	.name = NETLBL_NLTYPE_UNLABELED_NAME,
1371 	.version = NETLBL_PROTO_VERSION,
1372 	.maxattr = NLBL_UNLABEL_A_MAX,
1373 	.policy = netlbl_unlabel_genl_policy,
1374 	.module = THIS_MODULE,
1375 	.small_ops = netlbl_unlabel_genl_ops,
1376 	.n_small_ops = ARRAY_SIZE(netlbl_unlabel_genl_ops),
1377 	.resv_start_op = NLBL_UNLABEL_C_STATICLISTDEF + 1,
1378 };
1379 
1380 /*
1381  * NetLabel Generic NETLINK Protocol Functions
1382  */
1383 
1384 /**
1385  * netlbl_unlabel_genl_init - Register the Unlabeled NetLabel component
1386  *
1387  * Description:
1388  * Register the unlabeled packet NetLabel component with the Generic NETLINK
1389  * mechanism.  Returns zero on success, negative values on failure.
1390  *
1391  */
netlbl_unlabel_genl_init(void)1392 int __init netlbl_unlabel_genl_init(void)
1393 {
1394 	return genl_register_family(&netlbl_unlabel_gnl_family);
1395 }
1396 
1397 /*
1398  * NetLabel KAPI Hooks
1399  */
1400 
1401 static struct notifier_block netlbl_unlhsh_netdev_notifier = {
1402 	.notifier_call = netlbl_unlhsh_netdev_handler,
1403 };
1404 
1405 /**
1406  * netlbl_unlabel_init - Initialize the unlabeled connection hash table
1407  * @size: the number of bits to use for the hash buckets
1408  *
1409  * Description:
1410  * Initializes the unlabeled connection hash table and registers a network
1411  * device notification handler.  This function should only be called by the
1412  * NetLabel subsystem itself during initialization.  Returns zero on success,
1413  * non-zero values on error.
1414  *
1415  */
netlbl_unlabel_init(u32 size)1416 int __init netlbl_unlabel_init(u32 size)
1417 {
1418 	u32 iter;
1419 	struct netlbl_unlhsh_tbl *hsh_tbl;
1420 
1421 	if (size == 0)
1422 		return -EINVAL;
1423 
1424 	hsh_tbl = kmalloc(sizeof(*hsh_tbl), GFP_KERNEL);
1425 	if (hsh_tbl == NULL)
1426 		return -ENOMEM;
1427 	hsh_tbl->size = 1 << size;
1428 	hsh_tbl->tbl = kcalloc(hsh_tbl->size,
1429 			       sizeof(struct list_head),
1430 			       GFP_KERNEL);
1431 	if (hsh_tbl->tbl == NULL) {
1432 		kfree(hsh_tbl);
1433 		return -ENOMEM;
1434 	}
1435 	for (iter = 0; iter < hsh_tbl->size; iter++)
1436 		INIT_LIST_HEAD(&hsh_tbl->tbl[iter]);
1437 
1438 	spin_lock(&netlbl_unlhsh_lock);
1439 	rcu_assign_pointer(netlbl_unlhsh, hsh_tbl);
1440 	spin_unlock(&netlbl_unlhsh_lock);
1441 
1442 	register_netdevice_notifier(&netlbl_unlhsh_netdev_notifier);
1443 
1444 	return 0;
1445 }
1446 
1447 /**
1448  * netlbl_unlabel_getattr - Get the security attributes for an unlabled packet
1449  * @skb: the packet
1450  * @family: protocol family
1451  * @secattr: the security attributes
1452  *
1453  * Description:
1454  * Determine the security attributes, if any, for an unlabled packet and return
1455  * them in @secattr.  Returns zero on success and negative values on failure.
1456  *
1457  */
netlbl_unlabel_getattr(const struct sk_buff * skb,u16 family,struct netlbl_lsm_secattr * secattr)1458 int netlbl_unlabel_getattr(const struct sk_buff *skb,
1459 			   u16 family,
1460 			   struct netlbl_lsm_secattr *secattr)
1461 {
1462 	struct netlbl_unlhsh_iface *iface;
1463 
1464 	rcu_read_lock();
1465 	iface = netlbl_unlhsh_search_iface(skb->skb_iif);
1466 	if (iface == NULL)
1467 		iface = rcu_dereference(netlbl_unlhsh_def);
1468 	if (iface == NULL || !iface->valid)
1469 		goto unlabel_getattr_nolabel;
1470 
1471 #if IS_ENABLED(CONFIG_IPV6)
1472 	/* When resolving a fallback label, check the sk_buff version as
1473 	 * it is possible (e.g. SCTP) to have family = PF_INET6 while
1474 	 * receiving ip_hdr(skb)->version = 4.
1475 	 */
1476 	if (family == PF_INET6 && ip_hdr(skb)->version == 4)
1477 		family = PF_INET;
1478 #endif /* IPv6 */
1479 
1480 	switch (family) {
1481 	case PF_INET: {
1482 		struct iphdr *hdr4;
1483 		struct netlbl_af4list *addr4;
1484 
1485 		hdr4 = ip_hdr(skb);
1486 		addr4 = netlbl_af4list_search(hdr4->saddr,
1487 					      &iface->addr4_list);
1488 		if (addr4 == NULL)
1489 			goto unlabel_getattr_nolabel;
1490 		secattr->attr.secid = netlbl_unlhsh_addr4_entry(addr4)->secid;
1491 		break;
1492 	}
1493 #if IS_ENABLED(CONFIG_IPV6)
1494 	case PF_INET6: {
1495 		struct ipv6hdr *hdr6;
1496 		struct netlbl_af6list *addr6;
1497 
1498 		hdr6 = ipv6_hdr(skb);
1499 		addr6 = netlbl_af6list_search(&hdr6->saddr,
1500 					      &iface->addr6_list);
1501 		if (addr6 == NULL)
1502 			goto unlabel_getattr_nolabel;
1503 		secattr->attr.secid = netlbl_unlhsh_addr6_entry(addr6)->secid;
1504 		break;
1505 	}
1506 #endif /* IPv6 */
1507 	default:
1508 		goto unlabel_getattr_nolabel;
1509 	}
1510 	rcu_read_unlock();
1511 
1512 	secattr->flags |= NETLBL_SECATTR_SECID;
1513 	secattr->type = NETLBL_NLTYPE_UNLABELED;
1514 	return 0;
1515 
1516 unlabel_getattr_nolabel:
1517 	rcu_read_unlock();
1518 	if (netlabel_unlabel_acceptflg == 0)
1519 		return -ENOMSG;
1520 	secattr->type = NETLBL_NLTYPE_UNLABELED;
1521 	return 0;
1522 }
1523 
1524 /**
1525  * netlbl_unlabel_defconf - Set the default config to allow unlabeled packets
1526  *
1527  * Description:
1528  * Set the default NetLabel configuration to allow incoming unlabeled packets
1529  * and to send unlabeled network traffic by default.
1530  *
1531  */
netlbl_unlabel_defconf(void)1532 int __init netlbl_unlabel_defconf(void)
1533 {
1534 	int ret_val;
1535 	struct netlbl_dom_map *entry;
1536 	struct netlbl_audit audit_info;
1537 
1538 	/* Only the kernel is allowed to call this function and the only time
1539 	 * it is called is at bootup before the audit subsystem is reporting
1540 	 * messages so don't worry to much about these values. */
1541 	security_current_getsecid_subj(&audit_info.secid);
1542 	audit_info.loginuid = GLOBAL_ROOT_UID;
1543 	audit_info.sessionid = 0;
1544 
1545 	entry = kzalloc(sizeof(*entry), GFP_KERNEL);
1546 	if (entry == NULL)
1547 		return -ENOMEM;
1548 	entry->family = AF_UNSPEC;
1549 	entry->def.type = NETLBL_NLTYPE_UNLABELED;
1550 	ret_val = netlbl_domhsh_add_default(entry, &audit_info);
1551 	if (ret_val != 0)
1552 		return ret_val;
1553 
1554 	netlbl_unlabel_acceptflg_set(1, &audit_info);
1555 
1556 	return 0;
1557 }
1558