[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>
This commit is contained in:
committed by
David S. Miller
parent
2b7e24b66d
commit
dc49c1f94e
@ -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 (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);
|
||||
|
||||
if (peer_sid == SECSID_NULL)
|
||||
return -EINVAL;
|
||||
if (peer_secid == SECSID_NULL)
|
||||
err = -EINVAL;
|
||||
*secid = peer_secid;
|
||||
|
||||
err = security_sid_to_context(peer_sid, secdata, seclen);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
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,
|
||||
|
||||
|
Reference in New Issue
Block a user