aboutsummaryrefslogtreecommitdiffstats
path: root/net/core
diff options
context:
space:
mode:
authorEric W. Biederman <ebiederm@xmission.com>2012-09-06 14:20:01 -0400
committerDavid S. Miller <davem@davemloft.net>2012-09-07 14:42:05 -0400
commitdbe9a4173ea53b72b2c35d19f676a85b69f1c9fe (patch)
tree49952d501032a2bc303d1d646ec6b1f00773b266 /net/core
parentd679c5324d9a87c6295f56c2dea52d5f68834f41 (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.c17
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)) {