Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jmorris/selinux-2.6

* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jmorris/selinux-2.6:
SELinux: use SECINITSID_NETMSG instead of SECINITSID_UNLABELED for NetLabel
SELinux: enable dynamic activation/deactivation of NetLabel/SELinux enforcement

+162 -66
+27 -35
include/net/netlabel.h
··· 144 }; 145 146 /* 147 - * LSM security attribute operations 148 */ 149 - 150 151 /** 152 * netlbl_secattr_cache_alloc - Allocate and initialize a secattr cache ··· 282 } 283 284 #ifdef CONFIG_NETLABEL 285 int netlbl_secattr_catmap_walk(struct netlbl_lsm_secattr_catmap *catmap, 286 u32 offset); 287 int netlbl_secattr_catmap_walk_rng(struct netlbl_lsm_secattr_catmap *catmap, ··· 296 u32 start, 297 u32 end, 298 gfp_t flags); 299 #else 300 static inline int netlbl_secattr_catmap_walk( 301 struct netlbl_lsm_secattr_catmap *catmap, ··· 322 { 323 return -ENOENT; 324 } 325 - 326 static inline int netlbl_secattr_catmap_walk_rng( 327 struct netlbl_lsm_secattr_catmap *catmap, 328 u32 offset) 329 { 330 return -ENOENT; 331 } 332 - 333 static inline int netlbl_secattr_catmap_setbit( 334 struct netlbl_lsm_secattr_catmap *catmap, 335 u32 bit, ··· 335 { 336 return 0; 337 } 338 - 339 static inline int netlbl_secattr_catmap_setrng( 340 struct netlbl_lsm_secattr_catmap *catmap, 341 u32 start, ··· 343 { 344 return 0; 345 } 346 - #endif 347 - 348 - /* 349 - * LSM protocol operations 350 - */ 351 - 352 - #ifdef CONFIG_NETLABEL 353 - int netlbl_sock_setattr(struct sock *sk, 354 - const struct netlbl_lsm_secattr *secattr); 355 - int netlbl_sock_getattr(struct sock *sk, 356 - struct netlbl_lsm_secattr *secattr); 357 - int netlbl_skbuff_getattr(const struct sk_buff *skb, 358 - struct netlbl_lsm_secattr *secattr); 359 - void netlbl_skbuff_err(struct sk_buff *skb, int error); 360 - #else 361 static inline int netlbl_sock_setattr(struct sock *sk, 362 const struct netlbl_lsm_secattr *secattr) 363 { 364 return -ENOSYS; 365 } 366 - 367 static inline int netlbl_sock_getattr(struct sock *sk, 368 struct netlbl_lsm_secattr *secattr) 369 { 370 return -ENOSYS; 371 } 372 - 373 static inline int netlbl_skbuff_getattr(const struct sk_buff *skb, 374 struct netlbl_lsm_secattr *secattr) 375 { 376 return -ENOSYS; 377 } 378 - 379 static inline void netlbl_skbuff_err(struct sk_buff *skb, int error) 380 { 381 return; 382 } 383 - #endif /* CONFIG_NETLABEL */ 384 - 385 - /* 386 - * LSM label mapping cache operations 387 - */ 388 - 389 - #ifdef CONFIG_NETLABEL 390 - void netlbl_cache_invalidate(void); 391 - int netlbl_cache_add(const struct sk_buff *skb, 392 - const struct netlbl_lsm_secattr *secattr); 393 - #else 394 static inline void netlbl_cache_invalidate(void) 395 { 396 return; 397 } 398 - 399 static inline int netlbl_cache_add(const struct sk_buff *skb, 400 const struct netlbl_lsm_secattr *secattr) 401 {
··· 144 }; 145 146 /* 147 + * LSM security attribute operations (inline) 148 */ 149 150 /** 151 * netlbl_secattr_cache_alloc - Allocate and initialize a secattr cache ··· 283 } 284 285 #ifdef CONFIG_NETLABEL 286 + /* 287 + * LSM security attribute operations 288 + */ 289 int netlbl_secattr_catmap_walk(struct netlbl_lsm_secattr_catmap *catmap, 290 u32 offset); 291 int netlbl_secattr_catmap_walk_rng(struct netlbl_lsm_secattr_catmap *catmap, ··· 294 u32 start, 295 u32 end, 296 gfp_t flags); 297 + 298 + /* 299 + * LSM protocol operations 300 + */ 301 + int netlbl_enabled(void); 302 + int netlbl_sock_setattr(struct sock *sk, 303 + const struct netlbl_lsm_secattr *secattr); 304 + int netlbl_sock_getattr(struct sock *sk, 305 + struct netlbl_lsm_secattr *secattr); 306 + int netlbl_skbuff_getattr(const struct sk_buff *skb, 307 + struct netlbl_lsm_secattr *secattr); 308 + void netlbl_skbuff_err(struct sk_buff *skb, int error); 309 + 310 + /* 311 + * LSM label mapping cache operations 312 + */ 313 + void netlbl_cache_invalidate(void); 314 + int netlbl_cache_add(const struct sk_buff *skb, 315 + const struct netlbl_lsm_secattr *secattr); 316 #else 317 static inline int netlbl_secattr_catmap_walk( 318 struct netlbl_lsm_secattr_catmap *catmap, ··· 301 { 302 return -ENOENT; 303 } 304 static inline int netlbl_secattr_catmap_walk_rng( 305 struct netlbl_lsm_secattr_catmap *catmap, 306 u32 offset) 307 { 308 return -ENOENT; 309 } 310 static inline int netlbl_secattr_catmap_setbit( 311 struct netlbl_lsm_secattr_catmap *catmap, 312 u32 bit, ··· 316 { 317 return 0; 318 } 319 static inline int netlbl_secattr_catmap_setrng( 320 struct netlbl_lsm_secattr_catmap *catmap, 321 u32 start, ··· 325 { 326 return 0; 327 } 328 + static inline int netlbl_enabled(void) 329 + { 330 + return 0; 331 + } 332 static inline int netlbl_sock_setattr(struct sock *sk, 333 const struct netlbl_lsm_secattr *secattr) 334 { 335 return -ENOSYS; 336 } 337 static inline int netlbl_sock_getattr(struct sock *sk, 338 struct netlbl_lsm_secattr *secattr) 339 { 340 return -ENOSYS; 341 } 342 static inline int netlbl_skbuff_getattr(const struct sk_buff *skb, 343 struct netlbl_lsm_secattr *secattr) 344 { 345 return -ENOSYS; 346 } 347 static inline void netlbl_skbuff_err(struct sk_buff *skb, int error) 348 { 349 return; 350 } 351 static inline void netlbl_cache_invalidate(void) 352 { 353 return; 354 } 355 static inline int netlbl_cache_add(const struct sk_buff *skb, 356 const struct netlbl_lsm_secattr *secattr) 357 {
+5
net/netlabel/netlabel_cipso_v4.c
··· 41 42 #include "netlabel_user.h" 43 #include "netlabel_cipso_v4.h" 44 45 /* Argument struct for cipso_v4_doi_walk() */ 46 struct netlbl_cipsov4_doiwalk_arg { ··· 420 ret_val = netlbl_cipsov4_add_pass(info); 421 break; 422 } 423 424 audit_buf = netlbl_audit_start_common(AUDIT_MAC_CIPSOV4_ADD, 425 &audit_info); ··· 697 ret_val = cipso_v4_doi_remove(doi, 698 &audit_info, 699 netlbl_cipsov4_doi_free); 700 701 audit_buf = netlbl_audit_start_common(AUDIT_MAC_CIPSOV4_DEL, 702 &audit_info);
··· 41 42 #include "netlabel_user.h" 43 #include "netlabel_cipso_v4.h" 44 + #include "netlabel_mgmt.h" 45 46 /* Argument struct for cipso_v4_doi_walk() */ 47 struct netlbl_cipsov4_doiwalk_arg { ··· 419 ret_val = netlbl_cipsov4_add_pass(info); 420 break; 421 } 422 + if (ret_val == 0) 423 + netlbl_mgmt_protocount_inc(); 424 425 audit_buf = netlbl_audit_start_common(AUDIT_MAC_CIPSOV4_ADD, 426 &audit_info); ··· 694 ret_val = cipso_v4_doi_remove(doi, 695 &audit_info, 696 netlbl_cipsov4_doi_free); 697 + if (ret_val == 0) 698 + netlbl_mgmt_protocount_dec(); 699 700 audit_buf = netlbl_audit_start_common(AUDIT_MAC_CIPSOV4_DEL, 701 &audit_info);
+21
net/netlabel/netlabel_kapi.c
··· 38 #include "netlabel_domainhash.h" 39 #include "netlabel_unlabeled.h" 40 #include "netlabel_user.h" 41 42 /* 43 * Security Attribute Functions ··· 244 /* 245 * LSM Functions 246 */ 247 248 /** 249 * netlbl_socket_setattr - Label a socket using the correct protocol
··· 38 #include "netlabel_domainhash.h" 39 #include "netlabel_unlabeled.h" 40 #include "netlabel_user.h" 41 + #include "netlabel_mgmt.h" 42 43 /* 44 * Security Attribute Functions ··· 243 /* 244 * LSM Functions 245 */ 246 + 247 + /** 248 + * netlbl_enabled - Determine if the NetLabel subsystem is enabled 249 + * 250 + * Description: 251 + * The LSM can use this function to determine if it should use NetLabel 252 + * security attributes in it's enforcement mechanism. Currently, NetLabel is 253 + * considered to be enabled when it's configuration contains a valid setup for 254 + * at least one labeled protocol (i.e. NetLabel can understand incoming 255 + * labeled packets of at least one type); otherwise NetLabel is considered to 256 + * be disabled. 257 + * 258 + */ 259 + int netlbl_enabled(void) 260 + { 261 + /* At some point we probably want to expose this mechanism to the user 262 + * as well so that admins can toggle NetLabel regardless of the 263 + * configuration */ 264 + return (netlbl_mgmt_protocount_value() > 0 ? 1 : 0); 265 + } 266 267 /** 268 * netlbl_socket_setattr - Label a socket using the correct protocol
+65
net/netlabel/netlabel_mgmt.c
··· 42 #include "netlabel_user.h" 43 #include "netlabel_mgmt.h" 44 45 /* Argument struct for netlbl_domhsh_walk() */ 46 struct netlbl_domhsh_walk_arg { 47 struct netlink_callback *nl_cb; ··· 69 [NLBL_MGMT_A_VERSION] = { .type = NLA_U32 }, 70 [NLBL_MGMT_A_CV4DOI] = { .type = NLA_U32 }, 71 }; 72 73 /* 74 * NetLabel Command Handlers
··· 42 #include "netlabel_user.h" 43 #include "netlabel_mgmt.h" 44 45 + /* NetLabel configured protocol count */ 46 + static DEFINE_SPINLOCK(netlabel_mgmt_protocount_lock); 47 + static u32 netlabel_mgmt_protocount = 0; 48 + 49 /* Argument struct for netlbl_domhsh_walk() */ 50 struct netlbl_domhsh_walk_arg { 51 struct netlink_callback *nl_cb; ··· 65 [NLBL_MGMT_A_VERSION] = { .type = NLA_U32 }, 66 [NLBL_MGMT_A_CV4DOI] = { .type = NLA_U32 }, 67 }; 68 + 69 + /* 70 + * NetLabel Misc Managment Functions 71 + */ 72 + 73 + /** 74 + * netlbl_mgmt_protocount_inc - Increment the configured labeled protocol count 75 + * 76 + * Description: 77 + * Increment the number of labeled protocol configurations in the current 78 + * NetLabel configuration. Keep track of this for use in determining if 79 + * NetLabel label enforcement should be active/enabled or not in the LSM. 80 + * 81 + */ 82 + void netlbl_mgmt_protocount_inc(void) 83 + { 84 + rcu_read_lock(); 85 + spin_lock(&netlabel_mgmt_protocount_lock); 86 + netlabel_mgmt_protocount++; 87 + spin_unlock(&netlabel_mgmt_protocount_lock); 88 + rcu_read_unlock(); 89 + } 90 + 91 + /** 92 + * netlbl_mgmt_protocount_dec - Decrement the configured labeled protocol count 93 + * 94 + * Description: 95 + * Decrement the number of labeled protocol configurations in the current 96 + * NetLabel configuration. Keep track of this for use in determining if 97 + * NetLabel label enforcement should be active/enabled or not in the LSM. 98 + * 99 + */ 100 + void netlbl_mgmt_protocount_dec(void) 101 + { 102 + rcu_read_lock(); 103 + spin_lock(&netlabel_mgmt_protocount_lock); 104 + if (netlabel_mgmt_protocount > 0) 105 + netlabel_mgmt_protocount--; 106 + spin_unlock(&netlabel_mgmt_protocount_lock); 107 + rcu_read_unlock(); 108 + } 109 + 110 + /** 111 + * netlbl_mgmt_protocount_value - Return the number of configured protocols 112 + * 113 + * Description: 114 + * Return the number of labeled protocols in the current NetLabel 115 + * configuration. This value is useful in determining if NetLabel label 116 + * enforcement should be active/enabled or not in the LSM. 117 + * 118 + */ 119 + u32 netlbl_mgmt_protocount_value(void) 120 + { 121 + u32 val; 122 + 123 + rcu_read_lock(); 124 + val = netlabel_mgmt_protocount; 125 + rcu_read_unlock(); 126 + 127 + return val; 128 + } 129 130 /* 131 * NetLabel Command Handlers
+5
net/netlabel/netlabel_mgmt.h
··· 168 /* NetLabel protocol functions */ 169 int netlbl_mgmt_genl_init(void); 170 171 #endif
··· 168 /* NetLabel protocol functions */ 169 int netlbl_mgmt_genl_init(void); 170 171 + /* NetLabel misc management functions */ 172 + void netlbl_mgmt_protocount_inc(void); 173 + void netlbl_mgmt_protocount_dec(void); 174 + u32 netlbl_mgmt_protocount_value(void); 175 + 176 #endif
+11 -10
security/selinux/hooks.c
··· 3129 /** 3130 * selinux_skb_extlbl_sid - Determine the external label of a packet 3131 * @skb: the packet 3132 - * @base_sid: the SELinux SID to use as a context for MLS only external labels 3133 * @sid: the packet's SID 3134 * 3135 * Description: 3136 * Check the various different forms of external packet labeling and determine 3137 - * the external SID for the packet. 3138 * 3139 */ 3140 - static void selinux_skb_extlbl_sid(struct sk_buff *skb, 3141 - u32 base_sid, 3142 - u32 *sid) 3143 { 3144 u32 xfrm_sid; 3145 u32 nlbl_sid; ··· 3149 selinux_skb_xfrm_sid(skb, &xfrm_sid); 3150 if (selinux_netlbl_skbuff_getsid(skb, 3151 (xfrm_sid == SECSID_NULL ? 3152 - base_sid : xfrm_sid), 3153 &nlbl_sid) != 0) 3154 nlbl_sid = SECSID_NULL; 3155 - 3156 *sid = (nlbl_sid == SECSID_NULL ? xfrm_sid : nlbl_sid); 3157 } 3158 ··· 3696 if (sock && sock->sk->sk_family == PF_UNIX) 3697 selinux_get_inode_sid(SOCK_INODE(sock), &peer_secid); 3698 else if (skb) 3699 - selinux_skb_extlbl_sid(skb, SECINITSID_UNLABELED, &peer_secid); 3700 3701 if (peer_secid == SECSID_NULL) 3702 err = -EINVAL; ··· 3757 u32 newsid; 3758 u32 peersid; 3759 3760 - selinux_skb_extlbl_sid(skb, SECINITSID_UNLABELED, &peersid); 3761 if (peersid == SECSID_NULL) { 3762 req->secid = sksec->sid; 3763 req->peer_secid = SECSID_NULL; ··· 3795 { 3796 struct sk_security_struct *sksec = sk->sk_security; 3797 3798 - selinux_skb_extlbl_sid(skb, SECINITSID_UNLABELED, &sksec->peer_sid); 3799 } 3800 3801 static void selinux_req_classify_flow(const struct request_sock *req,
··· 3129 /** 3130 * selinux_skb_extlbl_sid - Determine the external label of a packet 3131 * @skb: the packet 3132 * @sid: the packet's SID 3133 * 3134 * Description: 3135 * Check the various different forms of external packet labeling and determine 3136 + * the external SID for the packet. If only one form of external labeling is 3137 + * present then it is used, if both labeled IPsec and NetLabel labels are 3138 + * present then the SELinux type information is taken from the labeled IPsec 3139 + * SA and the MLS sensitivity label information is taken from the NetLabel 3140 + * security attributes. This bit of "magic" is done in the call to 3141 + * selinux_netlbl_skbuff_getsid(). 3142 * 3143 */ 3144 + static void selinux_skb_extlbl_sid(struct sk_buff *skb, u32 *sid) 3145 { 3146 u32 xfrm_sid; 3147 u32 nlbl_sid; ··· 3147 selinux_skb_xfrm_sid(skb, &xfrm_sid); 3148 if (selinux_netlbl_skbuff_getsid(skb, 3149 (xfrm_sid == SECSID_NULL ? 3150 + SECINITSID_NETMSG : xfrm_sid), 3151 &nlbl_sid) != 0) 3152 nlbl_sid = SECSID_NULL; 3153 *sid = (nlbl_sid == SECSID_NULL ? xfrm_sid : nlbl_sid); 3154 } 3155 ··· 3695 if (sock && sock->sk->sk_family == PF_UNIX) 3696 selinux_get_inode_sid(SOCK_INODE(sock), &peer_secid); 3697 else if (skb) 3698 + selinux_skb_extlbl_sid(skb, &peer_secid); 3699 3700 if (peer_secid == SECSID_NULL) 3701 err = -EINVAL; ··· 3756 u32 newsid; 3757 u32 peersid; 3758 3759 + selinux_skb_extlbl_sid(skb, &peersid); 3760 if (peersid == SECSID_NULL) { 3761 req->secid = sksec->sid; 3762 req->peer_secid = SECSID_NULL; ··· 3794 { 3795 struct sk_security_struct *sksec = sk->sk_security; 3796 3797 + selinux_skb_extlbl_sid(skb, &sksec->peer_sid); 3798 } 3799 3800 static void selinux_req_classify_flow(const struct request_sock *req,
+28 -21
security/selinux/netlabel.c
··· 155 int rc; 156 struct netlbl_lsm_secattr secattr; 157 158 netlbl_secattr_init(&secattr); 159 rc = netlbl_skbuff_getattr(skb, &secattr); 160 if (rc == 0 && secattr.flags != NETLBL_SECATTR_NONE) 161 - rc = security_netlbl_secattr_to_sid(&secattr, 162 - base_sid, 163 - sid); 164 else 165 *sid = SECSID_NULL; 166 netlbl_secattr_destroy(&secattr); ··· 201 if (netlbl_sock_getattr(sk, &secattr) == 0 && 202 secattr.flags != NETLBL_SECATTR_NONE && 203 security_netlbl_secattr_to_sid(&secattr, 204 - SECINITSID_UNLABELED, 205 &nlbl_peer_sid) == 0) 206 sksec->peer_sid = nlbl_peer_sid; 207 netlbl_secattr_destroy(&secattr); ··· 298 struct avc_audit_data *ad) 299 { 300 int rc; 301 - u32 netlbl_sid; 302 - u32 recv_perm; 303 304 - rc = selinux_netlbl_skbuff_getsid(skb, 305 - SECINITSID_UNLABELED, 306 - &netlbl_sid); 307 if (rc != 0) 308 return rc; 309 310 - if (netlbl_sid == SECSID_NULL) 311 - return 0; 312 - 313 switch (sksec->sclass) { 314 case SECCLASS_UDP_SOCKET: 315 - recv_perm = UDP_SOCKET__RECVFROM; 316 break; 317 case SECCLASS_TCP_SOCKET: 318 - recv_perm = TCP_SOCKET__RECVFROM; 319 break; 320 default: 321 - recv_perm = RAWIP_SOCKET__RECVFROM; 322 } 323 324 - rc = avc_has_perm(sksec->sid, 325 - netlbl_sid, 326 - sksec->sclass, 327 - recv_perm, 328 - ad); 329 if (rc == 0) 330 return 0; 331 332 - netlbl_skbuff_err(skb, rc); 333 return rc; 334 } 335
··· 155 int rc; 156 struct netlbl_lsm_secattr secattr; 157 158 + if (!netlbl_enabled()) { 159 + *sid = SECSID_NULL; 160 + return 0; 161 + } 162 + 163 netlbl_secattr_init(&secattr); 164 rc = netlbl_skbuff_getattr(skb, &secattr); 165 if (rc == 0 && secattr.flags != NETLBL_SECATTR_NONE) 166 + rc = security_netlbl_secattr_to_sid(&secattr, base_sid, sid); 167 else 168 *sid = SECSID_NULL; 169 netlbl_secattr_destroy(&secattr); ··· 198 if (netlbl_sock_getattr(sk, &secattr) == 0 && 199 secattr.flags != NETLBL_SECATTR_NONE && 200 security_netlbl_secattr_to_sid(&secattr, 201 + SECINITSID_NETMSG, 202 &nlbl_peer_sid) == 0) 203 sksec->peer_sid = nlbl_peer_sid; 204 netlbl_secattr_destroy(&secattr); ··· 295 struct avc_audit_data *ad) 296 { 297 int rc; 298 + u32 nlbl_sid; 299 + u32 perm; 300 + struct netlbl_lsm_secattr secattr; 301 302 + if (!netlbl_enabled()) 303 + return 0; 304 + 305 + netlbl_secattr_init(&secattr); 306 + rc = netlbl_skbuff_getattr(skb, &secattr); 307 + if (rc == 0 && secattr.flags != NETLBL_SECATTR_NONE) 308 + rc = security_netlbl_secattr_to_sid(&secattr, 309 + SECINITSID_NETMSG, 310 + &nlbl_sid); 311 + else 312 + nlbl_sid = SECINITSID_UNLABELED; 313 + netlbl_secattr_destroy(&secattr); 314 if (rc != 0) 315 return rc; 316 317 switch (sksec->sclass) { 318 case SECCLASS_UDP_SOCKET: 319 + perm = UDP_SOCKET__RECVFROM; 320 break; 321 case SECCLASS_TCP_SOCKET: 322 + perm = TCP_SOCKET__RECVFROM; 323 break; 324 default: 325 + perm = RAWIP_SOCKET__RECVFROM; 326 } 327 328 + rc = avc_has_perm(sksec->sid, nlbl_sid, sksec->sclass, perm, ad); 329 if (rc == 0) 330 return 0; 331 332 + if (nlbl_sid != SECINITSID_UNLABELED) 333 + netlbl_skbuff_err(skb, rc); 334 return rc; 335 } 336