diff options
author | David Howells <dhowells@redhat.com> | 2008-11-13 18:39:16 -0500 |
---|---|---|
committer | James Morris <jmorris@namei.org> | 2008-11-13 18:39:16 -0500 |
commit | b6dff3ec5e116e3af6f537d4caedcad6b9e5082a (patch) | |
tree | 9e76f972eb7ce9b84e0146c8e4126a3f86acb428 /kernel/sys.c | |
parent | 15a2460ed0af7538ca8e6c610fe607a2cd9da142 (diff) |
CRED: Separate task security context from task_struct
Separate the task security context from task_struct. At this point, the
security data is temporarily embedded in the task_struct with two pointers
pointing to it.
Note that the Alpha arch is altered as it refers to (E)UID and (E)GID in
entry.S via asm-offsets.
With comment fixes Signed-off-by: Marc Dionne <marc.c.dionne@gmail.com>
Signed-off-by: David Howells <dhowells@redhat.com>
Acked-by: James Morris <jmorris@namei.org>
Acked-by: Serge Hallyn <serue@us.ibm.com>
Signed-off-by: James Morris <jmorris@namei.org>
Diffstat (limited to 'kernel/sys.c')
-rw-r--r-- | kernel/sys.c | 266 |
1 files changed, 151 insertions, 115 deletions
diff --git a/kernel/sys.c b/kernel/sys.c index ed5c29c748ac..5d81f07c0150 100644 --- a/kernel/sys.c +++ b/kernel/sys.c | |||
@@ -117,7 +117,9 @@ static int set_one_prio(struct task_struct *p, int niceval, int error) | |||
117 | uid_t euid = current_euid(); | 117 | uid_t euid = current_euid(); |
118 | int no_nice; | 118 | int no_nice; |
119 | 119 | ||
120 | if (p->uid != euid && p->euid != euid && !capable(CAP_SYS_NICE)) { | 120 | if (p->cred->uid != euid && |
121 | p->cred->euid != euid && | ||
122 | !capable(CAP_SYS_NICE)) { | ||
121 | error = -EPERM; | 123 | error = -EPERM; |
122 | goto out; | 124 | goto out; |
123 | } | 125 | } |
@@ -174,7 +176,7 @@ asmlinkage long sys_setpriority(int which, int who, int niceval) | |||
174 | } while_each_pid_thread(pgrp, PIDTYPE_PGID, p); | 176 | } while_each_pid_thread(pgrp, PIDTYPE_PGID, p); |
175 | break; | 177 | break; |
176 | case PRIO_USER: | 178 | case PRIO_USER: |
177 | user = current->user; | 179 | user = current->cred->user; |
178 | if (!who) | 180 | if (!who) |
179 | who = current_uid(); | 181 | who = current_uid(); |
180 | else | 182 | else |
@@ -182,7 +184,7 @@ asmlinkage long sys_setpriority(int which, int who, int niceval) | |||
182 | goto out_unlock; /* No processes for this user */ | 184 | goto out_unlock; /* No processes for this user */ |
183 | 185 | ||
184 | do_each_thread(g, p) | 186 | do_each_thread(g, p) |
185 | if (p->uid == who) | 187 | if (p->cred->uid == who) |
186 | error = set_one_prio(p, niceval, error); | 188 | error = set_one_prio(p, niceval, error); |
187 | while_each_thread(g, p); | 189 | while_each_thread(g, p); |
188 | if (who != current_uid()) | 190 | if (who != current_uid()) |
@@ -236,7 +238,7 @@ asmlinkage long sys_getpriority(int which, int who) | |||
236 | } while_each_pid_thread(pgrp, PIDTYPE_PGID, p); | 238 | } while_each_pid_thread(pgrp, PIDTYPE_PGID, p); |
237 | break; | 239 | break; |
238 | case PRIO_USER: | 240 | case PRIO_USER: |
239 | user = current->user; | 241 | user = current->cred->user; |
240 | if (!who) | 242 | if (!who) |
241 | who = current_uid(); | 243 | who = current_uid(); |
242 | else | 244 | else |
@@ -244,7 +246,7 @@ asmlinkage long sys_getpriority(int which, int who) | |||
244 | goto out_unlock; /* No processes for this user */ | 246 | goto out_unlock; /* No processes for this user */ |
245 | 247 | ||
246 | do_each_thread(g, p) | 248 | do_each_thread(g, p) |
247 | if (p->uid == who) { | 249 | if (p->cred->uid == who) { |
248 | niceval = 20 - task_nice(p); | 250 | niceval = 20 - task_nice(p); |
249 | if (niceval > retval) | 251 | if (niceval > retval) |
250 | retval = niceval; | 252 | retval = niceval; |
@@ -472,8 +474,9 @@ void ctrl_alt_del(void) | |||
472 | */ | 474 | */ |
473 | asmlinkage long sys_setregid(gid_t rgid, gid_t egid) | 475 | asmlinkage long sys_setregid(gid_t rgid, gid_t egid) |
474 | { | 476 | { |
475 | int old_rgid = current->gid; | 477 | struct cred *cred = current->cred; |
476 | int old_egid = current->egid; | 478 | int old_rgid = cred->gid; |
479 | int old_egid = cred->egid; | ||
477 | int new_rgid = old_rgid; | 480 | int new_rgid = old_rgid; |
478 | int new_egid = old_egid; | 481 | int new_egid = old_egid; |
479 | int retval; | 482 | int retval; |
@@ -484,7 +487,7 @@ asmlinkage long sys_setregid(gid_t rgid, gid_t egid) | |||
484 | 487 | ||
485 | if (rgid != (gid_t) -1) { | 488 | if (rgid != (gid_t) -1) { |
486 | if ((old_rgid == rgid) || | 489 | if ((old_rgid == rgid) || |
487 | (current->egid==rgid) || | 490 | (cred->egid == rgid) || |
488 | capable(CAP_SETGID)) | 491 | capable(CAP_SETGID)) |
489 | new_rgid = rgid; | 492 | new_rgid = rgid; |
490 | else | 493 | else |
@@ -492,8 +495,8 @@ asmlinkage long sys_setregid(gid_t rgid, gid_t egid) | |||
492 | } | 495 | } |
493 | if (egid != (gid_t) -1) { | 496 | if (egid != (gid_t) -1) { |
494 | if ((old_rgid == egid) || | 497 | if ((old_rgid == egid) || |
495 | (current->egid == egid) || | 498 | (cred->egid == egid) || |
496 | (current->sgid == egid) || | 499 | (cred->sgid == egid) || |
497 | capable(CAP_SETGID)) | 500 | capable(CAP_SETGID)) |
498 | new_egid = egid; | 501 | new_egid = egid; |
499 | else | 502 | else |
@@ -505,10 +508,10 @@ asmlinkage long sys_setregid(gid_t rgid, gid_t egid) | |||
505 | } | 508 | } |
506 | if (rgid != (gid_t) -1 || | 509 | if (rgid != (gid_t) -1 || |
507 | (egid != (gid_t) -1 && egid != old_rgid)) | 510 | (egid != (gid_t) -1 && egid != old_rgid)) |
508 | current->sgid = new_egid; | 511 | cred->sgid = new_egid; |
509 | current->fsgid = new_egid; | 512 | cred->fsgid = new_egid; |
510 | current->egid = new_egid; | 513 | cred->egid = new_egid; |
511 | current->gid = new_rgid; | 514 | cred->gid = new_rgid; |
512 | key_fsgid_changed(current); | 515 | key_fsgid_changed(current); |
513 | proc_id_connector(current, PROC_EVENT_GID); | 516 | proc_id_connector(current, PROC_EVENT_GID); |
514 | return 0; | 517 | return 0; |
@@ -521,7 +524,8 @@ asmlinkage long sys_setregid(gid_t rgid, gid_t egid) | |||
521 | */ | 524 | */ |
522 | asmlinkage long sys_setgid(gid_t gid) | 525 | asmlinkage long sys_setgid(gid_t gid) |
523 | { | 526 | { |
524 | int old_egid = current->egid; | 527 | struct cred *cred = current->cred; |
528 | int old_egid = cred->egid; | ||
525 | int retval; | 529 | int retval; |
526 | 530 | ||
527 | retval = security_task_setgid(gid, (gid_t)-1, (gid_t)-1, LSM_SETID_ID); | 531 | retval = security_task_setgid(gid, (gid_t)-1, (gid_t)-1, LSM_SETID_ID); |
@@ -533,13 +537,13 @@ asmlinkage long sys_setgid(gid_t gid) | |||
533 | set_dumpable(current->mm, suid_dumpable); | 537 | set_dumpable(current->mm, suid_dumpable); |
534 | smp_wmb(); | 538 | smp_wmb(); |
535 | } | 539 | } |
536 | current->gid = current->egid = current->sgid = current->fsgid = gid; | 540 | cred->gid = cred->egid = cred->sgid = cred->fsgid = gid; |
537 | } else if ((gid == current->gid) || (gid == current->sgid)) { | 541 | } else if ((gid == cred->gid) || (gid == cred->sgid)) { |
538 | if (old_egid != gid) { | 542 | if (old_egid != gid) { |
539 | set_dumpable(current->mm, suid_dumpable); | 543 | set_dumpable(current->mm, suid_dumpable); |
540 | smp_wmb(); | 544 | smp_wmb(); |
541 | } | 545 | } |
542 | current->egid = current->fsgid = gid; | 546 | cred->egid = cred->fsgid = gid; |
543 | } | 547 | } |
544 | else | 548 | else |
545 | return -EPERM; | 549 | return -EPERM; |
@@ -570,7 +574,7 @@ static int set_user(uid_t new_ruid, int dumpclear) | |||
570 | set_dumpable(current->mm, suid_dumpable); | 574 | set_dumpable(current->mm, suid_dumpable); |
571 | smp_wmb(); | 575 | smp_wmb(); |
572 | } | 576 | } |
573 | current->uid = new_ruid; | 577 | current->cred->uid = new_ruid; |
574 | return 0; | 578 | return 0; |
575 | } | 579 | } |
576 | 580 | ||
@@ -591,6 +595,7 @@ static int set_user(uid_t new_ruid, int dumpclear) | |||
591 | */ | 595 | */ |
592 | asmlinkage long sys_setreuid(uid_t ruid, uid_t euid) | 596 | asmlinkage long sys_setreuid(uid_t ruid, uid_t euid) |
593 | { | 597 | { |
598 | struct cred *cred = current->cred; | ||
594 | int old_ruid, old_euid, old_suid, new_ruid, new_euid; | 599 | int old_ruid, old_euid, old_suid, new_ruid, new_euid; |
595 | int retval; | 600 | int retval; |
596 | 601 | ||
@@ -598,14 +603,14 @@ asmlinkage long sys_setreuid(uid_t ruid, uid_t euid) | |||
598 | if (retval) | 603 | if (retval) |
599 | return retval; | 604 | return retval; |
600 | 605 | ||
601 | new_ruid = old_ruid = current->uid; | 606 | new_ruid = old_ruid = cred->uid; |
602 | new_euid = old_euid = current->euid; | 607 | new_euid = old_euid = cred->euid; |
603 | old_suid = current->suid; | 608 | old_suid = cred->suid; |
604 | 609 | ||
605 | if (ruid != (uid_t) -1) { | 610 | if (ruid != (uid_t) -1) { |
606 | new_ruid = ruid; | 611 | new_ruid = ruid; |
607 | if ((old_ruid != ruid) && | 612 | if ((old_ruid != ruid) && |
608 | (current->euid != ruid) && | 613 | (cred->euid != ruid) && |
609 | !capable(CAP_SETUID)) | 614 | !capable(CAP_SETUID)) |
610 | return -EPERM; | 615 | return -EPERM; |
611 | } | 616 | } |
@@ -613,8 +618,8 @@ asmlinkage long sys_setreuid(uid_t ruid, uid_t euid) | |||
613 | if (euid != (uid_t) -1) { | 618 | if (euid != (uid_t) -1) { |
614 | new_euid = euid; | 619 | new_euid = euid; |
615 | if ((old_ruid != euid) && | 620 | if ((old_ruid != euid) && |
616 | (current->euid != euid) && | 621 | (cred->euid != euid) && |
617 | (current->suid != euid) && | 622 | (cred->suid != euid) && |
618 | !capable(CAP_SETUID)) | 623 | !capable(CAP_SETUID)) |
619 | return -EPERM; | 624 | return -EPERM; |
620 | } | 625 | } |
@@ -626,11 +631,11 @@ asmlinkage long sys_setreuid(uid_t ruid, uid_t euid) | |||
626 | set_dumpable(current->mm, suid_dumpable); | 631 | set_dumpable(current->mm, suid_dumpable); |
627 | smp_wmb(); | 632 | smp_wmb(); |
628 | } | 633 | } |
629 | current->fsuid = current->euid = new_euid; | 634 | cred->fsuid = cred->euid = new_euid; |
630 | if (ruid != (uid_t) -1 || | 635 | if (ruid != (uid_t) -1 || |
631 | (euid != (uid_t) -1 && euid != old_ruid)) | 636 | (euid != (uid_t) -1 && euid != old_ruid)) |
632 | current->suid = current->euid; | 637 | cred->suid = cred->euid; |
633 | current->fsuid = current->euid; | 638 | cred->fsuid = cred->euid; |
634 | 639 | ||
635 | key_fsuid_changed(current); | 640 | key_fsuid_changed(current); |
636 | proc_id_connector(current, PROC_EVENT_UID); | 641 | proc_id_connector(current, PROC_EVENT_UID); |
@@ -653,7 +658,8 @@ asmlinkage long sys_setreuid(uid_t ruid, uid_t euid) | |||
653 | */ | 658 | */ |
654 | asmlinkage long sys_setuid(uid_t uid) | 659 | asmlinkage long sys_setuid(uid_t uid) |
655 | { | 660 | { |
656 | int old_euid = current->euid; | 661 | struct cred *cred = current->cred; |
662 | int old_euid = cred->euid; | ||
657 | int old_ruid, old_suid, new_suid; | 663 | int old_ruid, old_suid, new_suid; |
658 | int retval; | 664 | int retval; |
659 | 665 | ||
@@ -661,23 +667,23 @@ asmlinkage long sys_setuid(uid_t uid) | |||
661 | if (retval) | 667 | if (retval) |
662 | return retval; | 668 | return retval; |
663 | 669 | ||
664 | old_ruid = current->uid; | 670 | old_ruid = cred->uid; |
665 | old_suid = current->suid; | 671 | old_suid = cred->suid; |
666 | new_suid = old_suid; | 672 | new_suid = old_suid; |
667 | 673 | ||
668 | if (capable(CAP_SETUID)) { | 674 | if (capable(CAP_SETUID)) { |
669 | if (uid != old_ruid && set_user(uid, old_euid != uid) < 0) | 675 | if (uid != old_ruid && set_user(uid, old_euid != uid) < 0) |
670 | return -EAGAIN; | 676 | return -EAGAIN; |
671 | new_suid = uid; | 677 | new_suid = uid; |
672 | } else if ((uid != current->uid) && (uid != new_suid)) | 678 | } else if ((uid != cred->uid) && (uid != new_suid)) |
673 | return -EPERM; | 679 | return -EPERM; |
674 | 680 | ||
675 | if (old_euid != uid) { | 681 | if (old_euid != uid) { |
676 | set_dumpable(current->mm, suid_dumpable); | 682 | set_dumpable(current->mm, suid_dumpable); |
677 | smp_wmb(); | 683 | smp_wmb(); |
678 | } | 684 | } |
679 | current->fsuid = current->euid = uid; | 685 | cred->fsuid = cred->euid = uid; |
680 | current->suid = new_suid; | 686 | cred->suid = new_suid; |
681 | 687 | ||
682 | key_fsuid_changed(current); | 688 | key_fsuid_changed(current); |
683 | proc_id_connector(current, PROC_EVENT_UID); | 689 | proc_id_connector(current, PROC_EVENT_UID); |
@@ -692,9 +698,10 @@ asmlinkage long sys_setuid(uid_t uid) | |||
692 | */ | 698 | */ |
693 | asmlinkage long sys_setresuid(uid_t ruid, uid_t euid, uid_t suid) | 699 | asmlinkage long sys_setresuid(uid_t ruid, uid_t euid, uid_t suid) |
694 | { | 700 | { |
695 | int old_ruid = current->uid; | 701 | struct cred *cred = current->cred; |
696 | int old_euid = current->euid; | 702 | int old_ruid = cred->uid; |
697 | int old_suid = current->suid; | 703 | int old_euid = cred->euid; |
704 | int old_suid = cred->suid; | ||
698 | int retval; | 705 | int retval; |
699 | 706 | ||
700 | retval = security_task_setuid(ruid, euid, suid, LSM_SETID_RES); | 707 | retval = security_task_setuid(ruid, euid, suid, LSM_SETID_RES); |
@@ -702,30 +709,31 @@ asmlinkage long sys_setresuid(uid_t ruid, uid_t euid, uid_t suid) | |||
702 | return retval; | 709 | return retval; |
703 | 710 | ||
704 | if (!capable(CAP_SETUID)) { | 711 | if (!capable(CAP_SETUID)) { |
705 | if ((ruid != (uid_t) -1) && (ruid != current->uid) && | 712 | if ((ruid != (uid_t) -1) && (ruid != cred->uid) && |
706 | (ruid != current->euid) && (ruid != current->suid)) | 713 | (ruid != cred->euid) && (ruid != cred->suid)) |
707 | return -EPERM; | 714 | return -EPERM; |
708 | if ((euid != (uid_t) -1) && (euid != current->uid) && | 715 | if ((euid != (uid_t) -1) && (euid != cred->uid) && |
709 | (euid != current->euid) && (euid != current->suid)) | 716 | (euid != cred->euid) && (euid != cred->suid)) |
710 | return -EPERM; | 717 | return -EPERM; |
711 | if ((suid != (uid_t) -1) && (suid != current->uid) && | 718 | if ((suid != (uid_t) -1) && (suid != cred->uid) && |
712 | (suid != current->euid) && (suid != current->suid)) | 719 | (suid != cred->euid) && (suid != cred->suid)) |
713 | return -EPERM; | 720 | return -EPERM; |
714 | } | 721 | } |
715 | if (ruid != (uid_t) -1) { | 722 | if (ruid != (uid_t) -1) { |
716 | if (ruid != current->uid && set_user(ruid, euid != current->euid) < 0) | 723 | if (ruid != cred->uid && |
724 | set_user(ruid, euid != cred->euid) < 0) | ||
717 | return -EAGAIN; | 725 | return -EAGAIN; |
718 | } | 726 | } |
719 | if (euid != (uid_t) -1) { | 727 | if (euid != (uid_t) -1) { |
720 | if (euid != current->euid) { | 728 | if (euid != cred->euid) { |
721 | set_dumpable(current->mm, suid_dumpable); | 729 | set_dumpable(current->mm, suid_dumpable); |
722 | smp_wmb(); | 730 | smp_wmb(); |
723 | } | 731 | } |
724 | current->euid = euid; | 732 | cred->euid = euid; |
725 | } | 733 | } |
726 | current->fsuid = current->euid; | 734 | cred->fsuid = cred->euid; |
727 | if (suid != (uid_t) -1) | 735 | if (suid != (uid_t) -1) |
728 | current->suid = suid; | 736 | cred->suid = suid; |
729 | 737 | ||
730 | key_fsuid_changed(current); | 738 | key_fsuid_changed(current); |
731 | proc_id_connector(current, PROC_EVENT_UID); | 739 | proc_id_connector(current, PROC_EVENT_UID); |
@@ -735,11 +743,12 @@ asmlinkage long sys_setresuid(uid_t ruid, uid_t euid, uid_t suid) | |||
735 | 743 | ||
736 | asmlinkage long sys_getresuid(uid_t __user *ruid, uid_t __user *euid, uid_t __user *suid) | 744 | asmlinkage long sys_getresuid(uid_t __user *ruid, uid_t __user *euid, uid_t __user *suid) |
737 | { | 745 | { |
746 | struct cred *cred = current->cred; | ||
738 | int retval; | 747 | int retval; |
739 | 748 | ||
740 | if (!(retval = put_user(current->uid, ruid)) && | 749 | if (!(retval = put_user(cred->uid, ruid)) && |
741 | !(retval = put_user(current->euid, euid))) | 750 | !(retval = put_user(cred->euid, euid))) |
742 | retval = put_user(current->suid, suid); | 751 | retval = put_user(cred->suid, suid); |
743 | 752 | ||
744 | return retval; | 753 | return retval; |
745 | } | 754 | } |
@@ -749,6 +758,7 @@ asmlinkage long sys_getresuid(uid_t __user *ruid, uid_t __user *euid, uid_t __us | |||
749 | */ | 758 | */ |
750 | asmlinkage long sys_setresgid(gid_t rgid, gid_t egid, gid_t sgid) | 759 | asmlinkage long sys_setresgid(gid_t rgid, gid_t egid, gid_t sgid) |
751 | { | 760 | { |
761 | struct cred *cred = current->cred; | ||
752 | int retval; | 762 | int retval; |
753 | 763 | ||
754 | retval = security_task_setgid(rgid, egid, sgid, LSM_SETID_RES); | 764 | retval = security_task_setgid(rgid, egid, sgid, LSM_SETID_RES); |
@@ -756,28 +766,28 @@ asmlinkage long sys_setresgid(gid_t rgid, gid_t egid, gid_t sgid) | |||
756 | return retval; | 766 | return retval; |
757 | 767 | ||
758 | if (!capable(CAP_SETGID)) { | 768 | if (!capable(CAP_SETGID)) { |
759 | if ((rgid != (gid_t) -1) && (rgid != current->gid) && | 769 | if ((rgid != (gid_t) -1) && (rgid != cred->gid) && |
760 | (rgid != current->egid) && (rgid != current->sgid)) | 770 | (rgid != cred->egid) && (rgid != cred->sgid)) |
761 | return -EPERM; | 771 | return -EPERM; |
762 | if ((egid != (gid_t) -1) && (egid != current->gid) && | 772 | if ((egid != (gid_t) -1) && (egid != cred->gid) && |
763 | (egid != current->egid) && (egid != current->sgid)) | 773 | (egid != cred->egid) && (egid != cred->sgid)) |
764 | return -EPERM; | 774 | return -EPERM; |
765 | if ((sgid != (gid_t) -1) && (sgid != current->gid) && | 775 | if ((sgid != (gid_t) -1) && (sgid != cred->gid) && |
766 | (sgid != current->egid) && (sgid != current->sgid)) | 776 | (sgid != cred->egid) && (sgid != cred->sgid)) |
767 | return -EPERM; | 777 | return -EPERM; |
768 | } | 778 | } |
769 | if (egid != (gid_t) -1) { | 779 | if (egid != (gid_t) -1) { |
770 | if (egid != current->egid) { | 780 | if (egid != cred->egid) { |
771 | set_dumpable(current->mm, suid_dumpable); | 781 | set_dumpable(current->mm, suid_dumpable); |
772 | smp_wmb(); | 782 | smp_wmb(); |
773 | } | 783 | } |
774 | current->egid = egid; | 784 | cred->egid = egid; |
775 | } | 785 | } |
776 | current->fsgid = current->egid; | 786 | cred->fsgid = cred->egid; |
777 | if (rgid != (gid_t) -1) | 787 | if (rgid != (gid_t) -1) |
778 | current->gid = rgid; | 788 | cred->gid = rgid; |
779 | if (sgid != (gid_t) -1) | 789 | if (sgid != (gid_t) -1) |
780 | current->sgid = sgid; | 790 | cred->sgid = sgid; |
781 | 791 | ||
782 | key_fsgid_changed(current); | 792 | key_fsgid_changed(current); |
783 | proc_id_connector(current, PROC_EVENT_GID); | 793 | proc_id_connector(current, PROC_EVENT_GID); |
@@ -786,11 +796,12 @@ asmlinkage long sys_setresgid(gid_t rgid, gid_t egid, gid_t sgid) | |||
786 | 796 | ||
787 | asmlinkage long sys_getresgid(gid_t __user *rgid, gid_t __user *egid, gid_t __user *sgid) | 797 | asmlinkage long sys_getresgid(gid_t __user *rgid, gid_t __user *egid, gid_t __user *sgid) |
788 | { | 798 | { |
799 | struct cred *cred = current->cred; | ||
789 | int retval; | 800 | int retval; |
790 | 801 | ||
791 | if (!(retval = put_user(current->gid, rgid)) && | 802 | if (!(retval = put_user(cred->gid, rgid)) && |
792 | !(retval = put_user(current->egid, egid))) | 803 | !(retval = put_user(cred->egid, egid))) |
793 | retval = put_user(current->sgid, sgid); | 804 | retval = put_user(cred->sgid, sgid); |
794 | 805 | ||
795 | return retval; | 806 | return retval; |
796 | } | 807 | } |
@@ -804,20 +815,21 @@ asmlinkage long sys_getresgid(gid_t __user *rgid, gid_t __user *egid, gid_t __us | |||
804 | */ | 815 | */ |
805 | asmlinkage long sys_setfsuid(uid_t uid) | 816 | asmlinkage long sys_setfsuid(uid_t uid) |
806 | { | 817 | { |
818 | struct cred *cred = current->cred; | ||
807 | int old_fsuid; | 819 | int old_fsuid; |
808 | 820 | ||
809 | old_fsuid = current->fsuid; | 821 | old_fsuid = cred->fsuid; |
810 | if (security_task_setuid(uid, (uid_t)-1, (uid_t)-1, LSM_SETID_FS)) | 822 | if (security_task_setuid(uid, (uid_t)-1, (uid_t)-1, LSM_SETID_FS)) |
811 | return old_fsuid; | 823 | return old_fsuid; |
812 | 824 | ||
813 | if (uid == current->uid || uid == current->euid || | 825 | if (uid == cred->uid || uid == cred->euid || |
814 | uid == current->suid || uid == current->fsuid || | 826 | uid == cred->suid || uid == cred->fsuid || |
815 | capable(CAP_SETUID)) { | 827 | capable(CAP_SETUID)) { |
816 | if (uid != old_fsuid) { | 828 | if (uid != old_fsuid) { |
817 | set_dumpable(current->mm, suid_dumpable); | 829 | set_dumpable(current->mm, suid_dumpable); |
818 | smp_wmb(); | 830 | smp_wmb(); |
819 | } | 831 | } |
820 | current->fsuid = uid; | 832 | cred->fsuid = uid; |
821 | } | 833 | } |
822 | 834 | ||
823 | key_fsuid_changed(current); | 835 | key_fsuid_changed(current); |
@@ -833,20 +845,21 @@ asmlinkage long sys_setfsuid(uid_t uid) | |||
833 | */ | 845 | */ |
834 | asmlinkage long sys_setfsgid(gid_t gid) | 846 | asmlinkage long sys_setfsgid(gid_t gid) |
835 | { | 847 | { |
848 | struct cred *cred = current->cred; | ||
836 | int old_fsgid; | 849 | int old_fsgid; |
837 | 850 | ||
838 | old_fsgid = current->fsgid; | 851 | old_fsgid = cred->fsgid; |
839 | if (security_task_setgid(gid, (gid_t)-1, (gid_t)-1, LSM_SETID_FS)) | 852 | if (security_task_setgid(gid, (gid_t)-1, (gid_t)-1, LSM_SETID_FS)) |
840 | return old_fsgid; | 853 | return old_fsgid; |
841 | 854 | ||
842 | if (gid == current->gid || gid == current->egid || | 855 | if (gid == cred->gid || gid == cred->egid || |
843 | gid == current->sgid || gid == current->fsgid || | 856 | gid == cred->sgid || gid == cred->fsgid || |
844 | capable(CAP_SETGID)) { | 857 | capable(CAP_SETGID)) { |
845 | if (gid != old_fsgid) { | 858 | if (gid != old_fsgid) { |
846 | set_dumpable(current->mm, suid_dumpable); | 859 | set_dumpable(current->mm, suid_dumpable); |
847 | smp_wmb(); | 860 | smp_wmb(); |
848 | } | 861 | } |
849 | current->fsgid = gid; | 862 | cred->fsgid = gid; |
850 | key_fsgid_changed(current); | 863 | key_fsgid_changed(current); |
851 | proc_id_connector(current, PROC_EVENT_GID); | 864 | proc_id_connector(current, PROC_EVENT_GID); |
852 | } | 865 | } |
@@ -1208,8 +1221,15 @@ int groups_search(struct group_info *group_info, gid_t grp) | |||
1208 | return 0; | 1221 | return 0; |
1209 | } | 1222 | } |
1210 | 1223 | ||
1211 | /* validate and set current->group_info */ | 1224 | /** |
1212 | int set_current_groups(struct group_info *group_info) | 1225 | * set_groups - Change a group subscription in a security record |
1226 | * @sec: The security record to alter | ||
1227 | * @group_info: The group list to impose | ||
1228 | * | ||
1229 | * Validate a group subscription and, if valid, impose it upon a task security | ||
1230 | * record. | ||
1231 | */ | ||
1232 | int set_groups(struct cred *cred, struct group_info *group_info) | ||
1213 | { | 1233 | { |
1214 | int retval; | 1234 | int retval; |
1215 | struct group_info *old_info; | 1235 | struct group_info *old_info; |
@@ -1221,20 +1241,34 @@ int set_current_groups(struct group_info *group_info) | |||
1221 | groups_sort(group_info); | 1241 | groups_sort(group_info); |
1222 | get_group_info(group_info); | 1242 | get_group_info(group_info); |
1223 | 1243 | ||
1224 | task_lock(current); | 1244 | spin_lock(&cred->lock); |
1225 | old_info = current->group_info; | 1245 | old_info = cred->group_info; |
1226 | current->group_info = group_info; | 1246 | cred->group_info = group_info; |
1227 | task_unlock(current); | 1247 | spin_unlock(&cred->lock); |
1228 | 1248 | ||
1229 | put_group_info(old_info); | 1249 | put_group_info(old_info); |
1230 | |||
1231 | return 0; | 1250 | return 0; |
1232 | } | 1251 | } |
1233 | 1252 | ||
1253 | EXPORT_SYMBOL(set_groups); | ||
1254 | |||
1255 | /** | ||
1256 | * set_current_groups - Change current's group subscription | ||
1257 | * @group_info: The group list to impose | ||
1258 | * | ||
1259 | * Validate a group subscription and, if valid, impose it upon current's task | ||
1260 | * security record. | ||
1261 | */ | ||
1262 | int set_current_groups(struct group_info *group_info) | ||
1263 | { | ||
1264 | return set_groups(current->cred, group_info); | ||
1265 | } | ||
1266 | |||
1234 | EXPORT_SYMBOL(set_current_groups); | 1267 | EXPORT_SYMBOL(set_current_groups); |
1235 | 1268 | ||
1236 | asmlinkage long sys_getgroups(int gidsetsize, gid_t __user *grouplist) | 1269 | asmlinkage long sys_getgroups(int gidsetsize, gid_t __user *grouplist) |
1237 | { | 1270 | { |
1271 | struct cred *cred = current->cred; | ||
1238 | int i = 0; | 1272 | int i = 0; |
1239 | 1273 | ||
1240 | /* | 1274 | /* |
@@ -1246,13 +1280,13 @@ asmlinkage long sys_getgroups(int gidsetsize, gid_t __user *grouplist) | |||
1246 | return -EINVAL; | 1280 | return -EINVAL; |
1247 | 1281 | ||
1248 | /* no need to grab task_lock here; it cannot change */ | 1282 | /* no need to grab task_lock here; it cannot change */ |
1249 | i = current->group_info->ngroups; | 1283 | i = cred->group_info->ngroups; |
1250 | if (gidsetsize) { | 1284 | if (gidsetsize) { |
1251 | if (i > gidsetsize) { | 1285 | if (i > gidsetsize) { |
1252 | i = -EINVAL; | 1286 | i = -EINVAL; |
1253 | goto out; | 1287 | goto out; |
1254 | } | 1288 | } |
1255 | if (groups_to_user(grouplist, current->group_info)) { | 1289 | if (groups_to_user(grouplist, cred->group_info)) { |
1256 | i = -EFAULT; | 1290 | i = -EFAULT; |
1257 | goto out; | 1291 | goto out; |
1258 | } | 1292 | } |
@@ -1296,9 +1330,10 @@ asmlinkage long sys_setgroups(int gidsetsize, gid_t __user *grouplist) | |||
1296 | */ | 1330 | */ |
1297 | int in_group_p(gid_t grp) | 1331 | int in_group_p(gid_t grp) |
1298 | { | 1332 | { |
1333 | struct cred *cred = current->cred; | ||
1299 | int retval = 1; | 1334 | int retval = 1; |
1300 | if (grp != current->fsgid) | 1335 | if (grp != cred->fsgid) |
1301 | retval = groups_search(current->group_info, grp); | 1336 | retval = groups_search(cred->group_info, grp); |
1302 | return retval; | 1337 | return retval; |
1303 | } | 1338 | } |
1304 | 1339 | ||
@@ -1306,9 +1341,10 @@ EXPORT_SYMBOL(in_group_p); | |||
1306 | 1341 | ||
1307 | int in_egroup_p(gid_t grp) | 1342 | int in_egroup_p(gid_t grp) |
1308 | { | 1343 | { |
1344 | struct cred *cred = current->cred; | ||
1309 | int retval = 1; | 1345 | int retval = 1; |
1310 | if (grp != current->egid) | 1346 | if (grp != cred->egid) |
1311 | retval = groups_search(current->group_info, grp); | 1347 | retval = groups_search(cred->group_info, grp); |
1312 | return retval; | 1348 | return retval; |
1313 | } | 1349 | } |
1314 | 1350 | ||
@@ -1624,7 +1660,9 @@ asmlinkage long sys_umask(int mask) | |||
1624 | asmlinkage long sys_prctl(int option, unsigned long arg2, unsigned long arg3, | 1660 | asmlinkage long sys_prctl(int option, unsigned long arg2, unsigned long arg3, |
1625 | unsigned long arg4, unsigned long arg5) | 1661 | unsigned long arg4, unsigned long arg5) |
1626 | { | 1662 | { |
1627 | long error = 0; | 1663 | struct task_struct *me = current; |
1664 | unsigned char comm[sizeof(me->comm)]; | ||
1665 | long error; | ||
1628 | 1666 | ||
1629 | if (security_task_prctl(option, arg2, arg3, arg4, arg5, &error)) | 1667 | if (security_task_prctl(option, arg2, arg3, arg4, arg5, &error)) |
1630 | return error; | 1668 | return error; |
@@ -1635,39 +1673,41 @@ asmlinkage long sys_prctl(int option, unsigned long arg2, unsigned long arg3, | |||
1635 | error = -EINVAL; | 1673 | error = -EINVAL; |
1636 | break; | 1674 | break; |
1637 | } | 1675 | } |
1638 | current->pdeath_signal = arg2; | 1676 | me->pdeath_signal = arg2; |
1677 | error = 0; | ||
1639 | break; | 1678 | break; |
1640 | case PR_GET_PDEATHSIG: | 1679 | case PR_GET_PDEATHSIG: |
1641 | error = put_user(current->pdeath_signal, (int __user *)arg2); | 1680 | error = put_user(me->pdeath_signal, (int __user *)arg2); |
1642 | break; | 1681 | break; |
1643 | case PR_GET_DUMPABLE: | 1682 | case PR_GET_DUMPABLE: |
1644 | error = get_dumpable(current->mm); | 1683 | error = get_dumpable(me->mm); |
1645 | break; | 1684 | break; |
1646 | case PR_SET_DUMPABLE: | 1685 | case PR_SET_DUMPABLE: |
1647 | if (arg2 < 0 || arg2 > 1) { | 1686 | if (arg2 < 0 || arg2 > 1) { |
1648 | error = -EINVAL; | 1687 | error = -EINVAL; |
1649 | break; | 1688 | break; |
1650 | } | 1689 | } |
1651 | set_dumpable(current->mm, arg2); | 1690 | set_dumpable(me->mm, arg2); |
1691 | error = 0; | ||
1652 | break; | 1692 | break; |
1653 | 1693 | ||
1654 | case PR_SET_UNALIGN: | 1694 | case PR_SET_UNALIGN: |
1655 | error = SET_UNALIGN_CTL(current, arg2); | 1695 | error = SET_UNALIGN_CTL(me, arg2); |
1656 | break; | 1696 | break; |
1657 | case PR_GET_UNALIGN: | 1697 | case PR_GET_UNALIGN: |
1658 | error = GET_UNALIGN_CTL(current, arg2); | 1698 | error = GET_UNALIGN_CTL(me, arg2); |
1659 | break; | 1699 | break; |
1660 | case PR_SET_FPEMU: | 1700 | case PR_SET_FPEMU: |
1661 | error = SET_FPEMU_CTL(current, arg2); | 1701 | error = SET_FPEMU_CTL(me, arg2); |
1662 | break; | 1702 | break; |
1663 | case PR_GET_FPEMU: | 1703 | case PR_GET_FPEMU: |
1664 | error = GET_FPEMU_CTL(current, arg2); | 1704 | error = GET_FPEMU_CTL(me, arg2); |
1665 | break; | 1705 | break; |
1666 | case PR_SET_FPEXC: | 1706 | case PR_SET_FPEXC: |
1667 | error = SET_FPEXC_CTL(current, arg2); | 1707 | error = SET_FPEXC_CTL(me, arg2); |
1668 | break; | 1708 | break; |
1669 | case PR_GET_FPEXC: | 1709 | case PR_GET_FPEXC: |
1670 | error = GET_FPEXC_CTL(current, arg2); | 1710 | error = GET_FPEXC_CTL(me, arg2); |
1671 | break; | 1711 | break; |
1672 | case PR_GET_TIMING: | 1712 | case PR_GET_TIMING: |
1673 | error = PR_TIMING_STATISTICAL; | 1713 | error = PR_TIMING_STATISTICAL; |
@@ -1675,33 +1715,28 @@ asmlinkage long sys_prctl(int option, unsigned long arg2, unsigned long arg3, | |||
1675 | case PR_SET_TIMING: | 1715 | case PR_SET_TIMING: |
1676 | if (arg2 != PR_TIMING_STATISTICAL) | 1716 | if (arg2 != PR_TIMING_STATISTICAL) |
1677 | error = -EINVAL; | 1717 | error = -EINVAL; |
1718 | else | ||
1719 | error = 0; | ||
1678 | break; | 1720 | break; |
1679 | 1721 | ||
1680 | case PR_SET_NAME: { | 1722 | case PR_SET_NAME: |
1681 | struct task_struct *me = current; | 1723 | comm[sizeof(me->comm)-1] = 0; |
1682 | unsigned char ncomm[sizeof(me->comm)]; | 1724 | if (strncpy_from_user(comm, (char __user *)arg2, |
1683 | 1725 | 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; | 1726 | return -EFAULT; |
1688 | set_task_comm(me, ncomm); | 1727 | set_task_comm(me, comm); |
1689 | return 0; | 1728 | return 0; |
1690 | } | 1729 | case PR_GET_NAME: |
1691 | case PR_GET_NAME: { | 1730 | get_task_comm(comm, me); |
1692 | struct task_struct *me = current; | 1731 | if (copy_to_user((char __user *)arg2, comm, |
1693 | unsigned char tcomm[sizeof(me->comm)]; | 1732 | sizeof(comm))) |
1694 | |||
1695 | get_task_comm(tcomm, me); | ||
1696 | if (copy_to_user((char __user *)arg2, tcomm, sizeof(tcomm))) | ||
1697 | return -EFAULT; | 1733 | return -EFAULT; |
1698 | return 0; | 1734 | return 0; |
1699 | } | ||
1700 | case PR_GET_ENDIAN: | 1735 | case PR_GET_ENDIAN: |
1701 | error = GET_ENDIAN(current, arg2); | 1736 | error = GET_ENDIAN(me, arg2); |
1702 | break; | 1737 | break; |
1703 | case PR_SET_ENDIAN: | 1738 | case PR_SET_ENDIAN: |
1704 | error = SET_ENDIAN(current, arg2); | 1739 | error = SET_ENDIAN(me, arg2); |
1705 | break; | 1740 | break; |
1706 | 1741 | ||
1707 | case PR_GET_SECCOMP: | 1742 | case PR_GET_SECCOMP: |
@@ -1725,6 +1760,7 @@ asmlinkage long sys_prctl(int option, unsigned long arg2, unsigned long arg3, | |||
1725 | current->default_timer_slack_ns; | 1760 | current->default_timer_slack_ns; |
1726 | else | 1761 | else |
1727 | current->timer_slack_ns = arg2; | 1762 | current->timer_slack_ns = arg2; |
1763 | error = 0; | ||
1728 | break; | 1764 | break; |
1729 | default: | 1765 | default: |
1730 | error = -EINVAL; | 1766 | error = -EINVAL; |