| From 8a0d551a59ac92d8ff048d6cb29d3a02073e81e8 Mon Sep 17 00:00:00 2001 |
| From: Jeff Layton <jlayton@redhat.com> |
| Date: Tue, 20 Dec 2011 06:57:45 -0500 |
| Subject: nfs: fix regression in handling of context= option in NFSv4 |
| |
| From: Jeff Layton <jlayton@redhat.com> |
| |
| commit 8a0d551a59ac92d8ff048d6cb29d3a02073e81e8 upstream. |
| |
| Setting the security context of a NFSv4 mount via the context= mount |
| option is currently broken. The NFSv4 codepath allocates a parsed |
| options struct, and then parses the mount options to fill it. It |
| eventually calls nfs4_remote_mount which calls security_init_mnt_opts. |
| That clobbers the lsm_opts struct that was populated earlier. This bug |
| also looks like it causes a small memory leak on each v4 mount where |
| context= is used. |
| |
| Fix this by moving the initialization of the lsm_opts into |
| nfs_alloc_parsed_mount_data. Also, add a destructor for |
| nfs_parsed_mount_data to make it easier to free all of the allocations |
| hanging off of it, and to ensure that the security_free_mnt_opts is |
| called whenever security_init_mnt_opts is. |
| |
| I believe this regression was introduced quite some time ago, probably |
| by commit c02d7adf. |
| |
| Signed-off-by: Jeff Layton <jlayton@redhat.com> |
| Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> |
| |
| --- |
| fs/nfs/super.c | 43 +++++++++++++++++++------------------------ |
| 1 file changed, 19 insertions(+), 24 deletions(-) |
| |
| --- a/fs/nfs/super.c |
| +++ b/fs/nfs/super.c |
| @@ -904,10 +904,24 @@ static struct nfs_parsed_mount_data *nfs |
| data->auth_flavor_len = 1; |
| data->version = version; |
| data->minorversion = 0; |
| + security_init_mnt_opts(&data->lsm_opts); |
| } |
| return data; |
| } |
| |
| +static void nfs_free_parsed_mount_data(struct nfs_parsed_mount_data *data) |
| +{ |
| + if (data) { |
| + kfree(data->client_address); |
| + kfree(data->mount_server.hostname); |
| + kfree(data->nfs_server.export_path); |
| + kfree(data->nfs_server.hostname); |
| + kfree(data->fscache_uniq); |
| + security_free_mnt_opts(&data->lsm_opts); |
| + kfree(data); |
| + } |
| +} |
| + |
| /* |
| * Sanity-check a server address provided by the mount command. |
| * |
| @@ -2218,9 +2232,7 @@ static struct dentry *nfs_fs_mount(struc |
| data = nfs_alloc_parsed_mount_data(NFS_DEFAULT_VERSION); |
| mntfh = nfs_alloc_fhandle(); |
| if (data == NULL || mntfh == NULL) |
| - goto out_free_fh; |
| - |
| - security_init_mnt_opts(&data->lsm_opts); |
| + goto out; |
| |
| /* Validate the mount data */ |
| error = nfs_validate_mount_data(raw_data, data, mntfh, dev_name); |
| @@ -2232,8 +2244,6 @@ static struct dentry *nfs_fs_mount(struc |
| #ifdef CONFIG_NFS_V4 |
| if (data->version == 4) { |
| mntroot = nfs4_try_mount(flags, dev_name, data); |
| - kfree(data->client_address); |
| - kfree(data->nfs_server.export_path); |
| goto out; |
| } |
| #endif /* CONFIG_NFS_V4 */ |
| @@ -2284,13 +2294,8 @@ static struct dentry *nfs_fs_mount(struc |
| s->s_flags |= MS_ACTIVE; |
| |
| out: |
| - kfree(data->nfs_server.hostname); |
| - kfree(data->mount_server.hostname); |
| - kfree(data->fscache_uniq); |
| - security_free_mnt_opts(&data->lsm_opts); |
| -out_free_fh: |
| + nfs_free_parsed_mount_data(data); |
| nfs_free_fhandle(mntfh); |
| - kfree(data); |
| return mntroot; |
| |
| out_err_nosb: |
| @@ -2613,9 +2618,7 @@ nfs4_remote_mount(struct file_system_typ |
| |
| mntfh = nfs_alloc_fhandle(); |
| if (data == NULL || mntfh == NULL) |
| - goto out_free_fh; |
| - |
| - security_init_mnt_opts(&data->lsm_opts); |
| + goto out; |
| |
| /* Get a volume representation */ |
| server = nfs4_create_server(data, mntfh); |
| @@ -2663,13 +2666,10 @@ nfs4_remote_mount(struct file_system_typ |
| |
| s->s_flags |= MS_ACTIVE; |
| |
| - security_free_mnt_opts(&data->lsm_opts); |
| nfs_free_fhandle(mntfh); |
| return mntroot; |
| |
| out: |
| - security_free_mnt_opts(&data->lsm_opts); |
| -out_free_fh: |
| nfs_free_fhandle(mntfh); |
| return ERR_PTR(error); |
| |
| @@ -2855,7 +2855,7 @@ static struct dentry *nfs4_mount(struct |
| |
| data = nfs_alloc_parsed_mount_data(4); |
| if (data == NULL) |
| - goto out_free_data; |
| + goto out; |
| |
| /* Validate the mount data */ |
| error = nfs4_validate_mount_data(raw_data, data, dev_name); |
| @@ -2869,12 +2869,7 @@ static struct dentry *nfs4_mount(struct |
| error = PTR_ERR(res); |
| |
| out: |
| - kfree(data->client_address); |
| - kfree(data->nfs_server.export_path); |
| - kfree(data->nfs_server.hostname); |
| - kfree(data->fscache_uniq); |
| -out_free_data: |
| - kfree(data); |
| + nfs_free_parsed_mount_data(data); |
| dprintk("<-- nfs4_mount() = %d%s\n", error, |
| error != 0 ? " [error]" : ""); |
| return res; |