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