mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 10:40:15 +02:00 
			
		
		
		
	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);
 | 
									      struct user_namespace *ns, int cap);
 | 
				
			||||||
extern bool capable(int cap);
 | 
					extern bool capable(int cap);
 | 
				
			||||||
extern bool ns_capable(struct user_namespace *ns, int cap);
 | 
					extern bool ns_capable(struct user_namespace *ns, int cap);
 | 
				
			||||||
 | 
					extern bool ns_capable_noaudit(struct user_namespace *ns, int cap);
 | 
				
			||||||
#else
 | 
					#else
 | 
				
			||||||
static inline bool has_capability(struct task_struct *t, int cap)
 | 
					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;
 | 
						return true;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					static inline bool ns_capable_noaudit(struct user_namespace *ns, int cap)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return true;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
#endif /* CONFIG_MULTIUSER */
 | 
					#endif /* CONFIG_MULTIUSER */
 | 
				
			||||||
extern bool capable_wrt_inode_uidgid(const struct inode *inode, int cap);
 | 
					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);
 | 
					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);
 | 
						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_capable - Determine if the current task has a superior capability in effect
 | 
				
			||||||
 * @ns:  The usernamespace we want the capability in
 | 
					 * @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)
 | 
					bool ns_capable(struct user_namespace *ns, int cap)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	if (unlikely(!cap_valid(cap))) {
 | 
						return ns_capable_common(ns, cap, true);
 | 
				
			||||||
		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;
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
EXPORT_SYMBOL(ns_capable);
 | 
					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
 | 
					 * capable - Determine if the current task has a superior capability in effect
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue