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