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
8 * Author: Paul Moore <paul.moore@hp.com>
13 * (c) Copyright Hewlett-Packard Development Company, L.P., 2006
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.
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.
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
31 #include <linux/init.h>
32 #include <linux/types.h>
33 #include <linux/audit.h>
35 #include <net/netlabel.h>
36 #include <net/cipso_ipv4.h>
39 #include "netlabel_domainhash.h"
40 #include "netlabel_unlabeled.h"
41 #include "netlabel_cipso_v4.h"
42 #include "netlabel_user.h"
43 #include "netlabel_mgmt.h"
46 * Configuration Functions
50 * netlbl_cfg_map_del - Remove a NetLabel/LSM domain mapping
51 * @domain: the domain mapping to remove
52 * @audit_info: NetLabel audit information
55 * Removes a NetLabel/LSM domain mapping. A @domain value of NULL causes the
56 * default domain mapping to be removed. Returns zero on success, negative
60 int netlbl_cfg_map_del(const char *domain
, struct netlbl_audit
*audit_info
)
62 return netlbl_domhsh_remove(domain
, audit_info
);
66 * netlbl_cfg_unlbl_add_map - Add an unlabeled NetLabel/LSM domain mapping
67 * @domain: the domain mapping to add
68 * @audit_info: NetLabel audit information
71 * Adds a new unlabeled NetLabel/LSM domain mapping. A @domain value of NULL
72 * causes a new default domain mapping to be added. Returns zero on success,
73 * negative values on failure.
76 int netlbl_cfg_unlbl_add_map(const char *domain
,
77 struct netlbl_audit
*audit_info
)
79 int ret_val
= -ENOMEM
;
80 struct netlbl_dom_map
*entry
;
82 entry
= kzalloc(sizeof(*entry
), GFP_ATOMIC
);
84 goto cfg_unlbl_add_map_failure
;
86 entry
->domain
= kstrdup(domain
, GFP_ATOMIC
);
87 if (entry
->domain
== NULL
)
88 goto cfg_unlbl_add_map_failure
;
90 entry
->type
= NETLBL_NLTYPE_UNLABELED
;
92 ret_val
= netlbl_domhsh_add(entry
, audit_info
);
94 goto cfg_unlbl_add_map_failure
;
98 cfg_unlbl_add_map_failure
:
100 kfree(entry
->domain
);
106 * netlbl_cfg_cipsov4_add - Add a new CIPSOv4 DOI definition
107 * @doi_def: the DOI definition
108 * @audit_info: NetLabel audit information
111 * Add a new CIPSOv4 DOI definition to the NetLabel subsystem. Returns zero on
112 * success, negative values on failure.
115 int netlbl_cfg_cipsov4_add(struct cipso_v4_doi
*doi_def
,
116 struct netlbl_audit
*audit_info
)
119 const char *type_str
;
120 struct audit_buffer
*audit_buf
;
122 ret_val
= cipso_v4_doi_add(doi_def
);
124 audit_buf
= netlbl_audit_start_common(AUDIT_MAC_CIPSOV4_ADD
,
126 if (audit_buf
!= NULL
) {
127 switch (doi_def
->type
) {
128 case CIPSO_V4_MAP_STD
:
131 case CIPSO_V4_MAP_PASS
:
135 type_str
= "(unknown)";
137 audit_log_format(audit_buf
,
138 " cipso_doi=%u cipso_type=%s res=%u",
141 ret_val
== 0 ? 1 : 0);
142 audit_log_end(audit_buf
);
149 * netlbl_cfg_cipsov4_add_map - Add a new CIPSOv4 DOI definition and mapping
150 * @doi_def: the DOI definition
151 * @domain: the domain mapping to add
152 * @audit_info: NetLabel audit information
155 * Add a new CIPSOv4 DOI definition and NetLabel/LSM domain mapping for this
156 * new DOI definition to the NetLabel subsystem. A @domain value of NULL adds
157 * a new default domain mapping. Returns zero on success, negative values on
161 int netlbl_cfg_cipsov4_add_map(struct cipso_v4_doi
*doi_def
,
163 struct netlbl_audit
*audit_info
)
165 int ret_val
= -ENOMEM
;
166 struct netlbl_dom_map
*entry
;
168 entry
= kzalloc(sizeof(*entry
), GFP_ATOMIC
);
170 goto cfg_cipsov4_add_map_failure
;
171 if (domain
!= NULL
) {
172 entry
->domain
= kstrdup(domain
, GFP_ATOMIC
);
173 if (entry
->domain
== NULL
)
174 goto cfg_cipsov4_add_map_failure
;
176 entry
->type
= NETLBL_NLTYPE_CIPSOV4
;
177 entry
->type_def
.cipsov4
= doi_def
;
179 /* Grab a RCU read lock here so nothing happens to the doi_def variable
180 * between adding it to the CIPSOv4 protocol engine and adding a
181 * domain mapping for it. */
184 ret_val
= netlbl_cfg_cipsov4_add(doi_def
, audit_info
);
186 goto cfg_cipsov4_add_map_failure_unlock
;
187 ret_val
= netlbl_domhsh_add(entry
, audit_info
);
189 goto cfg_cipsov4_add_map_failure_remove_doi
;
194 cfg_cipsov4_add_map_failure_remove_doi
:
195 cipso_v4_doi_remove(doi_def
->doi
, audit_info
, netlbl_cipsov4_doi_free
);
196 cfg_cipsov4_add_map_failure_unlock
:
198 cfg_cipsov4_add_map_failure
:
200 kfree(entry
->domain
);
206 * netlbl_cfg_cipsov4_del - Removean existing CIPSOv4 DOI definition
207 * @doi: the CIPSO DOI value
208 * @audit_info: NetLabel audit information
211 * Removes an existing CIPSOv4 DOI definition from the NetLabel subsystem.
212 * Returns zero on success, negative values on failure.
215 int netlbl_cfg_cipsov4_del(u32 doi
, struct netlbl_audit
*audit_info
)
217 return cipso_v4_doi_remove(doi
, audit_info
, netlbl_cipsov4_doi_free
);
221 * Security Attribute Functions
225 * netlbl_secattr_catmap_walk - Walk a LSM secattr catmap looking for a bit
226 * @catmap: the category bitmap
227 * @offset: the offset to start searching at, in bits
230 * This function walks a LSM secattr category bitmap starting at @offset and
231 * returns the spot of the first set bit or -ENOENT if no bits are set.
234 int netlbl_secattr_catmap_walk(struct netlbl_lsm_secattr_catmap
*catmap
,
237 struct netlbl_lsm_secattr_catmap
*iter
= catmap
;
240 NETLBL_CATMAP_MAPTYPE bitmap
;
242 if (offset
> iter
->startbit
) {
243 while (offset
>= (iter
->startbit
+ NETLBL_CATMAP_SIZE
)) {
248 node_idx
= (offset
- iter
->startbit
) / NETLBL_CATMAP_MAPSIZE
;
249 node_bit
= offset
- iter
->startbit
-
250 (NETLBL_CATMAP_MAPSIZE
* node_idx
);
255 bitmap
= iter
->bitmap
[node_idx
] >> node_bit
;
259 while ((bitmap
& NETLBL_CATMAP_BIT
) == 0) {
263 return iter
->startbit
+
264 (NETLBL_CATMAP_MAPSIZE
* node_idx
) + node_bit
;
266 if (++node_idx
>= NETLBL_CATMAP_MAPCNT
) {
267 if (iter
->next
!= NULL
) {
273 bitmap
= iter
->bitmap
[node_idx
];
281 * netlbl_secattr_catmap_walk_rng - Find the end of a string of set bits
282 * @catmap: the category bitmap
283 * @offset: the offset to start searching at, in bits
286 * This function walks a LSM secattr category bitmap starting at @offset and
287 * returns the spot of the first cleared bit or -ENOENT if the offset is past
288 * the end of the bitmap.
291 int netlbl_secattr_catmap_walk_rng(struct netlbl_lsm_secattr_catmap
*catmap
,
294 struct netlbl_lsm_secattr_catmap
*iter
= catmap
;
297 NETLBL_CATMAP_MAPTYPE bitmask
;
298 NETLBL_CATMAP_MAPTYPE bitmap
;
300 if (offset
> iter
->startbit
) {
301 while (offset
>= (iter
->startbit
+ NETLBL_CATMAP_SIZE
)) {
306 node_idx
= (offset
- iter
->startbit
) / NETLBL_CATMAP_MAPSIZE
;
307 node_bit
= offset
- iter
->startbit
-
308 (NETLBL_CATMAP_MAPSIZE
* node_idx
);
313 bitmask
= NETLBL_CATMAP_BIT
<< node_bit
;
316 bitmap
= iter
->bitmap
[node_idx
];
317 while (bitmask
!= 0 && (bitmap
& bitmask
) != 0) {
323 return iter
->startbit
+
324 (NETLBL_CATMAP_MAPSIZE
* node_idx
) +
326 else if (++node_idx
>= NETLBL_CATMAP_MAPCNT
) {
327 if (iter
->next
== NULL
)
328 return iter
->startbit
+ NETLBL_CATMAP_SIZE
- 1;
332 bitmask
= NETLBL_CATMAP_BIT
;
340 * netlbl_secattr_catmap_setbit - Set a bit in a LSM secattr catmap
341 * @catmap: the category bitmap
342 * @bit: the bit to set
343 * @flags: memory allocation flags
346 * Set the bit specified by @bit in @catmap. Returns zero on success,
347 * negative values on failure.
350 int netlbl_secattr_catmap_setbit(struct netlbl_lsm_secattr_catmap
*catmap
,
354 struct netlbl_lsm_secattr_catmap
*iter
= catmap
;
358 while (iter
->next
!= NULL
&&
359 bit
>= (iter
->startbit
+ NETLBL_CATMAP_SIZE
))
361 if (bit
>= (iter
->startbit
+ NETLBL_CATMAP_SIZE
)) {
362 iter
->next
= netlbl_secattr_catmap_alloc(flags
);
363 if (iter
->next
== NULL
)
366 iter
->startbit
= bit
& ~(NETLBL_CATMAP_SIZE
- 1);
369 /* gcc always rounds to zero when doing integer division */
370 node_idx
= (bit
- iter
->startbit
) / NETLBL_CATMAP_MAPSIZE
;
371 node_bit
= bit
- iter
->startbit
- (NETLBL_CATMAP_MAPSIZE
* node_idx
);
372 iter
->bitmap
[node_idx
] |= NETLBL_CATMAP_BIT
<< node_bit
;
378 * netlbl_secattr_catmap_setrng - Set a range of bits in a LSM secattr catmap
379 * @catmap: the category bitmap
380 * @start: the starting bit
381 * @end: the last bit in the string
382 * @flags: memory allocation flags
385 * Set a range of bits, starting at @start and ending with @end. Returns zero
386 * on success, negative values on failure.
389 int netlbl_secattr_catmap_setrng(struct netlbl_lsm_secattr_catmap
*catmap
,
395 struct netlbl_lsm_secattr_catmap
*iter
= catmap
;
399 /* XXX - This could probably be made a bit faster by combining writes
400 * to the catmap instead of setting a single bit each time, but for
401 * right now skipping to the start of the range in the catmap should
402 * be a nice improvement over calling the individual setbit function
403 * repeatedly from a loop. */
405 while (iter
->next
!= NULL
&&
406 start
>= (iter
->startbit
+ NETLBL_CATMAP_SIZE
))
408 iter_max_spot
= iter
->startbit
+ NETLBL_CATMAP_SIZE
;
410 for (spot
= start
; spot
<= end
&& ret_val
== 0; spot
++) {
411 if (spot
>= iter_max_spot
&& iter
->next
!= NULL
) {
413 iter_max_spot
= iter
->startbit
+ NETLBL_CATMAP_SIZE
;
415 ret_val
= netlbl_secattr_catmap_setbit(iter
, spot
, GFP_ATOMIC
);
426 * netlbl_enabled - Determine if the NetLabel subsystem is enabled
429 * The LSM can use this function to determine if it should use NetLabel
430 * security attributes in it's enforcement mechanism. Currently, NetLabel is
431 * considered to be enabled when it's configuration contains a valid setup for
432 * at least one labeled protocol (i.e. NetLabel can understand incoming
433 * labeled packets of at least one type); otherwise NetLabel is considered to
437 int netlbl_enabled(void)
439 /* At some point we probably want to expose this mechanism to the user
440 * as well so that admins can toggle NetLabel regardless of the
442 return (netlbl_mgmt_protocount_value() > 0 ? 1 : 0);
446 * netlbl_socket_setattr - Label a socket using the correct protocol
447 * @sk: the socket to label
448 * @secattr: the security attributes
451 * Attach the correct label to the given socket using the security attributes
452 * specified in @secattr. This function requires exclusive access to @sk,
453 * which means it either needs to be in the process of being created or locked.
454 * Returns zero on success, negative values on failure.
457 int netlbl_sock_setattr(struct sock
*sk
,
458 const struct netlbl_lsm_secattr
*secattr
)
460 int ret_val
= -ENOENT
;
461 struct netlbl_dom_map
*dom_entry
;
464 dom_entry
= netlbl_domhsh_getentry(secattr
->domain
);
465 if (dom_entry
== NULL
)
466 goto socket_setattr_return
;
467 switch (dom_entry
->type
) {
468 case NETLBL_NLTYPE_CIPSOV4
:
469 ret_val
= cipso_v4_sock_setattr(sk
,
470 dom_entry
->type_def
.cipsov4
,
473 case NETLBL_NLTYPE_UNLABELED
:
480 socket_setattr_return
:
486 * netlbl_sock_getattr - Determine the security attributes of a sock
488 * @secattr: the security attributes
491 * Examines the given sock to see any NetLabel style labeling has been
492 * applied to the sock, if so it parses the socket label and returns the
493 * security attributes in @secattr. Returns zero on success, negative values
497 int netlbl_sock_getattr(struct sock
*sk
, struct netlbl_lsm_secattr
*secattr
)
501 ret_val
= cipso_v4_sock_getattr(sk
, secattr
);
505 return netlbl_unlabel_getattr(secattr
);
509 * netlbl_skbuff_getattr - Determine the security attributes of a packet
511 * @secattr: the security attributes
514 * Examines the given packet to see if a recognized form of packet labeling
515 * is present, if so it parses the packet label and returns the security
516 * attributes in @secattr. Returns zero on success, negative values on
520 int netlbl_skbuff_getattr(const struct sk_buff
*skb
,
521 struct netlbl_lsm_secattr
*secattr
)
523 if (CIPSO_V4_OPTEXIST(skb
) &&
524 cipso_v4_skbuff_getattr(skb
, secattr
) == 0)
527 return netlbl_unlabel_getattr(secattr
);
531 * netlbl_skbuff_err - Handle a LSM error on a sk_buff
533 * @error: the error code
536 * Deal with a LSM problem when handling the packet in @skb, typically this is
537 * a permission denied problem (-EACCES). The correct action is determined
538 * according to the packet's labeling protocol.
541 void netlbl_skbuff_err(struct sk_buff
*skb
, int error
)
543 if (CIPSO_V4_OPTEXIST(skb
))
544 cipso_v4_error(skb
, error
, 0);
548 * netlbl_cache_invalidate - Invalidate all of the NetLabel protocol caches
551 * For all of the NetLabel protocols that support some form of label mapping
552 * cache, invalidate the cache. Returns zero on success, negative values on
556 void netlbl_cache_invalidate(void)
558 cipso_v4_cache_invalidate();
562 * netlbl_cache_add - Add an entry to a NetLabel protocol cache
564 * @secattr: the packet's security attributes
567 * Add the LSM security attributes for the given packet to the underlying
568 * NetLabel protocol's label mapping cache. Returns zero on success, negative
572 int netlbl_cache_add(const struct sk_buff
*skb
,
573 const struct netlbl_lsm_secattr
*secattr
)
575 if ((secattr
->flags
& NETLBL_SECATTR_CACHE
) == 0)
578 if (CIPSO_V4_OPTEXIST(skb
))
579 return cipso_v4_cache_add(skb
, secattr
);
589 * netlbl_init - Initialize NetLabel
592 * Perform the required NetLabel initialization before first use.
595 static int __init
netlbl_init(void)
599 printk(KERN_INFO
"NetLabel: Initializing\n");
600 printk(KERN_INFO
"NetLabel: domain hash size = %u\n",
601 (1 << NETLBL_DOMHSH_BITSIZE
));
602 printk(KERN_INFO
"NetLabel: protocols ="
607 ret_val
= netlbl_domhsh_init(NETLBL_DOMHSH_BITSIZE
);
611 ret_val
= netlbl_netlink_init();
615 ret_val
= netlbl_unlabel_defconf();
618 printk(KERN_INFO
"NetLabel: unlabeled traffic allowed by default\n");
623 panic("NetLabel: failed to initialize properly (%d)\n", ret_val
);
626 subsys_initcall(netlbl_init
);