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