Commit b2e4f544 authored by Eric W. Biederman's avatar Eric W. Biederman

userns: Convert net/core/scm.c to use kuids and kgids

With the existence of kuid_t and kgid_t we can take this further
and remove the usage of struct cred altogether, ensuring we
don't get cache line misses from reference counts.   For now
however start simply and do a straight forward conversion
I can be certain is correct.

In cred_to_ucred use from_kuid_munged and from_kgid_munged
as these values are going directly to userspace and we want to use
the userspace safe values not -1 when reporting a value that does not
map.  The earlier conversion that used from_kuid was buggy in that
respect.  Oops.

Cc: Eric Dumazet <eric.dumazet@gmail.com>
Acked-by: default avatarDavid S. Miller <davem@davemloft.net>
Acked-by: default avatarSerge Hallyn <serge.hallyn@canonical.com>
Signed-off-by: default avatarEric W. Biederman <ebiederm@xmission.com>
parent 81abe27b
...@@ -45,12 +45,17 @@ ...@@ -45,12 +45,17 @@
static __inline__ int scm_check_creds(struct ucred *creds) static __inline__ int scm_check_creds(struct ucred *creds)
{ {
const struct cred *cred = current_cred(); 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)) && if ((creds->pid == task_tgid_vnr(current) || capable(CAP_SYS_ADMIN)) &&
((creds->uid == cred->uid || creds->uid == cred->euid || ((uid_eq(uid, cred->uid) || uid_eq(uid, cred->euid) ||
creds->uid == cred->suid) || capable(CAP_SETUID)) && uid_eq(uid, cred->suid)) || capable(CAP_SETUID)) &&
((creds->gid == cred->gid || creds->gid == cred->egid || ((gid_eq(gid, cred->gid) || gid_eq(gid, cred->egid) ||
creds->gid == cred->sgid) || capable(CAP_SETGID))) { gid_eq(gid, cred->sgid)) || capable(CAP_SETGID))) {
return 0; return 0;
} }
return -EPERM; return -EPERM;
...@@ -149,6 +154,9 @@ int __scm_send(struct socket *sock, struct msghdr *msg, struct scm_cookie *p) ...@@ -149,6 +154,9 @@ int __scm_send(struct socket *sock, struct msghdr *msg, struct scm_cookie *p)
goto error; goto error;
break; break;
case SCM_CREDENTIALS: case SCM_CREDENTIALS:
{
kuid_t uid;
kgid_t gid;
if (cmsg->cmsg_len != CMSG_LEN(sizeof(struct ucred))) if (cmsg->cmsg_len != CMSG_LEN(sizeof(struct ucred)))
goto error; goto error;
memcpy(&p->creds, CMSG_DATA(cmsg), sizeof(struct ucred)); 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,22 +174,29 @@ int __scm_send(struct socket *sock, struct msghdr *msg, struct scm_cookie *p)
p->pid = pid; 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 || if (!p->cred ||
(p->cred->euid != p->creds.uid) || !uid_eq(p->cred->euid, uid) ||
(p->cred->egid != p->creds.gid)) { !gid_eq(p->cred->egid, gid)) {
struct cred *cred; struct cred *cred;
err = -ENOMEM; err = -ENOMEM;
cred = prepare_creds(); cred = prepare_creds();
if (!cred) if (!cred)
goto error; goto error;
cred->uid = cred->euid = p->creds.uid; cred->uid = cred->euid = uid;
cred->gid = cred->egid = p->creds.gid; cred->gid = cred->egid = gid;
if (p->cred) if (p->cred)
put_cred(p->cred); put_cred(p->cred);
p->cred = cred; p->cred = cred;
} }
break; break;
}
default: default:
goto error; goto error;
} }
......
...@@ -868,8 +868,8 @@ void cred_to_ucred(struct pid *pid, const struct cred *cred, ...@@ -868,8 +868,8 @@ void cred_to_ucred(struct pid *pid, const struct cred *cred,
if (cred) { if (cred) {
struct user_namespace *current_ns = current_user_ns(); struct user_namespace *current_ns = current_user_ns();
ucred->uid = from_kuid(current_ns, cred->euid); ucred->uid = from_kuid_munged(current_ns, cred->euid);
ucred->gid = from_kgid(current_ns, cred->egid); ucred->gid = from_kgid_munged(current_ns, cred->egid);
} }
} }
EXPORT_SYMBOL_GPL(cred_to_ucred); EXPORT_SYMBOL_GPL(cred_to_ucred);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment