aboutsummaryrefslogtreecommitdiffstats
path: root/net/core/scm.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/core/scm.c')
-rw-r--r--net/core/scm.c31
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 @@
45static __inline__ int scm_check_creds(struct ucred *creds) 45static __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 }