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