mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 10:40:15 +02:00 
			
		
		
		
	fs: Call d_automount with the filesystems creds
Seth Forshee reported a mount regression in nfs autmounts
with "fs: Add user namespace member to struct super_block".
It turns out that the assumption that current->cred is something
reasonable during mount while necessary to improve support of
unprivileged mounts is wrong in the automount path.
To fix the existing filesystems override current->cred with the
init_cred before calling d_automount and restore current->cred after
d_automount completes.
To support unprivileged mounts would require a more nuanced cred
selection, so fail on unprivileged mounts for the time being.  As none
of the filesystems that currently set FS_USERNS_MOUNT implement
d_automount this check is only good for preventing future problems.
Fixes: 6e4eab577a ("fs: Add user namespace member to struct super_block")
Tested-by: Seth Forshee <seth.forshee@canonical.com>
Signed-off-by: "Eric W. Biederman" <ebiederm@xmission.com>
			
			
This commit is contained in:
		
							parent
							
								
									8175435777
								
							
						
					
					
						commit
						aeaa4a79ff
					
				
					 1 changed files with 7 additions and 0 deletions
				
			
		| 
						 | 
					@ -36,6 +36,7 @@
 | 
				
			||||||
#include <linux/posix_acl.h>
 | 
					#include <linux/posix_acl.h>
 | 
				
			||||||
#include <linux/hash.h>
 | 
					#include <linux/hash.h>
 | 
				
			||||||
#include <linux/bitops.h>
 | 
					#include <linux/bitops.h>
 | 
				
			||||||
 | 
					#include <linux/init_task.h>
 | 
				
			||||||
#include <asm/uaccess.h>
 | 
					#include <asm/uaccess.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "internal.h"
 | 
					#include "internal.h"
 | 
				
			||||||
| 
						 | 
					@ -1099,6 +1100,7 @@ static int follow_automount(struct path *path, struct nameidata *nd,
 | 
				
			||||||
			    bool *need_mntput)
 | 
								    bool *need_mntput)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct vfsmount *mnt;
 | 
						struct vfsmount *mnt;
 | 
				
			||||||
 | 
						const struct cred *old_cred;
 | 
				
			||||||
	int err;
 | 
						int err;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (!path->dentry->d_op || !path->dentry->d_op->d_automount)
 | 
						if (!path->dentry->d_op || !path->dentry->d_op->d_automount)
 | 
				
			||||||
| 
						 | 
					@ -1120,11 +1122,16 @@ static int follow_automount(struct path *path, struct nameidata *nd,
 | 
				
			||||||
	    path->dentry->d_inode)
 | 
						    path->dentry->d_inode)
 | 
				
			||||||
		return -EISDIR;
 | 
							return -EISDIR;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (path->dentry->d_sb->s_user_ns != &init_user_ns)
 | 
				
			||||||
 | 
							return -EACCES;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	nd->total_link_count++;
 | 
						nd->total_link_count++;
 | 
				
			||||||
	if (nd->total_link_count >= 40)
 | 
						if (nd->total_link_count >= 40)
 | 
				
			||||||
		return -ELOOP;
 | 
							return -ELOOP;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						old_cred = override_creds(&init_cred);
 | 
				
			||||||
	mnt = path->dentry->d_op->d_automount(path);
 | 
						mnt = path->dentry->d_op->d_automount(path);
 | 
				
			||||||
 | 
						revert_creds(old_cred);
 | 
				
			||||||
	if (IS_ERR(mnt)) {
 | 
						if (IS_ERR(mnt)) {
 | 
				
			||||||
		/*
 | 
							/*
 | 
				
			||||||
		 * The filesystem is allowed to return -EISDIR here to indicate
 | 
							 * The filesystem is allowed to return -EISDIR here to indicate
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue