summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMicah Morton <mortonm@chromium.org>2019-01-07 19:10:53 -0500
committerJames Morris <james.morris@microsoft.com>2019-01-10 17:16:06 -0500
commitc1a85a00ea66cb6f0bd0f14e47c28c2b0999799f (patch)
tree310c082e0b41d2d3ff8b619553ed5e45ad244862
parent2233975cd7927672525361c4c6eebc0b8d018a74 (diff)
LSM: generalize flag passing to security_capable
This patch provides a general mechanism for passing flags to the security_capable LSM hook. It replaces the specific 'audit' flag that is used to tell security_capable whether it should log an audit message for the given capability check. The reason for generalizing this flag passing is so we can add an additional flag that signifies whether security_capable is being called by a setid syscall (which is needed by the proposed SafeSetID LSM). Signed-off-by: Micah Morton <mortonm@chromium.org> Reviewed-by: Kees Cook <keescook@chromium.org> Signed-off-by: James Morris <james.morris@microsoft.com>
-rw-r--r--include/linux/lsm_hooks.h8
-rw-r--r--include/linux/security.h28
-rw-r--r--kernel/capability.c22
-rw-r--r--kernel/seccomp.c4
-rw-r--r--security/apparmor/capability.c14
-rw-r--r--security/apparmor/include/capability.h2
-rw-r--r--security/apparmor/ipc.c3
-rw-r--r--security/apparmor/lsm.c4
-rw-r--r--security/apparmor/resource.c2
-rw-r--r--security/commoncap.c17
-rw-r--r--security/security.c14
-rw-r--r--security/selinux/hooks.c18
-rw-r--r--security/smack/smack_access.c2
13 files changed, 71 insertions, 67 deletions
diff --git a/include/linux/lsm_hooks.h b/include/linux/lsm_hooks.h
index 40511a8a5ae6..195707210975 100644
--- a/include/linux/lsm_hooks.h
+++ b/include/linux/lsm_hooks.h
@@ -1270,7 +1270,7 @@
1270 * @cred contains the credentials to use. 1270 * @cred contains the credentials to use.
1271 * @ns contains the user namespace we want the capability in 1271 * @ns contains the user namespace we want the capability in
1272 * @cap contains the capability <include/linux/capability.h>. 1272 * @cap contains the capability <include/linux/capability.h>.
1273 * @audit contains whether to write an audit message or not 1273 * @opts contains options for the capable check <include/linux/security.h>
1274 * Return 0 if the capability is granted for @tsk. 1274 * Return 0 if the capability is granted for @tsk.
1275 * @syslog: 1275 * @syslog:
1276 * Check permission before accessing the kernel message ring or changing 1276 * Check permission before accessing the kernel message ring or changing
@@ -1446,8 +1446,10 @@ union security_list_options {
1446 const kernel_cap_t *effective, 1446 const kernel_cap_t *effective,
1447 const kernel_cap_t *inheritable, 1447 const kernel_cap_t *inheritable,
1448 const kernel_cap_t *permitted); 1448 const kernel_cap_t *permitted);
1449 int (*capable)(const struct cred *cred, struct user_namespace *ns, 1449 int (*capable)(const struct cred *cred,
1450 int cap, int audit); 1450 struct user_namespace *ns,
1451 int cap,
1452 unsigned int opts);
1451 int (*quotactl)(int cmds, int type, int id, struct super_block *sb); 1453 int (*quotactl)(int cmds, int type, int id, struct super_block *sb);
1452 int (*quota_on)(struct dentry *dentry); 1454 int (*quota_on)(struct dentry *dentry);
1453 int (*syslog)(int type); 1455 int (*syslog)(int type);
diff --git a/include/linux/security.h b/include/linux/security.h
index b2c5333ed4b5..13537a49ae97 100644
--- a/include/linux/security.h
+++ b/include/linux/security.h
@@ -54,9 +54,12 @@ struct xattr;
54struct xfrm_sec_ctx; 54struct xfrm_sec_ctx;
55struct mm_struct; 55struct mm_struct;
56 56
57/* Default (no) options for the capable function */
58#define CAP_OPT_NONE 0x0
57/* If capable should audit the security request */ 59/* If capable should audit the security request */
58#define SECURITY_CAP_NOAUDIT 0 60#define CAP_OPT_NOAUDIT BIT(1)
59#define SECURITY_CAP_AUDIT 1 61/* If capable is being called by a setid function */
62#define CAP_OPT_INSETID BIT(2)
60 63
61/* LSM Agnostic defines for sb_set_mnt_opts */ 64/* LSM Agnostic defines for sb_set_mnt_opts */
62#define SECURITY_LSM_NATIVE_LABELS 1 65#define SECURITY_LSM_NATIVE_LABELS 1
@@ -72,7 +75,7 @@ enum lsm_event {
72 75
73/* These functions are in security/commoncap.c */ 76/* These functions are in security/commoncap.c */
74extern int cap_capable(const struct cred *cred, struct user_namespace *ns, 77extern int cap_capable(const struct cred *cred, struct user_namespace *ns,
75 int cap, int audit); 78 int cap, unsigned int opts);
76extern int cap_settime(const struct timespec64 *ts, const struct timezone *tz); 79extern int cap_settime(const struct timespec64 *ts, const struct timezone *tz);
77extern int cap_ptrace_access_check(struct task_struct *child, unsigned int mode); 80extern int cap_ptrace_access_check(struct task_struct *child, unsigned int mode);
78extern int cap_ptrace_traceme(struct task_struct *parent); 81extern int cap_ptrace_traceme(struct task_struct *parent);
@@ -207,10 +210,10 @@ int security_capset(struct cred *new, const struct cred *old,
207 const kernel_cap_t *effective, 210 const kernel_cap_t *effective,
208 const kernel_cap_t *inheritable, 211 const kernel_cap_t *inheritable,
209 const kernel_cap_t *permitted); 212 const kernel_cap_t *permitted);
210int security_capable(const struct cred *cred, struct user_namespace *ns, 213int security_capable(const struct cred *cred,
211 int cap); 214 struct user_namespace *ns,
212int security_capable_noaudit(const struct cred *cred, struct user_namespace *ns, 215 int cap,
213 int cap); 216 unsigned int opts);
214int security_quotactl(int cmds, int type, int id, struct super_block *sb); 217int security_quotactl(int cmds, int type, int id, struct super_block *sb);
215int security_quota_on(struct dentry *dentry); 218int security_quota_on(struct dentry *dentry);
216int security_syslog(int type); 219int security_syslog(int type);
@@ -464,14 +467,11 @@ static inline int security_capset(struct cred *new,
464} 467}
465 468
466static inline int security_capable(const struct cred *cred, 469static inline int security_capable(const struct cred *cred,
467 struct user_namespace *ns, int cap) 470 struct user_namespace *ns,
471 int cap,
472 unsigned int opts)
468{ 473{
469 return cap_capable(cred, ns, cap, SECURITY_CAP_AUDIT); 474 return cap_capable(cred, ns, cap, opts);
470}
471
472static inline int security_capable_noaudit(const struct cred *cred,
473 struct user_namespace *ns, int cap) {
474 return cap_capable(cred, ns, cap, SECURITY_CAP_NOAUDIT);
475} 475}
476 476
477static inline int security_quotactl(int cmds, int type, int id, 477static inline int security_quotactl(int cmds, int type, int id,
diff --git a/kernel/capability.c b/kernel/capability.c
index 1e1c0236f55b..7718d7dcadc7 100644
--- a/kernel/capability.c
+++ b/kernel/capability.c
@@ -299,7 +299,7 @@ bool has_ns_capability(struct task_struct *t,
299 int ret; 299 int ret;
300 300
301 rcu_read_lock(); 301 rcu_read_lock();
302 ret = security_capable(__task_cred(t), ns, cap); 302 ret = security_capable(__task_cred(t), ns, cap, CAP_OPT_NONE);
303 rcu_read_unlock(); 303 rcu_read_unlock();
304 304
305 return (ret == 0); 305 return (ret == 0);
@@ -340,7 +340,7 @@ bool has_ns_capability_noaudit(struct task_struct *t,
340 int ret; 340 int ret;
341 341
342 rcu_read_lock(); 342 rcu_read_lock();
343 ret = security_capable_noaudit(__task_cred(t), ns, cap); 343 ret = security_capable(__task_cred(t), ns, cap, CAP_OPT_NOAUDIT);
344 rcu_read_unlock(); 344 rcu_read_unlock();
345 345
346 return (ret == 0); 346 return (ret == 0);
@@ -363,7 +363,9 @@ bool has_capability_noaudit(struct task_struct *t, int cap)
363 return has_ns_capability_noaudit(t, &init_user_ns, cap); 363 return has_ns_capability_noaudit(t, &init_user_ns, cap);
364} 364}
365 365
366static bool ns_capable_common(struct user_namespace *ns, int cap, bool audit) 366static bool ns_capable_common(struct user_namespace *ns,
367 int cap,
368 unsigned int opts)
367{ 369{
368 int capable; 370 int capable;
369 371
@@ -372,8 +374,7 @@ static bool ns_capable_common(struct user_namespace *ns, int cap, bool audit)
372 BUG(); 374 BUG();
373 } 375 }
374 376
375 capable = audit ? security_capable(current_cred(), ns, cap) : 377 capable = security_capable(current_cred(), ns, cap, opts);
376 security_capable_noaudit(current_cred(), ns, cap);
377 if (capable == 0) { 378 if (capable == 0) {
378 current->flags |= PF_SUPERPRIV; 379 current->flags |= PF_SUPERPRIV;
379 return true; 380 return true;
@@ -394,7 +395,7 @@ static bool ns_capable_common(struct user_namespace *ns, int cap, bool audit)
394 */ 395 */
395bool ns_capable(struct user_namespace *ns, int cap) 396bool ns_capable(struct user_namespace *ns, int cap)
396{ 397{
397 return ns_capable_common(ns, cap, true); 398 return ns_capable_common(ns, cap, CAP_OPT_NONE);
398} 399}
399EXPORT_SYMBOL(ns_capable); 400EXPORT_SYMBOL(ns_capable);
400 401
@@ -412,7 +413,7 @@ EXPORT_SYMBOL(ns_capable);
412 */ 413 */
413bool ns_capable_noaudit(struct user_namespace *ns, int cap) 414bool ns_capable_noaudit(struct user_namespace *ns, int cap)
414{ 415{
415 return ns_capable_common(ns, cap, false); 416 return ns_capable_common(ns, cap, CAP_OPT_NOAUDIT);
416} 417}
417EXPORT_SYMBOL(ns_capable_noaudit); 418EXPORT_SYMBOL(ns_capable_noaudit);
418 419
@@ -448,10 +449,11 @@ EXPORT_SYMBOL(capable);
448bool file_ns_capable(const struct file *file, struct user_namespace *ns, 449bool file_ns_capable(const struct file *file, struct user_namespace *ns,
449 int cap) 450 int cap)
450{ 451{
452
451 if (WARN_ON_ONCE(!cap_valid(cap))) 453 if (WARN_ON_ONCE(!cap_valid(cap)))
452 return false; 454 return false;
453 455
454 if (security_capable(file->f_cred, ns, cap) == 0) 456 if (security_capable(file->f_cred, ns, cap, CAP_OPT_NONE) == 0)
455 return true; 457 return true;
456 458
457 return false; 459 return false;
@@ -500,10 +502,12 @@ bool ptracer_capable(struct task_struct *tsk, struct user_namespace *ns)
500{ 502{
501 int ret = 0; /* An absent tracer adds no restrictions */ 503 int ret = 0; /* An absent tracer adds no restrictions */
502 const struct cred *cred; 504 const struct cred *cred;
505
503 rcu_read_lock(); 506 rcu_read_lock();
504 cred = rcu_dereference(tsk->ptracer_cred); 507 cred = rcu_dereference(tsk->ptracer_cred);
505 if (cred) 508 if (cred)
506 ret = security_capable_noaudit(cred, ns, CAP_SYS_PTRACE); 509 ret = security_capable(cred, ns, CAP_SYS_PTRACE,
510 CAP_OPT_NOAUDIT);
507 rcu_read_unlock(); 511 rcu_read_unlock();
508 return (ret == 0); 512 return (ret == 0);
509} 513}
diff --git a/kernel/seccomp.c b/kernel/seccomp.c
index d7f538847b84..38a77800def6 100644
--- a/kernel/seccomp.c
+++ b/kernel/seccomp.c
@@ -443,8 +443,8 @@ static struct seccomp_filter *seccomp_prepare_filter(struct sock_fprog *fprog)
443 * behavior of privileged children. 443 * behavior of privileged children.
444 */ 444 */
445 if (!task_no_new_privs(current) && 445 if (!task_no_new_privs(current) &&
446 security_capable_noaudit(current_cred(), current_user_ns(), 446 security_capable(current_cred(), current_user_ns(),
447 CAP_SYS_ADMIN) != 0) 447 CAP_SYS_ADMIN, CAP_OPT_NOAUDIT) != 0)
448 return ERR_PTR(-EACCES); 448 return ERR_PTR(-EACCES);
449 449
450 /* Allocate a new seccomp_filter */ 450 /* Allocate a new seccomp_filter */
diff --git a/security/apparmor/capability.c b/security/apparmor/capability.c
index 253ef6e9d445..752f73980e30 100644
--- a/security/apparmor/capability.c
+++ b/security/apparmor/capability.c
@@ -110,13 +110,13 @@ static int audit_caps(struct common_audit_data *sa, struct aa_profile *profile,
110 * profile_capable - test if profile allows use of capability @cap 110 * profile_capable - test if profile allows use of capability @cap
111 * @profile: profile being enforced (NOT NULL, NOT unconfined) 111 * @profile: profile being enforced (NOT NULL, NOT unconfined)
112 * @cap: capability to test if allowed 112 * @cap: capability to test if allowed
113 * @audit: whether an audit record should be generated 113 * @opts: CAP_OPT_NOAUDIT bit determines whether audit record is generated
114 * @sa: audit data (MAY BE NULL indicating no auditing) 114 * @sa: audit data (MAY BE NULL indicating no auditing)
115 * 115 *
116 * Returns: 0 if allowed else -EPERM 116 * Returns: 0 if allowed else -EPERM
117 */ 117 */
118static int profile_capable(struct aa_profile *profile, int cap, int audit, 118static int profile_capable(struct aa_profile *profile, int cap,
119 struct common_audit_data *sa) 119 unsigned int opts, struct common_audit_data *sa)
120{ 120{
121 int error; 121 int error;
122 122
@@ -126,7 +126,7 @@ static int profile_capable(struct aa_profile *profile, int cap, int audit,
126 else 126 else
127 error = -EPERM; 127 error = -EPERM;
128 128
129 if (audit == SECURITY_CAP_NOAUDIT) { 129 if (opts & CAP_OPT_NOAUDIT) {
130 if (!COMPLAIN_MODE(profile)) 130 if (!COMPLAIN_MODE(profile))
131 return error; 131 return error;
132 /* audit the cap request in complain mode but note that it 132 /* audit the cap request in complain mode but note that it
@@ -142,13 +142,13 @@ static int profile_capable(struct aa_profile *profile, int cap, int audit,
142 * aa_capable - test permission to use capability 142 * aa_capable - test permission to use capability
143 * @label: label being tested for capability (NOT NULL) 143 * @label: label being tested for capability (NOT NULL)
144 * @cap: capability to be tested 144 * @cap: capability to be tested
145 * @audit: whether an audit record should be generated 145 * @opts: CAP_OPT_NOAUDIT bit determines whether audit record is generated
146 * 146 *
147 * Look up capability in profile capability set. 147 * Look up capability in profile capability set.
148 * 148 *
149 * Returns: 0 on success, or else an error code. 149 * Returns: 0 on success, or else an error code.
150 */ 150 */
151int aa_capable(struct aa_label *label, int cap, int audit) 151int aa_capable(struct aa_label *label, int cap, unsigned int opts)
152{ 152{
153 struct aa_profile *profile; 153 struct aa_profile *profile;
154 int error = 0; 154 int error = 0;
@@ -156,7 +156,7 @@ int aa_capable(struct aa_label *label, int cap, int audit)
156 156
157 sa.u.cap = cap; 157 sa.u.cap = cap;
158 error = fn_for_each_confined(label, profile, 158 error = fn_for_each_confined(label, profile,
159 profile_capable(profile, cap, audit, &sa)); 159 profile_capable(profile, cap, opts, &sa));
160 160
161 return error; 161 return error;
162} 162}
diff --git a/security/apparmor/include/capability.h b/security/apparmor/include/capability.h
index e0304e2aeb7f..1b3663b6ab12 100644
--- a/security/apparmor/include/capability.h
+++ b/security/apparmor/include/capability.h
@@ -40,7 +40,7 @@ struct aa_caps {
40 40
41extern struct aa_sfs_entry aa_sfs_entry_caps[]; 41extern struct aa_sfs_entry aa_sfs_entry_caps[];
42 42
43int aa_capable(struct aa_label *label, int cap, int audit); 43int aa_capable(struct aa_label *label, int cap, unsigned int opts);
44 44
45static inline void aa_free_cap_rules(struct aa_caps *caps) 45static inline void aa_free_cap_rules(struct aa_caps *caps)
46{ 46{
diff --git a/security/apparmor/ipc.c b/security/apparmor/ipc.c
index 527ea1557120..aacd1e95cb59 100644
--- a/security/apparmor/ipc.c
+++ b/security/apparmor/ipc.c
@@ -107,7 +107,8 @@ static int profile_tracer_perm(struct aa_profile *tracer,
107 aad(sa)->label = &tracer->label; 107 aad(sa)->label = &tracer->label;
108 aad(sa)->peer = tracee; 108 aad(sa)->peer = tracee;
109 aad(sa)->request = 0; 109 aad(sa)->request = 0;
110 aad(sa)->error = aa_capable(&tracer->label, CAP_SYS_PTRACE, 1); 110 aad(sa)->error = aa_capable(&tracer->label, CAP_SYS_PTRACE,
111 CAP_OPT_NONE);
111 112
112 return aa_audit(AUDIT_APPARMOR_AUTO, tracer, sa, audit_ptrace_cb); 113 return aa_audit(AUDIT_APPARMOR_AUTO, tracer, sa, audit_ptrace_cb);
113} 114}
diff --git a/security/apparmor/lsm.c b/security/apparmor/lsm.c
index 60ef71268ccf..b6c395e2acd0 100644
--- a/security/apparmor/lsm.c
+++ b/security/apparmor/lsm.c
@@ -172,14 +172,14 @@ static int apparmor_capget(struct task_struct *target, kernel_cap_t *effective,
172} 172}
173 173
174static int apparmor_capable(const struct cred *cred, struct user_namespace *ns, 174static int apparmor_capable(const struct cred *cred, struct user_namespace *ns,
175 int cap, int audit) 175 int cap, unsigned int opts)
176{ 176{
177 struct aa_label *label; 177 struct aa_label *label;
178 int error = 0; 178 int error = 0;
179 179
180 label = aa_get_newest_cred_label(cred); 180 label = aa_get_newest_cred_label(cred);
181 if (!unconfined(label)) 181 if (!unconfined(label))
182 error = aa_capable(label, cap, audit); 182 error = aa_capable(label, cap, opts);
183 aa_put_label(label); 183 aa_put_label(label);
184 184
185 return error; 185 return error;
diff --git a/security/apparmor/resource.c b/security/apparmor/resource.c
index 95fd26d09757..552ed09cb47e 100644
--- a/security/apparmor/resource.c
+++ b/security/apparmor/resource.c
@@ -124,7 +124,7 @@ int aa_task_setrlimit(struct aa_label *label, struct task_struct *task,
124 */ 124 */
125 125
126 if (label != peer && 126 if (label != peer &&
127 aa_capable(label, CAP_SYS_RESOURCE, SECURITY_CAP_NOAUDIT) != 0) 127 aa_capable(label, CAP_SYS_RESOURCE, CAP_OPT_NOAUDIT) != 0)
128 error = fn_for_each(label, profile, 128 error = fn_for_each(label, profile,
129 audit_resource(profile, resource, 129 audit_resource(profile, resource,
130 new_rlim->rlim_max, peer, 130 new_rlim->rlim_max, peer,
diff --git a/security/commoncap.c b/security/commoncap.c
index 52e04136bfa8..188eaf59f82f 100644
--- a/security/commoncap.c
+++ b/security/commoncap.c
@@ -68,7 +68,7 @@ static void warn_setuid_and_fcaps_mixed(const char *fname)
68 * kernel's capable() and has_capability() returns 1 for this case. 68 * kernel's capable() and has_capability() returns 1 for this case.
69 */ 69 */
70int cap_capable(const struct cred *cred, struct user_namespace *targ_ns, 70int cap_capable(const struct cred *cred, struct user_namespace *targ_ns,
71 int cap, int audit) 71 int cap, unsigned int opts)
72{ 72{
73 struct user_namespace *ns = targ_ns; 73 struct user_namespace *ns = targ_ns;
74 74
@@ -222,12 +222,11 @@ int cap_capget(struct task_struct *target, kernel_cap_t *effective,
222 */ 222 */
223static inline int cap_inh_is_capped(void) 223static inline int cap_inh_is_capped(void)
224{ 224{
225
226 /* they are so limited unless the current task has the CAP_SETPCAP 225 /* they are so limited unless the current task has the CAP_SETPCAP
227 * capability 226 * capability
228 */ 227 */
229 if (cap_capable(current_cred(), current_cred()->user_ns, 228 if (cap_capable(current_cred(), current_cred()->user_ns,
230 CAP_SETPCAP, SECURITY_CAP_AUDIT) == 0) 229 CAP_SETPCAP, CAP_OPT_NONE) == 0)
231 return 0; 230 return 0;
232 return 1; 231 return 1;
233} 232}
@@ -1208,8 +1207,9 @@ int cap_task_prctl(int option, unsigned long arg2, unsigned long arg3,
1208 || ((old->securebits & SECURE_ALL_LOCKS & ~arg2)) /*[2]*/ 1207 || ((old->securebits & SECURE_ALL_LOCKS & ~arg2)) /*[2]*/
1209 || (arg2 & ~(SECURE_ALL_LOCKS | SECURE_ALL_BITS)) /*[3]*/ 1208 || (arg2 & ~(SECURE_ALL_LOCKS | SECURE_ALL_BITS)) /*[3]*/
1210 || (cap_capable(current_cred(), 1209 || (cap_capable(current_cred(),
1211 current_cred()->user_ns, CAP_SETPCAP, 1210 current_cred()->user_ns,
1212 SECURITY_CAP_AUDIT) != 0) /*[4]*/ 1211 CAP_SETPCAP,
1212 CAP_OPT_NONE) != 0) /*[4]*/
1213 /* 1213 /*
1214 * [1] no changing of bits that are locked 1214 * [1] no changing of bits that are locked
1215 * [2] no unlocking of locks 1215 * [2] no unlocking of locks
@@ -1304,9 +1304,10 @@ int cap_vm_enough_memory(struct mm_struct *mm, long pages)
1304{ 1304{
1305 int cap_sys_admin = 0; 1305 int cap_sys_admin = 0;
1306 1306
1307 if (cap_capable(current_cred(), &init_user_ns, CAP_SYS_ADMIN, 1307 if (cap_capable(current_cred(), &init_user_ns,
1308 SECURITY_CAP_NOAUDIT) == 0) 1308 CAP_SYS_ADMIN, CAP_OPT_NOAUDIT) == 0)
1309 cap_sys_admin = 1; 1309 cap_sys_admin = 1;
1310
1310 return cap_sys_admin; 1311 return cap_sys_admin;
1311} 1312}
1312 1313
@@ -1325,7 +1326,7 @@ int cap_mmap_addr(unsigned long addr)
1325 1326
1326 if (addr < dac_mmap_min_addr) { 1327 if (addr < dac_mmap_min_addr) {
1327 ret = cap_capable(current_cred(), &init_user_ns, CAP_SYS_RAWIO, 1328 ret = cap_capable(current_cred(), &init_user_ns, CAP_SYS_RAWIO,
1328 SECURITY_CAP_AUDIT); 1329 CAP_OPT_NONE);
1329 /* set PF_SUPERPRIV if it turns out we allow the low mmap */ 1330 /* set PF_SUPERPRIV if it turns out we allow the low mmap */
1330 if (ret == 0) 1331 if (ret == 0)
1331 current->flags |= PF_SUPERPRIV; 1332 current->flags |= PF_SUPERPRIV;
diff --git a/security/security.c b/security/security.c
index 953fc3ea18a9..a618e22df5c6 100644
--- a/security/security.c
+++ b/security/security.c
@@ -689,16 +689,12 @@ int security_capset(struct cred *new, const struct cred *old,
689 effective, inheritable, permitted); 689 effective, inheritable, permitted);
690} 690}
691 691
692int security_capable(const struct cred *cred, struct user_namespace *ns, 692int security_capable(const struct cred *cred,
693 int cap) 693 struct user_namespace *ns,
694 int cap,
695 unsigned int opts)
694{ 696{
695 return call_int_hook(capable, 0, cred, ns, cap, SECURITY_CAP_AUDIT); 697 return call_int_hook(capable, 0, cred, ns, cap, opts);
696}
697
698int security_capable_noaudit(const struct cred *cred, struct user_namespace *ns,
699 int cap)
700{
701 return call_int_hook(capable, 0, cred, ns, cap, SECURITY_CAP_NOAUDIT);
702} 698}
703 699
704int security_quotactl(int cmds, int type, int id, struct super_block *sb) 700int security_quotactl(int cmds, int type, int id, struct super_block *sb)
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index d98e1d8d18f6..b2ee49f938f1 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -1578,7 +1578,7 @@ static inline u32 signal_to_av(int sig)
1578 1578
1579/* Check whether a task is allowed to use a capability. */ 1579/* Check whether a task is allowed to use a capability. */
1580static int cred_has_capability(const struct cred *cred, 1580static int cred_has_capability(const struct cred *cred,
1581 int cap, int audit, bool initns) 1581 int cap, unsigned int opts, bool initns)
1582{ 1582{
1583 struct common_audit_data ad; 1583 struct common_audit_data ad;
1584 struct av_decision avd; 1584 struct av_decision avd;
@@ -1605,7 +1605,7 @@ static int cred_has_capability(const struct cred *cred,
1605 1605
1606 rc = avc_has_perm_noaudit(&selinux_state, 1606 rc = avc_has_perm_noaudit(&selinux_state,
1607 sid, sid, sclass, av, 0, &avd); 1607 sid, sid, sclass, av, 0, &avd);
1608 if (audit == SECURITY_CAP_AUDIT) { 1608 if (!(opts & CAP_OPT_NOAUDIT)) {
1609 int rc2 = avc_audit(&selinux_state, 1609 int rc2 = avc_audit(&selinux_state,
1610 sid, sid, sclass, av, &avd, rc, &ad, 0); 1610 sid, sid, sclass, av, &avd, rc, &ad, 0);
1611 if (rc2) 1611 if (rc2)
@@ -2125,9 +2125,9 @@ static int selinux_capset(struct cred *new, const struct cred *old,
2125 */ 2125 */
2126 2126
2127static int selinux_capable(const struct cred *cred, struct user_namespace *ns, 2127static int selinux_capable(const struct cred *cred, struct user_namespace *ns,
2128 int cap, int audit) 2128 int cap, unsigned int opts)
2129{ 2129{
2130 return cred_has_capability(cred, cap, audit, ns == &init_user_ns); 2130 return cred_has_capability(cred, cap, opts, ns == &init_user_ns);
2131} 2131}
2132 2132
2133static int selinux_quotactl(int cmds, int type, int id, struct super_block *sb) 2133static int selinux_quotactl(int cmds, int type, int id, struct super_block *sb)
@@ -2201,7 +2201,7 @@ static int selinux_vm_enough_memory(struct mm_struct *mm, long pages)
2201 int rc, cap_sys_admin = 0; 2201 int rc, cap_sys_admin = 0;
2202 2202
2203 rc = cred_has_capability(current_cred(), CAP_SYS_ADMIN, 2203 rc = cred_has_capability(current_cred(), CAP_SYS_ADMIN,
2204 SECURITY_CAP_NOAUDIT, true); 2204 CAP_OPT_NOAUDIT, true);
2205 if (rc == 0) 2205 if (rc == 0)
2206 cap_sys_admin = 1; 2206 cap_sys_admin = 1;
2207 2207
@@ -2988,11 +2988,11 @@ static int selinux_inode_getattr(const struct path *path)
2988static bool has_cap_mac_admin(bool audit) 2988static bool has_cap_mac_admin(bool audit)
2989{ 2989{
2990 const struct cred *cred = current_cred(); 2990 const struct cred *cred = current_cred();
2991 int cap_audit = audit ? SECURITY_CAP_AUDIT : SECURITY_CAP_NOAUDIT; 2991 unsigned int opts = audit ? CAP_OPT_NONE : CAP_OPT_NOAUDIT;
2992 2992
2993 if (cap_capable(cred, &init_user_ns, CAP_MAC_ADMIN, cap_audit)) 2993 if (cap_capable(cred, &init_user_ns, CAP_MAC_ADMIN, opts))
2994 return false; 2994 return false;
2995 if (cred_has_capability(cred, CAP_MAC_ADMIN, cap_audit, true)) 2995 if (cred_has_capability(cred, CAP_MAC_ADMIN, opts, true))
2996 return false; 2996 return false;
2997 return true; 2997 return true;
2998} 2998}
@@ -3387,7 +3387,7 @@ static int selinux_file_ioctl(struct file *file, unsigned int cmd,
3387 case KDSKBENT: 3387 case KDSKBENT:
3388 case KDSKBSENT: 3388 case KDSKBSENT:
3389 error = cred_has_capability(cred, CAP_SYS_TTY_CONFIG, 3389 error = cred_has_capability(cred, CAP_SYS_TTY_CONFIG,
3390 SECURITY_CAP_AUDIT, true); 3390 CAP_OPT_NONE, true);
3391 break; 3391 break;
3392 3392
3393 /* default case assumes that the command will go 3393 /* default case assumes that the command will go
diff --git a/security/smack/smack_access.c b/security/smack/smack_access.c
index 489d49a20b47..fe2ce3a65822 100644
--- a/security/smack/smack_access.c
+++ b/security/smack/smack_access.c
@@ -640,7 +640,7 @@ bool smack_privileged_cred(int cap, const struct cred *cred)
640 struct smack_known_list_elem *sklep; 640 struct smack_known_list_elem *sklep;
641 int rc; 641 int rc;
642 642
643 rc = cap_capable(cred, &init_user_ns, cap, SECURITY_CAP_AUDIT); 643 rc = cap_capable(cred, &init_user_ns, cap, CAP_OPT_NONE);
644 if (rc) 644 if (rc)
645 return false; 645 return false;
646 646