ACK: [PATCH][SRU][Disco] UBUNTU: SAUCE: shiftfs: prevent use-after-free when verifying mount options

Stefan Bader stefan.bader at canonical.com
Mon Apr 15 13:51:56 UTC 2019


On 15.04.19 15:21, Christian Brauner wrote:
> BugLink: https://bugs.launchpad.net/ubuntu/+source/linux/+bug/1824735
> 
> Copy up the passthrough mount settings of the mark mount point to the
> shiftfs overlay.
> 
> Before this commit we used to keep a reference to the shiftfs mark
> mount's shiftfs_super_info which was stashed in the superblock of the
> mark mount. The problem is that we only take a reference to the mount of
> the underlay, i.e. the filesystem that is *under* the shiftfs mark
> mount. This means when someone performs a shiftfs mark mount, then a
> shiftfs overlay mount and then immediately unmounts the shiftfs mark
> mount we muck with invalid memory since shiftfs_put_super might have
> already been called freeing that memory.
> 
> Another solution would be to start reference counting. But this would be
> overkill. We only care about the passthrough mount option of the mark
> mount. And we only need it to verify that on remount the new passthrough
> options of the shiftfs overlay are a subset of the mark mount's
> passthrough options. In other scenarios we don't care. So copying up is
> good enough and also only needs to happen once on mount, i.e. when a new
> superblock is created and the .fill_super method is called.
> 
> Signed-off-by: Christian Brauner <christian.brauner at ubuntu.com>
Acked-by: Stefan Bader <stefan.bader at canonical.com>
> ---
>  fs/shiftfs.c | 29 ++++++++++++++++++-----------
>  1 file changed, 18 insertions(+), 11 deletions(-)
> 
> diff --git a/fs/shiftfs.c b/fs/shiftfs.c
> index 8e064756ea0c..4c8a6ec2a617 100644
> --- a/fs/shiftfs.c
> +++ b/fs/shiftfs.c
> @@ -28,7 +28,7 @@ struct shiftfs_super_info {
>  	const struct cred *creator_cred;
>  	bool mark;
>  	unsigned int passthrough;
> -	struct shiftfs_super_info *info_mark;
> +	unsigned int passthrough_mark;
>  };
>  
>  struct shiftfs_file_info {
> @@ -52,10 +52,6 @@ static inline bool shiftfs_passthrough_ioctls(struct shiftfs_super_info *info)
>  	if (!(info->passthrough & SHIFTFS_PASSTHROUGH_IOCTL))
>  		return false;
>  
> -	if (info->info_mark &&
> -	    !(info->info_mark->passthrough & SHIFTFS_PASSTHROUGH_IOCTL))
> -		return false;
> -
>  	return true;
>  }
>  
> @@ -64,10 +60,6 @@ static inline bool shiftfs_passthrough_statfs(struct shiftfs_super_info *info)
>  	if (!(info->passthrough & SHIFTFS_PASSTHROUGH_STAT))
>  		return false;
>  
> -	if (info->info_mark &&
> -	    !(info->info_mark->passthrough & SHIFTFS_PASSTHROUGH_STAT))
> -		return false;
> -
>  	return true;
>  }
>  
> @@ -1824,7 +1816,7 @@ static int shiftfs_remount(struct super_block *sb, int *flags, char *data)
>  
>  	if (info->passthrough != new.passthrough) {
>  		/* Don't allow exceeding passthrough options of mark mount. */
> -		if (!passthrough_is_subset(info->info_mark->passthrough,
> +		if (!passthrough_is_subset(info->passthrough_mark,
>  					   info->passthrough))
>  			return -EPERM;
>  
> @@ -1926,9 +1918,19 @@ static int shiftfs_fill_super(struct super_block *sb, void *raw_data,
>  
>  			sbinfo->mnt = mntget(sbinfo_mp->mnt);
>  			dentry = dget(path.dentry->d_fsdata);
> +			/*
> +			 * Copy up the passthrough mount options from the
> +			 * parent mark mountpoint.
> +			 */
> +			sbinfo->passthrough_mark = sbinfo_mp->passthrough_mark;
>  		} else {
>  			sbinfo->mnt = mntget(path.mnt);
>  			dentry = dget(path.dentry);
> +			/*
> +			 * For a new mark passthrough_mark and passthrough
> +			 * are identical.
> +			 */
> +			sbinfo->passthrough_mark = sbinfo->passthrough;
>  		}
>  
>  		sbinfo->creator_cred = prepare_creds();
> @@ -1956,7 +1958,12 @@ static int shiftfs_fill_super(struct super_block *sb, void *raw_data,
>  		sbinfo->mnt = mntget(sbinfo_mp->mnt);
>  		sbinfo->creator_cred = get_cred(sbinfo_mp->creator_cred);
>  		dentry = dget(path.dentry->d_fsdata);
> -		sbinfo->info_mark = sbinfo_mp;
> +		/*
> +		 * Copy up passthrough settings from mark mountpoint so we can
> +		 * verify when the overlay wants to remount with different
> +		 * passthrough settings.
> +		 */
> +		sbinfo->passthrough_mark = sbinfo_mp->passthrough;
>  	}
>  
>  	sb->s_stack_depth = dentry->d_sb->s_stack_depth + 1;
> 


-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 833 bytes
Desc: OpenPGP digital signature
URL: <https://lists.ubuntu.com/archives/kernel-team/attachments/20190415/5ec54610/attachment.sig>


More information about the kernel-team mailing list