afs: Fix afs_xattr_get_yfs() to not try freeing an error value
[linux-2.6-microblaze.git] / fs / afs / xattr.c
1 /* Extended attribute handling for AFS.  We use xattrs to get and set metadata
2  * instead of providing pioctl().
3  *
4  * Copyright (C) 2017 Red Hat, Inc. All Rights Reserved.
5  * Written by David Howells (dhowells@redhat.com)
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public Licence
9  * as published by the Free Software Foundation; either version
10  * 2 of the Licence, or (at your option) any later version.
11  */
12
13 #include <linux/slab.h>
14 #include <linux/fs.h>
15 #include <linux/xattr.h>
16 #include "internal.h"
17
18 static const char afs_xattr_list[] =
19         "afs.acl\0"
20         "afs.cell\0"
21         "afs.fid\0"
22         "afs.volume\0"
23         "afs.yfs.acl\0"
24         "afs.yfs.acl_inherited\0"
25         "afs.yfs.acl_num_cleaned\0"
26         "afs.yfs.vol_acl";
27
28 /*
29  * Retrieve a list of the supported xattrs.
30  */
31 ssize_t afs_listxattr(struct dentry *dentry, char *buffer, size_t size)
32 {
33         if (size == 0)
34                 return sizeof(afs_xattr_list);
35         if (size < sizeof(afs_xattr_list))
36                 return -ERANGE;
37         memcpy(buffer, afs_xattr_list, sizeof(afs_xattr_list));
38         return sizeof(afs_xattr_list);
39 }
40
41 /*
42  * Get a file's ACL.
43  */
44 static int afs_xattr_get_acl(const struct xattr_handler *handler,
45                              struct dentry *dentry,
46                              struct inode *inode, const char *name,
47                              void *buffer, size_t size)
48 {
49         struct afs_fs_cursor fc;
50         struct afs_vnode *vnode = AFS_FS_I(inode);
51         struct afs_acl *acl = NULL;
52         struct key *key;
53         int ret;
54
55         key = afs_request_key(vnode->volume->cell);
56         if (IS_ERR(key))
57                 return PTR_ERR(key);
58
59         ret = -ERESTARTSYS;
60         if (afs_begin_vnode_operation(&fc, vnode, key)) {
61                 while (afs_select_fileserver(&fc)) {
62                         fc.cb_break = afs_calc_vnode_cb_break(vnode);
63                         acl = afs_fs_fetch_acl(&fc);
64                 }
65
66                 afs_check_for_remote_deletion(&fc, fc.vnode);
67                 afs_vnode_commit_status(&fc, vnode, fc.cb_break);
68                 ret = afs_end_vnode_operation(&fc);
69         }
70
71         if (ret == 0) {
72                 ret = acl->size;
73                 if (size > 0) {
74                         if (acl->size <= size)
75                                 memcpy(buffer, acl->data, acl->size);
76                         else
77                                 ret = -ERANGE;
78                 }
79                 kfree(acl);
80         }
81
82         key_put(key);
83         return ret;
84 }
85
86 /*
87  * Set a file's AFS3 ACL.
88  */
89 static int afs_xattr_set_acl(const struct xattr_handler *handler,
90                              struct dentry *dentry,
91                              struct inode *inode, const char *name,
92                              const void *buffer, size_t size, int flags)
93 {
94         struct afs_fs_cursor fc;
95         struct afs_vnode *vnode = AFS_FS_I(inode);
96         struct afs_acl *acl = NULL;
97         struct key *key;
98         int ret;
99
100         if (flags == XATTR_CREATE)
101                 return -EINVAL;
102
103         key = afs_request_key(vnode->volume->cell);
104         if (IS_ERR(key))
105                 return PTR_ERR(key);
106
107         acl = kmalloc(sizeof(*acl) + size, GFP_KERNEL);
108         if (!acl) {
109                 key_put(key);
110                 return -ENOMEM;
111         }
112
113         acl->size = size;
114         memcpy(acl->data, buffer, size);
115
116         ret = -ERESTARTSYS;
117         if (afs_begin_vnode_operation(&fc, vnode, key)) {
118                 while (afs_select_fileserver(&fc)) {
119                         fc.cb_break = afs_calc_vnode_cb_break(vnode);
120                         afs_fs_store_acl(&fc, acl);
121                 }
122
123                 afs_check_for_remote_deletion(&fc, fc.vnode);
124                 afs_vnode_commit_status(&fc, vnode, fc.cb_break);
125                 ret = afs_end_vnode_operation(&fc);
126         }
127
128         kfree(acl);
129         key_put(key);
130         return ret;
131 }
132
133 static const struct xattr_handler afs_xattr_afs_acl_handler = {
134         .name   = "afs.acl",
135         .get    = afs_xattr_get_acl,
136         .set    = afs_xattr_set_acl,
137 };
138
139 /*
140  * Get a file's YFS ACL.
141  */
142 static int afs_xattr_get_yfs(const struct xattr_handler *handler,
143                              struct dentry *dentry,
144                              struct inode *inode, const char *name,
145                              void *buffer, size_t size)
146 {
147         struct afs_fs_cursor fc;
148         struct afs_vnode *vnode = AFS_FS_I(inode);
149         struct yfs_acl *yacl = NULL;
150         struct key *key;
151         char buf[16], *data;
152         int which = 0, dsize, ret = -ENOMEM;
153
154         if (strcmp(name, "acl") == 0)
155                 which = 0;
156         else if (strcmp(name, "acl_inherited") == 0)
157                 which = 1;
158         else if (strcmp(name, "acl_num_cleaned") == 0)
159                 which = 2;
160         else if (strcmp(name, "vol_acl") == 0)
161                 which = 3;
162         else
163                 return -EOPNOTSUPP;
164
165         yacl = kzalloc(sizeof(struct yfs_acl), GFP_KERNEL);
166         if (!yacl)
167                 goto error;
168
169         if (which == 0)
170                 yacl->flags |= YFS_ACL_WANT_ACL;
171         else if (which == 3)
172                 yacl->flags |= YFS_ACL_WANT_VOL_ACL;
173
174         key = afs_request_key(vnode->volume->cell);
175         if (IS_ERR(key)) {
176                 ret = PTR_ERR(key);
177                 goto error_yacl;
178         }
179
180         ret = -ERESTARTSYS;
181         if (afs_begin_vnode_operation(&fc, vnode, key)) {
182                 while (afs_select_fileserver(&fc)) {
183                         fc.cb_break = afs_calc_vnode_cb_break(vnode);
184                         yfs_fs_fetch_opaque_acl(&fc, yacl);
185                 }
186
187                 afs_check_for_remote_deletion(&fc, fc.vnode);
188                 afs_vnode_commit_status(&fc, vnode, fc.cb_break);
189                 ret = afs_end_vnode_operation(&fc);
190         }
191
192         if (ret < 0)
193                 goto error_key;
194
195         switch (which) {
196         case 0:
197                 data = yacl->acl->data;
198                 dsize = yacl->acl->size;
199                 break;
200         case 1:
201                 data = buf;
202                 dsize = snprintf(buf, sizeof(buf), "%u", yacl->inherit_flag);
203                 break;
204         case 2:
205                 data = buf;
206                 dsize = snprintf(buf, sizeof(buf), "%u", yacl->num_cleaned);
207                 break;
208         case 3:
209                 data = yacl->vol_acl->data;
210                 dsize = yacl->vol_acl->size;
211                 break;
212         default:
213                 ret = -EOPNOTSUPP;
214                 goto error_key;
215         }
216
217         ret = dsize;
218         if (size > 0) {
219                 if (dsize > size) {
220                         ret = -ERANGE;
221                         goto error_key;
222                 }
223                 memcpy(buffer, data, dsize);
224         }
225
226 error_key:
227         key_put(key);
228 error_yacl:
229         yfs_free_opaque_acl(yacl);
230 error:
231         return ret;
232 }
233
234 /*
235  * Set a file's YFS ACL.
236  */
237 static int afs_xattr_set_yfs(const struct xattr_handler *handler,
238                              struct dentry *dentry,
239                              struct inode *inode, const char *name,
240                              const void *buffer, size_t size, int flags)
241 {
242         struct afs_fs_cursor fc;
243         struct afs_vnode *vnode = AFS_FS_I(inode);
244         struct afs_acl *acl = NULL;
245         struct key *key;
246         int ret;
247
248         if (flags == XATTR_CREATE ||
249             strcmp(name, "acl") != 0)
250                 return -EINVAL;
251
252         key = afs_request_key(vnode->volume->cell);
253         if (IS_ERR(key))
254                 return PTR_ERR(key);
255
256         acl = kmalloc(sizeof(*acl) + size, GFP_KERNEL);
257         if (!acl) {
258                 key_put(key);
259                 return -ENOMEM;
260         }
261
262         acl->size = size;
263         memcpy(acl->data, buffer, size);
264
265         ret = -ERESTARTSYS;
266         if (afs_begin_vnode_operation(&fc, vnode, key)) {
267                 while (afs_select_fileserver(&fc)) {
268                         fc.cb_break = afs_calc_vnode_cb_break(vnode);
269                         yfs_fs_store_opaque_acl2(&fc, acl);
270                 }
271
272                 afs_check_for_remote_deletion(&fc, fc.vnode);
273                 afs_vnode_commit_status(&fc, vnode, fc.cb_break);
274                 ret = afs_end_vnode_operation(&fc);
275         }
276
277         kfree(acl);
278         key_put(key);
279         return ret;
280 }
281
282 static const struct xattr_handler afs_xattr_yfs_handler = {
283         .prefix = "afs.yfs.",
284         .get    = afs_xattr_get_yfs,
285         .set    = afs_xattr_set_yfs,
286 };
287
288 /*
289  * Get the name of the cell on which a file resides.
290  */
291 static int afs_xattr_get_cell(const struct xattr_handler *handler,
292                               struct dentry *dentry,
293                               struct inode *inode, const char *name,
294                               void *buffer, size_t size)
295 {
296         struct afs_vnode *vnode = AFS_FS_I(inode);
297         struct afs_cell *cell = vnode->volume->cell;
298         size_t namelen;
299
300         namelen = cell->name_len;
301         if (size == 0)
302                 return namelen;
303         if (namelen > size)
304                 return -ERANGE;
305         memcpy(buffer, cell->name, namelen);
306         return namelen;
307 }
308
309 static const struct xattr_handler afs_xattr_afs_cell_handler = {
310         .name   = "afs.cell",
311         .get    = afs_xattr_get_cell,
312 };
313
314 /*
315  * Get the volume ID, vnode ID and vnode uniquifier of a file as a sequence of
316  * hex numbers separated by colons.
317  */
318 static int afs_xattr_get_fid(const struct xattr_handler *handler,
319                              struct dentry *dentry,
320                              struct inode *inode, const char *name,
321                              void *buffer, size_t size)
322 {
323         struct afs_vnode *vnode = AFS_FS_I(inode);
324         char text[16 + 1 + 24 + 1 + 8 + 1];
325         size_t len;
326
327         /* The volume ID is 64-bit, the vnode ID is 96-bit and the
328          * uniquifier is 32-bit.
329          */
330         len = sprintf(text, "%llx:", vnode->fid.vid);
331         if (vnode->fid.vnode_hi)
332                 len += sprintf(text + len, "%x%016llx",
333                                vnode->fid.vnode_hi, vnode->fid.vnode);
334         else
335                 len += sprintf(text + len, "%llx", vnode->fid.vnode);
336         len += sprintf(text + len, ":%x", vnode->fid.unique);
337
338         if (size == 0)
339                 return len;
340         if (len > size)
341                 return -ERANGE;
342         memcpy(buffer, text, len);
343         return len;
344 }
345
346 static const struct xattr_handler afs_xattr_afs_fid_handler = {
347         .name   = "afs.fid",
348         .get    = afs_xattr_get_fid,
349 };
350
351 /*
352  * Get the name of the volume on which a file resides.
353  */
354 static int afs_xattr_get_volume(const struct xattr_handler *handler,
355                               struct dentry *dentry,
356                               struct inode *inode, const char *name,
357                               void *buffer, size_t size)
358 {
359         struct afs_vnode *vnode = AFS_FS_I(inode);
360         const char *volname = vnode->volume->name;
361         size_t namelen;
362
363         namelen = strlen(volname);
364         if (size == 0)
365                 return namelen;
366         if (namelen > size)
367                 return -ERANGE;
368         memcpy(buffer, volname, namelen);
369         return namelen;
370 }
371
372 static const struct xattr_handler afs_xattr_afs_volume_handler = {
373         .name   = "afs.volume",
374         .get    = afs_xattr_get_volume,
375 };
376
377 const struct xattr_handler *afs_xattr_handlers[] = {
378         &afs_xattr_afs_acl_handler,
379         &afs_xattr_afs_cell_handler,
380         &afs_xattr_afs_fid_handler,
381         &afs_xattr_afs_volume_handler,
382         &afs_xattr_yfs_handler,         /* afs.yfs. prefix */
383         NULL
384 };