2 * NetLabel CALIPSO/IPv6 Support
4 * This file defines the CALIPSO/IPv6 functions for the NetLabel system. The
5 * NetLabel system manages static and dynamic label mappings for network
6 * protocols such as CIPSO and CALIPSO.
8 * Authors: Paul Moore <paul@paul-moore.com>
9 * Huw Davies <huw@codeweavers.com>
13 /* (c) Copyright Hewlett-Packard Development Company, L.P., 2006
14 * (c) Copyright Huw Davies <huw@codeweavers.com>, 2015
16 * This program is free software; you can redistribute it and/or modify
17 * it under the terms of the GNU General Public License as published by
18 * the Free Software Foundation; either version 2 of the License, or
19 * (at your option) any later version.
21 * This program is distributed in the hope that it will be useful,
22 * but WITHOUT ANY WARRANTY; without even the implied warranty of
23 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
24 * the GNU General Public License for more details.
26 * You should have received a copy of the GNU General Public License
27 * along with this program; if not, see <http://www.gnu.org/licenses/>.
31 #include <linux/types.h>
32 #include <linux/socket.h>
33 #include <linux/string.h>
34 #include <linux/skbuff.h>
35 #include <linux/audit.h>
36 #include <linux/slab.h>
38 #include <net/netlink.h>
39 #include <net/genetlink.h>
40 #include <net/netlabel.h>
41 #include <net/calipso.h>
42 #include <linux/atomic.h>
44 #include "netlabel_user.h"
45 #include "netlabel_calipso.h"
46 #include "netlabel_mgmt.h"
47 #include "netlabel_domainhash.h"
49 /* Argument struct for calipso_doi_walk() */
50 struct netlbl_calipso_doiwalk_arg
{
51 struct netlink_callback
*nl_cb
;
56 /* Argument struct for netlbl_domhsh_walk() */
57 struct netlbl_domhsh_walk_arg
{
58 struct netlbl_audit
*audit_info
;
62 /* NetLabel Generic NETLINK CALIPSO family */
63 static struct genl_family netlbl_calipso_gnl_family
= {
64 .id
= GENL_ID_GENERATE
,
66 .name
= NETLBL_NLTYPE_CALIPSO_NAME
,
67 .version
= NETLBL_PROTO_VERSION
,
68 .maxattr
= NLBL_CALIPSO_A_MAX
,
71 /* NetLabel Netlink attribute policy */
72 static const struct nla_policy calipso_genl_policy
[NLBL_CALIPSO_A_MAX
+ 1] = {
73 [NLBL_CALIPSO_A_DOI
] = { .type
= NLA_U32
},
74 [NLBL_CALIPSO_A_MTYPE
] = { .type
= NLA_U32
},
77 /* NetLabel Command Handlers
80 * netlbl_calipso_add_pass - Adds a CALIPSO pass DOI definition
81 * @info: the Generic NETLINK info block
82 * @audit_info: NetLabel audit information
85 * Create a new CALIPSO_MAP_PASS DOI definition based on the given ADD message
86 * and add it to the CALIPSO engine. Return zero on success and non-zero on
90 static int netlbl_calipso_add_pass(struct genl_info
*info
,
91 struct netlbl_audit
*audit_info
)
94 struct calipso_doi
*doi_def
= NULL
;
96 doi_def
= kmalloc(sizeof(*doi_def
), GFP_KERNEL
);
99 doi_def
->type
= CALIPSO_MAP_PASS
;
100 doi_def
->doi
= nla_get_u32(info
->attrs
[NLBL_CALIPSO_A_DOI
]);
101 ret_val
= calipso_doi_add(doi_def
, audit_info
);
103 calipso_doi_free(doi_def
);
109 * netlbl_calipso_add - Handle an ADD message
110 * @skb: the NETLINK buffer
111 * @info: the Generic NETLINK info block
114 * Create a new DOI definition based on the given ADD message and add it to the
115 * CALIPSO engine. Returns zero on success, negative values on failure.
118 static int netlbl_calipso_add(struct sk_buff
*skb
, struct genl_info
*info
)
121 int ret_val
= -EINVAL
;
122 struct netlbl_audit audit_info
;
124 if (!info
->attrs
[NLBL_CALIPSO_A_DOI
] ||
125 !info
->attrs
[NLBL_CALIPSO_A_MTYPE
])
128 netlbl_netlink_auditinfo(skb
, &audit_info
);
129 switch (nla_get_u32(info
->attrs
[NLBL_CALIPSO_A_MTYPE
])) {
130 case CALIPSO_MAP_PASS
:
131 ret_val
= netlbl_calipso_add_pass(info
, &audit_info
);
135 atomic_inc(&netlabel_mgmt_protocount
);
141 * netlbl_calipso_list - Handle a LIST message
142 * @skb: the NETLINK buffer
143 * @info: the Generic NETLINK info block
146 * Process a user generated LIST message and respond accordingly.
147 * Returns zero on success and negative values on error.
150 static int netlbl_calipso_list(struct sk_buff
*skb
, struct genl_info
*info
)
153 struct sk_buff
*ans_skb
= NULL
;
156 struct calipso_doi
*doi_def
;
158 if (!info
->attrs
[NLBL_CALIPSO_A_DOI
]) {
163 doi
= nla_get_u32(info
->attrs
[NLBL_CALIPSO_A_DOI
]);
165 doi_def
= calipso_doi_getdef(doi
);
171 ans_skb
= nlmsg_new(NLMSG_DEFAULT_SIZE
, GFP_KERNEL
);
174 goto list_failure_put
;
176 data
= genlmsg_put_reply(ans_skb
, info
, &netlbl_calipso_gnl_family
,
177 0, NLBL_CALIPSO_C_LIST
);
180 goto list_failure_put
;
183 ret_val
= nla_put_u32(ans_skb
, NLBL_CALIPSO_A_MTYPE
, doi_def
->type
);
185 goto list_failure_put
;
187 calipso_doi_putdef(doi_def
);
189 genlmsg_end(ans_skb
, data
);
190 return genlmsg_reply(ans_skb
, info
);
193 calipso_doi_putdef(doi_def
);
200 * netlbl_calipso_listall_cb - calipso_doi_walk() callback for LISTALL
201 * @doi_def: the CALIPSO DOI definition
202 * @arg: the netlbl_calipso_doiwalk_arg structure
205 * This function is designed to be used as a callback to the
206 * calipso_doi_walk() function for use in generating a response for a LISTALL
207 * message. Returns the size of the message on success, negative values on
211 static int netlbl_calipso_listall_cb(struct calipso_doi
*doi_def
, void *arg
)
213 int ret_val
= -ENOMEM
;
214 struct netlbl_calipso_doiwalk_arg
*cb_arg
= arg
;
217 data
= genlmsg_put(cb_arg
->skb
, NETLINK_CB(cb_arg
->nl_cb
->skb
).portid
,
218 cb_arg
->seq
, &netlbl_calipso_gnl_family
,
219 NLM_F_MULTI
, NLBL_CALIPSO_C_LISTALL
);
221 goto listall_cb_failure
;
223 ret_val
= nla_put_u32(cb_arg
->skb
, NLBL_CALIPSO_A_DOI
, doi_def
->doi
);
225 goto listall_cb_failure
;
226 ret_val
= nla_put_u32(cb_arg
->skb
,
227 NLBL_CALIPSO_A_MTYPE
,
230 goto listall_cb_failure
;
232 genlmsg_end(cb_arg
->skb
, data
);
236 genlmsg_cancel(cb_arg
->skb
, data
);
241 * netlbl_calipso_listall - Handle a LISTALL message
242 * @skb: the NETLINK buffer
243 * @cb: the NETLINK callback
246 * Process a user generated LISTALL message and respond accordingly. Returns
247 * zero on success and negative values on error.
250 static int netlbl_calipso_listall(struct sk_buff
*skb
,
251 struct netlink_callback
*cb
)
253 struct netlbl_calipso_doiwalk_arg cb_arg
;
254 u32 doi_skip
= cb
->args
[0];
258 cb_arg
.seq
= cb
->nlh
->nlmsg_seq
;
260 calipso_doi_walk(&doi_skip
, netlbl_calipso_listall_cb
, &cb_arg
);
262 cb
->args
[0] = doi_skip
;
267 * netlbl_calipso_remove_cb - netlbl_calipso_remove() callback for REMOVE
268 * @entry: LSM domain mapping entry
269 * @arg: the netlbl_domhsh_walk_arg structure
272 * This function is intended for use by netlbl_calipso_remove() as the callback
273 * for the netlbl_domhsh_walk() function; it removes LSM domain map entries
274 * which are associated with the CALIPSO DOI specified in @arg. Returns zero on
275 * success, negative values on failure.
278 static int netlbl_calipso_remove_cb(struct netlbl_dom_map
*entry
, void *arg
)
280 struct netlbl_domhsh_walk_arg
*cb_arg
= arg
;
282 if (entry
->def
.type
== NETLBL_NLTYPE_CALIPSO
&&
283 entry
->def
.calipso
->doi
== cb_arg
->doi
)
284 return netlbl_domhsh_remove_entry(entry
, cb_arg
->audit_info
);
290 * netlbl_calipso_remove - Handle a REMOVE message
291 * @skb: the NETLINK buffer
292 * @info: the Generic NETLINK info block
295 * Process a user generated REMOVE message and respond accordingly. Returns
296 * zero on success, negative values on failure.
299 static int netlbl_calipso_remove(struct sk_buff
*skb
, struct genl_info
*info
)
301 int ret_val
= -EINVAL
;
302 struct netlbl_domhsh_walk_arg cb_arg
;
303 struct netlbl_audit audit_info
;
307 if (!info
->attrs
[NLBL_CALIPSO_A_DOI
])
310 netlbl_netlink_auditinfo(skb
, &audit_info
);
311 cb_arg
.doi
= nla_get_u32(info
->attrs
[NLBL_CALIPSO_A_DOI
]);
312 cb_arg
.audit_info
= &audit_info
;
313 ret_val
= netlbl_domhsh_walk(&skip_bkt
, &skip_chain
,
314 netlbl_calipso_remove_cb
, &cb_arg
);
315 if (ret_val
== 0 || ret_val
== -ENOENT
) {
316 ret_val
= calipso_doi_remove(cb_arg
.doi
, &audit_info
);
318 atomic_dec(&netlabel_mgmt_protocount
);
324 /* NetLabel Generic NETLINK Command Definitions
327 static const struct genl_ops netlbl_calipso_ops
[] = {
329 .cmd
= NLBL_CALIPSO_C_ADD
,
330 .flags
= GENL_ADMIN_PERM
,
331 .policy
= calipso_genl_policy
,
332 .doit
= netlbl_calipso_add
,
336 .cmd
= NLBL_CALIPSO_C_REMOVE
,
337 .flags
= GENL_ADMIN_PERM
,
338 .policy
= calipso_genl_policy
,
339 .doit
= netlbl_calipso_remove
,
343 .cmd
= NLBL_CALIPSO_C_LIST
,
345 .policy
= calipso_genl_policy
,
346 .doit
= netlbl_calipso_list
,
350 .cmd
= NLBL_CALIPSO_C_LISTALL
,
352 .policy
= calipso_genl_policy
,
354 .dumpit
= netlbl_calipso_listall
,
358 /* NetLabel Generic NETLINK Protocol Functions
362 * netlbl_calipso_genl_init - Register the CALIPSO NetLabel component
365 * Register the CALIPSO packet NetLabel component with the Generic NETLINK
366 * mechanism. Returns zero on success, negative values on failure.
369 int __init
netlbl_calipso_genl_init(void)
371 return genl_register_family_with_ops(&netlbl_calipso_gnl_family
,
375 static const struct netlbl_calipso_ops
*calipso_ops
;
378 * netlbl_calipso_ops_register - Register the CALIPSO operations
381 * Register the CALIPSO packet engine operations.
384 const struct netlbl_calipso_ops
*
385 netlbl_calipso_ops_register(const struct netlbl_calipso_ops
*ops
)
387 return xchg(&calipso_ops
, ops
);
389 EXPORT_SYMBOL(netlbl_calipso_ops_register
);
391 static const struct netlbl_calipso_ops
*netlbl_calipso_ops_get(void)
393 return ACCESS_ONCE(calipso_ops
);
397 * calipso_doi_add - Add a new DOI to the CALIPSO protocol engine
398 * @doi_def: the DOI structure
399 * @audit_info: NetLabel audit information
402 * The caller defines a new DOI for use by the CALIPSO engine and calls this
403 * function to add it to the list of acceptable domains. The caller must
404 * ensure that the mapping table specified in @doi_def->map meets all of the
405 * requirements of the mapping type (see calipso.h for details). Returns
406 * zero on success and non-zero on failure.
409 int calipso_doi_add(struct calipso_doi
*doi_def
,
410 struct netlbl_audit
*audit_info
)
412 int ret_val
= -ENOMSG
;
413 const struct netlbl_calipso_ops
*ops
= netlbl_calipso_ops_get();
416 ret_val
= ops
->doi_add(doi_def
, audit_info
);
421 * calipso_doi_free - Frees a DOI definition
422 * @doi_def: the DOI definition
425 * This function frees all of the memory associated with a DOI definition.
428 void calipso_doi_free(struct calipso_doi
*doi_def
)
430 const struct netlbl_calipso_ops
*ops
= netlbl_calipso_ops_get();
433 ops
->doi_free(doi_def
);
437 * calipso_doi_remove - Remove an existing DOI from the CALIPSO protocol engine
438 * @doi: the DOI value
439 * @audit_secid: the LSM secid to use in the audit message
442 * Removes a DOI definition from the CALIPSO engine. The NetLabel routines will
443 * be called to release their own LSM domain mappings as well as our own
444 * domain list. Returns zero on success and negative values on failure.
447 int calipso_doi_remove(u32 doi
, struct netlbl_audit
*audit_info
)
449 int ret_val
= -ENOMSG
;
450 const struct netlbl_calipso_ops
*ops
= netlbl_calipso_ops_get();
453 ret_val
= ops
->doi_remove(doi
, audit_info
);
458 * calipso_doi_getdef - Returns a reference to a valid DOI definition
459 * @doi: the DOI value
462 * Searches for a valid DOI definition and if one is found it is returned to
463 * the caller. Otherwise NULL is returned. The caller must ensure that
464 * calipso_doi_putdef() is called when the caller is done.
467 struct calipso_doi
*calipso_doi_getdef(u32 doi
)
469 struct calipso_doi
*ret_val
= NULL
;
470 const struct netlbl_calipso_ops
*ops
= netlbl_calipso_ops_get();
473 ret_val
= ops
->doi_getdef(doi
);
478 * calipso_doi_putdef - Releases a reference for the given DOI definition
479 * @doi_def: the DOI definition
482 * Releases a DOI definition reference obtained from calipso_doi_getdef().
485 void calipso_doi_putdef(struct calipso_doi
*doi_def
)
487 const struct netlbl_calipso_ops
*ops
= netlbl_calipso_ops_get();
490 ops
->doi_putdef(doi_def
);
494 * calipso_doi_walk - Iterate through the DOI definitions
495 * @skip_cnt: skip past this number of DOI definitions, updated
496 * @callback: callback for each DOI definition
497 * @cb_arg: argument for the callback function
500 * Iterate over the DOI definition list, skipping the first @skip_cnt entries.
501 * For each entry call @callback, if @callback returns a negative value stop
502 * 'walking' through the list and return. Updates the value in @skip_cnt upon
503 * return. Returns zero on success, negative values on failure.
506 int calipso_doi_walk(u32
*skip_cnt
,
507 int (*callback
)(struct calipso_doi
*doi_def
, void *arg
),
510 int ret_val
= -ENOMSG
;
511 const struct netlbl_calipso_ops
*ops
= netlbl_calipso_ops_get();
514 ret_val
= ops
->doi_walk(skip_cnt
, callback
, cb_arg
);
519 * calipso_sock_getattr - Get the security attributes from a sock
521 * @secattr: the security attributes
524 * Query @sk to see if there is a CALIPSO option attached to the sock and if
525 * there is return the CALIPSO security attributes in @secattr. This function
526 * requires that @sk be locked, or privately held, but it does not do any
527 * locking itself. Returns zero on success and negative values on failure.
530 int calipso_sock_getattr(struct sock
*sk
, struct netlbl_lsm_secattr
*secattr
)
532 int ret_val
= -ENOMSG
;
533 const struct netlbl_calipso_ops
*ops
= netlbl_calipso_ops_get();
536 ret_val
= ops
->sock_getattr(sk
, secattr
);
541 * calipso_sock_setattr - Add a CALIPSO option to a socket
543 * @doi_def: the CALIPSO DOI to use
544 * @secattr: the specific security attributes of the socket
547 * Set the CALIPSO option on the given socket using the DOI definition and
548 * security attributes passed to the function. This function requires
549 * exclusive access to @sk, which means it either needs to be in the
550 * process of being created or locked. Returns zero on success and negative
554 int calipso_sock_setattr(struct sock
*sk
,
555 const struct calipso_doi
*doi_def
,
556 const struct netlbl_lsm_secattr
*secattr
)
558 int ret_val
= -ENOMSG
;
559 const struct netlbl_calipso_ops
*ops
= netlbl_calipso_ops_get();
562 ret_val
= ops
->sock_setattr(sk
, doi_def
, secattr
);
567 * calipso_sock_delattr - Delete the CALIPSO option from a socket
571 * Removes the CALIPSO option from a socket, if present.
574 void calipso_sock_delattr(struct sock
*sk
)
576 const struct netlbl_calipso_ops
*ops
= netlbl_calipso_ops_get();
579 ops
->sock_delattr(sk
);
583 * calipso_req_setattr - Add a CALIPSO option to a connection request socket
584 * @req: the connection request socket
585 * @doi_def: the CALIPSO DOI to use
586 * @secattr: the specific security attributes of the socket
589 * Set the CALIPSO option on the given socket using the DOI definition and
590 * security attributes passed to the function. Returns zero on success and
591 * negative values on failure.
594 int calipso_req_setattr(struct request_sock
*req
,
595 const struct calipso_doi
*doi_def
,
596 const struct netlbl_lsm_secattr
*secattr
)
598 int ret_val
= -ENOMSG
;
599 const struct netlbl_calipso_ops
*ops
= netlbl_calipso_ops_get();
602 ret_val
= ops
->req_setattr(req
, doi_def
, secattr
);
607 * calipso_req_delattr - Delete the CALIPSO option from a request socket
608 * @reg: the request socket
611 * Removes the CALIPSO option from a request socket, if present.
614 void calipso_req_delattr(struct request_sock
*req
)
616 const struct netlbl_calipso_ops
*ops
= netlbl_calipso_ops_get();
619 ops
->req_delattr(req
);
623 * calipso_optptr - Find the CALIPSO option in the packet
627 * Parse the packet's IP header looking for a CALIPSO option. Returns a pointer
628 * to the start of the CALIPSO option on success, NULL if one if not found.
631 unsigned char *calipso_optptr(const struct sk_buff
*skb
)
633 unsigned char *ret_val
= NULL
;
634 const struct netlbl_calipso_ops
*ops
= netlbl_calipso_ops_get();
637 ret_val
= ops
->skbuff_optptr(skb
);
642 * calipso_getattr - Get the security attributes from a memory block.
643 * @calipso: the CALIPSO option
644 * @secattr: the security attributes
647 * Inspect @calipso and return the security attributes in @secattr.
648 * Returns zero on success and negative values on failure.
651 int calipso_getattr(const unsigned char *calipso
,
652 struct netlbl_lsm_secattr
*secattr
)
654 int ret_val
= -ENOMSG
;
655 const struct netlbl_calipso_ops
*ops
= netlbl_calipso_ops_get();
658 ret_val
= ops
->opt_getattr(calipso
, secattr
);
663 * calipso_skbuff_setattr - Set the CALIPSO option on a packet
665 * @doi_def: the CALIPSO DOI to use
666 * @secattr: the security attributes
669 * Set the CALIPSO option on the given packet based on the security attributes.
670 * Returns a pointer to the IP header on success and NULL on failure.
673 int calipso_skbuff_setattr(struct sk_buff
*skb
,
674 const struct calipso_doi
*doi_def
,
675 const struct netlbl_lsm_secattr
*secattr
)
677 int ret_val
= -ENOMSG
;
678 const struct netlbl_calipso_ops
*ops
= netlbl_calipso_ops_get();
681 ret_val
= ops
->skbuff_setattr(skb
, doi_def
, secattr
);
686 * calipso_skbuff_delattr - Delete any CALIPSO options from a packet
690 * Removes any and all CALIPSO options from the given packet. Returns zero on
691 * success, negative values on failure.
694 int calipso_skbuff_delattr(struct sk_buff
*skb
)
696 int ret_val
= -ENOMSG
;
697 const struct netlbl_calipso_ops
*ops
= netlbl_calipso_ops_get();
700 ret_val
= ops
->skbuff_delattr(skb
);
705 * calipso_cache_invalidate - Invalidates the current CALIPSO cache
708 * Invalidates and frees any entries in the CALIPSO cache. Returns zero on
709 * success and negative values on failure.
712 void calipso_cache_invalidate(void)
714 const struct netlbl_calipso_ops
*ops
= netlbl_calipso_ops_get();
717 ops
->cache_invalidate();
721 * calipso_cache_add - Add an entry to the CALIPSO cache
722 * @calipso_ptr: the CALIPSO option
723 * @secattr: the packet's security attributes
726 * Add a new entry into the CALIPSO label mapping cache.
727 * Returns zero on success, negative values on failure.
730 int calipso_cache_add(const unsigned char *calipso_ptr
,
731 const struct netlbl_lsm_secattr
*secattr
)
734 int ret_val
= -ENOMSG
;
735 const struct netlbl_calipso_ops
*ops
= netlbl_calipso_ops_get();
738 ret_val
= ops
->cache_add(calipso_ptr
, secattr
);