]>
Commit | Line | Data |
---|---|---|
7b5b1623 GKH |
1 | From 8a0d551a59ac92d8ff048d6cb29d3a02073e81e8 Mon Sep 17 00:00:00 2001 |
2 | From: Jeff Layton <jlayton@redhat.com> | |
3 | Date: Tue, 20 Dec 2011 06:57:45 -0500 | |
4 | Subject: nfs: fix regression in handling of context= option in NFSv4 | |
5 | ||
6 | From: Jeff Layton <jlayton@redhat.com> | |
7 | ||
8 | commit 8a0d551a59ac92d8ff048d6cb29d3a02073e81e8 upstream. | |
9 | ||
10 | Setting the security context of a NFSv4 mount via the context= mount | |
11 | option is currently broken. The NFSv4 codepath allocates a parsed | |
12 | options struct, and then parses the mount options to fill it. It | |
13 | eventually calls nfs4_remote_mount which calls security_init_mnt_opts. | |
14 | That clobbers the lsm_opts struct that was populated earlier. This bug | |
15 | also looks like it causes a small memory leak on each v4 mount where | |
16 | context= is used. | |
17 | ||
18 | Fix this by moving the initialization of the lsm_opts into | |
19 | nfs_alloc_parsed_mount_data. Also, add a destructor for | |
20 | nfs_parsed_mount_data to make it easier to free all of the allocations | |
21 | hanging off of it, and to ensure that the security_free_mnt_opts is | |
22 | called whenever security_init_mnt_opts is. | |
23 | ||
24 | I believe this regression was introduced quite some time ago, probably | |
25 | by commit c02d7adf. | |
26 | ||
27 | Signed-off-by: Jeff Layton <jlayton@redhat.com> | |
28 | Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com> | |
29 | Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> | |
30 | ||
31 | --- | |
32 | fs/nfs/super.c | 43 +++++++++++++++++++------------------------ | |
33 | 1 file changed, 19 insertions(+), 24 deletions(-) | |
34 | ||
35 | --- a/fs/nfs/super.c | |
36 | +++ b/fs/nfs/super.c | |
37 | @@ -909,10 +909,24 @@ static struct nfs_parsed_mount_data *nfs | |
38 | data->auth_flavor_len = 1; | |
39 | data->version = version; | |
40 | data->minorversion = 0; | |
41 | + security_init_mnt_opts(&data->lsm_opts); | |
42 | } | |
43 | return data; | |
44 | } | |
45 | ||
46 | +static void nfs_free_parsed_mount_data(struct nfs_parsed_mount_data *data) | |
47 | +{ | |
48 | + if (data) { | |
49 | + kfree(data->client_address); | |
50 | + kfree(data->mount_server.hostname); | |
51 | + kfree(data->nfs_server.export_path); | |
52 | + kfree(data->nfs_server.hostname); | |
53 | + kfree(data->fscache_uniq); | |
54 | + security_free_mnt_opts(&data->lsm_opts); | |
55 | + kfree(data); | |
56 | + } | |
57 | +} | |
58 | + | |
59 | /* | |
60 | * Sanity-check a server address provided by the mount command. | |
61 | * | |
62 | @@ -2220,9 +2234,7 @@ static struct dentry *nfs_fs_mount(struc | |
63 | data = nfs_alloc_parsed_mount_data(NFS_DEFAULT_VERSION); | |
64 | mntfh = nfs_alloc_fhandle(); | |
65 | if (data == NULL || mntfh == NULL) | |
66 | - goto out_free_fh; | |
67 | - | |
68 | - security_init_mnt_opts(&data->lsm_opts); | |
69 | + goto out; | |
70 | ||
71 | /* Validate the mount data */ | |
72 | error = nfs_validate_mount_data(raw_data, data, mntfh, dev_name); | |
73 | @@ -2234,8 +2246,6 @@ static struct dentry *nfs_fs_mount(struc | |
74 | #ifdef CONFIG_NFS_V4 | |
75 | if (data->version == 4) { | |
76 | mntroot = nfs4_try_mount(flags, dev_name, data); | |
77 | - kfree(data->client_address); | |
78 | - kfree(data->nfs_server.export_path); | |
79 | goto out; | |
80 | } | |
81 | #endif /* CONFIG_NFS_V4 */ | |
82 | @@ -2290,13 +2300,8 @@ static struct dentry *nfs_fs_mount(struc | |
83 | s->s_flags |= MS_ACTIVE; | |
84 | ||
85 | out: | |
86 | - kfree(data->nfs_server.hostname); | |
87 | - kfree(data->mount_server.hostname); | |
88 | - kfree(data->fscache_uniq); | |
89 | - security_free_mnt_opts(&data->lsm_opts); | |
90 | -out_free_fh: | |
91 | + nfs_free_parsed_mount_data(data); | |
92 | nfs_free_fhandle(mntfh); | |
93 | - kfree(data); | |
94 | return mntroot; | |
95 | ||
96 | out_err_nosb: | |
97 | @@ -2623,9 +2628,7 @@ nfs4_remote_mount(struct file_system_typ | |
98 | ||
99 | mntfh = nfs_alloc_fhandle(); | |
100 | if (data == NULL || mntfh == NULL) | |
101 | - goto out_free_fh; | |
102 | - | |
103 | - security_init_mnt_opts(&data->lsm_opts); | |
104 | + goto out; | |
105 | ||
106 | /* Get a volume representation */ | |
107 | server = nfs4_create_server(data, mntfh); | |
108 | @@ -2677,13 +2680,10 @@ nfs4_remote_mount(struct file_system_typ | |
109 | ||
110 | s->s_flags |= MS_ACTIVE; | |
111 | ||
112 | - security_free_mnt_opts(&data->lsm_opts); | |
113 | nfs_free_fhandle(mntfh); | |
114 | return mntroot; | |
115 | ||
116 | out: | |
117 | - security_free_mnt_opts(&data->lsm_opts); | |
118 | -out_free_fh: | |
119 | nfs_free_fhandle(mntfh); | |
120 | return ERR_PTR(error); | |
121 | ||
122 | @@ -2838,7 +2838,7 @@ static struct dentry *nfs4_mount(struct | |
123 | ||
124 | data = nfs_alloc_parsed_mount_data(4); | |
125 | if (data == NULL) | |
126 | - goto out_free_data; | |
127 | + goto out; | |
128 | ||
129 | /* Validate the mount data */ | |
130 | error = nfs4_validate_mount_data(raw_data, data, dev_name); | |
131 | @@ -2852,12 +2852,7 @@ static struct dentry *nfs4_mount(struct | |
132 | error = PTR_ERR(res); | |
133 | ||
134 | out: | |
135 | - kfree(data->client_address); | |
136 | - kfree(data->nfs_server.export_path); | |
137 | - kfree(data->nfs_server.hostname); | |
138 | - kfree(data->fscache_uniq); | |
139 | -out_free_data: | |
140 | - kfree(data); | |
141 | + nfs_free_parsed_mount_data(data); | |
142 | dprintk("<-- nfs4_mount() = %d%s\n", error, | |
143 | error != 0 ? " [error]" : ""); | |
144 | return res; |