aboutsummaryrefslogtreecommitdiffstats
path: root/fs/afs
diff options
context:
space:
mode:
authorDavid Howells <dhowells@redhat.com>2019-05-12 03:31:23 -0400
committerDavid Howells <dhowells@redhat.com>2019-05-15 12:35:53 -0400
commit773e0c40253443e0ce5491cb0e414b62f7cc45ed (patch)
tree48752e7b9ff1ec36c9baeadc7e4f11ebf16addf7 /fs/afs
parentcc1dd5c85cb70ebe09ccf1cc34f29af65442a10f (diff)
afs: Fix afs_xattr_get_yfs() to not try freeing an error value
afs_xattr_get_yfs() tries to free yacl, which may hold an error value (say if yfs_fs_fetch_opaque_acl() failed and returned an error). Fix this by allocating yacl up front (since it's a fixed-length struct, unlike afs_acl) and passing it in to the RPC function. This also allows the flags to be placed in the object rather than passing them through to the RPC function. Fixes: ae46578b963f ("afs: Get YFS ACLs and information through xattrs") Signed-off-by: David Howells <dhowells@redhat.com>
Diffstat (limited to 'fs/afs')
-rw-r--r--fs/afs/internal.h2
-rw-r--r--fs/afs/xattr.c86
-rw-r--r--fs/afs/yfsclient.c29
3 files changed, 53 insertions, 64 deletions
diff --git a/fs/afs/internal.h b/fs/afs/internal.h
index b3cd6e8ad59d..74ee0f8ef8dd 100644
--- a/fs/afs/internal.h
+++ b/fs/afs/internal.h
@@ -1382,7 +1382,7 @@ struct yfs_acl {
1382}; 1382};
1383 1383
1384extern void yfs_free_opaque_acl(struct yfs_acl *); 1384extern void yfs_free_opaque_acl(struct yfs_acl *);
1385extern struct yfs_acl *yfs_fs_fetch_opaque_acl(struct afs_fs_cursor *, unsigned int); 1385extern struct yfs_acl *yfs_fs_fetch_opaque_acl(struct afs_fs_cursor *, struct yfs_acl *);
1386extern int yfs_fs_store_opaque_acl2(struct afs_fs_cursor *, const struct afs_acl *); 1386extern int yfs_fs_store_opaque_acl2(struct afs_fs_cursor *, const struct afs_acl *);
1387 1387
1388/* 1388/*
diff --git a/fs/afs/xattr.c b/fs/afs/xattr.c
index b6c44e75b361..d12bcda911e1 100644
--- a/fs/afs/xattr.c
+++ b/fs/afs/xattr.c
@@ -148,9 +148,8 @@ static int afs_xattr_get_yfs(const struct xattr_handler *handler,
148 struct afs_vnode *vnode = AFS_FS_I(inode); 148 struct afs_vnode *vnode = AFS_FS_I(inode);
149 struct yfs_acl *yacl = NULL; 149 struct yfs_acl *yacl = NULL;
150 struct key *key; 150 struct key *key;
151 unsigned int flags = 0;
152 char buf[16], *data; 151 char buf[16], *data;
153 int which = 0, dsize, ret; 152 int which = 0, dsize, ret = -ENOMEM;
154 153
155 if (strcmp(name, "acl") == 0) 154 if (strcmp(name, "acl") == 0)
156 which = 0; 155 which = 0;
@@ -163,20 +162,26 @@ static int afs_xattr_get_yfs(const struct xattr_handler *handler,
163 else 162 else
164 return -EOPNOTSUPP; 163 return -EOPNOTSUPP;
165 164
165 yacl = kzalloc(sizeof(struct yfs_acl), GFP_KERNEL);
166 if (!yacl)
167 goto error;
168
166 if (which == 0) 169 if (which == 0)
167 flags |= YFS_ACL_WANT_ACL; 170 yacl->flags |= YFS_ACL_WANT_ACL;
168 else if (which == 3) 171 else if (which == 3)
169 flags |= YFS_ACL_WANT_VOL_ACL; 172 yacl->flags |= YFS_ACL_WANT_VOL_ACL;
170 173
171 key = afs_request_key(vnode->volume->cell); 174 key = afs_request_key(vnode->volume->cell);
172 if (IS_ERR(key)) 175 if (IS_ERR(key)) {
173 return PTR_ERR(key); 176 ret = PTR_ERR(key);
177 goto error_yacl;
178 }
174 179
175 ret = -ERESTARTSYS; 180 ret = -ERESTARTSYS;
176 if (afs_begin_vnode_operation(&fc, vnode, key)) { 181 if (afs_begin_vnode_operation(&fc, vnode, key)) {
177 while (afs_select_fileserver(&fc)) { 182 while (afs_select_fileserver(&fc)) {
178 fc.cb_break = afs_calc_vnode_cb_break(vnode); 183 fc.cb_break = afs_calc_vnode_cb_break(vnode);
179 yacl = yfs_fs_fetch_opaque_acl(&fc, flags); 184 yfs_fs_fetch_opaque_acl(&fc, yacl);
180 } 185 }
181 186
182 afs_check_for_remote_deletion(&fc, fc.vnode); 187 afs_check_for_remote_deletion(&fc, fc.vnode);
@@ -184,44 +189,45 @@ static int afs_xattr_get_yfs(const struct xattr_handler *handler,
184 ret = afs_end_vnode_operation(&fc); 189 ret = afs_end_vnode_operation(&fc);
185 } 190 }
186 191
187 if (ret == 0) { 192 if (ret < 0)
188 switch (which) { 193 goto error_key;
189 case 0: 194
190 data = yacl->acl->data; 195 switch (which) {
191 dsize = yacl->acl->size; 196 case 0:
192 break; 197 data = yacl->acl->data;
193 case 1: 198 dsize = yacl->acl->size;
194 data = buf; 199 break;
195 dsize = snprintf(buf, sizeof(buf), "%u", 200 case 1:
196 yacl->inherit_flag); 201 data = buf;
197 break; 202 dsize = snprintf(buf, sizeof(buf), "%u", yacl->inherit_flag);
198 case 2: 203 break;
199 data = buf; 204 case 2:
200 dsize = snprintf(buf, sizeof(buf), "%u", 205 data = buf;
201 yacl->num_cleaned); 206 dsize = snprintf(buf, sizeof(buf), "%u", yacl->num_cleaned);
202 break; 207 break;
203 case 3: 208 case 3:
204 data = yacl->vol_acl->data; 209 data = yacl->vol_acl->data;
205 dsize = yacl->vol_acl->size; 210 dsize = yacl->vol_acl->size;
206 break; 211 break;
207 default: 212 default:
208 ret = -EOPNOTSUPP; 213 ret = -EOPNOTSUPP;
209 goto out; 214 goto error_key;
210 } 215 }
211 216
212 ret = dsize; 217 ret = dsize;
213 if (size > 0) { 218 if (size > 0) {
214 if (dsize > size) { 219 if (dsize > size) {
215 ret = -ERANGE; 220 ret = -ERANGE;
216 goto out; 221 goto error_key;
217 }
218 memcpy(buffer, data, dsize);
219 } 222 }
223 memcpy(buffer, data, dsize);
220 } 224 }
221 225
222out: 226error_key:
223 yfs_free_opaque_acl(yacl);
224 key_put(key); 227 key_put(key);
228error_yacl:
229 yfs_free_opaque_acl(yacl);
230error:
225 return ret; 231 return ret;
226} 232}
227 233
diff --git a/fs/afs/yfsclient.c b/fs/afs/yfsclient.c
index 6cf7d161baa1..d3e9e3fe0b58 100644
--- a/fs/afs/yfsclient.c
+++ b/fs/afs/yfsclient.c
@@ -2333,12 +2333,6 @@ void yfs_free_opaque_acl(struct yfs_acl *yacl)
2333 } 2333 }
2334} 2334}
2335 2335
2336static void yfs_destroy_fs_fetch_opaque_acl(struct afs_call *call)
2337{
2338 yfs_free_opaque_acl(call->reply[0]);
2339 afs_flat_call_destructor(call);
2340}
2341
2342/* 2336/*
2343 * YFS.FetchOpaqueACL operation type 2337 * YFS.FetchOpaqueACL operation type
2344 */ 2338 */
@@ -2346,18 +2340,17 @@ static const struct afs_call_type yfs_RXYFSFetchOpaqueACL = {
2346 .name = "YFS.FetchOpaqueACL", 2340 .name = "YFS.FetchOpaqueACL",
2347 .op = yfs_FS_FetchOpaqueACL, 2341 .op = yfs_FS_FetchOpaqueACL,
2348 .deliver = yfs_deliver_fs_fetch_opaque_acl, 2342 .deliver = yfs_deliver_fs_fetch_opaque_acl,
2349 .destructor = yfs_destroy_fs_fetch_opaque_acl, 2343 .destructor = afs_flat_call_destructor,
2350}; 2344};
2351 2345
2352/* 2346/*
2353 * Fetch the YFS advanced ACLs for a file. 2347 * Fetch the YFS advanced ACLs for a file.
2354 */ 2348 */
2355struct yfs_acl *yfs_fs_fetch_opaque_acl(struct afs_fs_cursor *fc, 2349struct yfs_acl *yfs_fs_fetch_opaque_acl(struct afs_fs_cursor *fc,
2356 unsigned int flags) 2350 struct yfs_acl *yacl)
2357{ 2351{
2358 struct afs_vnode *vnode = fc->vnode; 2352 struct afs_vnode *vnode = fc->vnode;
2359 struct afs_call *call; 2353 struct afs_call *call;
2360 struct yfs_acl *yacl;
2361 struct afs_net *net = afs_v2net(vnode); 2354 struct afs_net *net = afs_v2net(vnode);
2362 __be32 *bp; 2355 __be32 *bp;
2363 2356
@@ -2370,19 +2363,15 @@ struct yfs_acl *yfs_fs_fetch_opaque_acl(struct afs_fs_cursor *fc,
2370 sizeof(__be32) * 2 + 2363 sizeof(__be32) * 2 +
2371 sizeof(struct yfs_xdr_YFSFetchStatus) + 2364 sizeof(struct yfs_xdr_YFSFetchStatus) +
2372 sizeof(struct yfs_xdr_YFSVolSync)); 2365 sizeof(struct yfs_xdr_YFSVolSync));
2373 if (!call) 2366 if (!call) {
2374 goto nomem; 2367 fc->ac.error = -ENOMEM;
2375 2368 return ERR_PTR(-ENOMEM);
2376 yacl = kzalloc(sizeof(struct yfs_acl), GFP_KERNEL); 2369 }
2377 if (!yacl)
2378 goto nomem_call;
2379 2370
2380 yacl->flags = flags;
2381 call->key = fc->key; 2371 call->key = fc->key;
2382 call->reply[0] = yacl; 2372 call->reply[0] = yacl;
2383 call->reply[1] = vnode; 2373 call->reply[1] = vnode;
2384 call->reply[2] = NULL; /* volsync */ 2374 call->reply[2] = NULL; /* volsync */
2385 call->ret_reply0 = true;
2386 2375
2387 /* marshall the parameters */ 2376 /* marshall the parameters */
2388 bp = call->request; 2377 bp = call->request;
@@ -2396,12 +2385,6 @@ struct yfs_acl *yfs_fs_fetch_opaque_acl(struct afs_fs_cursor *fc,
2396 trace_afs_make_fs_call(call, &vnode->fid); 2385 trace_afs_make_fs_call(call, &vnode->fid);
2397 afs_make_call(&fc->ac, call, GFP_KERNEL); 2386 afs_make_call(&fc->ac, call, GFP_KERNEL);
2398 return (struct yfs_acl *)afs_wait_for_call_to_complete(call, &fc->ac); 2387 return (struct yfs_acl *)afs_wait_for_call_to_complete(call, &fc->ac);
2399
2400nomem_call:
2401 afs_put_call(call);
2402nomem:
2403 fc->ac.error = -ENOMEM;
2404 return ERR_PTR(-ENOMEM);
2405} 2388}
2406 2389
2407/* 2390/*