aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/sys.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/sys.c')
-rw-r--r--kernel/sys.c450
1 files changed, 245 insertions, 205 deletions
diff --git a/kernel/sys.c b/kernel/sys.c
index ccc9eb736d35..ab735040468a 100644
--- a/kernel/sys.c
+++ b/kernel/sys.c
@@ -180,7 +180,7 @@ asmlinkage long sys_setpriority(int which, int who, int niceval)
180 } while_each_pid_thread(pgrp, PIDTYPE_PGID, p); 180 } while_each_pid_thread(pgrp, PIDTYPE_PGID, p);
181 break; 181 break;
182 case PRIO_USER: 182 case PRIO_USER:
183 user = cred->user; 183 user = (struct user_struct *) cred->user;
184 if (!who) 184 if (!who)
185 who = cred->uid; 185 who = cred->uid;
186 else if ((who != cred->uid) && 186 else if ((who != cred->uid) &&
@@ -479,47 +479,48 @@ void ctrl_alt_del(void)
479 */ 479 */
480asmlinkage long sys_setregid(gid_t rgid, gid_t egid) 480asmlinkage long sys_setregid(gid_t rgid, gid_t egid)
481{ 481{
482 struct cred *cred = current->cred; 482 const struct cred *old;
483 int old_rgid = cred->gid; 483 struct cred *new;
484 int old_egid = cred->egid;
485 int new_rgid = old_rgid;
486 int new_egid = old_egid;
487 int retval; 484 int retval;
488 485
486 new = prepare_creds();
487 if (!new)
488 return -ENOMEM;
489 old = current_cred();
490
489 retval = security_task_setgid(rgid, egid, (gid_t)-1, LSM_SETID_RE); 491 retval = security_task_setgid(rgid, egid, (gid_t)-1, LSM_SETID_RE);
490 if (retval) 492 if (retval)
491 return retval; 493 goto error;
492 494
495 retval = -EPERM;
493 if (rgid != (gid_t) -1) { 496 if (rgid != (gid_t) -1) {
494 if ((old_rgid == rgid) || 497 if (old->gid == rgid ||
495 (cred->egid == rgid) || 498 old->egid == rgid ||
496 capable(CAP_SETGID)) 499 capable(CAP_SETGID))
497 new_rgid = rgid; 500 new->gid = rgid;
498 else 501 else
499 return -EPERM; 502 goto error;
500 } 503 }
501 if (egid != (gid_t) -1) { 504 if (egid != (gid_t) -1) {
502 if ((old_rgid == egid) || 505 if (old->gid == egid ||
503 (cred->egid == egid) || 506 old->egid == egid ||
504 (cred->sgid == egid) || 507 old->sgid == egid ||
505 capable(CAP_SETGID)) 508 capable(CAP_SETGID))
506 new_egid = egid; 509 new->egid = egid;
507 else 510 else
508 return -EPERM; 511 goto error;
509 }
510 if (new_egid != old_egid) {
511 set_dumpable(current->mm, suid_dumpable);
512 smp_wmb();
513 } 512 }
513
514 if (rgid != (gid_t) -1 || 514 if (rgid != (gid_t) -1 ||
515 (egid != (gid_t) -1 && egid != old_rgid)) 515 (egid != (gid_t) -1 && egid != old->gid))
516 cred->sgid = new_egid; 516 new->sgid = new->egid;
517 cred->fsgid = new_egid; 517 new->fsgid = new->egid;
518 cred->egid = new_egid; 518
519 cred->gid = new_rgid; 519 return commit_creds(new);
520 key_fsgid_changed(current); 520
521 proc_id_connector(current, PROC_EVENT_GID); 521error:
522 return 0; 522 abort_creds(new);
523 return retval;
523} 524}
524 525
525/* 526/*
@@ -529,40 +530,42 @@ asmlinkage long sys_setregid(gid_t rgid, gid_t egid)
529 */ 530 */
530asmlinkage long sys_setgid(gid_t gid) 531asmlinkage long sys_setgid(gid_t gid)
531{ 532{
532 struct cred *cred = current->cred; 533 const struct cred *old;
533 int old_egid = cred->egid; 534 struct cred *new;
534 int retval; 535 int retval;
535 536
537 new = prepare_creds();
538 if (!new)
539 return -ENOMEM;
540 old = current_cred();
541
536 retval = security_task_setgid(gid, (gid_t)-1, (gid_t)-1, LSM_SETID_ID); 542 retval = security_task_setgid(gid, (gid_t)-1, (gid_t)-1, LSM_SETID_ID);
537 if (retval) 543 if (retval)
538 return retval; 544 goto error;
539 545
540 if (capable(CAP_SETGID)) { 546 retval = -EPERM;
541 if (old_egid != gid) { 547 if (capable(CAP_SETGID))
542 set_dumpable(current->mm, suid_dumpable); 548 new->gid = new->egid = new->sgid = new->fsgid = gid;
543 smp_wmb(); 549 else if (gid == old->gid || gid == old->sgid)
544 } 550 new->egid = new->fsgid = gid;
545 cred->gid = cred->egid = cred->sgid = cred->fsgid = gid;
546 } else if ((gid == cred->gid) || (gid == cred->sgid)) {
547 if (old_egid != gid) {
548 set_dumpable(current->mm, suid_dumpable);
549 smp_wmb();
550 }
551 cred->egid = cred->fsgid = gid;
552 }
553 else 551 else
554 return -EPERM; 552 goto error;
555 553
556 key_fsgid_changed(current); 554 return commit_creds(new);
557 proc_id_connector(current, PROC_EVENT_GID); 555
558 return 0; 556error:
557 abort_creds(new);
558 return retval;
559} 559}
560 560
561static int set_user(uid_t new_ruid, int dumpclear) 561/*
562 * change the user struct in a credentials set to match the new UID
563 */
564static int set_user(struct cred *new)
562{ 565{
563 struct user_struct *new_user; 566 struct user_struct *new_user;
564 567
565 new_user = alloc_uid(current->nsproxy->user_ns, new_ruid); 568 new_user = alloc_uid(current->nsproxy->user_ns, new->uid);
566 if (!new_user) 569 if (!new_user)
567 return -EAGAIN; 570 return -EAGAIN;
568 571
@@ -573,13 +576,8 @@ static int set_user(uid_t new_ruid, int dumpclear)
573 return -EAGAIN; 576 return -EAGAIN;
574 } 577 }
575 578
576 switch_uid(new_user); 579 free_uid(new->user);
577 580 new->user = new_user;
578 if (dumpclear) {
579 set_dumpable(current->mm, suid_dumpable);
580 smp_wmb();
581 }
582 current->cred->uid = new_ruid;
583 return 0; 581 return 0;
584} 582}
585 583
@@ -600,55 +598,56 @@ static int set_user(uid_t new_ruid, int dumpclear)
600 */ 598 */
601asmlinkage long sys_setreuid(uid_t ruid, uid_t euid) 599asmlinkage long sys_setreuid(uid_t ruid, uid_t euid)
602{ 600{
603 struct cred *cred = current->cred; 601 const struct cred *old;
604 int old_ruid, old_euid, old_suid, new_ruid, new_euid; 602 struct cred *new;
605 int retval; 603 int retval;
606 604
605 new = prepare_creds();
606 if (!new)
607 return -ENOMEM;
608 old = current_cred();
609
607 retval = security_task_setuid(ruid, euid, (uid_t)-1, LSM_SETID_RE); 610 retval = security_task_setuid(ruid, euid, (uid_t)-1, LSM_SETID_RE);
608 if (retval) 611 if (retval)
609 return retval; 612 goto error;
610
611 new_ruid = old_ruid = cred->uid;
612 new_euid = old_euid = cred->euid;
613 old_suid = cred->suid;
614 613
614 retval = -EPERM;
615 if (ruid != (uid_t) -1) { 615 if (ruid != (uid_t) -1) {
616 new_ruid = ruid; 616 new->uid = ruid;
617 if ((old_ruid != ruid) && 617 if (old->uid != ruid &&
618 (cred->euid != ruid) && 618 old->euid != ruid &&
619 !capable(CAP_SETUID)) 619 !capable(CAP_SETUID))
620 return -EPERM; 620 goto error;
621 } 621 }
622 622
623 if (euid != (uid_t) -1) { 623 if (euid != (uid_t) -1) {
624 new_euid = euid; 624 new->euid = euid;
625 if ((old_ruid != euid) && 625 if (old->uid != euid &&
626 (cred->euid != euid) && 626 old->euid != euid &&
627 (cred->suid != euid) && 627 old->suid != euid &&
628 !capable(CAP_SETUID)) 628 !capable(CAP_SETUID))
629 return -EPERM; 629 goto error;
630 } 630 }
631 631
632 if (new_ruid != old_ruid && set_user(new_ruid, new_euid != old_euid) < 0) 632 retval = -EAGAIN;
633 return -EAGAIN; 633 if (new->uid != old->uid && set_user(new) < 0)
634 goto error;
634 635
635 if (new_euid != old_euid) {
636 set_dumpable(current->mm, suid_dumpable);
637 smp_wmb();
638 }
639 cred->fsuid = cred->euid = new_euid;
640 if (ruid != (uid_t) -1 || 636 if (ruid != (uid_t) -1 ||
641 (euid != (uid_t) -1 && euid != old_ruid)) 637 (euid != (uid_t) -1 && euid != old->uid))
642 cred->suid = cred->euid; 638 new->suid = new->euid;
643 cred->fsuid = cred->euid; 639 new->fsuid = new->euid;
644
645 key_fsuid_changed(current);
646 proc_id_connector(current, PROC_EVENT_UID);
647 640
648 return security_task_post_setuid(old_ruid, old_euid, old_suid, LSM_SETID_RE); 641 retval = security_task_fix_setuid(new, old, LSM_SETID_RE);
649} 642 if (retval < 0)
643 goto error;
650 644
645 return commit_creds(new);
651 646
647error:
648 abort_creds(new);
649 return retval;
650}
652 651
653/* 652/*
654 * setuid() is implemented like SysV with SAVED_IDS 653 * setuid() is implemented like SysV with SAVED_IDS
@@ -663,37 +662,41 @@ asmlinkage long sys_setreuid(uid_t ruid, uid_t euid)
663 */ 662 */
664asmlinkage long sys_setuid(uid_t uid) 663asmlinkage long sys_setuid(uid_t uid)
665{ 664{
666 struct cred *cred = current->cred; 665 const struct cred *old;
667 int old_euid = cred->euid; 666 struct cred *new;
668 int old_ruid, old_suid, new_suid;
669 int retval; 667 int retval;
670 668
669 new = prepare_creds();
670 if (!new)
671 return -ENOMEM;
672 old = current_cred();
673
671 retval = security_task_setuid(uid, (uid_t)-1, (uid_t)-1, LSM_SETID_ID); 674 retval = security_task_setuid(uid, (uid_t)-1, (uid_t)-1, LSM_SETID_ID);
672 if (retval) 675 if (retval)
673 return retval; 676 goto error;
674 677
675 old_ruid = cred->uid; 678 retval = -EPERM;
676 old_suid = cred->suid;
677 new_suid = old_suid;
678
679 if (capable(CAP_SETUID)) { 679 if (capable(CAP_SETUID)) {
680 if (uid != old_ruid && set_user(uid, old_euid != uid) < 0) 680 new->suid = new->uid = uid;
681 return -EAGAIN; 681 if (uid != old->uid && set_user(new) < 0) {
682 new_suid = uid; 682 retval = -EAGAIN;
683 } else if ((uid != cred->uid) && (uid != new_suid)) 683 goto error;
684 return -EPERM; 684 }
685 685 } else if (uid != old->uid && uid != new->suid) {
686 if (old_euid != uid) { 686 goto error;
687 set_dumpable(current->mm, suid_dumpable);
688 smp_wmb();
689 } 687 }
690 cred->fsuid = cred->euid = uid;
691 cred->suid = new_suid;
692 688
693 key_fsuid_changed(current); 689 new->fsuid = new->euid = uid;
694 proc_id_connector(current, PROC_EVENT_UID); 690
691 retval = security_task_fix_setuid(new, old, LSM_SETID_ID);
692 if (retval < 0)
693 goto error;
694
695 return commit_creds(new);
695 696
696 return security_task_post_setuid(old_ruid, old_euid, old_suid, LSM_SETID_ID); 697error:
698 abort_creds(new);
699 return retval;
697} 700}
698 701
699 702
@@ -703,47 +706,53 @@ asmlinkage long sys_setuid(uid_t uid)
703 */ 706 */
704asmlinkage long sys_setresuid(uid_t ruid, uid_t euid, uid_t suid) 707asmlinkage long sys_setresuid(uid_t ruid, uid_t euid, uid_t suid)
705{ 708{
706 struct cred *cred = current->cred; 709 const struct cred *old;
707 int old_ruid = cred->uid; 710 struct cred *new;
708 int old_euid = cred->euid;
709 int old_suid = cred->suid;
710 int retval; 711 int retval;
711 712
713 new = prepare_creds();
714 if (!new)
715 return -ENOMEM;
716
712 retval = security_task_setuid(ruid, euid, suid, LSM_SETID_RES); 717 retval = security_task_setuid(ruid, euid, suid, LSM_SETID_RES);
713 if (retval) 718 if (retval)
714 return retval; 719 goto error;
720 old = current_cred();
715 721
722 retval = -EPERM;
716 if (!capable(CAP_SETUID)) { 723 if (!capable(CAP_SETUID)) {
717 if ((ruid != (uid_t) -1) && (ruid != cred->uid) && 724 if (ruid != (uid_t) -1 && ruid != old->uid &&
718 (ruid != cred->euid) && (ruid != cred->suid)) 725 ruid != old->euid && ruid != old->suid)
719 return -EPERM; 726 goto error;
720 if ((euid != (uid_t) -1) && (euid != cred->uid) && 727 if (euid != (uid_t) -1 && euid != old->uid &&
721 (euid != cred->euid) && (euid != cred->suid)) 728 euid != old->euid && euid != old->suid)
722 return -EPERM; 729 goto error;
723 if ((suid != (uid_t) -1) && (suid != cred->uid) && 730 if (suid != (uid_t) -1 && suid != old->uid &&
724 (suid != cred->euid) && (suid != cred->suid)) 731 suid != old->euid && suid != old->suid)
725 return -EPERM; 732 goto error;
726 } 733 }
734
735 retval = -EAGAIN;
727 if (ruid != (uid_t) -1) { 736 if (ruid != (uid_t) -1) {
728 if (ruid != cred->uid && 737 new->uid = ruid;
729 set_user(ruid, euid != cred->euid) < 0) 738 if (ruid != old->uid && set_user(new) < 0)
730 return -EAGAIN; 739 goto error;
731 } 740 }
732 if (euid != (uid_t) -1) { 741 if (euid != (uid_t) -1)
733 if (euid != cred->euid) { 742 new->euid = euid;
734 set_dumpable(current->mm, suid_dumpable);
735 smp_wmb();
736 }
737 cred->euid = euid;
738 }
739 cred->fsuid = cred->euid;
740 if (suid != (uid_t) -1) 743 if (suid != (uid_t) -1)
741 cred->suid = suid; 744 new->suid = suid;
745 new->fsuid = new->euid;
742 746
743 key_fsuid_changed(current); 747 retval = security_task_fix_setuid(new, old, LSM_SETID_RES);
744 proc_id_connector(current, PROC_EVENT_UID); 748 if (retval < 0)
749 goto error;
745 750
746 return security_task_post_setuid(old_ruid, old_euid, old_suid, LSM_SETID_RES); 751 return commit_creds(new);
752
753error:
754 abort_creds(new);
755 return retval;
747} 756}
748 757
749asmlinkage long sys_getresuid(uid_t __user *ruid, uid_t __user *euid, uid_t __user *suid) 758asmlinkage long sys_getresuid(uid_t __user *ruid, uid_t __user *euid, uid_t __user *suid)
@@ -763,40 +772,45 @@ asmlinkage long sys_getresuid(uid_t __user *ruid, uid_t __user *euid, uid_t __us
763 */ 772 */
764asmlinkage long sys_setresgid(gid_t rgid, gid_t egid, gid_t sgid) 773asmlinkage long sys_setresgid(gid_t rgid, gid_t egid, gid_t sgid)
765{ 774{
766 struct cred *cred = current->cred; 775 const struct cred *old;
776 struct cred *new;
767 int retval; 777 int retval;
768 778
779 new = prepare_creds();
780 if (!new)
781 return -ENOMEM;
782 old = current_cred();
783
769 retval = security_task_setgid(rgid, egid, sgid, LSM_SETID_RES); 784 retval = security_task_setgid(rgid, egid, sgid, LSM_SETID_RES);
770 if (retval) 785 if (retval)
771 return retval; 786 goto error;
772 787
788 retval = -EPERM;
773 if (!capable(CAP_SETGID)) { 789 if (!capable(CAP_SETGID)) {
774 if ((rgid != (gid_t) -1) && (rgid != cred->gid) && 790 if (rgid != (gid_t) -1 && rgid != old->gid &&
775 (rgid != cred->egid) && (rgid != cred->sgid)) 791 rgid != old->egid && rgid != old->sgid)
776 return -EPERM; 792 goto error;
777 if ((egid != (gid_t) -1) && (egid != cred->gid) && 793 if (egid != (gid_t) -1 && egid != old->gid &&
778 (egid != cred->egid) && (egid != cred->sgid)) 794 egid != old->egid && egid != old->sgid)
779 return -EPERM; 795 goto error;
780 if ((sgid != (gid_t) -1) && (sgid != cred->gid) && 796 if (sgid != (gid_t) -1 && sgid != old->gid &&
781 (sgid != cred->egid) && (sgid != cred->sgid)) 797 sgid != old->egid && sgid != old->sgid)
782 return -EPERM; 798 goto error;
783 } 799 }
784 if (egid != (gid_t) -1) { 800
785 if (egid != cred->egid) {
786 set_dumpable(current->mm, suid_dumpable);
787 smp_wmb();
788 }
789 cred->egid = egid;
790 }
791 cred->fsgid = cred->egid;
792 if (rgid != (gid_t) -1) 801 if (rgid != (gid_t) -1)
793 cred->gid = rgid; 802 new->gid = rgid;
803 if (egid != (gid_t) -1)
804 new->egid = egid;
794 if (sgid != (gid_t) -1) 805 if (sgid != (gid_t) -1)
795 cred->sgid = sgid; 806 new->sgid = sgid;
807 new->fsgid = new->egid;
796 808
797 key_fsgid_changed(current); 809 return commit_creds(new);
798 proc_id_connector(current, PROC_EVENT_GID); 810
799 return 0; 811error:
812 abort_creds(new);
813 return retval;
800} 814}
801 815
802asmlinkage long sys_getresgid(gid_t __user *rgid, gid_t __user *egid, gid_t __user *sgid) 816asmlinkage long sys_getresgid(gid_t __user *rgid, gid_t __user *egid, gid_t __user *sgid)
@@ -820,28 +834,35 @@ asmlinkage long sys_getresgid(gid_t __user *rgid, gid_t __user *egid, gid_t __us
820 */ 834 */
821asmlinkage long sys_setfsuid(uid_t uid) 835asmlinkage long sys_setfsuid(uid_t uid)
822{ 836{
823 struct cred *cred = current->cred; 837 const struct cred *old;
824 int old_fsuid; 838 struct cred *new;
839 uid_t old_fsuid;
840
841 new = prepare_creds();
842 if (!new)
843 return current_fsuid();
844 old = current_cred();
845 old_fsuid = old->fsuid;
825 846
826 old_fsuid = cred->fsuid; 847 if (security_task_setuid(uid, (uid_t)-1, (uid_t)-1, LSM_SETID_FS) < 0)
827 if (security_task_setuid(uid, (uid_t)-1, (uid_t)-1, LSM_SETID_FS)) 848 goto error;
828 return old_fsuid;
829 849
830 if (uid == cred->uid || uid == cred->euid || 850 if (uid == old->uid || uid == old->euid ||
831 uid == cred->suid || uid == cred->fsuid || 851 uid == old->suid || uid == old->fsuid ||
832 capable(CAP_SETUID)) { 852 capable(CAP_SETUID)) {
833 if (uid != old_fsuid) { 853 if (uid != old_fsuid) {
834 set_dumpable(current->mm, suid_dumpable); 854 new->fsuid = uid;
835 smp_wmb(); 855 if (security_task_fix_setuid(new, old, LSM_SETID_FS) == 0)
856 goto change_okay;
836 } 857 }
837 cred->fsuid = uid;
838 } 858 }
839 859
840 key_fsuid_changed(current); 860error:
841 proc_id_connector(current, PROC_EVENT_UID); 861 abort_creds(new);
842 862 return old_fsuid;
843 security_task_post_setuid(old_fsuid, (uid_t)-1, (uid_t)-1, LSM_SETID_FS);
844 863
864change_okay:
865 commit_creds(new);
845 return old_fsuid; 866 return old_fsuid;
846} 867}
847 868
@@ -850,24 +871,34 @@ asmlinkage long sys_setfsuid(uid_t uid)
850 */ 871 */
851asmlinkage long sys_setfsgid(gid_t gid) 872asmlinkage long sys_setfsgid(gid_t gid)
852{ 873{
853 struct cred *cred = current->cred; 874 const struct cred *old;
854 int old_fsgid; 875 struct cred *new;
876 gid_t old_fsgid;
877
878 new = prepare_creds();
879 if (!new)
880 return current_fsgid();
881 old = current_cred();
882 old_fsgid = old->fsgid;
855 883
856 old_fsgid = cred->fsgid;
857 if (security_task_setgid(gid, (gid_t)-1, (gid_t)-1, LSM_SETID_FS)) 884 if (security_task_setgid(gid, (gid_t)-1, (gid_t)-1, LSM_SETID_FS))
858 return old_fsgid; 885 goto error;
859 886
860 if (gid == cred->gid || gid == cred->egid || 887 if (gid == old->gid || gid == old->egid ||
861 gid == cred->sgid || gid == cred->fsgid || 888 gid == old->sgid || gid == old->fsgid ||
862 capable(CAP_SETGID)) { 889 capable(CAP_SETGID)) {
863 if (gid != old_fsgid) { 890 if (gid != old_fsgid) {
864 set_dumpable(current->mm, suid_dumpable); 891 new->fsgid = gid;
865 smp_wmb(); 892 goto change_okay;
866 } 893 }
867 cred->fsgid = gid;
868 key_fsgid_changed(current);
869 proc_id_connector(current, PROC_EVENT_GID);
870 } 894 }
895
896error:
897 abort_creds(new);
898 return old_fsgid;
899
900change_okay:
901 commit_creds(new);
871 return old_fsgid; 902 return old_fsgid;
872} 903}
873 904
@@ -1136,7 +1167,7 @@ EXPORT_SYMBOL(groups_free);
1136 1167
1137/* export the group_info to a user-space array */ 1168/* export the group_info to a user-space array */
1138static int groups_to_user(gid_t __user *grouplist, 1169static int groups_to_user(gid_t __user *grouplist,
1139 struct group_info *group_info) 1170 const struct group_info *group_info)
1140{ 1171{
1141 int i; 1172 int i;
1142 unsigned int count = group_info->ngroups; 1173 unsigned int count = group_info->ngroups;
@@ -1227,31 +1258,25 @@ int groups_search(const struct group_info *group_info, gid_t grp)
1227} 1258}
1228 1259
1229/** 1260/**
1230 * set_groups - Change a group subscription in a security record 1261 * set_groups - Change a group subscription in a set of credentials
1231 * @sec: The security record to alter 1262 * @new: The newly prepared set of credentials to alter
1232 * @group_info: The group list to impose 1263 * @group_info: The group list to install
1233 * 1264 *
1234 * Validate a group subscription and, if valid, impose it upon a task security 1265 * Validate a group subscription and, if valid, insert it into a set
1235 * record. 1266 * of credentials.
1236 */ 1267 */
1237int set_groups(struct cred *cred, struct group_info *group_info) 1268int set_groups(struct cred *new, struct group_info *group_info)
1238{ 1269{
1239 int retval; 1270 int retval;
1240 struct group_info *old_info;
1241 1271
1242 retval = security_task_setgroups(group_info); 1272 retval = security_task_setgroups(group_info);
1243 if (retval) 1273 if (retval)
1244 return retval; 1274 return retval;
1245 1275
1276 put_group_info(new->group_info);
1246 groups_sort(group_info); 1277 groups_sort(group_info);
1247 get_group_info(group_info); 1278 get_group_info(group_info);
1248 1279 new->group_info = group_info;
1249 spin_lock(&cred->lock);
1250 old_info = cred->group_info;
1251 cred->group_info = group_info;
1252 spin_unlock(&cred->lock);
1253
1254 put_group_info(old_info);
1255 return 0; 1280 return 0;
1256} 1281}
1257 1282
@@ -1266,7 +1291,20 @@ EXPORT_SYMBOL(set_groups);
1266 */ 1291 */
1267int set_current_groups(struct group_info *group_info) 1292int set_current_groups(struct group_info *group_info)
1268{ 1293{
1269 return set_groups(current->cred, group_info); 1294 struct cred *new;
1295 int ret;
1296
1297 new = prepare_creds();
1298 if (!new)
1299 return -ENOMEM;
1300
1301 ret = set_groups(new, group_info);
1302 if (ret < 0) {
1303 abort_creds(new);
1304 return ret;
1305 }
1306
1307 return commit_creds(new);
1270} 1308}
1271 1309
1272EXPORT_SYMBOL(set_current_groups); 1310EXPORT_SYMBOL(set_current_groups);
@@ -1666,9 +1704,11 @@ asmlinkage long sys_prctl(int option, unsigned long arg2, unsigned long arg3,
1666 unsigned char comm[sizeof(me->comm)]; 1704 unsigned char comm[sizeof(me->comm)];
1667 long error; 1705 long error;
1668 1706
1669 if (security_task_prctl(option, arg2, arg3, arg4, arg5, &error)) 1707 error = security_task_prctl(option, arg2, arg3, arg4, arg5);
1708 if (error != -ENOSYS)
1670 return error; 1709 return error;
1671 1710
1711 error = 0;
1672 switch (option) { 1712 switch (option) {
1673 case PR_SET_PDEATHSIG: 1713 case PR_SET_PDEATHSIG:
1674 if (!valid_signal(arg2)) { 1714 if (!valid_signal(arg2)) {