xref: /linux/fs/orangefs/xattr.c (revision f2327dc8513d0928a64b75656a6efe12b5c7c00a)
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