diff options
author | Eric W. Biederman <ebiederm@xmission.com> | 2012-09-06 14:20:01 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2012-09-07 14:42:05 -0400 |
commit | dbe9a4173ea53b72b2c35d19f676a85b69f1c9fe (patch) | |
tree | 49952d501032a2bc303d1d646ec6b1f00773b266 /net | |
parent | d679c5324d9a87c6295f56c2dea52d5f68834f41 (diff) |
scm: Don't use struct ucred in NETLINK_CB and struct scm_cookie.
Passing uids and gids on NETLINK_CB from a process in one user
namespace to a process in another user namespace can result in the
wrong uid or gid being presented to userspace. Avoid that problem by
passing kuids and kgids instead.
- define struct scm_creds for use in scm_cookie and netlink_skb_parms
that holds uid and gid information in kuid_t and kgid_t.
- Modify scm_set_cred to fill out scm_creds by heand instead of using
cred_to_ucred to fill out struct ucred. This conversion ensures
userspace does not get incorrect uid or gid values to look at.
- Modify scm_recv to convert from struct scm_creds to struct ucred
before copying credential values to userspace.
- Modify __scm_send to populate struct scm_creds on in the scm_cookie,
instead of just copying struct ucred from userspace.
- Modify netlink_sendmsg to copy scm_creds instead of struct ucred
into the NETLINK_CB.
Signed-off-by: "Eric W. Biederman" <ebiederm@xmission.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net')
-rw-r--r-- | net/core/scm.c | 17 | ||||
-rw-r--r-- | net/netlink/af_netlink.c | 2 |
2 files changed, 12 insertions, 7 deletions
diff --git a/net/core/scm.c b/net/core/scm.c index 6ab491d6c26f..9c1c63da3ca8 100644 --- a/net/core/scm.c +++ b/net/core/scm.c | |||
@@ -155,19 +155,21 @@ int __scm_send(struct socket *sock, struct msghdr *msg, struct scm_cookie *p) | |||
155 | break; | 155 | break; |
156 | case SCM_CREDENTIALS: | 156 | case SCM_CREDENTIALS: |
157 | { | 157 | { |
158 | struct ucred creds; | ||
158 | kuid_t uid; | 159 | kuid_t uid; |
159 | kgid_t gid; | 160 | kgid_t gid; |
160 | if (cmsg->cmsg_len != CMSG_LEN(sizeof(struct ucred))) | 161 | if (cmsg->cmsg_len != CMSG_LEN(sizeof(struct ucred))) |
161 | goto error; | 162 | goto error; |
162 | memcpy(&p->creds, CMSG_DATA(cmsg), sizeof(struct ucred)); | 163 | memcpy(&creds, CMSG_DATA(cmsg), sizeof(struct ucred)); |
163 | err = scm_check_creds(&p->creds); | 164 | err = scm_check_creds(&creds); |
164 | if (err) | 165 | if (err) |
165 | goto error; | 166 | goto error; |
166 | 167 | ||
167 | if (!p->pid || pid_vnr(p->pid) != p->creds.pid) { | 168 | p->creds.pid = creds.pid; |
169 | if (!p->pid || pid_vnr(p->pid) != creds.pid) { | ||
168 | struct pid *pid; | 170 | struct pid *pid; |
169 | err = -ESRCH; | 171 | err = -ESRCH; |
170 | pid = find_get_pid(p->creds.pid); | 172 | pid = find_get_pid(creds.pid); |
171 | if (!pid) | 173 | if (!pid) |
172 | goto error; | 174 | goto error; |
173 | put_pid(p->pid); | 175 | put_pid(p->pid); |
@@ -175,11 +177,14 @@ int __scm_send(struct socket *sock, struct msghdr *msg, struct scm_cookie *p) | |||
175 | } | 177 | } |
176 | 178 | ||
177 | err = -EINVAL; | 179 | err = -EINVAL; |
178 | uid = make_kuid(current_user_ns(), p->creds.uid); | 180 | uid = make_kuid(current_user_ns(), creds.uid); |
179 | gid = make_kgid(current_user_ns(), p->creds.gid); | 181 | gid = make_kgid(current_user_ns(), creds.gid); |
180 | if (!uid_valid(uid) || !gid_valid(gid)) | 182 | if (!uid_valid(uid) || !gid_valid(gid)) |
181 | goto error; | 183 | goto error; |
182 | 184 | ||
185 | p->creds.uid = uid; | ||
186 | p->creds.gid = gid; | ||
187 | |||
183 | if (!p->cred || | 188 | if (!p->cred || |
184 | !uid_eq(p->cred->euid, uid) || | 189 | !uid_eq(p->cred->euid, uid) || |
185 | !gid_eq(p->cred->egid, gid)) { | 190 | !gid_eq(p->cred->egid, gid)) { |
diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c index 382119917166..f530b1ca1773 100644 --- a/net/netlink/af_netlink.c +++ b/net/netlink/af_netlink.c | |||
@@ -1399,7 +1399,7 @@ static int netlink_sendmsg(struct kiocb *kiocb, struct socket *sock, | |||
1399 | 1399 | ||
1400 | NETLINK_CB(skb).pid = nlk->pid; | 1400 | NETLINK_CB(skb).pid = nlk->pid; |
1401 | NETLINK_CB(skb).dst_group = dst_group; | 1401 | NETLINK_CB(skb).dst_group = dst_group; |
1402 | memcpy(NETLINK_CREDS(skb), &siocb->scm->creds, sizeof(struct ucred)); | 1402 | NETLINK_CB(skb).creds = siocb->scm->creds; |
1403 | 1403 | ||
1404 | err = -EFAULT; | 1404 | err = -EFAULT; |
1405 | if (memcpy_fromiovec(skb_put(skb, len), msg->msg_iov, len)) { | 1405 | if (memcpy_fromiovec(skb_put(skb, len), msg->msg_iov, len)) { |