diff options
Diffstat (limited to 'kernel/sys.c')
-rw-r--r-- | kernel/sys.c | 31 |
1 files changed, 15 insertions, 16 deletions
diff --git a/kernel/sys.c b/kernel/sys.c index 9968c5fb55b9..877fe4f8e05e 100644 --- a/kernel/sys.c +++ b/kernel/sys.c | |||
@@ -8,7 +8,6 @@ | |||
8 | #include <linux/mm.h> | 8 | #include <linux/mm.h> |
9 | #include <linux/utsname.h> | 9 | #include <linux/utsname.h> |
10 | #include <linux/mman.h> | 10 | #include <linux/mman.h> |
11 | #include <linux/smp_lock.h> | ||
12 | #include <linux/notifier.h> | 11 | #include <linux/notifier.h> |
13 | #include <linux/reboot.h> | 12 | #include <linux/reboot.h> |
14 | #include <linux/prctl.h> | 13 | #include <linux/prctl.h> |
@@ -163,6 +162,7 @@ SYSCALL_DEFINE3(setpriority, int, which, int, who, int, niceval) | |||
163 | if (niceval > 19) | 162 | if (niceval > 19) |
164 | niceval = 19; | 163 | niceval = 19; |
165 | 164 | ||
165 | rcu_read_lock(); | ||
166 | read_lock(&tasklist_lock); | 166 | read_lock(&tasklist_lock); |
167 | switch (which) { | 167 | switch (which) { |
168 | case PRIO_PROCESS: | 168 | case PRIO_PROCESS: |
@@ -190,16 +190,17 @@ SYSCALL_DEFINE3(setpriority, int, which, int, who, int, niceval) | |||
190 | !(user = find_user(who))) | 190 | !(user = find_user(who))) |
191 | goto out_unlock; /* No processes for this user */ | 191 | goto out_unlock; /* No processes for this user */ |
192 | 192 | ||
193 | do_each_thread(g, p) | 193 | do_each_thread(g, p) { |
194 | if (__task_cred(p)->uid == who) | 194 | if (__task_cred(p)->uid == who) |
195 | error = set_one_prio(p, niceval, error); | 195 | error = set_one_prio(p, niceval, error); |
196 | while_each_thread(g, p); | 196 | } while_each_thread(g, p); |
197 | if (who != cred->uid) | 197 | if (who != cred->uid) |
198 | free_uid(user); /* For find_user() */ | 198 | free_uid(user); /* For find_user() */ |
199 | break; | 199 | break; |
200 | } | 200 | } |
201 | out_unlock: | 201 | out_unlock: |
202 | read_unlock(&tasklist_lock); | 202 | read_unlock(&tasklist_lock); |
203 | rcu_read_unlock(); | ||
203 | out: | 204 | out: |
204 | return error; | 205 | return error; |
205 | } | 206 | } |
@@ -221,6 +222,7 @@ SYSCALL_DEFINE2(getpriority, int, which, int, who) | |||
221 | if (which > PRIO_USER || which < PRIO_PROCESS) | 222 | if (which > PRIO_USER || which < PRIO_PROCESS) |
222 | return -EINVAL; | 223 | return -EINVAL; |
223 | 224 | ||
225 | rcu_read_lock(); | ||
224 | read_lock(&tasklist_lock); | 226 | read_lock(&tasklist_lock); |
225 | switch (which) { | 227 | switch (which) { |
226 | case PRIO_PROCESS: | 228 | case PRIO_PROCESS: |
@@ -253,19 +255,20 @@ SYSCALL_DEFINE2(getpriority, int, which, int, who) | |||
253 | !(user = find_user(who))) | 255 | !(user = find_user(who))) |
254 | goto out_unlock; /* No processes for this user */ | 256 | goto out_unlock; /* No processes for this user */ |
255 | 257 | ||
256 | do_each_thread(g, p) | 258 | do_each_thread(g, p) { |
257 | if (__task_cred(p)->uid == who) { | 259 | if (__task_cred(p)->uid == who) { |
258 | niceval = 20 - task_nice(p); | 260 | niceval = 20 - task_nice(p); |
259 | if (niceval > retval) | 261 | if (niceval > retval) |
260 | retval = niceval; | 262 | retval = niceval; |
261 | } | 263 | } |
262 | while_each_thread(g, p); | 264 | } while_each_thread(g, p); |
263 | if (who != cred->uid) | 265 | if (who != cred->uid) |
264 | free_uid(user); /* for find_user() */ | 266 | free_uid(user); /* for find_user() */ |
265 | break; | 267 | break; |
266 | } | 268 | } |
267 | out_unlock: | 269 | out_unlock: |
268 | read_unlock(&tasklist_lock); | 270 | read_unlock(&tasklist_lock); |
271 | rcu_read_unlock(); | ||
269 | 272 | ||
270 | return retval; | 273 | return retval; |
271 | } | 274 | } |
@@ -349,6 +352,9 @@ void kernel_power_off(void) | |||
349 | machine_power_off(); | 352 | machine_power_off(); |
350 | } | 353 | } |
351 | EXPORT_SYMBOL_GPL(kernel_power_off); | 354 | EXPORT_SYMBOL_GPL(kernel_power_off); |
355 | |||
356 | static DEFINE_MUTEX(reboot_mutex); | ||
357 | |||
352 | /* | 358 | /* |
353 | * Reboot system call: for obvious reasons only root may call it, | 359 | * Reboot system call: for obvious reasons only root may call it, |
354 | * and even root needs to set up some magic numbers in the registers | 360 | * and even root needs to set up some magic numbers in the registers |
@@ -381,7 +387,7 @@ SYSCALL_DEFINE4(reboot, int, magic1, int, magic2, unsigned int, cmd, | |||
381 | if ((cmd == LINUX_REBOOT_CMD_POWER_OFF) && !pm_power_off) | 387 | if ((cmd == LINUX_REBOOT_CMD_POWER_OFF) && !pm_power_off) |
382 | cmd = LINUX_REBOOT_CMD_HALT; | 388 | cmd = LINUX_REBOOT_CMD_HALT; |
383 | 389 | ||
384 | lock_kernel(); | 390 | mutex_lock(&reboot_mutex); |
385 | switch (cmd) { | 391 | switch (cmd) { |
386 | case LINUX_REBOOT_CMD_RESTART: | 392 | case LINUX_REBOOT_CMD_RESTART: |
387 | kernel_restart(NULL); | 393 | kernel_restart(NULL); |
@@ -397,20 +403,18 @@ SYSCALL_DEFINE4(reboot, int, magic1, int, magic2, unsigned int, cmd, | |||
397 | 403 | ||
398 | case LINUX_REBOOT_CMD_HALT: | 404 | case LINUX_REBOOT_CMD_HALT: |
399 | kernel_halt(); | 405 | kernel_halt(); |
400 | unlock_kernel(); | ||
401 | do_exit(0); | 406 | do_exit(0); |
402 | panic("cannot halt"); | 407 | panic("cannot halt"); |
403 | 408 | ||
404 | case LINUX_REBOOT_CMD_POWER_OFF: | 409 | case LINUX_REBOOT_CMD_POWER_OFF: |
405 | kernel_power_off(); | 410 | kernel_power_off(); |
406 | unlock_kernel(); | ||
407 | do_exit(0); | 411 | do_exit(0); |
408 | break; | 412 | break; |
409 | 413 | ||
410 | case LINUX_REBOOT_CMD_RESTART2: | 414 | case LINUX_REBOOT_CMD_RESTART2: |
411 | if (strncpy_from_user(&buffer[0], arg, sizeof(buffer) - 1) < 0) { | 415 | if (strncpy_from_user(&buffer[0], arg, sizeof(buffer) - 1) < 0) { |
412 | unlock_kernel(); | 416 | ret = -EFAULT; |
413 | return -EFAULT; | 417 | break; |
414 | } | 418 | } |
415 | buffer[sizeof(buffer) - 1] = '\0'; | 419 | buffer[sizeof(buffer) - 1] = '\0'; |
416 | 420 | ||
@@ -433,7 +437,7 @@ SYSCALL_DEFINE4(reboot, int, magic1, int, magic2, unsigned int, cmd, | |||
433 | ret = -EINVAL; | 437 | ret = -EINVAL; |
434 | break; | 438 | break; |
435 | } | 439 | } |
436 | unlock_kernel(); | 440 | mutex_unlock(&reboot_mutex); |
437 | return ret; | 441 | return ret; |
438 | } | 442 | } |
439 | 443 | ||
@@ -567,11 +571,6 @@ static int set_user(struct cred *new) | |||
567 | if (!new_user) | 571 | if (!new_user) |
568 | return -EAGAIN; | 572 | return -EAGAIN; |
569 | 573 | ||
570 | if (!task_can_switch_user(new_user, current)) { | ||
571 | free_uid(new_user); | ||
572 | return -EINVAL; | ||
573 | } | ||
574 | |||
575 | if (atomic_read(&new_user->processes) >= | 574 | if (atomic_read(&new_user->processes) >= |
576 | current->signal->rlim[RLIMIT_NPROC].rlim_cur && | 575 | current->signal->rlim[RLIMIT_NPROC].rlim_cur && |
577 | new_user != INIT_USER) { | 576 | new_user != INIT_USER) { |