diff options
| -rw-r--r-- | security/commoncap.c | 72 |
1 files changed, 30 insertions, 42 deletions
diff --git a/security/commoncap.c b/security/commoncap.c index b9d613e0ef14..9fe46e22c7f2 100644 --- a/security/commoncap.c +++ b/security/commoncap.c | |||
| @@ -822,15 +822,20 @@ int cap_task_setnice(struct task_struct *p, int nice) | |||
| 822 | * Implement PR_CAPBSET_DROP. Attempt to remove the specified capability from | 822 | * Implement PR_CAPBSET_DROP. Attempt to remove the specified capability from |
| 823 | * the current task's bounding set. Returns 0 on success, -ve on error. | 823 | * the current task's bounding set. Returns 0 on success, -ve on error. |
| 824 | */ | 824 | */ |
| 825 | static long cap_prctl_drop(struct cred *new, unsigned long cap) | 825 | static int cap_prctl_drop(unsigned long cap) |
| 826 | { | 826 | { |
| 827 | struct cred *new; | ||
| 828 | |||
| 827 | if (!ns_capable(current_user_ns(), CAP_SETPCAP)) | 829 | if (!ns_capable(current_user_ns(), CAP_SETPCAP)) |
| 828 | return -EPERM; | 830 | return -EPERM; |
| 829 | if (!cap_valid(cap)) | 831 | if (!cap_valid(cap)) |
| 830 | return -EINVAL; | 832 | return -EINVAL; |
| 831 | 833 | ||
| 834 | new = prepare_creds(); | ||
| 835 | if (!new) | ||
| 836 | return -ENOMEM; | ||
| 832 | cap_lower(new->cap_bset, cap); | 837 | cap_lower(new->cap_bset, cap); |
| 833 | return 0; | 838 | return commit_creds(new); |
| 834 | } | 839 | } |
| 835 | 840 | ||
| 836 | /** | 841 | /** |
| @@ -848,26 +853,17 @@ static long cap_prctl_drop(struct cred *new, unsigned long cap) | |||
| 848 | int cap_task_prctl(int option, unsigned long arg2, unsigned long arg3, | 853 | int cap_task_prctl(int option, unsigned long arg2, unsigned long arg3, |
| 849 | unsigned long arg4, unsigned long arg5) | 854 | unsigned long arg4, unsigned long arg5) |
| 850 | { | 855 | { |
| 856 | const struct cred *old = current_cred(); | ||
| 851 | struct cred *new; | 857 | struct cred *new; |
| 852 | long error = 0; | ||
| 853 | |||
| 854 | new = prepare_creds(); | ||
| 855 | if (!new) | ||
| 856 | return -ENOMEM; | ||
| 857 | 858 | ||
| 858 | switch (option) { | 859 | switch (option) { |
| 859 | case PR_CAPBSET_READ: | 860 | case PR_CAPBSET_READ: |
| 860 | error = -EINVAL; | ||
| 861 | if (!cap_valid(arg2)) | 861 | if (!cap_valid(arg2)) |
| 862 | goto error; | 862 | return -EINVAL; |
| 863 | error = !!cap_raised(new->cap_bset, arg2); | 863 | return !!cap_raised(old->cap_bset, arg2); |
| 864 | goto no_change; | ||
| 865 | 864 | ||
| 866 | case PR_CAPBSET_DROP: | 865 | case PR_CAPBSET_DROP: |
| 867 | error = cap_prctl_drop(new, arg2); | 866 | return cap_prctl_drop(arg2); |
| 868 | if (error < 0) | ||
| 869 | goto error; | ||
| 870 | goto changed; | ||
| 871 | 867 | ||
| 872 | /* | 868 | /* |
| 873 | * The next four prctl's remain to assist with transitioning a | 869 | * The next four prctl's remain to assist with transitioning a |
| @@ -889,10 +885,9 @@ int cap_task_prctl(int option, unsigned long arg2, unsigned long arg3, | |||
| 889 | * capability-based-privilege environment. | 885 | * capability-based-privilege environment. |
| 890 | */ | 886 | */ |
| 891 | case PR_SET_SECUREBITS: | 887 | case PR_SET_SECUREBITS: |
| 892 | error = -EPERM; | 888 | if ((((old->securebits & SECURE_ALL_LOCKS) >> 1) |
| 893 | if ((((new->securebits & SECURE_ALL_LOCKS) >> 1) | 889 | & (old->securebits ^ arg2)) /*[1]*/ |
| 894 | & (new->securebits ^ arg2)) /*[1]*/ | 890 | || ((old->securebits & SECURE_ALL_LOCKS & ~arg2)) /*[2]*/ |
| 895 | || ((new->securebits & SECURE_ALL_LOCKS & ~arg2)) /*[2]*/ | ||
| 896 | || (arg2 & ~(SECURE_ALL_LOCKS | SECURE_ALL_BITS)) /*[3]*/ | 891 | || (arg2 & ~(SECURE_ALL_LOCKS | SECURE_ALL_BITS)) /*[3]*/ |
| 897 | || (cap_capable(current_cred(), | 892 | || (cap_capable(current_cred(), |
| 898 | current_cred()->user_ns, CAP_SETPCAP, | 893 | current_cred()->user_ns, CAP_SETPCAP, |
| @@ -906,46 +901,39 @@ int cap_task_prctl(int option, unsigned long arg2, unsigned long arg3, | |||
| 906 | */ | 901 | */ |
| 907 | ) | 902 | ) |
| 908 | /* cannot change a locked bit */ | 903 | /* cannot change a locked bit */ |
| 909 | goto error; | 904 | return -EPERM; |
| 905 | |||
| 906 | new = prepare_creds(); | ||
| 907 | if (!new) | ||
| 908 | return -ENOMEM; | ||
| 910 | new->securebits = arg2; | 909 | new->securebits = arg2; |
| 911 | goto changed; | 910 | return commit_creds(new); |
| 912 | 911 | ||
| 913 | case PR_GET_SECUREBITS: | 912 | case PR_GET_SECUREBITS: |
| 914 | error = new->securebits; | 913 | return old->securebits; |
| 915 | goto no_change; | ||
| 916 | 914 | ||
| 917 | case PR_GET_KEEPCAPS: | 915 | case PR_GET_KEEPCAPS: |
| 918 | if (issecure(SECURE_KEEP_CAPS)) | 916 | return !!issecure(SECURE_KEEP_CAPS); |
| 919 | error = 1; | ||
| 920 | goto no_change; | ||
| 921 | 917 | ||
| 922 | case PR_SET_KEEPCAPS: | 918 | case PR_SET_KEEPCAPS: |
| 923 | error = -EINVAL; | ||
| 924 | if (arg2 > 1) /* Note, we rely on arg2 being unsigned here */ | 919 | if (arg2 > 1) /* Note, we rely on arg2 being unsigned here */ |
| 925 | goto error; | 920 | return -EINVAL; |
| 926 | error = -EPERM; | ||
| 927 | if (issecure(SECURE_KEEP_CAPS_LOCKED)) | 921 | if (issecure(SECURE_KEEP_CAPS_LOCKED)) |
| 928 | goto error; | 922 | return -EPERM; |
| 923 | |||
| 924 | new = prepare_creds(); | ||
| 925 | if (!new) | ||
| 926 | return -ENOMEM; | ||
| 929 | if (arg2) | 927 | if (arg2) |
| 930 | new->securebits |= issecure_mask(SECURE_KEEP_CAPS); | 928 | new->securebits |= issecure_mask(SECURE_KEEP_CAPS); |
| 931 | else | 929 | else |
| 932 | new->securebits &= ~issecure_mask(SECURE_KEEP_CAPS); | 930 | new->securebits &= ~issecure_mask(SECURE_KEEP_CAPS); |
| 933 | goto changed; | 931 | return commit_creds(new); |
| 934 | 932 | ||
| 935 | default: | 933 | default: |
| 936 | /* No functionality available - continue with default */ | 934 | /* No functionality available - continue with default */ |
| 937 | error = -ENOSYS; | 935 | return -ENOSYS; |
| 938 | goto error; | ||
| 939 | } | 936 | } |
| 940 | |||
| 941 | /* Functionality provided */ | ||
| 942 | changed: | ||
| 943 | return commit_creds(new); | ||
| 944 | |||
| 945 | no_change: | ||
| 946 | error: | ||
| 947 | abort_creds(new); | ||
| 948 | return error; | ||
| 949 | } | 937 | } |
| 950 | 938 | ||
| 951 | /** | 939 | /** |
