Skip to content

Commit 98f368e

Browse files
tyhicksJames Morris
authored andcommitted
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 <[email protected]> Acked-by: Serge E. Hallyn <[email protected]> Signed-off-by: James Morris <[email protected]>
1 parent 2885c1e commit 98f368e

File tree

2 files changed

+41
-10
lines changed

2 files changed

+41
-10
lines changed

include/linux/capability.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -206,6 +206,7 @@ extern bool has_ns_capability_noaudit(struct task_struct *t,
206206
struct user_namespace *ns, int cap);
207207
extern bool capable(int cap);
208208
extern bool ns_capable(struct user_namespace *ns, int cap);
209+
extern bool ns_capable_noaudit(struct user_namespace *ns, int cap);
209210
#else
210211
static inline bool has_capability(struct task_struct *t, int cap)
211212
{
@@ -233,6 +234,10 @@ static inline bool ns_capable(struct user_namespace *ns, int cap)
233234
{
234235
return true;
235236
}
237+
static inline bool ns_capable_noaudit(struct user_namespace *ns, int cap)
238+
{
239+
return true;
240+
}
236241
#endif /* CONFIG_MULTIUSER */
237242
extern bool capable_wrt_inode_uidgid(const struct inode *inode, int cap);
238243
extern bool file_ns_capable(const struct file *file, struct user_namespace *ns, int cap);

kernel/capability.c

Lines changed: 36 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -361,6 +361,24 @@ bool has_capability_noaudit(struct task_struct *t, int cap)
361361
return has_ns_capability_noaudit(t, &init_user_ns, cap);
362362
}
363363

364+
static 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+
364382
/**
365383
* ns_capable - Determine if the current task has a superior capability in effect
366384
* @ns: The usernamespace we want the capability in
@@ -374,19 +392,27 @@ bool has_capability_noaudit(struct task_struct *t, int cap)
374392
*/
375393
bool ns_capable(struct user_namespace *ns, int cap)
376394
{
377-
if (unlikely(!cap_valid(cap))) {
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;
395+
return ns_capable_common(ns, cap, true);
387396
}
388397
EXPORT_SYMBOL(ns_capable);
389398

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+
*/
411+
bool ns_capable_noaudit(struct user_namespace *ns, int cap)
412+
{
413+
return ns_capable_common(ns, cap, false);
414+
}
415+
EXPORT_SYMBOL(ns_capable_noaudit);
390416

391417
/**
392418
* capable - Determine if the current task has a superior capability in effect

0 commit comments

Comments
 (0)