aboutsummaryrefslogtreecommitdiffstats
path: root/net
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 /net
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 'net')
-rw-r--r--net/ipv4/ip_sockglue.c9
-rw-r--r--net/unix/af_unix.c17
2 files changed, 12 insertions, 14 deletions
diff --git a/net/ipv4/ip_sockglue.c b/net/ipv4/ip_sockglue.c
index 84f43a3c9098..2d05c4133d3e 100644
--- a/net/ipv4/ip_sockglue.c
+++ b/net/ipv4/ip_sockglue.c
@@ -112,14 +112,19 @@ static void ip_cmsg_recv_retopts(struct msghdr *msg, struct sk_buff *skb)
112static void ip_cmsg_recv_security(struct msghdr *msg, struct sk_buff *skb) 112static void ip_cmsg_recv_security(struct msghdr *msg, struct sk_buff *skb)
113{ 113{
114 char *secdata; 114 char *secdata;
115 u32 seclen; 115 u32 seclen, secid;
116 int err; 116 int err;
117 117
118 err = security_socket_getpeersec_dgram(skb, &secdata, &seclen); 118 err = security_socket_getpeersec_dgram(NULL, skb, &secid);
119 if (err)
120 return;
121
122 err = security_secid_to_secctx(secid, &secdata, &seclen);
119 if (err) 123 if (err)
120 return; 124 return;
121 125
122 put_cmsg(msg, SOL_IP, SCM_SECURITY, seclen, secdata); 126 put_cmsg(msg, SOL_IP, SCM_SECURITY, seclen, secdata);
127 security_release_secctx(secdata, seclen);
123} 128}
124 129
125 130
diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c
index 6f2909279268..de6ec519272e 100644
--- a/net/unix/af_unix.c
+++ b/net/unix/af_unix.c
@@ -128,23 +128,17 @@ static atomic_t unix_nr_socks = ATOMIC_INIT(0);
128#define UNIX_ABSTRACT(sk) (unix_sk(sk)->addr->hash != UNIX_HASH_SIZE) 128#define UNIX_ABSTRACT(sk) (unix_sk(sk)->addr->hash != UNIX_HASH_SIZE)
129 129
130#ifdef CONFIG_SECURITY_NETWORK 130#ifdef CONFIG_SECURITY_NETWORK
131static void unix_get_peersec_dgram(struct sk_buff *skb) 131static void unix_get_secdata(struct scm_cookie *scm, struct sk_buff *skb)
132{ 132{
133 int err; 133 memcpy(UNIXSID(skb), &scm->secid, sizeof(u32));
134
135 err = security_socket_getpeersec_dgram(skb, UNIXSECDATA(skb),
136 UNIXSECLEN(skb));
137 if (err)
138 *(UNIXSECDATA(skb)) = NULL;
139} 134}
140 135
141static inline void unix_set_secdata(struct scm_cookie *scm, struct sk_buff *skb) 136static inline void unix_set_secdata(struct scm_cookie *scm, struct sk_buff *skb)
142{ 137{
143 scm->secdata = *UNIXSECDATA(skb); 138 scm->secid = *UNIXSID(skb);
144 scm->seclen = *UNIXSECLEN(skb);
145} 139}
146#else 140#else
147static inline void unix_get_peersec_dgram(struct sk_buff *skb) 141static inline void unix_get_secdata(struct scm_cookie *scm, struct sk_buff *skb)
148{ } 142{ }
149 143
150static inline void unix_set_secdata(struct scm_cookie *scm, struct sk_buff *skb) 144static 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,
1322 memcpy(UNIXCREDS(skb), &siocb->scm->creds, sizeof(struct ucred)); 1316 memcpy(UNIXCREDS(skb), &siocb->scm->creds, sizeof(struct ucred));
1323 if (siocb->scm->fp) 1317 if (siocb->scm->fp)
1324 unix_attach_fds(siocb->scm, skb); 1318 unix_attach_fds(siocb->scm, skb);
1325 1319 unix_get_secdata(siocb->scm, skb);
1326 unix_get_peersec_dgram(skb);
1327 1320
1328 skb->h.raw = skb->data; 1321 skb->h.raw = skb->data;
1329 err = memcpy_fromiovec(skb_put(skb,len), msg->msg_iov, len); 1322 err = memcpy_fromiovec(skb_put(skb,len), msg->msg_iov, len);