[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:
Catherine Zhang 2006-08-02 14:12:06 -07:00 committed by David S. Miller
parent 2b7e24b66d
commit dc49c1f94e
7 changed files with 110 additions and 44 deletions

View file

@ -128,23 +128,17 @@ static atomic_t unix_nr_socks = ATOMIC_INIT(0);
#define UNIX_ABSTRACT(sk) (unix_sk(sk)->addr->hash != UNIX_HASH_SIZE)
#ifdef CONFIG_SECURITY_NETWORK
static void unix_get_peersec_dgram(struct sk_buff *skb)
static void unix_get_secdata(struct scm_cookie *scm, struct sk_buff *skb)
{
int err;
err = security_socket_getpeersec_dgram(skb, UNIXSECDATA(skb),
UNIXSECLEN(skb));
if (err)
*(UNIXSECDATA(skb)) = NULL;
memcpy(UNIXSID(skb), &scm->secid, sizeof(u32));
}
static inline void unix_set_secdata(struct scm_cookie *scm, struct sk_buff *skb)
{
scm->secdata = *UNIXSECDATA(skb);
scm->seclen = *UNIXSECLEN(skb);
scm->secid = *UNIXSID(skb);
}
#else
static inline void unix_get_peersec_dgram(struct sk_buff *skb)
static inline void unix_get_secdata(struct scm_cookie *scm, struct sk_buff *skb)
{ }
static inline void unix_set_secdata(struct scm_cookie *scm, struct sk_buff *skb)
@ -1322,8 +1316,7 @@ static int unix_dgram_sendmsg(struct kiocb *kiocb, struct socket *sock,
memcpy(UNIXCREDS(skb), &siocb->scm->creds, sizeof(struct ucred));
if (siocb->scm->fp)
unix_attach_fds(siocb->scm, skb);
unix_get_peersec_dgram(skb);
unix_get_secdata(siocb->scm, skb);
skb->h.raw = skb->data;
err = memcpy_fromiovec(skb_put(skb,len), msg->msg_iov, len);