aboutsummaryrefslogtreecommitdiffstats
path: root/security
diff options
context:
space:
mode:
authorJames Bottomley <jejb@sparkweed.localdomain>2006-09-23 22:03:52 -0400
committerJames Bottomley <jejb@sparkweed.localdomain>2006-09-23 22:03:52 -0400
commit1aedf2ccc60fade26c46fae12e28664d0da3f199 (patch)
treed91083e3079f1ddb942a382ac2b5a7525570ad59 /security
parentdfdc58ba354adb80d67c99f7be84f95a8e02e466 (diff)
parent1ab9dd0902df4f4ff56fbf672220549090ab28ba (diff)
Merge mulgrave-w:git/linux-2.6
Conflicts: include/linux/blkdev.h Trivial merge to incorporate tag prototypes.
Diffstat (limited to 'security')
-rw-r--r--security/dummy.c64
-rw-r--r--security/selinux/hooks.c245
-rw-r--r--security/selinux/include/av_perm_to_string.h1
-rw-r--r--security/selinux/include/av_permissions.h1
-rw-r--r--security/selinux/include/objsec.h9
-rw-r--r--security/selinux/include/security.h2
-rw-r--r--security/selinux/include/selinux_netlabel.h119
-rw-r--r--security/selinux/include/xfrm.h43
-rw-r--r--security/selinux/ss/ebitmap.c140
-rw-r--r--security/selinux/ss/ebitmap.h6
-rw-r--r--security/selinux/ss/mls.c176
-rw-r--r--security/selinux/ss/mls.h41
-rw-r--r--security/selinux/ss/services.c613
-rw-r--r--security/selinux/xfrm.c216
14 files changed, 1524 insertions, 152 deletions
diff --git a/security/dummy.c b/security/dummy.c
index 58c6d399c844..aeee70565509 100644
--- a/security/dummy.c
+++ b/security/dummy.c
@@ -709,10 +709,10 @@ static int dummy_socket_create (int family, int type,
709 return 0; 709 return 0;
710} 710}
711 711
712static void dummy_socket_post_create (struct socket *sock, int family, int type, 712static int dummy_socket_post_create (struct socket *sock, int family, int type,
713 int protocol, int kern) 713 int protocol, int kern)
714{ 714{
715 return; 715 return 0;
716} 716}
717 717
718static int dummy_socket_bind (struct socket *sock, struct sockaddr *address, 718static int dummy_socket_bind (struct socket *sock, struct sockaddr *address,
@@ -805,14 +805,38 @@ static inline void dummy_sk_free_security (struct sock *sk)
805{ 805{
806} 806}
807 807
808static unsigned int dummy_sk_getsid(struct sock *sk, struct flowi *fl, u8 dir) 808static inline void dummy_sk_clone_security (const struct sock *sk, struct sock *newsk)
809{
810}
811
812static inline void dummy_sk_getsecid(struct sock *sk, u32 *secid)
813{
814}
815
816static inline void dummy_sock_graft(struct sock* sk, struct socket *parent)
817{
818}
819
820static inline int dummy_inet_conn_request(struct sock *sk,
821 struct sk_buff *skb, struct request_sock *req)
809{ 822{
810 return 0; 823 return 0;
811} 824}
825
826static inline void dummy_inet_csk_clone(struct sock *newsk,
827 const struct request_sock *req)
828{
829}
830
831static inline void dummy_req_classify_flow(const struct request_sock *req,
832 struct flowi *fl)
833{
834}
812#endif /* CONFIG_SECURITY_NETWORK */ 835#endif /* CONFIG_SECURITY_NETWORK */
813 836
814#ifdef CONFIG_SECURITY_NETWORK_XFRM 837#ifdef CONFIG_SECURITY_NETWORK_XFRM
815static int dummy_xfrm_policy_alloc_security(struct xfrm_policy *xp, struct xfrm_user_sec_ctx *sec_ctx) 838static int dummy_xfrm_policy_alloc_security(struct xfrm_policy *xp,
839 struct xfrm_user_sec_ctx *sec_ctx, struct sock *sk)
816{ 840{
817 return 0; 841 return 0;
818} 842}
@@ -831,7 +855,8 @@ static int dummy_xfrm_policy_delete_security(struct xfrm_policy *xp)
831 return 0; 855 return 0;
832} 856}
833 857
834static int dummy_xfrm_state_alloc_security(struct xfrm_state *x, struct xfrm_user_sec_ctx *sec_ctx) 858static int dummy_xfrm_state_alloc_security(struct xfrm_state *x,
859 struct xfrm_user_sec_ctx *sec_ctx, struct xfrm_sec_ctx *pol, u32 secid)
835{ 860{
836 return 0; 861 return 0;
837} 862}
@@ -849,6 +874,23 @@ static int dummy_xfrm_policy_lookup(struct xfrm_policy *xp, u32 sk_sid, u8 dir)
849{ 874{
850 return 0; 875 return 0;
851} 876}
877
878static int dummy_xfrm_state_pol_flow_match(struct xfrm_state *x,
879 struct xfrm_policy *xp, struct flowi *fl)
880{
881 return 1;
882}
883
884static int dummy_xfrm_flow_state_match(struct flowi *fl, struct xfrm_state *xfrm)
885{
886 return 1;
887}
888
889static int dummy_xfrm_decode_session(struct sk_buff *skb, u32 *fl, int ckall)
890{
891 return 0;
892}
893
852#endif /* CONFIG_SECURITY_NETWORK_XFRM */ 894#endif /* CONFIG_SECURITY_NETWORK_XFRM */
853static int dummy_register_security (const char *name, struct security_operations *ops) 895static int dummy_register_security (const char *name, struct security_operations *ops)
854{ 896{
@@ -1060,7 +1102,12 @@ void security_fixup_ops (struct security_operations *ops)
1060 set_to_dummy_if_null(ops, socket_getpeersec_dgram); 1102 set_to_dummy_if_null(ops, socket_getpeersec_dgram);
1061 set_to_dummy_if_null(ops, sk_alloc_security); 1103 set_to_dummy_if_null(ops, sk_alloc_security);
1062 set_to_dummy_if_null(ops, sk_free_security); 1104 set_to_dummy_if_null(ops, sk_free_security);
1063 set_to_dummy_if_null(ops, sk_getsid); 1105 set_to_dummy_if_null(ops, sk_clone_security);
1106 set_to_dummy_if_null(ops, sk_getsecid);
1107 set_to_dummy_if_null(ops, sock_graft);
1108 set_to_dummy_if_null(ops, inet_conn_request);
1109 set_to_dummy_if_null(ops, inet_csk_clone);
1110 set_to_dummy_if_null(ops, req_classify_flow);
1064 #endif /* CONFIG_SECURITY_NETWORK */ 1111 #endif /* CONFIG_SECURITY_NETWORK */
1065#ifdef CONFIG_SECURITY_NETWORK_XFRM 1112#ifdef CONFIG_SECURITY_NETWORK_XFRM
1066 set_to_dummy_if_null(ops, xfrm_policy_alloc_security); 1113 set_to_dummy_if_null(ops, xfrm_policy_alloc_security);
@@ -1071,6 +1118,9 @@ void security_fixup_ops (struct security_operations *ops)
1071 set_to_dummy_if_null(ops, xfrm_state_free_security); 1118 set_to_dummy_if_null(ops, xfrm_state_free_security);
1072 set_to_dummy_if_null(ops, xfrm_state_delete_security); 1119 set_to_dummy_if_null(ops, xfrm_state_delete_security);
1073 set_to_dummy_if_null(ops, xfrm_policy_lookup); 1120 set_to_dummy_if_null(ops, xfrm_policy_lookup);
1121 set_to_dummy_if_null(ops, xfrm_state_pol_flow_match);
1122 set_to_dummy_if_null(ops, xfrm_flow_state_match);
1123 set_to_dummy_if_null(ops, xfrm_decode_session);
1074#endif /* CONFIG_SECURITY_NETWORK_XFRM */ 1124#endif /* CONFIG_SECURITY_NETWORK_XFRM */
1075#ifdef CONFIG_KEYS 1125#ifdef CONFIG_KEYS
1076 set_to_dummy_if_null(ops, key_alloc); 1126 set_to_dummy_if_null(ops, key_alloc);
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index 5d1b8c733199..5a66c4c09f7a 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -12,6 +12,8 @@
12 * Copyright (C) 2003 Red Hat, Inc., James Morris <jmorris@redhat.com> 12 * Copyright (C) 2003 Red Hat, Inc., James Morris <jmorris@redhat.com>
13 * Copyright (C) 2004-2005 Trusted Computer Solutions, Inc. 13 * Copyright (C) 2004-2005 Trusted Computer Solutions, Inc.
14 * <dgoeddel@trustedcs.com> 14 * <dgoeddel@trustedcs.com>
15 * Copyright (C) 2006 Hewlett-Packard Development Company, L.P.
16 * Paul Moore, <paul.moore@hp.com>
15 * 17 *
16 * This program is free software; you can redistribute it and/or modify 18 * This program is free software; you can redistribute it and/or modify
17 * it under the terms of the GNU General Public License version 2, 19 * it under the terms of the GNU General Public License version 2,
@@ -74,6 +76,7 @@
74#include "objsec.h" 76#include "objsec.h"
75#include "netif.h" 77#include "netif.h"
76#include "xfrm.h" 78#include "xfrm.h"
79#include "selinux_netlabel.h"
77 80
78#define XATTR_SELINUX_SUFFIX "selinux" 81#define XATTR_SELINUX_SUFFIX "selinux"
79#define XATTR_NAME_SELINUX XATTR_SECURITY_PREFIX XATTR_SELINUX_SUFFIX 82#define XATTR_NAME_SELINUX XATTR_SECURITY_PREFIX XATTR_SELINUX_SUFFIX
@@ -269,17 +272,17 @@ static int sk_alloc_security(struct sock *sk, int family, gfp_t priority)
269{ 272{
270 struct sk_security_struct *ssec; 273 struct sk_security_struct *ssec;
271 274
272 if (family != PF_UNIX)
273 return 0;
274
275 ssec = kzalloc(sizeof(*ssec), priority); 275 ssec = kzalloc(sizeof(*ssec), priority);
276 if (!ssec) 276 if (!ssec)
277 return -ENOMEM; 277 return -ENOMEM;
278 278
279 ssec->sk = sk; 279 ssec->sk = sk;
280 ssec->peer_sid = SECINITSID_UNLABELED; 280 ssec->peer_sid = SECINITSID_UNLABELED;
281 ssec->sid = SECINITSID_UNLABELED;
281 sk->sk_security = ssec; 282 sk->sk_security = ssec;
282 283
284 selinux_netlbl_sk_security_init(ssec, family);
285
283 return 0; 286 return 0;
284} 287}
285 288
@@ -287,9 +290,6 @@ static void sk_free_security(struct sock *sk)
287{ 290{
288 struct sk_security_struct *ssec = sk->sk_security; 291 struct sk_security_struct *ssec = sk->sk_security;
289 292
290 if (sk->sk_family != PF_UNIX)
291 return;
292
293 sk->sk_security = NULL; 293 sk->sk_security = NULL;
294 kfree(ssec); 294 kfree(ssec);
295} 295}
@@ -2400,6 +2400,7 @@ static int selinux_inode_listsecurity(struct inode *inode, char *buffer, size_t
2400 2400
2401static int selinux_file_permission(struct file *file, int mask) 2401static int selinux_file_permission(struct file *file, int mask)
2402{ 2402{
2403 int rc;
2403 struct inode *inode = file->f_dentry->d_inode; 2404 struct inode *inode = file->f_dentry->d_inode;
2404 2405
2405 if (!mask) { 2406 if (!mask) {
@@ -2411,8 +2412,12 @@ static int selinux_file_permission(struct file *file, int mask)
2411 if ((file->f_flags & O_APPEND) && (mask & MAY_WRITE)) 2412 if ((file->f_flags & O_APPEND) && (mask & MAY_WRITE))
2412 mask |= MAY_APPEND; 2413 mask |= MAY_APPEND;
2413 2414
2414 return file_has_perm(current, file, 2415 rc = file_has_perm(current, file,
2415 file_mask_to_av(inode->i_mode, mask)); 2416 file_mask_to_av(inode->i_mode, mask));
2417 if (rc)
2418 return rc;
2419
2420 return selinux_netlbl_inode_permission(inode, mask);
2416} 2421}
2417 2422
2418static int selinux_file_alloc_security(struct file *file) 2423static int selinux_file_alloc_security(struct file *file)
@@ -3063,11 +3068,13 @@ out:
3063 return err; 3068 return err;
3064} 3069}
3065 3070
3066static void selinux_socket_post_create(struct socket *sock, int family, 3071static int selinux_socket_post_create(struct socket *sock, int family,
3067 int type, int protocol, int kern) 3072 int type, int protocol, int kern)
3068{ 3073{
3074 int err = 0;
3069 struct inode_security_struct *isec; 3075 struct inode_security_struct *isec;
3070 struct task_security_struct *tsec; 3076 struct task_security_struct *tsec;
3077 struct sk_security_struct *sksec;
3071 u32 newsid; 3078 u32 newsid;
3072 3079
3073 isec = SOCK_INODE(sock)->i_security; 3080 isec = SOCK_INODE(sock)->i_security;
@@ -3078,7 +3085,15 @@ static void selinux_socket_post_create(struct socket *sock, int family,
3078 isec->sid = kern ? SECINITSID_KERNEL : newsid; 3085 isec->sid = kern ? SECINITSID_KERNEL : newsid;
3079 isec->initialized = 1; 3086 isec->initialized = 1;
3080 3087
3081 return; 3088 if (sock->sk) {
3089 sksec = sock->sk->sk_security;
3090 sksec->sid = isec->sid;
3091 err = selinux_netlbl_socket_post_create(sock,
3092 family,
3093 isec->sid);
3094 }
3095
3096 return err;
3082} 3097}
3083 3098
3084/* Range of port numbers used to automatically bind. 3099/* Range of port numbers used to automatically bind.
@@ -3259,7 +3274,13 @@ static int selinux_socket_accept(struct socket *sock, struct socket *newsock)
3259static int selinux_socket_sendmsg(struct socket *sock, struct msghdr *msg, 3274static int selinux_socket_sendmsg(struct socket *sock, struct msghdr *msg,
3260 int size) 3275 int size)
3261{ 3276{
3262 return socket_has_perm(current, sock, SOCKET__WRITE); 3277 int rc;
3278
3279 rc = socket_has_perm(current, sock, SOCKET__WRITE);
3280 if (rc)
3281 return rc;
3282
3283 return selinux_netlbl_inode_permission(SOCK_INODE(sock), MAY_WRITE);
3263} 3284}
3264 3285
3265static int selinux_socket_recvmsg(struct socket *sock, struct msghdr *msg, 3286static int selinux_socket_recvmsg(struct socket *sock, struct msghdr *msg,
@@ -3327,8 +3348,9 @@ static int selinux_socket_unix_stream_connect(struct socket *sock,
3327 /* server child socket */ 3348 /* server child socket */
3328 ssec = newsk->sk_security; 3349 ssec = newsk->sk_security;
3329 ssec->peer_sid = isec->sid; 3350 ssec->peer_sid = isec->sid;
3330 3351 err = security_sid_mls_copy(other_isec->sid, ssec->peer_sid, &ssec->sid);
3331 return 0; 3352
3353 return err;
3332} 3354}
3333 3355
3334static int selinux_socket_unix_may_send(struct socket *sock, 3356static int selinux_socket_unix_may_send(struct socket *sock,
@@ -3354,11 +3376,29 @@ static int selinux_socket_unix_may_send(struct socket *sock,
3354} 3376}
3355 3377
3356static int selinux_sock_rcv_skb_compat(struct sock *sk, struct sk_buff *skb, 3378static int selinux_sock_rcv_skb_compat(struct sock *sk, struct sk_buff *skb,
3357 struct avc_audit_data *ad, u32 sock_sid, u16 sock_class, 3379 struct avc_audit_data *ad, u16 family, char *addrp, int len)
3358 u16 family, char *addrp, int len)
3359{ 3380{
3360 int err = 0; 3381 int err = 0;
3361 u32 netif_perm, node_perm, node_sid, if_sid, recv_perm = 0; 3382 u32 netif_perm, node_perm, node_sid, if_sid, recv_perm = 0;
3383 struct socket *sock;
3384 u16 sock_class = 0;
3385 u32 sock_sid = 0;
3386
3387 read_lock_bh(&sk->sk_callback_lock);
3388 sock = sk->sk_socket;
3389 if (sock) {
3390 struct inode *inode;
3391 inode = SOCK_INODE(sock);
3392 if (inode) {
3393 struct inode_security_struct *isec;
3394 isec = inode->i_security;
3395 sock_sid = isec->sid;
3396 sock_class = isec->sclass;
3397 }
3398 }
3399 read_unlock_bh(&sk->sk_callback_lock);
3400 if (!sock_sid)
3401 goto out;
3362 3402
3363 if (!skb->dev) 3403 if (!skb->dev)
3364 goto out; 3404 goto out;
@@ -3418,12 +3458,10 @@ out:
3418static int selinux_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb) 3458static int selinux_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb)
3419{ 3459{
3420 u16 family; 3460 u16 family;
3421 u16 sock_class = 0;
3422 char *addrp; 3461 char *addrp;
3423 int len, err = 0; 3462 int len, err = 0;
3424 u32 sock_sid = 0;
3425 struct socket *sock;
3426 struct avc_audit_data ad; 3463 struct avc_audit_data ad;
3464 struct sk_security_struct *sksec = sk->sk_security;
3427 3465
3428 family = sk->sk_family; 3466 family = sk->sk_family;
3429 if (family != PF_INET && family != PF_INET6) 3467 if (family != PF_INET && family != PF_INET6)
@@ -3433,22 +3471,6 @@ static int selinux_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb)
3433 if (family == PF_INET6 && skb->protocol == ntohs(ETH_P_IP)) 3471 if (family == PF_INET6 && skb->protocol == ntohs(ETH_P_IP))
3434 family = PF_INET; 3472 family = PF_INET;
3435 3473
3436 read_lock_bh(&sk->sk_callback_lock);
3437 sock = sk->sk_socket;
3438 if (sock) {
3439 struct inode *inode;
3440 inode = SOCK_INODE(sock);
3441 if (inode) {
3442 struct inode_security_struct *isec;
3443 isec = inode->i_security;
3444 sock_sid = isec->sid;
3445 sock_class = isec->sclass;
3446 }
3447 }
3448 read_unlock_bh(&sk->sk_callback_lock);
3449 if (!sock_sid)
3450 goto out;
3451
3452 AVC_AUDIT_DATA_INIT(&ad, NET); 3474 AVC_AUDIT_DATA_INIT(&ad, NET);
3453 ad.u.net.netif = skb->dev ? skb->dev->name : "[unknown]"; 3475 ad.u.net.netif = skb->dev ? skb->dev->name : "[unknown]";
3454 ad.u.net.family = family; 3476 ad.u.net.family = family;
@@ -3458,16 +3480,19 @@ static int selinux_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb)
3458 goto out; 3480 goto out;
3459 3481
3460 if (selinux_compat_net) 3482 if (selinux_compat_net)
3461 err = selinux_sock_rcv_skb_compat(sk, skb, &ad, sock_sid, 3483 err = selinux_sock_rcv_skb_compat(sk, skb, &ad, family,
3462 sock_class, family,
3463 addrp, len); 3484 addrp, len);
3464 else 3485 else
3465 err = avc_has_perm(sock_sid, skb->secmark, SECCLASS_PACKET, 3486 err = avc_has_perm(sksec->sid, skb->secmark, SECCLASS_PACKET,
3466 PACKET__RECV, &ad); 3487 PACKET__RECV, &ad);
3467 if (err) 3488 if (err)
3468 goto out; 3489 goto out;
3469 3490
3470 err = selinux_xfrm_sock_rcv_skb(sock_sid, skb); 3491 err = selinux_netlbl_sock_rcv_skb(sksec, skb, &ad);
3492 if (err)
3493 goto out;
3494
3495 err = selinux_xfrm_sock_rcv_skb(sksec->sid, skb, &ad);
3471out: 3496out:
3472 return err; 3497 return err;
3473} 3498}
@@ -3490,8 +3515,9 @@ static int selinux_socket_getpeersec_stream(struct socket *sock, char __user *op
3490 peer_sid = ssec->peer_sid; 3515 peer_sid = ssec->peer_sid;
3491 } 3516 }
3492 else if (isec->sclass == SECCLASS_TCP_SOCKET) { 3517 else if (isec->sclass == SECCLASS_TCP_SOCKET) {
3493 peer_sid = selinux_socket_getpeer_stream(sock->sk); 3518 peer_sid = selinux_netlbl_socket_getpeersec_stream(sock);
3494 3519 if (peer_sid == SECSID_NULL)
3520 peer_sid = selinux_socket_getpeer_stream(sock->sk);
3495 if (peer_sid == SECSID_NULL) { 3521 if (peer_sid == SECSID_NULL) {
3496 err = -ENOPROTOOPT; 3522 err = -ENOPROTOOPT;
3497 goto out; 3523 goto out;
@@ -3531,8 +3557,11 @@ static int selinux_socket_getpeersec_dgram(struct socket *sock, struct sk_buff *
3531 3557
3532 if (sock && (sock->sk->sk_family == PF_UNIX)) 3558 if (sock && (sock->sk->sk_family == PF_UNIX))
3533 selinux_get_inode_sid(SOCK_INODE(sock), &peer_secid); 3559 selinux_get_inode_sid(SOCK_INODE(sock), &peer_secid);
3534 else if (skb) 3560 else if (skb) {
3535 peer_secid = selinux_socket_getpeer_dgram(skb); 3561 peer_secid = selinux_netlbl_socket_getpeersec_dgram(skb);
3562 if (peer_secid == SECSID_NULL)
3563 peer_secid = selinux_socket_getpeer_dgram(skb);
3564 }
3536 3565
3537 if (peer_secid == SECSID_NULL) 3566 if (peer_secid == SECSID_NULL)
3538 err = -EINVAL; 3567 err = -EINVAL;
@@ -3551,22 +3580,86 @@ static void selinux_sk_free_security(struct sock *sk)
3551 sk_free_security(sk); 3580 sk_free_security(sk);
3552} 3581}
3553 3582
3554static unsigned int selinux_sk_getsid_security(struct sock *sk, struct flowi *fl, u8 dir) 3583static void selinux_sk_clone_security(const struct sock *sk, struct sock *newsk)
3555{ 3584{
3556 struct inode_security_struct *isec; 3585 struct sk_security_struct *ssec = sk->sk_security;
3557 u32 sock_sid = SECINITSID_ANY_SOCKET; 3586 struct sk_security_struct *newssec = newsk->sk_security;
3587
3588 newssec->sid = ssec->sid;
3589 newssec->peer_sid = ssec->peer_sid;
3558 3590
3591 selinux_netlbl_sk_clone_security(ssec, newssec);
3592}
3593
3594static void selinux_sk_getsecid(struct sock *sk, u32 *secid)
3595{
3559 if (!sk) 3596 if (!sk)
3560 return selinux_no_sk_sid(fl); 3597 *secid = SECINITSID_ANY_SOCKET;
3598 else {
3599 struct sk_security_struct *sksec = sk->sk_security;
3600
3601 *secid = sksec->sid;
3602 }
3603}
3604
3605static void selinux_sock_graft(struct sock* sk, struct socket *parent)
3606{
3607 struct inode_security_struct *isec = SOCK_INODE(parent)->i_security;
3608 struct sk_security_struct *sksec = sk->sk_security;
3609
3610 isec->sid = sksec->sid;
3611
3612 selinux_netlbl_sock_graft(sk, parent);
3613}
3614
3615static int selinux_inet_conn_request(struct sock *sk, struct sk_buff *skb,
3616 struct request_sock *req)
3617{
3618 struct sk_security_struct *sksec = sk->sk_security;
3619 int err;
3620 u32 newsid;
3621 u32 peersid;
3622
3623 newsid = selinux_netlbl_inet_conn_request(skb, sksec->sid);
3624 if (newsid != SECSID_NULL) {
3625 req->secid = newsid;
3626 return 0;
3627 }
3628
3629 err = selinux_xfrm_decode_session(skb, &peersid, 0);
3630 BUG_ON(err);
3631
3632 if (peersid == SECSID_NULL) {
3633 req->secid = sksec->sid;
3634 return 0;
3635 }
3636
3637 err = security_sid_mls_copy(sksec->sid, peersid, &newsid);
3638 if (err)
3639 return err;
3640
3641 req->secid = newsid;
3642 return 0;
3643}
3644
3645static void selinux_inet_csk_clone(struct sock *newsk,
3646 const struct request_sock *req)
3647{
3648 struct sk_security_struct *newsksec = newsk->sk_security;
3561 3649
3562 read_lock_bh(&sk->sk_callback_lock); 3650 newsksec->sid = req->secid;
3563 isec = get_sock_isec(sk); 3651 /* NOTE: Ideally, we should also get the isec->sid for the
3652 new socket in sync, but we don't have the isec available yet.
3653 So we will wait until sock_graft to do it, by which
3654 time it will have been created and available. */
3564 3655
3565 if (isec) 3656 selinux_netlbl_sk_security_init(newsksec, req->rsk_ops->family);
3566 sock_sid = isec->sid; 3657}
3567 3658
3568 read_unlock_bh(&sk->sk_callback_lock); 3659static void selinux_req_classify_flow(const struct request_sock *req,
3569 return sock_sid; 3660 struct flowi *fl)
3661{
3662 fl->secid = req->secid;
3570} 3663}
3571 3664
3572static int selinux_nlmsg_perm(struct sock *sk, struct sk_buff *skb) 3665static int selinux_nlmsg_perm(struct sock *sk, struct sk_buff *skb)
@@ -3608,12 +3701,24 @@ out:
3608#ifdef CONFIG_NETFILTER 3701#ifdef CONFIG_NETFILTER
3609 3702
3610static int selinux_ip_postroute_last_compat(struct sock *sk, struct net_device *dev, 3703static int selinux_ip_postroute_last_compat(struct sock *sk, struct net_device *dev,
3611 struct inode_security_struct *isec,
3612 struct avc_audit_data *ad, 3704 struct avc_audit_data *ad,
3613 u16 family, char *addrp, int len) 3705 u16 family, char *addrp, int len)
3614{ 3706{
3615 int err; 3707 int err = 0;
3616 u32 netif_perm, node_perm, node_sid, if_sid, send_perm = 0; 3708 u32 netif_perm, node_perm, node_sid, if_sid, send_perm = 0;
3709 struct socket *sock;
3710 struct inode *inode;
3711 struct inode_security_struct *isec;
3712
3713 sock = sk->sk_socket;
3714 if (!sock)
3715 goto out;
3716
3717 inode = SOCK_INODE(sock);
3718 if (!inode)
3719 goto out;
3720
3721 isec = inode->i_security;
3617 3722
3618 err = sel_netif_sids(dev, &if_sid, NULL); 3723 err = sel_netif_sids(dev, &if_sid, NULL);
3619 if (err) 3724 if (err)
@@ -3678,26 +3783,16 @@ static unsigned int selinux_ip_postroute_last(unsigned int hooknum,
3678 char *addrp; 3783 char *addrp;
3679 int len, err = 0; 3784 int len, err = 0;
3680 struct sock *sk; 3785 struct sock *sk;
3681 struct socket *sock;
3682 struct inode *inode;
3683 struct sk_buff *skb = *pskb; 3786 struct sk_buff *skb = *pskb;
3684 struct inode_security_struct *isec;
3685 struct avc_audit_data ad; 3787 struct avc_audit_data ad;
3686 struct net_device *dev = (struct net_device *)out; 3788 struct net_device *dev = (struct net_device *)out;
3789 struct sk_security_struct *sksec;
3687 3790
3688 sk = skb->sk; 3791 sk = skb->sk;
3689 if (!sk) 3792 if (!sk)
3690 goto out; 3793 goto out;
3691 3794
3692 sock = sk->sk_socket; 3795 sksec = sk->sk_security;
3693 if (!sock)
3694 goto out;
3695
3696 inode = SOCK_INODE(sock);
3697 if (!inode)
3698 goto out;
3699
3700 isec = inode->i_security;
3701 3796
3702 AVC_AUDIT_DATA_INIT(&ad, NET); 3797 AVC_AUDIT_DATA_INIT(&ad, NET);
3703 ad.u.net.netif = dev->name; 3798 ad.u.net.netif = dev->name;
@@ -3708,16 +3803,16 @@ static unsigned int selinux_ip_postroute_last(unsigned int hooknum,
3708 goto out; 3803 goto out;
3709 3804
3710 if (selinux_compat_net) 3805 if (selinux_compat_net)
3711 err = selinux_ip_postroute_last_compat(sk, dev, isec, &ad, 3806 err = selinux_ip_postroute_last_compat(sk, dev, &ad,
3712 family, addrp, len); 3807 family, addrp, len);
3713 else 3808 else
3714 err = avc_has_perm(isec->sid, skb->secmark, SECCLASS_PACKET, 3809 err = avc_has_perm(sksec->sid, skb->secmark, SECCLASS_PACKET,
3715 PACKET__SEND, &ad); 3810 PACKET__SEND, &ad);
3716 3811
3717 if (err) 3812 if (err)
3718 goto out; 3813 goto out;
3719 3814
3720 err = selinux_xfrm_postroute_last(isec->sid, skb); 3815 err = selinux_xfrm_postroute_last(sksec->sid, skb, &ad);
3721out: 3816out:
3722 return err ? NF_DROP : NF_ACCEPT; 3817 return err ? NF_DROP : NF_ACCEPT;
3723} 3818}
@@ -4618,7 +4713,12 @@ static struct security_operations selinux_ops = {
4618 .socket_getpeersec_dgram = selinux_socket_getpeersec_dgram, 4713 .socket_getpeersec_dgram = selinux_socket_getpeersec_dgram,
4619 .sk_alloc_security = selinux_sk_alloc_security, 4714 .sk_alloc_security = selinux_sk_alloc_security,
4620 .sk_free_security = selinux_sk_free_security, 4715 .sk_free_security = selinux_sk_free_security,
4621 .sk_getsid = selinux_sk_getsid_security, 4716 .sk_clone_security = selinux_sk_clone_security,
4717 .sk_getsecid = selinux_sk_getsecid,
4718 .sock_graft = selinux_sock_graft,
4719 .inet_conn_request = selinux_inet_conn_request,
4720 .inet_csk_clone = selinux_inet_csk_clone,
4721 .req_classify_flow = selinux_req_classify_flow,
4622 4722
4623#ifdef CONFIG_SECURITY_NETWORK_XFRM 4723#ifdef CONFIG_SECURITY_NETWORK_XFRM
4624 .xfrm_policy_alloc_security = selinux_xfrm_policy_alloc, 4724 .xfrm_policy_alloc_security = selinux_xfrm_policy_alloc,
@@ -4629,6 +4729,9 @@ static struct security_operations selinux_ops = {
4629 .xfrm_state_free_security = selinux_xfrm_state_free, 4729 .xfrm_state_free_security = selinux_xfrm_state_free,
4630 .xfrm_state_delete_security = selinux_xfrm_state_delete, 4730 .xfrm_state_delete_security = selinux_xfrm_state_delete,
4631 .xfrm_policy_lookup = selinux_xfrm_policy_lookup, 4731 .xfrm_policy_lookup = selinux_xfrm_policy_lookup,
4732 .xfrm_state_pol_flow_match = selinux_xfrm_state_pol_flow_match,
4733 .xfrm_flow_state_match = selinux_xfrm_flow_state_match,
4734 .xfrm_decode_session = selinux_xfrm_decode_session,
4632#endif 4735#endif
4633 4736
4634#ifdef CONFIG_KEYS 4737#ifdef CONFIG_KEYS
diff --git a/security/selinux/include/av_perm_to_string.h b/security/selinux/include/av_perm_to_string.h
index 7c9b58380833..09fc8a2345eb 100644
--- a/security/selinux/include/av_perm_to_string.h
+++ b/security/selinux/include/av_perm_to_string.h
@@ -241,6 +241,7 @@
241 S_(SECCLASS_ASSOCIATION, ASSOCIATION__SENDTO, "sendto") 241 S_(SECCLASS_ASSOCIATION, ASSOCIATION__SENDTO, "sendto")
242 S_(SECCLASS_ASSOCIATION, ASSOCIATION__RECVFROM, "recvfrom") 242 S_(SECCLASS_ASSOCIATION, ASSOCIATION__RECVFROM, "recvfrom")
243 S_(SECCLASS_ASSOCIATION, ASSOCIATION__SETCONTEXT, "setcontext") 243 S_(SECCLASS_ASSOCIATION, ASSOCIATION__SETCONTEXT, "setcontext")
244 S_(SECCLASS_ASSOCIATION, ASSOCIATION__POLMATCH, "polmatch")
244 S_(SECCLASS_PACKET, PACKET__SEND, "send") 245 S_(SECCLASS_PACKET, PACKET__SEND, "send")
245 S_(SECCLASS_PACKET, PACKET__RECV, "recv") 246 S_(SECCLASS_PACKET, PACKET__RECV, "recv")
246 S_(SECCLASS_PACKET, PACKET__RELABELTO, "relabelto") 247 S_(SECCLASS_PACKET, PACKET__RELABELTO, "relabelto")
diff --git a/security/selinux/include/av_permissions.h b/security/selinux/include/av_permissions.h
index 69fd4b48202c..81f4f526c8b1 100644
--- a/security/selinux/include/av_permissions.h
+++ b/security/selinux/include/av_permissions.h
@@ -911,6 +911,7 @@
911#define ASSOCIATION__SENDTO 0x00000001UL 911#define ASSOCIATION__SENDTO 0x00000001UL
912#define ASSOCIATION__RECVFROM 0x00000002UL 912#define ASSOCIATION__RECVFROM 0x00000002UL
913#define ASSOCIATION__SETCONTEXT 0x00000004UL 913#define ASSOCIATION__SETCONTEXT 0x00000004UL
914#define ASSOCIATION__POLMATCH 0x00000008UL
914 915
915#define NETLINK_KOBJECT_UEVENT_SOCKET__IOCTL 0x00000001UL 916#define NETLINK_KOBJECT_UEVENT_SOCKET__IOCTL 0x00000001UL
916#define NETLINK_KOBJECT_UEVENT_SOCKET__READ 0x00000002UL 917#define NETLINK_KOBJECT_UEVENT_SOCKET__READ 0x00000002UL
diff --git a/security/selinux/include/objsec.h b/security/selinux/include/objsec.h
index 940178865fc7..0a39bfd1319f 100644
--- a/security/selinux/include/objsec.h
+++ b/security/selinux/include/objsec.h
@@ -99,7 +99,16 @@ struct netif_security_struct {
99 99
100struct sk_security_struct { 100struct sk_security_struct {
101 struct sock *sk; /* back pointer to sk object */ 101 struct sock *sk; /* back pointer to sk object */
102 u32 sid; /* SID of this object */
102 u32 peer_sid; /* SID of peer */ 103 u32 peer_sid; /* SID of peer */
104#ifdef CONFIG_NETLABEL
105 u16 sclass; /* sock security class */
106 enum { /* NetLabel state */
107 NLBL_UNSET = 0,
108 NLBL_REQUIRE,
109 NLBL_LABELED,
110 } nlbl_state;
111#endif
103}; 112};
104 113
105struct key_security_struct { 114struct key_security_struct {
diff --git a/security/selinux/include/security.h b/security/selinux/include/security.h
index 063af47bb231..911954a692fa 100644
--- a/security/selinux/include/security.h
+++ b/security/selinux/include/security.h
@@ -78,6 +78,8 @@ int security_node_sid(u16 domain, void *addr, u32 addrlen,
78int security_validate_transition(u32 oldsid, u32 newsid, u32 tasksid, 78int security_validate_transition(u32 oldsid, u32 newsid, u32 tasksid,
79 u16 tclass); 79 u16 tclass);
80 80
81int security_sid_mls_copy(u32 sid, u32 mls_sid, u32 *new_sid);
82
81#define SECURITY_FS_USE_XATTR 1 /* use xattr */ 83#define SECURITY_FS_USE_XATTR 1 /* use xattr */
82#define SECURITY_FS_USE_TRANS 2 /* use transition SIDs, e.g. devpts/tmpfs */ 84#define SECURITY_FS_USE_TRANS 2 /* use transition SIDs, e.g. devpts/tmpfs */
83#define SECURITY_FS_USE_TASK 3 /* use task SIDs, e.g. pipefs/sockfs */ 85#define SECURITY_FS_USE_TASK 3 /* use task SIDs, e.g. pipefs/sockfs */
diff --git a/security/selinux/include/selinux_netlabel.h b/security/selinux/include/selinux_netlabel.h
new file mode 100644
index 000000000000..ecab4bddaaf4
--- /dev/null
+++ b/security/selinux/include/selinux_netlabel.h
@@ -0,0 +1,119 @@
1/*
2 * SELinux interface to the NetLabel subsystem
3 *
4 * Author : Paul Moore <paul.moore@hp.com>
5 *
6 */
7
8/*
9 * (c) Copyright Hewlett-Packard Development Company, L.P., 2006
10 *
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
15 *
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
19 * the GNU General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 *
25 */
26
27#ifndef _SELINUX_NETLABEL_H_
28#define _SELINUX_NETLABEL_H_
29
30#include <linux/types.h>
31#include <linux/fs.h>
32#include <linux/net.h>
33#include <linux/skbuff.h>
34#include <net/sock.h>
35
36#include "avc.h"
37#include "objsec.h"
38
39#ifdef CONFIG_NETLABEL
40void selinux_netlbl_cache_invalidate(void);
41int selinux_netlbl_socket_post_create(struct socket *sock,
42 int sock_family,
43 u32 sid);
44void selinux_netlbl_sock_graft(struct sock *sk, struct socket *sock);
45u32 selinux_netlbl_inet_conn_request(struct sk_buff *skb, u32 sock_sid);
46int selinux_netlbl_sock_rcv_skb(struct sk_security_struct *sksec,
47 struct sk_buff *skb,
48 struct avc_audit_data *ad);
49u32 selinux_netlbl_socket_getpeersec_stream(struct socket *sock);
50u32 selinux_netlbl_socket_getpeersec_dgram(struct sk_buff *skb);
51void selinux_netlbl_sk_security_init(struct sk_security_struct *ssec,
52 int family);
53void selinux_netlbl_sk_clone_security(struct sk_security_struct *ssec,
54 struct sk_security_struct *newssec);
55int selinux_netlbl_inode_permission(struct inode *inode, int mask);
56#else
57static inline void selinux_netlbl_cache_invalidate(void)
58{
59 return;
60}
61
62static inline int selinux_netlbl_socket_post_create(struct socket *sock,
63 int sock_family,
64 u32 sid)
65{
66 return 0;
67}
68
69static inline void selinux_netlbl_sock_graft(struct sock *sk,
70 struct socket *sock)
71{
72 return;
73}
74
75static inline u32 selinux_netlbl_inet_conn_request(struct sk_buff *skb,
76 u32 sock_sid)
77{
78 return SECSID_NULL;
79}
80
81static inline int selinux_netlbl_sock_rcv_skb(struct sk_security_struct *sksec,
82 struct sk_buff *skb,
83 struct avc_audit_data *ad)
84{
85 return 0;
86}
87
88static inline u32 selinux_netlbl_socket_getpeersec_stream(struct socket *sock)
89{
90 return SECSID_NULL;
91}
92
93static inline u32 selinux_netlbl_socket_getpeersec_dgram(struct sk_buff *skb)
94{
95 return SECSID_NULL;
96}
97
98static inline void selinux_netlbl_sk_security_init(
99 struct sk_security_struct *ssec,
100 int family)
101{
102 return;
103}
104
105static inline void selinux_netlbl_sk_clone_security(
106 struct sk_security_struct *ssec,
107 struct sk_security_struct *newssec)
108{
109 return;
110}
111
112static inline int selinux_netlbl_inode_permission(struct inode *inode,
113 int mask)
114{
115 return 0;
116}
117#endif /* CONFIG_NETLABEL */
118
119#endif
diff --git a/security/selinux/include/xfrm.h b/security/selinux/include/xfrm.h
index c96498a10eb8..81eb59890162 100644
--- a/security/selinux/include/xfrm.h
+++ b/security/selinux/include/xfrm.h
@@ -2,18 +2,25 @@
2 * SELinux support for the XFRM LSM hooks 2 * SELinux support for the XFRM LSM hooks
3 * 3 *
4 * Author : Trent Jaeger, <jaegert@us.ibm.com> 4 * Author : Trent Jaeger, <jaegert@us.ibm.com>
5 * Updated : Venkat Yekkirala, <vyekkirala@TrustedCS.com>
5 */ 6 */
6#ifndef _SELINUX_XFRM_H_ 7#ifndef _SELINUX_XFRM_H_
7#define _SELINUX_XFRM_H_ 8#define _SELINUX_XFRM_H_
8 9
9int selinux_xfrm_policy_alloc(struct xfrm_policy *xp, struct xfrm_user_sec_ctx *sec_ctx); 10int selinux_xfrm_policy_alloc(struct xfrm_policy *xp,
11 struct xfrm_user_sec_ctx *sec_ctx, struct sock *sk);
10int selinux_xfrm_policy_clone(struct xfrm_policy *old, struct xfrm_policy *new); 12int selinux_xfrm_policy_clone(struct xfrm_policy *old, struct xfrm_policy *new);
11void selinux_xfrm_policy_free(struct xfrm_policy *xp); 13void selinux_xfrm_policy_free(struct xfrm_policy *xp);
12int selinux_xfrm_policy_delete(struct xfrm_policy *xp); 14int selinux_xfrm_policy_delete(struct xfrm_policy *xp);
13int selinux_xfrm_state_alloc(struct xfrm_state *x, struct xfrm_user_sec_ctx *sec_ctx); 15int selinux_xfrm_state_alloc(struct xfrm_state *x,
16 struct xfrm_user_sec_ctx *sec_ctx, struct xfrm_sec_ctx *pol, u32 secid);
14void selinux_xfrm_state_free(struct xfrm_state *x); 17void selinux_xfrm_state_free(struct xfrm_state *x);
15int selinux_xfrm_state_delete(struct xfrm_state *x); 18int selinux_xfrm_state_delete(struct xfrm_state *x);
16int selinux_xfrm_policy_lookup(struct xfrm_policy *xp, u32 sk_sid, u8 dir); 19int selinux_xfrm_policy_lookup(struct xfrm_policy *xp, u32 fl_secid, u8 dir);
20int selinux_xfrm_state_pol_flow_match(struct xfrm_state *x,
21 struct xfrm_policy *xp, struct flowi *fl);
22int selinux_xfrm_flow_state_match(struct flowi *fl, struct xfrm_state *xfrm);
23
17 24
18/* 25/*
19 * Extract the security blob from the sock (it's actually on the socket) 26 * Extract the security blob from the sock (it's actually on the socket)
@@ -26,30 +33,23 @@ static inline struct inode_security_struct *get_sock_isec(struct sock *sk)
26 return SOCK_INODE(sk->sk_socket)->i_security; 33 return SOCK_INODE(sk->sk_socket)->i_security;
27} 34}
28 35
29
30static inline u32 selinux_no_sk_sid(struct flowi *fl)
31{
32 /* NOTE: no sock occurs on ICMP reply, forwards, ... */
33 /* icmp_reply: authorize as kernel packet */
34 if (fl && fl->proto == IPPROTO_ICMP) {
35 return SECINITSID_KERNEL;
36 }
37
38 return SECINITSID_ANY_SOCKET;
39}
40
41#ifdef CONFIG_SECURITY_NETWORK_XFRM 36#ifdef CONFIG_SECURITY_NETWORK_XFRM
42int selinux_xfrm_sock_rcv_skb(u32 sid, struct sk_buff *skb); 37int selinux_xfrm_sock_rcv_skb(u32 sid, struct sk_buff *skb,
43int selinux_xfrm_postroute_last(u32 isec_sid, struct sk_buff *skb); 38 struct avc_audit_data *ad);
39int selinux_xfrm_postroute_last(u32 isec_sid, struct sk_buff *skb,
40 struct avc_audit_data *ad);
44u32 selinux_socket_getpeer_stream(struct sock *sk); 41u32 selinux_socket_getpeer_stream(struct sock *sk);
45u32 selinux_socket_getpeer_dgram(struct sk_buff *skb); 42u32 selinux_socket_getpeer_dgram(struct sk_buff *skb);
43int selinux_xfrm_decode_session(struct sk_buff *skb, u32 *sid, int ckall);
46#else 44#else
47static inline int selinux_xfrm_sock_rcv_skb(u32 isec_sid, struct sk_buff *skb) 45static inline int selinux_xfrm_sock_rcv_skb(u32 isec_sid, struct sk_buff *skb,
46 struct avc_audit_data *ad)
48{ 47{
49 return 0; 48 return 0;
50} 49}
51 50
52static inline int selinux_xfrm_postroute_last(u32 isec_sid, struct sk_buff *skb) 51static inline int selinux_xfrm_postroute_last(u32 isec_sid, struct sk_buff *skb,
52 struct avc_audit_data *ad)
53{ 53{
54 return 0; 54 return 0;
55} 55}
@@ -63,6 +63,11 @@ static inline int selinux_socket_getpeer_dgram(struct sk_buff *skb)
63{ 63{
64 return SECSID_NULL; 64 return SECSID_NULL;
65} 65}
66static inline int selinux_xfrm_decode_session(struct sk_buff *skb, u32 *sid, int ckall)
67{
68 *sid = SECSID_NULL;
69 return 0;
70}
66#endif 71#endif
67 72
68#endif /* _SELINUX_XFRM_H_ */ 73#endif /* _SELINUX_XFRM_H_ */
diff --git a/security/selinux/ss/ebitmap.c b/security/selinux/ss/ebitmap.c
index 47024a6e1844..cfed1d30fa6a 100644
--- a/security/selinux/ss/ebitmap.c
+++ b/security/selinux/ss/ebitmap.c
@@ -3,6 +3,14 @@
3 * 3 *
4 * Author : Stephen Smalley, <sds@epoch.ncsc.mil> 4 * Author : Stephen Smalley, <sds@epoch.ncsc.mil>
5 */ 5 */
6/*
7 * Updated: Hewlett-Packard <paul.moore@hp.com>
8 *
9 * Added ebitmap_export() and ebitmap_import()
10 *
11 * (c) Copyright Hewlett-Packard Development Company, L.P., 2006
12 */
13
6#include <linux/kernel.h> 14#include <linux/kernel.h>
7#include <linux/slab.h> 15#include <linux/slab.h>
8#include <linux/errno.h> 16#include <linux/errno.h>
@@ -59,6 +67,138 @@ int ebitmap_cpy(struct ebitmap *dst, struct ebitmap *src)
59 return 0; 67 return 0;
60} 68}
61 69
70/**
71 * ebitmap_export - Export an ebitmap to a unsigned char bitmap string
72 * @src: the ebitmap to export
73 * @dst: the resulting bitmap string
74 * @dst_len: length of dst in bytes
75 *
76 * Description:
77 * Allocate a buffer at least src->highbit bits long and export the extensible
78 * bitmap into the buffer. The bitmap string will be in little endian format,
79 * i.e. LSB first. The value returned in dst_len may not the true size of the
80 * buffer as the length of the buffer is rounded up to a multiple of MAPTYPE.
81 * The caller must free the buffer when finished. Returns zero on success,
82 * negative values on failure.
83 *
84 */
85int ebitmap_export(const struct ebitmap *src,
86 unsigned char **dst,
87 size_t *dst_len)
88{
89 size_t bitmap_len;
90 unsigned char *bitmap;
91 struct ebitmap_node *iter_node;
92 MAPTYPE node_val;
93 size_t bitmap_byte;
94 unsigned char bitmask;
95
96 bitmap_len = src->highbit / 8;
97 if (src->highbit % 7)
98 bitmap_len += 1;
99 if (bitmap_len == 0)
100 return -EINVAL;
101
102 bitmap = kzalloc((bitmap_len & ~(sizeof(MAPTYPE) - 1)) +
103 sizeof(MAPTYPE),
104 GFP_ATOMIC);
105 if (bitmap == NULL)
106 return -ENOMEM;
107
108 iter_node = src->node;
109 do {
110 bitmap_byte = iter_node->startbit / 8;
111 bitmask = 0x80;
112 node_val = iter_node->map;
113 do {
114 if (bitmask == 0) {
115 bitmap_byte++;
116 bitmask = 0x80;
117 }
118 if (node_val & (MAPTYPE)0x01)
119 bitmap[bitmap_byte] |= bitmask;
120 node_val >>= 1;
121 bitmask >>= 1;
122 } while (node_val > 0);
123 iter_node = iter_node->next;
124 } while (iter_node);
125
126 *dst = bitmap;
127 *dst_len = bitmap_len;
128 return 0;
129}
130
131/**
132 * ebitmap_import - Import an unsigned char bitmap string into an ebitmap
133 * @src: the bitmap string
134 * @src_len: the bitmap length in bytes
135 * @dst: the empty ebitmap
136 *
137 * Description:
138 * This function takes a little endian bitmap string in src and imports it into
139 * the ebitmap pointed to by dst. Returns zero on success, negative values on
140 * failure.
141 *
142 */
143int ebitmap_import(const unsigned char *src,
144 size_t src_len,
145 struct ebitmap *dst)
146{
147 size_t src_off = 0;
148 size_t node_limit;
149 struct ebitmap_node *node_new;
150 struct ebitmap_node *node_last = NULL;
151 u32 i_byte;
152 u32 i_bit;
153 unsigned char src_byte;
154
155 while (src_off < src_len) {
156 if (src_len - src_off >= sizeof(MAPTYPE)) {
157 if (*(MAPTYPE *)&src[src_off] == 0) {
158 src_off += sizeof(MAPTYPE);
159 continue;
160 }
161 node_limit = sizeof(MAPTYPE);
162 } else {
163 for (src_byte = 0, i_byte = src_off;
164 i_byte < src_len && src_byte == 0;
165 i_byte++)
166 src_byte |= src[i_byte];
167 if (src_byte == 0)
168 break;
169 node_limit = src_len - src_off;
170 }
171
172 node_new = kzalloc(sizeof(*node_new), GFP_ATOMIC);
173 if (unlikely(node_new == NULL)) {
174 ebitmap_destroy(dst);
175 return -ENOMEM;
176 }
177 node_new->startbit = src_off * 8;
178 for (i_byte = 0; i_byte < node_limit; i_byte++) {
179 src_byte = src[src_off++];
180 for (i_bit = i_byte * 8; src_byte != 0; i_bit++) {
181 if (src_byte & 0x80)
182 node_new->map |= MAPBIT << i_bit;
183 src_byte <<= 1;
184 }
185 }
186
187 if (node_last != NULL)
188 node_last->next = node_new;
189 else
190 dst->node = node_new;
191 node_last = node_new;
192 }
193
194 if (likely(node_last != NULL))
195 dst->highbit = node_last->startbit + MAPSIZE;
196 else
197 ebitmap_init(dst);
198
199 return 0;
200}
201
62int ebitmap_contains(struct ebitmap *e1, struct ebitmap *e2) 202int ebitmap_contains(struct ebitmap *e1, struct ebitmap *e2)
63{ 203{
64 struct ebitmap_node *n1, *n2; 204 struct ebitmap_node *n1, *n2;
diff --git a/security/selinux/ss/ebitmap.h b/security/selinux/ss/ebitmap.h
index 8bf41055a6cb..da2d4651b10d 100644
--- a/security/selinux/ss/ebitmap.h
+++ b/security/selinux/ss/ebitmap.h
@@ -69,6 +69,12 @@ static inline int ebitmap_node_get_bit(struct ebitmap_node * n,
69 69
70int ebitmap_cmp(struct ebitmap *e1, struct ebitmap *e2); 70int ebitmap_cmp(struct ebitmap *e1, struct ebitmap *e2);
71int ebitmap_cpy(struct ebitmap *dst, struct ebitmap *src); 71int ebitmap_cpy(struct ebitmap *dst, struct ebitmap *src);
72int ebitmap_export(const struct ebitmap *src,
73 unsigned char **dst,
74 size_t *dst_len);
75int ebitmap_import(const unsigned char *src,
76 size_t src_len,
77 struct ebitmap *dst);
72int ebitmap_contains(struct ebitmap *e1, struct ebitmap *e2); 78int ebitmap_contains(struct ebitmap *e1, struct ebitmap *e2);
73int ebitmap_get_bit(struct ebitmap *e, unsigned long bit); 79int ebitmap_get_bit(struct ebitmap *e, unsigned long bit);
74int ebitmap_set_bit(struct ebitmap *e, unsigned long bit, int value); 80int ebitmap_set_bit(struct ebitmap *e, unsigned long bit, int value);
diff --git a/security/selinux/ss/mls.c b/security/selinux/ss/mls.c
index 7bc5b6440f70..119bd6078ba1 100644
--- a/security/selinux/ss/mls.c
+++ b/security/selinux/ss/mls.c
@@ -10,6 +10,13 @@
10 * 10 *
11 * Copyright (C) 2004-2006 Trusted Computer Solutions, Inc. 11 * Copyright (C) 2004-2006 Trusted Computer Solutions, Inc.
12 */ 12 */
13/*
14 * Updated: Hewlett-Packard <paul.moore@hp.com>
15 *
16 * Added support to import/export the MLS label
17 *
18 * (c) Copyright Hewlett-Packard Development Company, L.P., 2006
19 */
13 20
14#include <linux/kernel.h> 21#include <linux/kernel.h>
15#include <linux/slab.h> 22#include <linux/slab.h>
@@ -212,26 +219,6 @@ int mls_context_isvalid(struct policydb *p, struct context *c)
212} 219}
213 220
214/* 221/*
215 * Copies the MLS range from `src' into `dst'.
216 */
217static inline int mls_copy_context(struct context *dst,
218 struct context *src)
219{
220 int l, rc = 0;
221
222 /* Copy the MLS range from the source context */
223 for (l = 0; l < 2; l++) {
224 dst->range.level[l].sens = src->range.level[l].sens;
225 rc = ebitmap_cpy(&dst->range.level[l].cat,
226 &src->range.level[l].cat);
227 if (rc)
228 break;
229 }
230
231 return rc;
232}
233
234/*
235 * Set the MLS fields in the security context structure 222 * Set the MLS fields in the security context structure
236 * `context' based on the string representation in 223 * `context' based on the string representation in
237 * the string `*scontext'. Update `*scontext' to 224 * the string `*scontext'. Update `*scontext' to
@@ -585,3 +572,152 @@ int mls_compute_sid(struct context *scontext,
585 return -EINVAL; 572 return -EINVAL;
586} 573}
587 574
575/**
576 * mls_export_lvl - Export the MLS sensitivity levels
577 * @context: the security context
578 * @low: the low sensitivity level
579 * @high: the high sensitivity level
580 *
581 * Description:
582 * Given the security context copy the low MLS sensitivity level into lvl_low
583 * and the high sensitivity level in lvl_high. The MLS levels are only
584 * exported if the pointers are not NULL, if they are NULL then that level is
585 * not exported.
586 *
587 */
588void mls_export_lvl(const struct context *context, u32 *low, u32 *high)
589{
590 if (!selinux_mls_enabled)
591 return;
592
593 if (low != NULL)
594 *low = context->range.level[0].sens - 1;
595 if (high != NULL)
596 *high = context->range.level[1].sens - 1;
597}
598
599/**
600 * mls_import_lvl - Import the MLS sensitivity levels
601 * @context: the security context
602 * @low: the low sensitivity level
603 * @high: the high sensitivity level
604 *
605 * Description:
606 * Given the security context and the two sensitivty levels, set the MLS levels
607 * in the context according the two given as parameters. Returns zero on
608 * success, negative values on failure.
609 *
610 */
611void mls_import_lvl(struct context *context, u32 low, u32 high)
612{
613 if (!selinux_mls_enabled)
614 return;
615
616 context->range.level[0].sens = low + 1;
617 context->range.level[1].sens = high + 1;
618}
619
620/**
621 * mls_export_cat - Export the MLS categories
622 * @context: the security context
623 * @low: the low category
624 * @low_len: length of the cat_low bitmap in bytes
625 * @high: the high category
626 * @high_len: length of the cat_high bitmap in bytes
627 *
628 * Description:
629 * Given the security context export the low MLS category bitmap into cat_low
630 * and the high category bitmap into cat_high. The MLS categories are only
631 * exported if the pointers are not NULL, if they are NULL then that level is
632 * not exported. The caller is responsibile for freeing the memory when
633 * finished. Returns zero on success, negative values on failure.
634 *
635 */
636int mls_export_cat(const struct context *context,
637 unsigned char **low,
638 size_t *low_len,
639 unsigned char **high,
640 size_t *high_len)
641{
642 int rc = -EPERM;
643
644 if (!selinux_mls_enabled)
645 return 0;
646
647 if (low != NULL) {
648 rc = ebitmap_export(&context->range.level[0].cat,
649 low,
650 low_len);
651 if (rc != 0)
652 goto export_cat_failure;
653 }
654 if (high != NULL) {
655 rc = ebitmap_export(&context->range.level[1].cat,
656 high,
657 high_len);
658 if (rc != 0)
659 goto export_cat_failure;
660 }
661
662 return 0;
663
664export_cat_failure:
665 if (low != NULL)
666 kfree(*low);
667 if (high != NULL)
668 kfree(*high);
669 return rc;
670}
671
672/**
673 * mls_import_cat - Import the MLS categories
674 * @context: the security context
675 * @low: the low category
676 * @low_len: length of the cat_low bitmap in bytes
677 * @high: the high category
678 * @high_len: length of the cat_high bitmap in bytes
679 *
680 * Description:
681 * Given the security context and the two category bitmap strings import the
682 * categories into the security context. The MLS categories are only imported
683 * if the pointers are not NULL, if they are NULL they are skipped. Returns
684 * zero on success, negative values on failure.
685 *
686 */
687int mls_import_cat(struct context *context,
688 const unsigned char *low,
689 size_t low_len,
690 const unsigned char *high,
691 size_t high_len)
692{
693 int rc = -EPERM;
694
695 if (!selinux_mls_enabled)
696 return 0;
697
698 if (low != NULL) {
699 rc = ebitmap_import(low,
700 low_len,
701 &context->range.level[0].cat);
702 if (rc != 0)
703 goto import_cat_failure;
704 }
705 if (high != NULL) {
706 if (high == low)
707 rc = ebitmap_cpy(&context->range.level[1].cat,
708 &context->range.level[0].cat);
709 else
710 rc = ebitmap_import(high,
711 high_len,
712 &context->range.level[1].cat);
713 if (rc != 0)
714 goto import_cat_failure;
715 }
716
717 return 0;
718
719import_cat_failure:
720 ebitmap_destroy(&context->range.level[0].cat);
721 ebitmap_destroy(&context->range.level[1].cat);
722 return rc;
723}
diff --git a/security/selinux/ss/mls.h b/security/selinux/ss/mls.h
index fbb42f07dd7c..df6032c6d492 100644
--- a/security/selinux/ss/mls.h
+++ b/security/selinux/ss/mls.h
@@ -10,6 +10,13 @@
10 * 10 *
11 * Copyright (C) 2004-2006 Trusted Computer Solutions, Inc. 11 * Copyright (C) 2004-2006 Trusted Computer Solutions, Inc.
12 */ 12 */
13/*
14 * Updated: Hewlett-Packard <paul.moore@hp.com>
15 *
16 * Added support to import/export the MLS label
17 *
18 * (c) Copyright Hewlett-Packard Development Company, L.P., 2006
19 */
13 20
14#ifndef _SS_MLS_H_ 21#ifndef _SS_MLS_H_
15#define _SS_MLS_H_ 22#define _SS_MLS_H_
@@ -17,6 +24,26 @@
17#include "context.h" 24#include "context.h"
18#include "policydb.h" 25#include "policydb.h"
19 26
27/*
28 * Copies the MLS range from `src' into `dst'.
29 */
30static inline int mls_copy_context(struct context *dst,
31 struct context *src)
32{
33 int l, rc = 0;
34
35 /* Copy the MLS range from the source context */
36 for (l = 0; l < 2; l++) {
37 dst->range.level[l].sens = src->range.level[l].sens;
38 rc = ebitmap_cpy(&dst->range.level[l].cat,
39 &src->range.level[l].cat);
40 if (rc)
41 break;
42 }
43
44 return rc;
45}
46
20int mls_compute_context_len(struct context *context); 47int mls_compute_context_len(struct context *context);
21void mls_sid_to_context(struct context *context, char **scontext); 48void mls_sid_to_context(struct context *context, char **scontext);
22int mls_context_isvalid(struct policydb *p, struct context *c); 49int mls_context_isvalid(struct policydb *p, struct context *c);
@@ -42,5 +69,19 @@ int mls_compute_sid(struct context *scontext,
42int mls_setup_user_range(struct context *fromcon, struct user_datum *user, 69int mls_setup_user_range(struct context *fromcon, struct user_datum *user,
43 struct context *usercon); 70 struct context *usercon);
44 71
72void mls_export_lvl(const struct context *context, u32 *low, u32 *high);
73void mls_import_lvl(struct context *context, u32 low, u32 high);
74
75int mls_export_cat(const struct context *context,
76 unsigned char **low,
77 size_t *low_len,
78 unsigned char **high,
79 size_t *high_len);
80int mls_import_cat(struct context *context,
81 const unsigned char *low,
82 size_t low_len,
83 const unsigned char *high,
84 size_t high_len);
85
45#endif /* _SS_MLS_H */ 86#endif /* _SS_MLS_H */
46 87
diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c
index 85e429884393..7eb69a602d8f 100644
--- a/security/selinux/ss/services.c
+++ b/security/selinux/ss/services.c
@@ -13,6 +13,11 @@
13 * 13 *
14 * Added conditional policy language extensions 14 * Added conditional policy language extensions
15 * 15 *
16 * Updated: Hewlett-Packard <paul.moore@hp.com>
17 *
18 * Added support for NetLabel
19 *
20 * Copyright (C) 2006 Hewlett-Packard Development Company, L.P.
16 * Copyright (C) 2004-2006 Trusted Computer Solutions, Inc. 21 * Copyright (C) 2004-2006 Trusted Computer Solutions, Inc.
17 * Copyright (C) 2003 - 2004 Tresys Technology, LLC 22 * Copyright (C) 2003 - 2004 Tresys Technology, LLC
18 * Copyright (C) 2003 Red Hat, Inc., James Morris <jmorris@redhat.com> 23 * Copyright (C) 2003 Red Hat, Inc., James Morris <jmorris@redhat.com>
@@ -29,6 +34,8 @@
29#include <linux/sched.h> 34#include <linux/sched.h>
30#include <linux/audit.h> 35#include <linux/audit.h>
31#include <linux/mutex.h> 36#include <linux/mutex.h>
37#include <net/sock.h>
38#include <net/netlabel.h>
32 39
33#include "flask.h" 40#include "flask.h"
34#include "avc.h" 41#include "avc.h"
@@ -40,6 +47,8 @@
40#include "services.h" 47#include "services.h"
41#include "conditional.h" 48#include "conditional.h"
42#include "mls.h" 49#include "mls.h"
50#include "objsec.h"
51#include "selinux_netlabel.h"
43 52
44extern void selnl_notify_policyload(u32 seqno); 53extern void selnl_notify_policyload(u32 seqno);
45unsigned int policydb_loaded_version; 54unsigned int policydb_loaded_version;
@@ -1241,6 +1250,7 @@ int security_load_policy(void *data, size_t len)
1241 selinux_complete_init(); 1250 selinux_complete_init();
1242 avc_ss_reset(seqno); 1251 avc_ss_reset(seqno);
1243 selnl_notify_policyload(seqno); 1252 selnl_notify_policyload(seqno);
1253 selinux_netlbl_cache_invalidate();
1244 return 0; 1254 return 0;
1245 } 1255 }
1246 1256
@@ -1295,6 +1305,7 @@ int security_load_policy(void *data, size_t len)
1295 1305
1296 avc_ss_reset(seqno); 1306 avc_ss_reset(seqno);
1297 selnl_notify_policyload(seqno); 1307 selnl_notify_policyload(seqno);
1308 selinux_netlbl_cache_invalidate();
1298 1309
1299 return 0; 1310 return 0;
1300 1311
@@ -1817,6 +1828,75 @@ out:
1817 return rc; 1828 return rc;
1818} 1829}
1819 1830
1831/*
1832 * security_sid_mls_copy() - computes a new sid based on the given
1833 * sid and the mls portion of mls_sid.
1834 */
1835int security_sid_mls_copy(u32 sid, u32 mls_sid, u32 *new_sid)
1836{
1837 struct context *context1;
1838 struct context *context2;
1839 struct context newcon;
1840 char *s;
1841 u32 len;
1842 int rc = 0;
1843
1844 if (!ss_initialized || !selinux_mls_enabled) {
1845 *new_sid = sid;
1846 goto out;
1847 }
1848
1849 context_init(&newcon);
1850
1851 POLICY_RDLOCK;
1852 context1 = sidtab_search(&sidtab, sid);
1853 if (!context1) {
1854 printk(KERN_ERR "security_sid_mls_copy: unrecognized SID "
1855 "%d\n", sid);
1856 rc = -EINVAL;
1857 goto out_unlock;
1858 }
1859
1860 context2 = sidtab_search(&sidtab, mls_sid);
1861 if (!context2) {
1862 printk(KERN_ERR "security_sid_mls_copy: unrecognized SID "
1863 "%d\n", mls_sid);
1864 rc = -EINVAL;
1865 goto out_unlock;
1866 }
1867
1868 newcon.user = context1->user;
1869 newcon.role = context1->role;
1870 newcon.type = context1->type;
1871 rc = mls_copy_context(&newcon, context2);
1872 if (rc)
1873 goto out_unlock;
1874
1875
1876 /* Check the validity of the new context. */
1877 if (!policydb_context_isvalid(&policydb, &newcon)) {
1878 rc = convert_context_handle_invalid_context(&newcon);
1879 if (rc)
1880 goto bad;
1881 }
1882
1883 rc = sidtab_context_to_sid(&sidtab, &newcon, new_sid);
1884 goto out_unlock;
1885
1886bad:
1887 if (!context_struct_to_string(&newcon, &s, &len)) {
1888 audit_log(current->audit_context, GFP_ATOMIC, AUDIT_SELINUX_ERR,
1889 "security_sid_mls_copy: invalid context %s", s);
1890 kfree(s);
1891 }
1892
1893out_unlock:
1894 POLICY_RDUNLOCK;
1895 context_destroy(&newcon);
1896out:
1897 return rc;
1898}
1899
1820struct selinux_audit_rule { 1900struct selinux_audit_rule {
1821 u32 au_seqno; 1901 u32 au_seqno;
1822 struct context au_ctxt; 1902 struct context au_ctxt;
@@ -2064,3 +2144,536 @@ void selinux_audit_set_callback(int (*callback)(void))
2064{ 2144{
2065 aurule_callback = callback; 2145 aurule_callback = callback;
2066} 2146}
2147
2148#ifdef CONFIG_NETLABEL
2149/*
2150 * This is the structure we store inside the NetLabel cache block.
2151 */
2152#define NETLBL_CACHE(x) ((struct netlbl_cache *)(x))
2153#define NETLBL_CACHE_T_NONE 0
2154#define NETLBL_CACHE_T_SID 1
2155#define NETLBL_CACHE_T_MLS 2
2156struct netlbl_cache {
2157 u32 type;
2158 union {
2159 u32 sid;
2160 struct mls_range mls_label;
2161 } data;
2162};
2163
2164/**
2165 * selinux_netlbl_cache_free - Free the NetLabel cached data
2166 * @data: the data to free
2167 *
2168 * Description:
2169 * This function is intended to be used as the free() callback inside the
2170 * netlbl_lsm_cache structure.
2171 *
2172 */
2173static void selinux_netlbl_cache_free(const void *data)
2174{
2175 struct netlbl_cache *cache = NETLBL_CACHE(data);
2176 switch (cache->type) {
2177 case NETLBL_CACHE_T_MLS:
2178 ebitmap_destroy(&cache->data.mls_label.level[0].cat);
2179 break;
2180 }
2181 kfree(data);
2182}
2183
2184/**
2185 * selinux_netlbl_cache_add - Add an entry to the NetLabel cache
2186 * @skb: the packet
2187 * @ctx: the SELinux context
2188 *
2189 * Description:
2190 * Attempt to cache the context in @ctx, which was derived from the packet in
2191 * @skb, in the NetLabel subsystem cache.
2192 *
2193 */
2194static void selinux_netlbl_cache_add(struct sk_buff *skb, struct context *ctx)
2195{
2196 struct netlbl_cache *cache = NULL;
2197 struct netlbl_lsm_secattr secattr;
2198
2199 netlbl_secattr_init(&secattr);
2200
2201 cache = kzalloc(sizeof(*cache), GFP_ATOMIC);
2202 if (cache == NULL)
2203 goto netlbl_cache_add_failure;
2204 secattr.cache.free = selinux_netlbl_cache_free;
2205 secattr.cache.data = (void *)cache;
2206
2207 cache->type = NETLBL_CACHE_T_MLS;
2208 if (ebitmap_cpy(&cache->data.mls_label.level[0].cat,
2209 &ctx->range.level[0].cat) != 0)
2210 goto netlbl_cache_add_failure;
2211 cache->data.mls_label.level[1].cat.highbit =
2212 cache->data.mls_label.level[0].cat.highbit;
2213 cache->data.mls_label.level[1].cat.node =
2214 cache->data.mls_label.level[0].cat.node;
2215 cache->data.mls_label.level[0].sens = ctx->range.level[0].sens;
2216 cache->data.mls_label.level[1].sens = ctx->range.level[0].sens;
2217
2218 if (netlbl_cache_add(skb, &secattr) != 0)
2219 goto netlbl_cache_add_failure;
2220
2221 return;
2222
2223netlbl_cache_add_failure:
2224 netlbl_secattr_destroy(&secattr, 1);
2225}
2226
2227/**
2228 * selinux_netlbl_cache_invalidate - Invalidate the NetLabel cache
2229 *
2230 * Description:
2231 * Invalidate the NetLabel security attribute mapping cache.
2232 *
2233 */
2234void selinux_netlbl_cache_invalidate(void)
2235{
2236 netlbl_cache_invalidate();
2237}
2238
2239/**
2240 * selinux_netlbl_secattr_to_sid - Convert a NetLabel secattr to a SELinux SID
2241 * @skb: the network packet
2242 * @secattr: the NetLabel packet security attributes
2243 * @base_sid: the SELinux SID to use as a context for MLS only attributes
2244 * @sid: the SELinux SID
2245 *
2246 * Description:
2247 * Convert the given NetLabel packet security attributes in @secattr into a
2248 * SELinux SID. If the @secattr field does not contain a full SELinux
2249 * SID/context then use the context in @base_sid as the foundation. If @skb
2250 * is not NULL attempt to cache as much data as possibile. Returns zero on
2251 * success, negative values on failure.
2252 *
2253 */
2254static int selinux_netlbl_secattr_to_sid(struct sk_buff *skb,
2255 struct netlbl_lsm_secattr *secattr,
2256 u32 base_sid,
2257 u32 *sid)
2258{
2259 int rc = -EIDRM;
2260 struct context *ctx;
2261 struct context ctx_new;
2262 struct netlbl_cache *cache;
2263
2264 POLICY_RDLOCK;
2265
2266 if (secattr->cache.data) {
2267 cache = NETLBL_CACHE(secattr->cache.data);
2268 switch (cache->type) {
2269 case NETLBL_CACHE_T_SID:
2270 *sid = cache->data.sid;
2271 rc = 0;
2272 break;
2273 case NETLBL_CACHE_T_MLS:
2274 ctx = sidtab_search(&sidtab, base_sid);
2275 if (ctx == NULL)
2276 goto netlbl_secattr_to_sid_return;
2277
2278 ctx_new.user = ctx->user;
2279 ctx_new.role = ctx->role;
2280 ctx_new.type = ctx->type;
2281 ctx_new.range.level[0].sens =
2282 cache->data.mls_label.level[0].sens;
2283 ctx_new.range.level[0].cat.highbit =
2284 cache->data.mls_label.level[0].cat.highbit;
2285 ctx_new.range.level[0].cat.node =
2286 cache->data.mls_label.level[0].cat.node;
2287 ctx_new.range.level[1].sens =
2288 cache->data.mls_label.level[1].sens;
2289 ctx_new.range.level[1].cat.highbit =
2290 cache->data.mls_label.level[1].cat.highbit;
2291 ctx_new.range.level[1].cat.node =
2292 cache->data.mls_label.level[1].cat.node;
2293
2294 rc = sidtab_context_to_sid(&sidtab, &ctx_new, sid);
2295 break;
2296 default:
2297 goto netlbl_secattr_to_sid_return;
2298 }
2299 } else if (secattr->mls_lvl_vld) {
2300 ctx = sidtab_search(&sidtab, base_sid);
2301 if (ctx == NULL)
2302 goto netlbl_secattr_to_sid_return;
2303
2304 ctx_new.user = ctx->user;
2305 ctx_new.role = ctx->role;
2306 ctx_new.type = ctx->type;
2307 mls_import_lvl(&ctx_new, secattr->mls_lvl, secattr->mls_lvl);
2308 if (secattr->mls_cat) {
2309 if (mls_import_cat(&ctx_new,
2310 secattr->mls_cat,
2311 secattr->mls_cat_len,
2312 NULL,
2313 0) != 0)
2314 goto netlbl_secattr_to_sid_return;
2315 ctx_new.range.level[1].cat.highbit =
2316 ctx_new.range.level[0].cat.highbit;
2317 ctx_new.range.level[1].cat.node =
2318 ctx_new.range.level[0].cat.node;
2319 } else {
2320 ebitmap_init(&ctx_new.range.level[0].cat);
2321 ebitmap_init(&ctx_new.range.level[1].cat);
2322 }
2323 if (mls_context_isvalid(&policydb, &ctx_new) != 1)
2324 goto netlbl_secattr_to_sid_return_cleanup;
2325
2326 rc = sidtab_context_to_sid(&sidtab, &ctx_new, sid);
2327 if (rc != 0)
2328 goto netlbl_secattr_to_sid_return_cleanup;
2329
2330 if (skb != NULL)
2331 selinux_netlbl_cache_add(skb, &ctx_new);
2332 ebitmap_destroy(&ctx_new.range.level[0].cat);
2333 } else {
2334 *sid = SECINITSID_UNLABELED;
2335 rc = 0;
2336 }
2337
2338netlbl_secattr_to_sid_return:
2339 POLICY_RDUNLOCK;
2340 return rc;
2341netlbl_secattr_to_sid_return_cleanup:
2342 ebitmap_destroy(&ctx_new.range.level[0].cat);
2343 goto netlbl_secattr_to_sid_return;
2344}
2345
2346/**
2347 * selinux_netlbl_skbuff_getsid - Get the sid of a packet using NetLabel
2348 * @skb: the packet
2349 * @base_sid: the SELinux SID to use as a context for MLS only attributes
2350 * @sid: the SID
2351 *
2352 * Description:
2353 * Call the NetLabel mechanism to get the security attributes of the given
2354 * packet and use those attributes to determine the correct context/SID to
2355 * assign to the packet. Returns zero on success, negative values on failure.
2356 *
2357 */
2358static int selinux_netlbl_skbuff_getsid(struct sk_buff *skb,
2359 u32 base_sid,
2360 u32 *sid)
2361{
2362 int rc;
2363 struct netlbl_lsm_secattr secattr;
2364
2365 netlbl_secattr_init(&secattr);
2366 rc = netlbl_skbuff_getattr(skb, &secattr);
2367 if (rc == 0)
2368 rc = selinux_netlbl_secattr_to_sid(skb,
2369 &secattr,
2370 base_sid,
2371 sid);
2372 netlbl_secattr_destroy(&secattr, 0);
2373
2374 return rc;
2375}
2376
2377/**
2378 * selinux_netlbl_socket_setsid - Label a socket using the NetLabel mechanism
2379 * @sock: the socket to label
2380 * @sid: the SID to use
2381 *
2382 * Description:
2383 * Attempt to label a socket using the NetLabel mechanism using the given
2384 * SID. Returns zero values on success, negative values on failure.
2385 *
2386 */
2387static int selinux_netlbl_socket_setsid(struct socket *sock, u32 sid)
2388{
2389 int rc = -ENOENT;
2390 struct sk_security_struct *sksec = sock->sk->sk_security;
2391 struct netlbl_lsm_secattr secattr;
2392 struct context *ctx;
2393
2394 if (!ss_initialized)
2395 return 0;
2396
2397 POLICY_RDLOCK;
2398
2399 ctx = sidtab_search(&sidtab, sid);
2400 if (ctx == NULL)
2401 goto netlbl_socket_setsid_return;
2402
2403 netlbl_secattr_init(&secattr);
2404 secattr.domain = kstrdup(policydb.p_type_val_to_name[ctx->type - 1],
2405 GFP_ATOMIC);
2406 mls_export_lvl(ctx, &secattr.mls_lvl, NULL);
2407 secattr.mls_lvl_vld = 1;
2408 mls_export_cat(ctx,
2409 &secattr.mls_cat,
2410 &secattr.mls_cat_len,
2411 NULL,
2412 NULL);
2413
2414 rc = netlbl_socket_setattr(sock, &secattr);
2415 if (rc == 0)
2416 sksec->nlbl_state = NLBL_LABELED;
2417
2418 netlbl_secattr_destroy(&secattr, 0);
2419
2420netlbl_socket_setsid_return:
2421 POLICY_RDUNLOCK;
2422 return rc;
2423}
2424
2425/**
2426 * selinux_netlbl_sk_security_init - Setup the NetLabel fields
2427 * @ssec: the sk_security_struct
2428 * @family: the socket family
2429 *
2430 * Description:
2431 * Called when a new sk_security_struct is allocated to initialize the NetLabel
2432 * fields.
2433 *
2434 */
2435void selinux_netlbl_sk_security_init(struct sk_security_struct *ssec,
2436 int family)
2437{
2438 if (family == PF_INET)
2439 ssec->nlbl_state = NLBL_REQUIRE;
2440 else
2441 ssec->nlbl_state = NLBL_UNSET;
2442}
2443
2444/**
2445 * selinux_netlbl_sk_clone_security - Copy the NetLabel fields
2446 * @ssec: the original sk_security_struct
2447 * @newssec: the cloned sk_security_struct
2448 *
2449 * Description:
2450 * Clone the NetLabel specific sk_security_struct fields from @ssec to
2451 * @newssec.
2452 *
2453 */
2454void selinux_netlbl_sk_clone_security(struct sk_security_struct *ssec,
2455 struct sk_security_struct *newssec)
2456{
2457 newssec->sclass = ssec->sclass;
2458 if (ssec->nlbl_state != NLBL_UNSET)
2459 newssec->nlbl_state = NLBL_REQUIRE;
2460 else
2461 newssec->nlbl_state = NLBL_UNSET;
2462}
2463
2464/**
2465 * selinux_netlbl_socket_post_create - Label a socket using NetLabel
2466 * @sock: the socket to label
2467 * @sock_family: the socket family
2468 * @sid: the SID to use
2469 *
2470 * Description:
2471 * Attempt to label a socket using the NetLabel mechanism using the given
2472 * SID. Returns zero values on success, negative values on failure.
2473 *
2474 */
2475int selinux_netlbl_socket_post_create(struct socket *sock,
2476 int sock_family,
2477 u32 sid)
2478{
2479 struct inode_security_struct *isec = SOCK_INODE(sock)->i_security;
2480 struct sk_security_struct *sksec = sock->sk->sk_security;
2481
2482 sksec->sclass = isec->sclass;
2483
2484 if (sock_family != PF_INET)
2485 return 0;
2486
2487 sksec->nlbl_state = NLBL_REQUIRE;
2488 return selinux_netlbl_socket_setsid(sock, sid);
2489}
2490
2491/**
2492 * selinux_netlbl_sock_graft - Netlabel the new socket
2493 * @sk: the new connection
2494 * @sock: the new socket
2495 *
2496 * Description:
2497 * The connection represented by @sk is being grafted onto @sock so set the
2498 * socket's NetLabel to match the SID of @sk.
2499 *
2500 */
2501void selinux_netlbl_sock_graft(struct sock *sk, struct socket *sock)
2502{
2503 struct inode_security_struct *isec = SOCK_INODE(sock)->i_security;
2504 struct sk_security_struct *sksec = sk->sk_security;
2505
2506 sksec->sclass = isec->sclass;
2507
2508 if (sk->sk_family != PF_INET)
2509 return;
2510
2511 sksec->nlbl_state = NLBL_REQUIRE;
2512 sksec->peer_sid = sksec->sid;
2513
2514 /* Try to set the NetLabel on the socket to save time later, if we fail
2515 * here we will pick up the pieces in later calls to
2516 * selinux_netlbl_inode_permission(). */
2517 selinux_netlbl_socket_setsid(sock, sksec->sid);
2518}
2519
2520/**
2521 * selinux_netlbl_inet_conn_request - Handle a new connection request
2522 * @skb: the packet
2523 * @sock_sid: the SID of the parent socket
2524 *
2525 * Description:
2526 * If present, use the security attributes of the packet in @skb and the
2527 * parent sock's SID to arrive at a SID for the new child sock. Returns the
2528 * SID of the connection or SECSID_NULL on failure.
2529 *
2530 */
2531u32 selinux_netlbl_inet_conn_request(struct sk_buff *skb, u32 sock_sid)
2532{
2533 int rc;
2534 u32 peer_sid;
2535
2536 rc = selinux_netlbl_skbuff_getsid(skb, sock_sid, &peer_sid);
2537 if (rc != 0)
2538 return SECSID_NULL;
2539
2540 if (peer_sid == SECINITSID_UNLABELED)
2541 return SECSID_NULL;
2542
2543 return peer_sid;
2544}
2545
2546/**
2547 * selinux_netlbl_inode_permission - Verify the socket is NetLabel labeled
2548 * @inode: the file descriptor's inode
2549 * @mask: the permission mask
2550 *
2551 * Description:
2552 * Looks at a file's inode and if it is marked as a socket protected by
2553 * NetLabel then verify that the socket has been labeled, if not try to label
2554 * the socket now with the inode's SID. Returns zero on success, negative
2555 * values on failure.
2556 *
2557 */
2558int selinux_netlbl_inode_permission(struct inode *inode, int mask)
2559{
2560 int rc;
2561 struct inode_security_struct *isec;
2562 struct sk_security_struct *sksec;
2563 struct socket *sock;
2564
2565 if (!S_ISSOCK(inode->i_mode))
2566 return 0;
2567
2568 sock = SOCKET_I(inode);
2569 isec = inode->i_security;
2570 sksec = sock->sk->sk_security;
2571 down(&isec->sem);
2572 if (unlikely(sksec->nlbl_state == NLBL_REQUIRE &&
2573 (mask & (MAY_WRITE | MAY_APPEND)))) {
2574 lock_sock(sock->sk);
2575 rc = selinux_netlbl_socket_setsid(sock, sksec->sid);
2576 release_sock(sock->sk);
2577 } else
2578 rc = 0;
2579 up(&isec->sem);
2580
2581 return rc;
2582}
2583
2584/**
2585 * selinux_netlbl_sock_rcv_skb - Do an inbound access check using NetLabel
2586 * @sksec: the sock's sk_security_struct
2587 * @skb: the packet
2588 * @ad: the audit data
2589 *
2590 * Description:
2591 * Fetch the NetLabel security attributes from @skb and perform an access check
2592 * against the receiving socket. Returns zero on success, negative values on
2593 * error.
2594 *
2595 */
2596int selinux_netlbl_sock_rcv_skb(struct sk_security_struct *sksec,
2597 struct sk_buff *skb,
2598 struct avc_audit_data *ad)
2599{
2600 int rc;
2601 u32 netlbl_sid;
2602 u32 recv_perm;
2603
2604 rc = selinux_netlbl_skbuff_getsid(skb, sksec->sid, &netlbl_sid);
2605 if (rc != 0)
2606 return rc;
2607
2608 if (netlbl_sid == SECINITSID_UNLABELED)
2609 return 0;
2610
2611 switch (sksec->sclass) {
2612 case SECCLASS_UDP_SOCKET:
2613 recv_perm = UDP_SOCKET__RECV_MSG;
2614 break;
2615 case SECCLASS_TCP_SOCKET:
2616 recv_perm = TCP_SOCKET__RECV_MSG;
2617 break;
2618 default:
2619 recv_perm = RAWIP_SOCKET__RECV_MSG;
2620 }
2621
2622 rc = avc_has_perm(sksec->sid,
2623 netlbl_sid,
2624 sksec->sclass,
2625 recv_perm,
2626 ad);
2627 if (rc == 0)
2628 return 0;
2629
2630 netlbl_skbuff_err(skb, rc);
2631 return rc;
2632}
2633
2634/**
2635 * selinux_netlbl_socket_getpeersec_stream - Return the connected peer's SID
2636 * @sock: the socket
2637 *
2638 * Description:
2639 * Examine @sock to find the connected peer's SID. Returns the SID on success
2640 * or SECSID_NULL on error.
2641 *
2642 */
2643u32 selinux_netlbl_socket_getpeersec_stream(struct socket *sock)
2644{
2645 struct sk_security_struct *sksec = sock->sk->sk_security;
2646
2647 if (sksec->peer_sid == SECINITSID_UNLABELED)
2648 return SECSID_NULL;
2649
2650 return sksec->peer_sid;
2651}
2652
2653/**
2654 * selinux_netlbl_socket_getpeersec_dgram - Return the SID of a NetLabel packet
2655 * @skb: the packet
2656 *
2657 * Description:
2658 * Examine @skb to find the SID assigned to it by NetLabel. Returns the SID on
2659 * success, SECSID_NULL on error.
2660 *
2661 */
2662u32 selinux_netlbl_socket_getpeersec_dgram(struct sk_buff *skb)
2663{
2664 int peer_sid;
2665 struct sock *sk = skb->sk;
2666 struct inode_security_struct *isec;
2667
2668 if (sk == NULL || sk->sk_socket == NULL)
2669 return SECSID_NULL;
2670
2671 isec = SOCK_INODE(sk->sk_socket)->i_security;
2672 if (selinux_netlbl_skbuff_getsid(skb, isec->sid, &peer_sid) != 0)
2673 return SECSID_NULL;
2674 if (peer_sid == SECINITSID_UNLABELED)
2675 return SECSID_NULL;
2676
2677 return peer_sid;
2678}
2679#endif /* CONFIG_NETLABEL */
diff --git a/security/selinux/xfrm.c b/security/selinux/xfrm.c
index 6c985ced8102..3e742b850af6 100644
--- a/security/selinux/xfrm.c
+++ b/security/selinux/xfrm.c
@@ -6,7 +6,12 @@
6 * Authors: Serge Hallyn <sergeh@us.ibm.com> 6 * Authors: Serge Hallyn <sergeh@us.ibm.com>
7 * Trent Jaeger <jaegert@us.ibm.com> 7 * Trent Jaeger <jaegert@us.ibm.com>
8 * 8 *
9 * Updated: Venkat Yekkirala <vyekkirala@TrustedCS.com>
10 *
11 * Granular IPSec Associations for use in MLS environments.
12 *
9 * Copyright (C) 2005 International Business Machines Corporation 13 * Copyright (C) 2005 International Business Machines Corporation
14 * Copyright (C) 2006 Trusted Computer Solutions, Inc.
10 * 15 *
11 * This program is free software; you can redistribute it and/or modify 16 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License version 2, 17 * it under the terms of the GNU General Public License version 2,
@@ -67,10 +72,10 @@ static inline int selinux_authorizable_xfrm(struct xfrm_state *x)
67} 72}
68 73
69/* 74/*
70 * LSM hook implementation that authorizes that a socket can be used 75 * LSM hook implementation that authorizes that a flow can use
71 * with the corresponding xfrm_sec_ctx and direction. 76 * a xfrm policy rule.
72 */ 77 */
73int selinux_xfrm_policy_lookup(struct xfrm_policy *xp, u32 sk_sid, u8 dir) 78int selinux_xfrm_policy_lookup(struct xfrm_policy *xp, u32 fl_secid, u8 dir)
74{ 79{
75 int rc = 0; 80 int rc = 0;
76 u32 sel_sid = SECINITSID_UNLABELED; 81 u32 sel_sid = SECINITSID_UNLABELED;
@@ -84,27 +89,130 @@ int selinux_xfrm_policy_lookup(struct xfrm_policy *xp, u32 sk_sid, u8 dir)
84 sel_sid = ctx->ctx_sid; 89 sel_sid = ctx->ctx_sid;
85 } 90 }
86 91
87 rc = avc_has_perm(sk_sid, sel_sid, SECCLASS_ASSOCIATION, 92 rc = avc_has_perm(fl_secid, sel_sid, SECCLASS_ASSOCIATION,
88 ((dir == FLOW_DIR_IN) ? ASSOCIATION__RECVFROM : 93 ASSOCIATION__POLMATCH,
89 ((dir == FLOW_DIR_OUT) ? ASSOCIATION__SENDTO :
90 (ASSOCIATION__SENDTO | ASSOCIATION__RECVFROM))),
91 NULL); 94 NULL);
92 95
93 return rc; 96 return rc;
94} 97}
95 98
96/* 99/*
100 * LSM hook implementation that authorizes that a state matches
101 * the given policy, flow combo.
102 */
103
104int selinux_xfrm_state_pol_flow_match(struct xfrm_state *x, struct xfrm_policy *xp,
105 struct flowi *fl)
106{
107 u32 state_sid;
108 u32 pol_sid;
109 int err;
110
111 if (x->security)
112 state_sid = x->security->ctx_sid;
113 else
114 state_sid = SECINITSID_UNLABELED;
115
116 if (xp->security)
117 pol_sid = xp->security->ctx_sid;
118 else
119 pol_sid = SECINITSID_UNLABELED;
120
121 err = avc_has_perm(state_sid, pol_sid, SECCLASS_ASSOCIATION,
122 ASSOCIATION__POLMATCH,
123 NULL);
124
125 if (err)
126 return 0;
127
128 return selinux_xfrm_flow_state_match(fl, x);
129}
130
131/*
132 * LSM hook implementation that authorizes that a particular outgoing flow
133 * can use a given security association.
134 */
135
136int selinux_xfrm_flow_state_match(struct flowi *fl, struct xfrm_state *xfrm)
137{
138 int rc = 0;
139 u32 sel_sid = SECINITSID_UNLABELED;
140 struct xfrm_sec_ctx *ctx;
141
142 /* Context sid is either set to label or ANY_ASSOC */
143 if ((ctx = xfrm->security)) {
144 if (!selinux_authorizable_ctx(ctx))
145 return 0;
146
147 sel_sid = ctx->ctx_sid;
148 }
149
150 rc = avc_has_perm(fl->secid, sel_sid, SECCLASS_ASSOCIATION,
151 ASSOCIATION__SENDTO,
152 NULL)? 0:1;
153
154 return rc;
155}
156
157/*
158 * LSM hook implementation that determines the sid for the session.
159 */
160
161int selinux_xfrm_decode_session(struct sk_buff *skb, u32 *sid, int ckall)
162{
163 struct sec_path *sp;
164
165 *sid = SECSID_NULL;
166
167 if (skb == NULL)
168 return 0;
169
170 sp = skb->sp;
171 if (sp) {
172 int i, sid_set = 0;
173
174 for (i = sp->len-1; i >= 0; i--) {
175 struct xfrm_state *x = sp->xvec[i];
176 if (selinux_authorizable_xfrm(x)) {
177 struct xfrm_sec_ctx *ctx = x->security;
178
179 if (!sid_set) {
180 *sid = ctx->ctx_sid;
181 sid_set = 1;
182
183 if (!ckall)
184 break;
185 }
186 else if (*sid != ctx->ctx_sid)
187 return -EINVAL;
188 }
189 }
190 }
191
192 return 0;
193}
194
195/*
97 * Security blob allocation for xfrm_policy and xfrm_state 196 * Security blob allocation for xfrm_policy and xfrm_state
98 * CTX does not have a meaningful value on input 197 * CTX does not have a meaningful value on input
99 */ 198 */
100static int selinux_xfrm_sec_ctx_alloc(struct xfrm_sec_ctx **ctxp, struct xfrm_user_sec_ctx *uctx) 199static int selinux_xfrm_sec_ctx_alloc(struct xfrm_sec_ctx **ctxp,
200 struct xfrm_user_sec_ctx *uctx, struct xfrm_sec_ctx *pol, u32 sid)
101{ 201{
102 int rc = 0; 202 int rc = 0;
103 struct task_security_struct *tsec = current->security; 203 struct task_security_struct *tsec = current->security;
104 struct xfrm_sec_ctx *ctx; 204 struct xfrm_sec_ctx *ctx = NULL;
205 char *ctx_str = NULL;
206 u32 str_len;
207 u32 ctx_sid;
208
209 BUG_ON(uctx && pol);
210
211 if (!uctx)
212 goto not_from_user;
105 213
106 BUG_ON(!uctx); 214 if (uctx->ctx_doi != XFRM_SC_ALG_SELINUX)
107 BUG_ON(uctx->ctx_doi != XFRM_SC_ALG_SELINUX); 215 return -EINVAL;
108 216
109 if (uctx->ctx_len >= PAGE_SIZE) 217 if (uctx->ctx_len >= PAGE_SIZE)
110 return -ENOMEM; 218 return -ENOMEM;
@@ -141,9 +249,43 @@ static int selinux_xfrm_sec_ctx_alloc(struct xfrm_sec_ctx **ctxp, struct xfrm_us
141 249
142 return rc; 250 return rc;
143 251
252not_from_user:
253 if (pol) {
254 rc = security_sid_mls_copy(pol->ctx_sid, sid, &ctx_sid);
255 if (rc)
256 goto out;
257 }
258 else
259 ctx_sid = sid;
260
261 rc = security_sid_to_context(ctx_sid, &ctx_str, &str_len);
262 if (rc)
263 goto out;
264
265 *ctxp = ctx = kmalloc(sizeof(*ctx) +
266 str_len,
267 GFP_ATOMIC);
268
269 if (!ctx) {
270 rc = -ENOMEM;
271 goto out;
272 }
273
274 ctx->ctx_doi = XFRM_SC_DOI_LSM;
275 ctx->ctx_alg = XFRM_SC_ALG_SELINUX;
276 ctx->ctx_sid = ctx_sid;
277 ctx->ctx_len = str_len;
278 memcpy(ctx->ctx_str,
279 ctx_str,
280 str_len);
281
282 goto out2;
283
144out: 284out:
145 *ctxp = NULL; 285 *ctxp = NULL;
146 kfree(ctx); 286 kfree(ctx);
287out2:
288 kfree(ctx_str);
147 return rc; 289 return rc;
148} 290}
149 291
@@ -151,13 +293,23 @@ out:
151 * LSM hook implementation that allocs and transfers uctx spec to 293 * LSM hook implementation that allocs and transfers uctx spec to
152 * xfrm_policy. 294 * xfrm_policy.
153 */ 295 */
154int selinux_xfrm_policy_alloc(struct xfrm_policy *xp, struct xfrm_user_sec_ctx *uctx) 296int selinux_xfrm_policy_alloc(struct xfrm_policy *xp,
297 struct xfrm_user_sec_ctx *uctx, struct sock *sk)
155{ 298{
156 int err; 299 int err;
300 u32 sid;
157 301
158 BUG_ON(!xp); 302 BUG_ON(!xp);
303 BUG_ON(uctx && sk);
159 304
160 err = selinux_xfrm_sec_ctx_alloc(&xp->security, uctx); 305 if (sk) {
306 struct sk_security_struct *ssec = sk->sk_security;
307 sid = ssec->sid;
308 }
309 else
310 sid = SECSID_NULL;
311
312 err = selinux_xfrm_sec_ctx_alloc(&xp->security, uctx, NULL, sid);
161 return err; 313 return err;
162} 314}
163 315
@@ -217,13 +369,14 @@ int selinux_xfrm_policy_delete(struct xfrm_policy *xp)
217 * LSM hook implementation that allocs and transfers sec_ctx spec to 369 * LSM hook implementation that allocs and transfers sec_ctx spec to
218 * xfrm_state. 370 * xfrm_state.
219 */ 371 */
220int selinux_xfrm_state_alloc(struct xfrm_state *x, struct xfrm_user_sec_ctx *uctx) 372int selinux_xfrm_state_alloc(struct xfrm_state *x, struct xfrm_user_sec_ctx *uctx,
373 struct xfrm_sec_ctx *pol, u32 secid)
221{ 374{
222 int err; 375 int err;
223 376
224 BUG_ON(!x); 377 BUG_ON(!x);
225 378
226 err = selinux_xfrm_sec_ctx_alloc(&x->security, uctx); 379 err = selinux_xfrm_sec_ctx_alloc(&x->security, uctx, pol, secid);
227 return err; 380 return err;
228} 381}
229 382
@@ -329,38 +482,30 @@ int selinux_xfrm_state_delete(struct xfrm_state *x)
329 * we need to check for unlabelled access since this may not have 482 * we need to check for unlabelled access since this may not have
330 * gone thru the IPSec process. 483 * gone thru the IPSec process.
331 */ 484 */
332int selinux_xfrm_sock_rcv_skb(u32 isec_sid, struct sk_buff *skb) 485int selinux_xfrm_sock_rcv_skb(u32 isec_sid, struct sk_buff *skb,
486 struct avc_audit_data *ad)
333{ 487{
334 int i, rc = 0; 488 int i, rc = 0;
335 struct sec_path *sp; 489 struct sec_path *sp;
490 u32 sel_sid = SECINITSID_UNLABELED;
336 491
337 sp = skb->sp; 492 sp = skb->sp;
338 493
339 if (sp) { 494 if (sp) {
340 /*
341 * __xfrm_policy_check does not approve unless xfrm_policy_ok
342 * says that spi's match for policy and the socket.
343 *
344 * Only need to verify the existence of an authorizable sp.
345 */
346 for (i = 0; i < sp->len; i++) { 495 for (i = 0; i < sp->len; i++) {
347 struct xfrm_state *x = sp->xvec[i]; 496 struct xfrm_state *x = sp->xvec[i];
348 497
349 if (x && selinux_authorizable_xfrm(x)) 498 if (x && selinux_authorizable_xfrm(x)) {
350 goto accept; 499 struct xfrm_sec_ctx *ctx = x->security;
500 sel_sid = ctx->ctx_sid;
501 break;
502 }
351 } 503 }
352 } 504 }
353 505
354 /* check SELinux sock for unlabelled access */ 506 rc = avc_has_perm(isec_sid, sel_sid, SECCLASS_ASSOCIATION,
355 rc = avc_has_perm(isec_sid, SECINITSID_UNLABELED, SECCLASS_ASSOCIATION, 507 ASSOCIATION__RECVFROM, ad);
356 ASSOCIATION__RECVFROM, NULL);
357 if (rc)
358 goto drop;
359
360accept:
361 return 0;
362 508
363drop:
364 return rc; 509 return rc;
365} 510}
366 511
@@ -371,7 +516,8 @@ drop:
371 * If we do have a authorizable security association, then it has already been 516 * If we do have a authorizable security association, then it has already been
372 * checked in xfrm_policy_lookup hook. 517 * checked in xfrm_policy_lookup hook.
373 */ 518 */
374int selinux_xfrm_postroute_last(u32 isec_sid, struct sk_buff *skb) 519int selinux_xfrm_postroute_last(u32 isec_sid, struct sk_buff *skb,
520 struct avc_audit_data *ad)
375{ 521{
376 struct dst_entry *dst; 522 struct dst_entry *dst;
377 int rc = 0; 523 int rc = 0;
@@ -391,7 +537,7 @@ int selinux_xfrm_postroute_last(u32 isec_sid, struct sk_buff *skb)
391 } 537 }
392 538
393 rc = avc_has_perm(isec_sid, SECINITSID_UNLABELED, SECCLASS_ASSOCIATION, 539 rc = avc_has_perm(isec_sid, SECINITSID_UNLABELED, SECCLASS_ASSOCIATION,
394 ASSOCIATION__SENDTO, NULL); 540 ASSOCIATION__SENDTO, ad);
395out: 541out:
396 return rc; 542 return rc;
397} 543}