diff options
Diffstat (limited to 'kernel/sys.c')
-rw-r--r-- | kernel/sys.c | 110 |
1 files changed, 72 insertions, 38 deletions
diff --git a/kernel/sys.c b/kernel/sys.c index f006632c2ba7..da24bc1292db 100644 --- a/kernel/sys.c +++ b/kernel/sys.c | |||
@@ -525,7 +525,7 @@ asmlinkage long sys_setregid(gid_t rgid, gid_t egid) | |||
525 | } | 525 | } |
526 | if (new_egid != old_egid) | 526 | if (new_egid != old_egid) |
527 | { | 527 | { |
528 | current->mm->dumpable = 0; | 528 | current->mm->dumpable = suid_dumpable; |
529 | smp_wmb(); | 529 | smp_wmb(); |
530 | } | 530 | } |
531 | if (rgid != (gid_t) -1 || | 531 | if (rgid != (gid_t) -1 || |
@@ -556,7 +556,7 @@ asmlinkage long sys_setgid(gid_t gid) | |||
556 | { | 556 | { |
557 | if(old_egid != gid) | 557 | if(old_egid != gid) |
558 | { | 558 | { |
559 | current->mm->dumpable=0; | 559 | current->mm->dumpable = suid_dumpable; |
560 | smp_wmb(); | 560 | smp_wmb(); |
561 | } | 561 | } |
562 | current->gid = current->egid = current->sgid = current->fsgid = gid; | 562 | current->gid = current->egid = current->sgid = current->fsgid = gid; |
@@ -565,7 +565,7 @@ asmlinkage long sys_setgid(gid_t gid) | |||
565 | { | 565 | { |
566 | if(old_egid != gid) | 566 | if(old_egid != gid) |
567 | { | 567 | { |
568 | current->mm->dumpable=0; | 568 | current->mm->dumpable = suid_dumpable; |
569 | smp_wmb(); | 569 | smp_wmb(); |
570 | } | 570 | } |
571 | current->egid = current->fsgid = gid; | 571 | current->egid = current->fsgid = gid; |
@@ -596,7 +596,7 @@ static int set_user(uid_t new_ruid, int dumpclear) | |||
596 | 596 | ||
597 | if(dumpclear) | 597 | if(dumpclear) |
598 | { | 598 | { |
599 | current->mm->dumpable = 0; | 599 | current->mm->dumpable = suid_dumpable; |
600 | smp_wmb(); | 600 | smp_wmb(); |
601 | } | 601 | } |
602 | current->uid = new_ruid; | 602 | current->uid = new_ruid; |
@@ -653,7 +653,7 @@ asmlinkage long sys_setreuid(uid_t ruid, uid_t euid) | |||
653 | 653 | ||
654 | if (new_euid != old_euid) | 654 | if (new_euid != old_euid) |
655 | { | 655 | { |
656 | current->mm->dumpable=0; | 656 | current->mm->dumpable = suid_dumpable; |
657 | smp_wmb(); | 657 | smp_wmb(); |
658 | } | 658 | } |
659 | current->fsuid = current->euid = new_euid; | 659 | current->fsuid = current->euid = new_euid; |
@@ -703,7 +703,7 @@ asmlinkage long sys_setuid(uid_t uid) | |||
703 | 703 | ||
704 | if (old_euid != uid) | 704 | if (old_euid != uid) |
705 | { | 705 | { |
706 | current->mm->dumpable = 0; | 706 | current->mm->dumpable = suid_dumpable; |
707 | smp_wmb(); | 707 | smp_wmb(); |
708 | } | 708 | } |
709 | current->fsuid = current->euid = uid; | 709 | current->fsuid = current->euid = uid; |
@@ -748,7 +748,7 @@ asmlinkage long sys_setresuid(uid_t ruid, uid_t euid, uid_t suid) | |||
748 | if (euid != (uid_t) -1) { | 748 | if (euid != (uid_t) -1) { |
749 | if (euid != current->euid) | 749 | if (euid != current->euid) |
750 | { | 750 | { |
751 | current->mm->dumpable = 0; | 751 | current->mm->dumpable = suid_dumpable; |
752 | smp_wmb(); | 752 | smp_wmb(); |
753 | } | 753 | } |
754 | current->euid = euid; | 754 | current->euid = euid; |
@@ -798,7 +798,7 @@ asmlinkage long sys_setresgid(gid_t rgid, gid_t egid, gid_t sgid) | |||
798 | if (egid != (gid_t) -1) { | 798 | if (egid != (gid_t) -1) { |
799 | if (egid != current->egid) | 799 | if (egid != current->egid) |
800 | { | 800 | { |
801 | current->mm->dumpable = 0; | 801 | current->mm->dumpable = suid_dumpable; |
802 | smp_wmb(); | 802 | smp_wmb(); |
803 | } | 803 | } |
804 | current->egid = egid; | 804 | current->egid = egid; |
@@ -845,7 +845,7 @@ asmlinkage long sys_setfsuid(uid_t uid) | |||
845 | { | 845 | { |
846 | if (uid != old_fsuid) | 846 | if (uid != old_fsuid) |
847 | { | 847 | { |
848 | current->mm->dumpable = 0; | 848 | current->mm->dumpable = suid_dumpable; |
849 | smp_wmb(); | 849 | smp_wmb(); |
850 | } | 850 | } |
851 | current->fsuid = uid; | 851 | current->fsuid = uid; |
@@ -875,7 +875,7 @@ asmlinkage long sys_setfsgid(gid_t gid) | |||
875 | { | 875 | { |
876 | if (gid != old_fsgid) | 876 | if (gid != old_fsgid) |
877 | { | 877 | { |
878 | current->mm->dumpable = 0; | 878 | current->mm->dumpable = suid_dumpable; |
879 | smp_wmb(); | 879 | smp_wmb(); |
880 | } | 880 | } |
881 | current->fsgid = gid; | 881 | current->fsgid = gid; |
@@ -894,35 +894,69 @@ asmlinkage long sys_times(struct tms __user * tbuf) | |||
894 | */ | 894 | */ |
895 | if (tbuf) { | 895 | if (tbuf) { |
896 | struct tms tmp; | 896 | struct tms tmp; |
897 | struct task_struct *tsk = current; | ||
898 | struct task_struct *t; | ||
899 | cputime_t utime, stime, cutime, cstime; | 897 | cputime_t utime, stime, cutime, cstime; |
900 | 898 | ||
901 | read_lock(&tasklist_lock); | 899 | #ifdef CONFIG_SMP |
902 | utime = tsk->signal->utime; | 900 | if (thread_group_empty(current)) { |
903 | stime = tsk->signal->stime; | 901 | /* |
904 | t = tsk; | 902 | * Single thread case without the use of any locks. |
905 | do { | 903 | * |
906 | utime = cputime_add(utime, t->utime); | 904 | * We may race with release_task if two threads are |
907 | stime = cputime_add(stime, t->stime); | 905 | * executing. However, release task first adds up the |
908 | t = next_thread(t); | 906 | * counters (__exit_signal) before removing the task |
909 | } while (t != tsk); | 907 | * from the process tasklist (__unhash_process). |
910 | 908 | * __exit_signal also acquires and releases the | |
911 | /* | 909 | * siglock which results in the proper memory ordering |
912 | * While we have tasklist_lock read-locked, no dying thread | 910 | * so that the list modifications are always visible |
913 | * can be updating current->signal->[us]time. Instead, | 911 | * after the counters have been updated. |
914 | * we got their counts included in the live thread loop. | 912 | * |
915 | * However, another thread can come in right now and | 913 | * If the counters have been updated by the second thread |
916 | * do a wait call that updates current->signal->c[us]time. | 914 | * but the thread has not yet been removed from the list |
917 | * To make sure we always see that pair updated atomically, | 915 | * then the other branch will be executing which will |
918 | * we take the siglock around fetching them. | 916 | * block on tasklist_lock until the exit handling of the |
919 | */ | 917 | * other task is finished. |
920 | spin_lock_irq(&tsk->sighand->siglock); | 918 | * |
921 | cutime = tsk->signal->cutime; | 919 | * This also implies that the sighand->siglock cannot |
922 | cstime = tsk->signal->cstime; | 920 | * be held by another processor. So we can also |
923 | spin_unlock_irq(&tsk->sighand->siglock); | 921 | * skip acquiring that lock. |
924 | read_unlock(&tasklist_lock); | 922 | */ |
923 | utime = cputime_add(current->signal->utime, current->utime); | ||
924 | stime = cputime_add(current->signal->utime, current->stime); | ||
925 | cutime = current->signal->cutime; | ||
926 | cstime = current->signal->cstime; | ||
927 | } else | ||
928 | #endif | ||
929 | { | ||
930 | |||
931 | /* Process with multiple threads */ | ||
932 | struct task_struct *tsk = current; | ||
933 | struct task_struct *t; | ||
925 | 934 | ||
935 | read_lock(&tasklist_lock); | ||
936 | utime = tsk->signal->utime; | ||
937 | stime = tsk->signal->stime; | ||
938 | t = tsk; | ||
939 | do { | ||
940 | utime = cputime_add(utime, t->utime); | ||
941 | stime = cputime_add(stime, t->stime); | ||
942 | t = next_thread(t); | ||
943 | } while (t != tsk); | ||
944 | |||
945 | /* | ||
946 | * While we have tasklist_lock read-locked, no dying thread | ||
947 | * can be updating current->signal->[us]time. Instead, | ||
948 | * we got their counts included in the live thread loop. | ||
949 | * However, another thread can come in right now and | ||
950 | * do a wait call that updates current->signal->c[us]time. | ||
951 | * To make sure we always see that pair updated atomically, | ||
952 | * we take the siglock around fetching them. | ||
953 | */ | ||
954 | spin_lock_irq(&tsk->sighand->siglock); | ||
955 | cutime = tsk->signal->cutime; | ||
956 | cstime = tsk->signal->cstime; | ||
957 | spin_unlock_irq(&tsk->sighand->siglock); | ||
958 | read_unlock(&tasklist_lock); | ||
959 | } | ||
926 | tmp.tms_utime = cputime_to_clock_t(utime); | 960 | tmp.tms_utime = cputime_to_clock_t(utime); |
927 | tmp.tms_stime = cputime_to_clock_t(stime); | 961 | tmp.tms_stime = cputime_to_clock_t(stime); |
928 | tmp.tms_cutime = cputime_to_clock_t(cutime); | 962 | tmp.tms_cutime = cputime_to_clock_t(cutime); |
@@ -1225,7 +1259,7 @@ static void groups_sort(struct group_info *group_info) | |||
1225 | } | 1259 | } |
1226 | 1260 | ||
1227 | /* a simple bsearch */ | 1261 | /* a simple bsearch */ |
1228 | static int groups_search(struct group_info *group_info, gid_t grp) | 1262 | int groups_search(struct group_info *group_info, gid_t grp) |
1229 | { | 1263 | { |
1230 | int left, right; | 1264 | int left, right; |
1231 | 1265 | ||
@@ -1652,7 +1686,7 @@ asmlinkage long sys_prctl(int option, unsigned long arg2, unsigned long arg3, | |||
1652 | error = 1; | 1686 | error = 1; |
1653 | break; | 1687 | break; |
1654 | case PR_SET_DUMPABLE: | 1688 | case PR_SET_DUMPABLE: |
1655 | if (arg2 != 0 && arg2 != 1) { | 1689 | if (arg2 < 0 || arg2 > 2) { |
1656 | error = -EINVAL; | 1690 | error = -EINVAL; |
1657 | break; | 1691 | break; |
1658 | } | 1692 | } |