diff options
Diffstat (limited to 'net/core/scm.c')
-rw-r--r-- | net/core/scm.c | 31 |
1 files changed, 23 insertions, 8 deletions
diff --git a/net/core/scm.c b/net/core/scm.c index 8f6ccfd68ef4..5472ae7a0657 100644 --- a/net/core/scm.c +++ b/net/core/scm.c | |||
@@ -45,12 +45,17 @@ | |||
45 | static __inline__ int scm_check_creds(struct ucred *creds) | 45 | static __inline__ int scm_check_creds(struct ucred *creds) |
46 | { | 46 | { |
47 | const struct cred *cred = current_cred(); | 47 | const struct cred *cred = current_cred(); |
48 | kuid_t uid = make_kuid(cred->user_ns, creds->uid); | ||
49 | kgid_t gid = make_kgid(cred->user_ns, creds->gid); | ||
50 | |||
51 | if (!uid_valid(uid) || !gid_valid(gid)) | ||
52 | return -EINVAL; | ||
48 | 53 | ||
49 | if ((creds->pid == task_tgid_vnr(current) || capable(CAP_SYS_ADMIN)) && | 54 | if ((creds->pid == task_tgid_vnr(current) || capable(CAP_SYS_ADMIN)) && |
50 | ((creds->uid == cred->uid || creds->uid == cred->euid || | 55 | ((uid_eq(uid, cred->uid) || uid_eq(uid, cred->euid) || |
51 | creds->uid == cred->suid) || capable(CAP_SETUID)) && | 56 | uid_eq(uid, cred->suid)) || capable(CAP_SETUID)) && |
52 | ((creds->gid == cred->gid || creds->gid == cred->egid || | 57 | ((gid_eq(gid, cred->gid) || gid_eq(gid, cred->egid) || |
53 | creds->gid == cred->sgid) || capable(CAP_SETGID))) { | 58 | gid_eq(gid, cred->sgid)) || capable(CAP_SETGID))) { |
54 | return 0; | 59 | return 0; |
55 | } | 60 | } |
56 | return -EPERM; | 61 | return -EPERM; |
@@ -149,6 +154,9 @@ int __scm_send(struct socket *sock, struct msghdr *msg, struct scm_cookie *p) | |||
149 | goto error; | 154 | goto error; |
150 | break; | 155 | break; |
151 | case SCM_CREDENTIALS: | 156 | case SCM_CREDENTIALS: |
157 | { | ||
158 | kuid_t uid; | ||
159 | kgid_t gid; | ||
152 | if (cmsg->cmsg_len != CMSG_LEN(sizeof(struct ucred))) | 160 | if (cmsg->cmsg_len != CMSG_LEN(sizeof(struct ucred))) |
153 | goto error; | 161 | goto error; |
154 | memcpy(&p->creds, CMSG_DATA(cmsg), sizeof(struct ucred)); | 162 | memcpy(&p->creds, CMSG_DATA(cmsg), sizeof(struct ucred)); |
@@ -166,22 +174,29 @@ int __scm_send(struct socket *sock, struct msghdr *msg, struct scm_cookie *p) | |||
166 | p->pid = pid; | 174 | p->pid = pid; |
167 | } | 175 | } |
168 | 176 | ||
177 | err = -EINVAL; | ||
178 | uid = make_kuid(current_user_ns(), p->creds.uid); | ||
179 | gid = make_kgid(current_user_ns(), p->creds.gid); | ||
180 | if (!uid_valid(uid) || !gid_valid(gid)) | ||
181 | goto error; | ||
182 | |||
169 | if (!p->cred || | 183 | if (!p->cred || |
170 | (p->cred->euid != p->creds.uid) || | 184 | !uid_eq(p->cred->euid, uid) || |
171 | (p->cred->egid != p->creds.gid)) { | 185 | !gid_eq(p->cred->egid, gid)) { |
172 | struct cred *cred; | 186 | struct cred *cred; |
173 | err = -ENOMEM; | 187 | err = -ENOMEM; |
174 | cred = prepare_creds(); | 188 | cred = prepare_creds(); |
175 | if (!cred) | 189 | if (!cred) |
176 | goto error; | 190 | goto error; |
177 | 191 | ||
178 | cred->uid = cred->euid = p->creds.uid; | 192 | cred->uid = cred->euid = uid; |
179 | cred->gid = cred->egid = p->creds.gid; | 193 | cred->gid = cred->egid = gid; |
180 | if (p->cred) | 194 | if (p->cred) |
181 | put_cred(p->cred); | 195 | put_cred(p->cred); |
182 | p->cred = cred; | 196 | p->cred = cred; |
183 | } | 197 | } |
184 | break; | 198 | break; |
199 | } | ||
185 | default: | 200 | default: |
186 | goto error; | 201 | goto error; |
187 | } | 202 | } |