|
@@ -45,12 +45,17 @@
|
|
|
static __inline__ int scm_check_creds(struct ucred *creds)
|
|
|
{
|
|
|
const struct cred *cred = current_cred();
|
|
|
+ kuid_t uid = make_kuid(cred->user_ns, creds->uid);
|
|
|
+ kgid_t gid = make_kgid(cred->user_ns, creds->gid);
|
|
|
+
|
|
|
+ if (!uid_valid(uid) || !gid_valid(gid))
|
|
|
+ return -EINVAL;
|
|
|
|
|
|
if ((creds->pid == task_tgid_vnr(current) || capable(CAP_SYS_ADMIN)) &&
|
|
|
- ((creds->uid == cred->uid || creds->uid == cred->euid ||
|
|
|
- creds->uid == cred->suid) || capable(CAP_SETUID)) &&
|
|
|
- ((creds->gid == cred->gid || creds->gid == cred->egid ||
|
|
|
- creds->gid == cred->sgid) || capable(CAP_SETGID))) {
|
|
|
+ ((uid_eq(uid, cred->uid) || uid_eq(uid, cred->euid) ||
|
|
|
+ uid_eq(uid, cred->suid)) || capable(CAP_SETUID)) &&
|
|
|
+ ((gid_eq(gid, cred->gid) || gid_eq(gid, cred->egid) ||
|
|
|
+ gid_eq(gid, cred->sgid)) || capable(CAP_SETGID))) {
|
|
|
return 0;
|
|
|
}
|
|
|
return -EPERM;
|
|
@@ -149,6 +154,9 @@ int __scm_send(struct socket *sock, struct msghdr *msg, struct scm_cookie *p)
|
|
|
goto error;
|
|
|
break;
|
|
|
case SCM_CREDENTIALS:
|
|
|
+ {
|
|
|
+ kuid_t uid;
|
|
|
+ kgid_t gid;
|
|
|
if (cmsg->cmsg_len != CMSG_LEN(sizeof(struct ucred)))
|
|
|
goto error;
|
|
|
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)
|
|
|
p->pid = pid;
|
|
|
}
|
|
|
|
|
|
+ err = -EINVAL;
|
|
|
+ uid = make_kuid(current_user_ns(), p->creds.uid);
|
|
|
+ gid = make_kgid(current_user_ns(), p->creds.gid);
|
|
|
+ if (!uid_valid(uid) || !gid_valid(gid))
|
|
|
+ goto error;
|
|
|
+
|
|
|
if (!p->cred ||
|
|
|
- (p->cred->euid != p->creds.uid) ||
|
|
|
- (p->cred->egid != p->creds.gid)) {
|
|
|
+ !uid_eq(p->cred->euid, uid) ||
|
|
|
+ !gid_eq(p->cred->egid, gid)) {
|
|
|
struct cred *cred;
|
|
|
err = -ENOMEM;
|
|
|
cred = prepare_creds();
|
|
|
if (!cred)
|
|
|
goto error;
|
|
|
|
|
|
- cred->uid = cred->euid = p->creds.uid;
|
|
|
- cred->gid = cred->egid = p->creds.gid;
|
|
|
+ cred->uid = cred->euid = uid;
|
|
|
+ cred->gid = cred->egid = gid;
|
|
|
if (p->cred)
|
|
|
put_cred(p->cred);
|
|
|
p->cred = cred;
|
|
|
}
|
|
|
break;
|
|
|
+ }
|
|
|
default:
|
|
|
goto error;
|
|
|
}
|