aboutsummaryrefslogtreecommitdiffstats
path: root/security
diff options
context:
space:
mode:
authorEric Paris <eparis@redhat.com>2012-01-03 12:25:14 -0500
committerEric Paris <eparis@redhat.com>2012-01-05 18:52:53 -0500
commit6a9de49115d5ff9871d953af1a5c8249e1585731 (patch)
treeeee3700ccc2ce26c566bfe99129e646fac9f983e /security
parent2653812e14f4e16688ec8247d7fd290bdbbc4747 (diff)
capabilities: remove the task from capable LSM hook entirely
The capabilities framework is based around credentials, not necessarily the current task. Yet we still passed the current task down into LSMs from the security_capable() LSM hook as if it was a meaningful portion of the security decision. This patch removes the 'generic' passing of current and instead forces individual LSMs to use current explicitly if they think it is appropriate. In our case those LSMs are SELinux and AppArmor. I believe the AppArmor use of current is incorrect, but that is wholely unrelated to this patch. This patch does not change what AppArmor does, it just makes it clear in the AppArmor code that it is doing it. The SELinux code still uses current in it's audit message, which may also be wrong and needs further investigation. Again this is NOT a change, it may have always been wrong, this patch just makes it clear what is happening. Signed-off-by: Eric Paris <eparis@redhat.com>
Diffstat (limited to 'security')
-rw-r--r--security/apparmor/lsm.c8
-rw-r--r--security/commoncap.c16
-rw-r--r--security/security.c7
-rw-r--r--security/selinux/hooks.c23
4 files changed, 24 insertions, 30 deletions
diff --git a/security/apparmor/lsm.c b/security/apparmor/lsm.c
index 37832026e58a..ef4e2a8a33a5 100644
--- a/security/apparmor/lsm.c
+++ b/security/apparmor/lsm.c
@@ -136,16 +136,16 @@ static int apparmor_capget(struct task_struct *target, kernel_cap_t *effective,
136 return 0; 136 return 0;
137} 137}
138 138
139static int apparmor_capable(struct task_struct *task, const struct cred *cred, 139static int apparmor_capable(const struct cred *cred, struct user_namespace *ns,
140 struct user_namespace *ns, int cap, int audit) 140 int cap, int audit)
141{ 141{
142 struct aa_profile *profile; 142 struct aa_profile *profile;
143 /* cap_capable returns 0 on success, else -EPERM */ 143 /* cap_capable returns 0 on success, else -EPERM */
144 int error = cap_capable(task, cred, ns, cap, audit); 144 int error = cap_capable(cred, ns, cap, audit);
145 if (!error) { 145 if (!error) {
146 profile = aa_cred_profile(cred); 146 profile = aa_cred_profile(cred);
147 if (!unconfined(profile)) 147 if (!unconfined(profile))
148 error = aa_capable(task, profile, cap, audit); 148 error = aa_capable(current, profile, cap, audit);
149 } 149 }
150 return error; 150 return error;
151} 151}
diff --git a/security/commoncap.c b/security/commoncap.c
index a93b3b733079..89f02ff66af9 100644
--- a/security/commoncap.c
+++ b/security/commoncap.c
@@ -66,7 +66,6 @@ EXPORT_SYMBOL(cap_netlink_recv);
66 66
67/** 67/**
68 * cap_capable - Determine whether a task has a particular effective capability 68 * cap_capable - Determine whether a task has a particular effective capability
69 * @tsk: The task to query
70 * @cred: The credentials to use 69 * @cred: The credentials to use
71 * @ns: The user namespace in which we need the capability 70 * @ns: The user namespace in which we need the capability
72 * @cap: The capability to check for 71 * @cap: The capability to check for
@@ -80,8 +79,8 @@ EXPORT_SYMBOL(cap_netlink_recv);
80 * cap_has_capability() returns 0 when a task has a capability, but the 79 * cap_has_capability() returns 0 when a task has a capability, but the
81 * kernel's capable() and has_capability() returns 1 for this case. 80 * kernel's capable() and has_capability() returns 1 for this case.
82 */ 81 */
83int cap_capable(struct task_struct *tsk, const struct cred *cred, 82int cap_capable(const struct cred *cred, struct user_namespace *targ_ns,
84 struct user_namespace *targ_ns, int cap, int audit) 83 int cap, int audit)
85{ 84{
86 for (;;) { 85 for (;;) {
87 /* The creator of the user namespace has all caps. */ 86 /* The creator of the user namespace has all caps. */
@@ -222,9 +221,8 @@ static inline int cap_inh_is_capped(void)
222 /* they are so limited unless the current task has the CAP_SETPCAP 221 /* they are so limited unless the current task has the CAP_SETPCAP
223 * capability 222 * capability
224 */ 223 */
225 if (cap_capable(current, current_cred(), 224 if (cap_capable(current_cred(), current_cred()->user->user_ns,
226 current_cred()->user->user_ns, CAP_SETPCAP, 225 CAP_SETPCAP, SECURITY_CAP_AUDIT) == 0)
227 SECURITY_CAP_AUDIT) == 0)
228 return 0; 226 return 0;
229 return 1; 227 return 1;
230} 228}
@@ -870,7 +868,7 @@ int cap_task_prctl(int option, unsigned long arg2, unsigned long arg3,
870 & (new->securebits ^ arg2)) /*[1]*/ 868 & (new->securebits ^ arg2)) /*[1]*/
871 || ((new->securebits & SECURE_ALL_LOCKS & ~arg2)) /*[2]*/ 869 || ((new->securebits & SECURE_ALL_LOCKS & ~arg2)) /*[2]*/
872 || (arg2 & ~(SECURE_ALL_LOCKS | SECURE_ALL_BITS)) /*[3]*/ 870 || (arg2 & ~(SECURE_ALL_LOCKS | SECURE_ALL_BITS)) /*[3]*/
873 || (cap_capable(current, current_cred(), 871 || (cap_capable(current_cred(),
874 current_cred()->user->user_ns, CAP_SETPCAP, 872 current_cred()->user->user_ns, CAP_SETPCAP,
875 SECURITY_CAP_AUDIT) != 0) /*[4]*/ 873 SECURITY_CAP_AUDIT) != 0) /*[4]*/
876 /* 874 /*
@@ -936,7 +934,7 @@ int cap_vm_enough_memory(struct mm_struct *mm, long pages)
936{ 934{
937 int cap_sys_admin = 0; 935 int cap_sys_admin = 0;
938 936
939 if (cap_capable(current, current_cred(), &init_user_ns, CAP_SYS_ADMIN, 937 if (cap_capable(current_cred(), &init_user_ns, CAP_SYS_ADMIN,
940 SECURITY_CAP_NOAUDIT) == 0) 938 SECURITY_CAP_NOAUDIT) == 0)
941 cap_sys_admin = 1; 939 cap_sys_admin = 1;
942 return __vm_enough_memory(mm, pages, cap_sys_admin); 940 return __vm_enough_memory(mm, pages, cap_sys_admin);
@@ -963,7 +961,7 @@ int cap_file_mmap(struct file *file, unsigned long reqprot,
963 int ret = 0; 961 int ret = 0;
964 962
965 if (addr < dac_mmap_min_addr) { 963 if (addr < dac_mmap_min_addr) {
966 ret = cap_capable(current, current_cred(), &init_user_ns, CAP_SYS_RAWIO, 964 ret = cap_capable(current_cred(), &init_user_ns, CAP_SYS_RAWIO,
967 SECURITY_CAP_AUDIT); 965 SECURITY_CAP_AUDIT);
968 /* set PF_SUPERPRIV if it turns out we allow the low mmap */ 966 /* set PF_SUPERPRIV if it turns out we allow the low mmap */
969 if (ret == 0) 967 if (ret == 0)
diff --git a/security/security.c b/security/security.c
index d9e153390926..9ae68c64455e 100644
--- a/security/security.c
+++ b/security/security.c
@@ -157,8 +157,7 @@ int security_capset(struct cred *new, const struct cred *old,
157int security_capable(struct user_namespace *ns, const struct cred *cred, 157int security_capable(struct user_namespace *ns, const struct cred *cred,
158 int cap) 158 int cap)
159{ 159{
160 return security_ops->capable(current, cred, ns, cap, 160 return security_ops->capable(cred, ns, cap, SECURITY_CAP_AUDIT);
161 SECURITY_CAP_AUDIT);
162} 161}
163 162
164int security_real_capable(struct task_struct *tsk, struct user_namespace *ns, 163int security_real_capable(struct task_struct *tsk, struct user_namespace *ns,
@@ -168,7 +167,7 @@ int security_real_capable(struct task_struct *tsk, struct user_namespace *ns,
168 int ret; 167 int ret;
169 168
170 cred = get_task_cred(tsk); 169 cred = get_task_cred(tsk);
171 ret = security_ops->capable(tsk, cred, ns, cap, SECURITY_CAP_AUDIT); 170 ret = security_ops->capable(cred, ns, cap, SECURITY_CAP_AUDIT);
172 put_cred(cred); 171 put_cred(cred);
173 return ret; 172 return ret;
174} 173}
@@ -180,7 +179,7 @@ int security_real_capable_noaudit(struct task_struct *tsk,
180 int ret; 179 int ret;
181 180
182 cred = get_task_cred(tsk); 181 cred = get_task_cred(tsk);
183 ret = security_ops->capable(tsk, cred, ns, cap, SECURITY_CAP_NOAUDIT); 182 ret = security_ops->capable(cred, ns, cap, SECURITY_CAP_NOAUDIT);
184 put_cred(cred); 183 put_cred(cred);
185 return ret; 184 return ret;
186} 185}
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index e545b9f67072..c9605c4a2e08 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -1414,8 +1414,7 @@ static int current_has_perm(const struct task_struct *tsk,
1414#endif 1414#endif
1415 1415
1416/* Check whether a task is allowed to use a capability. */ 1416/* Check whether a task is allowed to use a capability. */
1417static int task_has_capability(struct task_struct *tsk, 1417static int cred_has_capability(const struct cred *cred,
1418 const struct cred *cred,
1419 int cap, int audit) 1418 int cap, int audit)
1420{ 1419{
1421 struct common_audit_data ad; 1420 struct common_audit_data ad;
@@ -1426,7 +1425,7 @@ static int task_has_capability(struct task_struct *tsk,
1426 int rc; 1425 int rc;
1427 1426
1428 COMMON_AUDIT_DATA_INIT(&ad, CAP); 1427 COMMON_AUDIT_DATA_INIT(&ad, CAP);
1429 ad.tsk = tsk; 1428 ad.tsk = current;
1430 ad.u.cap = cap; 1429 ad.u.cap = cap;
1431 1430
1432 switch (CAP_TO_INDEX(cap)) { 1431 switch (CAP_TO_INDEX(cap)) {
@@ -1867,16 +1866,16 @@ static int selinux_capset(struct cred *new, const struct cred *old,
1867 * the CAP_SETUID and CAP_SETGID capabilities using the capable hook. 1866 * the CAP_SETUID and CAP_SETGID capabilities using the capable hook.
1868 */ 1867 */
1869 1868
1870static int selinux_capable(struct task_struct *tsk, const struct cred *cred, 1869static int selinux_capable(const struct cred *cred, struct user_namespace *ns,
1871 struct user_namespace *ns, int cap, int audit) 1870 int cap, int audit)
1872{ 1871{
1873 int rc; 1872 int rc;
1874 1873
1875 rc = cap_capable(tsk, cred, ns, cap, audit); 1874 rc = cap_capable(cred, ns, cap, audit);
1876 if (rc) 1875 if (rc)
1877 return rc; 1876 return rc;
1878 1877
1879 return task_has_capability(tsk, cred, cap, audit); 1878 return cred_has_capability(cred, cap, audit);
1880} 1879}
1881 1880
1882static int selinux_quotactl(int cmds, int type, int id, struct super_block *sb) 1881static int selinux_quotactl(int cmds, int type, int id, struct super_block *sb)
@@ -1953,8 +1952,7 @@ static int selinux_vm_enough_memory(struct mm_struct *mm, long pages)
1953{ 1952{
1954 int rc, cap_sys_admin = 0; 1953 int rc, cap_sys_admin = 0;
1955 1954
1956 rc = selinux_capable(current, current_cred(), 1955 rc = selinux_capable(current_cred(), &init_user_ns, CAP_SYS_ADMIN,
1957 &init_user_ns, CAP_SYS_ADMIN,
1958 SECURITY_CAP_NOAUDIT); 1956 SECURITY_CAP_NOAUDIT);
1959 if (rc == 0) 1957 if (rc == 0)
1960 cap_sys_admin = 1; 1958 cap_sys_admin = 1;
@@ -2858,8 +2856,7 @@ static int selinux_inode_getsecurity(const struct inode *inode, const char *name
2858 * and lack of permission just means that we fall back to the 2856 * and lack of permission just means that we fall back to the
2859 * in-core context value, not a denial. 2857 * in-core context value, not a denial.
2860 */ 2858 */
2861 error = selinux_capable(current, current_cred(), 2859 error = selinux_capable(current_cred(), &init_user_ns, CAP_MAC_ADMIN,
2862 &init_user_ns, CAP_MAC_ADMIN,
2863 SECURITY_CAP_NOAUDIT); 2860 SECURITY_CAP_NOAUDIT);
2864 if (!error) 2861 if (!error)
2865 error = security_sid_to_context_force(isec->sid, &context, 2862 error = security_sid_to_context_force(isec->sid, &context,
@@ -2992,8 +2989,8 @@ static int selinux_file_ioctl(struct file *file, unsigned int cmd,
2992 2989
2993 case KDSKBENT: 2990 case KDSKBENT:
2994 case KDSKBSENT: 2991 case KDSKBSENT:
2995 error = task_has_capability(current, cred, CAP_SYS_TTY_CONFIG, 2992 error = cred_has_capability(cred, CAP_SYS_TTY_CONFIG,
2996 SECURITY_CAP_AUDIT); 2993 SECURITY_CAP_AUDIT);
2997 break; 2994 break;
2998 2995
2999 /* default case assumes that the command will go 2996 /* default case assumes that the command will go