aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorEric W. Biederman <ebiederm@xmission.com>2012-05-23 18:39:45 -0400
committerEric W. Biederman <ebiederm@xmission.com>2012-08-15 00:41:58 -0400
commitb2e4f544fddc812d6fe802bab5f600b4b783f45d (patch)
tree4b17b92fc11ff292a8c683217e8027c2d3fee09e /net
parent81abe27b10af98f861c955be63da700938dd59c1 (diff)
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: David S. Miller <davem@davemloft.net> Acked-by: Serge Hallyn <serge.hallyn@canonical.com> Signed-off-by: Eric W. Biederman <ebiederm@xmission.com>
Diffstat (limited to 'net')
-rw-r--r--net/core/scm.c31
-rw-r--r--net/core/sock.c4
2 files changed, 25 insertions, 10 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 }
diff --git a/net/core/sock.c b/net/core/sock.c
index 6b654b3ddfda..9c7fe4ff30fc 100644
--- a/net/core/sock.c
+++ b/net/core/sock.c
@@ -868,8 +868,8 @@ void cred_to_ucred(struct pid *pid, const struct cred *cred,
868 if (cred) { 868 if (cred) {
869 struct user_namespace *current_ns = current_user_ns(); 869 struct user_namespace *current_ns = current_user_ns();
870 870
871 ucred->uid = from_kuid(current_ns, cred->euid); 871 ucred->uid = from_kuid_munged(current_ns, cred->euid);
872 ucred->gid = from_kgid(current_ns, cred->egid); 872 ucred->gid = from_kgid_munged(current_ns, cred->egid);
873 } 873 }
874} 874}
875EXPORT_SYMBOL_GPL(cred_to_ucred); 875EXPORT_SYMBOL_GPL(cred_to_ucred);