diff options
Diffstat (limited to 'kernel/sys.c')
| -rw-r--r-- | kernel/sys.c | 34 |
1 files changed, 23 insertions, 11 deletions
diff --git a/kernel/sys.c b/kernel/sys.c index 71852417cfc..f0c43b4b665 100644 --- a/kernel/sys.c +++ b/kernel/sys.c | |||
| @@ -175,6 +175,8 @@ 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 | 180 | ||
| 179 | if (which > PRIO_USER || which < PRIO_PROCESS) | 181 | if (which > PRIO_USER || which < PRIO_PROCESS) |
| 180 | goto out; | 182 | goto out; |
| @@ -207,18 +209,22 @@ SYSCALL_DEFINE3(setpriority, int, which, int, who, int, niceval) | |||
| 207 | } while_each_pid_thread(pgrp, PIDTYPE_PGID, p); | 209 | } while_each_pid_thread(pgrp, PIDTYPE_PGID, p); |
| 208 | break; | 210 | break; |
| 209 | case PRIO_USER: | 211 | case PRIO_USER: |
| 212 | cred_uid = make_kuid(cred->user_ns, cred->uid); | ||
| 213 | uid = make_kuid(cred->user_ns, who); | ||
| 210 | user = cred->user; | 214 | user = cred->user; |
| 211 | if (!who) | 215 | if (!who) |
| 212 | who = cred->uid; | 216 | uid = cred_uid; |
| 213 | else if ((who != cred->uid) && | 217 | else if (!uid_eq(uid, cred_uid) && |
| 214 | !(user = find_user(who))) | 218 | !(user = find_user(uid))) |
| 215 | goto out_unlock; /* No processes for this user */ | 219 | goto out_unlock; /* No processes for this user */ |
| 216 | 220 | ||
| 217 | do_each_thread(g, p) { | 221 | do_each_thread(g, p) { |
| 218 | if (__task_cred(p)->uid == who) | 222 | const struct cred *tcred = __task_cred(p); |
| 223 | kuid_t tcred_uid = make_kuid(tcred->user_ns, tcred->uid); | ||
| 224 | if (uid_eq(tcred_uid, uid)) | ||
| 219 | error = set_one_prio(p, niceval, error); | 225 | error = set_one_prio(p, niceval, error); |
| 220 | } while_each_thread(g, p); | 226 | } while_each_thread(g, p); |
| 221 | if (who != cred->uid) | 227 | if (!uid_eq(uid, cred_uid)) |
| 222 | free_uid(user); /* For find_user() */ | 228 | free_uid(user); /* For find_user() */ |
| 223 | break; | 229 | break; |
| 224 | } | 230 | } |
| @@ -242,6 +248,8 @@ SYSCALL_DEFINE2(getpriority, int, which, int, who) | |||
| 242 | const struct cred *cred = current_cred(); | 248 | const struct cred *cred = current_cred(); |
| 243 | long niceval, retval = -ESRCH; | 249 | long niceval, retval = -ESRCH; |
| 244 | struct pid *pgrp; | 250 | struct pid *pgrp; |
| 251 | kuid_t cred_uid; | ||
| 252 | kuid_t uid; | ||
| 245 | 253 | ||
| 246 | if (which > PRIO_USER || which < PRIO_PROCESS) | 254 | if (which > PRIO_USER || which < PRIO_PROCESS) |
| 247 | return -EINVAL; | 255 | return -EINVAL; |
| @@ -272,21 +280,25 @@ SYSCALL_DEFINE2(getpriority, int, which, int, who) | |||
| 272 | } while_each_pid_thread(pgrp, PIDTYPE_PGID, p); | 280 | } while_each_pid_thread(pgrp, PIDTYPE_PGID, p); |
| 273 | break; | 281 | break; |
| 274 | case PRIO_USER: | 282 | case PRIO_USER: |
| 283 | cred_uid = make_kuid(cred->user_ns, cred->uid); | ||
| 284 | uid = make_kuid(cred->user_ns, who); | ||
| 275 | user = cred->user; | 285 | user = cred->user; |
| 276 | if (!who) | 286 | if (!who) |
| 277 | who = cred->uid; | 287 | uid = cred_uid; |
| 278 | else if ((who != cred->uid) && | 288 | else if (!uid_eq(uid, cred_uid) && |
| 279 | !(user = find_user(who))) | 289 | !(user = find_user(uid))) |
| 280 | goto out_unlock; /* No processes for this user */ | 290 | goto out_unlock; /* No processes for this user */ |
| 281 | 291 | ||
| 282 | do_each_thread(g, p) { | 292 | do_each_thread(g, p) { |
| 283 | if (__task_cred(p)->uid == who) { | 293 | const struct cred *tcred = __task_cred(p); |
| 294 | kuid_t tcred_uid = make_kuid(tcred->user_ns, tcred->uid); | ||
| 295 | if (uid_eq(tcred_uid, uid)) { | ||
| 284 | niceval = 20 - task_nice(p); | 296 | niceval = 20 - task_nice(p); |
| 285 | if (niceval > retval) | 297 | if (niceval > retval) |
| 286 | retval = niceval; | 298 | retval = niceval; |
| 287 | } | 299 | } |
| 288 | } while_each_thread(g, p); | 300 | } while_each_thread(g, p); |
| 289 | if (who != cred->uid) | 301 | if (!uid_eq(uid, cred_uid)) |
| 290 | free_uid(user); /* for find_user() */ | 302 | free_uid(user); /* for find_user() */ |
| 291 | break; | 303 | break; |
| 292 | } | 304 | } |
| @@ -629,7 +641,7 @@ static int set_user(struct cred *new) | |||
| 629 | { | 641 | { |
| 630 | struct user_struct *new_user; | 642 | struct user_struct *new_user; |
| 631 | 643 | ||
| 632 | new_user = alloc_uid(current_user_ns(), new->uid); | 644 | new_user = alloc_uid(make_kuid(new->user_ns, new->uid)); |
| 633 | if (!new_user) | 645 | if (!new_user) |
| 634 | return -EAGAIN; | 646 | return -EAGAIN; |
| 635 | 647 | ||
