diff options
author | Catherine Zhang <cxzhang@watson.ibm.com> | 2006-08-02 17:12:06 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2006-08-02 17:12:06 -0400 |
commit | dc49c1f94e3469d94b952e8f5160dd4ccd791d79 (patch) | |
tree | e47b1974c262a03dbabf0a148325d9089817e78e /security | |
parent | 2b7e24b66d31d677d76b49918e711eb360c978b6 (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.c | 14 | ||||
-rw-r--r-- | security/selinux/hooks.c | 38 |
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 | ||
794 | static int dummy_socket_getpeersec_dgram(struct sk_buff *skb, char **secdata, | 794 | static 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 | ||
878 | static int dummy_secid_to_secctx(u32 secid, char **secdata, u32 *seclen) | ||
879 | { | ||
880 | return -EOPNOTSUPP; | ||
881 | } | ||
882 | |||
883 | static void dummy_release_secctx(char *secdata, u32 seclen) | ||
884 | { | ||
885 | } | ||
886 | |||
879 | #ifdef CONFIG_KEYS | 887 | #ifdef CONFIG_KEYS |
880 | static inline int dummy_key_alloc(struct key *key, struct task_struct *ctx, | 888 | static 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 | ||
3527 | static int selinux_socket_getpeersec_dgram(struct sk_buff *skb, char **secdata, u32 *seclen) | 3527 | static 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 | ||
3548 | static int selinux_sk_alloc_security(struct sock *sk, int family, gfp_t priority) | 3544 | static 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 | ||
4406 | static int selinux_secid_to_secctx(u32 secid, char **secdata, u32 *seclen) | ||
4407 | { | ||
4408 | return security_sid_to_context(secid, secdata, seclen); | ||
4409 | } | ||
4410 | |||
4411 | static 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 | ||
4412 | static int selinux_key_alloc(struct key *k, struct task_struct *tsk, | 4419 | static 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 | ||