aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTyler Hicks <tyhicks@canonical.com>2016-06-03 00:43:21 -0400
committerJames Morris <james.l.morris@oracle.com>2016-06-06 06:16:18 -0400
commit98f368e9e2630a3ce3e80fb10fb2e02038cf9578 (patch)
treeae14325043192683972bc25ca35c8b7ceb8b8241
parent2885c1e3e0c29e4a1915214ddc9673925f538299 (diff)
kernel: Add noaudit variant of ns_capable()
When checking the current cred for a capability in a specific user namespace, it isn't always desirable to have the LSMs audit the check. This patch adds a noaudit variant of ns_capable() for when those situations arise. The common logic between ns_capable() and the new ns_capable_noaudit() is moved into a single, shared function to keep duplicated code to a minimum and ease maintainability. Signed-off-by: Tyler Hicks <tyhicks@canonical.com> Acked-by: Serge E. Hallyn <serge.hallyn@ubuntu.com> Signed-off-by: James Morris <james.l.morris@oracle.com>
-rw-r--r--include/linux/capability.h5
-rw-r--r--kernel/capability.c46
2 files changed, 41 insertions, 10 deletions
diff --git a/include/linux/capability.h b/include/linux/capability.h
index 00690ff92edf..5f3c63dde2d5 100644
--- a/include/linux/capability.h
+++ b/include/linux/capability.h
@@ -206,6 +206,7 @@ extern bool has_ns_capability_noaudit(struct task_struct *t,
206 struct user_namespace *ns, int cap); 206 struct user_namespace *ns, int cap);
207extern bool capable(int cap); 207extern bool capable(int cap);
208extern bool ns_capable(struct user_namespace *ns, int cap); 208extern bool ns_capable(struct user_namespace *ns, int cap);
209extern bool ns_capable_noaudit(struct user_namespace *ns, int cap);
209#else 210#else
210static inline bool has_capability(struct task_struct *t, int cap) 211static inline bool has_capability(struct task_struct *t, int cap)
211{ 212{
@@ -233,6 +234,10 @@ static inline bool ns_capable(struct user_namespace *ns, int cap)
233{ 234{
234 return true; 235 return true;
235} 236}
237static inline bool ns_capable_noaudit(struct user_namespace *ns, int cap)
238{
239 return true;
240}
236#endif /* CONFIG_MULTIUSER */ 241#endif /* CONFIG_MULTIUSER */
237extern bool capable_wrt_inode_uidgid(const struct inode *inode, int cap); 242extern bool capable_wrt_inode_uidgid(const struct inode *inode, int cap);
238extern bool file_ns_capable(const struct file *file, struct user_namespace *ns, int cap); 243extern bool file_ns_capable(const struct file *file, struct user_namespace *ns, int cap);
diff --git a/kernel/capability.c b/kernel/capability.c
index 45432b54d5c6..00411c82dac5 100644
--- a/kernel/capability.c
+++ b/kernel/capability.c
@@ -361,6 +361,24 @@ bool has_capability_noaudit(struct task_struct *t, int cap)
361 return has_ns_capability_noaudit(t, &init_user_ns, cap); 361 return has_ns_capability_noaudit(t, &init_user_ns, cap);
362} 362}
363 363
364static bool ns_capable_common(struct user_namespace *ns, int cap, bool audit)
365{
366 int capable;
367
368 if (unlikely(!cap_valid(cap))) {
369 pr_crit("capable() called with invalid cap=%u\n", cap);
370 BUG();
371 }
372
373 capable = audit ? security_capable(current_cred(), ns, cap) :
374 security_capable_noaudit(current_cred(), ns, cap);
375 if (capable == 0) {
376 current->flags |= PF_SUPERPRIV;
377 return true;
378 }
379 return false;
380}
381
364/** 382/**
365 * ns_capable - Determine if the current task has a superior capability in effect 383 * ns_capable - Determine if the current task has a superior capability in effect
366 * @ns: The usernamespace we want the capability in 384 * @ns: The usernamespace we want the capability in
@@ -374,19 +392,27 @@ bool has_capability_noaudit(struct task_struct *t, int cap)
374 */ 392 */
375bool ns_capable(struct user_namespace *ns, int cap) 393bool ns_capable(struct user_namespace *ns, int cap)
376{ 394{
377 if (unlikely(!cap_valid(cap))) { 395 return ns_capable_common(ns, cap, true);
378 pr_crit("capable() called with invalid cap=%u\n", cap);
379 BUG();
380 }
381
382 if (security_capable(current_cred(), ns, cap) == 0) {
383 current->flags |= PF_SUPERPRIV;
384 return true;
385 }
386 return false;
387} 396}
388EXPORT_SYMBOL(ns_capable); 397EXPORT_SYMBOL(ns_capable);
389 398
399/**
400 * ns_capable_noaudit - Determine if the current task has a superior capability
401 * (unaudited) in effect
402 * @ns: The usernamespace we want the capability in
403 * @cap: The capability to be tested for
404 *
405 * Return true if the current task has the given superior capability currently
406 * available for use, false if not.
407 *
408 * This sets PF_SUPERPRIV on the task if the capability is available on the
409 * assumption that it's about to be used.
410 */
411bool ns_capable_noaudit(struct user_namespace *ns, int cap)
412{
413 return ns_capable_common(ns, cap, false);
414}
415EXPORT_SYMBOL(ns_capable_noaudit);
390 416
391/** 417/**
392 * capable - Determine if the current task has a superior capability in effect 418 * capable - Determine if the current task has a superior capability in effect