aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/sys.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/sys.c')
-rw-r--r--kernel/sys.c592
1 files changed, 337 insertions, 255 deletions
diff --git a/kernel/sys.c b/kernel/sys.c
index 31deba8f7d16..763c3c17ded3 100644
--- a/kernel/sys.c
+++ b/kernel/sys.c
@@ -33,6 +33,7 @@
33#include <linux/task_io_accounting_ops.h> 33#include <linux/task_io_accounting_ops.h>
34#include <linux/seccomp.h> 34#include <linux/seccomp.h>
35#include <linux/cpu.h> 35#include <linux/cpu.h>
36#include <linux/ptrace.h>
36 37
37#include <linux/compat.h> 38#include <linux/compat.h>
38#include <linux/syscalls.h> 39#include <linux/syscalls.h>
@@ -112,12 +113,17 @@ EXPORT_SYMBOL(cad_pid);
112 113
113void (*pm_power_off_prepare)(void); 114void (*pm_power_off_prepare)(void);
114 115
116/*
117 * set the priority of a task
118 * - the caller must hold the RCU read lock
119 */
115static int set_one_prio(struct task_struct *p, int niceval, int error) 120static int set_one_prio(struct task_struct *p, int niceval, int error)
116{ 121{
122 const struct cred *cred = current_cred(), *pcred = __task_cred(p);
117 int no_nice; 123 int no_nice;
118 124
119 if (p->uid != current->euid && 125 if (pcred->uid != cred->euid &&
120 p->euid != current->euid && !capable(CAP_SYS_NICE)) { 126 pcred->euid != cred->euid && !capable(CAP_SYS_NICE)) {
121 error = -EPERM; 127 error = -EPERM;
122 goto out; 128 goto out;
123 } 129 }
@@ -141,6 +147,7 @@ asmlinkage long sys_setpriority(int which, int who, int niceval)
141{ 147{
142 struct task_struct *g, *p; 148 struct task_struct *g, *p;
143 struct user_struct *user; 149 struct user_struct *user;
150 const struct cred *cred = current_cred();
144 int error = -EINVAL; 151 int error = -EINVAL;
145 struct pid *pgrp; 152 struct pid *pgrp;
146 153
@@ -174,18 +181,18 @@ asmlinkage long sys_setpriority(int which, int who, int niceval)
174 } while_each_pid_thread(pgrp, PIDTYPE_PGID, p); 181 } while_each_pid_thread(pgrp, PIDTYPE_PGID, p);
175 break; 182 break;
176 case PRIO_USER: 183 case PRIO_USER:
177 user = current->user; 184 user = (struct user_struct *) cred->user;
178 if (!who) 185 if (!who)
179 who = current->uid; 186 who = cred->uid;
180 else 187 else if ((who != cred->uid) &&
181 if ((who != current->uid) && !(user = find_user(who))) 188 !(user = find_user(who)))
182 goto out_unlock; /* No processes for this user */ 189 goto out_unlock; /* No processes for this user */
183 190
184 do_each_thread(g, p) 191 do_each_thread(g, p)
185 if (p->uid == who) 192 if (__task_cred(p)->uid == who)
186 error = set_one_prio(p, niceval, error); 193 error = set_one_prio(p, niceval, error);
187 while_each_thread(g, p); 194 while_each_thread(g, p);
188 if (who != current->uid) 195 if (who != cred->uid)
189 free_uid(user); /* For find_user() */ 196 free_uid(user); /* For find_user() */
190 break; 197 break;
191 } 198 }
@@ -205,6 +212,7 @@ asmlinkage long sys_getpriority(int which, int who)
205{ 212{
206 struct task_struct *g, *p; 213 struct task_struct *g, *p;
207 struct user_struct *user; 214 struct user_struct *user;
215 const struct cred *cred = current_cred();
208 long niceval, retval = -ESRCH; 216 long niceval, retval = -ESRCH;
209 struct pid *pgrp; 217 struct pid *pgrp;
210 218
@@ -236,21 +244,21 @@ asmlinkage long sys_getpriority(int which, int who)
236 } while_each_pid_thread(pgrp, PIDTYPE_PGID, p); 244 } while_each_pid_thread(pgrp, PIDTYPE_PGID, p);
237 break; 245 break;
238 case PRIO_USER: 246 case PRIO_USER:
239 user = current->user; 247 user = (struct user_struct *) cred->user;
240 if (!who) 248 if (!who)
241 who = current->uid; 249 who = cred->uid;
242 else 250 else if ((who != cred->uid) &&
243 if ((who != current->uid) && !(user = find_user(who))) 251 !(user = find_user(who)))
244 goto out_unlock; /* No processes for this user */ 252 goto out_unlock; /* No processes for this user */
245 253
246 do_each_thread(g, p) 254 do_each_thread(g, p)
247 if (p->uid == who) { 255 if (__task_cred(p)->uid == who) {
248 niceval = 20 - task_nice(p); 256 niceval = 20 - task_nice(p);
249 if (niceval > retval) 257 if (niceval > retval)
250 retval = niceval; 258 retval = niceval;
251 } 259 }
252 while_each_thread(g, p); 260 while_each_thread(g, p);
253 if (who != current->uid) 261 if (who != cred->uid)
254 free_uid(user); /* for find_user() */ 262 free_uid(user); /* for find_user() */
255 break; 263 break;
256 } 264 }
@@ -472,46 +480,48 @@ void ctrl_alt_del(void)
472 */ 480 */
473asmlinkage long sys_setregid(gid_t rgid, gid_t egid) 481asmlinkage long sys_setregid(gid_t rgid, gid_t egid)
474{ 482{
475 int old_rgid = current->gid; 483 const struct cred *old;
476 int old_egid = current->egid; 484 struct cred *new;
477 int new_rgid = old_rgid;
478 int new_egid = old_egid;
479 int retval; 485 int retval;
480 486
487 new = prepare_creds();
488 if (!new)
489 return -ENOMEM;
490 old = current_cred();
491
481 retval = security_task_setgid(rgid, egid, (gid_t)-1, LSM_SETID_RE); 492 retval = security_task_setgid(rgid, egid, (gid_t)-1, LSM_SETID_RE);
482 if (retval) 493 if (retval)
483 return retval; 494 goto error;
484 495
496 retval = -EPERM;
485 if (rgid != (gid_t) -1) { 497 if (rgid != (gid_t) -1) {
486 if ((old_rgid == rgid) || 498 if (old->gid == rgid ||
487 (current->egid==rgid) || 499 old->egid == rgid ||
488 capable(CAP_SETGID)) 500 capable(CAP_SETGID))
489 new_rgid = rgid; 501 new->gid = rgid;
490 else 502 else
491 return -EPERM; 503 goto error;
492 } 504 }
493 if (egid != (gid_t) -1) { 505 if (egid != (gid_t) -1) {
494 if ((old_rgid == egid) || 506 if (old->gid == egid ||
495 (current->egid == egid) || 507 old->egid == egid ||
496 (current->sgid == egid) || 508 old->sgid == egid ||
497 capable(CAP_SETGID)) 509 capable(CAP_SETGID))
498 new_egid = egid; 510 new->egid = egid;
499 else 511 else
500 return -EPERM; 512 goto error;
501 }
502 if (new_egid != old_egid) {
503 set_dumpable(current->mm, suid_dumpable);
504 smp_wmb();
505 } 513 }
514
506 if (rgid != (gid_t) -1 || 515 if (rgid != (gid_t) -1 ||
507 (egid != (gid_t) -1 && egid != old_rgid)) 516 (egid != (gid_t) -1 && egid != old->gid))
508 current->sgid = new_egid; 517 new->sgid = new->egid;
509 current->fsgid = new_egid; 518 new->fsgid = new->egid;
510 current->egid = new_egid; 519
511 current->gid = new_rgid; 520 return commit_creds(new);
512 key_fsgid_changed(current); 521
513 proc_id_connector(current, PROC_EVENT_GID); 522error:
514 return 0; 523 abort_creds(new);
524 return retval;
515} 525}
516 526
517/* 527/*
@@ -521,56 +531,54 @@ asmlinkage long sys_setregid(gid_t rgid, gid_t egid)
521 */ 531 */
522asmlinkage long sys_setgid(gid_t gid) 532asmlinkage long sys_setgid(gid_t gid)
523{ 533{
524 int old_egid = current->egid; 534 const struct cred *old;
535 struct cred *new;
525 int retval; 536 int retval;
526 537
538 new = prepare_creds();
539 if (!new)
540 return -ENOMEM;
541 old = current_cred();
542
527 retval = security_task_setgid(gid, (gid_t)-1, (gid_t)-1, LSM_SETID_ID); 543 retval = security_task_setgid(gid, (gid_t)-1, (gid_t)-1, LSM_SETID_ID);
528 if (retval) 544 if (retval)
529 return retval; 545 goto error;
530 546
531 if (capable(CAP_SETGID)) { 547 retval = -EPERM;
532 if (old_egid != gid) { 548 if (capable(CAP_SETGID))
533 set_dumpable(current->mm, suid_dumpable); 549 new->gid = new->egid = new->sgid = new->fsgid = gid;
534 smp_wmb(); 550 else if (gid == old->gid || gid == old->sgid)
535 } 551 new->egid = new->fsgid = gid;
536 current->gid = current->egid = current->sgid = current->fsgid = gid;
537 } else if ((gid == current->gid) || (gid == current->sgid)) {
538 if (old_egid != gid) {
539 set_dumpable(current->mm, suid_dumpable);
540 smp_wmb();
541 }
542 current->egid = current->fsgid = gid;
543 }
544 else 552 else
545 return -EPERM; 553 goto error;
546 554
547 key_fsgid_changed(current); 555 return commit_creds(new);
548 proc_id_connector(current, PROC_EVENT_GID); 556
549 return 0; 557error:
558 abort_creds(new);
559 return retval;
550} 560}
551 561
552static int set_user(uid_t new_ruid, int dumpclear) 562/*
563 * change the user struct in a credentials set to match the new UID
564 */
565static int set_user(struct cred *new)
553{ 566{
554 struct user_struct *new_user; 567 struct user_struct *new_user;
555 568
556 new_user = alloc_uid(current->nsproxy->user_ns, new_ruid); 569 new_user = alloc_uid(current_user_ns(), new->uid);
557 if (!new_user) 570 if (!new_user)
558 return -EAGAIN; 571 return -EAGAIN;
559 572
560 if (atomic_read(&new_user->processes) >= 573 if (atomic_read(&new_user->processes) >=
561 current->signal->rlim[RLIMIT_NPROC].rlim_cur && 574 current->signal->rlim[RLIMIT_NPROC].rlim_cur &&
562 new_user != current->nsproxy->user_ns->root_user) { 575 new_user != INIT_USER) {
563 free_uid(new_user); 576 free_uid(new_user);
564 return -EAGAIN; 577 return -EAGAIN;
565 } 578 }
566 579
567 switch_uid(new_user); 580 free_uid(new->user);
568 581 new->user = new_user;
569 if (dumpclear) {
570 set_dumpable(current->mm, suid_dumpable);
571 smp_wmb();
572 }
573 current->uid = new_ruid;
574 return 0; 582 return 0;
575} 583}
576 584
@@ -591,54 +599,56 @@ static int set_user(uid_t new_ruid, int dumpclear)
591 */ 599 */
592asmlinkage long sys_setreuid(uid_t ruid, uid_t euid) 600asmlinkage long sys_setreuid(uid_t ruid, uid_t euid)
593{ 601{
594 int old_ruid, old_euid, old_suid, new_ruid, new_euid; 602 const struct cred *old;
603 struct cred *new;
595 int retval; 604 int retval;
596 605
606 new = prepare_creds();
607 if (!new)
608 return -ENOMEM;
609 old = current_cred();
610
597 retval = security_task_setuid(ruid, euid, (uid_t)-1, LSM_SETID_RE); 611 retval = security_task_setuid(ruid, euid, (uid_t)-1, LSM_SETID_RE);
598 if (retval) 612 if (retval)
599 return retval; 613 goto error;
600
601 new_ruid = old_ruid = current->uid;
602 new_euid = old_euid = current->euid;
603 old_suid = current->suid;
604 614
615 retval = -EPERM;
605 if (ruid != (uid_t) -1) { 616 if (ruid != (uid_t) -1) {
606 new_ruid = ruid; 617 new->uid = ruid;
607 if ((old_ruid != ruid) && 618 if (old->uid != ruid &&
608 (current->euid != ruid) && 619 old->euid != ruid &&
609 !capable(CAP_SETUID)) 620 !capable(CAP_SETUID))
610 return -EPERM; 621 goto error;
611 } 622 }
612 623
613 if (euid != (uid_t) -1) { 624 if (euid != (uid_t) -1) {
614 new_euid = euid; 625 new->euid = euid;
615 if ((old_ruid != euid) && 626 if (old->uid != euid &&
616 (current->euid != euid) && 627 old->euid != euid &&
617 (current->suid != euid) && 628 old->suid != euid &&
618 !capable(CAP_SETUID)) 629 !capable(CAP_SETUID))
619 return -EPERM; 630 goto error;
620 } 631 }
621 632
622 if (new_ruid != old_ruid && set_user(new_ruid, new_euid != old_euid) < 0) 633 retval = -EAGAIN;
623 return -EAGAIN; 634 if (new->uid != old->uid && set_user(new) < 0)
635 goto error;
624 636
625 if (new_euid != old_euid) {
626 set_dumpable(current->mm, suid_dumpable);
627 smp_wmb();
628 }
629 current->fsuid = current->euid = new_euid;
630 if (ruid != (uid_t) -1 || 637 if (ruid != (uid_t) -1 ||
631 (euid != (uid_t) -1 && euid != old_ruid)) 638 (euid != (uid_t) -1 && euid != old->uid))
632 current->suid = current->euid; 639 new->suid = new->euid;
633 current->fsuid = current->euid; 640 new->fsuid = new->euid;
634 641
635 key_fsuid_changed(current); 642 retval = security_task_fix_setuid(new, old, LSM_SETID_RE);
636 proc_id_connector(current, PROC_EVENT_UID); 643 if (retval < 0)
637 644 goto error;
638 return security_task_post_setuid(old_ruid, old_euid, old_suid, LSM_SETID_RE);
639}
640 645
646 return commit_creds(new);
641 647
648error:
649 abort_creds(new);
650 return retval;
651}
642 652
643/* 653/*
644 * setuid() is implemented like SysV with SAVED_IDS 654 * setuid() is implemented like SysV with SAVED_IDS
@@ -653,36 +663,41 @@ asmlinkage long sys_setreuid(uid_t ruid, uid_t euid)
653 */ 663 */
654asmlinkage long sys_setuid(uid_t uid) 664asmlinkage long sys_setuid(uid_t uid)
655{ 665{
656 int old_euid = current->euid; 666 const struct cred *old;
657 int old_ruid, old_suid, new_suid; 667 struct cred *new;
658 int retval; 668 int retval;
659 669
670 new = prepare_creds();
671 if (!new)
672 return -ENOMEM;
673 old = current_cred();
674
660 retval = security_task_setuid(uid, (uid_t)-1, (uid_t)-1, LSM_SETID_ID); 675 retval = security_task_setuid(uid, (uid_t)-1, (uid_t)-1, LSM_SETID_ID);
661 if (retval) 676 if (retval)
662 return retval; 677 goto error;
663 678
664 old_ruid = current->uid; 679 retval = -EPERM;
665 old_suid = current->suid;
666 new_suid = old_suid;
667
668 if (capable(CAP_SETUID)) { 680 if (capable(CAP_SETUID)) {
669 if (uid != old_ruid && set_user(uid, old_euid != uid) < 0) 681 new->suid = new->uid = uid;
670 return -EAGAIN; 682 if (uid != old->uid && set_user(new) < 0) {
671 new_suid = uid; 683 retval = -EAGAIN;
672 } else if ((uid != current->uid) && (uid != new_suid)) 684 goto error;
673 return -EPERM; 685 }
674 686 } else if (uid != old->uid && uid != new->suid) {
675 if (old_euid != uid) { 687 goto error;
676 set_dumpable(current->mm, suid_dumpable);
677 smp_wmb();
678 } 688 }
679 current->fsuid = current->euid = uid;
680 current->suid = new_suid;
681 689
682 key_fsuid_changed(current); 690 new->fsuid = new->euid = uid;
683 proc_id_connector(current, PROC_EVENT_UID); 691
692 retval = security_task_fix_setuid(new, old, LSM_SETID_ID);
693 if (retval < 0)
694 goto error;
684 695
685 return security_task_post_setuid(old_ruid, old_euid, old_suid, LSM_SETID_ID); 696 return commit_creds(new);
697
698error:
699 abort_creds(new);
700 return retval;
686} 701}
687 702
688 703
@@ -692,54 +707,63 @@ asmlinkage long sys_setuid(uid_t uid)
692 */ 707 */
693asmlinkage long sys_setresuid(uid_t ruid, uid_t euid, uid_t suid) 708asmlinkage long sys_setresuid(uid_t ruid, uid_t euid, uid_t suid)
694{ 709{
695 int old_ruid = current->uid; 710 const struct cred *old;
696 int old_euid = current->euid; 711 struct cred *new;
697 int old_suid = current->suid;
698 int retval; 712 int retval;
699 713
714 new = prepare_creds();
715 if (!new)
716 return -ENOMEM;
717
700 retval = security_task_setuid(ruid, euid, suid, LSM_SETID_RES); 718 retval = security_task_setuid(ruid, euid, suid, LSM_SETID_RES);
701 if (retval) 719 if (retval)
702 return retval; 720 goto error;
721 old = current_cred();
703 722
723 retval = -EPERM;
704 if (!capable(CAP_SETUID)) { 724 if (!capable(CAP_SETUID)) {
705 if ((ruid != (uid_t) -1) && (ruid != current->uid) && 725 if (ruid != (uid_t) -1 && ruid != old->uid &&
706 (ruid != current->euid) && (ruid != current->suid)) 726 ruid != old->euid && ruid != old->suid)
707 return -EPERM; 727 goto error;
708 if ((euid != (uid_t) -1) && (euid != current->uid) && 728 if (euid != (uid_t) -1 && euid != old->uid &&
709 (euid != current->euid) && (euid != current->suid)) 729 euid != old->euid && euid != old->suid)
710 return -EPERM; 730 goto error;
711 if ((suid != (uid_t) -1) && (suid != current->uid) && 731 if (suid != (uid_t) -1 && suid != old->uid &&
712 (suid != current->euid) && (suid != current->suid)) 732 suid != old->euid && suid != old->suid)
713 return -EPERM; 733 goto error;
714 } 734 }
735
736 retval = -EAGAIN;
715 if (ruid != (uid_t) -1) { 737 if (ruid != (uid_t) -1) {
716 if (ruid != current->uid && set_user(ruid, euid != current->euid) < 0) 738 new->uid = ruid;
717 return -EAGAIN; 739 if (ruid != old->uid && set_user(new) < 0)
740 goto error;
718 } 741 }
719 if (euid != (uid_t) -1) { 742 if (euid != (uid_t) -1)
720 if (euid != current->euid) { 743 new->euid = euid;
721 set_dumpable(current->mm, suid_dumpable);
722 smp_wmb();
723 }
724 current->euid = euid;
725 }
726 current->fsuid = current->euid;
727 if (suid != (uid_t) -1) 744 if (suid != (uid_t) -1)
728 current->suid = suid; 745 new->suid = suid;
746 new->fsuid = new->euid;
747
748 retval = security_task_fix_setuid(new, old, LSM_SETID_RES);
749 if (retval < 0)
750 goto error;
729 751
730 key_fsuid_changed(current); 752 return commit_creds(new);
731 proc_id_connector(current, PROC_EVENT_UID);
732 753
733 return security_task_post_setuid(old_ruid, old_euid, old_suid, LSM_SETID_RES); 754error:
755 abort_creds(new);
756 return retval;
734} 757}
735 758
736asmlinkage long sys_getresuid(uid_t __user *ruid, uid_t __user *euid, uid_t __user *suid) 759asmlinkage long sys_getresuid(uid_t __user *ruid, uid_t __user *euid, uid_t __user *suid)
737{ 760{
761 const struct cred *cred = current_cred();
738 int retval; 762 int retval;
739 763
740 if (!(retval = put_user(current->uid, ruid)) && 764 if (!(retval = put_user(cred->uid, ruid)) &&
741 !(retval = put_user(current->euid, euid))) 765 !(retval = put_user(cred->euid, euid)))
742 retval = put_user(current->suid, suid); 766 retval = put_user(cred->suid, suid);
743 767
744 return retval; 768 return retval;
745} 769}
@@ -749,48 +773,55 @@ asmlinkage long sys_getresuid(uid_t __user *ruid, uid_t __user *euid, uid_t __us
749 */ 773 */
750asmlinkage long sys_setresgid(gid_t rgid, gid_t egid, gid_t sgid) 774asmlinkage long sys_setresgid(gid_t rgid, gid_t egid, gid_t sgid)
751{ 775{
776 const struct cred *old;
777 struct cred *new;
752 int retval; 778 int retval;
753 779
780 new = prepare_creds();
781 if (!new)
782 return -ENOMEM;
783 old = current_cred();
784
754 retval = security_task_setgid(rgid, egid, sgid, LSM_SETID_RES); 785 retval = security_task_setgid(rgid, egid, sgid, LSM_SETID_RES);
755 if (retval) 786 if (retval)
756 return retval; 787 goto error;
757 788
789 retval = -EPERM;
758 if (!capable(CAP_SETGID)) { 790 if (!capable(CAP_SETGID)) {
759 if ((rgid != (gid_t) -1) && (rgid != current->gid) && 791 if (rgid != (gid_t) -1 && rgid != old->gid &&
760 (rgid != current->egid) && (rgid != current->sgid)) 792 rgid != old->egid && rgid != old->sgid)
761 return -EPERM; 793 goto error;
762 if ((egid != (gid_t) -1) && (egid != current->gid) && 794 if (egid != (gid_t) -1 && egid != old->gid &&
763 (egid != current->egid) && (egid != current->sgid)) 795 egid != old->egid && egid != old->sgid)
764 return -EPERM; 796 goto error;
765 if ((sgid != (gid_t) -1) && (sgid != current->gid) && 797 if (sgid != (gid_t) -1 && sgid != old->gid &&
766 (sgid != current->egid) && (sgid != current->sgid)) 798 sgid != old->egid && sgid != old->sgid)
767 return -EPERM; 799 goto error;
768 }
769 if (egid != (gid_t) -1) {
770 if (egid != current->egid) {
771 set_dumpable(current->mm, suid_dumpable);
772 smp_wmb();
773 }
774 current->egid = egid;
775 } 800 }
776 current->fsgid = current->egid; 801
777 if (rgid != (gid_t) -1) 802 if (rgid != (gid_t) -1)
778 current->gid = rgid; 803 new->gid = rgid;
804 if (egid != (gid_t) -1)
805 new->egid = egid;
779 if (sgid != (gid_t) -1) 806 if (sgid != (gid_t) -1)
780 current->sgid = sgid; 807 new->sgid = sgid;
808 new->fsgid = new->egid;
781 809
782 key_fsgid_changed(current); 810 return commit_creds(new);
783 proc_id_connector(current, PROC_EVENT_GID); 811
784 return 0; 812error:
813 abort_creds(new);
814 return retval;
785} 815}
786 816
787asmlinkage long sys_getresgid(gid_t __user *rgid, gid_t __user *egid, gid_t __user *sgid) 817asmlinkage long sys_getresgid(gid_t __user *rgid, gid_t __user *egid, gid_t __user *sgid)
788{ 818{
819 const struct cred *cred = current_cred();
789 int retval; 820 int retval;
790 821
791 if (!(retval = put_user(current->gid, rgid)) && 822 if (!(retval = put_user(cred->gid, rgid)) &&
792 !(retval = put_user(current->egid, egid))) 823 !(retval = put_user(cred->egid, egid)))
793 retval = put_user(current->sgid, sgid); 824 retval = put_user(cred->sgid, sgid);
794 825
795 return retval; 826 return retval;
796} 827}
@@ -804,27 +835,35 @@ asmlinkage long sys_getresgid(gid_t __user *rgid, gid_t __user *egid, gid_t __us
804 */ 835 */
805asmlinkage long sys_setfsuid(uid_t uid) 836asmlinkage long sys_setfsuid(uid_t uid)
806{ 837{
807 int old_fsuid; 838 const struct cred *old;
839 struct cred *new;
840 uid_t old_fsuid;
841
842 new = prepare_creds();
843 if (!new)
844 return current_fsuid();
845 old = current_cred();
846 old_fsuid = old->fsuid;
808 847
809 old_fsuid = current->fsuid; 848 if (security_task_setuid(uid, (uid_t)-1, (uid_t)-1, LSM_SETID_FS) < 0)
810 if (security_task_setuid(uid, (uid_t)-1, (uid_t)-1, LSM_SETID_FS)) 849 goto error;
811 return old_fsuid;
812 850
813 if (uid == current->uid || uid == current->euid || 851 if (uid == old->uid || uid == old->euid ||
814 uid == current->suid || uid == current->fsuid || 852 uid == old->suid || uid == old->fsuid ||
815 capable(CAP_SETUID)) { 853 capable(CAP_SETUID)) {
816 if (uid != old_fsuid) { 854 if (uid != old_fsuid) {
817 set_dumpable(current->mm, suid_dumpable); 855 new->fsuid = uid;
818 smp_wmb(); 856 if (security_task_fix_setuid(new, old, LSM_SETID_FS) == 0)
857 goto change_okay;
819 } 858 }
820 current->fsuid = uid;
821 } 859 }
822 860
823 key_fsuid_changed(current); 861error:
824 proc_id_connector(current, PROC_EVENT_UID); 862 abort_creds(new);
825 863 return old_fsuid;
826 security_task_post_setuid(old_fsuid, (uid_t)-1, (uid_t)-1, LSM_SETID_FS);
827 864
865change_okay:
866 commit_creds(new);
828 return old_fsuid; 867 return old_fsuid;
829} 868}
830 869
@@ -833,23 +872,34 @@ asmlinkage long sys_setfsuid(uid_t uid)
833 */ 872 */
834asmlinkage long sys_setfsgid(gid_t gid) 873asmlinkage long sys_setfsgid(gid_t gid)
835{ 874{
836 int old_fsgid; 875 const struct cred *old;
876 struct cred *new;
877 gid_t old_fsgid;
878
879 new = prepare_creds();
880 if (!new)
881 return current_fsgid();
882 old = current_cred();
883 old_fsgid = old->fsgid;
837 884
838 old_fsgid = current->fsgid;
839 if (security_task_setgid(gid, (gid_t)-1, (gid_t)-1, LSM_SETID_FS)) 885 if (security_task_setgid(gid, (gid_t)-1, (gid_t)-1, LSM_SETID_FS))
840 return old_fsgid; 886 goto error;
841 887
842 if (gid == current->gid || gid == current->egid || 888 if (gid == old->gid || gid == old->egid ||
843 gid == current->sgid || gid == current->fsgid || 889 gid == old->sgid || gid == old->fsgid ||
844 capable(CAP_SETGID)) { 890 capable(CAP_SETGID)) {
845 if (gid != old_fsgid) { 891 if (gid != old_fsgid) {
846 set_dumpable(current->mm, suid_dumpable); 892 new->fsgid = gid;
847 smp_wmb(); 893 goto change_okay;
848 } 894 }
849 current->fsgid = gid;
850 key_fsgid_changed(current);
851 proc_id_connector(current, PROC_EVENT_GID);
852 } 895 }
896
897error:
898 abort_creds(new);
899 return old_fsgid;
900
901change_okay:
902 commit_creds(new);
853 return old_fsgid; 903 return old_fsgid;
854} 904}
855 905
@@ -858,8 +908,8 @@ void do_sys_times(struct tms *tms)
858 struct task_cputime cputime; 908 struct task_cputime cputime;
859 cputime_t cutime, cstime; 909 cputime_t cutime, cstime;
860 910
861 spin_lock_irq(&current->sighand->siglock);
862 thread_group_cputime(current, &cputime); 911 thread_group_cputime(current, &cputime);
912 spin_lock_irq(&current->sighand->siglock);
863 cutime = current->signal->cutime; 913 cutime = current->signal->cutime;
864 cstime = current->signal->cstime; 914 cstime = current->signal->cstime;
865 spin_unlock_irq(&current->sighand->siglock); 915 spin_unlock_irq(&current->sighand->siglock);
@@ -878,6 +928,7 @@ asmlinkage long sys_times(struct tms __user * tbuf)
878 if (copy_to_user(tbuf, &tmp, sizeof(struct tms))) 928 if (copy_to_user(tbuf, &tmp, sizeof(struct tms)))
879 return -EFAULT; 929 return -EFAULT;
880 } 930 }
931 force_successful_syscall_return();
881 return (long) jiffies_64_to_clock_t(get_jiffies_64()); 932 return (long) jiffies_64_to_clock_t(get_jiffies_64());
882} 933}
883 934
@@ -1118,7 +1169,7 @@ EXPORT_SYMBOL(groups_free);
1118 1169
1119/* export the group_info to a user-space array */ 1170/* export the group_info to a user-space array */
1120static int groups_to_user(gid_t __user *grouplist, 1171static int groups_to_user(gid_t __user *grouplist,
1121 struct group_info *group_info) 1172 const struct group_info *group_info)
1122{ 1173{
1123 int i; 1174 int i;
1124 unsigned int count = group_info->ngroups; 1175 unsigned int count = group_info->ngroups;
@@ -1186,7 +1237,7 @@ static void groups_sort(struct group_info *group_info)
1186} 1237}
1187 1238
1188/* a simple bsearch */ 1239/* a simple bsearch */
1189int groups_search(struct group_info *group_info, gid_t grp) 1240int groups_search(const struct group_info *group_info, gid_t grp)
1190{ 1241{
1191 unsigned int left, right; 1242 unsigned int left, right;
1192 1243
@@ -1208,51 +1259,74 @@ int groups_search(struct group_info *group_info, gid_t grp)
1208 return 0; 1259 return 0;
1209} 1260}
1210 1261
1211/* validate and set current->group_info */ 1262/**
1212int set_current_groups(struct group_info *group_info) 1263 * set_groups - Change a group subscription in a set of credentials
1264 * @new: The newly prepared set of credentials to alter
1265 * @group_info: The group list to install
1266 *
1267 * Validate a group subscription and, if valid, insert it into a set
1268 * of credentials.
1269 */
1270int set_groups(struct cred *new, struct group_info *group_info)
1213{ 1271{
1214 int retval; 1272 int retval;
1215 struct group_info *old_info;
1216 1273
1217 retval = security_task_setgroups(group_info); 1274 retval = security_task_setgroups(group_info);
1218 if (retval) 1275 if (retval)
1219 return retval; 1276 return retval;
1220 1277
1278 put_group_info(new->group_info);
1221 groups_sort(group_info); 1279 groups_sort(group_info);
1222 get_group_info(group_info); 1280 get_group_info(group_info);
1281 new->group_info = group_info;
1282 return 0;
1283}
1223 1284
1224 task_lock(current); 1285EXPORT_SYMBOL(set_groups);
1225 old_info = current->group_info;
1226 current->group_info = group_info;
1227 task_unlock(current);
1228 1286
1229 put_group_info(old_info); 1287/**
1288 * set_current_groups - Change current's group subscription
1289 * @group_info: The group list to impose
1290 *
1291 * Validate a group subscription and, if valid, impose it upon current's task
1292 * security record.
1293 */
1294int set_current_groups(struct group_info *group_info)
1295{
1296 struct cred *new;
1297 int ret;
1230 1298
1231 return 0; 1299 new = prepare_creds();
1300 if (!new)
1301 return -ENOMEM;
1302
1303 ret = set_groups(new, group_info);
1304 if (ret < 0) {
1305 abort_creds(new);
1306 return ret;
1307 }
1308
1309 return commit_creds(new);
1232} 1310}
1233 1311
1234EXPORT_SYMBOL(set_current_groups); 1312EXPORT_SYMBOL(set_current_groups);
1235 1313
1236asmlinkage long sys_getgroups(int gidsetsize, gid_t __user *grouplist) 1314asmlinkage long sys_getgroups(int gidsetsize, gid_t __user *grouplist)
1237{ 1315{
1238 int i = 0; 1316 const struct cred *cred = current_cred();
1239 1317 int i;
1240 /*
1241 * SMP: Nobody else can change our grouplist. Thus we are
1242 * safe.
1243 */
1244 1318
1245 if (gidsetsize < 0) 1319 if (gidsetsize < 0)
1246 return -EINVAL; 1320 return -EINVAL;
1247 1321
1248 /* no need to grab task_lock here; it cannot change */ 1322 /* no need to grab task_lock here; it cannot change */
1249 i = current->group_info->ngroups; 1323 i = cred->group_info->ngroups;
1250 if (gidsetsize) { 1324 if (gidsetsize) {
1251 if (i > gidsetsize) { 1325 if (i > gidsetsize) {
1252 i = -EINVAL; 1326 i = -EINVAL;
1253 goto out; 1327 goto out;
1254 } 1328 }
1255 if (groups_to_user(grouplist, current->group_info)) { 1329 if (groups_to_user(grouplist, cred->group_info)) {
1256 i = -EFAULT; 1330 i = -EFAULT;
1257 goto out; 1331 goto out;
1258 } 1332 }
@@ -1296,9 +1370,11 @@ asmlinkage long sys_setgroups(int gidsetsize, gid_t __user *grouplist)
1296 */ 1370 */
1297int in_group_p(gid_t grp) 1371int in_group_p(gid_t grp)
1298{ 1372{
1373 const struct cred *cred = current_cred();
1299 int retval = 1; 1374 int retval = 1;
1300 if (grp != current->fsgid) 1375
1301 retval = groups_search(current->group_info, grp); 1376 if (grp != cred->fsgid)
1377 retval = groups_search(cred->group_info, grp);
1302 return retval; 1378 return retval;
1303} 1379}
1304 1380
@@ -1306,9 +1382,11 @@ EXPORT_SYMBOL(in_group_p);
1306 1382
1307int in_egroup_p(gid_t grp) 1383int in_egroup_p(gid_t grp)
1308{ 1384{
1385 const struct cred *cred = current_cred();
1309 int retval = 1; 1386 int retval = 1;
1310 if (grp != current->egid) 1387
1311 retval = groups_search(current->group_info, grp); 1388 if (grp != cred->egid)
1389 retval = groups_search(cred->group_info, grp);
1312 return retval; 1390 return retval;
1313} 1391}
1314 1392
@@ -1551,6 +1629,8 @@ static void k_getrusage(struct task_struct *p, int who, struct rusage *r)
1551 utime = stime = cputime_zero; 1629 utime = stime = cputime_zero;
1552 1630
1553 if (who == RUSAGE_THREAD) { 1631 if (who == RUSAGE_THREAD) {
1632 utime = task_utime(current);
1633 stime = task_stime(current);
1554 accumulate_thread_rusage(p, r); 1634 accumulate_thread_rusage(p, r);
1555 goto out; 1635 goto out;
1556 } 1636 }
@@ -1624,50 +1704,56 @@ asmlinkage long sys_umask(int mask)
1624asmlinkage long sys_prctl(int option, unsigned long arg2, unsigned long arg3, 1704asmlinkage long sys_prctl(int option, unsigned long arg2, unsigned long arg3,
1625 unsigned long arg4, unsigned long arg5) 1705 unsigned long arg4, unsigned long arg5)
1626{ 1706{
1627 long error = 0; 1707 struct task_struct *me = current;
1708 unsigned char comm[sizeof(me->comm)];
1709 long error;
1628 1710
1629 if (security_task_prctl(option, arg2, arg3, arg4, arg5, &error)) 1711 error = security_task_prctl(option, arg2, arg3, arg4, arg5);
1712 if (error != -ENOSYS)
1630 return error; 1713 return error;
1631 1714
1715 error = 0;
1632 switch (option) { 1716 switch (option) {
1633 case PR_SET_PDEATHSIG: 1717 case PR_SET_PDEATHSIG:
1634 if (!valid_signal(arg2)) { 1718 if (!valid_signal(arg2)) {
1635 error = -EINVAL; 1719 error = -EINVAL;
1636 break; 1720 break;
1637 } 1721 }
1638 current->pdeath_signal = arg2; 1722 me->pdeath_signal = arg2;
1723 error = 0;
1639 break; 1724 break;
1640 case PR_GET_PDEATHSIG: 1725 case PR_GET_PDEATHSIG:
1641 error = put_user(current->pdeath_signal, (int __user *)arg2); 1726 error = put_user(me->pdeath_signal, (int __user *)arg2);
1642 break; 1727 break;
1643 case PR_GET_DUMPABLE: 1728 case PR_GET_DUMPABLE:
1644 error = get_dumpable(current->mm); 1729 error = get_dumpable(me->mm);
1645 break; 1730 break;
1646 case PR_SET_DUMPABLE: 1731 case PR_SET_DUMPABLE:
1647 if (arg2 < 0 || arg2 > 1) { 1732 if (arg2 < 0 || arg2 > 1) {
1648 error = -EINVAL; 1733 error = -EINVAL;
1649 break; 1734 break;
1650 } 1735 }
1651 set_dumpable(current->mm, arg2); 1736 set_dumpable(me->mm, arg2);
1737 error = 0;
1652 break; 1738 break;
1653 1739
1654 case PR_SET_UNALIGN: 1740 case PR_SET_UNALIGN:
1655 error = SET_UNALIGN_CTL(current, arg2); 1741 error = SET_UNALIGN_CTL(me, arg2);
1656 break; 1742 break;
1657 case PR_GET_UNALIGN: 1743 case PR_GET_UNALIGN:
1658 error = GET_UNALIGN_CTL(current, arg2); 1744 error = GET_UNALIGN_CTL(me, arg2);
1659 break; 1745 break;
1660 case PR_SET_FPEMU: 1746 case PR_SET_FPEMU:
1661 error = SET_FPEMU_CTL(current, arg2); 1747 error = SET_FPEMU_CTL(me, arg2);
1662 break; 1748 break;
1663 case PR_GET_FPEMU: 1749 case PR_GET_FPEMU:
1664 error = GET_FPEMU_CTL(current, arg2); 1750 error = GET_FPEMU_CTL(me, arg2);
1665 break; 1751 break;
1666 case PR_SET_FPEXC: 1752 case PR_SET_FPEXC:
1667 error = SET_FPEXC_CTL(current, arg2); 1753 error = SET_FPEXC_CTL(me, arg2);
1668 break; 1754 break;
1669 case PR_GET_FPEXC: 1755 case PR_GET_FPEXC:
1670 error = GET_FPEXC_CTL(current, arg2); 1756 error = GET_FPEXC_CTL(me, arg2);
1671 break; 1757 break;
1672 case PR_GET_TIMING: 1758 case PR_GET_TIMING:
1673 error = PR_TIMING_STATISTICAL; 1759 error = PR_TIMING_STATISTICAL;
@@ -1675,33 +1761,28 @@ asmlinkage long sys_prctl(int option, unsigned long arg2, unsigned long arg3,
1675 case PR_SET_TIMING: 1761 case PR_SET_TIMING:
1676 if (arg2 != PR_TIMING_STATISTICAL) 1762 if (arg2 != PR_TIMING_STATISTICAL)
1677 error = -EINVAL; 1763 error = -EINVAL;
1764 else
1765 error = 0;
1678 break; 1766 break;
1679 1767
1680 case PR_SET_NAME: { 1768 case PR_SET_NAME:
1681 struct task_struct *me = current; 1769 comm[sizeof(me->comm)-1] = 0;
1682 unsigned char ncomm[sizeof(me->comm)]; 1770 if (strncpy_from_user(comm, (char __user *)arg2,
1683 1771 sizeof(me->comm) - 1) < 0)
1684 ncomm[sizeof(me->comm)-1] = 0;
1685 if (strncpy_from_user(ncomm, (char __user *)arg2,
1686 sizeof(me->comm)-1) < 0)
1687 return -EFAULT; 1772 return -EFAULT;
1688 set_task_comm(me, ncomm); 1773 set_task_comm(me, comm);
1689 return 0; 1774 return 0;
1690 } 1775 case PR_GET_NAME:
1691 case PR_GET_NAME: { 1776 get_task_comm(comm, me);
1692 struct task_struct *me = current; 1777 if (copy_to_user((char __user *)arg2, comm,
1693 unsigned char tcomm[sizeof(me->comm)]; 1778 sizeof(comm)))
1694
1695 get_task_comm(tcomm, me);
1696 if (copy_to_user((char __user *)arg2, tcomm, sizeof(tcomm)))
1697 return -EFAULT; 1779 return -EFAULT;
1698 return 0; 1780 return 0;
1699 }
1700 case PR_GET_ENDIAN: 1781 case PR_GET_ENDIAN:
1701 error = GET_ENDIAN(current, arg2); 1782 error = GET_ENDIAN(me, arg2);
1702 break; 1783 break;
1703 case PR_SET_ENDIAN: 1784 case PR_SET_ENDIAN:
1704 error = SET_ENDIAN(current, arg2); 1785 error = SET_ENDIAN(me, arg2);
1705 break; 1786 break;
1706 1787
1707 case PR_GET_SECCOMP: 1788 case PR_GET_SECCOMP:
@@ -1725,6 +1806,7 @@ asmlinkage long sys_prctl(int option, unsigned long arg2, unsigned long arg3,
1725 current->default_timer_slack_ns; 1806 current->default_timer_slack_ns;
1726 else 1807 else
1727 current->timer_slack_ns = arg2; 1808 current->timer_slack_ns = arg2;
1809 error = 0;
1728 break; 1810 break;
1729 default: 1811 default:
1730 error = -EINVAL; 1812 error = -EINVAL;