summaryrefslogtreecommitdiffstats
path: root/security/selinux
diff options
context:
space:
mode:
authorCatherine Zhang <cxzhang@watson.ibm.com>2006-08-02 23:12:06 +0200
committerDavid S. Miller <davem@davemloft.net>2006-08-02 23:12:06 +0200
commitdc49c1f94e3469d94b952e8f5160dd4ccd791d79 (patch)
treee47b1974c262a03dbabf0a148325d9089817e78e /security/selinux
parent[NET]: skb_queue_lock_key() is no longer used. (diff)
downloadlinux-dc49c1f94e3469d94b952e8f5160dd4ccd791d79.tar.xz
linux-dc49c1f94e3469d94b952e8f5160dd4ccd791d79.zip
[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/selinux')
-rw-r--r--security/selinux/hooks.c38
1 files changed, 24 insertions, 14 deletions
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:
return err;
}
-static int selinux_socket_getpeersec_dgram(struct sk_buff *skb, char **secdata, u32 *seclen)
+static int selinux_socket_getpeersec_dgram(struct socket *sock, struct sk_buff *skb, u32 *secid)
{
+ u32 peer_secid = SECSID_NULL;
int err = 0;
- u32 peer_sid;
- if (skb->sk->sk_family == PF_UNIX)
- selinux_get_inode_sid(SOCK_INODE(skb->sk->sk_socket),
- &peer_sid);
- else
- peer_sid = selinux_socket_getpeer_dgram(skb);
-
- if (peer_sid == SECSID_NULL)
- return -EINVAL;
+ if (sock && (sock->sk->sk_family == PF_UNIX))
+ selinux_get_inode_sid(SOCK_INODE(sock), &peer_secid);
+ else if (skb)
+ peer_secid = selinux_socket_getpeer_dgram(skb);
- err = security_sid_to_context(peer_sid, secdata, seclen);
- if (err)
- return err;
+ if (peer_secid == SECSID_NULL)
+ err = -EINVAL;
+ *secid = peer_secid;
- return 0;
+ return err;
}
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,
return size;
}
+static int selinux_secid_to_secctx(u32 secid, char **secdata, u32 *seclen)
+{
+ return security_sid_to_context(secid, secdata, seclen);
+}
+
+static void selinux_release_secctx(char *secdata, u32 seclen)
+{
+ if (secdata)
+ kfree(secdata);
+}
+
#ifdef CONFIG_KEYS
static int selinux_key_alloc(struct key *k, struct task_struct *tsk,
@@ -4587,6 +4594,9 @@ static struct security_operations selinux_ops = {
.getprocattr = selinux_getprocattr,
.setprocattr = selinux_setprocattr,
+ .secid_to_secctx = selinux_secid_to_secctx,
+ .release_secctx = selinux_release_secctx,
+
.unix_stream_connect = selinux_socket_unix_stream_connect,
.unix_may_send = selinux_socket_unix_may_send,