aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEric W. Biederman <ebiederm@xmission.com>2012-02-08 10:00:08 -0500
committerEric W. Biederman <ebiederm@xmission.com>2012-05-03 06:28:38 -0400
commit078de5f706ece36afd73bb4b8283314132d2dfdf (patch)
tree0dee00713f9cb5e2516260a66b8df99ef7d03e4d
parentae2975bc3476243b45a1e2344236d7920c268f38 (diff)
userns: Store uid and gid values in struct cred with kuid_t and kgid_t types
cred.h and a few trivial users of struct cred are changed. The rest of the users of struct cred are left for other patches as there are too many changes to make in one go and leave the change reviewable. If the user namespace is disabled and CONFIG_UIDGID_STRICT_TYPE_CHECKS are disabled the code will contiue to compile and behave correctly. Acked-by: Serge Hallyn <serge.hallyn@canonical.com> Signed-off-by: Eric W. Biederman <ebiederm@xmission.com>
-rw-r--r--arch/x86/mm/fault.c2
-rw-r--r--fs/ioprio.c8
-rw-r--r--include/linux/cred.h16
-rw-r--r--include/linux/user_namespace.h8
-rw-r--r--kernel/cred.c36
-rw-r--r--kernel/signal.c14
-rw-r--r--kernel/sys.c26
-rw-r--r--kernel/user_namespace.c4
-rw-r--r--mm/oom_kill.c4
-rw-r--r--security/commoncap.c3
10 files changed, 59 insertions, 62 deletions
diff --git a/arch/x86/mm/fault.c b/arch/x86/mm/fault.c
index 3ecfd1aaf214..76dcd9d8e0bc 100644
--- a/arch/x86/mm/fault.c
+++ b/arch/x86/mm/fault.c
@@ -582,7 +582,7 @@ show_fault_oops(struct pt_regs *regs, unsigned long error_code,
582 pte_t *pte = lookup_address(address, &level); 582 pte_t *pte = lookup_address(address, &level);
583 583
584 if (pte && pte_present(*pte) && !pte_exec(*pte)) 584 if (pte && pte_present(*pte) && !pte_exec(*pte))
585 printk(nx_warning, current_uid()); 585 printk(nx_warning, from_kuid(&init_user_ns, current_uid()));
586 } 586 }
587 587
588 printk(KERN_ALERT "BUG: unable to handle kernel "); 588 printk(KERN_ALERT "BUG: unable to handle kernel ");
diff --git a/fs/ioprio.c b/fs/ioprio.c
index 8e35e964d9ed..2072e41785d2 100644
--- a/fs/ioprio.c
+++ b/fs/ioprio.c
@@ -123,9 +123,7 @@ SYSCALL_DEFINE3(ioprio_set, int, which, int, who, int, ioprio)
123 break; 123 break;
124 124
125 do_each_thread(g, p) { 125 do_each_thread(g, p) {
126 const struct cred *tcred = __task_cred(p); 126 if (!uid_eq(task_uid(p), uid))
127 kuid_t tcred_uid = make_kuid(tcred->user_ns, tcred->uid);
128 if (!uid_eq(tcred_uid, uid))
129 continue; 127 continue;
130 ret = set_task_ioprio(p, ioprio); 128 ret = set_task_ioprio(p, ioprio);
131 if (ret) 129 if (ret)
@@ -220,9 +218,7 @@ SYSCALL_DEFINE2(ioprio_get, int, which, int, who)
220 break; 218 break;
221 219
222 do_each_thread(g, p) { 220 do_each_thread(g, p) {
223 const struct cred *tcred = __task_cred(p); 221 if (!uid_eq(task_uid(p), user->uid))
224 kuid_t tcred_uid = make_kuid(tcred->user_ns, tcred->uid);
225 if (!uid_eq(tcred_uid, user->uid))
226 continue; 222 continue;
227 tmpio = get_task_ioprio(p); 223 tmpio = get_task_ioprio(p);
228 if (tmpio < 0) 224 if (tmpio < 0)
diff --git a/include/linux/cred.h b/include/linux/cred.h
index 0ab3cda4a774..fac0579258fc 100644
--- a/include/linux/cred.h
+++ b/include/linux/cred.h
@@ -123,14 +123,14 @@ struct cred {
123#define CRED_MAGIC 0x43736564 123#define CRED_MAGIC 0x43736564
124#define CRED_MAGIC_DEAD 0x44656144 124#define CRED_MAGIC_DEAD 0x44656144
125#endif 125#endif
126 uid_t uid; /* real UID of the task */ 126 kuid_t uid; /* real UID of the task */
127 gid_t gid; /* real GID of the task */ 127 kgid_t gid; /* real GID of the task */
128 uid_t suid; /* saved UID of the task */ 128 kuid_t suid; /* saved UID of the task */
129 gid_t sgid; /* saved GID of the task */ 129 kgid_t sgid; /* saved GID of the task */
130 uid_t euid; /* effective UID of the task */ 130 kuid_t euid; /* effective UID of the task */
131 gid_t egid; /* effective GID of the task */ 131 kgid_t egid; /* effective GID of the task */
132 uid_t fsuid; /* UID for VFS ops */ 132 kuid_t fsuid; /* UID for VFS ops */
133 gid_t fsgid; /* GID for VFS ops */ 133 kgid_t fsgid; /* GID for VFS ops */
134 unsigned securebits; /* SUID-less security management */ 134 unsigned securebits; /* SUID-less security management */
135 kernel_cap_t cap_inheritable; /* caps our children can inherit */ 135 kernel_cap_t cap_inheritable; /* caps our children can inherit */
136 kernel_cap_t cap_permitted; /* caps we're permitted */ 136 kernel_cap_t cap_permitted; /* caps we're permitted */
diff --git a/include/linux/user_namespace.h b/include/linux/user_namespace.h
index 4c9846d90741..a2c61457cba1 100644
--- a/include/linux/user_namespace.h
+++ b/include/linux/user_namespace.h
@@ -70,15 +70,15 @@ static inline void put_user_ns(struct user_namespace *ns)
70#endif 70#endif
71 71
72static inline uid_t user_ns_map_uid(struct user_namespace *to, 72static inline uid_t user_ns_map_uid(struct user_namespace *to,
73 const struct cred *cred, uid_t uid) 73 const struct cred *cred, kuid_t uid)
74{ 74{
75 return from_kuid_munged(to, make_kuid(cred->user_ns, uid)); 75 return from_kuid_munged(to, uid);
76} 76}
77 77
78static inline gid_t user_ns_map_gid(struct user_namespace *to, 78static inline gid_t user_ns_map_gid(struct user_namespace *to,
79 const struct cred *cred, gid_t gid) 79 const struct cred *cred, kgid_t gid)
80{ 80{
81 return from_kgid_munged(to, make_kgid(cred->user_ns, gid)); 81 return from_kgid_munged(to, gid);
82} 82}
83 83
84#endif /* _LINUX_USER_H */ 84#endif /* _LINUX_USER_H */
diff --git a/kernel/cred.c b/kernel/cred.c
index 7a0d80669886..eddc5e2e9587 100644
--- a/kernel/cred.c
+++ b/kernel/cred.c
@@ -49,6 +49,14 @@ struct cred init_cred = {
49 .subscribers = ATOMIC_INIT(2), 49 .subscribers = ATOMIC_INIT(2),
50 .magic = CRED_MAGIC, 50 .magic = CRED_MAGIC,
51#endif 51#endif
52 .uid = GLOBAL_ROOT_UID,
53 .gid = GLOBAL_ROOT_GID,
54 .suid = GLOBAL_ROOT_UID,
55 .sgid = GLOBAL_ROOT_GID,
56 .euid = GLOBAL_ROOT_UID,
57 .egid = GLOBAL_ROOT_GID,
58 .fsuid = GLOBAL_ROOT_UID,
59 .fsgid = GLOBAL_ROOT_GID,
52 .securebits = SECUREBITS_DEFAULT, 60 .securebits = SECUREBITS_DEFAULT,
53 .cap_inheritable = CAP_EMPTY_SET, 61 .cap_inheritable = CAP_EMPTY_SET,
54 .cap_permitted = CAP_FULL_SET, 62 .cap_permitted = CAP_FULL_SET,
@@ -488,10 +496,10 @@ int commit_creds(struct cred *new)
488 get_cred(new); /* we will require a ref for the subj creds too */ 496 get_cred(new); /* we will require a ref for the subj creds too */
489 497
490 /* dumpability changes */ 498 /* dumpability changes */
491 if (old->euid != new->euid || 499 if (!uid_eq(old->euid, new->euid) ||
492 old->egid != new->egid || 500 !gid_eq(old->egid, new->egid) ||
493 old->fsuid != new->fsuid || 501 !uid_eq(old->fsuid, new->fsuid) ||
494 old->fsgid != new->fsgid || 502 !gid_eq(old->fsgid, new->fsgid) ||
495 !cap_issubset(new->cap_permitted, old->cap_permitted)) { 503 !cap_issubset(new->cap_permitted, old->cap_permitted)) {
496 if (task->mm) 504 if (task->mm)
497 set_dumpable(task->mm, suid_dumpable); 505 set_dumpable(task->mm, suid_dumpable);
@@ -500,9 +508,9 @@ int commit_creds(struct cred *new)
500 } 508 }
501 509
502 /* alter the thread keyring */ 510 /* alter the thread keyring */
503 if (new->fsuid != old->fsuid) 511 if (!uid_eq(new->fsuid, old->fsuid))
504 key_fsuid_changed(task); 512 key_fsuid_changed(task);
505 if (new->fsgid != old->fsgid) 513 if (!gid_eq(new->fsgid, old->fsgid))
506 key_fsgid_changed(task); 514 key_fsgid_changed(task);
507 515
508 /* do it 516 /* do it
@@ -519,16 +527,16 @@ int commit_creds(struct cred *new)
519 alter_cred_subscribers(old, -2); 527 alter_cred_subscribers(old, -2);
520 528
521 /* send notifications */ 529 /* send notifications */
522 if (new->uid != old->uid || 530 if (!uid_eq(new->uid, old->uid) ||
523 new->euid != old->euid || 531 !uid_eq(new->euid, old->euid) ||
524 new->suid != old->suid || 532 !uid_eq(new->suid, old->suid) ||
525 new->fsuid != old->fsuid) 533 !uid_eq(new->fsuid, old->fsuid))
526 proc_id_connector(task, PROC_EVENT_UID); 534 proc_id_connector(task, PROC_EVENT_UID);
527 535
528 if (new->gid != old->gid || 536 if (!gid_eq(new->gid, old->gid) ||
529 new->egid != old->egid || 537 !gid_eq(new->egid, old->egid) ||
530 new->sgid != old->sgid || 538 !gid_eq(new->sgid, old->sgid) ||
531 new->fsgid != old->fsgid) 539 !gid_eq(new->fsgid, old->fsgid))
532 proc_id_connector(task, PROC_EVENT_GID); 540 proc_id_connector(task, PROC_EVENT_GID);
533 541
534 /* release the old obj and subj refs both */ 542 /* release the old obj and subj refs both */
diff --git a/kernel/signal.c b/kernel/signal.c
index e2c5d84f2dac..2734dc965f69 100644
--- a/kernel/signal.c
+++ b/kernel/signal.c
@@ -1038,8 +1038,10 @@ static inline void userns_fixup_signal_uid(struct siginfo *info, struct task_str
1038 if (SI_FROMKERNEL(info)) 1038 if (SI_FROMKERNEL(info))
1039 return; 1039 return;
1040 1040
1041 info->si_uid = user_ns_map_uid(task_cred_xxx(t, user_ns), 1041 rcu_read_lock();
1042 current_cred(), info->si_uid); 1042 info->si_uid = from_kuid_munged(task_cred_xxx(t, user_ns),
1043 make_kuid(current_user_ns(), info->si_uid));
1044 rcu_read_unlock();
1043} 1045}
1044#else 1046#else
1045static inline void userns_fixup_signal_uid(struct siginfo *info, struct task_struct *t) 1047static inline void userns_fixup_signal_uid(struct siginfo *info, struct task_struct *t)
@@ -1106,7 +1108,7 @@ static int __send_signal(int sig, struct siginfo *info, struct task_struct *t,
1106 q->info.si_code = SI_USER; 1108 q->info.si_code = SI_USER;
1107 q->info.si_pid = task_tgid_nr_ns(current, 1109 q->info.si_pid = task_tgid_nr_ns(current,
1108 task_active_pid_ns(t)); 1110 task_active_pid_ns(t));
1109 q->info.si_uid = current_uid(); 1111 q->info.si_uid = from_kuid_munged(current_user_ns(), current_uid());
1110 break; 1112 break;
1111 case (unsigned long) SEND_SIG_PRIV: 1113 case (unsigned long) SEND_SIG_PRIV:
1112 q->info.si_signo = sig; 1114 q->info.si_signo = sig;
@@ -1973,7 +1975,7 @@ static void ptrace_do_notify(int signr, int exit_code, int why)
1973 info.si_signo = signr; 1975 info.si_signo = signr;
1974 info.si_code = exit_code; 1976 info.si_code = exit_code;
1975 info.si_pid = task_pid_vnr(current); 1977 info.si_pid = task_pid_vnr(current);
1976 info.si_uid = current_uid(); 1978 info.si_uid = from_kuid_munged(current_user_ns(), current_uid());
1977 1979
1978 /* Let the debugger run. */ 1980 /* Let the debugger run. */
1979 ptrace_stop(exit_code, why, 1, &info); 1981 ptrace_stop(exit_code, why, 1, &info);
@@ -2828,7 +2830,7 @@ SYSCALL_DEFINE2(kill, pid_t, pid, int, sig)
2828 info.si_errno = 0; 2830 info.si_errno = 0;
2829 info.si_code = SI_USER; 2831 info.si_code = SI_USER;
2830 info.si_pid = task_tgid_vnr(current); 2832 info.si_pid = task_tgid_vnr(current);
2831 info.si_uid = current_uid(); 2833 info.si_uid = from_kuid_munged(current_user_ns(), current_uid());
2832 2834
2833 return kill_something_info(sig, &info, pid); 2835 return kill_something_info(sig, &info, pid);
2834} 2836}
@@ -2871,7 +2873,7 @@ static int do_tkill(pid_t tgid, pid_t pid, int sig)
2871 info.si_errno = 0; 2873 info.si_errno = 0;
2872 info.si_code = SI_TKILL; 2874 info.si_code = SI_TKILL;
2873 info.si_pid = task_tgid_vnr(current); 2875 info.si_pid = task_tgid_vnr(current);
2874 info.si_uid = current_uid(); 2876 info.si_uid = from_kuid_munged(current_user_ns(), current_uid());
2875 2877
2876 return do_send_specific(tgid, pid, sig, &info); 2878 return do_send_specific(tgid, pid, sig, &info);
2877} 2879}
diff --git a/kernel/sys.c b/kernel/sys.c
index f0c43b4b6657..39962818c008 100644
--- a/kernel/sys.c
+++ b/kernel/sys.c
@@ -175,7 +175,6 @@ SYSCALL_DEFINE3(setpriority, int, which, int, who, int, niceval)
175 const struct cred *cred = current_cred(); 175 const struct cred *cred = current_cred();
176 int error = -EINVAL; 176 int error = -EINVAL;
177 struct pid *pgrp; 177 struct pid *pgrp;
178 kuid_t cred_uid;
179 kuid_t uid; 178 kuid_t uid;
180 179
181 if (which > PRIO_USER || which < PRIO_PROCESS) 180 if (which > PRIO_USER || which < PRIO_PROCESS)
@@ -209,22 +208,19 @@ SYSCALL_DEFINE3(setpriority, int, which, int, who, int, niceval)
209 } while_each_pid_thread(pgrp, PIDTYPE_PGID, p); 208 } while_each_pid_thread(pgrp, PIDTYPE_PGID, p);
210 break; 209 break;
211 case PRIO_USER: 210 case PRIO_USER:
212 cred_uid = make_kuid(cred->user_ns, cred->uid);
213 uid = make_kuid(cred->user_ns, who); 211 uid = make_kuid(cred->user_ns, who);
214 user = cred->user; 212 user = cred->user;
215 if (!who) 213 if (!who)
216 uid = cred_uid; 214 uid = cred->uid;
217 else if (!uid_eq(uid, cred_uid) && 215 else if (!uid_eq(uid, cred->uid) &&
218 !(user = find_user(uid))) 216 !(user = find_user(uid)))
219 goto out_unlock; /* No processes for this user */ 217 goto out_unlock; /* No processes for this user */
220 218
221 do_each_thread(g, p) { 219 do_each_thread(g, p) {
222 const struct cred *tcred = __task_cred(p); 220 if (uid_eq(task_uid(p), uid))
223 kuid_t tcred_uid = make_kuid(tcred->user_ns, tcred->uid);
224 if (uid_eq(tcred_uid, uid))
225 error = set_one_prio(p, niceval, error); 221 error = set_one_prio(p, niceval, error);
226 } while_each_thread(g, p); 222 } while_each_thread(g, p);
227 if (!uid_eq(uid, cred_uid)) 223 if (!uid_eq(uid, cred->uid))
228 free_uid(user); /* For find_user() */ 224 free_uid(user); /* For find_user() */
229 break; 225 break;
230 } 226 }
@@ -248,7 +244,6 @@ SYSCALL_DEFINE2(getpriority, int, which, int, who)
248 const struct cred *cred = current_cred(); 244 const struct cred *cred = current_cred();
249 long niceval, retval = -ESRCH; 245 long niceval, retval = -ESRCH;
250 struct pid *pgrp; 246 struct pid *pgrp;
251 kuid_t cred_uid;
252 kuid_t uid; 247 kuid_t uid;
253 248
254 if (which > PRIO_USER || which < PRIO_PROCESS) 249 if (which > PRIO_USER || which < PRIO_PROCESS)
@@ -280,25 +275,22 @@ SYSCALL_DEFINE2(getpriority, int, which, int, who)
280 } while_each_pid_thread(pgrp, PIDTYPE_PGID, p); 275 } while_each_pid_thread(pgrp, PIDTYPE_PGID, p);
281 break; 276 break;
282 case PRIO_USER: 277 case PRIO_USER:
283 cred_uid = make_kuid(cred->user_ns, cred->uid);
284 uid = make_kuid(cred->user_ns, who); 278 uid = make_kuid(cred->user_ns, who);
285 user = cred->user; 279 user = cred->user;
286 if (!who) 280 if (!who)
287 uid = cred_uid; 281 uid = cred->uid;
288 else if (!uid_eq(uid, cred_uid) && 282 else if (!uid_eq(uid, cred->uid) &&
289 !(user = find_user(uid))) 283 !(user = find_user(uid)))
290 goto out_unlock; /* No processes for this user */ 284 goto out_unlock; /* No processes for this user */
291 285
292 do_each_thread(g, p) { 286 do_each_thread(g, p) {
293 const struct cred *tcred = __task_cred(p); 287 if (uid_eq(task_uid(p), uid)) {
294 kuid_t tcred_uid = make_kuid(tcred->user_ns, tcred->uid);
295 if (uid_eq(tcred_uid, uid)) {
296 niceval = 20 - task_nice(p); 288 niceval = 20 - task_nice(p);
297 if (niceval > retval) 289 if (niceval > retval)
298 retval = niceval; 290 retval = niceval;
299 } 291 }
300 } while_each_thread(g, p); 292 } while_each_thread(g, p);
301 if (!uid_eq(uid, cred_uid)) 293 if (!uid_eq(uid, cred->uid))
302 free_uid(user); /* for find_user() */ 294 free_uid(user); /* for find_user() */
303 break; 295 break;
304 } 296 }
@@ -641,7 +633,7 @@ static int set_user(struct cred *new)
641{ 633{
642 struct user_struct *new_user; 634 struct user_struct *new_user;
643 635
644 new_user = alloc_uid(make_kuid(new->user_ns, new->uid)); 636 new_user = alloc_uid(new->uid);
645 if (!new_user) 637 if (!new_user)
646 return -EAGAIN; 638 return -EAGAIN;
647 639
diff --git a/kernel/user_namespace.c b/kernel/user_namespace.c
index 7eff867bfac5..86602316422d 100644
--- a/kernel/user_namespace.c
+++ b/kernel/user_namespace.c
@@ -36,8 +36,8 @@ static bool new_idmap_permitted(struct user_namespace *ns, int cap_setid,
36int create_user_ns(struct cred *new) 36int create_user_ns(struct cred *new)
37{ 37{
38 struct user_namespace *ns, *parent_ns = new->user_ns; 38 struct user_namespace *ns, *parent_ns = new->user_ns;
39 kuid_t owner = make_kuid(new->user_ns, new->euid); 39 kuid_t owner = new->euid;
40 kgid_t group = make_kgid(new->user_ns, new->egid); 40 kgid_t group = new->egid;
41 41
42 /* The creator needs a mapping in the parent user namespace 42 /* The creator needs a mapping in the parent user namespace
43 * or else we won't be able to reasonably tell userspace who 43 * or else we won't be able to reasonably tell userspace who
diff --git a/mm/oom_kill.c b/mm/oom_kill.c
index 46bf2ed5594c..9f09a1fde9f9 100644
--- a/mm/oom_kill.c
+++ b/mm/oom_kill.c
@@ -410,8 +410,8 @@ static void dump_tasks(const struct mem_cgroup *memcg, const nodemask_t *nodemas
410 } 410 }
411 411
412 pr_info("[%5d] %5d %5d %8lu %8lu %3u %3d %5d %s\n", 412 pr_info("[%5d] %5d %5d %8lu %8lu %3u %3d %5d %s\n",
413 task->pid, task_uid(task), task->tgid, 413 task->pid, from_kuid(&init_user_ns, task_uid(task)),
414 task->mm->total_vm, get_mm_rss(task->mm), 414 task->tgid, task->mm->total_vm, get_mm_rss(task->mm),
415 task_cpu(task), task->signal->oom_adj, 415 task_cpu(task), task->signal->oom_adj,
416 task->signal->oom_score_adj, task->comm); 416 task->signal->oom_score_adj, task->comm);
417 task_unlock(task); 417 task_unlock(task);
diff --git a/security/commoncap.c b/security/commoncap.c
index f2399d8afbe0..dbd465a59286 100644
--- a/security/commoncap.c
+++ b/security/commoncap.c
@@ -77,8 +77,7 @@ int cap_capable(const struct cred *cred, struct user_namespace *targ_ns,
77{ 77{
78 for (;;) { 78 for (;;) {
79 /* The owner of the user namespace has all caps. */ 79 /* The owner of the user namespace has all caps. */
80 if (targ_ns != &init_user_ns && uid_eq(targ_ns->owner, 80 if (targ_ns != &init_user_ns && uid_eq(targ_ns->owner, cred->euid))
81 make_kuid(cred->user_ns, cred->euid)))
82 return 0; 81 return 0;
83 82
84 /* Do we have the necessary capabilities? */ 83 /* Do we have the necessary capabilities? */