aboutsummaryrefslogtreecommitdiffstats
path: root/security/selinux/hooks.c
diff options
context:
space:
mode:
authorVenkat Yekkirala <vyekkirala@TrustedCS.com>2006-07-25 02:32:50 -0400
committerDavid S. Miller <davem@sunset.davemloft.net>2006-09-22 17:53:29 -0400
commit4237c75c0a35535d7f9f2bfeeb4b4df1e068a0bf (patch)
tree02adcb6fe6c346a8b99cf161ba5233ed1e572727 /security/selinux/hooks.c
parentcb969f072b6d67770b559617f14e767f47e77ece (diff)
[MLSXFRM]: Auto-labeling of child sockets
This automatically labels the TCP, Unix stream, and dccp child sockets as well as openreqs to be at the same MLS level as the peer. This will result in the selection of appropriately labeled IPSec Security Associations. This also uses the sock's sid (as opposed to the isec sid) in SELinux enforcement of secmark in rcv_skb and postroute_last hooks. Signed-off-by: Venkat Yekkirala <vyekkirala@TrustedCS.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'security/selinux/hooks.c')
-rw-r--r--security/selinux/hooks.c137
1 files changed, 93 insertions, 44 deletions
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index 4e5989d584ce..1dc935f7b919 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -3328,8 +3328,9 @@ static int selinux_socket_unix_stream_connect(struct socket *sock,
3328 /* server child socket */ 3328 /* server child socket */
3329 ssec = newsk->sk_security; 3329 ssec = newsk->sk_security;
3330 ssec->peer_sid = isec->sid; 3330 ssec->peer_sid = isec->sid;
3331 3331 err = security_sid_mls_copy(other_isec->sid, ssec->peer_sid, &ssec->sid);
3332 return 0; 3332
3333 return err;
3333} 3334}
3334 3335
3335static int selinux_socket_unix_may_send(struct socket *sock, 3336static int selinux_socket_unix_may_send(struct socket *sock,
@@ -3355,11 +3356,29 @@ static int selinux_socket_unix_may_send(struct socket *sock,
3355} 3356}
3356 3357
3357static int selinux_sock_rcv_skb_compat(struct sock *sk, struct sk_buff *skb, 3358static int selinux_sock_rcv_skb_compat(struct sock *sk, struct sk_buff *skb,
3358 struct avc_audit_data *ad, u32 sock_sid, u16 sock_class, 3359 struct avc_audit_data *ad, u16 family, char *addrp, int len)
3359 u16 family, char *addrp, int len)
3360{ 3360{
3361 int err = 0; 3361 int err = 0;
3362 u32 netif_perm, node_perm, node_sid, if_sid, recv_perm = 0; 3362 u32 netif_perm, node_perm, node_sid, if_sid, recv_perm = 0;
3363 struct socket *sock;
3364 u16 sock_class = 0;
3365 u32 sock_sid = 0;
3366
3367 read_lock_bh(&sk->sk_callback_lock);
3368 sock = sk->sk_socket;
3369 if (sock) {
3370 struct inode *inode;
3371 inode = SOCK_INODE(sock);
3372 if (inode) {
3373 struct inode_security_struct *isec;
3374 isec = inode->i_security;
3375 sock_sid = isec->sid;
3376 sock_class = isec->sclass;
3377 }
3378 }
3379 read_unlock_bh(&sk->sk_callback_lock);
3380 if (!sock_sid)
3381 goto out;
3363 3382
3364 if (!skb->dev) 3383 if (!skb->dev)
3365 goto out; 3384 goto out;
@@ -3419,12 +3438,10 @@ out:
3419static int selinux_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb) 3438static int selinux_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb)
3420{ 3439{
3421 u16 family; 3440 u16 family;
3422 u16 sock_class = 0;
3423 char *addrp; 3441 char *addrp;
3424 int len, err = 0; 3442 int len, err = 0;
3425 u32 sock_sid = 0;
3426 struct socket *sock;
3427 struct avc_audit_data ad; 3443 struct avc_audit_data ad;
3444 struct sk_security_struct *sksec = sk->sk_security;
3428 3445
3429 family = sk->sk_family; 3446 family = sk->sk_family;
3430 if (family != PF_INET && family != PF_INET6) 3447 if (family != PF_INET && family != PF_INET6)
@@ -3434,22 +3451,6 @@ static int selinux_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb)
3434 if (family == PF_INET6 && skb->protocol == ntohs(ETH_P_IP)) 3451 if (family == PF_INET6 && skb->protocol == ntohs(ETH_P_IP))
3435 family = PF_INET; 3452 family = PF_INET;
3436 3453
3437 read_lock_bh(&sk->sk_callback_lock);
3438 sock = sk->sk_socket;
3439 if (sock) {
3440 struct inode *inode;
3441 inode = SOCK_INODE(sock);
3442 if (inode) {
3443 struct inode_security_struct *isec;
3444 isec = inode->i_security;
3445 sock_sid = isec->sid;
3446 sock_class = isec->sclass;
3447 }
3448 }
3449 read_unlock_bh(&sk->sk_callback_lock);
3450 if (!sock_sid)
3451 goto out;
3452
3453 AVC_AUDIT_DATA_INIT(&ad, NET); 3454 AVC_AUDIT_DATA_INIT(&ad, NET);
3454 ad.u.net.netif = skb->dev ? skb->dev->name : "[unknown]"; 3455 ad.u.net.netif = skb->dev ? skb->dev->name : "[unknown]";
3455 ad.u.net.family = family; 3456 ad.u.net.family = family;
@@ -3459,16 +3460,15 @@ static int selinux_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb)
3459 goto out; 3460 goto out;
3460 3461
3461 if (selinux_compat_net) 3462 if (selinux_compat_net)
3462 err = selinux_sock_rcv_skb_compat(sk, skb, &ad, sock_sid, 3463 err = selinux_sock_rcv_skb_compat(sk, skb, &ad, family,
3463 sock_class, family,
3464 addrp, len); 3464 addrp, len);
3465 else 3465 else
3466 err = avc_has_perm(sock_sid, skb->secmark, SECCLASS_PACKET, 3466 err = avc_has_perm(sksec->sid, skb->secmark, SECCLASS_PACKET,
3467 PACKET__RECV, &ad); 3467 PACKET__RECV, &ad);
3468 if (err) 3468 if (err)
3469 goto out; 3469 goto out;
3470 3470
3471 err = selinux_xfrm_sock_rcv_skb(sock_sid, skb, &ad); 3471 err = selinux_xfrm_sock_rcv_skb(sksec->sid, skb, &ad);
3472out: 3472out:
3473 return err; 3473 return err;
3474} 3474}
@@ -3572,6 +3572,49 @@ static void selinux_sk_getsecid(struct sock *sk, u32 *secid)
3572 } 3572 }
3573} 3573}
3574 3574
3575void selinux_sock_graft(struct sock* sk, struct socket *parent)
3576{
3577 struct inode_security_struct *isec = SOCK_INODE(parent)->i_security;
3578 struct sk_security_struct *sksec = sk->sk_security;
3579
3580 isec->sid = sksec->sid;
3581}
3582
3583int selinux_inet_conn_request(struct sock *sk, struct sk_buff *skb,
3584 struct request_sock *req)
3585{
3586 struct sk_security_struct *sksec = sk->sk_security;
3587 int err;
3588 u32 newsid = 0;
3589 u32 peersid;
3590
3591 err = selinux_xfrm_decode_session(skb, &peersid, 0);
3592 BUG_ON(err);
3593
3594 err = security_sid_mls_copy(sksec->sid, peersid, &newsid);
3595 if (err)
3596 return err;
3597
3598 req->secid = newsid;
3599 return 0;
3600}
3601
3602void selinux_inet_csk_clone(struct sock *newsk, const struct request_sock *req)
3603{
3604 struct sk_security_struct *newsksec = newsk->sk_security;
3605
3606 newsksec->sid = req->secid;
3607 /* NOTE: Ideally, we should also get the isec->sid for the
3608 new socket in sync, but we don't have the isec available yet.
3609 So we will wait until sock_graft to do it, by which
3610 time it will have been created and available. */
3611}
3612
3613void selinux_req_classify_flow(const struct request_sock *req, struct flowi *fl)
3614{
3615 fl->secid = req->secid;
3616}
3617
3575static int selinux_nlmsg_perm(struct sock *sk, struct sk_buff *skb) 3618static int selinux_nlmsg_perm(struct sock *sk, struct sk_buff *skb)
3576{ 3619{
3577 int err = 0; 3620 int err = 0;
@@ -3611,12 +3654,24 @@ out:
3611#ifdef CONFIG_NETFILTER 3654#ifdef CONFIG_NETFILTER
3612 3655
3613static int selinux_ip_postroute_last_compat(struct sock *sk, struct net_device *dev, 3656static int selinux_ip_postroute_last_compat(struct sock *sk, struct net_device *dev,
3614 struct inode_security_struct *isec,
3615 struct avc_audit_data *ad, 3657 struct avc_audit_data *ad,
3616 u16 family, char *addrp, int len) 3658 u16 family, char *addrp, int len)
3617{ 3659{
3618 int err; 3660 int err = 0;
3619 u32 netif_perm, node_perm, node_sid, if_sid, send_perm = 0; 3661 u32 netif_perm, node_perm, node_sid, if_sid, send_perm = 0;
3662 struct socket *sock;
3663 struct inode *inode;
3664 struct inode_security_struct *isec;
3665
3666 sock = sk->sk_socket;
3667 if (!sock)
3668 goto out;
3669
3670 inode = SOCK_INODE(sock);
3671 if (!inode)
3672 goto out;
3673
3674 isec = inode->i_security;
3620 3675
3621 err = sel_netif_sids(dev, &if_sid, NULL); 3676 err = sel_netif_sids(dev, &if_sid, NULL);
3622 if (err) 3677 if (err)
@@ -3681,26 +3736,16 @@ static unsigned int selinux_ip_postroute_last(unsigned int hooknum,
3681 char *addrp; 3736 char *addrp;
3682 int len, err = 0; 3737 int len, err = 0;
3683 struct sock *sk; 3738 struct sock *sk;
3684 struct socket *sock;
3685 struct inode *inode;
3686 struct sk_buff *skb = *pskb; 3739 struct sk_buff *skb = *pskb;
3687 struct inode_security_struct *isec;
3688 struct avc_audit_data ad; 3740 struct avc_audit_data ad;
3689 struct net_device *dev = (struct net_device *)out; 3741 struct net_device *dev = (struct net_device *)out;
3742 struct sk_security_struct *sksec;
3690 3743
3691 sk = skb->sk; 3744 sk = skb->sk;
3692 if (!sk) 3745 if (!sk)
3693 goto out; 3746 goto out;
3694 3747
3695 sock = sk->sk_socket; 3748 sksec = sk->sk_security;
3696 if (!sock)
3697 goto out;
3698
3699 inode = SOCK_INODE(sock);
3700 if (!inode)
3701 goto out;
3702
3703 isec = inode->i_security;
3704 3749
3705 AVC_AUDIT_DATA_INIT(&ad, NET); 3750 AVC_AUDIT_DATA_INIT(&ad, NET);
3706 ad.u.net.netif = dev->name; 3751 ad.u.net.netif = dev->name;
@@ -3711,16 +3756,16 @@ static unsigned int selinux_ip_postroute_last(unsigned int hooknum,
3711 goto out; 3756 goto out;
3712 3757
3713 if (selinux_compat_net) 3758 if (selinux_compat_net)
3714 err = selinux_ip_postroute_last_compat(sk, dev, isec, &ad, 3759 err = selinux_ip_postroute_last_compat(sk, dev, &ad,
3715 family, addrp, len); 3760 family, addrp, len);
3716 else 3761 else
3717 err = avc_has_perm(isec->sid, skb->secmark, SECCLASS_PACKET, 3762 err = avc_has_perm(sksec->sid, skb->secmark, SECCLASS_PACKET,
3718 PACKET__SEND, &ad); 3763 PACKET__SEND, &ad);
3719 3764
3720 if (err) 3765 if (err)
3721 goto out; 3766 goto out;
3722 3767
3723 err = selinux_xfrm_postroute_last(isec->sid, skb, &ad); 3768 err = selinux_xfrm_postroute_last(sksec->sid, skb, &ad);
3724out: 3769out:
3725 return err ? NF_DROP : NF_ACCEPT; 3770 return err ? NF_DROP : NF_ACCEPT;
3726} 3771}
@@ -4623,6 +4668,10 @@ static struct security_operations selinux_ops = {
4623 .sk_free_security = selinux_sk_free_security, 4668 .sk_free_security = selinux_sk_free_security,
4624 .sk_clone_security = selinux_sk_clone_security, 4669 .sk_clone_security = selinux_sk_clone_security,
4625 .sk_getsecid = selinux_sk_getsecid, 4670 .sk_getsecid = selinux_sk_getsecid,
4671 .sock_graft = selinux_sock_graft,
4672 .inet_conn_request = selinux_inet_conn_request,
4673 .inet_csk_clone = selinux_inet_csk_clone,
4674 .req_classify_flow = selinux_req_classify_flow,
4626 4675
4627#ifdef CONFIG_SECURITY_NETWORK_XFRM 4676#ifdef CONFIG_SECURITY_NETWORK_XFRM
4628 .xfrm_policy_alloc_security = selinux_xfrm_policy_alloc, 4677 .xfrm_policy_alloc_security = selinux_xfrm_policy_alloc,