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