Cache user_ns in struct cred
If !CONFIG_USERNS, have current_user_ns() defined to (&init_user_ns). Get rid of _current_user_ns. This requires nsown_capable() to be defined in capability.c rather than as static inline in capability.h, so do that. Request_key needs init_user_ns defined at current_user_ns if !CONFIG_USERNS, so forward-declare that in cred.h if !CONFIG_USERNS at current_user_ns() define. Compile-tested with and without CONFIG_USERNS. Signed-off-by: Serge E. Hallyn <serge.hallyn@canonical.com> [ This makes a huge performance difference for acl_permission_check(), up to 30%. And that is one of the hottest kernel functions for loads that are pathname-lookup heavy. ] Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
This commit is contained in:
		
					parent
					
						
							
								381e7863d9
							
						
					
				
			
			
				commit
				
					
						47a150edc2
					
				
			
		
					 4 changed files with 27 additions and 20 deletions
				
			
		| 
						 | 
					@ -546,18 +546,7 @@ extern bool has_capability_noaudit(struct task_struct *t, 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 task_ns_capable(struct task_struct *t, int cap);
 | 
					extern bool task_ns_capable(struct task_struct *t, int cap);
 | 
				
			||||||
 | 
					extern bool nsown_capable(int cap);
 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * nsown_capable - Check superior capability to one's own user_ns
 | 
					 | 
				
			||||||
 * @cap: The capability in question
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * Return true if the current task has the given superior capability
 | 
					 | 
				
			||||||
 * targeted at its own user namespace.
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
static inline bool nsown_capable(int cap)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	return ns_capable(current_user_ns(), cap);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* audit system wants to get cap info from files as well */
 | 
					/* audit system wants to get cap info from files as well */
 | 
				
			||||||
extern int get_vfs_caps_from_disk(const struct dentry *dentry, struct cpu_vfs_cap_data *cpu_caps);
 | 
					extern int get_vfs_caps_from_disk(const struct dentry *dentry, struct cpu_vfs_cap_data *cpu_caps);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -146,6 +146,7 @@ struct cred {
 | 
				
			||||||
	void		*security;	/* subjective LSM security */
 | 
						void		*security;	/* subjective LSM security */
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
	struct user_struct *user;	/* real user ID subscription */
 | 
						struct user_struct *user;	/* real user ID subscription */
 | 
				
			||||||
 | 
						struct user_namespace *user_ns; /* cached user->user_ns */
 | 
				
			||||||
	struct group_info *group_info;	/* supplementary groups for euid/fsgid */
 | 
						struct group_info *group_info;	/* supplementary groups for euid/fsgid */
 | 
				
			||||||
	struct rcu_head	rcu;		/* RCU deletion hook */
 | 
						struct rcu_head	rcu;		/* RCU deletion hook */
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
| 
						 | 
					@ -354,10 +355,15 @@ static inline void put_cred(const struct cred *_cred)
 | 
				
			||||||
#define current_fsgid() 	(current_cred_xxx(fsgid))
 | 
					#define current_fsgid() 	(current_cred_xxx(fsgid))
 | 
				
			||||||
#define current_cap()		(current_cred_xxx(cap_effective))
 | 
					#define current_cap()		(current_cred_xxx(cap_effective))
 | 
				
			||||||
#define current_user()		(current_cred_xxx(user))
 | 
					#define current_user()		(current_cred_xxx(user))
 | 
				
			||||||
#define _current_user_ns()	(current_cred_xxx(user)->user_ns)
 | 
					 | 
				
			||||||
#define current_security()	(current_cred_xxx(security))
 | 
					#define current_security()	(current_cred_xxx(security))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
extern struct user_namespace *current_user_ns(void);
 | 
					#ifdef CONFIG_USER_NS
 | 
				
			||||||
 | 
					#define current_user_ns() (current_cred_xxx(user_ns))
 | 
				
			||||||
 | 
					#else
 | 
				
			||||||
 | 
					extern struct user_namespace init_user_ns;
 | 
				
			||||||
 | 
					#define current_user_ns() (&init_user_ns)
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define current_uid_gid(_uid, _gid)		\
 | 
					#define current_uid_gid(_uid, _gid)		\
 | 
				
			||||||
do {						\
 | 
					do {						\
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -399,3 +399,15 @@ bool task_ns_capable(struct task_struct *t, int cap)
 | 
				
			||||||
	return ns_capable(task_cred_xxx(t, user)->user_ns, cap);
 | 
						return ns_capable(task_cred_xxx(t, user)->user_ns, cap);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
EXPORT_SYMBOL(task_ns_capable);
 | 
					EXPORT_SYMBOL(task_ns_capable);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * nsown_capable - Check superior capability to one's own user_ns
 | 
				
			||||||
 | 
					 * @cap: The capability in question
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Return true if the current task has the given superior capability
 | 
				
			||||||
 | 
					 * targeted at its own user namespace.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					bool nsown_capable(int cap)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return ns_capable(current_user_ns(), cap);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -54,6 +54,7 @@ struct cred init_cred = {
 | 
				
			||||||
	.cap_effective		= CAP_INIT_EFF_SET,
 | 
						.cap_effective		= CAP_INIT_EFF_SET,
 | 
				
			||||||
	.cap_bset		= CAP_INIT_BSET,
 | 
						.cap_bset		= CAP_INIT_BSET,
 | 
				
			||||||
	.user			= INIT_USER,
 | 
						.user			= INIT_USER,
 | 
				
			||||||
 | 
						.user_ns		= &init_user_ns,
 | 
				
			||||||
	.group_info		= &init_groups,
 | 
						.group_info		= &init_groups,
 | 
				
			||||||
#ifdef CONFIG_KEYS
 | 
					#ifdef CONFIG_KEYS
 | 
				
			||||||
	.tgcred			= &init_tgcred,
 | 
						.tgcred			= &init_tgcred,
 | 
				
			||||||
| 
						 | 
					@ -410,6 +411,11 @@ int copy_creds(struct task_struct *p, unsigned long clone_flags)
 | 
				
			||||||
			goto error_put;
 | 
								goto error_put;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* cache user_ns in cred.  Doesn't need a refcount because it will
 | 
				
			||||||
 | 
						 * stay pinned by cred->user
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						new->user_ns = new->user->user_ns;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef CONFIG_KEYS
 | 
					#ifdef CONFIG_KEYS
 | 
				
			||||||
	/* new threads get their own thread keyrings if their parent already
 | 
						/* new threads get their own thread keyrings if their parent already
 | 
				
			||||||
	 * had one */
 | 
						 * had one */
 | 
				
			||||||
| 
						 | 
					@ -741,12 +747,6 @@ int set_create_files_as(struct cred *new, struct inode *inode)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
EXPORT_SYMBOL(set_create_files_as);
 | 
					EXPORT_SYMBOL(set_create_files_as);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct user_namespace *current_user_ns(void)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	return _current_user_ns();
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
EXPORT_SYMBOL(current_user_ns);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#ifdef CONFIG_DEBUG_CREDENTIALS
 | 
					#ifdef CONFIG_DEBUG_CREDENTIALS
 | 
				
			||||||
 | 
					
 | 
				
			||||||
bool creds_are_invalid(const struct cred *cred)
 | 
					bool creds_are_invalid(const struct cred *cred)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue