aboutsummaryrefslogtreecommitdiffstats
path: root/security/commoncap.c
diff options
context:
space:
mode:
Diffstat (limited to 'security/commoncap.c')
-rw-r--r--security/commoncap.c78
1 files changed, 63 insertions, 15 deletions
diff --git a/security/commoncap.c b/security/commoncap.c
index 49c57fd60aea..f20e984ccfb4 100644
--- a/security/commoncap.c
+++ b/security/commoncap.c
@@ -27,6 +27,7 @@
27#include <linux/sched.h> 27#include <linux/sched.h>
28#include <linux/prctl.h> 28#include <linux/prctl.h>
29#include <linux/securebits.h> 29#include <linux/securebits.h>
30#include <linux/user_namespace.h>
30 31
31/* 32/*
32 * If a non-root user executes a setuid-root binary in 33 * If a non-root user executes a setuid-root binary in
@@ -67,6 +68,7 @@ EXPORT_SYMBOL(cap_netlink_recv);
67 * cap_capable - Determine whether a task has a particular effective capability 68 * cap_capable - Determine whether a task has a particular effective capability
68 * @tsk: The task to query 69 * @tsk: The task to query
69 * @cred: The credentials to use 70 * @cred: The credentials to use
71 * @ns: The user namespace in which we need the capability
70 * @cap: The capability to check for 72 * @cap: The capability to check for
71 * @audit: Whether to write an audit message or not 73 * @audit: Whether to write an audit message or not
72 * 74 *
@@ -78,10 +80,30 @@ EXPORT_SYMBOL(cap_netlink_recv);
78 * cap_has_capability() returns 0 when a task has a capability, but the 80 * cap_has_capability() returns 0 when a task has a capability, but the
79 * kernel's capable() and has_capability() returns 1 for this case. 81 * kernel's capable() and has_capability() returns 1 for this case.
80 */ 82 */
81int cap_capable(struct task_struct *tsk, const struct cred *cred, int cap, 83int cap_capable(struct task_struct *tsk, const struct cred *cred,
82 int audit) 84 struct user_namespace *targ_ns, int cap, int audit)
83{ 85{
84 return cap_raised(cred->cap_effective, cap) ? 0 : -EPERM; 86 for (;;) {
87 /* The creator of the user namespace has all caps. */
88 if (targ_ns != &init_user_ns && targ_ns->creator == cred->user)
89 return 0;
90
91 /* Do we have the necessary capabilities? */
92 if (targ_ns == cred->user->user_ns)
93 return cap_raised(cred->cap_effective, cap) ? 0 : -EPERM;
94
95 /* Have we tried all of the parent namespaces? */
96 if (targ_ns == &init_user_ns)
97 return -EPERM;
98
99 /*
100 *If you have a capability in a parent user ns, then you have
101 * it over all children user namespaces as well.
102 */
103 targ_ns = targ_ns->creator->user_ns;
104 }
105
106 /* We never get here */
85} 107}
86 108
87/** 109/**
@@ -105,18 +127,30 @@ int cap_settime(const struct timespec *ts, const struct timezone *tz)
105 * @child: The process to be accessed 127 * @child: The process to be accessed
106 * @mode: The mode of attachment. 128 * @mode: The mode of attachment.
107 * 129 *
130 * If we are in the same or an ancestor user_ns and have all the target
131 * task's capabilities, then ptrace access is allowed.
132 * If we have the ptrace capability to the target user_ns, then ptrace
133 * access is allowed.
134 * Else denied.
135 *
108 * Determine whether a process may access another, returning 0 if permission 136 * Determine whether a process may access another, returning 0 if permission
109 * granted, -ve if denied. 137 * granted, -ve if denied.
110 */ 138 */
111int cap_ptrace_access_check(struct task_struct *child, unsigned int mode) 139int cap_ptrace_access_check(struct task_struct *child, unsigned int mode)
112{ 140{
113 int ret = 0; 141 int ret = 0;
142 const struct cred *cred, *child_cred;
114 143
115 rcu_read_lock(); 144 rcu_read_lock();
116 if (!cap_issubset(__task_cred(child)->cap_permitted, 145 cred = current_cred();
117 current_cred()->cap_permitted) && 146 child_cred = __task_cred(child);
118 !capable(CAP_SYS_PTRACE)) 147 if (cred->user->user_ns == child_cred->user->user_ns &&
119 ret = -EPERM; 148 cap_issubset(child_cred->cap_permitted, cred->cap_permitted))
149 goto out;
150 if (ns_capable(child_cred->user->user_ns, CAP_SYS_PTRACE))
151 goto out;
152 ret = -EPERM;
153out:
120 rcu_read_unlock(); 154 rcu_read_unlock();
121 return ret; 155 return ret;
122} 156}
@@ -125,18 +159,30 @@ int cap_ptrace_access_check(struct task_struct *child, unsigned int mode)
125 * cap_ptrace_traceme - Determine whether another process may trace the current 159 * cap_ptrace_traceme - Determine whether another process may trace the current
126 * @parent: The task proposed to be the tracer 160 * @parent: The task proposed to be the tracer
127 * 161 *
162 * If parent is in the same or an ancestor user_ns and has all current's
163 * capabilities, then ptrace access is allowed.
164 * If parent has the ptrace capability to current's user_ns, then ptrace
165 * access is allowed.
166 * Else denied.
167 *
128 * Determine whether the nominated task is permitted to trace the current 168 * Determine whether the nominated task is permitted to trace the current
129 * process, returning 0 if permission is granted, -ve if denied. 169 * process, returning 0 if permission is granted, -ve if denied.
130 */ 170 */
131int cap_ptrace_traceme(struct task_struct *parent) 171int cap_ptrace_traceme(struct task_struct *parent)
132{ 172{
133 int ret = 0; 173 int ret = 0;
174 const struct cred *cred, *child_cred;
134 175
135 rcu_read_lock(); 176 rcu_read_lock();
136 if (!cap_issubset(current_cred()->cap_permitted, 177 cred = __task_cred(parent);
137 __task_cred(parent)->cap_permitted) && 178 child_cred = current_cred();
138 !has_capability(parent, CAP_SYS_PTRACE)) 179 if (cred->user->user_ns == child_cred->user->user_ns &&
139 ret = -EPERM; 180 cap_issubset(child_cred->cap_permitted, cred->cap_permitted))
181 goto out;
182 if (has_ns_capability(parent, child_cred->user->user_ns, CAP_SYS_PTRACE))
183 goto out;
184 ret = -EPERM;
185out:
140 rcu_read_unlock(); 186 rcu_read_unlock();
141 return ret; 187 return ret;
142} 188}
@@ -176,7 +222,8 @@ static inline int cap_inh_is_capped(void)
176 /* they are so limited unless the current task has the CAP_SETPCAP 222 /* they are so limited unless the current task has the CAP_SETPCAP
177 * capability 223 * capability
178 */ 224 */
179 if (cap_capable(current, current_cred(), CAP_SETPCAP, 225 if (cap_capable(current, current_cred(),
226 current_cred()->user->user_ns, CAP_SETPCAP,
180 SECURITY_CAP_AUDIT) == 0) 227 SECURITY_CAP_AUDIT) == 0)
181 return 0; 228 return 0;
182 return 1; 229 return 1;
@@ -828,7 +875,8 @@ int cap_task_prctl(int option, unsigned long arg2, unsigned long arg3,
828 & (new->securebits ^ arg2)) /*[1]*/ 875 & (new->securebits ^ arg2)) /*[1]*/
829 || ((new->securebits & SECURE_ALL_LOCKS & ~arg2)) /*[2]*/ 876 || ((new->securebits & SECURE_ALL_LOCKS & ~arg2)) /*[2]*/
830 || (arg2 & ~(SECURE_ALL_LOCKS | SECURE_ALL_BITS)) /*[3]*/ 877 || (arg2 & ~(SECURE_ALL_LOCKS | SECURE_ALL_BITS)) /*[3]*/
831 || (cap_capable(current, current_cred(), CAP_SETPCAP, 878 || (cap_capable(current, current_cred(),
879 current_cred()->user->user_ns, CAP_SETPCAP,
832 SECURITY_CAP_AUDIT) != 0) /*[4]*/ 880 SECURITY_CAP_AUDIT) != 0) /*[4]*/
833 /* 881 /*
834 * [1] no changing of bits that are locked 882 * [1] no changing of bits that are locked
@@ -893,7 +941,7 @@ int cap_vm_enough_memory(struct mm_struct *mm, long pages)
893{ 941{
894 int cap_sys_admin = 0; 942 int cap_sys_admin = 0;
895 943
896 if (cap_capable(current, current_cred(), CAP_SYS_ADMIN, 944 if (cap_capable(current, current_cred(), &init_user_ns, CAP_SYS_ADMIN,
897 SECURITY_CAP_NOAUDIT) == 0) 945 SECURITY_CAP_NOAUDIT) == 0)
898 cap_sys_admin = 1; 946 cap_sys_admin = 1;
899 return __vm_enough_memory(mm, pages, cap_sys_admin); 947 return __vm_enough_memory(mm, pages, cap_sys_admin);
@@ -920,7 +968,7 @@ int cap_file_mmap(struct file *file, unsigned long reqprot,
920 int ret = 0; 968 int ret = 0;
921 969
922 if (addr < dac_mmap_min_addr) { 970 if (addr < dac_mmap_min_addr) {
923 ret = cap_capable(current, current_cred(), CAP_SYS_RAWIO, 971 ret = cap_capable(current, current_cred(), &init_user_ns, CAP_SYS_RAWIO,
924 SECURITY_CAP_AUDIT); 972 SECURITY_CAP_AUDIT);
925 /* set PF_SUPERPRIV if it turns out we allow the low mmap */ 973 /* set PF_SUPERPRIV if it turns out we allow the low mmap */
926 if (ret == 0) 974 if (ret == 0)