1 /* 2 File: fs/xattr.c 3 4 Extended attribute handling. 5 6 Copyright (C) 2001 by Andreas Gruenbacher <a.gruenbacher@computer.org> 7 Copyright (C) 2001 SGI - Silicon Graphics, Inc <linux-xfs@oss.sgi.com> 8 Copyright (c) 2004 Red Hat, Inc., James Morris <jmorris@redhat.com> 9 */ 10 #include <linux/fs.h> 11 #include <linux/slab.h> 12 #include <linux/smp_lock.h> 13 #include <linux/file.h> 14 #include <linux/xattr.h> 15 #include <linux/namei.h> 16 #include <linux/security.h> 17 #include <linux/syscalls.h> 18 #include <linux/module.h> 19 #include <linux/fsnotify.h> 20 #include <asm/uaccess.h> 21 22 /* 23 * Extended attribute SET operations 24 */ 25 static long 26 setxattr(struct dentry *d, char __user *name, void __user *value, 27 size_t size, int flags) 28 { 29 int error; 30 void *kvalue = NULL; 31 char kname[XATTR_NAME_MAX + 1]; 32 33 if (flags & ~(XATTR_CREATE|XATTR_REPLACE)) 34 return -EINVAL; 35 36 error = strncpy_from_user(kname, name, sizeof(kname)); 37 if (error == 0 || error == sizeof(kname)) 38 error = -ERANGE; 39 if (error < 0) 40 return error; 41 42 if (size) { 43 if (size > XATTR_SIZE_MAX) 44 return -E2BIG; 45 kvalue = kmalloc(size, GFP_KERNEL); 46 if (!kvalue) 47 return -ENOMEM; 48 if (copy_from_user(kvalue, value, size)) { 49 kfree(kvalue); 50 return -EFAULT; 51 } 52 } 53 54 error = -EOPNOTSUPP; 55 if (d->d_inode->i_op && d->d_inode->i_op->setxattr) { 56 down(&d->d_inode->i_sem); 57 error = security_inode_setxattr(d, kname, kvalue, size, flags); 58 if (error) 59 goto out; 60 error = d->d_inode->i_op->setxattr(d, kname, kvalue, size, flags); 61 if (!error) { 62 fsnotify_xattr(d); 63 security_inode_post_setxattr(d, kname, kvalue, size, flags); 64 } 65 out: 66 up(&d->d_inode->i_sem); 67 } 68 if (kvalue) 69 kfree(kvalue); 70 return error; 71 } 72 73 asmlinkage long 74 sys_setxattr(char __user *path, char __user *name, void __user *value, 75 size_t size, int flags) 76 { 77 struct nameidata nd; 78 int error; 79 80 error = user_path_walk(path, &nd); 81 if (error) 82 return error; 83 error = setxattr(nd.dentry, name, value, size, flags); 84 path_release(&nd); 85 return error; 86 } 87 88 asmlinkage long 89 sys_lsetxattr(char __user *path, char __user *name, void __user *value, 90 size_t size, int flags) 91 { 92 struct nameidata nd; 93 int error; 94 95 error = user_path_walk_link(path, &nd); 96 if (error) 97 return error; 98 error = setxattr(nd.dentry, name, value, size, flags); 99 path_release(&nd); 100 return error; 101 } 102 103 asmlinkage long 104 sys_fsetxattr(int fd, char __user *name, void __user *value, 105 size_t size, int flags) 106 { 107 struct file *f; 108 int error = -EBADF; 109 110 f = fget(fd); 111 if (!f) 112 return error; 113 error = setxattr(f->f_dentry, name, value, size, flags); 114 fput(f); 115 return error; 116 } 117 118 /* 119 * Extended attribute GET operations 120 */ 121 static ssize_t 122 getxattr(struct dentry *d, char __user *name, void __user *value, size_t size) 123 { 124 ssize_t error; 125 void *kvalue = NULL; 126 char kname[XATTR_NAME_MAX + 1]; 127 128 error = strncpy_from_user(kname, name, sizeof(kname)); 129 if (error == 0 || error == sizeof(kname)) 130 error = -ERANGE; 131 if (error < 0) 132 return error; 133 134 if (size) { 135 if (size > XATTR_SIZE_MAX) 136 size = XATTR_SIZE_MAX; 137 kvalue = kmalloc(size, GFP_KERNEL); 138 if (!kvalue) 139 return -ENOMEM; 140 } 141 142 error = -EOPNOTSUPP; 143 if (d->d_inode->i_op && d->d_inode->i_op->getxattr) { 144 error = security_inode_getxattr(d, kname); 145 if (error) 146 goto out; 147 error = d->d_inode->i_op->getxattr(d, kname, kvalue, size); 148 if (error > 0) { 149 if (size && copy_to_user(value, kvalue, error)) 150 error = -EFAULT; 151 } else if (error == -ERANGE && size >= XATTR_SIZE_MAX) { 152 /* The file system tried to returned a value bigger 153 than XATTR_SIZE_MAX bytes. Not possible. */ 154 error = -E2BIG; 155 } 156 } 157 out: 158 if (kvalue) 159 kfree(kvalue); 160 return error; 161 } 162 163 asmlinkage ssize_t 164 sys_getxattr(char __user *path, char __user *name, void __user *value, 165 size_t size) 166 { 167 struct nameidata nd; 168 ssize_t error; 169 170 error = user_path_walk(path, &nd); 171 if (error) 172 return error; 173 error = getxattr(nd.dentry, name, value, size); 174 path_release(&nd); 175 return error; 176 } 177 178 asmlinkage ssize_t 179 sys_lgetxattr(char __user *path, char __user *name, void __user *value, 180 size_t size) 181 { 182 struct nameidata nd; 183 ssize_t error; 184 185 error = user_path_walk_link(path, &nd); 186 if (error) 187 return error; 188 error = getxattr(nd.dentry, name, value, size); 189 path_release(&nd); 190 return error; 191 } 192 193 asmlinkage ssize_t 194 sys_fgetxattr(int fd, char __user *name, void __user *value, size_t size) 195 { 196 struct file *f; 197 ssize_t error = -EBADF; 198 199 f = fget(fd); 200 if (!f) 201 return error; 202 error = getxattr(f->f_dentry, name, value, size); 203 fput(f); 204 return error; 205 } 206 207 /* 208 * Extended attribute LIST operations 209 */ 210 static ssize_t 211 listxattr(struct dentry *d, char __user *list, size_t size) 212 { 213 ssize_t error; 214 char *klist = NULL; 215 216 if (size) { 217 if (size > XATTR_LIST_MAX) 218 size = XATTR_LIST_MAX; 219 klist = kmalloc(size, GFP_KERNEL); 220 if (!klist) 221 return -ENOMEM; 222 } 223 224 error = -EOPNOTSUPP; 225 if (d->d_inode->i_op && d->d_inode->i_op->listxattr) { 226 error = security_inode_listxattr(d); 227 if (error) 228 goto out; 229 error = d->d_inode->i_op->listxattr(d, klist, size); 230 if (error > 0) { 231 if (size && copy_to_user(list, klist, error)) 232 error = -EFAULT; 233 } else if (error == -ERANGE && size >= XATTR_LIST_MAX) { 234 /* The file system tried to returned a list bigger 235 than XATTR_LIST_MAX bytes. Not possible. */ 236 error = -E2BIG; 237 } 238 } 239 out: 240 if (klist) 241 kfree(klist); 242 return error; 243 } 244 245 asmlinkage ssize_t 246 sys_listxattr(char __user *path, char __user *list, size_t size) 247 { 248 struct nameidata nd; 249 ssize_t error; 250 251 error = user_path_walk(path, &nd); 252 if (error) 253 return error; 254 error = listxattr(nd.dentry, list, size); 255 path_release(&nd); 256 return error; 257 } 258 259 asmlinkage ssize_t 260 sys_llistxattr(char __user *path, char __user *list, size_t size) 261 { 262 struct nameidata nd; 263 ssize_t error; 264 265 error = user_path_walk_link(path, &nd); 266 if (error) 267 return error; 268 error = listxattr(nd.dentry, list, size); 269 path_release(&nd); 270 return error; 271 } 272 273 asmlinkage ssize_t 274 sys_flistxattr(int fd, char __user *list, size_t size) 275 { 276 struct file *f; 277 ssize_t error = -EBADF; 278 279 f = fget(fd); 280 if (!f) 281 return error; 282 error = listxattr(f->f_dentry, list, size); 283 fput(f); 284 return error; 285 } 286 287 /* 288 * Extended attribute REMOVE operations 289 */ 290 static long 291 removexattr(struct dentry *d, char __user *name) 292 { 293 int error; 294 char kname[XATTR_NAME_MAX + 1]; 295 296 error = strncpy_from_user(kname, name, sizeof(kname)); 297 if (error == 0 || error == sizeof(kname)) 298 error = -ERANGE; 299 if (error < 0) 300 return error; 301 302 error = -EOPNOTSUPP; 303 if (d->d_inode->i_op && d->d_inode->i_op->removexattr) { 304 error = security_inode_removexattr(d, kname); 305 if (error) 306 goto out; 307 down(&d->d_inode->i_sem); 308 error = d->d_inode->i_op->removexattr(d, kname); 309 up(&d->d_inode->i_sem); 310 } 311 out: 312 return error; 313 } 314 315 asmlinkage long 316 sys_removexattr(char __user *path, char __user *name) 317 { 318 struct nameidata nd; 319 int error; 320 321 error = user_path_walk(path, &nd); 322 if (error) 323 return error; 324 error = removexattr(nd.dentry, name); 325 path_release(&nd); 326 return error; 327 } 328 329 asmlinkage long 330 sys_lremovexattr(char __user *path, char __user *name) 331 { 332 struct nameidata nd; 333 int error; 334 335 error = user_path_walk_link(path, &nd); 336 if (error) 337 return error; 338 error = removexattr(nd.dentry, name); 339 path_release(&nd); 340 return error; 341 } 342 343 asmlinkage long 344 sys_fremovexattr(int fd, char __user *name) 345 { 346 struct file *f; 347 int error = -EBADF; 348 349 f = fget(fd); 350 if (!f) 351 return error; 352 error = removexattr(f->f_dentry, name); 353 fput(f); 354 return error; 355 } 356 357 358 static const char * 359 strcmp_prefix(const char *a, const char *a_prefix) 360 { 361 while (*a_prefix && *a == *a_prefix) { 362 a++; 363 a_prefix++; 364 } 365 return *a_prefix ? NULL : a; 366 } 367 368 /* 369 * In order to implement different sets of xattr operations for each xattr 370 * prefix with the generic xattr API, a filesystem should create a 371 * null-terminated array of struct xattr_handler (one for each prefix) and 372 * hang a pointer to it off of the s_xattr field of the superblock. 373 * 374 * The generic_fooxattr() functions will use this list to dispatch xattr 375 * operations to the correct xattr_handler. 376 */ 377 #define for_each_xattr_handler(handlers, handler) \ 378 for ((handler) = *(handlers)++; \ 379 (handler) != NULL; \ 380 (handler) = *(handlers)++) 381 382 /* 383 * Find the xattr_handler with the matching prefix. 384 */ 385 static struct xattr_handler * 386 xattr_resolve_name(struct xattr_handler **handlers, const char **name) 387 { 388 struct xattr_handler *handler; 389 390 if (!*name) 391 return NULL; 392 393 for_each_xattr_handler(handlers, handler) { 394 const char *n = strcmp_prefix(*name, handler->prefix); 395 if (n) { 396 *name = n; 397 break; 398 } 399 } 400 return handler; 401 } 402 403 /* 404 * Find the handler for the prefix and dispatch its get() operation. 405 */ 406 ssize_t 407 generic_getxattr(struct dentry *dentry, const char *name, void *buffer, size_t size) 408 { 409 struct xattr_handler *handler; 410 struct inode *inode = dentry->d_inode; 411 412 handler = xattr_resolve_name(inode->i_sb->s_xattr, &name); 413 if (!handler) 414 return -EOPNOTSUPP; 415 return handler->get(inode, name, buffer, size); 416 } 417 418 /* 419 * Combine the results of the list() operation from every xattr_handler in the 420 * list. 421 */ 422 ssize_t 423 generic_listxattr(struct dentry *dentry, char *buffer, size_t buffer_size) 424 { 425 struct inode *inode = dentry->d_inode; 426 struct xattr_handler *handler, **handlers = inode->i_sb->s_xattr; 427 unsigned int size = 0; 428 429 if (!buffer) { 430 for_each_xattr_handler(handlers, handler) 431 size += handler->list(inode, NULL, 0, NULL, 0); 432 } else { 433 char *buf = buffer; 434 435 for_each_xattr_handler(handlers, handler) { 436 size = handler->list(inode, buf, buffer_size, NULL, 0); 437 if (size > buffer_size) 438 return -ERANGE; 439 buf += size; 440 buffer_size -= size; 441 } 442 size = buf - buffer; 443 } 444 return size; 445 } 446 447 /* 448 * Find the handler for the prefix and dispatch its set() operation. 449 */ 450 int 451 generic_setxattr(struct dentry *dentry, const char *name, const void *value, size_t size, int flags) 452 { 453 struct xattr_handler *handler; 454 struct inode *inode = dentry->d_inode; 455 456 if (size == 0) 457 value = ""; /* empty EA, do not remove */ 458 handler = xattr_resolve_name(inode->i_sb->s_xattr, &name); 459 if (!handler) 460 return -EOPNOTSUPP; 461 return handler->set(inode, name, value, size, flags); 462 } 463 464 /* 465 * Find the handler for the prefix and dispatch its set() operation to remove 466 * any associated extended attribute. 467 */ 468 int 469 generic_removexattr(struct dentry *dentry, const char *name) 470 { 471 struct xattr_handler *handler; 472 struct inode *inode = dentry->d_inode; 473 474 handler = xattr_resolve_name(inode->i_sb->s_xattr, &name); 475 if (!handler) 476 return -EOPNOTSUPP; 477 return handler->set(inode, name, NULL, 0, XATTR_REPLACE); 478 } 479 480 EXPORT_SYMBOL(generic_getxattr); 481 EXPORT_SYMBOL(generic_listxattr); 482 EXPORT_SYMBOL(generic_setxattr); 483 EXPORT_SYMBOL(generic_removexattr); 484