diff options
author | Jeff Layton <jlayton@redhat.com> | 2011-12-20 06:57:45 -0500 |
---|---|---|
committer | Trond Myklebust <Trond.Myklebust@netapp.com> | 2012-01-05 10:42:40 -0500 |
commit | 8a0d551a59ac92d8ff048d6cb29d3a02073e81e8 (patch) | |
tree | df298123c28d66603a80e11728cd5af613ee4730 /fs/nfs | |
parent | 2edb6bc3852c681c0d948245bd55108dc6407604 (diff) |
nfs: fix regression in handling of context= option in NFSv4
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.
Cc: stable@vger.kernel.org
Signed-off-by: Jeff Layton <jlayton@redhat.com>
Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
Diffstat (limited to 'fs/nfs')
-rw-r--r-- | fs/nfs/super.c | 43 |
1 files changed, 19 insertions, 24 deletions
diff --git a/fs/nfs/super.c b/fs/nfs/super.c index 134777406ee3..3ada13c9986a 100644 --- a/fs/nfs/super.c +++ b/fs/nfs/super.c | |||
@@ -909,10 +909,24 @@ static struct nfs_parsed_mount_data *nfs_alloc_parsed_mount_data(unsigned int ve | |||
909 | data->auth_flavor_len = 1; | 909 | data->auth_flavor_len = 1; |
910 | data->version = version; | 910 | data->version = version; |
911 | data->minorversion = 0; | 911 | data->minorversion = 0; |
912 | security_init_mnt_opts(&data->lsm_opts); | ||
912 | } | 913 | } |
913 | return data; | 914 | return data; |
914 | } | 915 | } |
915 | 916 | ||
917 | static void nfs_free_parsed_mount_data(struct nfs_parsed_mount_data *data) | ||
918 | { | ||
919 | if (data) { | ||
920 | kfree(data->client_address); | ||
921 | kfree(data->mount_server.hostname); | ||
922 | kfree(data->nfs_server.export_path); | ||
923 | kfree(data->nfs_server.hostname); | ||
924 | kfree(data->fscache_uniq); | ||
925 | security_free_mnt_opts(&data->lsm_opts); | ||
926 | kfree(data); | ||
927 | } | ||
928 | } | ||
929 | |||
916 | /* | 930 | /* |
917 | * Sanity-check a server address provided by the mount command. | 931 | * Sanity-check a server address provided by the mount command. |
918 | * | 932 | * |
@@ -2220,9 +2234,7 @@ static struct dentry *nfs_fs_mount(struct file_system_type *fs_type, | |||
2220 | data = nfs_alloc_parsed_mount_data(NFS_DEFAULT_VERSION); | 2234 | data = nfs_alloc_parsed_mount_data(NFS_DEFAULT_VERSION); |
2221 | mntfh = nfs_alloc_fhandle(); | 2235 | mntfh = nfs_alloc_fhandle(); |
2222 | if (data == NULL || mntfh == NULL) | 2236 | if (data == NULL || mntfh == NULL) |
2223 | goto out_free_fh; | 2237 | goto out; |
2224 | |||
2225 | security_init_mnt_opts(&data->lsm_opts); | ||
2226 | 2238 | ||
2227 | /* Validate the mount data */ | 2239 | /* Validate the mount data */ |
2228 | error = nfs_validate_mount_data(raw_data, data, mntfh, dev_name); | 2240 | error = nfs_validate_mount_data(raw_data, data, mntfh, dev_name); |
@@ -2234,8 +2246,6 @@ static struct dentry *nfs_fs_mount(struct file_system_type *fs_type, | |||
2234 | #ifdef CONFIG_NFS_V4 | 2246 | #ifdef CONFIG_NFS_V4 |
2235 | if (data->version == 4) { | 2247 | if (data->version == 4) { |
2236 | mntroot = nfs4_try_mount(flags, dev_name, data); | 2248 | mntroot = nfs4_try_mount(flags, dev_name, data); |
2237 | kfree(data->client_address); | ||
2238 | kfree(data->nfs_server.export_path); | ||
2239 | goto out; | 2249 | goto out; |
2240 | } | 2250 | } |
2241 | #endif /* CONFIG_NFS_V4 */ | 2251 | #endif /* CONFIG_NFS_V4 */ |
@@ -2290,13 +2300,8 @@ static struct dentry *nfs_fs_mount(struct file_system_type *fs_type, | |||
2290 | s->s_flags |= MS_ACTIVE; | 2300 | s->s_flags |= MS_ACTIVE; |
2291 | 2301 | ||
2292 | out: | 2302 | out: |
2293 | kfree(data->nfs_server.hostname); | 2303 | nfs_free_parsed_mount_data(data); |
2294 | kfree(data->mount_server.hostname); | ||
2295 | kfree(data->fscache_uniq); | ||
2296 | security_free_mnt_opts(&data->lsm_opts); | ||
2297 | out_free_fh: | ||
2298 | nfs_free_fhandle(mntfh); | 2304 | nfs_free_fhandle(mntfh); |
2299 | kfree(data); | ||
2300 | return mntroot; | 2305 | return mntroot; |
2301 | 2306 | ||
2302 | out_err_nosb: | 2307 | out_err_nosb: |
@@ -2623,9 +2628,7 @@ nfs4_remote_mount(struct file_system_type *fs_type, int flags, | |||
2623 | 2628 | ||
2624 | mntfh = nfs_alloc_fhandle(); | 2629 | mntfh = nfs_alloc_fhandle(); |
2625 | if (data == NULL || mntfh == NULL) | 2630 | if (data == NULL || mntfh == NULL) |
2626 | goto out_free_fh; | 2631 | goto out; |
2627 | |||
2628 | security_init_mnt_opts(&data->lsm_opts); | ||
2629 | 2632 | ||
2630 | /* Get a volume representation */ | 2633 | /* Get a volume representation */ |
2631 | server = nfs4_create_server(data, mntfh); | 2634 | server = nfs4_create_server(data, mntfh); |
@@ -2677,13 +2680,10 @@ nfs4_remote_mount(struct file_system_type *fs_type, int flags, | |||
2677 | 2680 | ||
2678 | s->s_flags |= MS_ACTIVE; | 2681 | s->s_flags |= MS_ACTIVE; |
2679 | 2682 | ||
2680 | security_free_mnt_opts(&data->lsm_opts); | ||
2681 | nfs_free_fhandle(mntfh); | 2683 | nfs_free_fhandle(mntfh); |
2682 | return mntroot; | 2684 | return mntroot; |
2683 | 2685 | ||
2684 | out: | 2686 | out: |
2685 | security_free_mnt_opts(&data->lsm_opts); | ||
2686 | out_free_fh: | ||
2687 | nfs_free_fhandle(mntfh); | 2687 | nfs_free_fhandle(mntfh); |
2688 | return ERR_PTR(error); | 2688 | return ERR_PTR(error); |
2689 | 2689 | ||
@@ -2838,7 +2838,7 @@ static struct dentry *nfs4_mount(struct file_system_type *fs_type, | |||
2838 | 2838 | ||
2839 | data = nfs_alloc_parsed_mount_data(4); | 2839 | data = nfs_alloc_parsed_mount_data(4); |
2840 | if (data == NULL) | 2840 | if (data == NULL) |
2841 | goto out_free_data; | 2841 | goto out; |
2842 | 2842 | ||
2843 | /* Validate the mount data */ | 2843 | /* Validate the mount data */ |
2844 | error = nfs4_validate_mount_data(raw_data, data, dev_name); | 2844 | error = nfs4_validate_mount_data(raw_data, data, dev_name); |
@@ -2852,12 +2852,7 @@ static struct dentry *nfs4_mount(struct file_system_type *fs_type, | |||
2852 | error = PTR_ERR(res); | 2852 | error = PTR_ERR(res); |
2853 | 2853 | ||
2854 | out: | 2854 | out: |
2855 | kfree(data->client_address); | 2855 | nfs_free_parsed_mount_data(data); |
2856 | kfree(data->nfs_server.export_path); | ||
2857 | kfree(data->nfs_server.hostname); | ||
2858 | kfree(data->fscache_uniq); | ||
2859 | out_free_data: | ||
2860 | kfree(data); | ||
2861 | dprintk("<-- nfs4_mount() = %d%s\n", error, | 2856 | dprintk("<-- nfs4_mount() = %d%s\n", error, |
2862 | error != 0 ? " [error]" : ""); | 2857 | error != 0 ? " [error]" : ""); |
2863 | return res; | 2858 | return res; |