aboutsummaryrefslogtreecommitdiffstats
path: root/security
diff options
context:
space:
mode:
authorCatherine Zhang <cxzhang@watson.ibm.com>2006-08-02 17:12:06 -0400
committerDavid S. Miller <davem@davemloft.net>2006-08-02 17:12:06 -0400
commitdc49c1f94e3469d94b952e8f5160dd4ccd791d79 (patch)
treee47b1974c262a03dbabf0a148325d9089817e78e /security
parent2b7e24b66d31d677d76b49918e711eb360c978b6 (diff)
[AF_UNIX]: Kernel memory leak fix for af_unix datagram getpeersec patch
From: Catherine Zhang <cxzhang@watson.ibm.com> This patch implements a cleaner fix for the memory leak problem of the original unix datagram getpeersec patch. Instead of creating a security context each time a unix datagram is sent, we only create the security context when the receiver requests it. This new design requires modification of the current unix_getsecpeer_dgram LSM hook and addition of two new hooks, namely, secid_to_secctx and release_secctx. The former retrieves the security context and the latter releases it. A hook is required for releasing the security context because it is up to the security module to decide how that's done. In the case of Selinux, it's a simple kfree operation. Acked-by: Stephen Smalley <sds@tycho.nsa.gov> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'security')
-rw-r--r--security/dummy.c14
-rw-r--r--security/selinux/hooks.c38
2 files changed, 36 insertions, 16 deletions
diff --git a/security/dummy.c b/security/dummy.c
index bbbfda70e131..58c6d399c844 100644
--- a/security/dummy.c
+++ b/security/dummy.c
@@ -791,8 +791,7 @@ static int dummy_socket_getpeersec_stream(struct socket *sock, char __user *optv
791 return -ENOPROTOOPT; 791 return -ENOPROTOOPT;
792} 792}
793 793
794static int dummy_socket_getpeersec_dgram(struct sk_buff *skb, char **secdata, 794static int dummy_socket_getpeersec_dgram(struct socket *sock, struct sk_buff *skb, u32 *secid)
795 u32 *seclen)
796{ 795{
797 return -ENOPROTOOPT; 796 return -ENOPROTOOPT;
798} 797}
@@ -876,6 +875,15 @@ static int dummy_setprocattr(struct task_struct *p, char *name, void *value, siz
876 return -EINVAL; 875 return -EINVAL;
877} 876}
878 877
878static int dummy_secid_to_secctx(u32 secid, char **secdata, u32 *seclen)
879{
880 return -EOPNOTSUPP;
881}
882
883static void dummy_release_secctx(char *secdata, u32 seclen)
884{
885}
886
879#ifdef CONFIG_KEYS 887#ifdef CONFIG_KEYS
880static inline int dummy_key_alloc(struct key *key, struct task_struct *ctx, 888static inline int dummy_key_alloc(struct key *key, struct task_struct *ctx,
881 unsigned long flags) 889 unsigned long flags)
@@ -1028,6 +1036,8 @@ void security_fixup_ops (struct security_operations *ops)
1028 set_to_dummy_if_null(ops, d_instantiate); 1036 set_to_dummy_if_null(ops, d_instantiate);
1029 set_to_dummy_if_null(ops, getprocattr); 1037 set_to_dummy_if_null(ops, getprocattr);
1030 set_to_dummy_if_null(ops, setprocattr); 1038 set_to_dummy_if_null(ops, setprocattr);
1039 set_to_dummy_if_null(ops, secid_to_secctx);
1040 set_to_dummy_if_null(ops, release_secctx);
1031#ifdef CONFIG_SECURITY_NETWORK 1041#ifdef CONFIG_SECURITY_NETWORK
1032 set_to_dummy_if_null(ops, unix_stream_connect); 1042 set_to_dummy_if_null(ops, unix_stream_connect);
1033 set_to_dummy_if_null(ops, unix_may_send); 1043 set_to_dummy_if_null(ops, unix_may_send);
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index a91c961ba38b..5d1b8c733199 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -3524,25 +3524,21 @@ out:
3524 return err; 3524 return err;
3525} 3525}
3526 3526
3527static int selinux_socket_getpeersec_dgram(struct sk_buff *skb, char **secdata, u32 *seclen) 3527static int selinux_socket_getpeersec_dgram(struct socket *sock, struct sk_buff *skb, u32 *secid)
3528{ 3528{
3529 u32 peer_secid = SECSID_NULL;
3529 int err = 0; 3530 int err = 0;
3530 u32 peer_sid;
3531 3531
3532 if (skb->sk->sk_family == PF_UNIX) 3532 if (sock && (sock->sk->sk_family == PF_UNIX))
3533 selinux_get_inode_sid(SOCK_INODE(skb->sk->sk_socket), 3533 selinux_get_inode_sid(SOCK_INODE(sock), &peer_secid);
3534 &peer_sid); 3534 else if (skb)
3535 else 3535 peer_secid = selinux_socket_getpeer_dgram(skb);
3536 peer_sid = selinux_socket_getpeer_dgram(skb);
3537
3538 if (peer_sid == SECSID_NULL)
3539 return -EINVAL;
3540 3536
3541 err = security_sid_to_context(peer_sid, secdata, seclen); 3537 if (peer_secid == SECSID_NULL)
3542 if (err) 3538 err = -EINVAL;
3543 return err; 3539 *secid = peer_secid;
3544 3540
3545 return 0; 3541 return err;
3546} 3542}
3547 3543
3548static int selinux_sk_alloc_security(struct sock *sk, int family, gfp_t priority) 3544static int selinux_sk_alloc_security(struct sock *sk, int family, gfp_t priority)
@@ -4407,6 +4403,17 @@ static int selinux_setprocattr(struct task_struct *p,
4407 return size; 4403 return size;
4408} 4404}
4409 4405
4406static int selinux_secid_to_secctx(u32 secid, char **secdata, u32 *seclen)
4407{
4408 return security_sid_to_context(secid, secdata, seclen);
4409}
4410
4411static void selinux_release_secctx(char *secdata, u32 seclen)
4412{
4413 if (secdata)
4414 kfree(secdata);
4415}
4416
4410#ifdef CONFIG_KEYS 4417#ifdef CONFIG_KEYS
4411 4418
4412static int selinux_key_alloc(struct key *k, struct task_struct *tsk, 4419static int selinux_key_alloc(struct key *k, struct task_struct *tsk,
@@ -4587,6 +4594,9 @@ static struct security_operations selinux_ops = {
4587 .getprocattr = selinux_getprocattr, 4594 .getprocattr = selinux_getprocattr,
4588 .setprocattr = selinux_setprocattr, 4595 .setprocattr = selinux_setprocattr,
4589 4596
4597 .secid_to_secctx = selinux_secid_to_secctx,
4598 .release_secctx = selinux_release_secctx,
4599
4590 .unix_stream_connect = selinux_socket_unix_stream_connect, 4600 .unix_stream_connect = selinux_socket_unix_stream_connect,
4591 .unix_may_send = selinux_socket_unix_may_send, 4601 .unix_may_send = selinux_socket_unix_may_send,
4592 4602