• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /asuswrt-rt-n18u-9.0.0.4.380.2695/release/src-rt-6.x.4708/linux/linux-2.6/net/netlabel/
1/*
2 * NetLabel Kernel API
3 *
4 * This file defines the kernel API for the NetLabel system.  The NetLabel
5 * system manages static and dynamic label mappings for network protocols such
6 * as CIPSO and RIPSO.
7 *
8 * Author: Paul Moore <paul.moore@hp.com>
9 *
10 */
11
12/*
13 * (c) Copyright Hewlett-Packard Development Company, L.P., 2006, 2008
14 *
15 * This program is free software;  you can redistribute it and/or modify
16 * it under the terms of the GNU General Public License as published by
17 * the Free Software Foundation; either version 2 of the License, or
18 * (at your option) any later version.
19 *
20 * This program is distributed in the hope that it will be useful,
21 * but WITHOUT ANY WARRANTY;  without even the implied warranty of
22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
23 * the GNU General Public License for more details.
24 *
25 * You should have received a copy of the GNU General Public License
26 * along with this program;  if not, write to the Free Software
27 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
28 *
29 */
30
31#include <linux/init.h>
32#include <linux/types.h>
33#include <linux/slab.h>
34#include <linux/audit.h>
35#include <linux/in.h>
36#include <linux/in6.h>
37#include <net/ip.h>
38#include <net/ipv6.h>
39#include <net/netlabel.h>
40#include <net/cipso_ipv4.h>
41#include <asm/bug.h>
42#include <asm/atomic.h>
43
44#include "netlabel_domainhash.h"
45#include "netlabel_unlabeled.h"
46#include "netlabel_cipso_v4.h"
47#include "netlabel_user.h"
48#include "netlabel_mgmt.h"
49#include "netlabel_addrlist.h"
50
51/*
52 * Configuration Functions
53 */
54
55/**
56 * netlbl_cfg_map_del - Remove a NetLabel/LSM domain mapping
57 * @domain: the domain mapping to remove
58 * @family: address family
59 * @addr: IP address
60 * @mask: IP address mask
61 * @audit_info: NetLabel audit information
62 *
63 * Description:
64 * Removes a NetLabel/LSM domain mapping.  A @domain value of NULL causes the
65 * default domain mapping to be removed.  Returns zero on success, negative
66 * values on failure.
67 *
68 */
69int netlbl_cfg_map_del(const char *domain,
70		       u16 family,
71		       const void *addr,
72		       const void *mask,
73		       struct netlbl_audit *audit_info)
74{
75	if (addr == NULL && mask == NULL) {
76		return netlbl_domhsh_remove(domain, audit_info);
77	} else if (addr != NULL && mask != NULL) {
78		switch (family) {
79		case AF_INET:
80			return netlbl_domhsh_remove_af4(domain, addr, mask,
81							audit_info);
82		default:
83			return -EPFNOSUPPORT;
84		}
85	} else
86		return -EINVAL;
87}
88
89/**
90 * netlbl_cfg_unlbl_map_add - Add a new unlabeled mapping
91 * @domain: the domain mapping to add
92 * @family: address family
93 * @addr: IP address
94 * @mask: IP address mask
95 * @audit_info: NetLabel audit information
96 *
97 * Description:
98 * Adds a new unlabeled NetLabel/LSM domain mapping.  A @domain value of NULL
99 * causes a new default domain mapping to be added.  Returns zero on success,
100 * negative values on failure.
101 *
102 */
103int netlbl_cfg_unlbl_map_add(const char *domain,
104			     u16 family,
105			     const void *addr,
106			     const void *mask,
107			     struct netlbl_audit *audit_info)
108{
109	int ret_val = -ENOMEM;
110	struct netlbl_dom_map *entry;
111	struct netlbl_domaddr_map *addrmap = NULL;
112	struct netlbl_domaddr4_map *map4 = NULL;
113	struct netlbl_domaddr6_map *map6 = NULL;
114	const struct in_addr *addr4, *mask4;
115	const struct in6_addr *addr6, *mask6;
116
117	entry = kzalloc(sizeof(*entry), GFP_ATOMIC);
118	if (entry == NULL)
119		return -ENOMEM;
120	if (domain != NULL) {
121		entry->domain = kstrdup(domain, GFP_ATOMIC);
122		if (entry->domain == NULL)
123			goto cfg_unlbl_map_add_failure;
124	}
125
126	if (addr == NULL && mask == NULL)
127		entry->type = NETLBL_NLTYPE_UNLABELED;
128	else if (addr != NULL && mask != NULL) {
129		addrmap = kzalloc(sizeof(*addrmap), GFP_ATOMIC);
130		if (addrmap == NULL)
131			goto cfg_unlbl_map_add_failure;
132		INIT_LIST_HEAD(&addrmap->list4);
133		INIT_LIST_HEAD(&addrmap->list6);
134
135		switch (family) {
136		case AF_INET:
137			addr4 = addr;
138			mask4 = mask;
139			map4 = kzalloc(sizeof(*map4), GFP_ATOMIC);
140			if (map4 == NULL)
141				goto cfg_unlbl_map_add_failure;
142			map4->type = NETLBL_NLTYPE_UNLABELED;
143			map4->list.addr = addr4->s_addr & mask4->s_addr;
144			map4->list.mask = mask4->s_addr;
145			map4->list.valid = 1;
146			ret_val = netlbl_af4list_add(&map4->list,
147						     &addrmap->list4);
148			if (ret_val != 0)
149				goto cfg_unlbl_map_add_failure;
150			break;
151		case AF_INET6:
152			addr6 = addr;
153			mask6 = mask;
154			map6 = kzalloc(sizeof(*map6), GFP_ATOMIC);
155			if (map6 == NULL)
156				goto cfg_unlbl_map_add_failure;
157			map6->type = NETLBL_NLTYPE_UNLABELED;
158			ipv6_addr_copy(&map6->list.addr, addr6);
159			map6->list.addr.s6_addr32[0] &= mask6->s6_addr32[0];
160			map6->list.addr.s6_addr32[1] &= mask6->s6_addr32[1];
161			map6->list.addr.s6_addr32[2] &= mask6->s6_addr32[2];
162			map6->list.addr.s6_addr32[3] &= mask6->s6_addr32[3];
163			ipv6_addr_copy(&map6->list.mask, mask6);
164			map6->list.valid = 1;
165			ret_val = netlbl_af4list_add(&map4->list,
166						     &addrmap->list4);
167			if (ret_val != 0)
168				goto cfg_unlbl_map_add_failure;
169			break;
170		default:
171			goto cfg_unlbl_map_add_failure;
172			break;
173		}
174
175		entry->type_def.addrsel = addrmap;
176		entry->type = NETLBL_NLTYPE_ADDRSELECT;
177	} else {
178		ret_val = -EINVAL;
179		goto cfg_unlbl_map_add_failure;
180	}
181
182	ret_val = netlbl_domhsh_add(entry, audit_info);
183	if (ret_val != 0)
184		goto cfg_unlbl_map_add_failure;
185
186	return 0;
187
188cfg_unlbl_map_add_failure:
189	kfree(entry->domain);
190	kfree(entry);
191	kfree(addrmap);
192	kfree(map4);
193	kfree(map6);
194	return ret_val;
195}
196
197
198/**
199 * netlbl_cfg_unlbl_static_add - Adds a new static label
200 * @net: network namespace
201 * @dev_name: interface name
202 * @addr: IP address in network byte order (struct in[6]_addr)
203 * @mask: address mask in network byte order (struct in[6]_addr)
204 * @family: address family
205 * @secid: LSM secid value for the entry
206 * @audit_info: NetLabel audit information
207 *
208 * Description:
209 * Adds a new NetLabel static label to be used when protocol provided labels
210 * are not present on incoming traffic.  If @dev_name is NULL then the default
211 * interface will be used.  Returns zero on success, negative values on failure.
212 *
213 */
214int netlbl_cfg_unlbl_static_add(struct net *net,
215				const char *dev_name,
216				const void *addr,
217				const void *mask,
218				u16 family,
219				u32 secid,
220				struct netlbl_audit *audit_info)
221{
222	u32 addr_len;
223
224	switch (family) {
225	case AF_INET:
226		addr_len = sizeof(struct in_addr);
227		break;
228	case AF_INET6:
229		addr_len = sizeof(struct in6_addr);
230		break;
231	default:
232		return -EPFNOSUPPORT;
233	}
234
235	return netlbl_unlhsh_add(net,
236				 dev_name, addr, mask, addr_len,
237				 secid, audit_info);
238}
239
240/**
241 * netlbl_cfg_unlbl_static_del - Removes an existing static label
242 * @net: network namespace
243 * @dev_name: interface name
244 * @addr: IP address in network byte order (struct in[6]_addr)
245 * @mask: address mask in network byte order (struct in[6]_addr)
246 * @family: address family
247 * @secid: LSM secid value for the entry
248 * @audit_info: NetLabel audit information
249 *
250 * Description:
251 * Removes an existing NetLabel static label used when protocol provided labels
252 * are not present on incoming traffic.  If @dev_name is NULL then the default
253 * interface will be used.  Returns zero on success, negative values on failure.
254 *
255 */
256int netlbl_cfg_unlbl_static_del(struct net *net,
257				const char *dev_name,
258				const void *addr,
259				const void *mask,
260				u16 family,
261				struct netlbl_audit *audit_info)
262{
263	u32 addr_len;
264
265	switch (family) {
266	case AF_INET:
267		addr_len = sizeof(struct in_addr);
268		break;
269	case AF_INET6:
270		addr_len = sizeof(struct in6_addr);
271		break;
272	default:
273		return -EPFNOSUPPORT;
274	}
275
276	return netlbl_unlhsh_remove(net,
277				    dev_name, addr, mask, addr_len,
278				    audit_info);
279}
280
281/**
282 * netlbl_cfg_cipsov4_add - Add a new CIPSOv4 DOI definition
283 * @doi_def: CIPSO DOI definition
284 * @audit_info: NetLabel audit information
285 *
286 * Description:
287 * Add a new CIPSO DOI definition as defined by @doi_def.  Returns zero on
288 * success and negative values on failure.
289 *
290 */
291int netlbl_cfg_cipsov4_add(struct cipso_v4_doi *doi_def,
292			   struct netlbl_audit *audit_info)
293{
294	return cipso_v4_doi_add(doi_def, audit_info);
295}
296
297/**
298 * netlbl_cfg_cipsov4_del - Remove an existing CIPSOv4 DOI definition
299 * @doi: CIPSO DOI
300 * @audit_info: NetLabel audit information
301 *
302 * Description:
303 * Remove an existing CIPSO DOI definition matching @doi.  Returns zero on
304 * success and negative values on failure.
305 *
306 */
307void netlbl_cfg_cipsov4_del(u32 doi, struct netlbl_audit *audit_info)
308{
309	cipso_v4_doi_remove(doi, audit_info);
310}
311
312/**
313 * netlbl_cfg_cipsov4_map_add - Add a new CIPSOv4 DOI mapping
314 * @doi: the CIPSO DOI
315 * @domain: the domain mapping to add
316 * @addr: IP address
317 * @mask: IP address mask
318 * @audit_info: NetLabel audit information
319 *
320 * Description:
321 * Add a new NetLabel/LSM domain mapping for the given CIPSO DOI to the NetLabel
322 * subsystem.  A @domain value of NULL adds a new default domain mapping.
323 * Returns zero on success, negative values on failure.
324 *
325 */
326int netlbl_cfg_cipsov4_map_add(u32 doi,
327			       const char *domain,
328			       const struct in_addr *addr,
329			       const struct in_addr *mask,
330			       struct netlbl_audit *audit_info)
331{
332	int ret_val = -ENOMEM;
333	struct cipso_v4_doi *doi_def;
334	struct netlbl_dom_map *entry;
335	struct netlbl_domaddr_map *addrmap = NULL;
336	struct netlbl_domaddr4_map *addrinfo = NULL;
337
338	doi_def = cipso_v4_doi_getdef(doi);
339	if (doi_def == NULL)
340		return -ENOENT;
341
342	entry = kzalloc(sizeof(*entry), GFP_ATOMIC);
343	if (entry == NULL)
344		return -ENOMEM;
345	if (domain != NULL) {
346		entry->domain = kstrdup(domain, GFP_ATOMIC);
347		if (entry->domain == NULL)
348			goto cfg_cipsov4_map_add_failure;
349	}
350
351	if (addr == NULL && mask == NULL) {
352		entry->type_def.cipsov4 = doi_def;
353		entry->type = NETLBL_NLTYPE_CIPSOV4;
354	} else if (addr != NULL && mask != NULL) {
355		addrmap = kzalloc(sizeof(*addrmap), GFP_ATOMIC);
356		if (addrmap == NULL)
357			goto cfg_cipsov4_map_add_failure;
358		INIT_LIST_HEAD(&addrmap->list4);
359		INIT_LIST_HEAD(&addrmap->list6);
360
361		addrinfo = kzalloc(sizeof(*addrinfo), GFP_ATOMIC);
362		if (addrinfo == NULL)
363			goto cfg_cipsov4_map_add_failure;
364		addrinfo->type_def.cipsov4 = doi_def;
365		addrinfo->type = NETLBL_NLTYPE_CIPSOV4;
366		addrinfo->list.addr = addr->s_addr & mask->s_addr;
367		addrinfo->list.mask = mask->s_addr;
368		addrinfo->list.valid = 1;
369		ret_val = netlbl_af4list_add(&addrinfo->list, &addrmap->list4);
370		if (ret_val != 0)
371			goto cfg_cipsov4_map_add_failure;
372
373		entry->type_def.addrsel = addrmap;
374		entry->type = NETLBL_NLTYPE_ADDRSELECT;
375	} else {
376		ret_val = -EINVAL;
377		goto cfg_cipsov4_map_add_failure;
378	}
379
380	ret_val = netlbl_domhsh_add(entry, audit_info);
381	if (ret_val != 0)
382		goto cfg_cipsov4_map_add_failure;
383
384	return 0;
385
386cfg_cipsov4_map_add_failure:
387	cipso_v4_doi_putdef(doi_def);
388	kfree(entry->domain);
389	kfree(entry);
390	kfree(addrmap);
391	kfree(addrinfo);
392	return ret_val;
393}
394
395/*
396 * Security Attribute Functions
397 */
398
399/**
400 * netlbl_secattr_catmap_walk - Walk a LSM secattr catmap looking for a bit
401 * @catmap: the category bitmap
402 * @offset: the offset to start searching at, in bits
403 *
404 * Description:
405 * This function walks a LSM secattr category bitmap starting at @offset and
406 * returns the spot of the first set bit or -ENOENT if no bits are set.
407 *
408 */
409int netlbl_secattr_catmap_walk(struct netlbl_lsm_secattr_catmap *catmap,
410			       u32 offset)
411{
412	struct netlbl_lsm_secattr_catmap *iter = catmap;
413	u32 node_idx;
414	u32 node_bit;
415	NETLBL_CATMAP_MAPTYPE bitmap;
416
417	if (offset > iter->startbit) {
418		while (offset >= (iter->startbit + NETLBL_CATMAP_SIZE)) {
419			iter = iter->next;
420			if (iter == NULL)
421				return -ENOENT;
422		}
423		node_idx = (offset - iter->startbit) / NETLBL_CATMAP_MAPSIZE;
424		node_bit = offset - iter->startbit -
425			   (NETLBL_CATMAP_MAPSIZE * node_idx);
426	} else {
427		node_idx = 0;
428		node_bit = 0;
429	}
430	bitmap = iter->bitmap[node_idx] >> node_bit;
431
432	for (;;) {
433		if (bitmap != 0) {
434			while ((bitmap & NETLBL_CATMAP_BIT) == 0) {
435				bitmap >>= 1;
436				node_bit++;
437			}
438			return iter->startbit +
439				(NETLBL_CATMAP_MAPSIZE * node_idx) + node_bit;
440		}
441		if (++node_idx >= NETLBL_CATMAP_MAPCNT) {
442			if (iter->next != NULL) {
443				iter = iter->next;
444				node_idx = 0;
445			} else
446				return -ENOENT;
447		}
448		bitmap = iter->bitmap[node_idx];
449		node_bit = 0;
450	}
451
452	return -ENOENT;
453}
454
455/**
456 * netlbl_secattr_catmap_walk_rng - Find the end of a string of set bits
457 * @catmap: the category bitmap
458 * @offset: the offset to start searching at, in bits
459 *
460 * Description:
461 * This function walks a LSM secattr category bitmap starting at @offset and
462 * returns the spot of the first cleared bit or -ENOENT if the offset is past
463 * the end of the bitmap.
464 *
465 */
466int netlbl_secattr_catmap_walk_rng(struct netlbl_lsm_secattr_catmap *catmap,
467				   u32 offset)
468{
469	struct netlbl_lsm_secattr_catmap *iter = catmap;
470	u32 node_idx;
471	u32 node_bit;
472	NETLBL_CATMAP_MAPTYPE bitmask;
473	NETLBL_CATMAP_MAPTYPE bitmap;
474
475	if (offset > iter->startbit) {
476		while (offset >= (iter->startbit + NETLBL_CATMAP_SIZE)) {
477			iter = iter->next;
478			if (iter == NULL)
479				return -ENOENT;
480		}
481		node_idx = (offset - iter->startbit) / NETLBL_CATMAP_MAPSIZE;
482		node_bit = offset - iter->startbit -
483			   (NETLBL_CATMAP_MAPSIZE * node_idx);
484	} else {
485		node_idx = 0;
486		node_bit = 0;
487	}
488	bitmask = NETLBL_CATMAP_BIT << node_bit;
489
490	for (;;) {
491		bitmap = iter->bitmap[node_idx];
492		while (bitmask != 0 && (bitmap & bitmask) != 0) {
493			bitmask <<= 1;
494			node_bit++;
495		}
496
497		if (bitmask != 0)
498			return iter->startbit +
499				(NETLBL_CATMAP_MAPSIZE * node_idx) +
500				node_bit - 1;
501		else if (++node_idx >= NETLBL_CATMAP_MAPCNT) {
502			if (iter->next == NULL)
503				return iter->startbit +	NETLBL_CATMAP_SIZE - 1;
504			iter = iter->next;
505			node_idx = 0;
506		}
507		bitmask = NETLBL_CATMAP_BIT;
508		node_bit = 0;
509	}
510
511	return -ENOENT;
512}
513
514/**
515 * netlbl_secattr_catmap_setbit - Set a bit in a LSM secattr catmap
516 * @catmap: the category bitmap
517 * @bit: the bit to set
518 * @flags: memory allocation flags
519 *
520 * Description:
521 * Set the bit specified by @bit in @catmap.  Returns zero on success,
522 * negative values on failure.
523 *
524 */
525int netlbl_secattr_catmap_setbit(struct netlbl_lsm_secattr_catmap *catmap,
526				 u32 bit,
527				 gfp_t flags)
528{
529	struct netlbl_lsm_secattr_catmap *iter = catmap;
530	u32 node_bit;
531	u32 node_idx;
532
533	while (iter->next != NULL &&
534	       bit >= (iter->startbit + NETLBL_CATMAP_SIZE))
535		iter = iter->next;
536	if (bit >= (iter->startbit + NETLBL_CATMAP_SIZE)) {
537		iter->next = netlbl_secattr_catmap_alloc(flags);
538		if (iter->next == NULL)
539			return -ENOMEM;
540		iter = iter->next;
541		iter->startbit = bit & ~(NETLBL_CATMAP_SIZE - 1);
542	}
543
544	/* gcc always rounds to zero when doing integer division */
545	node_idx = (bit - iter->startbit) / NETLBL_CATMAP_MAPSIZE;
546	node_bit = bit - iter->startbit - (NETLBL_CATMAP_MAPSIZE * node_idx);
547	iter->bitmap[node_idx] |= NETLBL_CATMAP_BIT << node_bit;
548
549	return 0;
550}
551
552/**
553 * netlbl_secattr_catmap_setrng - Set a range of bits in a LSM secattr catmap
554 * @catmap: the category bitmap
555 * @start: the starting bit
556 * @end: the last bit in the string
557 * @flags: memory allocation flags
558 *
559 * Description:
560 * Set a range of bits, starting at @start and ending with @end.  Returns zero
561 * on success, negative values on failure.
562 *
563 */
564int netlbl_secattr_catmap_setrng(struct netlbl_lsm_secattr_catmap *catmap,
565				 u32 start,
566				 u32 end,
567				 gfp_t flags)
568{
569	int ret_val = 0;
570	struct netlbl_lsm_secattr_catmap *iter = catmap;
571	u32 iter_max_spot;
572	u32 spot;
573
574
575	while (iter->next != NULL &&
576	       start >= (iter->startbit + NETLBL_CATMAP_SIZE))
577		iter = iter->next;
578	iter_max_spot = iter->startbit + NETLBL_CATMAP_SIZE;
579
580	for (spot = start; spot <= end && ret_val == 0; spot++) {
581		if (spot >= iter_max_spot && iter->next != NULL) {
582			iter = iter->next;
583			iter_max_spot = iter->startbit + NETLBL_CATMAP_SIZE;
584		}
585		ret_val = netlbl_secattr_catmap_setbit(iter, spot, GFP_ATOMIC);
586	}
587
588	return ret_val;
589}
590
591/*
592 * LSM Functions
593 */
594
595/**
596 * netlbl_enabled - Determine if the NetLabel subsystem is enabled
597 *
598 * Description:
599 * The LSM can use this function to determine if it should use NetLabel
600 * security attributes in it's enforcement mechanism.  Currently, NetLabel is
601 * considered to be enabled when it's configuration contains a valid setup for
602 * at least one labeled protocol (i.e. NetLabel can understand incoming
603 * labeled packets of at least one type); otherwise NetLabel is considered to
604 * be disabled.
605 *
606 */
607int netlbl_enabled(void)
608{
609	/* At some point we probably want to expose this mechanism to the user
610	 * as well so that admins can toggle NetLabel regardless of the
611	 * configuration */
612	return (atomic_read(&netlabel_mgmt_protocount) > 0);
613}
614
615/**
616 * netlbl_sock_setattr - Label a socket using the correct protocol
617 * @sk: the socket to label
618 * @family: protocol family
619 * @secattr: the security attributes
620 *
621 * Description:
622 * Attach the correct label to the given socket using the security attributes
623 * specified in @secattr.  This function requires exclusive access to @sk,
624 * which means it either needs to be in the process of being created or locked.
625 * Returns zero on success, -EDESTADDRREQ if the domain is configured to use
626 * network address selectors (can't blindly label the socket), and negative
627 * values on all other failures.
628 *
629 */
630int netlbl_sock_setattr(struct sock *sk,
631			u16 family,
632			const struct netlbl_lsm_secattr *secattr)
633{
634	int ret_val;
635	struct netlbl_dom_map *dom_entry;
636
637	rcu_read_lock();
638	dom_entry = netlbl_domhsh_getentry(secattr->domain);
639	if (dom_entry == NULL) {
640		ret_val = -ENOENT;
641		goto socket_setattr_return;
642	}
643	switch (family) {
644	case AF_INET:
645		switch (dom_entry->type) {
646		case NETLBL_NLTYPE_ADDRSELECT:
647			ret_val = -EDESTADDRREQ;
648			break;
649		case NETLBL_NLTYPE_CIPSOV4:
650			ret_val = cipso_v4_sock_setattr(sk,
651						    dom_entry->type_def.cipsov4,
652						    secattr);
653			break;
654		case NETLBL_NLTYPE_UNLABELED:
655			ret_val = 0;
656			break;
657		default:
658			ret_val = -ENOENT;
659		}
660		break;
661#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
662	case AF_INET6:
663		/* since we don't support any IPv6 labeling protocols right
664		 * now we can optimize everything away until we do */
665		ret_val = 0;
666		break;
667#endif /* IPv6 */
668	default:
669		ret_val = -EPROTONOSUPPORT;
670	}
671
672socket_setattr_return:
673	rcu_read_unlock();
674	return ret_val;
675}
676
677/**
678 * netlbl_sock_delattr - Delete all the NetLabel labels on a socket
679 * @sk: the socket
680 *
681 * Description:
682 * Remove all the NetLabel labeling from @sk.  The caller is responsible for
683 * ensuring that @sk is locked.
684 *
685 */
686void netlbl_sock_delattr(struct sock *sk)
687{
688	cipso_v4_sock_delattr(sk);
689}
690
691/**
692 * netlbl_sock_getattr - Determine the security attributes of a sock
693 * @sk: the sock
694 * @secattr: the security attributes
695 *
696 * Description:
697 * Examines the given sock to see if any NetLabel style labeling has been
698 * applied to the sock, if so it parses the socket label and returns the
699 * security attributes in @secattr.  Returns zero on success, negative values
700 * on failure.
701 *
702 */
703int netlbl_sock_getattr(struct sock *sk,
704			struct netlbl_lsm_secattr *secattr)
705{
706	int ret_val;
707
708	switch (sk->sk_family) {
709	case AF_INET:
710		ret_val = cipso_v4_sock_getattr(sk, secattr);
711		break;
712#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
713	case AF_INET6:
714		ret_val = -ENOMSG;
715		break;
716#endif /* IPv6 */
717	default:
718		ret_val = -EPROTONOSUPPORT;
719	}
720
721	return ret_val;
722}
723
724/**
725 * netlbl_conn_setattr - Label a connected socket using the correct protocol
726 * @sk: the socket to label
727 * @addr: the destination address
728 * @secattr: the security attributes
729 *
730 * Description:
731 * Attach the correct label to the given connected socket using the security
732 * attributes specified in @secattr.  The caller is responsible for ensuring
733 * that @sk is locked.  Returns zero on success, negative values on failure.
734 *
735 */
736int netlbl_conn_setattr(struct sock *sk,
737			struct sockaddr *addr,
738			const struct netlbl_lsm_secattr *secattr)
739{
740	int ret_val;
741	struct sockaddr_in *addr4;
742	struct netlbl_domaddr4_map *af4_entry;
743
744	rcu_read_lock();
745	switch (addr->sa_family) {
746	case AF_INET:
747		addr4 = (struct sockaddr_in *)addr;
748		af4_entry = netlbl_domhsh_getentry_af4(secattr->domain,
749						       addr4->sin_addr.s_addr);
750		if (af4_entry == NULL) {
751			ret_val = -ENOENT;
752			goto conn_setattr_return;
753		}
754		switch (af4_entry->type) {
755		case NETLBL_NLTYPE_CIPSOV4:
756			ret_val = cipso_v4_sock_setattr(sk,
757						   af4_entry->type_def.cipsov4,
758						   secattr);
759			break;
760		case NETLBL_NLTYPE_UNLABELED:
761			/* just delete the protocols we support for right now
762			 * but we could remove other protocols if needed */
763			cipso_v4_sock_delattr(sk);
764			ret_val = 0;
765			break;
766		default:
767			ret_val = -ENOENT;
768		}
769		break;
770#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
771	case AF_INET6:
772		/* since we don't support any IPv6 labeling protocols right
773		 * now we can optimize everything away until we do */
774		ret_val = 0;
775		break;
776#endif /* IPv6 */
777	default:
778		ret_val = -EPROTONOSUPPORT;
779	}
780
781conn_setattr_return:
782	rcu_read_unlock();
783	return ret_val;
784}
785
786/**
787 * netlbl_req_setattr - Label a request socket using the correct protocol
788 * @req: the request socket to label
789 * @secattr: the security attributes
790 *
791 * Description:
792 * Attach the correct label to the given socket using the security attributes
793 * specified in @secattr.  Returns zero on success, negative values on failure.
794 *
795 */
796int netlbl_req_setattr(struct request_sock *req,
797		       const struct netlbl_lsm_secattr *secattr)
798{
799	int ret_val;
800	struct netlbl_dom_map *dom_entry;
801	struct netlbl_domaddr4_map *af4_entry;
802	u32 proto_type;
803	struct cipso_v4_doi *proto_cv4;
804
805	rcu_read_lock();
806	dom_entry = netlbl_domhsh_getentry(secattr->domain);
807	if (dom_entry == NULL) {
808		ret_val = -ENOENT;
809		goto req_setattr_return;
810	}
811	switch (req->rsk_ops->family) {
812	case AF_INET:
813		if (dom_entry->type == NETLBL_NLTYPE_ADDRSELECT) {
814			struct inet_request_sock *req_inet = inet_rsk(req);
815			af4_entry = netlbl_domhsh_getentry_af4(secattr->domain,
816							    req_inet->rmt_addr);
817			if (af4_entry == NULL) {
818				ret_val = -ENOENT;
819				goto req_setattr_return;
820			}
821			proto_type = af4_entry->type;
822			proto_cv4 = af4_entry->type_def.cipsov4;
823		} else {
824			proto_type = dom_entry->type;
825			proto_cv4 = dom_entry->type_def.cipsov4;
826		}
827		switch (proto_type) {
828		case NETLBL_NLTYPE_CIPSOV4:
829			ret_val = cipso_v4_req_setattr(req, proto_cv4, secattr);
830			break;
831		case NETLBL_NLTYPE_UNLABELED:
832			/* just delete the protocols we support for right now
833			 * but we could remove other protocols if needed */
834			cipso_v4_req_delattr(req);
835			ret_val = 0;
836			break;
837		default:
838			ret_val = -ENOENT;
839		}
840		break;
841#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
842	case AF_INET6:
843		/* since we don't support any IPv6 labeling protocols right
844		 * now we can optimize everything away until we do */
845		ret_val = 0;
846		break;
847#endif /* IPv6 */
848	default:
849		ret_val = -EPROTONOSUPPORT;
850	}
851
852req_setattr_return:
853	rcu_read_unlock();
854	return ret_val;
855}
856
857/**
858* netlbl_req_delattr - Delete all the NetLabel labels on a socket
859* @req: the socket
860*
861* Description:
862* Remove all the NetLabel labeling from @req.
863*
864*/
865void netlbl_req_delattr(struct request_sock *req)
866{
867	cipso_v4_req_delattr(req);
868}
869
870/**
871 * netlbl_skbuff_setattr - Label a packet using the correct protocol
872 * @skb: the packet
873 * @family: protocol family
874 * @secattr: the security attributes
875 *
876 * Description:
877 * Attach the correct label to the given packet using the security attributes
878 * specified in @secattr.  Returns zero on success, negative values on failure.
879 *
880 */
881int netlbl_skbuff_setattr(struct sk_buff *skb,
882			  u16 family,
883			  const struct netlbl_lsm_secattr *secattr)
884{
885	int ret_val;
886	struct iphdr *hdr4;
887	struct netlbl_domaddr4_map *af4_entry;
888
889	rcu_read_lock();
890	switch (family) {
891	case AF_INET:
892		hdr4 = ip_hdr(skb);
893		af4_entry = netlbl_domhsh_getentry_af4(secattr->domain,
894						       hdr4->daddr);
895		if (af4_entry == NULL) {
896			ret_val = -ENOENT;
897			goto skbuff_setattr_return;
898		}
899		switch (af4_entry->type) {
900		case NETLBL_NLTYPE_CIPSOV4:
901			ret_val = cipso_v4_skbuff_setattr(skb,
902						   af4_entry->type_def.cipsov4,
903						   secattr);
904			break;
905		case NETLBL_NLTYPE_UNLABELED:
906			/* just delete the protocols we support for right now
907			 * but we could remove other protocols if needed */
908			ret_val = cipso_v4_skbuff_delattr(skb);
909			break;
910		default:
911			ret_val = -ENOENT;
912		}
913		break;
914#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
915	case AF_INET6:
916		/* since we don't support any IPv6 labeling protocols right
917		 * now we can optimize everything away until we do */
918		ret_val = 0;
919		break;
920#endif /* IPv6 */
921	default:
922		ret_val = -EPROTONOSUPPORT;
923	}
924
925skbuff_setattr_return:
926	rcu_read_unlock();
927	return ret_val;
928}
929
930/**
931 * netlbl_skbuff_getattr - Determine the security attributes of a packet
932 * @skb: the packet
933 * @family: protocol family
934 * @secattr: the security attributes
935 *
936 * Description:
937 * Examines the given packet to see if a recognized form of packet labeling
938 * is present, if so it parses the packet label and returns the security
939 * attributes in @secattr.  Returns zero on success, negative values on
940 * failure.
941 *
942 */
943int netlbl_skbuff_getattr(const struct sk_buff *skb,
944			  u16 family,
945			  struct netlbl_lsm_secattr *secattr)
946{
947	switch (family) {
948	case AF_INET:
949		if (CIPSO_V4_OPTEXIST(skb) &&
950		    cipso_v4_skbuff_getattr(skb, secattr) == 0)
951			return 0;
952		break;
953#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
954	case AF_INET6:
955		break;
956#endif /* IPv6 */
957	}
958
959	return netlbl_unlabel_getattr(skb, family, secattr);
960}
961
962/**
963 * netlbl_skbuff_err - Handle a LSM error on a sk_buff
964 * @skb: the packet
965 * @error: the error code
966 * @gateway: true if host is acting as a gateway, false otherwise
967 *
968 * Description:
969 * Deal with a LSM problem when handling the packet in @skb, typically this is
970 * a permission denied problem (-EACCES).  The correct action is determined
971 * according to the packet's labeling protocol.
972 *
973 */
974void netlbl_skbuff_err(struct sk_buff *skb, int error, int gateway)
975{
976	if (CIPSO_V4_OPTEXIST(skb))
977		cipso_v4_error(skb, error, gateway);
978}
979
980/**
981 * netlbl_cache_invalidate - Invalidate all of the NetLabel protocol caches
982 *
983 * Description:
984 * For all of the NetLabel protocols that support some form of label mapping
985 * cache, invalidate the cache.  Returns zero on success, negative values on
986 * error.
987 *
988 */
989void netlbl_cache_invalidate(void)
990{
991	cipso_v4_cache_invalidate();
992}
993
994/**
995 * netlbl_cache_add - Add an entry to a NetLabel protocol cache
996 * @skb: the packet
997 * @secattr: the packet's security attributes
998 *
999 * Description:
1000 * Add the LSM security attributes for the given packet to the underlying
1001 * NetLabel protocol's label mapping cache.  Returns zero on success, negative
1002 * values on error.
1003 *
1004 */
1005int netlbl_cache_add(const struct sk_buff *skb,
1006		     const struct netlbl_lsm_secattr *secattr)
1007{
1008	if ((secattr->flags & NETLBL_SECATTR_CACHE) == 0)
1009		return -ENOMSG;
1010
1011	if (CIPSO_V4_OPTEXIST(skb))
1012		return cipso_v4_cache_add(skb, secattr);
1013
1014	return -ENOMSG;
1015}
1016
1017/*
1018 * Protocol Engine Functions
1019 */
1020
1021/**
1022 * netlbl_audit_start - Start an audit message
1023 * @type: audit message type
1024 * @audit_info: NetLabel audit information
1025 *
1026 * Description:
1027 * Start an audit message using the type specified in @type and fill the audit
1028 * message with some fields common to all NetLabel audit messages.  This
1029 * function should only be used by protocol engines, not LSMs.  Returns a
1030 * pointer to the audit buffer on success, NULL on failure.
1031 *
1032 */
1033struct audit_buffer *netlbl_audit_start(int type,
1034					struct netlbl_audit *audit_info)
1035{
1036	return netlbl_audit_start_common(type, audit_info);
1037}
1038
1039/*
1040 * Setup Functions
1041 */
1042
1043/**
1044 * netlbl_init - Initialize NetLabel
1045 *
1046 * Description:
1047 * Perform the required NetLabel initialization before first use.
1048 *
1049 */
1050static int __init netlbl_init(void)
1051{
1052	int ret_val;
1053
1054	printk(KERN_INFO "NetLabel: Initializing\n");
1055	printk(KERN_INFO "NetLabel:  domain hash size = %u\n",
1056	       (1 << NETLBL_DOMHSH_BITSIZE));
1057	printk(KERN_INFO "NetLabel:  protocols ="
1058	       " UNLABELED"
1059	       " CIPSOv4"
1060	       "\n");
1061
1062	ret_val = netlbl_domhsh_init(NETLBL_DOMHSH_BITSIZE);
1063	if (ret_val != 0)
1064		goto init_failure;
1065
1066	ret_val = netlbl_unlabel_init(NETLBL_UNLHSH_BITSIZE);
1067	if (ret_val != 0)
1068		goto init_failure;
1069
1070	ret_val = netlbl_netlink_init();
1071	if (ret_val != 0)
1072		goto init_failure;
1073
1074	ret_val = netlbl_unlabel_defconf();
1075	if (ret_val != 0)
1076		goto init_failure;
1077	printk(KERN_INFO "NetLabel:  unlabeled traffic allowed by default\n");
1078
1079	return 0;
1080
1081init_failure:
1082	panic("NetLabel: failed to initialize properly (%d)\n", ret_val);
1083}
1084
1085subsys_initcall(netlbl_init);
1086