The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/fs/xattr.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    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  */
    9 #include <linux/fs.h>
   10 #include <linux/slab.h>
   11 #include <linux/vmalloc.h>
   12 #include <linux/smp_lock.h>
   13 #include <linux/file.h>
   14 #include <linux/xattr.h>
   15 #include <asm/uaccess.h>
   16 
   17 /*
   18  * Extended attribute memory allocation wrappers, originally
   19  * based on the Intermezzo PRESTO_ALLOC/PRESTO_FREE macros.
   20  * The vmalloc use here is very uncommon - extended attributes
   21  * are supposed to be small chunks of metadata, and it is quite
   22  * unusual to have very many extended attributes, so lists tend
   23  * to be quite short as well.  The 64K upper limit is derived
   24  * from the extended attribute size limit used by XFS.
   25  * Intentionally allow zero @size for value/list size requests.
   26  */
   27 static void *
   28 xattr_alloc(size_t size, size_t limit)
   29 {
   30         void *ptr;
   31 
   32         if (size > limit)
   33                 return ERR_PTR(-E2BIG);
   34 
   35         if (!size)      /* size request, no buffer is needed */
   36                 return NULL;
   37         else if (size <= PAGE_SIZE)
   38                 ptr = kmalloc((unsigned long) size, GFP_KERNEL);
   39         else
   40                 ptr = vmalloc((unsigned long) size);
   41         if (!ptr)
   42                 return ERR_PTR(-ENOMEM);
   43         return ptr;
   44 }
   45 
   46 static void
   47 xattr_free(void *ptr, size_t size)
   48 {
   49         if (!size)      /* size request, no buffer was needed */
   50                 return;
   51         else if (size <= PAGE_SIZE)
   52                 kfree(ptr);
   53         else
   54                 vfree(ptr);
   55 }
   56 
   57 /*
   58  * Extended attribute SET operations
   59  */
   60 static long
   61 setxattr(struct dentry *d, char *name, void *value, size_t size, int flags)
   62 {
   63         int error;
   64         void *kvalue;
   65         char kname[XATTR_NAME_MAX + 1];
   66 
   67         if (flags & ~(XATTR_CREATE|XATTR_REPLACE))
   68                 return -EINVAL;
   69 
   70         error = strncpy_from_user(kname, name, sizeof(kname));
   71         if (error == 0 || error == sizeof(kname))
   72                 error = -ERANGE;
   73         if (error < 0)
   74                 return error;
   75 
   76         kvalue = xattr_alloc(size, XATTR_SIZE_MAX);
   77         if (IS_ERR(kvalue))
   78                 return PTR_ERR(kvalue);
   79 
   80         if (size > 0 && copy_from_user(kvalue, value, size)) {
   81                 xattr_free(kvalue, size);
   82                 return -EFAULT;
   83         }
   84 
   85         error = -EOPNOTSUPP;
   86         if (d->d_inode->i_op && d->d_inode->i_op->setxattr) {
   87                 down(&d->d_inode->i_sem);
   88                 lock_kernel();
   89                 error = d->d_inode->i_op->setxattr(d, kname, kvalue, size, flags);
   90                 unlock_kernel();
   91                 up(&d->d_inode->i_sem);
   92         }
   93 
   94         xattr_free(kvalue, size);
   95         return error;
   96 }
   97 
   98 asmlinkage long
   99 sys_setxattr(char *path, char *name, void *value, size_t size, int flags)
  100 {
  101         struct nameidata nd;
  102         int error;
  103 
  104         error = user_path_walk(path, &nd);
  105         if (error)
  106                 return error;
  107         error = setxattr(nd.dentry, name, value, size, flags);
  108         path_release(&nd);
  109         return error;
  110 }
  111 
  112 asmlinkage long
  113 sys_lsetxattr(char *path, char *name, void *value, size_t size, int flags)
  114 {
  115         struct nameidata nd;
  116         int error;
  117 
  118         error = user_path_walk_link(path, &nd);
  119         if (error)
  120                 return error;
  121         error = setxattr(nd.dentry, name, value, size, flags);
  122         path_release(&nd);
  123         return error;
  124 }
  125 
  126 asmlinkage long
  127 sys_fsetxattr(int fd, char *name, void *value, size_t size, int flags)
  128 {
  129         struct file *f;
  130         int error = -EBADF;
  131 
  132         f = fget(fd);
  133         if (!f)
  134                 return error;
  135         error = setxattr(f->f_dentry, name, value, size, flags);
  136         fput(f);
  137         return error;
  138 }
  139 
  140 /*
  141  * Extended attribute GET operations
  142  */
  143 static ssize_t
  144 getxattr(struct dentry *d, char *name, void *value, size_t size)
  145 {
  146         ssize_t error;
  147         void *kvalue;
  148         char kname[XATTR_NAME_MAX + 1];
  149 
  150         error = strncpy_from_user(kname, name, sizeof(kname));
  151         if (error == 0 || error == sizeof(kname))
  152                 error = -ERANGE;
  153         if (error < 0)
  154                 return error;
  155 
  156         kvalue = xattr_alloc(size, XATTR_SIZE_MAX);
  157         if (IS_ERR(kvalue))
  158                 return PTR_ERR(kvalue);
  159 
  160         error = -EOPNOTSUPP;
  161         if (d->d_inode->i_op && d->d_inode->i_op->getxattr) {
  162                 down(&d->d_inode->i_sem);
  163                 lock_kernel();
  164                 error = d->d_inode->i_op->getxattr(d, kname, kvalue, size);
  165                 unlock_kernel();
  166                 up(&d->d_inode->i_sem);
  167         }
  168 
  169         if (kvalue && error > 0)
  170                 if (copy_to_user(value, kvalue, error))
  171                         error = -EFAULT;
  172         xattr_free(kvalue, size);
  173         return error;
  174 }
  175 
  176 asmlinkage ssize_t
  177 sys_getxattr(char *path, char *name, void *value, size_t size)
  178 {
  179         struct nameidata nd;
  180         ssize_t error;
  181 
  182         error = user_path_walk(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_lgetxattr(char *path, char *name, void *value, size_t size)
  192 {
  193         struct nameidata nd;
  194         ssize_t error;
  195 
  196         error = user_path_walk_link(path, &nd);
  197         if (error)
  198                 return error;
  199         error = getxattr(nd.dentry, name, value, size);
  200         path_release(&nd);
  201         return error;
  202 }
  203 
  204 asmlinkage ssize_t
  205 sys_fgetxattr(int fd, char *name, void *value, size_t size)
  206 {
  207         struct file *f;
  208         ssize_t error = -EBADF;
  209 
  210         f = fget(fd);
  211         if (!f)
  212                 return error;
  213         error = getxattr(f->f_dentry, name, value, size);
  214         fput(f);
  215         return error;
  216 }
  217 
  218 /*
  219  * Extended attribute LIST operations
  220  */
  221 static ssize_t
  222 listxattr(struct dentry *d, char *list, size_t size)
  223 {
  224         ssize_t error;
  225         char *klist;
  226 
  227         klist = (char *)xattr_alloc(size, XATTR_LIST_MAX);
  228         if (IS_ERR(klist))
  229                 return PTR_ERR(klist);
  230 
  231         error = -EOPNOTSUPP;
  232         if (d->d_inode->i_op && d->d_inode->i_op->listxattr) {
  233                 down(&d->d_inode->i_sem);
  234                 lock_kernel();
  235                 error = d->d_inode->i_op->listxattr(d, klist, size);
  236                 unlock_kernel();
  237                 up(&d->d_inode->i_sem);
  238         }
  239 
  240         if (klist && error > 0)
  241                 if (copy_to_user(list, klist, error))
  242                         error = -EFAULT;
  243         xattr_free(klist, size);
  244         return error;
  245 }
  246 
  247 asmlinkage ssize_t
  248 sys_listxattr(char *path, char *list, size_t size)
  249 {
  250         struct nameidata nd;
  251         ssize_t error;
  252 
  253         error = user_path_walk(path, &nd);
  254         if (error)
  255                 return error;
  256         error = listxattr(nd.dentry, list, size);
  257         path_release(&nd);
  258         return error;
  259 }
  260 
  261 asmlinkage ssize_t
  262 sys_llistxattr(char *path, char *list, size_t size)
  263 {
  264         struct nameidata nd;
  265         ssize_t error;
  266 
  267         error = user_path_walk_link(path, &nd);
  268         if (error)
  269                 return error;
  270         error = listxattr(nd.dentry, list, size);
  271         path_release(&nd);
  272         return error;
  273 }
  274 
  275 asmlinkage ssize_t
  276 sys_flistxattr(int fd, char *list, size_t size)
  277 {
  278         struct file *f;
  279         ssize_t error = -EBADF;
  280 
  281         f = fget(fd);
  282         if (!f)
  283                 return error;
  284         error = listxattr(f->f_dentry, list, size);
  285         fput(f);
  286         return error;
  287 }
  288 
  289 /*
  290  * Extended attribute REMOVE operations
  291  */
  292 static long
  293 removexattr(struct dentry *d, char *name)
  294 {
  295         int error;
  296         char kname[XATTR_NAME_MAX + 1];
  297 
  298         error = strncpy_from_user(kname, name, sizeof(kname));
  299         if (error == 0 || error == sizeof(kname))
  300                 error = -ERANGE;
  301         if (error < 0)
  302                 return error;
  303 
  304         error = -EOPNOTSUPP;
  305         if (d->d_inode->i_op && d->d_inode->i_op->removexattr) {
  306                 down(&d->d_inode->i_sem);
  307                 lock_kernel();
  308                 error = d->d_inode->i_op->removexattr(d, kname);
  309                 unlock_kernel();
  310                 up(&d->d_inode->i_sem);
  311         }
  312         return error;
  313 }
  314 
  315 asmlinkage long
  316 sys_removexattr(char *path, char *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 *path, char *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 *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 }

Cache object: 6582b779d23eda336ec3a4de0125524d


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.