linux/fs/xattr.c
<<
>>
Prefs
   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/file.h>
  13#include <linux/xattr.h>
  14#include <linux/mount.h>
  15#include <linux/namei.h>
  16#include <linux/security.h>
  17#include <linux/evm.h>
  18#include <linux/syscalls.h>
  19#include <linux/export.h>
  20#include <linux/fsnotify.h>
  21#include <linux/audit.h>
  22#include <linux/vmalloc.h>
  23#include <linux/posix_acl_xattr.h>
  24
  25#include <asm/uaccess.h>
  26
  27/*
  28 * Check permissions for extended attribute access.  This is a bit complicated
  29 * because different namespaces have very different rules.
  30 */
  31static int
  32xattr_permission(struct inode *inode, const char *name, int mask)
  33{
  34        /*
  35         * We can never set or remove an extended attribute on a read-only
  36         * filesystem  or on an immutable / append-only inode.
  37         */
  38        if (mask & MAY_WRITE) {
  39                if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
  40                        return -EPERM;
  41        }
  42
  43        /*
  44         * No restriction for security.* and system.* from the VFS.  Decision
  45         * on these is left to the underlying filesystem / security module.
  46         */
  47        if (!strncmp(name, XATTR_SECURITY_PREFIX, XATTR_SECURITY_PREFIX_LEN) ||
  48            !strncmp(name, XATTR_SYSTEM_PREFIX, XATTR_SYSTEM_PREFIX_LEN))
  49                return 0;
  50
  51        /*
  52         * The trusted.* namespace can only be accessed by privileged users.
  53         */
  54        if (!strncmp(name, XATTR_TRUSTED_PREFIX, XATTR_TRUSTED_PREFIX_LEN)) {
  55                if (!capable(CAP_SYS_ADMIN))
  56                        return (mask & MAY_WRITE) ? -EPERM : -ENODATA;
  57                return 0;
  58        }
  59
  60        /*
  61         * In the user.* namespace, only regular files and directories can have
  62         * extended attributes. For sticky directories, only the owner and
  63         * privileged users can write attributes.
  64         */
  65        if (!strncmp(name, XATTR_USER_PREFIX, XATTR_USER_PREFIX_LEN)) {
  66                if (!S_ISREG(inode->i_mode) && !S_ISDIR(inode->i_mode))
  67                        return (mask & MAY_WRITE) ? -EPERM : -ENODATA;
  68                if (S_ISDIR(inode->i_mode) && (inode->i_mode & S_ISVTX) &&
  69                    (mask & MAY_WRITE) && !inode_owner_or_capable(inode))
  70                        return -EPERM;
  71        }
  72
  73        return inode_permission(inode, mask);
  74}
  75
  76/**
  77 *  __vfs_setxattr_noperm - perform setxattr operation without performing
  78 *  permission checks.
  79 *
  80 *  @dentry - object to perform setxattr on
  81 *  @name - xattr name to set
  82 *  @value - value to set @name to
  83 *  @size - size of @value
  84 *  @flags - flags to pass into filesystem operations
  85 *
  86 *  returns the result of the internal setxattr or setsecurity operations.
  87 *
  88 *  This function requires the caller to lock the inode's i_mutex before it
  89 *  is executed. It also assumes that the caller will make the appropriate
  90 *  permission checks.
  91 */
  92int __vfs_setxattr_noperm(struct dentry *dentry, const char *name,
  93                const void *value, size_t size, int flags)
  94{
  95        struct inode *inode = dentry->d_inode;
  96        int error = -EOPNOTSUPP;
  97        int issec = !strncmp(name, XATTR_SECURITY_PREFIX,
  98                                   XATTR_SECURITY_PREFIX_LEN);
  99
 100        if (issec)
 101                inode->i_flags &= ~S_NOSEC;
 102        if (inode->i_op->setxattr) {
 103                error = inode->i_op->setxattr(dentry, name, value, size, flags);
 104                if (!error) {
 105                        fsnotify_xattr(dentry);
 106                        security_inode_post_setxattr(dentry, name, value,
 107                                                     size, flags);
 108                }
 109        } else if (issec) {
 110                const char *suffix = name + XATTR_SECURITY_PREFIX_LEN;
 111                error = security_inode_setsecurity(inode, suffix, value,
 112                                                   size, flags);
 113                if (!error)
 114                        fsnotify_xattr(dentry);
 115        }
 116
 117        return error;
 118}
 119
 120
 121int
 122vfs_setxattr(struct dentry *dentry, const char *name, const void *value,
 123                size_t size, int flags)
 124{
 125        struct inode *inode = dentry->d_inode;
 126        int error;
 127
 128        error = xattr_permission(inode, name, MAY_WRITE);
 129        if (error)
 130                return error;
 131
 132        mutex_lock(&inode->i_mutex);
 133        error = security_inode_setxattr(dentry, name, value, size, flags);
 134        if (error)
 135                goto out;
 136
 137        error = __vfs_setxattr_noperm(dentry, name, value, size, flags);
 138
 139out:
 140        mutex_unlock(&inode->i_mutex);
 141        return error;
 142}
 143EXPORT_SYMBOL_GPL(vfs_setxattr);
 144
 145ssize_t
 146xattr_getsecurity(struct inode *inode, const char *name, void *value,
 147                        size_t size)
 148{
 149        void *buffer = NULL;
 150        ssize_t len;
 151
 152        if (!value || !size) {
 153                len = security_inode_getsecurity(inode, name, &buffer, false);
 154                goto out_noalloc;
 155        }
 156
 157        len = security_inode_getsecurity(inode, name, &buffer, true);
 158        if (len < 0)
 159                return len;
 160        if (size < len) {
 161                len = -ERANGE;
 162                goto out;
 163        }
 164        memcpy(value, buffer, len);
 165out:
 166        security_release_secctx(buffer, len);
 167out_noalloc:
 168        return len;
 169}
 170EXPORT_SYMBOL_GPL(xattr_getsecurity);
 171
 172/*
 173 * vfs_getxattr_alloc - allocate memory, if necessary, before calling getxattr
 174 *
 175 * Allocate memory, if not already allocated, or re-allocate correct size,
 176 * before retrieving the extended attribute.
 177 *
 178 * Returns the result of alloc, if failed, or the getxattr operation.
 179 */
 180ssize_t
 181vfs_getxattr_alloc(struct dentry *dentry, const char *name, char **xattr_value,
 182                   size_t xattr_size, gfp_t flags)
 183{
 184        struct inode *inode = dentry->d_inode;
 185        char *value = *xattr_value;
 186        int error;
 187
 188        error = xattr_permission(inode, name, MAY_READ);
 189        if (error)
 190                return error;
 191
 192        if (!inode->i_op->getxattr)
 193                return -EOPNOTSUPP;
 194
 195        error = inode->i_op->getxattr(dentry, name, NULL, 0);
 196        if (error < 0)
 197                return error;
 198
 199        if (!value || (error > xattr_size)) {
 200                value = krealloc(*xattr_value, error + 1, flags);
 201                if (!value)
 202                        return -ENOMEM;
 203                memset(value, 0, error + 1);
 204        }
 205
 206        error = inode->i_op->getxattr(dentry, name, value, error);
 207        *xattr_value = value;
 208        return error;
 209}
 210
 211/* Compare an extended attribute value with the given value */
 212int vfs_xattr_cmp(struct dentry *dentry, const char *xattr_name,
 213                  const char *value, size_t size, gfp_t flags)
 214{
 215        char *xattr_value = NULL;
 216        int rc;
 217
 218        rc = vfs_getxattr_alloc(dentry, xattr_name, &xattr_value, 0, flags);
 219        if (rc < 0)
 220                return rc;
 221
 222        if ((rc != size) || (memcmp(xattr_value, value, rc) != 0))
 223                rc = -EINVAL;
 224        else
 225                rc = 0;
 226        kfree(xattr_value);
 227        return rc;
 228}
 229
 230ssize_t
 231vfs_getxattr(struct dentry *dentry, const char *name, void *value, size_t size)
 232{
 233        struct inode *inode = dentry->d_inode;
 234        int error;
 235
 236        error = xattr_permission(inode, name, MAY_READ);
 237        if (error)
 238                return error;
 239
 240        error = security_inode_getxattr(dentry, name);
 241        if (error)
 242                return error;
 243
 244        if (!strncmp(name, XATTR_SECURITY_PREFIX,
 245                                XATTR_SECURITY_PREFIX_LEN)) {
 246                const char *suffix = name + XATTR_SECURITY_PREFIX_LEN;
 247                int ret = xattr_getsecurity(inode, suffix, value, size);
 248                /*
 249                 * Only overwrite the return value if a security module
 250                 * is actually active.
 251                 */
 252                if (ret == -EOPNOTSUPP)
 253                        goto nolsm;
 254                return ret;
 255        }
 256nolsm:
 257        if (inode->i_op->getxattr)
 258                error = inode->i_op->getxattr(dentry, name, value, size);
 259        else
 260                error = -EOPNOTSUPP;
 261
 262        return error;
 263}
 264EXPORT_SYMBOL_GPL(vfs_getxattr);
 265
 266ssize_t
 267vfs_listxattr(struct dentry *d, char *list, size_t size)
 268{
 269        ssize_t error;
 270
 271        error = security_inode_listxattr(d);
 272        if (error)
 273                return error;
 274        error = -EOPNOTSUPP;
 275        if (d->d_inode->i_op->listxattr) {
 276                error = d->d_inode->i_op->listxattr(d, list, size);
 277        } else {
 278                error = security_inode_listsecurity(d->d_inode, list, size);
 279                if (size && error > size)
 280                        error = -ERANGE;
 281        }
 282        return error;
 283}
 284EXPORT_SYMBOL_GPL(vfs_listxattr);
 285
 286int
 287vfs_removexattr(struct dentry *dentry, const char *name)
 288{
 289        struct inode *inode = dentry->d_inode;
 290        int error;
 291
 292        if (!inode->i_op->removexattr)
 293                return -EOPNOTSUPP;
 294
 295        error = xattr_permission(inode, name, MAY_WRITE);
 296        if (error)
 297                return error;
 298
 299        mutex_lock(&inode->i_mutex);
 300        error = security_inode_removexattr(dentry, name);
 301        if (error) {
 302                mutex_unlock(&inode->i_mutex);
 303                return error;
 304        }
 305
 306        error = inode->i_op->removexattr(dentry, name);
 307        mutex_unlock(&inode->i_mutex);
 308
 309        if (!error) {
 310                fsnotify_xattr(dentry);
 311                evm_inode_post_removexattr(dentry, name);
 312        }
 313        return error;
 314}
 315EXPORT_SYMBOL_GPL(vfs_removexattr);
 316
 317
 318/*
 319 * Extended attribute SET operations
 320 */
 321static long
 322setxattr(struct dentry *d, const char __user *name, const void __user *value,
 323         size_t size, int flags)
 324{
 325        int error;
 326        void *kvalue = NULL;
 327        void *vvalue = NULL;    /* If non-NULL, we used vmalloc() */
 328        char kname[XATTR_NAME_MAX + 1];
 329
 330        if (flags & ~(XATTR_CREATE|XATTR_REPLACE))
 331                return -EINVAL;
 332
 333        error = strncpy_from_user(kname, name, sizeof(kname));
 334        if (error == 0 || error == sizeof(kname))
 335                error = -ERANGE;
 336        if (error < 0)
 337                return error;
 338
 339        if (size) {
 340                if (size > XATTR_SIZE_MAX)
 341                        return -E2BIG;
 342                kvalue = kmalloc(size, GFP_KERNEL | __GFP_NOWARN);
 343                if (!kvalue) {
 344                        vvalue = vmalloc(size);
 345                        if (!vvalue)
 346                                return -ENOMEM;
 347                        kvalue = vvalue;
 348                }
 349                if (copy_from_user(kvalue, value, size)) {
 350                        error = -EFAULT;
 351                        goto out;
 352                }
 353                if ((strcmp(kname, XATTR_NAME_POSIX_ACL_ACCESS) == 0) ||
 354                    (strcmp(kname, XATTR_NAME_POSIX_ACL_DEFAULT) == 0))
 355                        posix_acl_fix_xattr_from_user(kvalue, size);
 356        }
 357
 358        error = vfs_setxattr(d, kname, kvalue, size, flags);
 359out:
 360        if (vvalue)
 361                vfree(vvalue);
 362        else
 363                kfree(kvalue);
 364        return error;
 365}
 366
 367SYSCALL_DEFINE5(setxattr, const char __user *, pathname,
 368                const char __user *, name, const void __user *, value,
 369                size_t, size, int, flags)
 370{
 371        struct path path;
 372        int error;
 373        unsigned int lookup_flags = LOOKUP_FOLLOW;
 374retry:
 375        error = user_path_at(AT_FDCWD, pathname, lookup_flags, &path);
 376        if (error)
 377                return error;
 378        error = mnt_want_write(path.mnt);
 379        if (!error) {
 380                error = setxattr(path.dentry, name, value, size, flags);
 381                mnt_drop_write(path.mnt);
 382        }
 383        path_put(&path);
 384        if (retry_estale(error, lookup_flags)) {
 385                lookup_flags |= LOOKUP_REVAL;
 386                goto retry;
 387        }
 388        return error;
 389}
 390
 391SYSCALL_DEFINE5(lsetxattr, const char __user *, pathname,
 392                const char __user *, name, const void __user *, value,
 393                size_t, size, int, flags)
 394{
 395        struct path path;
 396        int error;
 397        unsigned int lookup_flags = 0;
 398retry:
 399        error = user_path_at(AT_FDCWD, pathname, lookup_flags, &path);
 400        if (error)
 401                return error;
 402        error = mnt_want_write(path.mnt);
 403        if (!error) {
 404                error = setxattr(path.dentry, name, value, size, flags);
 405                mnt_drop_write(path.mnt);
 406        }
 407        path_put(&path);
 408        if (retry_estale(error, lookup_flags)) {
 409                lookup_flags |= LOOKUP_REVAL;
 410                goto retry;
 411        }
 412        return error;
 413}
 414
 415SYSCALL_DEFINE5(fsetxattr, int, fd, const char __user *, name,
 416                const void __user *,value, size_t, size, int, flags)
 417{
 418        struct fd f = fdget(fd);
 419        struct dentry *dentry;
 420        int error = -EBADF;
 421
 422        if (!f.file)
 423                return error;
 424        dentry = f.file->f_path.dentry;
 425        audit_inode(NULL, dentry, 0);
 426        error = mnt_want_write_file(f.file);
 427        if (!error) {
 428                error = setxattr(dentry, name, value, size, flags);
 429                mnt_drop_write_file(f.file);
 430        }
 431        fdput(f);
 432        return error;
 433}
 434
 435/*
 436 * Extended attribute GET operations
 437 */
 438static ssize_t
 439getxattr(struct dentry *d, const char __user *name, void __user *value,
 440         size_t size)
 441{
 442        ssize_t error;
 443        void *kvalue = NULL;
 444        void *vvalue = NULL;
 445        char kname[XATTR_NAME_MAX + 1];
 446
 447        error = strncpy_from_user(kname, name, sizeof(kname));
 448        if (error == 0 || error == sizeof(kname))
 449                error = -ERANGE;
 450        if (error < 0)
 451                return error;
 452
 453        if (size) {
 454                if (size > XATTR_SIZE_MAX)
 455                        size = XATTR_SIZE_MAX;
 456                kvalue = kzalloc(size, GFP_KERNEL | __GFP_NOWARN);
 457                if (!kvalue) {
 458                        vvalue = vmalloc(size);
 459                        if (!vvalue)
 460                                return -ENOMEM;
 461                        kvalue = vvalue;
 462                }
 463        }
 464
 465        error = vfs_getxattr(d, kname, kvalue, size);
 466        if (error > 0) {
 467                if ((strcmp(kname, XATTR_NAME_POSIX_ACL_ACCESS) == 0) ||
 468                    (strcmp(kname, XATTR_NAME_POSIX_ACL_DEFAULT) == 0))
 469                        posix_acl_fix_xattr_to_user(kvalue, size);
 470                if (size && copy_to_user(value, kvalue, error))
 471                        error = -EFAULT;
 472        } else if (error == -ERANGE && size >= XATTR_SIZE_MAX) {
 473                /* The file system tried to returned a value bigger
 474                   than XATTR_SIZE_MAX bytes. Not possible. */
 475                error = -E2BIG;
 476        }
 477        if (vvalue)
 478                vfree(vvalue);
 479        else
 480                kfree(kvalue);
 481        return error;
 482}
 483
 484SYSCALL_DEFINE4(getxattr, const char __user *, pathname,
 485                const char __user *, name, void __user *, value, size_t, size)
 486{
 487        struct path path;
 488        ssize_t error;
 489        unsigned int lookup_flags = LOOKUP_FOLLOW;
 490retry:
 491        error = user_path_at(AT_FDCWD, pathname, lookup_flags, &path);
 492        if (error)
 493                return error;
 494        error = getxattr(path.dentry, name, value, size);
 495        path_put(&path);
 496        if (retry_estale(error, lookup_flags)) {
 497                lookup_flags |= LOOKUP_REVAL;
 498                goto retry;
 499        }
 500        return error;
 501}
 502
 503SYSCALL_DEFINE4(lgetxattr, const char __user *, pathname,
 504                const char __user *, name, void __user *, value, size_t, size)
 505{
 506        struct path path;
 507        ssize_t error;
 508        unsigned int lookup_flags = 0;
 509retry:
 510        error = user_path_at(AT_FDCWD, pathname, lookup_flags, &path);
 511        if (error)
 512                return error;
 513        error = getxattr(path.dentry, name, value, size);
 514        path_put(&path);
 515        if (retry_estale(error, lookup_flags)) {
 516                lookup_flags |= LOOKUP_REVAL;
 517                goto retry;
 518        }
 519        return error;
 520}
 521
 522SYSCALL_DEFINE4(fgetxattr, int, fd, const char __user *, name,
 523                void __user *, value, size_t, size)
 524{
 525        struct fd f = fdget(fd);
 526        ssize_t error = -EBADF;
 527
 528        if (!f.file)
 529                return error;
 530        audit_inode(NULL, f.file->f_path.dentry, 0);
 531        error = getxattr(f.file->f_path.dentry, name, value, size);
 532        fdput(f);
 533        return error;
 534}
 535
 536/*
 537 * Extended attribute LIST operations
 538 */
 539static ssize_t
 540listxattr(struct dentry *d, char __user *list, size_t size)
 541{
 542        ssize_t error;
 543        char *klist = NULL;
 544        char *vlist = NULL;     /* If non-NULL, we used vmalloc() */
 545
 546        if (size) {
 547                if (size > XATTR_LIST_MAX)
 548                        size = XATTR_LIST_MAX;
 549                klist = kmalloc(size, __GFP_NOWARN | GFP_KERNEL);
 550                if (!klist) {
 551                        vlist = vmalloc(size);
 552                        if (!vlist)
 553                                return -ENOMEM;
 554                        klist = vlist;
 555                }
 556        }
 557
 558        error = vfs_listxattr(d, klist, size);
 559        if (error > 0) {
 560                if (size && copy_to_user(list, klist, error))
 561                        error = -EFAULT;
 562        } else if (error == -ERANGE && size >= XATTR_LIST_MAX) {
 563                /* The file system tried to returned a list bigger
 564                   than XATTR_LIST_MAX bytes. Not possible. */
 565                error = -E2BIG;
 566        }
 567        if (vlist)
 568                vfree(vlist);
 569        else
 570                kfree(klist);
 571        return error;
 572}
 573
 574SYSCALL_DEFINE3(listxattr, const char __user *, pathname, char __user *, list,
 575                size_t, size)
 576{
 577        struct path path;
 578        ssize_t error;
 579        unsigned int lookup_flags = LOOKUP_FOLLOW;
 580retry:
 581        error = user_path_at(AT_FDCWD, pathname, lookup_flags, &path);
 582        if (error)
 583                return error;
 584        error = listxattr(path.dentry, list, size);
 585        path_put(&path);
 586        if (retry_estale(error, lookup_flags)) {
 587                lookup_flags |= LOOKUP_REVAL;
 588                goto retry;
 589        }
 590        return error;
 591}
 592
 593SYSCALL_DEFINE3(llistxattr, const char __user *, pathname, char __user *, list,
 594                size_t, size)
 595{
 596        struct path path;
 597        ssize_t error;
 598        unsigned int lookup_flags = 0;
 599retry:
 600        error = user_path_at(AT_FDCWD, pathname, lookup_flags, &path);
 601        if (error)
 602                return error;
 603        error = listxattr(path.dentry, list, size);
 604        path_put(&path);
 605        if (retry_estale(error, lookup_flags)) {
 606                lookup_flags |= LOOKUP_REVAL;
 607                goto retry;
 608        }
 609        return error;
 610}
 611
 612SYSCALL_DEFINE3(flistxattr, int, fd, char __user *, list, size_t, size)
 613{
 614        struct fd f = fdget(fd);
 615        ssize_t error = -EBADF;
 616
 617        if (!f.file)
 618                return error;
 619        audit_inode(NULL, f.file->f_path.dentry, 0);
 620        error = listxattr(f.file->f_path.dentry, list, size);
 621        fdput(f);
 622        return error;
 623}
 624
 625/*
 626 * Extended attribute REMOVE operations
 627 */
 628static long
 629removexattr(struct dentry *d, const char __user *name)
 630{
 631        int error;
 632        char kname[XATTR_NAME_MAX + 1];
 633
 634        error = strncpy_from_user(kname, name, sizeof(kname));
 635        if (error == 0 || error == sizeof(kname))
 636                error = -ERANGE;
 637        if (error < 0)
 638                return error;
 639
 640        return vfs_removexattr(d, kname);
 641}
 642
 643SYSCALL_DEFINE2(removexattr, const char __user *, pathname,
 644                const char __user *, name)
 645{
 646        struct path path;
 647        int error;
 648        unsigned int lookup_flags = LOOKUP_FOLLOW;
 649retry:
 650        error = user_path_at(AT_FDCWD, pathname, lookup_flags, &path);
 651        if (error)
 652                return error;
 653        error = mnt_want_write(path.mnt);
 654        if (!error) {
 655                error = removexattr(path.dentry, name);
 656                mnt_drop_write(path.mnt);
 657        }
 658        path_put(&path);
 659        if (retry_estale(error, lookup_flags)) {
 660                lookup_flags |= LOOKUP_REVAL;
 661                goto retry;
 662        }
 663        return error;
 664}
 665
 666SYSCALL_DEFINE2(lremovexattr, const char __user *, pathname,
 667                const char __user *, name)
 668{
 669        struct path path;
 670        int error;
 671        unsigned int lookup_flags = 0;
 672retry:
 673        error = user_path_at(AT_FDCWD, pathname, lookup_flags, &path);
 674        if (error)
 675                return error;
 676        error = mnt_want_write(path.mnt);
 677        if (!error) {
 678                error = removexattr(path.dentry, name);
 679                mnt_drop_write(path.mnt);
 680        }
 681        path_put(&path);
 682        if (retry_estale(error, lookup_flags)) {
 683                lookup_flags |= LOOKUP_REVAL;
 684                goto retry;
 685        }
 686        return error;
 687}
 688
 689SYSCALL_DEFINE2(fremovexattr, int, fd, const char __user *, name)
 690{
 691        struct fd f = fdget(fd);
 692        struct dentry *dentry;
 693        int error = -EBADF;
 694
 695        if (!f.file)
 696                return error;
 697        dentry = f.file->f_path.dentry;
 698        audit_inode(NULL, dentry, 0);
 699        error = mnt_want_write_file(f.file);
 700        if (!error) {
 701                error = removexattr(dentry, name);
 702                mnt_drop_write_file(f.file);
 703        }
 704        fdput(f);
 705        return error;
 706}
 707
 708
 709static const char *
 710strcmp_prefix(const char *a, const char *a_prefix)
 711{
 712        while (*a_prefix && *a == *a_prefix) {
 713                a++;
 714                a_prefix++;
 715        }
 716        return *a_prefix ? NULL : a;
 717}
 718
 719/*
 720 * In order to implement different sets of xattr operations for each xattr
 721 * prefix with the generic xattr API, a filesystem should create a
 722 * null-terminated array of struct xattr_handler (one for each prefix) and
 723 * hang a pointer to it off of the s_xattr field of the superblock.
 724 *
 725 * The generic_fooxattr() functions will use this list to dispatch xattr
 726 * operations to the correct xattr_handler.
 727 */
 728#define for_each_xattr_handler(handlers, handler)               \
 729                for ((handler) = *(handlers)++;                 \
 730                        (handler) != NULL;                      \
 731                        (handler) = *(handlers)++)
 732
 733/*
 734 * Find the xattr_handler with the matching prefix.
 735 */
 736static const struct xattr_handler *
 737xattr_resolve_name(const struct xattr_handler **handlers, const char **name)
 738{
 739        const struct xattr_handler *handler;
 740
 741        if (!*name)
 742                return NULL;
 743
 744        for_each_xattr_handler(handlers, handler) {
 745                const char *n = strcmp_prefix(*name, handler->prefix);
 746                if (n) {
 747                        *name = n;
 748                        break;
 749                }
 750        }
 751        return handler;
 752}
 753
 754/*
 755 * Find the handler for the prefix and dispatch its get() operation.
 756 */
 757ssize_t
 758generic_getxattr(struct dentry *dentry, const char *name, void *buffer, size_t size)
 759{
 760        const struct xattr_handler *handler;
 761
 762        handler = xattr_resolve_name(dentry->d_sb->s_xattr, &name);
 763        if (!handler)
 764                return -EOPNOTSUPP;
 765        return handler->get(dentry, name, buffer, size, handler->flags);
 766}
 767
 768/*
 769 * Combine the results of the list() operation from every xattr_handler in the
 770 * list.
 771 */
 772ssize_t
 773generic_listxattr(struct dentry *dentry, char *buffer, size_t buffer_size)
 774{
 775        const struct xattr_handler *handler, **handlers = dentry->d_sb->s_xattr;
 776        unsigned int size = 0;
 777
 778        if (!buffer) {
 779                for_each_xattr_handler(handlers, handler) {
 780                        size += handler->list(dentry, NULL, 0, NULL, 0,
 781                                              handler->flags);
 782                }
 783        } else {
 784                char *buf = buffer;
 785
 786                for_each_xattr_handler(handlers, handler) {
 787                        size = handler->list(dentry, buf, buffer_size,
 788                                             NULL, 0, handler->flags);
 789                        if (size > buffer_size)
 790                                return -ERANGE;
 791                        buf += size;
 792                        buffer_size -= size;
 793                }
 794                size = buf - buffer;
 795        }
 796        return size;
 797}
 798
 799/*
 800 * Find the handler for the prefix and dispatch its set() operation.
 801 */
 802int
 803generic_setxattr(struct dentry *dentry, const char *name, const void *value, size_t size, int flags)
 804{
 805        const struct xattr_handler *handler;
 806
 807        if (size == 0)
 808                value = "";  /* empty EA, do not remove */
 809        handler = xattr_resolve_name(dentry->d_sb->s_xattr, &name);
 810        if (!handler)
 811                return -EOPNOTSUPP;
 812        return handler->set(dentry, name, value, size, flags, handler->flags);
 813}
 814
 815/*
 816 * Find the handler for the prefix and dispatch its set() operation to remove
 817 * any associated extended attribute.
 818 */
 819int
 820generic_removexattr(struct dentry *dentry, const char *name)
 821{
 822        const struct xattr_handler *handler;
 823
 824        handler = xattr_resolve_name(dentry->d_sb->s_xattr, &name);
 825        if (!handler)
 826                return -EOPNOTSUPP;
 827        return handler->set(dentry, name, NULL, 0,
 828                            XATTR_REPLACE, handler->flags);
 829}
 830
 831EXPORT_SYMBOL(generic_getxattr);
 832EXPORT_SYMBOL(generic_listxattr);
 833EXPORT_SYMBOL(generic_setxattr);
 834EXPORT_SYMBOL(generic_removexattr);
 835
 836/*
 837 * Allocate new xattr and copy in the value; but leave the name to callers.
 838 */
 839struct simple_xattr *simple_xattr_alloc(const void *value, size_t size)
 840{
 841        struct simple_xattr *new_xattr;
 842        size_t len;
 843
 844        /* wrap around? */
 845        len = sizeof(*new_xattr) + size;
 846        if (len <= sizeof(*new_xattr))
 847                return NULL;
 848
 849        new_xattr = kmalloc(len, GFP_KERNEL);
 850        if (!new_xattr)
 851                return NULL;
 852
 853        new_xattr->size = size;
 854        memcpy(new_xattr->value, value, size);
 855        return new_xattr;
 856}
 857
 858/*
 859 * xattr GET operation for in-memory/pseudo filesystems
 860 */
 861int simple_xattr_get(struct simple_xattrs *xattrs, const char *name,
 862                     void *buffer, size_t size)
 863{
 864        struct simple_xattr *xattr;
 865        int ret = -ENODATA;
 866
 867        spin_lock(&xattrs->lock);
 868        list_for_each_entry(xattr, &xattrs->head, list) {
 869                if (strcmp(name, xattr->name))
 870                        continue;
 871
 872                ret = xattr->size;
 873                if (buffer) {
 874                        if (size < xattr->size)
 875                                ret = -ERANGE;
 876                        else
 877                                memcpy(buffer, xattr->value, xattr->size);
 878                }
 879                break;
 880        }
 881        spin_unlock(&xattrs->lock);
 882        return ret;
 883}
 884
 885static int __simple_xattr_set(struct simple_xattrs *xattrs, const char *name,
 886                              const void *value, size_t size, int flags)
 887{
 888        struct simple_xattr *xattr;
 889        struct simple_xattr *new_xattr = NULL;
 890        int err = 0;
 891
 892        /* value == NULL means remove */
 893        if (value) {
 894                new_xattr = simple_xattr_alloc(value, size);
 895                if (!new_xattr)
 896                        return -ENOMEM;
 897
 898                new_xattr->name = kstrdup(name, GFP_KERNEL);
 899                if (!new_xattr->name) {
 900                        kfree(new_xattr);
 901                        return -ENOMEM;
 902                }
 903        }
 904
 905        spin_lock(&xattrs->lock);
 906        list_for_each_entry(xattr, &xattrs->head, list) {
 907                if (!strcmp(name, xattr->name)) {
 908                        if (flags & XATTR_CREATE) {
 909                                xattr = new_xattr;
 910                                err = -EEXIST;
 911                        } else if (new_xattr) {
 912                                list_replace(&xattr->list, &new_xattr->list);
 913                        } else {
 914                                list_del(&xattr->list);
 915                        }
 916                        goto out;
 917                }
 918        }
 919        if (flags & XATTR_REPLACE) {
 920                xattr = new_xattr;
 921                err = -ENODATA;
 922        } else {
 923                list_add(&new_xattr->list, &xattrs->head);
 924                xattr = NULL;
 925        }
 926out:
 927        spin_unlock(&xattrs->lock);
 928        if (xattr) {
 929                kfree(xattr->name);
 930                kfree(xattr);
 931        }
 932        return err;
 933
 934}
 935
 936/**
 937 * simple_xattr_set - xattr SET operation for in-memory/pseudo filesystems
 938 * @xattrs: target simple_xattr list
 939 * @name: name of the new extended attribute
 940 * @value: value of the new xattr. If %NULL, will remove the attribute
 941 * @size: size of the new xattr
 942 * @flags: %XATTR_{CREATE|REPLACE}
 943 *
 944 * %XATTR_CREATE is set, the xattr shouldn't exist already; otherwise fails
 945 * with -EEXIST.  If %XATTR_REPLACE is set, the xattr should exist;
 946 * otherwise, fails with -ENODATA.
 947 *
 948 * Returns 0 on success, -errno on failure.
 949 */
 950int simple_xattr_set(struct simple_xattrs *xattrs, const char *name,
 951                     const void *value, size_t size, int flags)
 952{
 953        if (size == 0)
 954                value = ""; /* empty EA, do not remove */
 955        return __simple_xattr_set(xattrs, name, value, size, flags);
 956}
 957
 958/*
 959 * xattr REMOVE operation for in-memory/pseudo filesystems
 960 */
 961int simple_xattr_remove(struct simple_xattrs *xattrs, const char *name)
 962{
 963        return __simple_xattr_set(xattrs, name, NULL, 0, XATTR_REPLACE);
 964}
 965
 966static bool xattr_is_trusted(const char *name)
 967{
 968        return !strncmp(name, XATTR_TRUSTED_PREFIX, XATTR_TRUSTED_PREFIX_LEN);
 969}
 970
 971/*
 972 * xattr LIST operation for in-memory/pseudo filesystems
 973 */
 974ssize_t simple_xattr_list(struct simple_xattrs *xattrs, char *buffer,
 975                          size_t size)
 976{
 977        bool trusted = capable(CAP_SYS_ADMIN);
 978        struct simple_xattr *xattr;
 979        size_t used = 0;
 980
 981        spin_lock(&xattrs->lock);
 982        list_for_each_entry(xattr, &xattrs->head, list) {
 983                size_t len;
 984
 985                /* skip "trusted." attributes for unprivileged callers */
 986                if (!trusted && xattr_is_trusted(xattr->name))
 987                        continue;
 988
 989                len = strlen(xattr->name) + 1;
 990                used += len;
 991                if (buffer) {
 992                        if (size < used) {
 993                                used = -ERANGE;
 994                                break;
 995                        }
 996                        memcpy(buffer, xattr->name, len);
 997                        buffer += len;
 998                }
 999        }
1000        spin_unlock(&xattrs->lock);
1001
1002        return used;
1003}
1004
1005/*
1006 * Adds an extended attribute to the list
1007 */
1008void simple_xattr_list_add(struct simple_xattrs *xattrs,
1009                           struct simple_xattr *new_xattr)
1010{
1011        spin_lock(&xattrs->lock);
1012        list_add(&new_xattr->list, &xattrs->head);
1013        spin_unlock(&xattrs->lock);
1014}
1015
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.