11ccea77eSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later
2d15c345fSPaul Moore /*
3d15c345fSPaul Moore * NetLabel Kernel API
4d15c345fSPaul Moore *
5d15c345fSPaul Moore * This file defines the kernel API for the NetLabel system. The NetLabel
6d15c345fSPaul Moore * system manages static and dynamic label mappings for network protocols such
7d15c345fSPaul Moore * as CIPSO and RIPSO.
8d15c345fSPaul Moore *
982c21bfaSPaul Moore * Author: Paul Moore <paul@paul-moore.com>
10d15c345fSPaul Moore */
11d15c345fSPaul Moore
12d15c345fSPaul Moore /*
13014ab19aSPaul Moore * (c) Copyright Hewlett-Packard Development Company, L.P., 2006, 2008
14d15c345fSPaul Moore */
15d15c345fSPaul Moore
16d15c345fSPaul Moore #include <linux/init.h>
17d15c345fSPaul Moore #include <linux/types.h>
185a0e3ad6STejun Heo #include <linux/slab.h>
19eda61d32SPaul Moore #include <linux/audit.h>
206c2e8ac0SPaul Moore #include <linux/in.h>
216c2e8ac0SPaul Moore #include <linux/in6.h>
22d15c345fSPaul Moore #include <net/ip.h>
236c2e8ac0SPaul Moore #include <net/ipv6.h>
24d15c345fSPaul Moore #include <net/netlabel.h>
25d15c345fSPaul Moore #include <net/cipso_ipv4.h>
26ceba1832SHuw Davies #include <net/calipso.h>
27d15c345fSPaul Moore #include <asm/bug.h>
2860063497SArun Sharma #include <linux/atomic.h>
29d15c345fSPaul Moore
30d15c345fSPaul Moore #include "netlabel_domainhash.h"
31d15c345fSPaul Moore #include "netlabel_unlabeled.h"
32eda61d32SPaul Moore #include "netlabel_cipso_v4.h"
33ceba1832SHuw Davies #include "netlabel_calipso.h"
34d15c345fSPaul Moore #include "netlabel_user.h"
3523bcdc1aSPaul Moore #include "netlabel_mgmt.h"
366c2e8ac0SPaul Moore #include "netlabel_addrlist.h"
37d15c345fSPaul Moore
38d15c345fSPaul Moore /*
39eda61d32SPaul Moore * Configuration Functions
40eda61d32SPaul Moore */
41eda61d32SPaul Moore
42eda61d32SPaul Moore /**
43eda61d32SPaul Moore * netlbl_cfg_map_del - Remove a NetLabel/LSM domain mapping
44eda61d32SPaul Moore * @domain: the domain mapping to remove
456c2e8ac0SPaul Moore * @family: address family
466c2e8ac0SPaul Moore * @addr: IP address
476c2e8ac0SPaul Moore * @mask: IP address mask
48eda61d32SPaul Moore * @audit_info: NetLabel audit information
49eda61d32SPaul Moore *
50eda61d32SPaul Moore * Description:
51eda61d32SPaul Moore * Removes a NetLabel/LSM domain mapping. A @domain value of NULL causes the
52eda61d32SPaul Moore * default domain mapping to be removed. Returns zero on success, negative
53eda61d32SPaul Moore * values on failure.
54eda61d32SPaul Moore *
55eda61d32SPaul Moore */
netlbl_cfg_map_del(const char * domain,u16 family,const void * addr,const void * mask,struct netlbl_audit * audit_info)566c2e8ac0SPaul Moore int netlbl_cfg_map_del(const char *domain,
576c2e8ac0SPaul Moore u16 family,
586c2e8ac0SPaul Moore const void *addr,
596c2e8ac0SPaul Moore const void *mask,
606c2e8ac0SPaul Moore struct netlbl_audit *audit_info)
61eda61d32SPaul Moore {
626c2e8ac0SPaul Moore if (addr == NULL && mask == NULL) {
638f18e675SHuw Davies return netlbl_domhsh_remove(domain, family, audit_info);
646c2e8ac0SPaul Moore } else if (addr != NULL && mask != NULL) {
656c2e8ac0SPaul Moore switch (family) {
666c2e8ac0SPaul Moore case AF_INET:
676c2e8ac0SPaul Moore return netlbl_domhsh_remove_af4(domain, addr, mask,
686c2e8ac0SPaul Moore audit_info);
693f09354aSHuw Davies #if IS_ENABLED(CONFIG_IPV6)
703f09354aSHuw Davies case AF_INET6:
713f09354aSHuw Davies return netlbl_domhsh_remove_af6(domain, addr, mask,
723f09354aSHuw Davies audit_info);
733f09354aSHuw Davies #endif /* IPv6 */
746c2e8ac0SPaul Moore default:
756c2e8ac0SPaul Moore return -EPFNOSUPPORT;
766c2e8ac0SPaul Moore }
776c2e8ac0SPaul Moore } else
786c2e8ac0SPaul Moore return -EINVAL;
79eda61d32SPaul Moore }
80eda61d32SPaul Moore
81eda61d32SPaul Moore /**
826c2e8ac0SPaul Moore * netlbl_cfg_unlbl_map_add - Add a new unlabeled mapping
83eda61d32SPaul Moore * @domain: the domain mapping to add
846c2e8ac0SPaul Moore * @family: address family
856c2e8ac0SPaul Moore * @addr: IP address
866c2e8ac0SPaul Moore * @mask: IP address mask
87eda61d32SPaul Moore * @audit_info: NetLabel audit information
88eda61d32SPaul Moore *
89eda61d32SPaul Moore * Description:
90eda61d32SPaul Moore * Adds a new unlabeled NetLabel/LSM domain mapping. A @domain value of NULL
91eda61d32SPaul Moore * causes a new default domain mapping to be added. Returns zero on success,
92eda61d32SPaul Moore * negative values on failure.
93eda61d32SPaul Moore *
94eda61d32SPaul Moore */
netlbl_cfg_unlbl_map_add(const char * domain,u16 family,const void * addr,const void * mask,struct netlbl_audit * audit_info)956c2e8ac0SPaul Moore int netlbl_cfg_unlbl_map_add(const char *domain,
966c2e8ac0SPaul Moore u16 family,
976c2e8ac0SPaul Moore const void *addr,
986c2e8ac0SPaul Moore const void *mask,
99eda61d32SPaul Moore struct netlbl_audit *audit_info)
100eda61d32SPaul Moore {
101eda61d32SPaul Moore int ret_val = -ENOMEM;
102eda61d32SPaul Moore struct netlbl_dom_map *entry;
1036c2e8ac0SPaul Moore struct netlbl_domaddr_map *addrmap = NULL;
1046c2e8ac0SPaul Moore struct netlbl_domaddr4_map *map4 = NULL;
1056c2e8ac0SPaul Moore struct netlbl_domaddr6_map *map6 = NULL;
106eda61d32SPaul Moore
107eda61d32SPaul Moore entry = kzalloc(sizeof(*entry), GFP_ATOMIC);
108eda61d32SPaul Moore if (entry == NULL)
109948a7243SPaul Moore return -ENOMEM;
110eda61d32SPaul Moore if (domain != NULL) {
111eda61d32SPaul Moore entry->domain = kstrdup(domain, GFP_ATOMIC);
112eda61d32SPaul Moore if (entry->domain == NULL)
1136c2e8ac0SPaul Moore goto cfg_unlbl_map_add_failure;
114eda61d32SPaul Moore }
1158f18e675SHuw Davies entry->family = family;
1166c2e8ac0SPaul Moore
1176c2e8ac0SPaul Moore if (addr == NULL && mask == NULL)
1186a8b7f0cSPaul Moore entry->def.type = NETLBL_NLTYPE_UNLABELED;
1196c2e8ac0SPaul Moore else if (addr != NULL && mask != NULL) {
1206c2e8ac0SPaul Moore addrmap = kzalloc(sizeof(*addrmap), GFP_ATOMIC);
1216c2e8ac0SPaul Moore if (addrmap == NULL)
1226c2e8ac0SPaul Moore goto cfg_unlbl_map_add_failure;
1236c2e8ac0SPaul Moore INIT_LIST_HEAD(&addrmap->list4);
1246c2e8ac0SPaul Moore INIT_LIST_HEAD(&addrmap->list6);
1256c2e8ac0SPaul Moore
1266c2e8ac0SPaul Moore switch (family) {
1271281bc25SPaul Moore case AF_INET: {
1281281bc25SPaul Moore const struct in_addr *addr4 = addr;
1291281bc25SPaul Moore const struct in_addr *mask4 = mask;
1306c2e8ac0SPaul Moore map4 = kzalloc(sizeof(*map4), GFP_ATOMIC);
1316c2e8ac0SPaul Moore if (map4 == NULL)
1326c2e8ac0SPaul Moore goto cfg_unlbl_map_add_failure;
1336a8b7f0cSPaul Moore map4->def.type = NETLBL_NLTYPE_UNLABELED;
1346c2e8ac0SPaul Moore map4->list.addr = addr4->s_addr & mask4->s_addr;
1356c2e8ac0SPaul Moore map4->list.mask = mask4->s_addr;
1366c2e8ac0SPaul Moore map4->list.valid = 1;
1376c2e8ac0SPaul Moore ret_val = netlbl_af4list_add(&map4->list,
1386c2e8ac0SPaul Moore &addrmap->list4);
1396c2e8ac0SPaul Moore if (ret_val != 0)
1406c2e8ac0SPaul Moore goto cfg_unlbl_map_add_failure;
1416c2e8ac0SPaul Moore break;
1421281bc25SPaul Moore }
143dfd56b8bSEric Dumazet #if IS_ENABLED(CONFIG_IPV6)
1441281bc25SPaul Moore case AF_INET6: {
1451281bc25SPaul Moore const struct in6_addr *addr6 = addr;
1461281bc25SPaul Moore const struct in6_addr *mask6 = mask;
1476c2e8ac0SPaul Moore map6 = kzalloc(sizeof(*map6), GFP_ATOMIC);
148ca7daea6SJulia Lawall if (map6 == NULL)
1496c2e8ac0SPaul Moore goto cfg_unlbl_map_add_failure;
1506a8b7f0cSPaul Moore map6->def.type = NETLBL_NLTYPE_UNLABELED;
1514e3fd7a0SAlexey Dobriyan map6->list.addr = *addr6;
1526c2e8ac0SPaul Moore map6->list.addr.s6_addr32[0] &= mask6->s6_addr32[0];
1536c2e8ac0SPaul Moore map6->list.addr.s6_addr32[1] &= mask6->s6_addr32[1];
1546c2e8ac0SPaul Moore map6->list.addr.s6_addr32[2] &= mask6->s6_addr32[2];
1556c2e8ac0SPaul Moore map6->list.addr.s6_addr32[3] &= mask6->s6_addr32[3];
1564e3fd7a0SAlexey Dobriyan map6->list.mask = *mask6;
1576c2e8ac0SPaul Moore map6->list.valid = 1;
15842ca0203SDan Carpenter ret_val = netlbl_af6list_add(&map6->list,
15942ca0203SDan Carpenter &addrmap->list6);
1606c2e8ac0SPaul Moore if (ret_val != 0)
1616c2e8ac0SPaul Moore goto cfg_unlbl_map_add_failure;
1626c2e8ac0SPaul Moore break;
1631281bc25SPaul Moore }
1641281bc25SPaul Moore #endif /* IPv6 */
1656c2e8ac0SPaul Moore default:
1666c2e8ac0SPaul Moore goto cfg_unlbl_map_add_failure;
1676c2e8ac0SPaul Moore }
1686c2e8ac0SPaul Moore
1696a8b7f0cSPaul Moore entry->def.addrsel = addrmap;
1706a8b7f0cSPaul Moore entry->def.type = NETLBL_NLTYPE_ADDRSELECT;
1716c2e8ac0SPaul Moore } else {
1726c2e8ac0SPaul Moore ret_val = -EINVAL;
1736c2e8ac0SPaul Moore goto cfg_unlbl_map_add_failure;
1746c2e8ac0SPaul Moore }
175eda61d32SPaul Moore
176eda61d32SPaul Moore ret_val = netlbl_domhsh_add(entry, audit_info);
177eda61d32SPaul Moore if (ret_val != 0)
1786c2e8ac0SPaul Moore goto cfg_unlbl_map_add_failure;
179eda61d32SPaul Moore
180eda61d32SPaul Moore return 0;
181eda61d32SPaul Moore
1826c2e8ac0SPaul Moore cfg_unlbl_map_add_failure:
183eda61d32SPaul Moore kfree(entry->domain);
184eda61d32SPaul Moore kfree(entry);
1856c2e8ac0SPaul Moore kfree(addrmap);
1866c2e8ac0SPaul Moore kfree(map4);
1876c2e8ac0SPaul Moore kfree(map6);
188eda61d32SPaul Moore return ret_val;
189eda61d32SPaul Moore }
190eda61d32SPaul Moore
1916c2e8ac0SPaul Moore
192eda61d32SPaul Moore /**
1936c2e8ac0SPaul Moore * netlbl_cfg_unlbl_static_add - Adds a new static label
1946c2e8ac0SPaul Moore * @net: network namespace
1956c2e8ac0SPaul Moore * @dev_name: interface name
1966c2e8ac0SPaul Moore * @addr: IP address in network byte order (struct in[6]_addr)
1976c2e8ac0SPaul Moore * @mask: address mask in network byte order (struct in[6]_addr)
1986c2e8ac0SPaul Moore * @family: address family
1996c2e8ac0SPaul Moore * @secid: LSM secid value for the entry
200eda61d32SPaul Moore * @audit_info: NetLabel audit information
201eda61d32SPaul Moore *
202eda61d32SPaul Moore * Description:
2036c2e8ac0SPaul Moore * Adds a new NetLabel static label to be used when protocol provided labels
2046c2e8ac0SPaul Moore * are not present on incoming traffic. If @dev_name is NULL then the default
2056c2e8ac0SPaul Moore * interface will be used. Returns zero on success, negative values on failure.
206eda61d32SPaul Moore *
207eda61d32SPaul Moore */
netlbl_cfg_unlbl_static_add(struct net * net,const char * dev_name,const void * addr,const void * mask,u16 family,u32 secid,struct netlbl_audit * audit_info)2086c2e8ac0SPaul Moore int netlbl_cfg_unlbl_static_add(struct net *net,
2096c2e8ac0SPaul Moore const char *dev_name,
2106c2e8ac0SPaul Moore const void *addr,
2116c2e8ac0SPaul Moore const void *mask,
2126c2e8ac0SPaul Moore u16 family,
2136c2e8ac0SPaul Moore u32 secid,
2146c2e8ac0SPaul Moore struct netlbl_audit *audit_info)
2156c2e8ac0SPaul Moore {
2166c2e8ac0SPaul Moore u32 addr_len;
2176c2e8ac0SPaul Moore
2186c2e8ac0SPaul Moore switch (family) {
2196c2e8ac0SPaul Moore case AF_INET:
2206c2e8ac0SPaul Moore addr_len = sizeof(struct in_addr);
2216c2e8ac0SPaul Moore break;
222dfd56b8bSEric Dumazet #if IS_ENABLED(CONFIG_IPV6)
2236c2e8ac0SPaul Moore case AF_INET6:
2246c2e8ac0SPaul Moore addr_len = sizeof(struct in6_addr);
2256c2e8ac0SPaul Moore break;
2261281bc25SPaul Moore #endif /* IPv6 */
2276c2e8ac0SPaul Moore default:
2286c2e8ac0SPaul Moore return -EPFNOSUPPORT;
2296c2e8ac0SPaul Moore }
2306c2e8ac0SPaul Moore
2316c2e8ac0SPaul Moore return netlbl_unlhsh_add(net,
2326c2e8ac0SPaul Moore dev_name, addr, mask, addr_len,
2336c2e8ac0SPaul Moore secid, audit_info);
2346c2e8ac0SPaul Moore }
2356c2e8ac0SPaul Moore
2366c2e8ac0SPaul Moore /**
2376c2e8ac0SPaul Moore * netlbl_cfg_unlbl_static_del - Removes an existing static label
2386c2e8ac0SPaul Moore * @net: network namespace
2396c2e8ac0SPaul Moore * @dev_name: interface name
2406c2e8ac0SPaul Moore * @addr: IP address in network byte order (struct in[6]_addr)
2416c2e8ac0SPaul Moore * @mask: address mask in network byte order (struct in[6]_addr)
2426c2e8ac0SPaul Moore * @family: address family
2436c2e8ac0SPaul Moore * @audit_info: NetLabel audit information
2446c2e8ac0SPaul Moore *
2456c2e8ac0SPaul Moore * Description:
2466c2e8ac0SPaul Moore * Removes an existing NetLabel static label used when protocol provided labels
2476c2e8ac0SPaul Moore * are not present on incoming traffic. If @dev_name is NULL then the default
2486c2e8ac0SPaul Moore * interface will be used. Returns zero on success, negative values on failure.
2496c2e8ac0SPaul Moore *
2506c2e8ac0SPaul Moore */
netlbl_cfg_unlbl_static_del(struct net * net,const char * dev_name,const void * addr,const void * mask,u16 family,struct netlbl_audit * audit_info)2516c2e8ac0SPaul Moore int netlbl_cfg_unlbl_static_del(struct net *net,
2526c2e8ac0SPaul Moore const char *dev_name,
2536c2e8ac0SPaul Moore const void *addr,
2546c2e8ac0SPaul Moore const void *mask,
2556c2e8ac0SPaul Moore u16 family,
2566c2e8ac0SPaul Moore struct netlbl_audit *audit_info)
2576c2e8ac0SPaul Moore {
2586c2e8ac0SPaul Moore u32 addr_len;
2596c2e8ac0SPaul Moore
2606c2e8ac0SPaul Moore switch (family) {
2616c2e8ac0SPaul Moore case AF_INET:
2626c2e8ac0SPaul Moore addr_len = sizeof(struct in_addr);
2636c2e8ac0SPaul Moore break;
264dfd56b8bSEric Dumazet #if IS_ENABLED(CONFIG_IPV6)
2656c2e8ac0SPaul Moore case AF_INET6:
2666c2e8ac0SPaul Moore addr_len = sizeof(struct in6_addr);
2676c2e8ac0SPaul Moore break;
2681281bc25SPaul Moore #endif /* IPv6 */
2696c2e8ac0SPaul Moore default:
2706c2e8ac0SPaul Moore return -EPFNOSUPPORT;
2716c2e8ac0SPaul Moore }
2726c2e8ac0SPaul Moore
2736c2e8ac0SPaul Moore return netlbl_unlhsh_remove(net,
2746c2e8ac0SPaul Moore dev_name, addr, mask, addr_len,
2756c2e8ac0SPaul Moore audit_info);
2766c2e8ac0SPaul Moore }
2776c2e8ac0SPaul Moore
2786c2e8ac0SPaul Moore /**
2796c2e8ac0SPaul Moore * netlbl_cfg_cipsov4_add - Add a new CIPSOv4 DOI definition
2806c2e8ac0SPaul Moore * @doi_def: CIPSO DOI definition
2816c2e8ac0SPaul Moore * @audit_info: NetLabel audit information
2826c2e8ac0SPaul Moore *
2836c2e8ac0SPaul Moore * Description:
2846c2e8ac0SPaul Moore * Add a new CIPSO DOI definition as defined by @doi_def. Returns zero on
2856c2e8ac0SPaul Moore * success and negative values on failure.
2866c2e8ac0SPaul Moore *
2876c2e8ac0SPaul Moore */
netlbl_cfg_cipsov4_add(struct cipso_v4_doi * doi_def,struct netlbl_audit * audit_info)2886c2e8ac0SPaul Moore int netlbl_cfg_cipsov4_add(struct cipso_v4_doi *doi_def,
2896c2e8ac0SPaul Moore struct netlbl_audit *audit_info)
2906c2e8ac0SPaul Moore {
2916c2e8ac0SPaul Moore return cipso_v4_doi_add(doi_def, audit_info);
2926c2e8ac0SPaul Moore }
2936c2e8ac0SPaul Moore
2946c2e8ac0SPaul Moore /**
2956c2e8ac0SPaul Moore * netlbl_cfg_cipsov4_del - Remove an existing CIPSOv4 DOI definition
2966c2e8ac0SPaul Moore * @doi: CIPSO DOI
2976c2e8ac0SPaul Moore * @audit_info: NetLabel audit information
2986c2e8ac0SPaul Moore *
2996c2e8ac0SPaul Moore * Description:
3006c2e8ac0SPaul Moore * Remove an existing CIPSO DOI definition matching @doi. Returns zero on
3016c2e8ac0SPaul Moore * success and negative values on failure.
3026c2e8ac0SPaul Moore *
3036c2e8ac0SPaul Moore */
netlbl_cfg_cipsov4_del(u32 doi,struct netlbl_audit * audit_info)3046c2e8ac0SPaul Moore void netlbl_cfg_cipsov4_del(u32 doi, struct netlbl_audit *audit_info)
3056c2e8ac0SPaul Moore {
3066c2e8ac0SPaul Moore cipso_v4_doi_remove(doi, audit_info);
3076c2e8ac0SPaul Moore }
3086c2e8ac0SPaul Moore
3096c2e8ac0SPaul Moore /**
3106c2e8ac0SPaul Moore * netlbl_cfg_cipsov4_map_add - Add a new CIPSOv4 DOI mapping
3116c2e8ac0SPaul Moore * @doi: the CIPSO DOI
3126c2e8ac0SPaul Moore * @domain: the domain mapping to add
3136c2e8ac0SPaul Moore * @addr: IP address
3146c2e8ac0SPaul Moore * @mask: IP address mask
3156c2e8ac0SPaul Moore * @audit_info: NetLabel audit information
3166c2e8ac0SPaul Moore *
3176c2e8ac0SPaul Moore * Description:
3186c2e8ac0SPaul Moore * Add a new NetLabel/LSM domain mapping for the given CIPSO DOI to the NetLabel
3196c2e8ac0SPaul Moore * subsystem. A @domain value of NULL adds a new default domain mapping.
3206c2e8ac0SPaul Moore * Returns zero on success, negative values on failure.
3216c2e8ac0SPaul Moore *
3226c2e8ac0SPaul Moore */
netlbl_cfg_cipsov4_map_add(u32 doi,const char * domain,const struct in_addr * addr,const struct in_addr * mask,struct netlbl_audit * audit_info)3236c2e8ac0SPaul Moore int netlbl_cfg_cipsov4_map_add(u32 doi,
324eda61d32SPaul Moore const char *domain,
3256c2e8ac0SPaul Moore const struct in_addr *addr,
3266c2e8ac0SPaul Moore const struct in_addr *mask,
327eda61d32SPaul Moore struct netlbl_audit *audit_info)
328eda61d32SPaul Moore {
329eda61d32SPaul Moore int ret_val = -ENOMEM;
3306c2e8ac0SPaul Moore struct cipso_v4_doi *doi_def;
331eda61d32SPaul Moore struct netlbl_dom_map *entry;
3326c2e8ac0SPaul Moore struct netlbl_domaddr_map *addrmap = NULL;
3336c2e8ac0SPaul Moore struct netlbl_domaddr4_map *addrinfo = NULL;
334eda61d32SPaul Moore
3356c2e8ac0SPaul Moore doi_def = cipso_v4_doi_getdef(doi);
3366c2e8ac0SPaul Moore if (doi_def == NULL)
3376c2e8ac0SPaul Moore return -ENOENT;
338b1edeb10SPaul Moore
339eda61d32SPaul Moore entry = kzalloc(sizeof(*entry), GFP_ATOMIC);
340eda61d32SPaul Moore if (entry == NULL)
34194a80d63SJulia Lawall goto out_entry;
3428f18e675SHuw Davies entry->family = AF_INET;
343eda61d32SPaul Moore if (domain != NULL) {
344eda61d32SPaul Moore entry->domain = kstrdup(domain, GFP_ATOMIC);
345eda61d32SPaul Moore if (entry->domain == NULL)
34694a80d63SJulia Lawall goto out_domain;
347eda61d32SPaul Moore }
348eda61d32SPaul Moore
3496c2e8ac0SPaul Moore if (addr == NULL && mask == NULL) {
3506a8b7f0cSPaul Moore entry->def.cipso = doi_def;
3516a8b7f0cSPaul Moore entry->def.type = NETLBL_NLTYPE_CIPSOV4;
3526c2e8ac0SPaul Moore } else if (addr != NULL && mask != NULL) {
3536c2e8ac0SPaul Moore addrmap = kzalloc(sizeof(*addrmap), GFP_ATOMIC);
3546c2e8ac0SPaul Moore if (addrmap == NULL)
35594a80d63SJulia Lawall goto out_addrmap;
3566c2e8ac0SPaul Moore INIT_LIST_HEAD(&addrmap->list4);
3576c2e8ac0SPaul Moore INIT_LIST_HEAD(&addrmap->list6);
3586c2e8ac0SPaul Moore
3596c2e8ac0SPaul Moore addrinfo = kzalloc(sizeof(*addrinfo), GFP_ATOMIC);
3606c2e8ac0SPaul Moore if (addrinfo == NULL)
36194a80d63SJulia Lawall goto out_addrinfo;
3626a8b7f0cSPaul Moore addrinfo->def.cipso = doi_def;
3636a8b7f0cSPaul Moore addrinfo->def.type = NETLBL_NLTYPE_CIPSOV4;
3646c2e8ac0SPaul Moore addrinfo->list.addr = addr->s_addr & mask->s_addr;
3656c2e8ac0SPaul Moore addrinfo->list.mask = mask->s_addr;
3666c2e8ac0SPaul Moore addrinfo->list.valid = 1;
3676c2e8ac0SPaul Moore ret_val = netlbl_af4list_add(&addrinfo->list, &addrmap->list4);
3686c2e8ac0SPaul Moore if (ret_val != 0)
3696c2e8ac0SPaul Moore goto cfg_cipsov4_map_add_failure;
3706c2e8ac0SPaul Moore
3716a8b7f0cSPaul Moore entry->def.addrsel = addrmap;
3726a8b7f0cSPaul Moore entry->def.type = NETLBL_NLTYPE_ADDRSELECT;
3736c2e8ac0SPaul Moore } else {
3746c2e8ac0SPaul Moore ret_val = -EINVAL;
37594a80d63SJulia Lawall goto out_addrmap;
376b1edeb10SPaul Moore }
3776c2e8ac0SPaul Moore
378eda61d32SPaul Moore ret_val = netlbl_domhsh_add(entry, audit_info);
379eda61d32SPaul Moore if (ret_val != 0)
3806c2e8ac0SPaul Moore goto cfg_cipsov4_map_add_failure;
381eda61d32SPaul Moore
3826c2e8ac0SPaul Moore return 0;
383b1edeb10SPaul Moore
3846c2e8ac0SPaul Moore cfg_cipsov4_map_add_failure:
3856c2e8ac0SPaul Moore kfree(addrinfo);
38694a80d63SJulia Lawall out_addrinfo:
38794a80d63SJulia Lawall kfree(addrmap);
38894a80d63SJulia Lawall out_addrmap:
38994a80d63SJulia Lawall kfree(entry->domain);
39094a80d63SJulia Lawall out_domain:
39194a80d63SJulia Lawall kfree(entry);
39294a80d63SJulia Lawall out_entry:
39394a80d63SJulia Lawall cipso_v4_doi_putdef(doi_def);
3946c2e8ac0SPaul Moore return ret_val;
395eda61d32SPaul Moore }
396eda61d32SPaul Moore
3973f09354aSHuw Davies /**
3983f09354aSHuw Davies * netlbl_cfg_calipso_add - Add a new CALIPSO DOI definition
3993f09354aSHuw Davies * @doi_def: CALIPSO DOI definition
4003f09354aSHuw Davies * @audit_info: NetLabel audit information
4013f09354aSHuw Davies *
4023f09354aSHuw Davies * Description:
4033f09354aSHuw Davies * Add a new CALIPSO DOI definition as defined by @doi_def. Returns zero on
4043f09354aSHuw Davies * success and negative values on failure.
4053f09354aSHuw Davies *
4063f09354aSHuw Davies */
netlbl_cfg_calipso_add(struct calipso_doi * doi_def,struct netlbl_audit * audit_info)4073f09354aSHuw Davies int netlbl_cfg_calipso_add(struct calipso_doi *doi_def,
4083f09354aSHuw Davies struct netlbl_audit *audit_info)
4093f09354aSHuw Davies {
4103f09354aSHuw Davies #if IS_ENABLED(CONFIG_IPV6)
4113f09354aSHuw Davies return calipso_doi_add(doi_def, audit_info);
4123f09354aSHuw Davies #else /* IPv6 */
4133f09354aSHuw Davies return -ENOSYS;
4143f09354aSHuw Davies #endif /* IPv6 */
4153f09354aSHuw Davies }
4163f09354aSHuw Davies
4173f09354aSHuw Davies /**
4183f09354aSHuw Davies * netlbl_cfg_calipso_del - Remove an existing CALIPSO DOI definition
4193f09354aSHuw Davies * @doi: CALIPSO DOI
4203f09354aSHuw Davies * @audit_info: NetLabel audit information
4213f09354aSHuw Davies *
4223f09354aSHuw Davies * Description:
4233f09354aSHuw Davies * Remove an existing CALIPSO DOI definition matching @doi. Returns zero on
4243f09354aSHuw Davies * success and negative values on failure.
4253f09354aSHuw Davies *
4263f09354aSHuw Davies */
netlbl_cfg_calipso_del(u32 doi,struct netlbl_audit * audit_info)4273f09354aSHuw Davies void netlbl_cfg_calipso_del(u32 doi, struct netlbl_audit *audit_info)
4283f09354aSHuw Davies {
4293f09354aSHuw Davies #if IS_ENABLED(CONFIG_IPV6)
4303f09354aSHuw Davies calipso_doi_remove(doi, audit_info);
4313f09354aSHuw Davies #endif /* IPv6 */
4323f09354aSHuw Davies }
4333f09354aSHuw Davies
4343f09354aSHuw Davies /**
4353f09354aSHuw Davies * netlbl_cfg_calipso_map_add - Add a new CALIPSO DOI mapping
4363f09354aSHuw Davies * @doi: the CALIPSO DOI
4373f09354aSHuw Davies * @domain: the domain mapping to add
4383f09354aSHuw Davies * @addr: IP address
4393f09354aSHuw Davies * @mask: IP address mask
4403f09354aSHuw Davies * @audit_info: NetLabel audit information
4413f09354aSHuw Davies *
4423f09354aSHuw Davies * Description:
4433f09354aSHuw Davies * Add a new NetLabel/LSM domain mapping for the given CALIPSO DOI to the
4443f09354aSHuw Davies * NetLabel subsystem. A @domain value of NULL adds a new default domain
4453f09354aSHuw Davies * mapping. Returns zero on success, negative values on failure.
4463f09354aSHuw Davies *
4473f09354aSHuw Davies */
netlbl_cfg_calipso_map_add(u32 doi,const char * domain,const struct in6_addr * addr,const struct in6_addr * mask,struct netlbl_audit * audit_info)4483f09354aSHuw Davies int netlbl_cfg_calipso_map_add(u32 doi,
4493f09354aSHuw Davies const char *domain,
4503f09354aSHuw Davies const struct in6_addr *addr,
4513f09354aSHuw Davies const struct in6_addr *mask,
4523f09354aSHuw Davies struct netlbl_audit *audit_info)
4533f09354aSHuw Davies {
4543f09354aSHuw Davies #if IS_ENABLED(CONFIG_IPV6)
4553f09354aSHuw Davies int ret_val = -ENOMEM;
4563f09354aSHuw Davies struct calipso_doi *doi_def;
4573f09354aSHuw Davies struct netlbl_dom_map *entry;
4583f09354aSHuw Davies struct netlbl_domaddr_map *addrmap = NULL;
4593f09354aSHuw Davies struct netlbl_domaddr6_map *addrinfo = NULL;
4603f09354aSHuw Davies
4613f09354aSHuw Davies doi_def = calipso_doi_getdef(doi);
4623f09354aSHuw Davies if (doi_def == NULL)
4633f09354aSHuw Davies return -ENOENT;
4643f09354aSHuw Davies
4653f09354aSHuw Davies entry = kzalloc(sizeof(*entry), GFP_ATOMIC);
4663f09354aSHuw Davies if (entry == NULL)
4673f09354aSHuw Davies goto out_entry;
4683f09354aSHuw Davies entry->family = AF_INET6;
4693f09354aSHuw Davies if (domain != NULL) {
4703f09354aSHuw Davies entry->domain = kstrdup(domain, GFP_ATOMIC);
4713f09354aSHuw Davies if (entry->domain == NULL)
4723f09354aSHuw Davies goto out_domain;
4733f09354aSHuw Davies }
4743f09354aSHuw Davies
4753f09354aSHuw Davies if (addr == NULL && mask == NULL) {
4763f09354aSHuw Davies entry->def.calipso = doi_def;
4773f09354aSHuw Davies entry->def.type = NETLBL_NLTYPE_CALIPSO;
4783f09354aSHuw Davies } else if (addr != NULL && mask != NULL) {
4793f09354aSHuw Davies addrmap = kzalloc(sizeof(*addrmap), GFP_ATOMIC);
4803f09354aSHuw Davies if (addrmap == NULL)
4813f09354aSHuw Davies goto out_addrmap;
4823f09354aSHuw Davies INIT_LIST_HEAD(&addrmap->list4);
4833f09354aSHuw Davies INIT_LIST_HEAD(&addrmap->list6);
4843f09354aSHuw Davies
4853f09354aSHuw Davies addrinfo = kzalloc(sizeof(*addrinfo), GFP_ATOMIC);
4863f09354aSHuw Davies if (addrinfo == NULL)
4873f09354aSHuw Davies goto out_addrinfo;
4883f09354aSHuw Davies addrinfo->def.calipso = doi_def;
4893f09354aSHuw Davies addrinfo->def.type = NETLBL_NLTYPE_CALIPSO;
4903f09354aSHuw Davies addrinfo->list.addr = *addr;
4913f09354aSHuw Davies addrinfo->list.addr.s6_addr32[0] &= mask->s6_addr32[0];
4923f09354aSHuw Davies addrinfo->list.addr.s6_addr32[1] &= mask->s6_addr32[1];
4933f09354aSHuw Davies addrinfo->list.addr.s6_addr32[2] &= mask->s6_addr32[2];
4943f09354aSHuw Davies addrinfo->list.addr.s6_addr32[3] &= mask->s6_addr32[3];
4953f09354aSHuw Davies addrinfo->list.mask = *mask;
4963f09354aSHuw Davies addrinfo->list.valid = 1;
4973f09354aSHuw Davies ret_val = netlbl_af6list_add(&addrinfo->list, &addrmap->list6);
4983f09354aSHuw Davies if (ret_val != 0)
4993f09354aSHuw Davies goto cfg_calipso_map_add_failure;
5003f09354aSHuw Davies
5013f09354aSHuw Davies entry->def.addrsel = addrmap;
5023f09354aSHuw Davies entry->def.type = NETLBL_NLTYPE_ADDRSELECT;
5033f09354aSHuw Davies } else {
5043f09354aSHuw Davies ret_val = -EINVAL;
5053f09354aSHuw Davies goto out_addrmap;
5063f09354aSHuw Davies }
5073f09354aSHuw Davies
5083f09354aSHuw Davies ret_val = netlbl_domhsh_add(entry, audit_info);
5093f09354aSHuw Davies if (ret_val != 0)
5103f09354aSHuw Davies goto cfg_calipso_map_add_failure;
5113f09354aSHuw Davies
5123f09354aSHuw Davies return 0;
5133f09354aSHuw Davies
5143f09354aSHuw Davies cfg_calipso_map_add_failure:
5153f09354aSHuw Davies kfree(addrinfo);
5163f09354aSHuw Davies out_addrinfo:
5173f09354aSHuw Davies kfree(addrmap);
5183f09354aSHuw Davies out_addrmap:
5193f09354aSHuw Davies kfree(entry->domain);
5203f09354aSHuw Davies out_domain:
5213f09354aSHuw Davies kfree(entry);
5223f09354aSHuw Davies out_entry:
5233f09354aSHuw Davies calipso_doi_putdef(doi_def);
5243f09354aSHuw Davies return ret_val;
5253f09354aSHuw Davies #else /* IPv6 */
5263f09354aSHuw Davies return -ENOSYS;
5273f09354aSHuw Davies #endif /* IPv6 */
5283f09354aSHuw Davies }
5293f09354aSHuw Davies
530eda61d32SPaul Moore /*
53102752760SPaul Moore * Security Attribute Functions
53202752760SPaul Moore */
53302752760SPaul Moore
5344b8feff2SPaul Moore #define _CM_F_NONE 0x00000000
5354b8feff2SPaul Moore #define _CM_F_ALLOC 0x00000001
536d960a618SPaul Moore #define _CM_F_WALK 0x00000002
5374b8feff2SPaul Moore
5384b8feff2SPaul Moore /**
5394fbe63d1SPaul Moore * _netlbl_catmap_getnode - Get a individual node from a catmap
5404b8feff2SPaul Moore * @catmap: pointer to the category bitmap
5414b8feff2SPaul Moore * @offset: the requested offset
5424b8feff2SPaul Moore * @cm_flags: catmap flags, see _CM_F_*
5434b8feff2SPaul Moore * @gfp_flags: memory allocation flags
5444b8feff2SPaul Moore *
5454b8feff2SPaul Moore * Description:
546d960a618SPaul Moore * Iterate through the catmap looking for the node associated with @offset.
547d960a618SPaul Moore * If the _CM_F_ALLOC flag is set in @cm_flags and there is no associated node,
548d960a618SPaul Moore * one will be created and inserted into the catmap. If the _CM_F_WALK flag is
549d960a618SPaul Moore * set in @cm_flags and there is no associated node, the next highest node will
550d960a618SPaul Moore * be returned. Returns a pointer to the node on success, NULL on failure.
5514b8feff2SPaul Moore *
5524b8feff2SPaul Moore */
_netlbl_catmap_getnode(struct netlbl_lsm_catmap ** catmap,u32 offset,unsigned int cm_flags,gfp_t gfp_flags)5534fbe63d1SPaul Moore static struct netlbl_lsm_catmap *_netlbl_catmap_getnode(
5544fbe63d1SPaul Moore struct netlbl_lsm_catmap **catmap,
5554b8feff2SPaul Moore u32 offset,
5564b8feff2SPaul Moore unsigned int cm_flags,
5574b8feff2SPaul Moore gfp_t gfp_flags)
5584b8feff2SPaul Moore {
5594fbe63d1SPaul Moore struct netlbl_lsm_catmap *iter = *catmap;
5604fbe63d1SPaul Moore struct netlbl_lsm_catmap *prev = NULL;
5614b8feff2SPaul Moore
562d960a618SPaul Moore if (iter == NULL)
5634fbe63d1SPaul Moore goto catmap_getnode_alloc;
564d960a618SPaul Moore if (offset < iter->startbit)
5654fbe63d1SPaul Moore goto catmap_getnode_walk;
5664b8feff2SPaul Moore while (iter && offset >= (iter->startbit + NETLBL_CATMAP_SIZE)) {
5674b8feff2SPaul Moore prev = iter;
5684b8feff2SPaul Moore iter = iter->next;
5694b8feff2SPaul Moore }
5704b8feff2SPaul Moore if (iter == NULL || offset < iter->startbit)
5714fbe63d1SPaul Moore goto catmap_getnode_walk;
5724b8feff2SPaul Moore
5734b8feff2SPaul Moore return iter;
5744b8feff2SPaul Moore
5754fbe63d1SPaul Moore catmap_getnode_walk:
576d960a618SPaul Moore if (cm_flags & _CM_F_WALK)
577d960a618SPaul Moore return iter;
5784fbe63d1SPaul Moore catmap_getnode_alloc:
5794b8feff2SPaul Moore if (!(cm_flags & _CM_F_ALLOC))
5804b8feff2SPaul Moore return NULL;
5814b8feff2SPaul Moore
5824fbe63d1SPaul Moore iter = netlbl_catmap_alloc(gfp_flags);
5834b8feff2SPaul Moore if (iter == NULL)
5844b8feff2SPaul Moore return NULL;
5854b8feff2SPaul Moore iter->startbit = offset & ~(NETLBL_CATMAP_SIZE - 1);
5864b8feff2SPaul Moore
5874b8feff2SPaul Moore if (prev == NULL) {
5884b8feff2SPaul Moore iter->next = *catmap;
5894b8feff2SPaul Moore *catmap = iter;
5904b8feff2SPaul Moore } else {
5914b8feff2SPaul Moore iter->next = prev->next;
5924b8feff2SPaul Moore prev->next = iter;
5934b8feff2SPaul Moore }
5944b8feff2SPaul Moore
5954b8feff2SPaul Moore return iter;
5964b8feff2SPaul Moore }
5974b8feff2SPaul Moore
59802752760SPaul Moore /**
5994fbe63d1SPaul Moore * netlbl_catmap_walk - Walk a LSM secattr catmap looking for a bit
60002752760SPaul Moore * @catmap: the category bitmap
60102752760SPaul Moore * @offset: the offset to start searching at, in bits
60202752760SPaul Moore *
60302752760SPaul Moore * Description:
60402752760SPaul Moore * This function walks a LSM secattr category bitmap starting at @offset and
60502752760SPaul Moore * returns the spot of the first set bit or -ENOENT if no bits are set.
60602752760SPaul Moore *
60702752760SPaul Moore */
netlbl_catmap_walk(struct netlbl_lsm_catmap * catmap,u32 offset)6084fbe63d1SPaul Moore int netlbl_catmap_walk(struct netlbl_lsm_catmap *catmap, u32 offset)
60902752760SPaul Moore {
61056fcd40fSColin Ian King struct netlbl_lsm_catmap *iter;
611d960a618SPaul Moore u32 idx;
612d960a618SPaul Moore u32 bit;
61323c5ae6dSGeorge Guo u64 bitmap;
61402752760SPaul Moore
6154fbe63d1SPaul Moore iter = _netlbl_catmap_getnode(&catmap, offset, _CM_F_WALK, 0);
61602752760SPaul Moore if (iter == NULL)
61702752760SPaul Moore return -ENOENT;
618d960a618SPaul Moore if (offset > iter->startbit) {
619d960a618SPaul Moore offset -= iter->startbit;
620d960a618SPaul Moore idx = offset / NETLBL_CATMAP_MAPSIZE;
621d960a618SPaul Moore bit = offset % NETLBL_CATMAP_MAPSIZE;
62202752760SPaul Moore } else {
623d960a618SPaul Moore idx = 0;
624d960a618SPaul Moore bit = 0;
62502752760SPaul Moore }
626d960a618SPaul Moore bitmap = iter->bitmap[idx] >> bit;
62702752760SPaul Moore
62802752760SPaul Moore for (;;) {
62902752760SPaul Moore if (bitmap != 0) {
63002752760SPaul Moore while ((bitmap & NETLBL_CATMAP_BIT) == 0) {
63102752760SPaul Moore bitmap >>= 1;
632d960a618SPaul Moore bit++;
63302752760SPaul Moore }
63402752760SPaul Moore return iter->startbit +
635d960a618SPaul Moore (NETLBL_CATMAP_MAPSIZE * idx) + bit;
63602752760SPaul Moore }
637d960a618SPaul Moore if (++idx >= NETLBL_CATMAP_MAPCNT) {
63802752760SPaul Moore if (iter->next != NULL) {
63902752760SPaul Moore iter = iter->next;
640d960a618SPaul Moore idx = 0;
64102752760SPaul Moore } else
64202752760SPaul Moore return -ENOENT;
64302752760SPaul Moore }
644d960a618SPaul Moore bitmap = iter->bitmap[idx];
645d960a618SPaul Moore bit = 0;
64602752760SPaul Moore }
64702752760SPaul Moore
64802752760SPaul Moore return -ENOENT;
64902752760SPaul Moore }
650ceba1832SHuw Davies EXPORT_SYMBOL(netlbl_catmap_walk);
65102752760SPaul Moore
65202752760SPaul Moore /**
6534fbe63d1SPaul Moore * netlbl_catmap_walkrng - Find the end of a string of set bits
65402752760SPaul Moore * @catmap: the category bitmap
65502752760SPaul Moore * @offset: the offset to start searching at, in bits
65602752760SPaul Moore *
65702752760SPaul Moore * Description:
65802752760SPaul Moore * This function walks a LSM secattr category bitmap starting at @offset and
65902752760SPaul Moore * returns the spot of the first cleared bit or -ENOENT if the offset is past
66002752760SPaul Moore * the end of the bitmap.
66102752760SPaul Moore *
66202752760SPaul Moore */
netlbl_catmap_walkrng(struct netlbl_lsm_catmap * catmap,u32 offset)6634fbe63d1SPaul Moore int netlbl_catmap_walkrng(struct netlbl_lsm_catmap *catmap, u32 offset)
66402752760SPaul Moore {
6654fbe63d1SPaul Moore struct netlbl_lsm_catmap *iter;
6664fbe63d1SPaul Moore struct netlbl_lsm_catmap *prev = NULL;
667d960a618SPaul Moore u32 idx;
668d960a618SPaul Moore u32 bit;
66923c5ae6dSGeorge Guo u64 bitmask;
67023c5ae6dSGeorge Guo u64 bitmap;
67102752760SPaul Moore
6724fbe63d1SPaul Moore iter = _netlbl_catmap_getnode(&catmap, offset, _CM_F_WALK, 0);
67302752760SPaul Moore if (iter == NULL)
67402752760SPaul Moore return -ENOENT;
675d960a618SPaul Moore if (offset > iter->startbit) {
676d960a618SPaul Moore offset -= iter->startbit;
677d960a618SPaul Moore idx = offset / NETLBL_CATMAP_MAPSIZE;
678d960a618SPaul Moore bit = offset % NETLBL_CATMAP_MAPSIZE;
67902752760SPaul Moore } else {
680d960a618SPaul Moore idx = 0;
681d960a618SPaul Moore bit = 0;
68202752760SPaul Moore }
683d960a618SPaul Moore bitmask = NETLBL_CATMAP_BIT << bit;
68402752760SPaul Moore
68502752760SPaul Moore for (;;) {
686d960a618SPaul Moore bitmap = iter->bitmap[idx];
68702752760SPaul Moore while (bitmask != 0 && (bitmap & bitmask) != 0) {
68802752760SPaul Moore bitmask <<= 1;
689d960a618SPaul Moore bit++;
69002752760SPaul Moore }
69102752760SPaul Moore
692d960a618SPaul Moore if (prev && idx == 0 && bit == 0)
693d960a618SPaul Moore return prev->startbit + NETLBL_CATMAP_SIZE - 1;
694d960a618SPaul Moore else if (bitmask != 0)
69502752760SPaul Moore return iter->startbit +
696d960a618SPaul Moore (NETLBL_CATMAP_MAPSIZE * idx) + bit - 1;
697d960a618SPaul Moore else if (++idx >= NETLBL_CATMAP_MAPCNT) {
69802752760SPaul Moore if (iter->next == NULL)
69902752760SPaul Moore return iter->startbit + NETLBL_CATMAP_SIZE - 1;
700d960a618SPaul Moore prev = iter;
70102752760SPaul Moore iter = iter->next;
702d960a618SPaul Moore idx = 0;
70302752760SPaul Moore }
70402752760SPaul Moore bitmask = NETLBL_CATMAP_BIT;
705d960a618SPaul Moore bit = 0;
70602752760SPaul Moore }
70702752760SPaul Moore
70802752760SPaul Moore return -ENOENT;
70902752760SPaul Moore }
71002752760SPaul Moore
71102752760SPaul Moore /**
7124fbe63d1SPaul Moore * netlbl_catmap_getlong - Export an unsigned long bitmap
7134b8feff2SPaul Moore * @catmap: pointer to the category bitmap
7144b8feff2SPaul Moore * @offset: pointer to the requested offset
7154b8feff2SPaul Moore * @bitmap: the exported bitmap
7164b8feff2SPaul Moore *
7174b8feff2SPaul Moore * Description:
7184b8feff2SPaul Moore * Export a bitmap with an offset greater than or equal to @offset and return
7194b8feff2SPaul Moore * it in @bitmap. The @offset must be aligned to an unsigned long and will be
7204b8feff2SPaul Moore * updated on return if different from what was requested; if the catmap is
7214b8feff2SPaul Moore * empty at the requested offset and beyond, the @offset is set to (u32)-1.
72284a57ae9SZheng Yongjun * Returns zero on success, negative values on failure.
7234b8feff2SPaul Moore *
7244b8feff2SPaul Moore */
netlbl_catmap_getlong(struct netlbl_lsm_catmap * catmap,u32 * offset,unsigned long * bitmap)7254fbe63d1SPaul Moore int netlbl_catmap_getlong(struct netlbl_lsm_catmap *catmap,
7264b8feff2SPaul Moore u32 *offset,
7274b8feff2SPaul Moore unsigned long *bitmap)
7284b8feff2SPaul Moore {
7294fbe63d1SPaul Moore struct netlbl_lsm_catmap *iter;
7304b8feff2SPaul Moore u32 off = *offset;
7314b8feff2SPaul Moore u32 idx;
7324b8feff2SPaul Moore
7334b8feff2SPaul Moore /* only allow aligned offsets */
7344b8feff2SPaul Moore if ((off & (BITS_PER_LONG - 1)) != 0)
7354b8feff2SPaul Moore return -EINVAL;
7364b8feff2SPaul Moore
737eead1c2eSPaolo Abeni /* a null catmap is equivalent to an empty one */
738eead1c2eSPaolo Abeni if (!catmap) {
739eead1c2eSPaolo Abeni *offset = (u32)-1;
740eead1c2eSPaolo Abeni return 0;
741eead1c2eSPaolo Abeni }
742eead1c2eSPaolo Abeni
7434b8feff2SPaul Moore if (off < catmap->startbit) {
7444b8feff2SPaul Moore off = catmap->startbit;
7454b8feff2SPaul Moore *offset = off;
7464b8feff2SPaul Moore }
74750b8629aSPaul Moore iter = _netlbl_catmap_getnode(&catmap, off, _CM_F_WALK, 0);
7484b8feff2SPaul Moore if (iter == NULL) {
7494b8feff2SPaul Moore *offset = (u32)-1;
7504b8feff2SPaul Moore return 0;
7514b8feff2SPaul Moore }
7524b8feff2SPaul Moore
7534b8feff2SPaul Moore if (off < iter->startbit) {
75450b8629aSPaul Moore *offset = iter->startbit;
75550b8629aSPaul Moore off = 0;
7564b8feff2SPaul Moore } else
7574b8feff2SPaul Moore off -= iter->startbit;
7584b8feff2SPaul Moore idx = off / NETLBL_CATMAP_MAPSIZE;
75950b8629aSPaul Moore *bitmap = iter->bitmap[idx] >> (off % NETLBL_CATMAP_MAPSIZE);
7604b8feff2SPaul Moore
7614b8feff2SPaul Moore return 0;
7624b8feff2SPaul Moore }
7634b8feff2SPaul Moore
7644b8feff2SPaul Moore /**
7654fbe63d1SPaul Moore * netlbl_catmap_setbit - Set a bit in a LSM secattr catmap
76641c3bd20SPaul Moore * @catmap: pointer to the category bitmap
76702752760SPaul Moore * @bit: the bit to set
76802752760SPaul Moore * @flags: memory allocation flags
76902752760SPaul Moore *
77002752760SPaul Moore * Description:
77102752760SPaul Moore * Set the bit specified by @bit in @catmap. Returns zero on success,
77202752760SPaul Moore * negative values on failure.
77302752760SPaul Moore *
77402752760SPaul Moore */
netlbl_catmap_setbit(struct netlbl_lsm_catmap ** catmap,u32 bit,gfp_t flags)7754fbe63d1SPaul Moore int netlbl_catmap_setbit(struct netlbl_lsm_catmap **catmap,
77602752760SPaul Moore u32 bit,
77702752760SPaul Moore gfp_t flags)
77802752760SPaul Moore {
7794fbe63d1SPaul Moore struct netlbl_lsm_catmap *iter;
7804b8feff2SPaul Moore u32 idx;
78102752760SPaul Moore
7824fbe63d1SPaul Moore iter = _netlbl_catmap_getnode(catmap, bit, _CM_F_ALLOC, flags);
78341c3bd20SPaul Moore if (iter == NULL)
78441c3bd20SPaul Moore return -ENOMEM;
78502752760SPaul Moore
7864b8feff2SPaul Moore bit -= iter->startbit;
7874b8feff2SPaul Moore idx = bit / NETLBL_CATMAP_MAPSIZE;
7884b8feff2SPaul Moore iter->bitmap[idx] |= NETLBL_CATMAP_BIT << (bit % NETLBL_CATMAP_MAPSIZE);
78902752760SPaul Moore
79002752760SPaul Moore return 0;
79102752760SPaul Moore }
792ceba1832SHuw Davies EXPORT_SYMBOL(netlbl_catmap_setbit);
79302752760SPaul Moore
79402752760SPaul Moore /**
7954fbe63d1SPaul Moore * netlbl_catmap_setrng - Set a range of bits in a LSM secattr catmap
79641c3bd20SPaul Moore * @catmap: pointer to the category bitmap
79702752760SPaul Moore * @start: the starting bit
79802752760SPaul Moore * @end: the last bit in the string
79902752760SPaul Moore * @flags: memory allocation flags
80002752760SPaul Moore *
80102752760SPaul Moore * Description:
80202752760SPaul Moore * Set a range of bits, starting at @start and ending with @end. Returns zero
80302752760SPaul Moore * on success, negative values on failure.
80402752760SPaul Moore *
80502752760SPaul Moore */
netlbl_catmap_setrng(struct netlbl_lsm_catmap ** catmap,u32 start,u32 end,gfp_t flags)8064fbe63d1SPaul Moore int netlbl_catmap_setrng(struct netlbl_lsm_catmap **catmap,
80702752760SPaul Moore u32 start,
80802752760SPaul Moore u32 end,
80902752760SPaul Moore gfp_t flags)
81002752760SPaul Moore {
8114b8feff2SPaul Moore int rc = 0;
8124b8feff2SPaul Moore u32 spot = start;
81302752760SPaul Moore
8144b8feff2SPaul Moore while (rc == 0 && spot <= end) {
815341e0cb5SJanak Desai if (((spot & (BITS_PER_LONG - 1)) == 0) &&
8164b8feff2SPaul Moore ((end - spot) > BITS_PER_LONG)) {
8174fbe63d1SPaul Moore rc = netlbl_catmap_setlong(catmap,
8184b8feff2SPaul Moore spot,
8194b8feff2SPaul Moore (unsigned long)-1,
8204b8feff2SPaul Moore flags);
8214b8feff2SPaul Moore spot += BITS_PER_LONG;
8224b8feff2SPaul Moore } else
8234fbe63d1SPaul Moore rc = netlbl_catmap_setbit(catmap, spot++, flags);
82402752760SPaul Moore }
82502752760SPaul Moore
8264b8feff2SPaul Moore return rc;
8274b8feff2SPaul Moore }
8284b8feff2SPaul Moore
8294b8feff2SPaul Moore /**
8304fbe63d1SPaul Moore * netlbl_catmap_setlong - Import an unsigned long bitmap
8314b8feff2SPaul Moore * @catmap: pointer to the category bitmap
8324b8feff2SPaul Moore * @offset: offset to the start of the imported bitmap
8334b8feff2SPaul Moore * @bitmap: the bitmap to import
8344b8feff2SPaul Moore * @flags: memory allocation flags
8354b8feff2SPaul Moore *
8364b8feff2SPaul Moore * Description:
8374b8feff2SPaul Moore * Import the bitmap specified in @bitmap into @catmap, using the offset
8384b8feff2SPaul Moore * in @offset. The offset must be aligned to an unsigned long. Returns zero
8394b8feff2SPaul Moore * on success, negative values on failure.
8404b8feff2SPaul Moore *
8414b8feff2SPaul Moore */
netlbl_catmap_setlong(struct netlbl_lsm_catmap ** catmap,u32 offset,unsigned long bitmap,gfp_t flags)8424fbe63d1SPaul Moore int netlbl_catmap_setlong(struct netlbl_lsm_catmap **catmap,
8434b8feff2SPaul Moore u32 offset,
8444b8feff2SPaul Moore unsigned long bitmap,
8454b8feff2SPaul Moore gfp_t flags)
8464b8feff2SPaul Moore {
8474fbe63d1SPaul Moore struct netlbl_lsm_catmap *iter;
8484b8feff2SPaul Moore u32 idx;
8494b8feff2SPaul Moore
8504b8feff2SPaul Moore /* only allow aligned offsets */
8514b8feff2SPaul Moore if ((offset & (BITS_PER_LONG - 1)) != 0)
8524b8feff2SPaul Moore return -EINVAL;
8534b8feff2SPaul Moore
8544fbe63d1SPaul Moore iter = _netlbl_catmap_getnode(catmap, offset, _CM_F_ALLOC, flags);
8554b8feff2SPaul Moore if (iter == NULL)
8564b8feff2SPaul Moore return -ENOMEM;
8574b8feff2SPaul Moore
8584b8feff2SPaul Moore offset -= iter->startbit;
8594b8feff2SPaul Moore idx = offset / NETLBL_CATMAP_MAPSIZE;
86023c5ae6dSGeorge Guo iter->bitmap[idx] |= (u64)bitmap
861b403643dSDmitry Mastykin << (offset % NETLBL_CATMAP_MAPSIZE);
8624b8feff2SPaul Moore
8634b8feff2SPaul Moore return 0;
86402752760SPaul Moore }
86502752760SPaul Moore
8663faa8f98SHuw Davies /* Bitmap functions
8673faa8f98SHuw Davies */
8683faa8f98SHuw Davies
8693faa8f98SHuw Davies /**
8703faa8f98SHuw Davies * netlbl_bitmap_walk - Walk a bitmap looking for a bit
8713faa8f98SHuw Davies * @bitmap: the bitmap
8723faa8f98SHuw Davies * @bitmap_len: length in bits
8733faa8f98SHuw Davies * @offset: starting offset
8743faa8f98SHuw Davies * @state: if non-zero, look for a set (1) bit else look for a cleared (0) bit
8753faa8f98SHuw Davies *
8763faa8f98SHuw Davies * Description:
8773faa8f98SHuw Davies * Starting at @offset, walk the bitmap from left to right until either the
8783faa8f98SHuw Davies * desired bit is found or we reach the end. Return the bit offset, -1 if
8799ff74d77SZhengchao Shao * not found.
8803faa8f98SHuw Davies */
netlbl_bitmap_walk(const unsigned char * bitmap,u32 bitmap_len,u32 offset,u8 state)8813faa8f98SHuw Davies int netlbl_bitmap_walk(const unsigned char *bitmap, u32 bitmap_len,
8823faa8f98SHuw Davies u32 offset, u8 state)
8833faa8f98SHuw Davies {
8843faa8f98SHuw Davies u32 bit_spot;
8853faa8f98SHuw Davies u32 byte_offset;
8863faa8f98SHuw Davies unsigned char bitmask;
8873faa8f98SHuw Davies unsigned char byte;
8883faa8f98SHuw Davies
889f22881deSWang Yufen if (offset >= bitmap_len)
890f22881deSWang Yufen return -1;
8913faa8f98SHuw Davies byte_offset = offset / 8;
8923faa8f98SHuw Davies byte = bitmap[byte_offset];
8933faa8f98SHuw Davies bit_spot = offset;
8943faa8f98SHuw Davies bitmask = 0x80 >> (offset % 8);
8953faa8f98SHuw Davies
8963faa8f98SHuw Davies while (bit_spot < bitmap_len) {
8973faa8f98SHuw Davies if ((state && (byte & bitmask) == bitmask) ||
8983faa8f98SHuw Davies (state == 0 && (byte & bitmask) == 0))
8993faa8f98SHuw Davies return bit_spot;
9003faa8f98SHuw Davies
9015578de48SPaul Moore if (++bit_spot >= bitmap_len)
9025578de48SPaul Moore return -1;
9033faa8f98SHuw Davies bitmask >>= 1;
9043faa8f98SHuw Davies if (bitmask == 0) {
9053faa8f98SHuw Davies byte = bitmap[++byte_offset];
9063faa8f98SHuw Davies bitmask = 0x80;
9073faa8f98SHuw Davies }
9083faa8f98SHuw Davies }
9093faa8f98SHuw Davies
9103faa8f98SHuw Davies return -1;
9113faa8f98SHuw Davies }
9123faa8f98SHuw Davies EXPORT_SYMBOL(netlbl_bitmap_walk);
9133faa8f98SHuw Davies
9143faa8f98SHuw Davies /**
9153faa8f98SHuw Davies * netlbl_bitmap_setbit - Sets a single bit in a bitmap
9163faa8f98SHuw Davies * @bitmap: the bitmap
9173faa8f98SHuw Davies * @bit: the bit
9183faa8f98SHuw Davies * @state: if non-zero, set the bit (1) else clear the bit (0)
9193faa8f98SHuw Davies *
9203faa8f98SHuw Davies * Description:
9213faa8f98SHuw Davies * Set a single bit in the bitmask. Returns zero on success, negative values
9223faa8f98SHuw Davies * on error.
9233faa8f98SHuw Davies */
netlbl_bitmap_setbit(unsigned char * bitmap,u32 bit,u8 state)9243faa8f98SHuw Davies void netlbl_bitmap_setbit(unsigned char *bitmap, u32 bit, u8 state)
9253faa8f98SHuw Davies {
9263faa8f98SHuw Davies u32 byte_spot;
9273faa8f98SHuw Davies u8 bitmask;
9283faa8f98SHuw Davies
9293faa8f98SHuw Davies /* gcc always rounds to zero when doing integer division */
9303faa8f98SHuw Davies byte_spot = bit / 8;
9313faa8f98SHuw Davies bitmask = 0x80 >> (bit % 8);
9323faa8f98SHuw Davies if (state)
9333faa8f98SHuw Davies bitmap[byte_spot] |= bitmask;
9343faa8f98SHuw Davies else
9353faa8f98SHuw Davies bitmap[byte_spot] &= ~bitmask;
9363faa8f98SHuw Davies }
9373faa8f98SHuw Davies EXPORT_SYMBOL(netlbl_bitmap_setbit);
9383faa8f98SHuw Davies
93902752760SPaul Moore /*
940d15c345fSPaul Moore * LSM Functions
941d15c345fSPaul Moore */
942d15c345fSPaul Moore
943d15c345fSPaul Moore /**
94423bcdc1aSPaul Moore * netlbl_enabled - Determine if the NetLabel subsystem is enabled
94523bcdc1aSPaul Moore *
94623bcdc1aSPaul Moore * Description:
94723bcdc1aSPaul Moore * The LSM can use this function to determine if it should use NetLabel
94823bcdc1aSPaul Moore * security attributes in it's enforcement mechanism. Currently, NetLabel is
94923bcdc1aSPaul Moore * considered to be enabled when it's configuration contains a valid setup for
95023bcdc1aSPaul Moore * at least one labeled protocol (i.e. NetLabel can understand incoming
95123bcdc1aSPaul Moore * labeled packets of at least one type); otherwise NetLabel is considered to
95223bcdc1aSPaul Moore * be disabled.
95323bcdc1aSPaul Moore *
95423bcdc1aSPaul Moore */
netlbl_enabled(void)95523bcdc1aSPaul Moore int netlbl_enabled(void)
95623bcdc1aSPaul Moore {
95723bcdc1aSPaul Moore /* At some point we probably want to expose this mechanism to the user
95823bcdc1aSPaul Moore * as well so that admins can toggle NetLabel regardless of the
95923bcdc1aSPaul Moore * configuration */
960c783f1ceSPaul Moore return (atomic_read(&netlabel_mgmt_protocount) > 0);
96123bcdc1aSPaul Moore }
96223bcdc1aSPaul Moore
96323bcdc1aSPaul Moore /**
964389fb800SPaul Moore * netlbl_sock_setattr - Label a socket using the correct protocol
965ba6ff9f2SPaul Moore * @sk: the socket to label
966389fb800SPaul Moore * @family: protocol family
967d15c345fSPaul Moore * @secattr: the security attributes
968*8ec9897eSDavide Caratti * @sk_locked: true if caller holds the socket lock
969d15c345fSPaul Moore *
970d15c345fSPaul Moore * Description:
971d15c345fSPaul Moore * Attach the correct label to the given socket using the security attributes
972ba6ff9f2SPaul Moore * specified in @secattr. This function requires exclusive access to @sk,
973ba6ff9f2SPaul Moore * which means it either needs to be in the process of being created or locked.
97463c41688SPaul Moore * Returns zero on success, -EDESTADDRREQ if the domain is configured to use
97563c41688SPaul Moore * network address selectors (can't blindly label the socket), and negative
97663c41688SPaul Moore * values on all other failures.
977d15c345fSPaul Moore *
978d15c345fSPaul Moore */
netlbl_sock_setattr(struct sock * sk,u16 family,const struct netlbl_lsm_secattr * secattr,bool sk_locked)979ba6ff9f2SPaul Moore int netlbl_sock_setattr(struct sock *sk,
980389fb800SPaul Moore u16 family,
981*8ec9897eSDavide Caratti const struct netlbl_lsm_secattr *secattr,
982*8ec9897eSDavide Caratti bool sk_locked)
983d15c345fSPaul Moore {
984389fb800SPaul Moore int ret_val;
985d15c345fSPaul Moore struct netlbl_dom_map *dom_entry;
986d15c345fSPaul Moore
987d15c345fSPaul Moore rcu_read_lock();
9888f18e675SHuw Davies dom_entry = netlbl_domhsh_getentry(secattr->domain, family);
989389fb800SPaul Moore if (dom_entry == NULL) {
990389fb800SPaul Moore ret_val = -ENOENT;
991d15c345fSPaul Moore goto socket_setattr_return;
992389fb800SPaul Moore }
993389fb800SPaul Moore switch (family) {
994389fb800SPaul Moore case AF_INET:
9956a8b7f0cSPaul Moore switch (dom_entry->def.type) {
99663c41688SPaul Moore case NETLBL_NLTYPE_ADDRSELECT:
99763c41688SPaul Moore ret_val = -EDESTADDRREQ;
99863c41688SPaul Moore break;
999d15c345fSPaul Moore case NETLBL_NLTYPE_CIPSOV4:
1000ba6ff9f2SPaul Moore ret_val = cipso_v4_sock_setattr(sk,
10016a8b7f0cSPaul Moore dom_entry->def.cipso,
1002*8ec9897eSDavide Caratti secattr, sk_locked);
1003d15c345fSPaul Moore break;
1004d15c345fSPaul Moore case NETLBL_NLTYPE_UNLABELED:
1005d15c345fSPaul Moore ret_val = 0;
1006d15c345fSPaul Moore break;
1007d15c345fSPaul Moore default:
1008d15c345fSPaul Moore ret_val = -ENOENT;
1009d15c345fSPaul Moore }
1010389fb800SPaul Moore break;
1011dfd56b8bSEric Dumazet #if IS_ENABLED(CONFIG_IPV6)
1012389fb800SPaul Moore case AF_INET6:
1013ceba1832SHuw Davies switch (dom_entry->def.type) {
1014ceba1832SHuw Davies case NETLBL_NLTYPE_ADDRSELECT:
1015ceba1832SHuw Davies ret_val = -EDESTADDRREQ;
1016ceba1832SHuw Davies break;
1017ceba1832SHuw Davies case NETLBL_NLTYPE_CALIPSO:
1018ceba1832SHuw Davies ret_val = calipso_sock_setattr(sk,
1019ceba1832SHuw Davies dom_entry->def.calipso,
1020ceba1832SHuw Davies secattr);
1021ceba1832SHuw Davies break;
1022ceba1832SHuw Davies case NETLBL_NLTYPE_UNLABELED:
1023389fb800SPaul Moore ret_val = 0;
1024389fb800SPaul Moore break;
1025ceba1832SHuw Davies default:
1026ceba1832SHuw Davies ret_val = -ENOENT;
1027ceba1832SHuw Davies }
1028ceba1832SHuw Davies break;
1029389fb800SPaul Moore #endif /* IPv6 */
1030389fb800SPaul Moore default:
1031389fb800SPaul Moore ret_val = -EPROTONOSUPPORT;
1032389fb800SPaul Moore }
1033d15c345fSPaul Moore
1034d15c345fSPaul Moore socket_setattr_return:
1035d15c345fSPaul Moore rcu_read_unlock();
1036d15c345fSPaul Moore return ret_val;
1037d15c345fSPaul Moore }
1038d15c345fSPaul Moore
1039d15c345fSPaul Moore /**
1040014ab19aSPaul Moore * netlbl_sock_delattr - Delete all the NetLabel labels on a socket
1041014ab19aSPaul Moore * @sk: the socket
1042014ab19aSPaul Moore *
1043014ab19aSPaul Moore * Description:
1044014ab19aSPaul Moore * Remove all the NetLabel labeling from @sk. The caller is responsible for
1045014ab19aSPaul Moore * ensuring that @sk is locked.
1046014ab19aSPaul Moore *
1047014ab19aSPaul Moore */
netlbl_sock_delattr(struct sock * sk)1048014ab19aSPaul Moore void netlbl_sock_delattr(struct sock *sk)
1049014ab19aSPaul Moore {
10500e0e3677SPaul Moore switch (sk->sk_family) {
10510e0e3677SPaul Moore case AF_INET:
1052014ab19aSPaul Moore cipso_v4_sock_delattr(sk);
10530e0e3677SPaul Moore break;
1054ceba1832SHuw Davies #if IS_ENABLED(CONFIG_IPV6)
1055ceba1832SHuw Davies case AF_INET6:
1056ceba1832SHuw Davies calipso_sock_delattr(sk);
1057ceba1832SHuw Davies break;
1058ceba1832SHuw Davies #endif /* IPv6 */
10590e0e3677SPaul Moore }
1060014ab19aSPaul Moore }
1061014ab19aSPaul Moore
1062014ab19aSPaul Moore /**
106314a72f53SPaul Moore * netlbl_sock_getattr - Determine the security attributes of a sock
106414a72f53SPaul Moore * @sk: the sock
106514a72f53SPaul Moore * @secattr: the security attributes
106614a72f53SPaul Moore *
106714a72f53SPaul Moore * Description:
10688cc44579SPaul Moore * Examines the given sock to see if any NetLabel style labeling has been
106914a72f53SPaul Moore * applied to the sock, if so it parses the socket label and returns the
107014a72f53SPaul Moore * security attributes in @secattr. Returns zero on success, negative values
107114a72f53SPaul Moore * on failure.
107214a72f53SPaul Moore *
107314a72f53SPaul Moore */
netlbl_sock_getattr(struct sock * sk,struct netlbl_lsm_secattr * secattr)1074389fb800SPaul Moore int netlbl_sock_getattr(struct sock *sk,
1075389fb800SPaul Moore struct netlbl_lsm_secattr *secattr)
107614a72f53SPaul Moore {
1077389fb800SPaul Moore int ret_val;
1078389fb800SPaul Moore
1079389fb800SPaul Moore switch (sk->sk_family) {
1080389fb800SPaul Moore case AF_INET:
1081389fb800SPaul Moore ret_val = cipso_v4_sock_getattr(sk, secattr);
1082389fb800SPaul Moore break;
1083dfd56b8bSEric Dumazet #if IS_ENABLED(CONFIG_IPV6)
1084389fb800SPaul Moore case AF_INET6:
1085ceba1832SHuw Davies ret_val = calipso_sock_getattr(sk, secattr);
1086389fb800SPaul Moore break;
1087389fb800SPaul Moore #endif /* IPv6 */
1088389fb800SPaul Moore default:
1089389fb800SPaul Moore ret_val = -EPROTONOSUPPORT;
1090389fb800SPaul Moore }
1091389fb800SPaul Moore
1092389fb800SPaul Moore return ret_val;
109314a72f53SPaul Moore }
109414a72f53SPaul Moore
109514a72f53SPaul Moore /**
1096*8ec9897eSDavide Caratti * netlbl_sk_lock_check - Check if the socket lock has been acquired.
1097*8ec9897eSDavide Caratti * @sk: the socket to be checked
1098*8ec9897eSDavide Caratti *
1099*8ec9897eSDavide Caratti * Return: true if socket @sk is locked or if lock debugging is disabled at
1100*8ec9897eSDavide Caratti * runtime or compile-time; false otherwise
1101*8ec9897eSDavide Caratti *
1102*8ec9897eSDavide Caratti */
1103*8ec9897eSDavide Caratti #ifdef CONFIG_LOCKDEP
netlbl_sk_lock_check(struct sock * sk)1104*8ec9897eSDavide Caratti bool netlbl_sk_lock_check(struct sock *sk)
1105*8ec9897eSDavide Caratti {
1106*8ec9897eSDavide Caratti if (debug_locks)
1107*8ec9897eSDavide Caratti return lockdep_sock_is_held(sk);
1108*8ec9897eSDavide Caratti return true;
1109*8ec9897eSDavide Caratti }
1110*8ec9897eSDavide Caratti #else
netlbl_sk_lock_check(struct sock * sk)1111*8ec9897eSDavide Caratti bool netlbl_sk_lock_check(struct sock *sk)
1112*8ec9897eSDavide Caratti {
1113*8ec9897eSDavide Caratti return true;
1114*8ec9897eSDavide Caratti }
1115*8ec9897eSDavide Caratti #endif
1116*8ec9897eSDavide Caratti
1117*8ec9897eSDavide Caratti /**
1118014ab19aSPaul Moore * netlbl_conn_setattr - Label a connected socket using the correct protocol
1119014ab19aSPaul Moore * @sk: the socket to label
1120014ab19aSPaul Moore * @addr: the destination address
1121014ab19aSPaul Moore * @secattr: the security attributes
1122014ab19aSPaul Moore *
1123014ab19aSPaul Moore * Description:
1124014ab19aSPaul Moore * Attach the correct label to the given connected socket using the security
1125014ab19aSPaul Moore * attributes specified in @secattr. The caller is responsible for ensuring
1126014ab19aSPaul Moore * that @sk is locked. Returns zero on success, negative values on failure.
1127014ab19aSPaul Moore *
1128014ab19aSPaul Moore */
netlbl_conn_setattr(struct sock * sk,struct sockaddr * addr,const struct netlbl_lsm_secattr * secattr)1129014ab19aSPaul Moore int netlbl_conn_setattr(struct sock *sk,
1130014ab19aSPaul Moore struct sockaddr *addr,
1131014ab19aSPaul Moore const struct netlbl_lsm_secattr *secattr)
1132014ab19aSPaul Moore {
1133014ab19aSPaul Moore int ret_val;
1134014ab19aSPaul Moore struct sockaddr_in *addr4;
1135ceba1832SHuw Davies #if IS_ENABLED(CONFIG_IPV6)
1136ceba1832SHuw Davies struct sockaddr_in6 *addr6;
1137ceba1832SHuw Davies #endif
11386a8b7f0cSPaul Moore struct netlbl_dommap_def *entry;
1139014ab19aSPaul Moore
1140014ab19aSPaul Moore rcu_read_lock();
1141014ab19aSPaul Moore switch (addr->sa_family) {
1142014ab19aSPaul Moore case AF_INET:
1143014ab19aSPaul Moore addr4 = (struct sockaddr_in *)addr;
11446a8b7f0cSPaul Moore entry = netlbl_domhsh_getentry_af4(secattr->domain,
1145014ab19aSPaul Moore addr4->sin_addr.s_addr);
11466a8b7f0cSPaul Moore if (entry == NULL) {
1147014ab19aSPaul Moore ret_val = -ENOENT;
1148014ab19aSPaul Moore goto conn_setattr_return;
1149014ab19aSPaul Moore }
11506a8b7f0cSPaul Moore switch (entry->type) {
1151014ab19aSPaul Moore case NETLBL_NLTYPE_CIPSOV4:
1152014ab19aSPaul Moore ret_val = cipso_v4_sock_setattr(sk,
1153*8ec9897eSDavide Caratti entry->cipso, secattr,
1154*8ec9897eSDavide Caratti netlbl_sk_lock_check(sk));
1155014ab19aSPaul Moore break;
1156014ab19aSPaul Moore case NETLBL_NLTYPE_UNLABELED:
1157014ab19aSPaul Moore /* just delete the protocols we support for right now
1158014ab19aSPaul Moore * but we could remove other protocols if needed */
1159ceba1832SHuw Davies netlbl_sock_delattr(sk);
1160014ab19aSPaul Moore ret_val = 0;
1161014ab19aSPaul Moore break;
1162014ab19aSPaul Moore default:
1163014ab19aSPaul Moore ret_val = -ENOENT;
1164014ab19aSPaul Moore }
1165014ab19aSPaul Moore break;
1166dfd56b8bSEric Dumazet #if IS_ENABLED(CONFIG_IPV6)
1167014ab19aSPaul Moore case AF_INET6:
1168ceba1832SHuw Davies addr6 = (struct sockaddr_in6 *)addr;
1169ceba1832SHuw Davies entry = netlbl_domhsh_getentry_af6(secattr->domain,
1170ceba1832SHuw Davies &addr6->sin6_addr);
1171ceba1832SHuw Davies if (entry == NULL) {
1172ceba1832SHuw Davies ret_val = -ENOENT;
1173ceba1832SHuw Davies goto conn_setattr_return;
1174ceba1832SHuw Davies }
1175ceba1832SHuw Davies switch (entry->type) {
1176ceba1832SHuw Davies case NETLBL_NLTYPE_CALIPSO:
1177ceba1832SHuw Davies ret_val = calipso_sock_setattr(sk,
1178ceba1832SHuw Davies entry->calipso, secattr);
1179ceba1832SHuw Davies break;
1180ceba1832SHuw Davies case NETLBL_NLTYPE_UNLABELED:
1181ceba1832SHuw Davies /* just delete the protocols we support for right now
1182ceba1832SHuw Davies * but we could remove other protocols if needed */
1183ceba1832SHuw Davies netlbl_sock_delattr(sk);
1184014ab19aSPaul Moore ret_val = 0;
1185014ab19aSPaul Moore break;
1186ceba1832SHuw Davies default:
1187ceba1832SHuw Davies ret_val = -ENOENT;
1188ceba1832SHuw Davies }
1189ceba1832SHuw Davies break;
1190014ab19aSPaul Moore #endif /* IPv6 */
1191014ab19aSPaul Moore default:
1192389fb800SPaul Moore ret_val = -EPROTONOSUPPORT;
1193014ab19aSPaul Moore }
1194014ab19aSPaul Moore
1195014ab19aSPaul Moore conn_setattr_return:
1196014ab19aSPaul Moore rcu_read_unlock();
1197014ab19aSPaul Moore return ret_val;
1198014ab19aSPaul Moore }
1199014ab19aSPaul Moore
1200014ab19aSPaul Moore /**
1201389fb800SPaul Moore * netlbl_req_setattr - Label a request socket using the correct protocol
1202389fb800SPaul Moore * @req: the request socket to label
1203389fb800SPaul Moore * @secattr: the security attributes
1204389fb800SPaul Moore *
1205389fb800SPaul Moore * Description:
1206389fb800SPaul Moore * Attach the correct label to the given socket using the security attributes
1207389fb800SPaul Moore * specified in @secattr. Returns zero on success, negative values on failure.
1208389fb800SPaul Moore *
1209389fb800SPaul Moore */
netlbl_req_setattr(struct request_sock * req,const struct netlbl_lsm_secattr * secattr)1210389fb800SPaul Moore int netlbl_req_setattr(struct request_sock *req,
1211389fb800SPaul Moore const struct netlbl_lsm_secattr *secattr)
1212389fb800SPaul Moore {
1213389fb800SPaul Moore int ret_val;
12146a8b7f0cSPaul Moore struct netlbl_dommap_def *entry;
1215e1adea92SHuw Davies struct inet_request_sock *ireq = inet_rsk(req);
1216389fb800SPaul Moore
1217389fb800SPaul Moore rcu_read_lock();
1218389fb800SPaul Moore switch (req->rsk_ops->family) {
1219389fb800SPaul Moore case AF_INET:
12206a8b7f0cSPaul Moore entry = netlbl_domhsh_getentry_af4(secattr->domain,
1221e1adea92SHuw Davies ireq->ir_rmt_addr);
12226a8b7f0cSPaul Moore if (entry == NULL) {
1223389fb800SPaul Moore ret_val = -ENOENT;
1224389fb800SPaul Moore goto req_setattr_return;
1225389fb800SPaul Moore }
12266a8b7f0cSPaul Moore switch (entry->type) {
1227389fb800SPaul Moore case NETLBL_NLTYPE_CIPSOV4:
12286a8b7f0cSPaul Moore ret_val = cipso_v4_req_setattr(req,
12296a8b7f0cSPaul Moore entry->cipso, secattr);
1230389fb800SPaul Moore break;
1231389fb800SPaul Moore case NETLBL_NLTYPE_UNLABELED:
1232e1adea92SHuw Davies netlbl_req_delattr(req);
1233389fb800SPaul Moore ret_val = 0;
1234389fb800SPaul Moore break;
1235389fb800SPaul Moore default:
1236389fb800SPaul Moore ret_val = -ENOENT;
1237389fb800SPaul Moore }
1238389fb800SPaul Moore break;
1239dfd56b8bSEric Dumazet #if IS_ENABLED(CONFIG_IPV6)
1240389fb800SPaul Moore case AF_INET6:
1241e1adea92SHuw Davies entry = netlbl_domhsh_getentry_af6(secattr->domain,
1242e1adea92SHuw Davies &ireq->ir_v6_rmt_addr);
1243e1adea92SHuw Davies if (entry == NULL) {
1244e1adea92SHuw Davies ret_val = -ENOENT;
1245e1adea92SHuw Davies goto req_setattr_return;
1246e1adea92SHuw Davies }
1247e1adea92SHuw Davies switch (entry->type) {
1248e1adea92SHuw Davies case NETLBL_NLTYPE_CALIPSO:
1249e1adea92SHuw Davies ret_val = calipso_req_setattr(req,
1250e1adea92SHuw Davies entry->calipso, secattr);
1251e1adea92SHuw Davies break;
1252e1adea92SHuw Davies case NETLBL_NLTYPE_UNLABELED:
1253e1adea92SHuw Davies netlbl_req_delattr(req);
1254389fb800SPaul Moore ret_val = 0;
1255389fb800SPaul Moore break;
1256e1adea92SHuw Davies default:
1257e1adea92SHuw Davies ret_val = -ENOENT;
1258e1adea92SHuw Davies }
1259e1adea92SHuw Davies break;
1260389fb800SPaul Moore #endif /* IPv6 */
1261389fb800SPaul Moore default:
1262389fb800SPaul Moore ret_val = -EPROTONOSUPPORT;
1263389fb800SPaul Moore }
1264389fb800SPaul Moore
1265389fb800SPaul Moore req_setattr_return:
1266389fb800SPaul Moore rcu_read_unlock();
1267389fb800SPaul Moore return ret_val;
1268389fb800SPaul Moore }
1269389fb800SPaul Moore
1270389fb800SPaul Moore /**
127107feee8fSPaul Moore * netlbl_req_delattr - Delete all the NetLabel labels on a socket
127207feee8fSPaul Moore * @req: the socket
127307feee8fSPaul Moore *
127407feee8fSPaul Moore * Description:
127507feee8fSPaul Moore * Remove all the NetLabel labeling from @req.
127607feee8fSPaul Moore *
127707feee8fSPaul Moore */
netlbl_req_delattr(struct request_sock * req)127807feee8fSPaul Moore void netlbl_req_delattr(struct request_sock *req)
127907feee8fSPaul Moore {
12800e0e3677SPaul Moore switch (req->rsk_ops->family) {
12810e0e3677SPaul Moore case AF_INET:
128207feee8fSPaul Moore cipso_v4_req_delattr(req);
12830e0e3677SPaul Moore break;
1284e1adea92SHuw Davies #if IS_ENABLED(CONFIG_IPV6)
1285e1adea92SHuw Davies case AF_INET6:
1286e1adea92SHuw Davies calipso_req_delattr(req);
1287e1adea92SHuw Davies break;
1288e1adea92SHuw Davies #endif /* IPv6 */
12890e0e3677SPaul Moore }
129007feee8fSPaul Moore }
129107feee8fSPaul Moore
129207feee8fSPaul Moore /**
1293948bf85cSPaul Moore * netlbl_skbuff_setattr - Label a packet using the correct protocol
1294948bf85cSPaul Moore * @skb: the packet
1295948bf85cSPaul Moore * @family: protocol family
1296948bf85cSPaul Moore * @secattr: the security attributes
1297948bf85cSPaul Moore *
1298948bf85cSPaul Moore * Description:
1299948bf85cSPaul Moore * Attach the correct label to the given packet using the security attributes
1300948bf85cSPaul Moore * specified in @secattr. Returns zero on success, negative values on failure.
1301948bf85cSPaul Moore *
1302948bf85cSPaul Moore */
netlbl_skbuff_setattr(struct sk_buff * skb,u16 family,const struct netlbl_lsm_secattr * secattr)1303948bf85cSPaul Moore int netlbl_skbuff_setattr(struct sk_buff *skb,
1304948bf85cSPaul Moore u16 family,
1305948bf85cSPaul Moore const struct netlbl_lsm_secattr *secattr)
1306948bf85cSPaul Moore {
1307948bf85cSPaul Moore int ret_val;
1308948bf85cSPaul Moore struct iphdr *hdr4;
13092917f57bSHuw Davies #if IS_ENABLED(CONFIG_IPV6)
13102917f57bSHuw Davies struct ipv6hdr *hdr6;
13112917f57bSHuw Davies #endif
13126a8b7f0cSPaul Moore struct netlbl_dommap_def *entry;
1313948bf85cSPaul Moore
1314948bf85cSPaul Moore rcu_read_lock();
1315948bf85cSPaul Moore switch (family) {
1316948bf85cSPaul Moore case AF_INET:
1317948bf85cSPaul Moore hdr4 = ip_hdr(skb);
13182917f57bSHuw Davies entry = netlbl_domhsh_getentry_af4(secattr->domain,
13192917f57bSHuw Davies hdr4->daddr);
13206a8b7f0cSPaul Moore if (entry == NULL) {
1321948bf85cSPaul Moore ret_val = -ENOENT;
1322948bf85cSPaul Moore goto skbuff_setattr_return;
1323948bf85cSPaul Moore }
13246a8b7f0cSPaul Moore switch (entry->type) {
1325948bf85cSPaul Moore case NETLBL_NLTYPE_CIPSOV4:
13266a8b7f0cSPaul Moore ret_val = cipso_v4_skbuff_setattr(skb, entry->cipso,
1327948bf85cSPaul Moore secattr);
1328948bf85cSPaul Moore break;
1329948bf85cSPaul Moore case NETLBL_NLTYPE_UNLABELED:
1330948bf85cSPaul Moore /* just delete the protocols we support for right now
1331948bf85cSPaul Moore * but we could remove other protocols if needed */
1332948bf85cSPaul Moore ret_val = cipso_v4_skbuff_delattr(skb);
1333948bf85cSPaul Moore break;
1334948bf85cSPaul Moore default:
1335948bf85cSPaul Moore ret_val = -ENOENT;
1336948bf85cSPaul Moore }
1337948bf85cSPaul Moore break;
1338dfd56b8bSEric Dumazet #if IS_ENABLED(CONFIG_IPV6)
1339948bf85cSPaul Moore case AF_INET6:
13402917f57bSHuw Davies hdr6 = ipv6_hdr(skb);
13412917f57bSHuw Davies entry = netlbl_domhsh_getentry_af6(secattr->domain,
13422917f57bSHuw Davies &hdr6->daddr);
13432917f57bSHuw Davies if (entry == NULL) {
13442917f57bSHuw Davies ret_val = -ENOENT;
13452917f57bSHuw Davies goto skbuff_setattr_return;
13462917f57bSHuw Davies }
13472917f57bSHuw Davies switch (entry->type) {
13482917f57bSHuw Davies case NETLBL_NLTYPE_CALIPSO:
13492917f57bSHuw Davies ret_val = calipso_skbuff_setattr(skb, entry->calipso,
13502917f57bSHuw Davies secattr);
13512917f57bSHuw Davies break;
13522917f57bSHuw Davies case NETLBL_NLTYPE_UNLABELED:
13532917f57bSHuw Davies /* just delete the protocols we support for right now
13542917f57bSHuw Davies * but we could remove other protocols if needed */
13552917f57bSHuw Davies ret_val = calipso_skbuff_delattr(skb);
13562917f57bSHuw Davies break;
13572917f57bSHuw Davies default:
13582917f57bSHuw Davies ret_val = -ENOENT;
13592917f57bSHuw Davies }
1360948bf85cSPaul Moore break;
1361948bf85cSPaul Moore #endif /* IPv6 */
1362948bf85cSPaul Moore default:
1363389fb800SPaul Moore ret_val = -EPROTONOSUPPORT;
1364948bf85cSPaul Moore }
1365948bf85cSPaul Moore
1366948bf85cSPaul Moore skbuff_setattr_return:
1367948bf85cSPaul Moore rcu_read_unlock();
1368948bf85cSPaul Moore return ret_val;
1369948bf85cSPaul Moore }
1370948bf85cSPaul Moore
1371948bf85cSPaul Moore /**
1372d15c345fSPaul Moore * netlbl_skbuff_getattr - Determine the security attributes of a packet
1373d15c345fSPaul Moore * @skb: the packet
137475e22910SPaul Moore * @family: protocol family
1375d15c345fSPaul Moore * @secattr: the security attributes
1376d15c345fSPaul Moore *
1377d15c345fSPaul Moore * Description:
1378d15c345fSPaul Moore * Examines the given packet to see if a recognized form of packet labeling
1379d15c345fSPaul Moore * is present, if so it parses the packet label and returns the security
1380d15c345fSPaul Moore * attributes in @secattr. Returns zero on success, negative values on
1381d15c345fSPaul Moore * failure.
1382d15c345fSPaul Moore *
1383d15c345fSPaul Moore */
netlbl_skbuff_getattr(const struct sk_buff * skb,u16 family,struct netlbl_lsm_secattr * secattr)1384d15c345fSPaul Moore int netlbl_skbuff_getattr(const struct sk_buff *skb,
138575e22910SPaul Moore u16 family,
1386d15c345fSPaul Moore struct netlbl_lsm_secattr *secattr)
1387d15c345fSPaul Moore {
138804f81f01SPaul Moore unsigned char *ptr;
138904f81f01SPaul Moore
1390389fb800SPaul Moore switch (family) {
1391389fb800SPaul Moore case AF_INET:
139204f81f01SPaul Moore ptr = cipso_v4_optptr(skb);
139304f81f01SPaul Moore if (ptr && cipso_v4_getattr(ptr, secattr) == 0)
1394d15c345fSPaul Moore return 0;
1395389fb800SPaul Moore break;
1396dfd56b8bSEric Dumazet #if IS_ENABLED(CONFIG_IPV6)
1397389fb800SPaul Moore case AF_INET6:
13982917f57bSHuw Davies ptr = calipso_optptr(skb);
13992917f57bSHuw Davies if (ptr && calipso_getattr(ptr, secattr) == 0)
14002917f57bSHuw Davies return 0;
1401389fb800SPaul Moore break;
1402389fb800SPaul Moore #endif /* IPv6 */
1403389fb800SPaul Moore }
1404d15c345fSPaul Moore
14058cc44579SPaul Moore return netlbl_unlabel_getattr(skb, family, secattr);
1406d15c345fSPaul Moore }
1407d15c345fSPaul Moore
1408d15c345fSPaul Moore /**
1409d15c345fSPaul Moore * netlbl_skbuff_err - Handle a LSM error on a sk_buff
1410d15c345fSPaul Moore * @skb: the packet
1411a04e71f6SHuw Davies * @family: the family
1412d15c345fSPaul Moore * @error: the error code
1413dfaebe98SPaul Moore * @gateway: true if host is acting as a gateway, false otherwise
1414d15c345fSPaul Moore *
1415d15c345fSPaul Moore * Description:
1416d15c345fSPaul Moore * Deal with a LSM problem when handling the packet in @skb, typically this is
1417d15c345fSPaul Moore * a permission denied problem (-EACCES). The correct action is determined
1418d15c345fSPaul Moore * according to the packet's labeling protocol.
1419d15c345fSPaul Moore *
1420d15c345fSPaul Moore */
netlbl_skbuff_err(struct sk_buff * skb,u16 family,int error,int gateway)1421a04e71f6SHuw Davies void netlbl_skbuff_err(struct sk_buff *skb, u16 family, int error, int gateway)
1422d15c345fSPaul Moore {
1423a04e71f6SHuw Davies switch (family) {
1424a04e71f6SHuw Davies case AF_INET:
142504f81f01SPaul Moore if (cipso_v4_optptr(skb))
1426dfaebe98SPaul Moore cipso_v4_error(skb, error, gateway);
1427a04e71f6SHuw Davies break;
1428a04e71f6SHuw Davies }
1429d15c345fSPaul Moore }
1430d15c345fSPaul Moore
1431d15c345fSPaul Moore /**
1432d15c345fSPaul Moore * netlbl_cache_invalidate - Invalidate all of the NetLabel protocol caches
1433d15c345fSPaul Moore *
1434d15c345fSPaul Moore * Description:
1435d15c345fSPaul Moore * For all of the NetLabel protocols that support some form of label mapping
1436d15c345fSPaul Moore * cache, invalidate the cache. Returns zero on success, negative values on
1437d15c345fSPaul Moore * error.
1438d15c345fSPaul Moore *
1439d15c345fSPaul Moore */
netlbl_cache_invalidate(void)1440d15c345fSPaul Moore void netlbl_cache_invalidate(void)
1441d15c345fSPaul Moore {
1442d15c345fSPaul Moore cipso_v4_cache_invalidate();
14434fee5242SHuw Davies #if IS_ENABLED(CONFIG_IPV6)
14444fee5242SHuw Davies calipso_cache_invalidate();
14454fee5242SHuw Davies #endif /* IPv6 */
1446d15c345fSPaul Moore }
1447d15c345fSPaul Moore
1448d15c345fSPaul Moore /**
1449d15c345fSPaul Moore * netlbl_cache_add - Add an entry to a NetLabel protocol cache
1450d15c345fSPaul Moore * @skb: the packet
14514fee5242SHuw Davies * @family: the family
1452d15c345fSPaul Moore * @secattr: the packet's security attributes
1453d15c345fSPaul Moore *
1454d15c345fSPaul Moore * Description:
1455d15c345fSPaul Moore * Add the LSM security attributes for the given packet to the underlying
1456d15c345fSPaul Moore * NetLabel protocol's label mapping cache. Returns zero on success, negative
1457d15c345fSPaul Moore * values on error.
1458d15c345fSPaul Moore *
1459d15c345fSPaul Moore */
netlbl_cache_add(const struct sk_buff * skb,u16 family,const struct netlbl_lsm_secattr * secattr)14604fee5242SHuw Davies int netlbl_cache_add(const struct sk_buff *skb, u16 family,
1461d15c345fSPaul Moore const struct netlbl_lsm_secattr *secattr)
1462d15c345fSPaul Moore {
146304f81f01SPaul Moore unsigned char *ptr;
146404f81f01SPaul Moore
1465701a90baSPaul Moore if ((secattr->flags & NETLBL_SECATTR_CACHE) == 0)
1466d15c345fSPaul Moore return -ENOMSG;
1467d15c345fSPaul Moore
14684fee5242SHuw Davies switch (family) {
14694fee5242SHuw Davies case AF_INET:
147004f81f01SPaul Moore ptr = cipso_v4_optptr(skb);
147104f81f01SPaul Moore if (ptr)
147204f81f01SPaul Moore return cipso_v4_cache_add(ptr, secattr);
14734fee5242SHuw Davies break;
14744fee5242SHuw Davies #if IS_ENABLED(CONFIG_IPV6)
14754fee5242SHuw Davies case AF_INET6:
14764fee5242SHuw Davies ptr = calipso_optptr(skb);
14774fee5242SHuw Davies if (ptr)
14784fee5242SHuw Davies return calipso_cache_add(ptr, secattr);
14794fee5242SHuw Davies break;
14804fee5242SHuw Davies #endif /* IPv6 */
14814fee5242SHuw Davies }
1482d15c345fSPaul Moore return -ENOMSG;
1483d15c345fSPaul Moore }
1484d15c345fSPaul Moore
1485d15c345fSPaul Moore /*
14866c2e8ac0SPaul Moore * Protocol Engine Functions
14876c2e8ac0SPaul Moore */
14886c2e8ac0SPaul Moore
14896c2e8ac0SPaul Moore /**
14906c2e8ac0SPaul Moore * netlbl_audit_start - Start an audit message
14916c2e8ac0SPaul Moore * @type: audit message type
14926c2e8ac0SPaul Moore * @audit_info: NetLabel audit information
14936c2e8ac0SPaul Moore *
14946c2e8ac0SPaul Moore * Description:
14956c2e8ac0SPaul Moore * Start an audit message using the type specified in @type and fill the audit
14966c2e8ac0SPaul Moore * message with some fields common to all NetLabel audit messages. This
14976c2e8ac0SPaul Moore * function should only be used by protocol engines, not LSMs. Returns a
14986c2e8ac0SPaul Moore * pointer to the audit buffer on success, NULL on failure.
14996c2e8ac0SPaul Moore *
15006c2e8ac0SPaul Moore */
netlbl_audit_start(int type,struct netlbl_audit * audit_info)15016c2e8ac0SPaul Moore struct audit_buffer *netlbl_audit_start(int type,
15026c2e8ac0SPaul Moore struct netlbl_audit *audit_info)
15036c2e8ac0SPaul Moore {
15046c2e8ac0SPaul Moore return netlbl_audit_start_common(type, audit_info);
15056c2e8ac0SPaul Moore }
1506cb72d382SHuw Davies EXPORT_SYMBOL(netlbl_audit_start);
15076c2e8ac0SPaul Moore
15086c2e8ac0SPaul Moore /*
1509d15c345fSPaul Moore * Setup Functions
1510d15c345fSPaul Moore */
1511d15c345fSPaul Moore
1512d15c345fSPaul Moore /**
1513d15c345fSPaul Moore * netlbl_init - Initialize NetLabel
1514d15c345fSPaul Moore *
1515d15c345fSPaul Moore * Description:
1516d15c345fSPaul Moore * Perform the required NetLabel initialization before first use.
1517d15c345fSPaul Moore *
1518d15c345fSPaul Moore */
netlbl_init(void)1519d15c345fSPaul Moore static int __init netlbl_init(void)
1520d15c345fSPaul Moore {
1521d15c345fSPaul Moore int ret_val;
1522d15c345fSPaul Moore
1523d15c345fSPaul Moore printk(KERN_INFO "NetLabel: Initializing\n");
1524d15c345fSPaul Moore printk(KERN_INFO "NetLabel: domain hash size = %u\n",
1525d15c345fSPaul Moore (1 << NETLBL_DOMHSH_BITSIZE));
1526bcd5e1a4SPaul Moore printk(KERN_INFO "NetLabel: protocols = UNLABELED CIPSOv4 CALIPSO\n");
1527d15c345fSPaul Moore
1528d15c345fSPaul Moore ret_val = netlbl_domhsh_init(NETLBL_DOMHSH_BITSIZE);
1529d15c345fSPaul Moore if (ret_val != 0)
1530d15c345fSPaul Moore goto init_failure;
1531d15c345fSPaul Moore
15328cc44579SPaul Moore ret_val = netlbl_unlabel_init(NETLBL_UNLHSH_BITSIZE);
15338cc44579SPaul Moore if (ret_val != 0)
15348cc44579SPaul Moore goto init_failure;
15358cc44579SPaul Moore
1536d15c345fSPaul Moore ret_val = netlbl_netlink_init();
1537d15c345fSPaul Moore if (ret_val != 0)
1538d15c345fSPaul Moore goto init_failure;
1539d15c345fSPaul Moore
1540d15c345fSPaul Moore ret_val = netlbl_unlabel_defconf();
1541d15c345fSPaul Moore if (ret_val != 0)
1542d15c345fSPaul Moore goto init_failure;
1543d15c345fSPaul Moore printk(KERN_INFO "NetLabel: unlabeled traffic allowed by default\n");
1544d15c345fSPaul Moore
1545d15c345fSPaul Moore return 0;
1546d15c345fSPaul Moore
1547d15c345fSPaul Moore init_failure:
1548d15c345fSPaul Moore panic("NetLabel: failed to initialize properly (%d)\n", ret_val);
1549d15c345fSPaul Moore }
1550d15c345fSPaul Moore
1551d15c345fSPaul Moore subsys_initcall(netlbl_init);
1552