1 // SPDX-License-Identifier: GPL-2.0
2 /*
3 * (C) 2001 Clemson University and The University of Chicago
4 * Copyright 2018 Omnibond Systems, L.L.C.
5 *
6 * See COPYING in top-level directory.
7 */
8
9 /*
10 * Linux VFS extended attribute operations.
11 */
12
13 #include "protocol.h"
14 #include "orangefs-kernel.h"
15 #include "orangefs-bufmap.h"
16 #include <linux/posix_acl_xattr.h>
17 #include <linux/xattr.h>
18 #include <linux/hashtable.h>
19
20 #define SYSTEM_ORANGEFS_KEY "system.pvfs2."
21 #define SYSTEM_ORANGEFS_KEY_LEN 13
22
23 /*
24 * this function returns
25 * 0 if the key corresponding to name is not meant to be printed as part
26 * of a listxattr.
27 * 1 if the key corresponding to name is meant to be returned as part of
28 * a listxattr.
29 * The ones that start SYSTEM_ORANGEFS_KEY are the ones to avoid printing.
30 */
is_reserved_key(const char * key,size_t size)31 static int is_reserved_key(const char *key, size_t size)
32 {
33
34 if (size < SYSTEM_ORANGEFS_KEY_LEN)
35 return 1;
36
37 return strncmp(key, SYSTEM_ORANGEFS_KEY, SYSTEM_ORANGEFS_KEY_LEN) ? 1 : 0;
38 }
39
convert_to_internal_xattr_flags(int setxattr_flags)40 static inline int convert_to_internal_xattr_flags(int setxattr_flags)
41 {
42 int internal_flag = 0;
43
44 if (setxattr_flags & XATTR_REPLACE) {
45 /* Attribute must exist! */
46 internal_flag = ORANGEFS_XATTR_REPLACE;
47 } else if (setxattr_flags & XATTR_CREATE) {
48 /* Attribute must not exist */
49 internal_flag = ORANGEFS_XATTR_CREATE;
50 }
51 return internal_flag;
52 }
53
xattr_key(const char * key)54 static unsigned int xattr_key(const char *key)
55 {
56 unsigned int i = 0;
57 if (!key)
58 return 0;
59 while (*key)
60 i += *key++;
61 return i % 16;
62 }
63
find_cached_xattr(struct inode * inode,const char * key)64 static struct orangefs_cached_xattr *find_cached_xattr(struct inode *inode,
65 const char *key)
66 {
67 struct orangefs_inode_s *orangefs_inode = ORANGEFS_I(inode);
68 struct orangefs_cached_xattr *cx;
69 struct hlist_head *h;
70 struct hlist_node *tmp;
71 h = &orangefs_inode->xattr_cache[xattr_key(key)];
72 if (hlist_empty(h))
73 return NULL;
74 hlist_for_each_entry_safe(cx, tmp, h, node) {
75 /* if (!time_before(jiffies, cx->timeout)) {
76 hlist_del(&cx->node);
77 kfree(cx);
78 continue;
79 }*/
80 if (!strcmp(cx->key, key))
81 return cx;
82 }
83 return NULL;
84 }
85
86 /*
87 * Tries to get a specified key's attributes of a given
88 * file into a user-specified buffer. Note that the getxattr
89 * interface allows for the users to probe the size of an
90 * extended attribute by passing in a value of 0 to size.
91 * Thus our return value is always the size of the attribute
92 * unless the key does not exist for the file and/or if
93 * there were errors in fetching the attribute value.
94 */
orangefs_inode_getxattr(struct inode * inode,const char * name,void * buffer,size_t size)95 ssize_t orangefs_inode_getxattr(struct inode *inode, const char *name,
96 void *buffer, size_t size)
97 {
98 struct orangefs_inode_s *orangefs_inode = ORANGEFS_I(inode);
99 struct orangefs_kernel_op_s *new_op = NULL;
100 struct orangefs_cached_xattr *cx;
101 ssize_t ret = -ENOMEM;
102 ssize_t length = 0;
103 int fsuid;
104 int fsgid;
105
106 gossip_debug(GOSSIP_XATTR_DEBUG,
107 "%s: name %s, buffer_size %zd\n",
108 __func__, name, size);
109
110 if (S_ISLNK(inode->i_mode))
111 return -EOPNOTSUPP;
112
113 if (strlen(name) >= ORANGEFS_MAX_XATTR_NAMELEN)
114 return -EINVAL;
115
116 fsuid = from_kuid(&init_user_ns, current_fsuid());
117 fsgid = from_kgid(&init_user_ns, current_fsgid());
118
119 gossip_debug(GOSSIP_XATTR_DEBUG,
120 "getxattr on inode %pU, name %s "
121 "(uid %o, gid %o)\n",
122 get_khandle_from_ino(inode),
123 name,
124 fsuid,
125 fsgid);
126
127 down_read(&orangefs_inode->xattr_sem);
128
129 cx = find_cached_xattr(inode, name);
130 if (cx && time_before(jiffies, cx->timeout)) {
131 if (cx->length == -1) {
132 ret = -ENODATA;
133 goto out_unlock;
134 } else {
135 if (size == 0) {
136 ret = cx->length;
137 goto out_unlock;
138 }
139 if (cx->length > size) {
140 ret = -ERANGE;
141 goto out_unlock;
142 }
143 memcpy(buffer, cx->val, cx->length);
144 memset(buffer + cx->length, 0, size - cx->length);
145 ret = cx->length;
146 goto out_unlock;
147 }
148 }
149
150 new_op = op_alloc(ORANGEFS_VFS_OP_GETXATTR);
151 if (!new_op)
152 goto out_unlock;
153
154 new_op->upcall.req.getxattr.refn = orangefs_inode->refn;
155 strcpy(new_op->upcall.req.getxattr.key, name);
156
157 /*
158 * NOTE: Although keys are meant to be NULL terminated textual
159 * strings, I am going to explicitly pass the length just in case
160 * we change this later on...
161 */
162 new_op->upcall.req.getxattr.key_sz = strlen(name) + 1;
163
164 ret = service_operation(new_op, "orangefs_inode_getxattr",
165 get_interruptible_flag(inode));
166 if (ret != 0) {
167 if (ret == -ENOENT) {
168 ret = -ENODATA;
169 gossip_debug(GOSSIP_XATTR_DEBUG,
170 "orangefs_inode_getxattr: inode %pU key %s"
171 " does not exist!\n",
172 get_khandle_from_ino(inode),
173 (char *)new_op->upcall.req.getxattr.key);
174 cx = kmalloc(sizeof *cx, GFP_KERNEL);
175 if (cx) {
176 strcpy(cx->key, name);
177 cx->length = -1;
178 cx->timeout = jiffies +
179 orangefs_getattr_timeout_msecs*HZ/1000;
180 hlist_add_head( &cx->node,
181 &orangefs_inode->xattr_cache[xattr_key(cx->key)]);
182 }
183 }
184 goto out_release_op;
185 }
186
187 /*
188 * Length returned includes null terminator.
189 */
190 length = new_op->downcall.resp.getxattr.val_sz;
191
192 /*
193 * Just return the length of the queried attribute.
194 */
195 if (size == 0) {
196 ret = length;
197 goto out_release_op;
198 }
199
200 /*
201 * Check to see if key length is > provided buffer size.
202 */
203 if (length > size) {
204 ret = -ERANGE;
205 goto out_release_op;
206 }
207
208 memcpy(buffer, new_op->downcall.resp.getxattr.val, length);
209 memset(buffer + length, 0, size - length);
210 gossip_debug(GOSSIP_XATTR_DEBUG,
211 "orangefs_inode_getxattr: inode %pU "
212 "key %s key_sz %d, val_len %d\n",
213 get_khandle_from_ino(inode),
214 (char *)new_op->
215 upcall.req.getxattr.key,
216 (int)new_op->
217 upcall.req.getxattr.key_sz,
218 (int)ret);
219
220 ret = length;
221
222 if (cx) {
223 strcpy(cx->key, name);
224 memcpy(cx->val, buffer, length);
225 cx->length = length;
226 cx->timeout = jiffies + HZ;
227 } else {
228 cx = kmalloc(sizeof *cx, GFP_KERNEL);
229 if (cx) {
230 strcpy(cx->key, name);
231 memcpy(cx->val, buffer, length);
232 cx->length = length;
233 cx->timeout = jiffies + HZ;
234 hlist_add_head(&cx->node,
235 &orangefs_inode->xattr_cache[xattr_key(cx->key)]);
236 }
237 }
238
239 out_release_op:
240 op_release(new_op);
241 out_unlock:
242 up_read(&orangefs_inode->xattr_sem);
243 return ret;
244 }
245
orangefs_inode_removexattr(struct inode * inode,const char * name,int flags)246 static int orangefs_inode_removexattr(struct inode *inode, const char *name,
247 int flags)
248 {
249 struct orangefs_inode_s *orangefs_inode = ORANGEFS_I(inode);
250 struct orangefs_kernel_op_s *new_op = NULL;
251 struct orangefs_cached_xattr *cx;
252 struct hlist_head *h;
253 struct hlist_node *tmp;
254 int ret = -ENOMEM;
255
256 if (strlen(name) >= ORANGEFS_MAX_XATTR_NAMELEN)
257 return -EINVAL;
258
259 down_write(&orangefs_inode->xattr_sem);
260 new_op = op_alloc(ORANGEFS_VFS_OP_REMOVEXATTR);
261 if (!new_op)
262 goto out_unlock;
263
264 new_op->upcall.req.removexattr.refn = orangefs_inode->refn;
265 /*
266 * NOTE: Although keys are meant to be NULL terminated
267 * textual strings, I am going to explicitly pass the
268 * length just in case we change this later on...
269 */
270 strcpy(new_op->upcall.req.removexattr.key, name);
271 new_op->upcall.req.removexattr.key_sz = strlen(name) + 1;
272
273 gossip_debug(GOSSIP_XATTR_DEBUG,
274 "orangefs_inode_removexattr: key %s, key_sz %d\n",
275 (char *)new_op->upcall.req.removexattr.key,
276 (int)new_op->upcall.req.removexattr.key_sz);
277
278 ret = service_operation(new_op,
279 "orangefs_inode_removexattr",
280 get_interruptible_flag(inode));
281 if (ret == -ENOENT) {
282 /*
283 * Request to replace a non-existent attribute is an error.
284 */
285 if (flags & XATTR_REPLACE)
286 ret = -ENODATA;
287 else
288 ret = 0;
289 }
290
291 gossip_debug(GOSSIP_XATTR_DEBUG,
292 "orangefs_inode_removexattr: returning %d\n", ret);
293
294 op_release(new_op);
295
296 h = &orangefs_inode->xattr_cache[xattr_key(name)];
297 hlist_for_each_entry_safe(cx, tmp, h, node) {
298 if (!strcmp(cx->key, name)) {
299 hlist_del(&cx->node);
300 kfree(cx);
301 break;
302 }
303 }
304
305 out_unlock:
306 up_write(&orangefs_inode->xattr_sem);
307 return ret;
308 }
309
310 /*
311 * Tries to set an attribute for a given key on a file.
312 *
313 * Returns a -ve number on error and 0 on success. Key is text, but value
314 * can be binary!
315 */
orangefs_inode_setxattr(struct inode * inode,const char * name,const void * value,size_t size,int flags)316 int orangefs_inode_setxattr(struct inode *inode, const char *name,
317 const void *value, size_t size, int flags)
318 {
319 struct orangefs_inode_s *orangefs_inode = ORANGEFS_I(inode);
320 struct orangefs_kernel_op_s *new_op;
321 int internal_flag = 0;
322 struct orangefs_cached_xattr *cx;
323 struct hlist_head *h;
324 struct hlist_node *tmp;
325 int ret = -ENOMEM;
326
327 gossip_debug(GOSSIP_XATTR_DEBUG,
328 "%s: name %s, buffer_size %zd\n",
329 __func__, name, size);
330
331 if (size > ORANGEFS_MAX_XATTR_VALUELEN)
332 return -EINVAL;
333 if (strlen(name) >= ORANGEFS_MAX_XATTR_NAMELEN)
334 return -EINVAL;
335
336 internal_flag = convert_to_internal_xattr_flags(flags);
337
338 /* This is equivalent to a removexattr */
339 if (size == 0 && !value) {
340 gossip_debug(GOSSIP_XATTR_DEBUG,
341 "removing xattr (%s)\n",
342 name);
343 return orangefs_inode_removexattr(inode, name, flags);
344 }
345
346 gossip_debug(GOSSIP_XATTR_DEBUG,
347 "setxattr on inode %pU, name %s\n",
348 get_khandle_from_ino(inode),
349 name);
350
351 down_write(&orangefs_inode->xattr_sem);
352 new_op = op_alloc(ORANGEFS_VFS_OP_SETXATTR);
353 if (!new_op)
354 goto out_unlock;
355
356
357 new_op->upcall.req.setxattr.refn = orangefs_inode->refn;
358 new_op->upcall.req.setxattr.flags = internal_flag;
359 /*
360 * NOTE: Although keys are meant to be NULL terminated textual
361 * strings, I am going to explicitly pass the length just in
362 * case we change this later on...
363 */
364 strcpy(new_op->upcall.req.setxattr.keyval.key, name);
365 new_op->upcall.req.setxattr.keyval.key_sz = strlen(name) + 1;
366 memcpy(new_op->upcall.req.setxattr.keyval.val, value, size);
367 new_op->upcall.req.setxattr.keyval.val_sz = size;
368
369 gossip_debug(GOSSIP_XATTR_DEBUG,
370 "orangefs_inode_setxattr: key %s, key_sz %d "
371 " value size %zd\n",
372 (char *)new_op->upcall.req.setxattr.keyval.key,
373 (int)new_op->upcall.req.setxattr.keyval.key_sz,
374 size);
375
376 ret = service_operation(new_op,
377 "orangefs_inode_setxattr",
378 get_interruptible_flag(inode));
379
380 gossip_debug(GOSSIP_XATTR_DEBUG,
381 "orangefs_inode_setxattr: returning %d\n",
382 ret);
383
384 /* when request is serviced properly, free req op struct */
385 op_release(new_op);
386
387 h = &orangefs_inode->xattr_cache[xattr_key(name)];
388 hlist_for_each_entry_safe(cx, tmp, h, node) {
389 if (!strcmp(cx->key, name)) {
390 hlist_del(&cx->node);
391 kfree(cx);
392 break;
393 }
394 }
395
396 out_unlock:
397 up_write(&orangefs_inode->xattr_sem);
398 return ret;
399 }
400
401 /*
402 * Tries to get a specified object's keys into a user-specified buffer of a
403 * given size. Note that like the previous instances of xattr routines, this
404 * also allows you to pass in a NULL pointer and 0 size to probe the size for
405 * subsequent memory allocations. Thus our return value is always the size of
406 * all the keys unless there were errors in fetching the keys!
407 */
orangefs_listxattr(struct dentry * dentry,char * buffer,size_t size)408 ssize_t orangefs_listxattr(struct dentry *dentry, char *buffer, size_t size)
409 {
410 struct inode *inode = dentry->d_inode;
411 struct orangefs_inode_s *orangefs_inode = ORANGEFS_I(inode);
412 struct orangefs_kernel_op_s *new_op;
413 __u64 token = ORANGEFS_ITERATE_START;
414 ssize_t ret = -ENOMEM;
415 ssize_t total = 0;
416 int count_keys = 0;
417 int key_size;
418 int i = 0;
419 int returned_count = 0;
420
421 if (size > 0 && !buffer) {
422 gossip_err("%s: bogus NULL pointers\n", __func__);
423 return -EINVAL;
424 }
425
426 down_read(&orangefs_inode->xattr_sem);
427 new_op = op_alloc(ORANGEFS_VFS_OP_LISTXATTR);
428 if (!new_op)
429 goto out_unlock;
430
431 if (buffer && size > 0)
432 memset(buffer, 0, size);
433
434 try_again:
435 key_size = 0;
436 new_op->upcall.req.listxattr.refn = orangefs_inode->refn;
437 new_op->upcall.req.listxattr.token = token;
438 new_op->upcall.req.listxattr.requested_count =
439 (size == 0) ? 0 : ORANGEFS_MAX_XATTR_LISTLEN;
440 ret = service_operation(new_op, __func__,
441 get_interruptible_flag(inode));
442 if (ret != 0)
443 goto done;
444
445 if (size == 0) {
446 /*
447 * This is a bit of a big upper limit, but I did not want to
448 * spend too much time getting this correct, since users end
449 * up allocating memory rather than us...
450 */
451 total = new_op->downcall.resp.listxattr.returned_count *
452 ORANGEFS_MAX_XATTR_NAMELEN;
453 goto done;
454 }
455
456 returned_count = new_op->downcall.resp.listxattr.returned_count;
457 if (returned_count < 0 ||
458 returned_count > ORANGEFS_MAX_XATTR_LISTLEN) {
459 gossip_err("%s: impossible value for returned_count:%d:\n",
460 __func__,
461 returned_count);
462 ret = -EIO;
463 goto done;
464 }
465
466 /*
467 * Check to see how much can be fit in the buffer. Fit only whole keys.
468 */
469 for (i = 0; i < returned_count; i++) {
470 if (new_op->downcall.resp.listxattr.lengths[i] < 0 ||
471 new_op->downcall.resp.listxattr.lengths[i] >
472 ORANGEFS_MAX_XATTR_NAMELEN) {
473 gossip_err("%s: impossible value for lengths[%d]\n",
474 __func__,
475 new_op->downcall.resp.listxattr.lengths[i]);
476 ret = -EIO;
477 goto done;
478 }
479 if (total + new_op->downcall.resp.listxattr.lengths[i] > size)
480 goto done;
481
482 /*
483 * Since many dumb programs try to setxattr() on our reserved
484 * xattrs this is a feeble attempt at defeating those by not
485 * listing them in the output of listxattr.. sigh
486 */
487 if (is_reserved_key(new_op->downcall.resp.listxattr.key +
488 key_size,
489 new_op->downcall.resp.
490 listxattr.lengths[i])) {
491 gossip_debug(GOSSIP_XATTR_DEBUG, "Copying key %d -> %s\n",
492 i, new_op->downcall.resp.listxattr.key +
493 key_size);
494 memcpy(buffer + total,
495 new_op->downcall.resp.listxattr.key + key_size,
496 new_op->downcall.resp.listxattr.lengths[i]);
497 total += new_op->downcall.resp.listxattr.lengths[i];
498 count_keys++;
499 } else {
500 gossip_debug(GOSSIP_XATTR_DEBUG, "[RESERVED] key %d -> %s\n",
501 i, new_op->downcall.resp.listxattr.key +
502 key_size);
503 }
504 key_size += new_op->downcall.resp.listxattr.lengths[i];
505 }
506
507 /*
508 * Since the buffer was large enough, we might have to continue
509 * fetching more keys!
510 */
511 token = new_op->downcall.resp.listxattr.token;
512 if (token != ORANGEFS_ITERATE_END)
513 goto try_again;
514
515 done:
516 gossip_debug(GOSSIP_XATTR_DEBUG, "%s: returning %d"
517 " [size of buffer %ld] (filled in %d keys)\n",
518 __func__,
519 ret ? (int)ret : (int)total,
520 (long)size,
521 count_keys);
522 op_release(new_op);
523 if (ret == 0)
524 ret = total;
525 out_unlock:
526 up_read(&orangefs_inode->xattr_sem);
527 return ret;
528 }
529
orangefs_xattr_set_default(const struct xattr_handler * handler,struct mnt_idmap * idmap,struct dentry * unused,struct inode * inode,const char * name,const void * buffer,size_t size,int flags)530 static int orangefs_xattr_set_default(const struct xattr_handler *handler,
531 struct mnt_idmap *idmap,
532 struct dentry *unused,
533 struct inode *inode,
534 const char *name,
535 const void *buffer,
536 size_t size,
537 int flags)
538 {
539 return orangefs_inode_setxattr(inode, name, buffer, size, flags);
540 }
541
orangefs_xattr_get_default(const struct xattr_handler * handler,struct dentry * unused,struct inode * inode,const char * name,void * buffer,size_t size)542 static int orangefs_xattr_get_default(const struct xattr_handler *handler,
543 struct dentry *unused,
544 struct inode *inode,
545 const char *name,
546 void *buffer,
547 size_t size)
548 {
549 return orangefs_inode_getxattr(inode, name, buffer, size);
550
551 }
552
553 static const struct xattr_handler orangefs_xattr_default_handler = {
554 .prefix = "", /* match any name => handlers called with full name */
555 .get = orangefs_xattr_get_default,
556 .set = orangefs_xattr_set_default,
557 };
558
559 const struct xattr_handler * const orangefs_xattr_handlers[] = {
560 &orangefs_xattr_default_handler,
561 NULL
562 };
563