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/core | |
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/core')
-rw-r--r-- | net/core/scm.c | 17 |
1 files changed, 11 insertions, 6 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)) { |