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>
This commit is contained in:
parent
2885c1e3e0
commit
98f368e9e2
2 changed files with 41 additions and 10 deletions
|
@ -206,6 +206,7 @@ extern bool has_ns_capability_noaudit(struct task_struct *t,
|
|||
struct user_namespace *ns, int cap);
|
||||
extern bool capable(int cap);
|
||||
extern bool ns_capable(struct user_namespace *ns, int cap);
|
||||
extern bool ns_capable_noaudit(struct user_namespace *ns, int cap);
|
||||
#else
|
||||
static inline bool has_capability(struct task_struct *t, int cap)
|
||||
{
|
||||
|
@ -233,6 +234,10 @@ static inline bool ns_capable(struct user_namespace *ns, int cap)
|
|||
{
|
||||
return true;
|
||||
}
|
||||
static inline bool ns_capable_noaudit(struct user_namespace *ns, int cap)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
#endif /* CONFIG_MULTIUSER */
|
||||
extern bool capable_wrt_inode_uidgid(const struct inode *inode, int cap);
|
||||
extern bool file_ns_capable(const struct file *file, struct user_namespace *ns, int cap);
|
||||
|
|
|
@ -361,6 +361,24 @@ bool has_capability_noaudit(struct task_struct *t, int cap)
|
|||
return has_ns_capability_noaudit(t, &init_user_ns, cap);
|
||||
}
|
||||
|
||||
static bool ns_capable_common(struct user_namespace *ns, int cap, bool audit)
|
||||
{
|
||||
int capable;
|
||||
|
||||
if (unlikely(!cap_valid(cap))) {
|
||||
pr_crit("capable() called with invalid cap=%u\n", cap);
|
||||
BUG();
|
||||
}
|
||||
|
||||
capable = audit ? security_capable(current_cred(), ns, cap) :
|
||||
security_capable_noaudit(current_cred(), ns, cap);
|
||||
if (capable == 0) {
|
||||
current->flags |= PF_SUPERPRIV;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* ns_capable - Determine if the current task has a superior capability in effect
|
||||
* @ns: The usernamespace we want the capability in
|
||||
|
@ -374,19 +392,27 @@ bool has_capability_noaudit(struct task_struct *t, int cap)
|
|||
*/
|
||||
bool ns_capable(struct user_namespace *ns, int cap)
|
||||
{
|
||||
if (unlikely(!cap_valid(cap))) {
|
||||
pr_crit("capable() called with invalid cap=%u\n", cap);
|
||||
BUG();
|
||||
}
|
||||
|
||||
if (security_capable(current_cred(), ns, cap) == 0) {
|
||||
current->flags |= PF_SUPERPRIV;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
return ns_capable_common(ns, cap, true);
|
||||
}
|
||||
EXPORT_SYMBOL(ns_capable);
|
||||
|
||||
/**
|
||||
* ns_capable_noaudit - Determine if the current task has a superior capability
|
||||
* (unaudited) in effect
|
||||
* @ns: The usernamespace we want the capability in
|
||||
* @cap: The capability to be tested for
|
||||
*
|
||||
* Return true if the current task has the given superior capability currently
|
||||
* available for use, false if not.
|
||||
*
|
||||
* This sets PF_SUPERPRIV on the task if the capability is available on the
|
||||
* assumption that it's about to be used.
|
||||
*/
|
||||
bool ns_capable_noaudit(struct user_namespace *ns, int cap)
|
||||
{
|
||||
return ns_capable_common(ns, cap, false);
|
||||
}
|
||||
EXPORT_SYMBOL(ns_capable_noaudit);
|
||||
|
||||
/**
|
||||
* capable - Determine if the current task has a superior capability in effect
|
||||
|
|
Loading…
Reference in a new issue