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 (S_ISLNK(inode->i_mode)) 77 return -EOPNOTSUPP; 78 79 if (strlen(name) > ORANGEFS_MAX_XATTR_NAMELEN) 80 return -EINVAL; 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 if (strlen(name) > ORANGEFS_MAX_XATTR_NAMELEN) 173 return -EINVAL; 174 175 down_write(&orangefs_inode->xattr_sem); 176 new_op = op_alloc(ORANGEFS_VFS_OP_REMOVEXATTR); 177 if (!new_op) 178 goto out_unlock; 179 180 new_op->upcall.req.removexattr.refn = orangefs_inode->refn; 181 /* 182 * NOTE: Although keys are meant to be NULL terminated 183 * textual strings, I am going to explicitly pass the 184 * length just in case we change this later on... 185 */ 186 strcpy(new_op->upcall.req.removexattr.key, name); 187 new_op->upcall.req.removexattr.key_sz = strlen(name) + 1; 188 189 gossip_debug(GOSSIP_XATTR_DEBUG, 190 "orangefs_inode_removexattr: key %s, key_sz %d\n", 191 (char *)new_op->upcall.req.removexattr.key, 192 (int)new_op->upcall.req.removexattr.key_sz); 193 194 ret = service_operation(new_op, 195 "orangefs_inode_removexattr", 196 get_interruptible_flag(inode)); 197 if (ret == -ENOENT) { 198 /* 199 * Request to replace a non-existent attribute is an error. 200 */ 201 if (flags & XATTR_REPLACE) 202 ret = -ENODATA; 203 else 204 ret = 0; 205 } 206 207 gossip_debug(GOSSIP_XATTR_DEBUG, 208 "orangefs_inode_removexattr: returning %d\n", ret); 209 210 op_release(new_op); 211 out_unlock: 212 up_write(&orangefs_inode->xattr_sem); 213 return ret; 214 } 215 216 /* 217 * Tries to set an attribute for a given key on a file. 218 * 219 * Returns a -ve number on error and 0 on success. Key is text, but value 220 * can be binary! 221 */ 222 int orangefs_inode_setxattr(struct inode *inode, const char *name, 223 const void *value, size_t size, int flags) 224 { 225 struct orangefs_inode_s *orangefs_inode = ORANGEFS_I(inode); 226 struct orangefs_kernel_op_s *new_op; 227 int internal_flag = 0; 228 int ret = -ENOMEM; 229 230 gossip_debug(GOSSIP_XATTR_DEBUG, 231 "%s: name %s, buffer_size %zd\n", 232 __func__, name, size); 233 234 if (size > ORANGEFS_MAX_XATTR_VALUELEN) 235 return -EINVAL; 236 if (strlen(name) > ORANGEFS_MAX_XATTR_NAMELEN) 237 return -EINVAL; 238 239 internal_flag = convert_to_internal_xattr_flags(flags); 240 241 /* This is equivalent to a removexattr */ 242 if (size == 0 && value == NULL) { 243 gossip_debug(GOSSIP_XATTR_DEBUG, 244 "removing xattr (%s)\n", 245 name); 246 return orangefs_inode_removexattr(inode, name, flags); 247 } 248 249 gossip_debug(GOSSIP_XATTR_DEBUG, 250 "setxattr on inode %pU, name %s\n", 251 get_khandle_from_ino(inode), 252 name); 253 254 down_write(&orangefs_inode->xattr_sem); 255 new_op = op_alloc(ORANGEFS_VFS_OP_SETXATTR); 256 if (!new_op) 257 goto out_unlock; 258 259 260 new_op->upcall.req.setxattr.refn = orangefs_inode->refn; 261 new_op->upcall.req.setxattr.flags = internal_flag; 262 /* 263 * NOTE: Although keys are meant to be NULL terminated textual 264 * strings, I am going to explicitly pass the length just in 265 * case we change this later on... 266 */ 267 strcpy(new_op->upcall.req.setxattr.keyval.key, name); 268 new_op->upcall.req.setxattr.keyval.key_sz = strlen(name) + 1; 269 memcpy(new_op->upcall.req.setxattr.keyval.val, value, size); 270 new_op->upcall.req.setxattr.keyval.val_sz = size; 271 272 gossip_debug(GOSSIP_XATTR_DEBUG, 273 "orangefs_inode_setxattr: key %s, key_sz %d " 274 " value size %zd\n", 275 (char *)new_op->upcall.req.setxattr.keyval.key, 276 (int)new_op->upcall.req.setxattr.keyval.key_sz, 277 size); 278 279 ret = service_operation(new_op, 280 "orangefs_inode_setxattr", 281 get_interruptible_flag(inode)); 282 283 gossip_debug(GOSSIP_XATTR_DEBUG, 284 "orangefs_inode_setxattr: returning %d\n", 285 ret); 286 287 /* when request is serviced properly, free req op struct */ 288 op_release(new_op); 289 out_unlock: 290 up_write(&orangefs_inode->xattr_sem); 291 return ret; 292 } 293 294 /* 295 * Tries to get a specified object's keys into a user-specified buffer of a 296 * given size. Note that like the previous instances of xattr routines, this 297 * also allows you to pass in a NULL pointer and 0 size to probe the size for 298 * subsequent memory allocations. Thus our return value is always the size of 299 * all the keys unless there were errors in fetching the keys! 300 */ 301 ssize_t orangefs_listxattr(struct dentry *dentry, char *buffer, size_t size) 302 { 303 struct inode *inode = dentry->d_inode; 304 struct orangefs_inode_s *orangefs_inode = ORANGEFS_I(inode); 305 struct orangefs_kernel_op_s *new_op; 306 __u64 token = ORANGEFS_ITERATE_START; 307 ssize_t ret = -ENOMEM; 308 ssize_t total = 0; 309 int count_keys = 0; 310 int key_size; 311 int i = 0; 312 int returned_count = 0; 313 314 if (size > 0 && buffer == NULL) { 315 gossip_err("%s: bogus NULL pointers\n", __func__); 316 return -EINVAL; 317 } 318 319 down_read(&orangefs_inode->xattr_sem); 320 new_op = op_alloc(ORANGEFS_VFS_OP_LISTXATTR); 321 if (!new_op) 322 goto out_unlock; 323 324 if (buffer && size > 0) 325 memset(buffer, 0, size); 326 327 try_again: 328 key_size = 0; 329 new_op->upcall.req.listxattr.refn = orangefs_inode->refn; 330 new_op->upcall.req.listxattr.token = token; 331 new_op->upcall.req.listxattr.requested_count = 332 (size == 0) ? 0 : ORANGEFS_MAX_XATTR_LISTLEN; 333 ret = service_operation(new_op, __func__, 334 get_interruptible_flag(inode)); 335 if (ret != 0) 336 goto done; 337 338 if (size == 0) { 339 /* 340 * This is a bit of a big upper limit, but I did not want to 341 * spend too much time getting this correct, since users end 342 * up allocating memory rather than us... 343 */ 344 total = new_op->downcall.resp.listxattr.returned_count * 345 ORANGEFS_MAX_XATTR_NAMELEN; 346 goto done; 347 } 348 349 returned_count = new_op->downcall.resp.listxattr.returned_count; 350 if (returned_count < 0 || 351 returned_count > ORANGEFS_MAX_XATTR_LISTLEN) { 352 gossip_err("%s: impossible value for returned_count:%d:\n", 353 __func__, 354 returned_count); 355 ret = -EIO; 356 goto done; 357 } 358 359 /* 360 * Check to see how much can be fit in the buffer. Fit only whole keys. 361 */ 362 for (i = 0; i < returned_count; i++) { 363 if (new_op->downcall.resp.listxattr.lengths[i] < 0 || 364 new_op->downcall.resp.listxattr.lengths[i] > 365 ORANGEFS_MAX_XATTR_NAMELEN) { 366 gossip_err("%s: impossible value for lengths[%d]\n", 367 __func__, 368 new_op->downcall.resp.listxattr.lengths[i]); 369 ret = -EIO; 370 goto done; 371 } 372 if (total + new_op->downcall.resp.listxattr.lengths[i] > size) 373 goto done; 374 375 /* 376 * Since many dumb programs try to setxattr() on our reserved 377 * xattrs this is a feeble attempt at defeating those by not 378 * listing them in the output of listxattr.. sigh 379 */ 380 if (is_reserved_key(new_op->downcall.resp.listxattr.key + 381 key_size, 382 new_op->downcall.resp. 383 listxattr.lengths[i])) { 384 gossip_debug(GOSSIP_XATTR_DEBUG, "Copying key %d -> %s\n", 385 i, new_op->downcall.resp.listxattr.key + 386 key_size); 387 memcpy(buffer + total, 388 new_op->downcall.resp.listxattr.key + key_size, 389 new_op->downcall.resp.listxattr.lengths[i]); 390 total += new_op->downcall.resp.listxattr.lengths[i]; 391 count_keys++; 392 } else { 393 gossip_debug(GOSSIP_XATTR_DEBUG, "[RESERVED] key %d -> %s\n", 394 i, new_op->downcall.resp.listxattr.key + 395 key_size); 396 } 397 key_size += new_op->downcall.resp.listxattr.lengths[i]; 398 } 399 400 /* 401 * Since the buffer was large enough, we might have to continue 402 * fetching more keys! 403 */ 404 token = new_op->downcall.resp.listxattr.token; 405 if (token != ORANGEFS_ITERATE_END) 406 goto try_again; 407 408 done: 409 gossip_debug(GOSSIP_XATTR_DEBUG, "%s: returning %d" 410 " [size of buffer %ld] (filled in %d keys)\n", 411 __func__, 412 ret ? (int)ret : (int)total, 413 (long)size, 414 count_keys); 415 op_release(new_op); 416 if (ret == 0) 417 ret = total; 418 out_unlock: 419 up_read(&orangefs_inode->xattr_sem); 420 return ret; 421 } 422 423 static int orangefs_xattr_set_default(const struct xattr_handler *handler, 424 struct dentry *unused, 425 struct inode *inode, 426 const char *name, 427 const void *buffer, 428 size_t size, 429 int flags) 430 { 431 return orangefs_inode_setxattr(inode, name, buffer, size, flags); 432 } 433 434 static int orangefs_xattr_get_default(const struct xattr_handler *handler, 435 struct dentry *unused, 436 struct inode *inode, 437 const char *name, 438 void *buffer, 439 size_t size) 440 { 441 return orangefs_inode_getxattr(inode, name, buffer, size); 442 443 } 444 445 static struct xattr_handler orangefs_xattr_default_handler = { 446 .prefix = "", /* match any name => handlers called with full name */ 447 .get = orangefs_xattr_get_default, 448 .set = orangefs_xattr_set_default, 449 }; 450 451 const struct xattr_handler *orangefs_xattr_handlers[] = { 452 &posix_acl_access_xattr_handler, 453 &posix_acl_default_xattr_handler, 454 &orangefs_xattr_default_handler, 455 NULL 456 }; 457