457c899653991 (Thomas Gleixner 2019-05-19 13:08:55 +0100 1) // SPDX-License-Identifier: GPL-2.0-only
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 2) /*
5c8ebd57b6a51 (Christoph Hellwig 2013-12-20 05:16:37 -0800 3) * Copyright (C) 2002,2003 by Andreas Gruenbacher <a.gruenbacher@computer.org>
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 4) *
5c8ebd57b6a51 (Christoph Hellwig 2013-12-20 05:16:37 -0800 5) * Fixes from William Schumacher incorporated on 15 March 2001.
5c8ebd57b6a51 (Christoph Hellwig 2013-12-20 05:16:37 -0800 6) * (Reported by Charles Bertsch, <CBertsch@microtest.com>).
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 7) */
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 8)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 9) /*
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 10) * This file contains generic functions for manipulating
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 11) * POSIX 1003.1e draft standard 17 ACLs.
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 12) */
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 13)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 14) #include <linux/kernel.h>
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 15) #include <linux/slab.h>
60063497a95e7 (Arun Sharma 2011-07-26 16:09:06 -0700 16) #include <linux/atomic.h>
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 17) #include <linux/fs.h>
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 18) #include <linux/sched.h>
5b825c3af1d8a (Ingo Molnar 2017-02-02 17:54:15 +0100 19) #include <linux/cred.h>
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 20) #include <linux/posix_acl.h>
5c8ebd57b6a51 (Christoph Hellwig 2013-12-20 05:16:37 -0800 21) #include <linux/posix_acl_xattr.h>
2aeccbe957d0d (Christoph Hellwig 2013-12-20 05:16:40 -0800 22) #include <linux/xattr.h>
630d9c47274aa (Paul Gortmaker 2011-11-16 23:57:37 -0500 23) #include <linux/export.h>
5c8ebd57b6a51 (Christoph Hellwig 2013-12-20 05:16:37 -0800 24) #include <linux/user_namespace.h>
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 25)
04c57f4501909 (Andreas Gruenbacher 2016-03-24 14:38:38 +0100 26) static struct posix_acl **acl_by_type(struct inode *inode, int type)
0afaa12047a45 (Andrew Morton 2014-01-21 15:48:42 -0800 27) {
0afaa12047a45 (Andrew Morton 2014-01-21 15:48:42 -0800 28) switch (type) {
0afaa12047a45 (Andrew Morton 2014-01-21 15:48:42 -0800 29) case ACL_TYPE_ACCESS:
0afaa12047a45 (Andrew Morton 2014-01-21 15:48:42 -0800 30) return &inode->i_acl;
0afaa12047a45 (Andrew Morton 2014-01-21 15:48:42 -0800 31) case ACL_TYPE_DEFAULT:
0afaa12047a45 (Andrew Morton 2014-01-21 15:48:42 -0800 32) return &inode->i_default_acl;
0afaa12047a45 (Andrew Morton 2014-01-21 15:48:42 -0800 33) default:
0afaa12047a45 (Andrew Morton 2014-01-21 15:48:42 -0800 34) BUG();
0afaa12047a45 (Andrew Morton 2014-01-21 15:48:42 -0800 35) }
0afaa12047a45 (Andrew Morton 2014-01-21 15:48:42 -0800 36) }
0afaa12047a45 (Andrew Morton 2014-01-21 15:48:42 -0800 37)
0afaa12047a45 (Andrew Morton 2014-01-21 15:48:42 -0800 38) struct posix_acl *get_cached_acl(struct inode *inode, int type)
0afaa12047a45 (Andrew Morton 2014-01-21 15:48:42 -0800 39) {
0afaa12047a45 (Andrew Morton 2014-01-21 15:48:42 -0800 40) struct posix_acl **p = acl_by_type(inode, type);
b8a7a3a667472 (Andreas Gruenbacher 2016-03-24 14:38:37 +0100 41) struct posix_acl *acl;
b8a7a3a667472 (Andreas Gruenbacher 2016-03-24 14:38:37 +0100 42)
b8a7a3a667472 (Andreas Gruenbacher 2016-03-24 14:38:37 +0100 43) for (;;) {
b8a7a3a667472 (Andreas Gruenbacher 2016-03-24 14:38:37 +0100 44) rcu_read_lock();
b8a7a3a667472 (Andreas Gruenbacher 2016-03-24 14:38:37 +0100 45) acl = rcu_dereference(*p);
b8a7a3a667472 (Andreas Gruenbacher 2016-03-24 14:38:37 +0100 46) if (!acl || is_uncached_acl(acl) ||
66717260545b6 (Elena Reshetova 2017-11-29 13:19:31 +0200 47) refcount_inc_not_zero(&acl->a_refcount))
b8a7a3a667472 (Andreas Gruenbacher 2016-03-24 14:38:37 +0100 48) break;
b8a7a3a667472 (Andreas Gruenbacher 2016-03-24 14:38:37 +0100 49) rcu_read_unlock();
b8a7a3a667472 (Andreas Gruenbacher 2016-03-24 14:38:37 +0100 50) cpu_relax();
0afaa12047a45 (Andrew Morton 2014-01-21 15:48:42 -0800 51) }
b8a7a3a667472 (Andreas Gruenbacher 2016-03-24 14:38:37 +0100 52) rcu_read_unlock();
0afaa12047a45 (Andrew Morton 2014-01-21 15:48:42 -0800 53) return acl;
0afaa12047a45 (Andrew Morton 2014-01-21 15:48:42 -0800 54) }
0afaa12047a45 (Andrew Morton 2014-01-21 15:48:42 -0800 55) EXPORT_SYMBOL(get_cached_acl);
0afaa12047a45 (Andrew Morton 2014-01-21 15:48:42 -0800 56)
0afaa12047a45 (Andrew Morton 2014-01-21 15:48:42 -0800 57) struct posix_acl *get_cached_acl_rcu(struct inode *inode, int type)
0afaa12047a45 (Andrew Morton 2014-01-21 15:48:42 -0800 58) {
0afaa12047a45 (Andrew Morton 2014-01-21 15:48:42 -0800 59) return rcu_dereference(*acl_by_type(inode, type));
0afaa12047a45 (Andrew Morton 2014-01-21 15:48:42 -0800 60) }
0afaa12047a45 (Andrew Morton 2014-01-21 15:48:42 -0800 61) EXPORT_SYMBOL(get_cached_acl_rcu);
0afaa12047a45 (Andrew Morton 2014-01-21 15:48:42 -0800 62)
0afaa12047a45 (Andrew Morton 2014-01-21 15:48:42 -0800 63) void set_cached_acl(struct inode *inode, int type, struct posix_acl *acl)
0afaa12047a45 (Andrew Morton 2014-01-21 15:48:42 -0800 64) {
0afaa12047a45 (Andrew Morton 2014-01-21 15:48:42 -0800 65) struct posix_acl **p = acl_by_type(inode, type);
0afaa12047a45 (Andrew Morton 2014-01-21 15:48:42 -0800 66) struct posix_acl *old;
b8a7a3a667472 (Andreas Gruenbacher 2016-03-24 14:38:37 +0100 67)
b8a7a3a667472 (Andreas Gruenbacher 2016-03-24 14:38:37 +0100 68) old = xchg(p, posix_acl_dup(acl));
b8a7a3a667472 (Andreas Gruenbacher 2016-03-24 14:38:37 +0100 69) if (!is_uncached_acl(old))
0afaa12047a45 (Andrew Morton 2014-01-21 15:48:42 -0800 70) posix_acl_release(old);
0afaa12047a45 (Andrew Morton 2014-01-21 15:48:42 -0800 71) }
0afaa12047a45 (Andrew Morton 2014-01-21 15:48:42 -0800 72) EXPORT_SYMBOL(set_cached_acl);
0afaa12047a45 (Andrew Morton 2014-01-21 15:48:42 -0800 73)
b8a7a3a667472 (Andreas Gruenbacher 2016-03-24 14:38:37 +0100 74) static void __forget_cached_acl(struct posix_acl **p)
0afaa12047a45 (Andrew Morton 2014-01-21 15:48:42 -0800 75) {
0afaa12047a45 (Andrew Morton 2014-01-21 15:48:42 -0800 76) struct posix_acl *old;
b8a7a3a667472 (Andreas Gruenbacher 2016-03-24 14:38:37 +0100 77)
b8a7a3a667472 (Andreas Gruenbacher 2016-03-24 14:38:37 +0100 78) old = xchg(p, ACL_NOT_CACHED);
b8a7a3a667472 (Andreas Gruenbacher 2016-03-24 14:38:37 +0100 79) if (!is_uncached_acl(old))
0afaa12047a45 (Andrew Morton 2014-01-21 15:48:42 -0800 80) posix_acl_release(old);
0afaa12047a45 (Andrew Morton 2014-01-21 15:48:42 -0800 81) }
b8a7a3a667472 (Andreas Gruenbacher 2016-03-24 14:38:37 +0100 82)
b8a7a3a667472 (Andreas Gruenbacher 2016-03-24 14:38:37 +0100 83) void forget_cached_acl(struct inode *inode, int type)
b8a7a3a667472 (Andreas Gruenbacher 2016-03-24 14:38:37 +0100 84) {
b8a7a3a667472 (Andreas Gruenbacher 2016-03-24 14:38:37 +0100 85) __forget_cached_acl(acl_by_type(inode, type));
b8a7a3a667472 (Andreas Gruenbacher 2016-03-24 14:38:37 +0100 86) }
0afaa12047a45 (Andrew Morton 2014-01-21 15:48:42 -0800 87) EXPORT_SYMBOL(forget_cached_acl);
0afaa12047a45 (Andrew Morton 2014-01-21 15:48:42 -0800 88)
0afaa12047a45 (Andrew Morton 2014-01-21 15:48:42 -0800 89) void forget_all_cached_acls(struct inode *inode)
0afaa12047a45 (Andrew Morton 2014-01-21 15:48:42 -0800 90) {
b8a7a3a667472 (Andreas Gruenbacher 2016-03-24 14:38:37 +0100 91) __forget_cached_acl(&inode->i_acl);
b8a7a3a667472 (Andreas Gruenbacher 2016-03-24 14:38:37 +0100 92) __forget_cached_acl(&inode->i_default_acl);
0afaa12047a45 (Andrew Morton 2014-01-21 15:48:42 -0800 93) }
0afaa12047a45 (Andrew Morton 2014-01-21 15:48:42 -0800 94) EXPORT_SYMBOL(forget_all_cached_acls);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 95)
2982baa2ae31e (Christoph Hellwig 2013-12-20 05:16:38 -0800 96) struct posix_acl *get_acl(struct inode *inode, int type)
2982baa2ae31e (Christoph Hellwig 2013-12-20 05:16:38 -0800 97) {
b8a7a3a667472 (Andreas Gruenbacher 2016-03-24 14:38:37 +0100 98) void *sentinel;
b8a7a3a667472 (Andreas Gruenbacher 2016-03-24 14:38:37 +0100 99) struct posix_acl **p;
2982baa2ae31e (Christoph Hellwig 2013-12-20 05:16:38 -0800 100) struct posix_acl *acl;
2982baa2ae31e (Christoph Hellwig 2013-12-20 05:16:38 -0800 101)
b8a7a3a667472 (Andreas Gruenbacher 2016-03-24 14:38:37 +0100 102) /*
b8a7a3a667472 (Andreas Gruenbacher 2016-03-24 14:38:37 +0100 103) * The sentinel is used to detect when another operation like
b8a7a3a667472 (Andreas Gruenbacher 2016-03-24 14:38:37 +0100 104) * set_cached_acl() or forget_cached_acl() races with get_acl().
b8a7a3a667472 (Andreas Gruenbacher 2016-03-24 14:38:37 +0100 105) * It is guaranteed that is_uncached_acl(sentinel) is true.
b8a7a3a667472 (Andreas Gruenbacher 2016-03-24 14:38:37 +0100 106) */
b8a7a3a667472 (Andreas Gruenbacher 2016-03-24 14:38:37 +0100 107)
2982baa2ae31e (Christoph Hellwig 2013-12-20 05:16:38 -0800 108) acl = get_cached_acl(inode, type);
b8a7a3a667472 (Andreas Gruenbacher 2016-03-24 14:38:37 +0100 109) if (!is_uncached_acl(acl))
2982baa2ae31e (Christoph Hellwig 2013-12-20 05:16:38 -0800 110) return acl;
2982baa2ae31e (Christoph Hellwig 2013-12-20 05:16:38 -0800 111)
2982baa2ae31e (Christoph Hellwig 2013-12-20 05:16:38 -0800 112) if (!IS_POSIXACL(inode))
2982baa2ae31e (Christoph Hellwig 2013-12-20 05:16:38 -0800 113) return NULL;
2982baa2ae31e (Christoph Hellwig 2013-12-20 05:16:38 -0800 114)
b8a7a3a667472 (Andreas Gruenbacher 2016-03-24 14:38:37 +0100 115) sentinel = uncached_acl_sentinel(current);
b8a7a3a667472 (Andreas Gruenbacher 2016-03-24 14:38:37 +0100 116) p = acl_by_type(inode, type);
b8a7a3a667472 (Andreas Gruenbacher 2016-03-24 14:38:37 +0100 117)
b8a7a3a667472 (Andreas Gruenbacher 2016-03-24 14:38:37 +0100 118) /*
b8a7a3a667472 (Andreas Gruenbacher 2016-03-24 14:38:37 +0100 119) * If the ACL isn't being read yet, set our sentinel. Otherwise, the
b8a7a3a667472 (Andreas Gruenbacher 2016-03-24 14:38:37 +0100 120) * current value of the ACL will not be ACL_NOT_CACHED and so our own
b8a7a3a667472 (Andreas Gruenbacher 2016-03-24 14:38:37 +0100 121) * sentinel will not be set; another task will update the cache. We
b8a7a3a667472 (Andreas Gruenbacher 2016-03-24 14:38:37 +0100 122) * could wait for that other task to complete its job, but it's easier
b8a7a3a667472 (Andreas Gruenbacher 2016-03-24 14:38:37 +0100 123) * to just call ->get_acl to fetch the ACL ourself. (This is going to
b8a7a3a667472 (Andreas Gruenbacher 2016-03-24 14:38:37 +0100 124) * be an unlikely race.)
b8a7a3a667472 (Andreas Gruenbacher 2016-03-24 14:38:37 +0100 125) */
b8a7a3a667472 (Andreas Gruenbacher 2016-03-24 14:38:37 +0100 126) if (cmpxchg(p, ACL_NOT_CACHED, sentinel) != ACL_NOT_CACHED)
b8a7a3a667472 (Andreas Gruenbacher 2016-03-24 14:38:37 +0100 127) /* fall through */ ;
b8a7a3a667472 (Andreas Gruenbacher 2016-03-24 14:38:37 +0100 128)
2982baa2ae31e (Christoph Hellwig 2013-12-20 05:16:38 -0800 129) /*
b8a7a3a667472 (Andreas Gruenbacher 2016-03-24 14:38:37 +0100 130) * Normally, the ACL returned by ->get_acl will be cached.
b8a7a3a667472 (Andreas Gruenbacher 2016-03-24 14:38:37 +0100 131) * A filesystem can prevent that by calling
b8a7a3a667472 (Andreas Gruenbacher 2016-03-24 14:38:37 +0100 132) * forget_cached_acl(inode, type) in ->get_acl.
2982baa2ae31e (Christoph Hellwig 2013-12-20 05:16:38 -0800 133) *
2982baa2ae31e (Christoph Hellwig 2013-12-20 05:16:38 -0800 134) * If the filesystem doesn't have a get_acl() function at all, we'll
2982baa2ae31e (Christoph Hellwig 2013-12-20 05:16:38 -0800 135) * just create the negative cache entry.
2982baa2ae31e (Christoph Hellwig 2013-12-20 05:16:38 -0800 136) */
2982baa2ae31e (Christoph Hellwig 2013-12-20 05:16:38 -0800 137) if (!inode->i_op->get_acl) {
2982baa2ae31e (Christoph Hellwig 2013-12-20 05:16:38 -0800 138) set_cached_acl(inode, type, NULL);
2982baa2ae31e (Christoph Hellwig 2013-12-20 05:16:38 -0800 139) return NULL;
2982baa2ae31e (Christoph Hellwig 2013-12-20 05:16:38 -0800 140) }
b8a7a3a667472 (Andreas Gruenbacher 2016-03-24 14:38:37 +0100 141) acl = inode->i_op->get_acl(inode, type);
b8a7a3a667472 (Andreas Gruenbacher 2016-03-24 14:38:37 +0100 142)
b8a7a3a667472 (Andreas Gruenbacher 2016-03-24 14:38:37 +0100 143) if (IS_ERR(acl)) {
b8a7a3a667472 (Andreas Gruenbacher 2016-03-24 14:38:37 +0100 144) /*
b8a7a3a667472 (Andreas Gruenbacher 2016-03-24 14:38:37 +0100 145) * Remove our sentinel so that we don't block future attempts
b8a7a3a667472 (Andreas Gruenbacher 2016-03-24 14:38:37 +0100 146) * to cache the ACL.
b8a7a3a667472 (Andreas Gruenbacher 2016-03-24 14:38:37 +0100 147) */
b8a7a3a667472 (Andreas Gruenbacher 2016-03-24 14:38:37 +0100 148) cmpxchg(p, sentinel, ACL_NOT_CACHED);
b8a7a3a667472 (Andreas Gruenbacher 2016-03-24 14:38:37 +0100 149) return acl;
b8a7a3a667472 (Andreas Gruenbacher 2016-03-24 14:38:37 +0100 150) }
b8a7a3a667472 (Andreas Gruenbacher 2016-03-24 14:38:37 +0100 151)
b8a7a3a667472 (Andreas Gruenbacher 2016-03-24 14:38:37 +0100 152) /*
b8a7a3a667472 (Andreas Gruenbacher 2016-03-24 14:38:37 +0100 153) * Cache the result, but only if our sentinel is still in place.
b8a7a3a667472 (Andreas Gruenbacher 2016-03-24 14:38:37 +0100 154) */
b8a7a3a667472 (Andreas Gruenbacher 2016-03-24 14:38:37 +0100 155) posix_acl_dup(acl);
b8a7a3a667472 (Andreas Gruenbacher 2016-03-24 14:38:37 +0100 156) if (unlikely(cmpxchg(p, sentinel, acl) != sentinel))
b8a7a3a667472 (Andreas Gruenbacher 2016-03-24 14:38:37 +0100 157) posix_acl_release(acl);
b8a7a3a667472 (Andreas Gruenbacher 2016-03-24 14:38:37 +0100 158) return acl;
2982baa2ae31e (Christoph Hellwig 2013-12-20 05:16:38 -0800 159) }
2982baa2ae31e (Christoph Hellwig 2013-12-20 05:16:38 -0800 160) EXPORT_SYMBOL(get_acl);
2982baa2ae31e (Christoph Hellwig 2013-12-20 05:16:38 -0800 161)
f61f6da0d5384 (Chuck Lever 2011-01-21 03:05:38 +0000 162) /*
f61f6da0d5384 (Chuck Lever 2011-01-21 03:05:38 +0000 163) * Init a fresh posix_acl
f61f6da0d5384 (Chuck Lever 2011-01-21 03:05:38 +0000 164) */
f61f6da0d5384 (Chuck Lever 2011-01-21 03:05:38 +0000 165) void
f61f6da0d5384 (Chuck Lever 2011-01-21 03:05:38 +0000 166) posix_acl_init(struct posix_acl *acl, int count)
f61f6da0d5384 (Chuck Lever 2011-01-21 03:05:38 +0000 167) {
66717260545b6 (Elena Reshetova 2017-11-29 13:19:31 +0200 168) refcount_set(&acl->a_refcount, 1);
f61f6da0d5384 (Chuck Lever 2011-01-21 03:05:38 +0000 169) acl->a_count = count;
f61f6da0d5384 (Chuck Lever 2011-01-21 03:05:38 +0000 170) }
0afaa12047a45 (Andrew Morton 2014-01-21 15:48:42 -0800 171) EXPORT_SYMBOL(posix_acl_init);
f61f6da0d5384 (Chuck Lever 2011-01-21 03:05:38 +0000 172)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 173) /*
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 174) * Allocate a new ACL with the specified number of entries.
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 175) */
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 176) struct posix_acl *
dd0fc66fb33cd (Al Viro 2005-10-07 07:46:04 +0100 177) posix_acl_alloc(int count, gfp_t flags)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 178) {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 179) const size_t size = sizeof(struct posix_acl) +
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 180) count * sizeof(struct posix_acl_entry);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 181) struct posix_acl *acl = kmalloc(size, flags);
f61f6da0d5384 (Chuck Lever 2011-01-21 03:05:38 +0000 182) if (acl)
f61f6da0d5384 (Chuck Lever 2011-01-21 03:05:38 +0000 183) posix_acl_init(acl, count);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 184) return acl;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 185) }
0afaa12047a45 (Andrew Morton 2014-01-21 15:48:42 -0800 186) EXPORT_SYMBOL(posix_acl_alloc);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 187)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 188) /*
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 189) * Clone an ACL.
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 190) */
edde854e8bb34 (Al Viro 2011-07-23 03:27:37 -0400 191) static struct posix_acl *
dd0fc66fb33cd (Al Viro 2005-10-07 07:46:04 +0100 192) posix_acl_clone(const struct posix_acl *acl, gfp_t flags)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 193) {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 194) struct posix_acl *clone = NULL;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 195)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 196) if (acl) {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 197) int size = sizeof(struct posix_acl) + acl->a_count *
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 198) sizeof(struct posix_acl_entry);
52978be636374 (Alexey Dobriyan 2006-09-30 23:27:21 -0700 199) clone = kmemdup(acl, size, flags);
52978be636374 (Alexey Dobriyan 2006-09-30 23:27:21 -0700 200) if (clone)
66717260545b6 (Elena Reshetova 2017-11-29 13:19:31 +0200 201) refcount_set(&clone->a_refcount, 1);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 202) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 203) return clone;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 204) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 205)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 206) /*
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 207) * Check if an acl is valid. Returns 0 if it is, or -E... otherwise.
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 208) */
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 209) int
0d4d717f25834 (Eric W. Biederman 2016-06-27 16:04:06 -0500 210) posix_acl_valid(struct user_namespace *user_ns, const struct posix_acl *acl)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 211) {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 212) const struct posix_acl_entry *pa, *pe;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 213) int state = ACL_USER_OBJ;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 214) int needs_mask = 0;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 215)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 216) FOREACH_ACL_ENTRY(pa, acl, pe) {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 217) if (pa->e_perm & ~(ACL_READ|ACL_WRITE|ACL_EXECUTE))
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 218) return -EINVAL;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 219) switch (pa->e_tag) {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 220) case ACL_USER_OBJ:
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 221) if (state == ACL_USER_OBJ) {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 222) state = ACL_USER;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 223) break;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 224) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 225) return -EINVAL;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 226)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 227) case ACL_USER:
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 228) if (state != ACL_USER)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 229) return -EINVAL;
0d4d717f25834 (Eric W. Biederman 2016-06-27 16:04:06 -0500 230) if (!kuid_has_mapping(user_ns, pa->e_uid))
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 231) return -EINVAL;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 232) needs_mask = 1;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 233) break;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 234)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 235) case ACL_GROUP_OBJ:
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 236) if (state == ACL_USER) {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 237) state = ACL_GROUP;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 238) break;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 239) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 240) return -EINVAL;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 241)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 242) case ACL_GROUP:
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 243) if (state != ACL_GROUP)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 244) return -EINVAL;
0d4d717f25834 (Eric W. Biederman 2016-06-27 16:04:06 -0500 245) if (!kgid_has_mapping(user_ns, pa->e_gid))
2f6f0654ab619 (Eric W. Biederman 2012-02-07 18:52:57 -0800 246) return -EINVAL;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 247) needs_mask = 1;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 248) break;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 249)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 250) case ACL_MASK:
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 251) if (state != ACL_GROUP)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 252) return -EINVAL;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 253) state = ACL_OTHER;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 254) break;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 255)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 256) case ACL_OTHER:
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 257) if (state == ACL_OTHER ||
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 258) (state == ACL_GROUP && !needs_mask)) {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 259) state = 0;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 260) break;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 261) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 262) return -EINVAL;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 263)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 264) default:
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 265) return -EINVAL;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 266) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 267) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 268) if (state == 0)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 269) return 0;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 270) return -EINVAL;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 271) }
0afaa12047a45 (Andrew Morton 2014-01-21 15:48:42 -0800 272) EXPORT_SYMBOL(posix_acl_valid);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 273)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 274) /*
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 275) * Returns 0 if the acl can be exactly represented in the traditional
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 276) * file mode permission bits, or else 1. Returns -E... on error.
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 277) */
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 278) int
d6952123b53cc (Al Viro 2011-07-23 18:56:36 -0400 279) posix_acl_equiv_mode(const struct posix_acl *acl, umode_t *mode_p)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 280) {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 281) const struct posix_acl_entry *pa, *pe;
d6952123b53cc (Al Viro 2011-07-23 18:56:36 -0400 282) umode_t mode = 0;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 283) int not_equiv = 0;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 284)
50c6e282bdf5e (Christoph Hellwig 2014-05-04 13:03:32 +0200 285) /*
50c6e282bdf5e (Christoph Hellwig 2014-05-04 13:03:32 +0200 286) * A null ACL can always be presented as mode bits.
50c6e282bdf5e (Christoph Hellwig 2014-05-04 13:03:32 +0200 287) */
50c6e282bdf5e (Christoph Hellwig 2014-05-04 13:03:32 +0200 288) if (!acl)
50c6e282bdf5e (Christoph Hellwig 2014-05-04 13:03:32 +0200 289) return 0;
50c6e282bdf5e (Christoph Hellwig 2014-05-04 13:03:32 +0200 290)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 291) FOREACH_ACL_ENTRY(pa, acl, pe) {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 292) switch (pa->e_tag) {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 293) case ACL_USER_OBJ:
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 294) mode |= (pa->e_perm & S_IRWXO) << 6;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 295) break;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 296) case ACL_GROUP_OBJ:
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 297) mode |= (pa->e_perm & S_IRWXO) << 3;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 298) break;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 299) case ACL_OTHER:
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 300) mode |= pa->e_perm & S_IRWXO;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 301) break;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 302) case ACL_MASK:
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 303) mode = (mode & ~S_IRWXG) |
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 304) ((pa->e_perm & S_IRWXO) << 3);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 305) not_equiv = 1;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 306) break;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 307) case ACL_USER:
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 308) case ACL_GROUP:
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 309) not_equiv = 1;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 310) break;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 311) default:
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 312) return -EINVAL;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 313) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 314) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 315) if (mode_p)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 316) *mode_p = (*mode_p & ~S_IRWXUGO) | mode;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 317) return not_equiv;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 318) }
0afaa12047a45 (Andrew Morton 2014-01-21 15:48:42 -0800 319) EXPORT_SYMBOL(posix_acl_equiv_mode);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 320)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 321) /*
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 322) * Create an ACL representing the file mode permission bits of an inode.
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 323) */
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 324) struct posix_acl *
3a5fba19b080b (Al Viro 2011-07-23 19:01:48 -0400 325) posix_acl_from_mode(umode_t mode, gfp_t flags)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 326) {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 327) struct posix_acl *acl = posix_acl_alloc(3, flags);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 328) if (!acl)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 329) return ERR_PTR(-ENOMEM);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 330)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 331) acl->a_entries[0].e_tag = ACL_USER_OBJ;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 332) acl->a_entries[0].e_perm = (mode & S_IRWXU) >> 6;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 333)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 334) acl->a_entries[1].e_tag = ACL_GROUP_OBJ;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 335) acl->a_entries[1].e_perm = (mode & S_IRWXG) >> 3;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 336)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 337) acl->a_entries[2].e_tag = ACL_OTHER;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 338) acl->a_entries[2].e_perm = (mode & S_IRWXO);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 339) return acl;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 340) }
0afaa12047a45 (Andrew Morton 2014-01-21 15:48:42 -0800 341) EXPORT_SYMBOL(posix_acl_from_mode);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 342)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 343) /*
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 344) * Return 0 if current is granted want access to the inode
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 345) * by the acl. Returns -E... otherwise.
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 346) */
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 347) int
47291baa8ddfd (Christian Brauner 2021-01-21 14:19:24 +0100 348) posix_acl_permission(struct user_namespace *mnt_userns, struct inode *inode,
47291baa8ddfd (Christian Brauner 2021-01-21 14:19:24 +0100 349) const struct posix_acl *acl, int want)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 350) {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 351) const struct posix_acl_entry *pa, *pe, *mask_obj;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 352) int found = 0;
47291baa8ddfd (Christian Brauner 2021-01-21 14:19:24 +0100 353) kuid_t uid;
47291baa8ddfd (Christian Brauner 2021-01-21 14:19:24 +0100 354) kgid_t gid;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 355)
63d72b93f2262 (Linus Torvalds 2020-06-07 12:19:06 -0700 356) want &= MAY_READ | MAY_WRITE | MAY_EXEC;
d124b60a83814 (Andreas Gruenbacher 2011-10-23 23:13:32 +0530 357)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 358) FOREACH_ACL_ENTRY(pa, acl, pe) {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 359) switch(pa->e_tag) {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 360) case ACL_USER_OBJ:
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 361) /* (May have been checked already) */
47291baa8ddfd (Christian Brauner 2021-01-21 14:19:24 +0100 362) uid = i_uid_into_mnt(mnt_userns, inode);
47291baa8ddfd (Christian Brauner 2021-01-21 14:19:24 +0100 363) if (uid_eq(uid, current_fsuid()))
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 364) goto check_perm;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 365) break;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 366) case ACL_USER:
47291baa8ddfd (Christian Brauner 2021-01-21 14:19:24 +0100 367) uid = kuid_into_mnt(mnt_userns, pa->e_uid);
47291baa8ddfd (Christian Brauner 2021-01-21 14:19:24 +0100 368) if (uid_eq(uid, current_fsuid()))
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 369) goto mask;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 370) break;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 371) case ACL_GROUP_OBJ:
47291baa8ddfd (Christian Brauner 2021-01-21 14:19:24 +0100 372) gid = i_gid_into_mnt(mnt_userns, inode);
47291baa8ddfd (Christian Brauner 2021-01-21 14:19:24 +0100 373) if (in_group_p(gid)) {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 374) found = 1;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 375) if ((pa->e_perm & want) == want)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 376) goto mask;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 377) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 378) break;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 379) case ACL_GROUP:
47291baa8ddfd (Christian Brauner 2021-01-21 14:19:24 +0100 380) gid = kgid_into_mnt(mnt_userns, pa->e_gid);
47291baa8ddfd (Christian Brauner 2021-01-21 14:19:24 +0100 381) if (in_group_p(gid)) {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 382) found = 1;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 383) if ((pa->e_perm & want) == want)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 384) goto mask;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 385) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 386) break;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 387) case ACL_MASK:
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 388) break;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 389) case ACL_OTHER:
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 390) if (found)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 391) return -EACCES;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 392) else
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 393) goto check_perm;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 394) default:
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 395) return -EIO;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 396) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 397) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 398) return -EIO;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 399)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 400) mask:
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 401) for (mask_obj = pa+1; mask_obj != pe; mask_obj++) {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 402) if (mask_obj->e_tag == ACL_MASK) {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 403) if ((pa->e_perm & mask_obj->e_perm & want) == want)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 404) return 0;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 405) return -EACCES;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 406) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 407) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 408)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 409) check_perm:
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 410) if ((pa->e_perm & want) == want)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 411) return 0;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 412) return -EACCES;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 413) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 414)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 415) /*
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 416) * Modify acl when creating a new inode. The caller must ensure the acl is
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 417) * only referenced once.
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 418) *
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 419) * mode_p initially must contain the mode parameter to the open() / creat()
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 420) * system calls. All permissions that are not granted by the acl are removed.
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 421) * The permissions in the acl are changed to reflect the mode_p parameter.
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 422) */
d3fb612076eeb (Al Viro 2011-07-23 18:37:50 -0400 423) static int posix_acl_create_masq(struct posix_acl *acl, umode_t *mode_p)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 424) {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 425) struct posix_acl_entry *pa, *pe;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 426) struct posix_acl_entry *group_obj = NULL, *mask_obj = NULL;
d3fb612076eeb (Al Viro 2011-07-23 18:37:50 -0400 427) umode_t mode = *mode_p;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 428) int not_equiv = 0;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 429)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 430) /* assert(atomic_read(acl->a_refcount) == 1); */
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 431)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 432) FOREACH_ACL_ENTRY(pa, acl, pe) {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 433) switch(pa->e_tag) {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 434) case ACL_USER_OBJ:
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 435) pa->e_perm &= (mode >> 6) | ~S_IRWXO;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 436) mode &= (pa->e_perm << 6) | ~S_IRWXU;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 437) break;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 438)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 439) case ACL_USER:
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 440) case ACL_GROUP:
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 441) not_equiv = 1;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 442) break;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 443)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 444) case ACL_GROUP_OBJ:
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 445) group_obj = pa;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 446) break;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 447)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 448) case ACL_OTHER:
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 449) pa->e_perm &= mode | ~S_IRWXO;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 450) mode &= pa->e_perm | ~S_IRWXO;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 451) break;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 452)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 453) case ACL_MASK:
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 454) mask_obj = pa;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 455) not_equiv = 1;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 456) break;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 457)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 458) default:
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 459) return -EIO;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 460) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 461) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 462)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 463) if (mask_obj) {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 464) mask_obj->e_perm &= (mode >> 3) | ~S_IRWXO;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 465) mode &= (mask_obj->e_perm << 3) | ~S_IRWXG;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 466) } else {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 467) if (!group_obj)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 468) return -EIO;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 469) group_obj->e_perm &= (mode >> 3) | ~S_IRWXO;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 470) mode &= (group_obj->e_perm << 3) | ~S_IRWXG;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 471) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 472)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 473) *mode_p = (*mode_p & ~S_IRWXUGO) | mode;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 474) return not_equiv;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 475) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 476)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 477) /*
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 478) * Modify the ACL for the chmod syscall.
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 479) */
5bf3258fd2acd (Christoph Hellwig 2013-12-20 05:16:41 -0800 480) static int __posix_acl_chmod_masq(struct posix_acl *acl, umode_t mode)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 481) {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 482) struct posix_acl_entry *group_obj = NULL, *mask_obj = NULL;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 483) struct posix_acl_entry *pa, *pe;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 484)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 485) /* assert(atomic_read(acl->a_refcount) == 1); */
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 486)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 487) FOREACH_ACL_ENTRY(pa, acl, pe) {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 488) switch(pa->e_tag) {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 489) case ACL_USER_OBJ:
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 490) pa->e_perm = (mode & S_IRWXU) >> 6;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 491) break;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 492)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 493) case ACL_USER:
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 494) case ACL_GROUP:
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 495) break;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 496)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 497) case ACL_GROUP_OBJ:
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 498) group_obj = pa;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 499) break;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 500)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 501) case ACL_MASK:
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 502) mask_obj = pa;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 503) break;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 504)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 505) case ACL_OTHER:
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 506) pa->e_perm = (mode & S_IRWXO);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 507) break;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 508)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 509) default:
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 510) return -EIO;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 511) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 512) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 513)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 514) if (mask_obj) {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 515) mask_obj->e_perm = (mode & S_IRWXG) >> 3;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 516) } else {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 517) if (!group_obj)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 518) return -EIO;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 519) group_obj->e_perm = (mode & S_IRWXG) >> 3;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 520) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 521)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 522) return 0;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 523) }
bc26ab5f65ae4 (Al Viro 2011-07-23 00:18:02 -0400 524)
826cae2f2b4d7 (Al Viro 2011-07-23 03:10:32 -0400 525) int
37bc15392a236 (Christoph Hellwig 2013-12-20 05:16:42 -0800 526) __posix_acl_create(struct posix_acl **acl, gfp_t gfp, umode_t *mode_p)
826cae2f2b4d7 (Al Viro 2011-07-23 03:10:32 -0400 527) {
826cae2f2b4d7 (Al Viro 2011-07-23 03:10:32 -0400 528) struct posix_acl *clone = posix_acl_clone(*acl, gfp);
826cae2f2b4d7 (Al Viro 2011-07-23 03:10:32 -0400 529) int err = -ENOMEM;
826cae2f2b4d7 (Al Viro 2011-07-23 03:10:32 -0400 530) if (clone) {
826cae2f2b4d7 (Al Viro 2011-07-23 03:10:32 -0400 531) err = posix_acl_create_masq(clone, mode_p);
826cae2f2b4d7 (Al Viro 2011-07-23 03:10:32 -0400 532) if (err < 0) {
826cae2f2b4d7 (Al Viro 2011-07-23 03:10:32 -0400 533) posix_acl_release(clone);
826cae2f2b4d7 (Al Viro 2011-07-23 03:10:32 -0400 534) clone = NULL;
826cae2f2b4d7 (Al Viro 2011-07-23 03:10:32 -0400 535) }
826cae2f2b4d7 (Al Viro 2011-07-23 03:10:32 -0400 536) }
826cae2f2b4d7 (Al Viro 2011-07-23 03:10:32 -0400 537) posix_acl_release(*acl);
826cae2f2b4d7 (Al Viro 2011-07-23 03:10:32 -0400 538) *acl = clone;
826cae2f2b4d7 (Al Viro 2011-07-23 03:10:32 -0400 539) return err;
826cae2f2b4d7 (Al Viro 2011-07-23 03:10:32 -0400 540) }
37bc15392a236 (Christoph Hellwig 2013-12-20 05:16:42 -0800 541) EXPORT_SYMBOL(__posix_acl_create);
826cae2f2b4d7 (Al Viro 2011-07-23 03:10:32 -0400 542)
bc26ab5f65ae4 (Al Viro 2011-07-23 00:18:02 -0400 543) int
5bf3258fd2acd (Christoph Hellwig 2013-12-20 05:16:41 -0800 544) __posix_acl_chmod(struct posix_acl **acl, gfp_t gfp, umode_t mode)
bc26ab5f65ae4 (Al Viro 2011-07-23 00:18:02 -0400 545) {
bc26ab5f65ae4 (Al Viro 2011-07-23 00:18:02 -0400 546) struct posix_acl *clone = posix_acl_clone(*acl, gfp);
bc26ab5f65ae4 (Al Viro 2011-07-23 00:18:02 -0400 547) int err = -ENOMEM;
bc26ab5f65ae4 (Al Viro 2011-07-23 00:18:02 -0400 548) if (clone) {
5bf3258fd2acd (Christoph Hellwig 2013-12-20 05:16:41 -0800 549) err = __posix_acl_chmod_masq(clone, mode);
bc26ab5f65ae4 (Al Viro 2011-07-23 00:18:02 -0400 550) if (err) {
bc26ab5f65ae4 (Al Viro 2011-07-23 00:18:02 -0400 551) posix_acl_release(clone);
bc26ab5f65ae4 (Al Viro 2011-07-23 00:18:02 -0400 552) clone = NULL;
bc26ab5f65ae4 (Al Viro 2011-07-23 00:18:02 -0400 553) }
bc26ab5f65ae4 (Al Viro 2011-07-23 00:18:02 -0400 554) }
bc26ab5f65ae4 (Al Viro 2011-07-23 00:18:02 -0400 555) posix_acl_release(*acl);
bc26ab5f65ae4 (Al Viro 2011-07-23 00:18:02 -0400 556) *acl = clone;
bc26ab5f65ae4 (Al Viro 2011-07-23 00:18:02 -0400 557) return err;
bc26ab5f65ae4 (Al Viro 2011-07-23 00:18:02 -0400 558) }
5bf3258fd2acd (Christoph Hellwig 2013-12-20 05:16:41 -0800 559) EXPORT_SYMBOL(__posix_acl_chmod);
5bf3258fd2acd (Christoph Hellwig 2013-12-20 05:16:41 -0800 560)
e65ce2a50cf6a (Christian Brauner 2021-01-21 14:19:27 +0100 561) /**
e65ce2a50cf6a (Christian Brauner 2021-01-21 14:19:27 +0100 562) * posix_acl_chmod - chmod a posix acl
e65ce2a50cf6a (Christian Brauner 2021-01-21 14:19:27 +0100 563) *
e65ce2a50cf6a (Christian Brauner 2021-01-21 14:19:27 +0100 564) * @mnt_userns: user namespace of the mount @inode was found from
e65ce2a50cf6a (Christian Brauner 2021-01-21 14:19:27 +0100 565) * @inode: inode to check permissions on
e65ce2a50cf6a (Christian Brauner 2021-01-21 14:19:27 +0100 566) * @mode: the new mode of @inode
e65ce2a50cf6a (Christian Brauner 2021-01-21 14:19:27 +0100 567) *
e65ce2a50cf6a (Christian Brauner 2021-01-21 14:19:27 +0100 568) * If the inode has been found through an idmapped mount the user namespace of
e65ce2a50cf6a (Christian Brauner 2021-01-21 14:19:27 +0100 569) * the vfsmount must be passed through @mnt_userns. This function will then
e65ce2a50cf6a (Christian Brauner 2021-01-21 14:19:27 +0100 570) * take care to map the inode according to @mnt_userns before checking
e65ce2a50cf6a (Christian Brauner 2021-01-21 14:19:27 +0100 571) * permissions. On non-idmapped mounts or if permission checking is to be
e65ce2a50cf6a (Christian Brauner 2021-01-21 14:19:27 +0100 572) * performed on the raw inode simply passs init_user_ns.
e65ce2a50cf6a (Christian Brauner 2021-01-21 14:19:27 +0100 573) */
5bf3258fd2acd (Christoph Hellwig 2013-12-20 05:16:41 -0800 574) int
e65ce2a50cf6a (Christian Brauner 2021-01-21 14:19:27 +0100 575) posix_acl_chmod(struct user_namespace *mnt_userns, struct inode *inode,
e65ce2a50cf6a (Christian Brauner 2021-01-21 14:19:27 +0100 576) umode_t mode)
5bf3258fd2acd (Christoph Hellwig 2013-12-20 05:16:41 -0800 577) {
5bf3258fd2acd (Christoph Hellwig 2013-12-20 05:16:41 -0800 578) struct posix_acl *acl;
5bf3258fd2acd (Christoph Hellwig 2013-12-20 05:16:41 -0800 579) int ret = 0;
5bf3258fd2acd (Christoph Hellwig 2013-12-20 05:16:41 -0800 580)
5bf3258fd2acd (Christoph Hellwig 2013-12-20 05:16:41 -0800 581) if (!IS_POSIXACL(inode))
5bf3258fd2acd (Christoph Hellwig 2013-12-20 05:16:41 -0800 582) return 0;
5bf3258fd2acd (Christoph Hellwig 2013-12-20 05:16:41 -0800 583) if (!inode->i_op->set_acl)
5bf3258fd2acd (Christoph Hellwig 2013-12-20 05:16:41 -0800 584) return -EOPNOTSUPP;
5bf3258fd2acd (Christoph Hellwig 2013-12-20 05:16:41 -0800 585)
5bf3258fd2acd (Christoph Hellwig 2013-12-20 05:16:41 -0800 586) acl = get_acl(inode, ACL_TYPE_ACCESS);
789b663ae3d42 (Trond Myklebust 2014-01-31 14:25:19 -0500 587) if (IS_ERR_OR_NULL(acl)) {
789b663ae3d42 (Trond Myklebust 2014-01-31 14:25:19 -0500 588) if (acl == ERR_PTR(-EOPNOTSUPP))
789b663ae3d42 (Trond Myklebust 2014-01-31 14:25:19 -0500 589) return 0;
5bf3258fd2acd (Christoph Hellwig 2013-12-20 05:16:41 -0800 590) return PTR_ERR(acl);
789b663ae3d42 (Trond Myklebust 2014-01-31 14:25:19 -0500 591) }
5bf3258fd2acd (Christoph Hellwig 2013-12-20 05:16:41 -0800 592)
37bc15392a236 (Christoph Hellwig 2013-12-20 05:16:42 -0800 593) ret = __posix_acl_chmod(&acl, GFP_KERNEL, mode);
5bf3258fd2acd (Christoph Hellwig 2013-12-20 05:16:41 -0800 594) if (ret)
5bf3258fd2acd (Christoph Hellwig 2013-12-20 05:16:41 -0800 595) return ret;
549c7297717c3 (Christian Brauner 2021-01-21 14:19:43 +0100 596) ret = inode->i_op->set_acl(mnt_userns, inode, acl, ACL_TYPE_ACCESS);
5bf3258fd2acd (Christoph Hellwig 2013-12-20 05:16:41 -0800 597) posix_acl_release(acl);
5bf3258fd2acd (Christoph Hellwig 2013-12-20 05:16:41 -0800 598) return ret;
5bf3258fd2acd (Christoph Hellwig 2013-12-20 05:16:41 -0800 599) }
bc26ab5f65ae4 (Al Viro 2011-07-23 00:18:02 -0400 600) EXPORT_SYMBOL(posix_acl_chmod);
5c8ebd57b6a51 (Christoph Hellwig 2013-12-20 05:16:37 -0800 601)
37bc15392a236 (Christoph Hellwig 2013-12-20 05:16:42 -0800 602) int
37bc15392a236 (Christoph Hellwig 2013-12-20 05:16:42 -0800 603) posix_acl_create(struct inode *dir, umode_t *mode,
37bc15392a236 (Christoph Hellwig 2013-12-20 05:16:42 -0800 604) struct posix_acl **default_acl, struct posix_acl **acl)
37bc15392a236 (Christoph Hellwig 2013-12-20 05:16:42 -0800 605) {
37bc15392a236 (Christoph Hellwig 2013-12-20 05:16:42 -0800 606) struct posix_acl *p;
c0c3a718e3ab2 (Dan Carpenter 2015-06-19 09:00:55 +1000 607) struct posix_acl *clone;
37bc15392a236 (Christoph Hellwig 2013-12-20 05:16:42 -0800 608) int ret;
37bc15392a236 (Christoph Hellwig 2013-12-20 05:16:42 -0800 609)
c0c3a718e3ab2 (Dan Carpenter 2015-06-19 09:00:55 +1000 610) *acl = NULL;
c0c3a718e3ab2 (Dan Carpenter 2015-06-19 09:00:55 +1000 611) *default_acl = NULL;
c0c3a718e3ab2 (Dan Carpenter 2015-06-19 09:00:55 +1000 612)
37bc15392a236 (Christoph Hellwig 2013-12-20 05:16:42 -0800 613) if (S_ISLNK(*mode) || !IS_POSIXACL(dir))
c0c3a718e3ab2 (Dan Carpenter 2015-06-19 09:00:55 +1000 614) return 0;
37bc15392a236 (Christoph Hellwig 2013-12-20 05:16:42 -0800 615)
37bc15392a236 (Christoph Hellwig 2013-12-20 05:16:42 -0800 616) p = get_acl(dir, ACL_TYPE_DEFAULT);
c0c3a718e3ab2 (Dan Carpenter 2015-06-19 09:00:55 +1000 617) if (!p || p == ERR_PTR(-EOPNOTSUPP)) {
c0c3a718e3ab2 (Dan Carpenter 2015-06-19 09:00:55 +1000 618) *mode &= ~current_umask();
c0c3a718e3ab2 (Dan Carpenter 2015-06-19 09:00:55 +1000 619) return 0;
37bc15392a236 (Christoph Hellwig 2013-12-20 05:16:42 -0800 620) }
c0c3a718e3ab2 (Dan Carpenter 2015-06-19 09:00:55 +1000 621) if (IS_ERR(p))
c0c3a718e3ab2 (Dan Carpenter 2015-06-19 09:00:55 +1000 622) return PTR_ERR(p);
37bc15392a236 (Christoph Hellwig 2013-12-20 05:16:42 -0800 623)
beaf226b863a0 (Miklos Szeredi 2016-09-16 12:44:21 +0200 624) ret = -ENOMEM;
c0c3a718e3ab2 (Dan Carpenter 2015-06-19 09:00:55 +1000 625) clone = posix_acl_clone(p, GFP_NOFS);
c0c3a718e3ab2 (Dan Carpenter 2015-06-19 09:00:55 +1000 626) if (!clone)
beaf226b863a0 (Miklos Szeredi 2016-09-16 12:44:21 +0200 627) goto err_release;
37bc15392a236 (Christoph Hellwig 2013-12-20 05:16:42 -0800 628)
c0c3a718e3ab2 (Dan Carpenter 2015-06-19 09:00:55 +1000 629) ret = posix_acl_create_masq(clone, mode);
fed0b588be2f5 (Omar Sandoval 2015-02-08 21:45:25 -0800 630) if (ret < 0)
beaf226b863a0 (Miklos Szeredi 2016-09-16 12:44:21 +0200 631) goto err_release_clone;
37bc15392a236 (Christoph Hellwig 2013-12-20 05:16:42 -0800 632)
c0c3a718e3ab2 (Dan Carpenter 2015-06-19 09:00:55 +1000 633) if (ret == 0)
c0c3a718e3ab2 (Dan Carpenter 2015-06-19 09:00:55 +1000 634) posix_acl_release(clone);
c0c3a718e3ab2 (Dan Carpenter 2015-06-19 09:00:55 +1000 635) else
c0c3a718e3ab2 (Dan Carpenter 2015-06-19 09:00:55 +1000 636) *acl = clone;
37bc15392a236 (Christoph Hellwig 2013-12-20 05:16:42 -0800 637)
c0c3a718e3ab2 (Dan Carpenter 2015-06-19 09:00:55 +1000 638) if (!S_ISDIR(*mode))
37bc15392a236 (Christoph Hellwig 2013-12-20 05:16:42 -0800 639) posix_acl_release(p);
c0c3a718e3ab2 (Dan Carpenter 2015-06-19 09:00:55 +1000 640) else
37bc15392a236 (Christoph Hellwig 2013-12-20 05:16:42 -0800 641) *default_acl = p;
37bc15392a236 (Christoph Hellwig 2013-12-20 05:16:42 -0800 642)
37bc15392a236 (Christoph Hellwig 2013-12-20 05:16:42 -0800 643) return 0;
fed0b588be2f5 (Omar Sandoval 2015-02-08 21:45:25 -0800 644)
beaf226b863a0 (Miklos Szeredi 2016-09-16 12:44:21 +0200 645) err_release_clone:
c0c3a718e3ab2 (Dan Carpenter 2015-06-19 09:00:55 +1000 646) posix_acl_release(clone);
beaf226b863a0 (Miklos Szeredi 2016-09-16 12:44:21 +0200 647) err_release:
fed0b588be2f5 (Omar Sandoval 2015-02-08 21:45:25 -0800 648) posix_acl_release(p);
beaf226b863a0 (Miklos Szeredi 2016-09-16 12:44:21 +0200 649) return ret;
37bc15392a236 (Christoph Hellwig 2013-12-20 05:16:42 -0800 650) }
37bc15392a236 (Christoph Hellwig 2013-12-20 05:16:42 -0800 651) EXPORT_SYMBOL_GPL(posix_acl_create);
37bc15392a236 (Christoph Hellwig 2013-12-20 05:16:42 -0800 652)
073931017b49d (Jan Kara 2016-09-19 17:39:09 +0200 653) /**
073931017b49d (Jan Kara 2016-09-19 17:39:09 +0200 654) * posix_acl_update_mode - update mode in set_acl
e65ce2a50cf6a (Christian Brauner 2021-01-21 14:19:27 +0100 655) * @mnt_userns: user namespace of the mount @inode was found from
e65ce2a50cf6a (Christian Brauner 2021-01-21 14:19:27 +0100 656) * @inode: target inode
e65ce2a50cf6a (Christian Brauner 2021-01-21 14:19:27 +0100 657) * @mode_p: mode (pointer) for update
e65ce2a50cf6a (Christian Brauner 2021-01-21 14:19:27 +0100 658) * @acl: acl pointer
073931017b49d (Jan Kara 2016-09-19 17:39:09 +0200 659) *
073931017b49d (Jan Kara 2016-09-19 17:39:09 +0200 660) * Update the file mode when setting an ACL: compute the new file permission
073931017b49d (Jan Kara 2016-09-19 17:39:09 +0200 661) * bits based on the ACL. In addition, if the ACL is equivalent to the new
e39e773ad100a (Randy Dunlap 2020-01-04 13:00:05 -0800 662) * file mode, set *@acl to NULL to indicate that no ACL should be set.
073931017b49d (Jan Kara 2016-09-19 17:39:09 +0200 663) *
e39e773ad100a (Randy Dunlap 2020-01-04 13:00:05 -0800 664) * As with chmod, clear the setgid bit if the caller is not in the owning group
073931017b49d (Jan Kara 2016-09-19 17:39:09 +0200 665) * or capable of CAP_FSETID (see inode_change_ok).
073931017b49d (Jan Kara 2016-09-19 17:39:09 +0200 666) *
e65ce2a50cf6a (Christian Brauner 2021-01-21 14:19:27 +0100 667) * If the inode has been found through an idmapped mount the user namespace of
e65ce2a50cf6a (Christian Brauner 2021-01-21 14:19:27 +0100 668) * the vfsmount must be passed through @mnt_userns. This function will then
e65ce2a50cf6a (Christian Brauner 2021-01-21 14:19:27 +0100 669) * take care to map the inode according to @mnt_userns before checking
e65ce2a50cf6a (Christian Brauner 2021-01-21 14:19:27 +0100 670) * permissions. On non-idmapped mounts or if permission checking is to be
e65ce2a50cf6a (Christian Brauner 2021-01-21 14:19:27 +0100 671) * performed on the raw inode simply passs init_user_ns.
e65ce2a50cf6a (Christian Brauner 2021-01-21 14:19:27 +0100 672) *
073931017b49d (Jan Kara 2016-09-19 17:39:09 +0200 673) * Called from set_acl inode operations.
073931017b49d (Jan Kara 2016-09-19 17:39:09 +0200 674) */
e65ce2a50cf6a (Christian Brauner 2021-01-21 14:19:27 +0100 675) int posix_acl_update_mode(struct user_namespace *mnt_userns,
e65ce2a50cf6a (Christian Brauner 2021-01-21 14:19:27 +0100 676) struct inode *inode, umode_t *mode_p,
073931017b49d (Jan Kara 2016-09-19 17:39:09 +0200 677) struct posix_acl **acl)
073931017b49d (Jan Kara 2016-09-19 17:39:09 +0200 678) {
073931017b49d (Jan Kara 2016-09-19 17:39:09 +0200 679) umode_t mode = inode->i_mode;
073931017b49d (Jan Kara 2016-09-19 17:39:09 +0200 680) int error;
073931017b49d (Jan Kara 2016-09-19 17:39:09 +0200 681)
073931017b49d (Jan Kara 2016-09-19 17:39:09 +0200 682) error = posix_acl_equiv_mode(*acl, &mode);
073931017b49d (Jan Kara 2016-09-19 17:39:09 +0200 683) if (error < 0)
073931017b49d (Jan Kara 2016-09-19 17:39:09 +0200 684) return error;
073931017b49d (Jan Kara 2016-09-19 17:39:09 +0200 685) if (error == 0)
073931017b49d (Jan Kara 2016-09-19 17:39:09 +0200 686) *acl = NULL;
e65ce2a50cf6a (Christian Brauner 2021-01-21 14:19:27 +0100 687) if (!in_group_p(i_gid_into_mnt(mnt_userns, inode)) &&
e65ce2a50cf6a (Christian Brauner 2021-01-21 14:19:27 +0100 688) !capable_wrt_inode_uidgid(mnt_userns, inode, CAP_FSETID))
073931017b49d (Jan Kara 2016-09-19 17:39:09 +0200 689) mode &= ~S_ISGID;
073931017b49d (Jan Kara 2016-09-19 17:39:09 +0200 690) *mode_p = mode;
073931017b49d (Jan Kara 2016-09-19 17:39:09 +0200 691) return 0;
073931017b49d (Jan Kara 2016-09-19 17:39:09 +0200 692) }
073931017b49d (Jan Kara 2016-09-19 17:39:09 +0200 693) EXPORT_SYMBOL(posix_acl_update_mode);
073931017b49d (Jan Kara 2016-09-19 17:39:09 +0200 694)
5c8ebd57b6a51 (Christoph Hellwig 2013-12-20 05:16:37 -0800 695) /*
5c8ebd57b6a51 (Christoph Hellwig 2013-12-20 05:16:37 -0800 696) * Fix up the uids and gids in posix acl extended attributes in place.
5c8ebd57b6a51 (Christoph Hellwig 2013-12-20 05:16:37 -0800 697) */
5c8ebd57b6a51 (Christoph Hellwig 2013-12-20 05:16:37 -0800 698) static void posix_acl_fix_xattr_userns(
5c8ebd57b6a51 (Christoph Hellwig 2013-12-20 05:16:37 -0800 699) struct user_namespace *to, struct user_namespace *from,
e65ce2a50cf6a (Christian Brauner 2021-01-21 14:19:27 +0100 700) struct user_namespace *mnt_userns,
e65ce2a50cf6a (Christian Brauner 2021-01-21 14:19:27 +0100 701) void *value, size_t size, bool from_user)
5c8ebd57b6a51 (Christoph Hellwig 2013-12-20 05:16:37 -0800 702) {
2211d5ba5c6c4 (Andreas Gruenbacher 2016-09-27 13:03:22 +0200 703) struct posix_acl_xattr_header *header = value;
2211d5ba5c6c4 (Andreas Gruenbacher 2016-09-27 13:03:22 +0200 704) struct posix_acl_xattr_entry *entry = (void *)(header + 1), *end;
5c8ebd57b6a51 (Christoph Hellwig 2013-12-20 05:16:37 -0800 705) int count;
5c8ebd57b6a51 (Christoph Hellwig 2013-12-20 05:16:37 -0800 706) kuid_t uid;
5c8ebd57b6a51 (Christoph Hellwig 2013-12-20 05:16:37 -0800 707) kgid_t gid;
5c8ebd57b6a51 (Christoph Hellwig 2013-12-20 05:16:37 -0800 708)
5c8ebd57b6a51 (Christoph Hellwig 2013-12-20 05:16:37 -0800 709) if (!value)
5c8ebd57b6a51 (Christoph Hellwig 2013-12-20 05:16:37 -0800 710) return;
2211d5ba5c6c4 (Andreas Gruenbacher 2016-09-27 13:03:22 +0200 711) if (size < sizeof(struct posix_acl_xattr_header))
5c8ebd57b6a51 (Christoph Hellwig 2013-12-20 05:16:37 -0800 712) return;
5c8ebd57b6a51 (Christoph Hellwig 2013-12-20 05:16:37 -0800 713) if (header->a_version != cpu_to_le32(POSIX_ACL_XATTR_VERSION))
5c8ebd57b6a51 (Christoph Hellwig 2013-12-20 05:16:37 -0800 714) return;
5c8ebd57b6a51 (Christoph Hellwig 2013-12-20 05:16:37 -0800 715)
5c8ebd57b6a51 (Christoph Hellwig 2013-12-20 05:16:37 -0800 716) count = posix_acl_xattr_count(size);
5c8ebd57b6a51 (Christoph Hellwig 2013-12-20 05:16:37 -0800 717) if (count < 0)
5c8ebd57b6a51 (Christoph Hellwig 2013-12-20 05:16:37 -0800 718) return;
5c8ebd57b6a51 (Christoph Hellwig 2013-12-20 05:16:37 -0800 719) if (count == 0)
5c8ebd57b6a51 (Christoph Hellwig 2013-12-20 05:16:37 -0800 720) return;
5c8ebd57b6a51 (Christoph Hellwig 2013-12-20 05:16:37 -0800 721)
5c8ebd57b6a51 (Christoph Hellwig 2013-12-20 05:16:37 -0800 722) for (end = entry + count; entry != end; entry++) {
5c8ebd57b6a51 (Christoph Hellwig 2013-12-20 05:16:37 -0800 723) switch(le16_to_cpu(entry->e_tag)) {
5c8ebd57b6a51 (Christoph Hellwig 2013-12-20 05:16:37 -0800 724) case ACL_USER:
5c8ebd57b6a51 (Christoph Hellwig 2013-12-20 05:16:37 -0800 725) uid = make_kuid(from, le32_to_cpu(entry->e_id));
e65ce2a50cf6a (Christian Brauner 2021-01-21 14:19:27 +0100 726) if (from_user)
e65ce2a50cf6a (Christian Brauner 2021-01-21 14:19:27 +0100 727) uid = kuid_from_mnt(mnt_userns, uid);
e65ce2a50cf6a (Christian Brauner 2021-01-21 14:19:27 +0100 728) else
e65ce2a50cf6a (Christian Brauner 2021-01-21 14:19:27 +0100 729) uid = kuid_into_mnt(mnt_userns, uid);
5c8ebd57b6a51 (Christoph Hellwig 2013-12-20 05:16:37 -0800 730) entry->e_id = cpu_to_le32(from_kuid(to, uid));
5c8ebd57b6a51 (Christoph Hellwig 2013-12-20 05:16:37 -0800 731) break;
5c8ebd57b6a51 (Christoph Hellwig 2013-12-20 05:16:37 -0800 732) case ACL_GROUP:
5c8ebd57b6a51 (Christoph Hellwig 2013-12-20 05:16:37 -0800 733) gid = make_kgid(from, le32_to_cpu(entry->e_id));
e65ce2a50cf6a (Christian Brauner 2021-01-21 14:19:27 +0100 734) if (from_user)
e65ce2a50cf6a (Christian Brauner 2021-01-21 14:19:27 +0100 735) gid = kgid_from_mnt(mnt_userns, gid);
e65ce2a50cf6a (Christian Brauner 2021-01-21 14:19:27 +0100 736) else
e65ce2a50cf6a (Christian Brauner 2021-01-21 14:19:27 +0100 737) gid = kgid_into_mnt(mnt_userns, gid);
5c8ebd57b6a51 (Christoph Hellwig 2013-12-20 05:16:37 -0800 738) entry->e_id = cpu_to_le32(from_kgid(to, gid));
5c8ebd57b6a51 (Christoph Hellwig 2013-12-20 05:16:37 -0800 739) break;
5c8ebd57b6a51 (Christoph Hellwig 2013-12-20 05:16:37 -0800 740) default:
5c8ebd57b6a51 (Christoph Hellwig 2013-12-20 05:16:37 -0800 741) break;
5c8ebd57b6a51 (Christoph Hellwig 2013-12-20 05:16:37 -0800 742) }
5c8ebd57b6a51 (Christoph Hellwig 2013-12-20 05:16:37 -0800 743) }
5c8ebd57b6a51 (Christoph Hellwig 2013-12-20 05:16:37 -0800 744) }
5c8ebd57b6a51 (Christoph Hellwig 2013-12-20 05:16:37 -0800 745)
e65ce2a50cf6a (Christian Brauner 2021-01-21 14:19:27 +0100 746) void posix_acl_fix_xattr_from_user(struct user_namespace *mnt_userns,
e65ce2a50cf6a (Christian Brauner 2021-01-21 14:19:27 +0100 747) void *value, size_t size)
5c8ebd57b6a51 (Christoph Hellwig 2013-12-20 05:16:37 -0800 748) {
5c8ebd57b6a51 (Christoph Hellwig 2013-12-20 05:16:37 -0800 749) struct user_namespace *user_ns = current_user_ns();
e65ce2a50cf6a (Christian Brauner 2021-01-21 14:19:27 +0100 750) if ((user_ns == &init_user_ns) && (mnt_userns == &init_user_ns))
5c8ebd57b6a51 (Christoph Hellwig 2013-12-20 05:16:37 -0800 751) return;
e65ce2a50cf6a (Christian Brauner 2021-01-21 14:19:27 +0100 752) posix_acl_fix_xattr_userns(&init_user_ns, user_ns, mnt_userns, value,
e65ce2a50cf6a (Christian Brauner 2021-01-21 14:19:27 +0100 753) size, true);
5c8ebd57b6a51 (Christoph Hellwig 2013-12-20 05:16:37 -0800 754) }
5c8ebd57b6a51 (Christoph Hellwig 2013-12-20 05:16:37 -0800 755)
e65ce2a50cf6a (Christian Brauner 2021-01-21 14:19:27 +0100 756) void posix_acl_fix_xattr_to_user(struct user_namespace *mnt_userns,
e65ce2a50cf6a (Christian Brauner 2021-01-21 14:19:27 +0100 757) void *value, size_t size)
5c8ebd57b6a51 (Christoph Hellwig 2013-12-20 05:16:37 -0800 758) {
5c8ebd57b6a51 (Christoph Hellwig 2013-12-20 05:16:37 -0800 759) struct user_namespace *user_ns = current_user_ns();
e65ce2a50cf6a (Christian Brauner 2021-01-21 14:19:27 +0100 760) if ((user_ns == &init_user_ns) && (mnt_userns == &init_user_ns))
5c8ebd57b6a51 (Christoph Hellwig 2013-12-20 05:16:37 -0800 761) return;
e65ce2a50cf6a (Christian Brauner 2021-01-21 14:19:27 +0100 762) posix_acl_fix_xattr_userns(user_ns, &init_user_ns, mnt_userns, value,
e65ce2a50cf6a (Christian Brauner 2021-01-21 14:19:27 +0100 763) size, false);
5c8ebd57b6a51 (Christoph Hellwig 2013-12-20 05:16:37 -0800 764) }
5c8ebd57b6a51 (Christoph Hellwig 2013-12-20 05:16:37 -0800 765)
5c8ebd57b6a51 (Christoph Hellwig 2013-12-20 05:16:37 -0800 766) /*
5c8ebd57b6a51 (Christoph Hellwig 2013-12-20 05:16:37 -0800 767) * Convert from extended attribute to in-memory representation.
5c8ebd57b6a51 (Christoph Hellwig 2013-12-20 05:16:37 -0800 768) */
5c8ebd57b6a51 (Christoph Hellwig 2013-12-20 05:16:37 -0800 769) struct posix_acl *
5c8ebd57b6a51 (Christoph Hellwig 2013-12-20 05:16:37 -0800 770) posix_acl_from_xattr(struct user_namespace *user_ns,
5c8ebd57b6a51 (Christoph Hellwig 2013-12-20 05:16:37 -0800 771) const void *value, size_t size)
5c8ebd57b6a51 (Christoph Hellwig 2013-12-20 05:16:37 -0800 772) {
2211d5ba5c6c4 (Andreas Gruenbacher 2016-09-27 13:03:22 +0200 773) const struct posix_acl_xattr_header *header = value;
2211d5ba5c6c4 (Andreas Gruenbacher 2016-09-27 13:03:22 +0200 774) const struct posix_acl_xattr_entry *entry = (const void *)(header + 1), *end;
5c8ebd57b6a51 (Christoph Hellwig 2013-12-20 05:16:37 -0800 775) int count;
5c8ebd57b6a51 (Christoph Hellwig 2013-12-20 05:16:37 -0800 776) struct posix_acl *acl;
5c8ebd57b6a51 (Christoph Hellwig 2013-12-20 05:16:37 -0800 777) struct posix_acl_entry *acl_e;
5c8ebd57b6a51 (Christoph Hellwig 2013-12-20 05:16:37 -0800 778)
5c8ebd57b6a51 (Christoph Hellwig 2013-12-20 05:16:37 -0800 779) if (!value)
5c8ebd57b6a51 (Christoph Hellwig 2013-12-20 05:16:37 -0800 780) return NULL;
2211d5ba5c6c4 (Andreas Gruenbacher 2016-09-27 13:03:22 +0200 781) if (size < sizeof(struct posix_acl_xattr_header))
5c8ebd57b6a51 (Christoph Hellwig 2013-12-20 05:16:37 -0800 782) return ERR_PTR(-EINVAL);
5c8ebd57b6a51 (Christoph Hellwig 2013-12-20 05:16:37 -0800 783) if (header->a_version != cpu_to_le32(POSIX_ACL_XATTR_VERSION))
5c8ebd57b6a51 (Christoph Hellwig 2013-12-20 05:16:37 -0800 784) return ERR_PTR(-EOPNOTSUPP);
5c8ebd57b6a51 (Christoph Hellwig 2013-12-20 05:16:37 -0800 785)
5c8ebd57b6a51 (Christoph Hellwig 2013-12-20 05:16:37 -0800 786) count = posix_acl_xattr_count(size);
5c8ebd57b6a51 (Christoph Hellwig 2013-12-20 05:16:37 -0800 787) if (count < 0)
5c8ebd57b6a51 (Christoph Hellwig 2013-12-20 05:16:37 -0800 788) return ERR_PTR(-EINVAL);
5c8ebd57b6a51 (Christoph Hellwig 2013-12-20 05:16:37 -0800 789) if (count == 0)
5c8ebd57b6a51 (Christoph Hellwig 2013-12-20 05:16:37 -0800 790) return NULL;
5c8ebd57b6a51 (Christoph Hellwig 2013-12-20 05:16:37 -0800 791)
5c8ebd57b6a51 (Christoph Hellwig 2013-12-20 05:16:37 -0800 792) acl = posix_acl_alloc(count, GFP_NOFS);
5c8ebd57b6a51 (Christoph Hellwig 2013-12-20 05:16:37 -0800 793) if (!acl)
5c8ebd57b6a51 (Christoph Hellwig 2013-12-20 05:16:37 -0800 794) return ERR_PTR(-ENOMEM);
5c8ebd57b6a51 (Christoph Hellwig 2013-12-20 05:16:37 -0800 795) acl_e = acl->a_entries;
5c8ebd57b6a51 (Christoph Hellwig 2013-12-20 05:16:37 -0800 796)
5c8ebd57b6a51 (Christoph Hellwig 2013-12-20 05:16:37 -0800 797) for (end = entry + count; entry != end; acl_e++, entry++) {
5c8ebd57b6a51 (Christoph Hellwig 2013-12-20 05:16:37 -0800 798) acl_e->e_tag = le16_to_cpu(entry->e_tag);
5c8ebd57b6a51 (Christoph Hellwig 2013-12-20 05:16:37 -0800 799) acl_e->e_perm = le16_to_cpu(entry->e_perm);
5c8ebd57b6a51 (Christoph Hellwig 2013-12-20 05:16:37 -0800 800)
5c8ebd57b6a51 (Christoph Hellwig 2013-12-20 05:16:37 -0800 801) switch(acl_e->e_tag) {
5c8ebd57b6a51 (Christoph Hellwig 2013-12-20 05:16:37 -0800 802) case ACL_USER_OBJ:
5c8ebd57b6a51 (Christoph Hellwig 2013-12-20 05:16:37 -0800 803) case ACL_GROUP_OBJ:
5c8ebd57b6a51 (Christoph Hellwig 2013-12-20 05:16:37 -0800 804) case ACL_MASK:
5c8ebd57b6a51 (Christoph Hellwig 2013-12-20 05:16:37 -0800 805) case ACL_OTHER:
5c8ebd57b6a51 (Christoph Hellwig 2013-12-20 05:16:37 -0800 806) break;
5c8ebd57b6a51 (Christoph Hellwig 2013-12-20 05:16:37 -0800 807)
5c8ebd57b6a51 (Christoph Hellwig 2013-12-20 05:16:37 -0800 808) case ACL_USER:
5c8ebd57b6a51 (Christoph Hellwig 2013-12-20 05:16:37 -0800 809) acl_e->e_uid =
5c8ebd57b6a51 (Christoph Hellwig 2013-12-20 05:16:37 -0800 810) make_kuid(user_ns,
5c8ebd57b6a51 (Christoph Hellwig 2013-12-20 05:16:37 -0800 811) le32_to_cpu(entry->e_id));
5c8ebd57b6a51 (Christoph Hellwig 2013-12-20 05:16:37 -0800 812) if (!uid_valid(acl_e->e_uid))
5c8ebd57b6a51 (Christoph Hellwig 2013-12-20 05:16:37 -0800 813) goto fail;
5c8ebd57b6a51 (Christoph Hellwig 2013-12-20 05:16:37 -0800 814) break;
5c8ebd57b6a51 (Christoph Hellwig 2013-12-20 05:16:37 -0800 815) case ACL_GROUP:
5c8ebd57b6a51 (Christoph Hellwig 2013-12-20 05:16:37 -0800 816) acl_e->e_gid =
5c8ebd57b6a51 (Christoph Hellwig 2013-12-20 05:16:37 -0800 817) make_kgid(user_ns,
5c8ebd57b6a51 (Christoph Hellwig 2013-12-20 05:16:37 -0800 818) le32_to_cpu(entry->e_id));
5c8ebd57b6a51 (Christoph Hellwig 2013-12-20 05:16:37 -0800 819) if (!gid_valid(acl_e->e_gid))
5c8ebd57b6a51 (Christoph Hellwig 2013-12-20 05:16:37 -0800 820) goto fail;
5c8ebd57b6a51 (Christoph Hellwig 2013-12-20 05:16:37 -0800 821) break;
5c8ebd57b6a51 (Christoph Hellwig 2013-12-20 05:16:37 -0800 822)
5c8ebd57b6a51 (Christoph Hellwig 2013-12-20 05:16:37 -0800 823) default:
5c8ebd57b6a51 (Christoph Hellwig 2013-12-20 05:16:37 -0800 824) goto fail;
5c8ebd57b6a51 (Christoph Hellwig 2013-12-20 05:16:37 -0800 825) }
5c8ebd57b6a51 (Christoph Hellwig 2013-12-20 05:16:37 -0800 826) }
5c8ebd57b6a51 (Christoph Hellwig 2013-12-20 05:16:37 -0800 827) return acl;
5c8ebd57b6a51 (Christoph Hellwig 2013-12-20 05:16:37 -0800 828)
5c8ebd57b6a51 (Christoph Hellwig 2013-12-20 05:16:37 -0800 829) fail:
5c8ebd57b6a51 (Christoph Hellwig 2013-12-20 05:16:37 -0800 830) posix_acl_release(acl);
5c8ebd57b6a51 (Christoph Hellwig 2013-12-20 05:16:37 -0800 831) return ERR_PTR(-EINVAL);
5c8ebd57b6a51 (Christoph Hellwig 2013-12-20 05:16:37 -0800 832) }
5c8ebd57b6a51 (Christoph Hellwig 2013-12-20 05:16:37 -0800 833) EXPORT_SYMBOL (posix_acl_from_xattr);
5c8ebd57b6a51 (Christoph Hellwig 2013-12-20 05:16:37 -0800 834)
5c8ebd57b6a51 (Christoph Hellwig 2013-12-20 05:16:37 -0800 835) /*
5c8ebd57b6a51 (Christoph Hellwig 2013-12-20 05:16:37 -0800 836) * Convert from in-memory to extended attribute representation.
5c8ebd57b6a51 (Christoph Hellwig 2013-12-20 05:16:37 -0800 837) */
5c8ebd57b6a51 (Christoph Hellwig 2013-12-20 05:16:37 -0800 838) int
5c8ebd57b6a51 (Christoph Hellwig 2013-12-20 05:16:37 -0800 839) posix_acl_to_xattr(struct user_namespace *user_ns, const struct posix_acl *acl,
5c8ebd57b6a51 (Christoph Hellwig 2013-12-20 05:16:37 -0800 840) void *buffer, size_t size)
5c8ebd57b6a51 (Christoph Hellwig 2013-12-20 05:16:37 -0800 841) {
2211d5ba5c6c4 (Andreas Gruenbacher 2016-09-27 13:03:22 +0200 842) struct posix_acl_xattr_header *ext_acl = buffer;
2211d5ba5c6c4 (Andreas Gruenbacher 2016-09-27 13:03:22 +0200 843) struct posix_acl_xattr_entry *ext_entry;
5c8ebd57b6a51 (Christoph Hellwig 2013-12-20 05:16:37 -0800 844) int real_size, n;
5c8ebd57b6a51 (Christoph Hellwig 2013-12-20 05:16:37 -0800 845)
5c8ebd57b6a51 (Christoph Hellwig 2013-12-20 05:16:37 -0800 846) real_size = posix_acl_xattr_size(acl->a_count);
5c8ebd57b6a51 (Christoph Hellwig 2013-12-20 05:16:37 -0800 847) if (!buffer)
5c8ebd57b6a51 (Christoph Hellwig 2013-12-20 05:16:37 -0800 848) return real_size;
5c8ebd57b6a51 (Christoph Hellwig 2013-12-20 05:16:37 -0800 849) if (real_size > size)
5c8ebd57b6a51 (Christoph Hellwig 2013-12-20 05:16:37 -0800 850) return -ERANGE;
47ba973440377 (Dan Carpenter 2014-02-14 12:05:49 +0300 851)
2211d5ba5c6c4 (Andreas Gruenbacher 2016-09-27 13:03:22 +0200 852) ext_entry = (void *)(ext_acl + 1);
5c8ebd57b6a51 (Christoph Hellwig 2013-12-20 05:16:37 -0800 853) ext_acl->a_version = cpu_to_le32(POSIX_ACL_XATTR_VERSION);
5c8ebd57b6a51 (Christoph Hellwig 2013-12-20 05:16:37 -0800 854)
5c8ebd57b6a51 (Christoph Hellwig 2013-12-20 05:16:37 -0800 855) for (n=0; n < acl->a_count; n++, ext_entry++) {
5c8ebd57b6a51 (Christoph Hellwig 2013-12-20 05:16:37 -0800 856) const struct posix_acl_entry *acl_e = &acl->a_entries[n];
5c8ebd57b6a51 (Christoph Hellwig 2013-12-20 05:16:37 -0800 857) ext_entry->e_tag = cpu_to_le16(acl_e->e_tag);
5c8ebd57b6a51 (Christoph Hellwig 2013-12-20 05:16:37 -0800 858) ext_entry->e_perm = cpu_to_le16(acl_e->e_perm);
5c8ebd57b6a51 (Christoph Hellwig 2013-12-20 05:16:37 -0800 859) switch(acl_e->e_tag) {
5c8ebd57b6a51 (Christoph Hellwig 2013-12-20 05:16:37 -0800 860) case ACL_USER:
5c8ebd57b6a51 (Christoph Hellwig 2013-12-20 05:16:37 -0800 861) ext_entry->e_id =
5c8ebd57b6a51 (Christoph Hellwig 2013-12-20 05:16:37 -0800 862) cpu_to_le32(from_kuid(user_ns, acl_e->e_uid));
5c8ebd57b6a51 (Christoph Hellwig 2013-12-20 05:16:37 -0800 863) break;
5c8ebd57b6a51 (Christoph Hellwig 2013-12-20 05:16:37 -0800 864) case ACL_GROUP:
5c8ebd57b6a51 (Christoph Hellwig 2013-12-20 05:16:37 -0800 865) ext_entry->e_id =
5c8ebd57b6a51 (Christoph Hellwig 2013-12-20 05:16:37 -0800 866) cpu_to_le32(from_kgid(user_ns, acl_e->e_gid));
5c8ebd57b6a51 (Christoph Hellwig 2013-12-20 05:16:37 -0800 867) break;
5c8ebd57b6a51 (Christoph Hellwig 2013-12-20 05:16:37 -0800 868) default:
5c8ebd57b6a51 (Christoph Hellwig 2013-12-20 05:16:37 -0800 869) ext_entry->e_id = cpu_to_le32(ACL_UNDEFINED_ID);
5c8ebd57b6a51 (Christoph Hellwig 2013-12-20 05:16:37 -0800 870) break;
5c8ebd57b6a51 (Christoph Hellwig 2013-12-20 05:16:37 -0800 871) }
5c8ebd57b6a51 (Christoph Hellwig 2013-12-20 05:16:37 -0800 872) }
5c8ebd57b6a51 (Christoph Hellwig 2013-12-20 05:16:37 -0800 873) return real_size;
5c8ebd57b6a51 (Christoph Hellwig 2013-12-20 05:16:37 -0800 874) }
5c8ebd57b6a51 (Christoph Hellwig 2013-12-20 05:16:37 -0800 875) EXPORT_SYMBOL (posix_acl_to_xattr);
2aeccbe957d0d (Christoph Hellwig 2013-12-20 05:16:40 -0800 876)
2aeccbe957d0d (Christoph Hellwig 2013-12-20 05:16:40 -0800 877) static int
d9a82a04033f8 (Andreas Gruenbacher 2015-10-04 19:18:51 +0200 878) posix_acl_xattr_get(const struct xattr_handler *handler,
b296821a7c42f (Al Viro 2016-04-10 20:48:24 -0400 879) struct dentry *unused, struct inode *inode,
b296821a7c42f (Al Viro 2016-04-10 20:48:24 -0400 880) const char *name, void *value, size_t size)
2aeccbe957d0d (Christoph Hellwig 2013-12-20 05:16:40 -0800 881) {
2aeccbe957d0d (Christoph Hellwig 2013-12-20 05:16:40 -0800 882) struct posix_acl *acl;
2aeccbe957d0d (Christoph Hellwig 2013-12-20 05:16:40 -0800 883) int error;
2aeccbe957d0d (Christoph Hellwig 2013-12-20 05:16:40 -0800 884)
b296821a7c42f (Al Viro 2016-04-10 20:48:24 -0400 885) if (!IS_POSIXACL(inode))
2aeccbe957d0d (Christoph Hellwig 2013-12-20 05:16:40 -0800 886) return -EOPNOTSUPP;
b296821a7c42f (Al Viro 2016-04-10 20:48:24 -0400 887) if (S_ISLNK(inode->i_mode))
2aeccbe957d0d (Christoph Hellwig 2013-12-20 05:16:40 -0800 888) return -EOPNOTSUPP;
2aeccbe957d0d (Christoph Hellwig 2013-12-20 05:16:40 -0800 889)
b296821a7c42f (Al Viro 2016-04-10 20:48:24 -0400 890) acl = get_acl(inode, handler->flags);
2aeccbe957d0d (Christoph Hellwig 2013-12-20 05:16:40 -0800 891) if (IS_ERR(acl))
2aeccbe957d0d (Christoph Hellwig 2013-12-20 05:16:40 -0800 892) return PTR_ERR(acl);
2aeccbe957d0d (Christoph Hellwig 2013-12-20 05:16:40 -0800 893) if (acl == NULL)
2aeccbe957d0d (Christoph Hellwig 2013-12-20 05:16:40 -0800 894) return -ENODATA;
2aeccbe957d0d (Christoph Hellwig 2013-12-20 05:16:40 -0800 895)
2aeccbe957d0d (Christoph Hellwig 2013-12-20 05:16:40 -0800 896) error = posix_acl_to_xattr(&init_user_ns, acl, value, size);
2aeccbe957d0d (Christoph Hellwig 2013-12-20 05:16:40 -0800 897) posix_acl_release(acl);
2aeccbe957d0d (Christoph Hellwig 2013-12-20 05:16:40 -0800 898)
2aeccbe957d0d (Christoph Hellwig 2013-12-20 05:16:40 -0800 899) return error;
2aeccbe957d0d (Christoph Hellwig 2013-12-20 05:16:40 -0800 900) }
2aeccbe957d0d (Christoph Hellwig 2013-12-20 05:16:40 -0800 901)
485e71e8fb635 (Andreas Gruenbacher 2016-06-22 23:57:25 +0200 902) int
e65ce2a50cf6a (Christian Brauner 2021-01-21 14:19:27 +0100 903) set_posix_acl(struct user_namespace *mnt_userns, struct inode *inode,
e65ce2a50cf6a (Christian Brauner 2021-01-21 14:19:27 +0100 904) int type, struct posix_acl *acl)
2aeccbe957d0d (Christoph Hellwig 2013-12-20 05:16:40 -0800 905) {
2aeccbe957d0d (Christoph Hellwig 2013-12-20 05:16:40 -0800 906) if (!IS_POSIXACL(inode))
2aeccbe957d0d (Christoph Hellwig 2013-12-20 05:16:40 -0800 907) return -EOPNOTSUPP;
2aeccbe957d0d (Christoph Hellwig 2013-12-20 05:16:40 -0800 908) if (!inode->i_op->set_acl)
2aeccbe957d0d (Christoph Hellwig 2013-12-20 05:16:40 -0800 909) return -EOPNOTSUPP;
2aeccbe957d0d (Christoph Hellwig 2013-12-20 05:16:40 -0800 910)
485e71e8fb635 (Andreas Gruenbacher 2016-06-22 23:57:25 +0200 911) if (type == ACL_TYPE_DEFAULT && !S_ISDIR(inode->i_mode))
485e71e8fb635 (Andreas Gruenbacher 2016-06-22 23:57:25 +0200 912) return acl ? -EACCES : 0;
e65ce2a50cf6a (Christian Brauner 2021-01-21 14:19:27 +0100 913) if (!inode_owner_or_capable(mnt_userns, inode))
2aeccbe957d0d (Christoph Hellwig 2013-12-20 05:16:40 -0800 914) return -EPERM;
2aeccbe957d0d (Christoph Hellwig 2013-12-20 05:16:40 -0800 915)
485e71e8fb635 (Andreas Gruenbacher 2016-06-22 23:57:25 +0200 916) if (acl) {
a867d7349e94b (Linus Torvalds 2016-07-29 15:54:19 -0700 917) int ret = posix_acl_valid(inode->i_sb->s_user_ns, acl);
485e71e8fb635 (Andreas Gruenbacher 2016-06-22 23:57:25 +0200 918) if (ret)
485e71e8fb635 (Andreas Gruenbacher 2016-06-22 23:57:25 +0200 919) return ret;
485e71e8fb635 (Andreas Gruenbacher 2016-06-22 23:57:25 +0200 920) }
549c7297717c3 (Christian Brauner 2021-01-21 14:19:43 +0100 921) return inode->i_op->set_acl(mnt_userns, inode, acl, type);
485e71e8fb635 (Andreas Gruenbacher 2016-06-22 23:57:25 +0200 922) }
485e71e8fb635 (Andreas Gruenbacher 2016-06-22 23:57:25 +0200 923) EXPORT_SYMBOL(set_posix_acl);
485e71e8fb635 (Andreas Gruenbacher 2016-06-22 23:57:25 +0200 924)
485e71e8fb635 (Andreas Gruenbacher 2016-06-22 23:57:25 +0200 925) static int
485e71e8fb635 (Andreas Gruenbacher 2016-06-22 23:57:25 +0200 926) posix_acl_xattr_set(const struct xattr_handler *handler,
e65ce2a50cf6a (Christian Brauner 2021-01-21 14:19:27 +0100 927) struct user_namespace *mnt_userns,
e65ce2a50cf6a (Christian Brauner 2021-01-21 14:19:27 +0100 928) struct dentry *unused, struct inode *inode,
e65ce2a50cf6a (Christian Brauner 2021-01-21 14:19:27 +0100 929) const char *name, const void *value, size_t size,
e65ce2a50cf6a (Christian Brauner 2021-01-21 14:19:27 +0100 930) int flags)
485e71e8fb635 (Andreas Gruenbacher 2016-06-22 23:57:25 +0200 931) {
485e71e8fb635 (Andreas Gruenbacher 2016-06-22 23:57:25 +0200 932) struct posix_acl *acl = NULL;
485e71e8fb635 (Andreas Gruenbacher 2016-06-22 23:57:25 +0200 933) int ret;
485e71e8fb635 (Andreas Gruenbacher 2016-06-22 23:57:25 +0200 934)
2aeccbe957d0d (Christoph Hellwig 2013-12-20 05:16:40 -0800 935) if (value) {
2aeccbe957d0d (Christoph Hellwig 2013-12-20 05:16:40 -0800 936) acl = posix_acl_from_xattr(&init_user_ns, value, size);
2aeccbe957d0d (Christoph Hellwig 2013-12-20 05:16:40 -0800 937) if (IS_ERR(acl))
2aeccbe957d0d (Christoph Hellwig 2013-12-20 05:16:40 -0800 938) return PTR_ERR(acl);
2aeccbe957d0d (Christoph Hellwig 2013-12-20 05:16:40 -0800 939) }
e65ce2a50cf6a (Christian Brauner 2021-01-21 14:19:27 +0100 940) ret = set_posix_acl(mnt_userns, inode, handler->flags, acl);
2aeccbe957d0d (Christoph Hellwig 2013-12-20 05:16:40 -0800 941) posix_acl_release(acl);
2aeccbe957d0d (Christoph Hellwig 2013-12-20 05:16:40 -0800 942) return ret;
2aeccbe957d0d (Christoph Hellwig 2013-12-20 05:16:40 -0800 943) }
2aeccbe957d0d (Christoph Hellwig 2013-12-20 05:16:40 -0800 944)
764a5c6b1fa43 (Andreas Gruenbacher 2015-12-02 14:44:43 +0100 945) static bool
764a5c6b1fa43 (Andreas Gruenbacher 2015-12-02 14:44:43 +0100 946) posix_acl_xattr_list(struct dentry *dentry)
2aeccbe957d0d (Christoph Hellwig 2013-12-20 05:16:40 -0800 947) {
764a5c6b1fa43 (Andreas Gruenbacher 2015-12-02 14:44:43 +0100 948) return IS_POSIXACL(d_backing_inode(dentry));
2aeccbe957d0d (Christoph Hellwig 2013-12-20 05:16:40 -0800 949) }
2aeccbe957d0d (Christoph Hellwig 2013-12-20 05:16:40 -0800 950)
2aeccbe957d0d (Christoph Hellwig 2013-12-20 05:16:40 -0800 951) const struct xattr_handler posix_acl_access_xattr_handler = {
98e9cb5711c68 (Andreas Gruenbacher 2015-12-02 14:44:36 +0100 952) .name = XATTR_NAME_POSIX_ACL_ACCESS,
2aeccbe957d0d (Christoph Hellwig 2013-12-20 05:16:40 -0800 953) .flags = ACL_TYPE_ACCESS,
2aeccbe957d0d (Christoph Hellwig 2013-12-20 05:16:40 -0800 954) .list = posix_acl_xattr_list,
2aeccbe957d0d (Christoph Hellwig 2013-12-20 05:16:40 -0800 955) .get = posix_acl_xattr_get,
2aeccbe957d0d (Christoph Hellwig 2013-12-20 05:16:40 -0800 956) .set = posix_acl_xattr_set,
2aeccbe957d0d (Christoph Hellwig 2013-12-20 05:16:40 -0800 957) };
2aeccbe957d0d (Christoph Hellwig 2013-12-20 05:16:40 -0800 958) EXPORT_SYMBOL_GPL(posix_acl_access_xattr_handler);
2aeccbe957d0d (Christoph Hellwig 2013-12-20 05:16:40 -0800 959)
2aeccbe957d0d (Christoph Hellwig 2013-12-20 05:16:40 -0800 960) const struct xattr_handler posix_acl_default_xattr_handler = {
98e9cb5711c68 (Andreas Gruenbacher 2015-12-02 14:44:36 +0100 961) .name = XATTR_NAME_POSIX_ACL_DEFAULT,
2aeccbe957d0d (Christoph Hellwig 2013-12-20 05:16:40 -0800 962) .flags = ACL_TYPE_DEFAULT,
2aeccbe957d0d (Christoph Hellwig 2013-12-20 05:16:40 -0800 963) .list = posix_acl_xattr_list,
2aeccbe957d0d (Christoph Hellwig 2013-12-20 05:16:40 -0800 964) .get = posix_acl_xattr_get,
2aeccbe957d0d (Christoph Hellwig 2013-12-20 05:16:40 -0800 965) .set = posix_acl_xattr_set,
2aeccbe957d0d (Christoph Hellwig 2013-12-20 05:16:40 -0800 966) };
2aeccbe957d0d (Christoph Hellwig 2013-12-20 05:16:40 -0800 967) EXPORT_SYMBOL_GPL(posix_acl_default_xattr_handler);
feda821e76f3b (Christoph Hellwig 2013-12-20 05:16:54 -0800 968)
549c7297717c3 (Christian Brauner 2021-01-21 14:19:43 +0100 969) int simple_set_acl(struct user_namespace *mnt_userns, struct inode *inode,
549c7297717c3 (Christian Brauner 2021-01-21 14:19:43 +0100 970) struct posix_acl *acl, int type)
feda821e76f3b (Christoph Hellwig 2013-12-20 05:16:54 -0800 971) {
feda821e76f3b (Christoph Hellwig 2013-12-20 05:16:54 -0800 972) int error;
feda821e76f3b (Christoph Hellwig 2013-12-20 05:16:54 -0800 973)
feda821e76f3b (Christoph Hellwig 2013-12-20 05:16:54 -0800 974) if (type == ACL_TYPE_ACCESS) {
549c7297717c3 (Christian Brauner 2021-01-21 14:19:43 +0100 975) error = posix_acl_update_mode(mnt_userns, inode,
497de07d89c14 (Gu Zheng 2017-01-09 09:34:48 +0800 976) &inode->i_mode, &acl);
497de07d89c14 (Gu Zheng 2017-01-09 09:34:48 +0800 977) if (error)
497de07d89c14 (Gu Zheng 2017-01-09 09:34:48 +0800 978) return error;
feda821e76f3b (Christoph Hellwig 2013-12-20 05:16:54 -0800 979) }
feda821e76f3b (Christoph Hellwig 2013-12-20 05:16:54 -0800 980)
078cd8279e659 (Deepa Dinamani 2016-09-14 07:48:04 -0700 981) inode->i_ctime = current_time(inode);
feda821e76f3b (Christoph Hellwig 2013-12-20 05:16:54 -0800 982) set_cached_acl(inode, type, acl);
feda821e76f3b (Christoph Hellwig 2013-12-20 05:16:54 -0800 983) return 0;
feda821e76f3b (Christoph Hellwig 2013-12-20 05:16:54 -0800 984) }
feda821e76f3b (Christoph Hellwig 2013-12-20 05:16:54 -0800 985)
feda821e76f3b (Christoph Hellwig 2013-12-20 05:16:54 -0800 986) int simple_acl_create(struct inode *dir, struct inode *inode)
feda821e76f3b (Christoph Hellwig 2013-12-20 05:16:54 -0800 987) {
feda821e76f3b (Christoph Hellwig 2013-12-20 05:16:54 -0800 988) struct posix_acl *default_acl, *acl;
feda821e76f3b (Christoph Hellwig 2013-12-20 05:16:54 -0800 989) int error;
feda821e76f3b (Christoph Hellwig 2013-12-20 05:16:54 -0800 990)
feda821e76f3b (Christoph Hellwig 2013-12-20 05:16:54 -0800 991) error = posix_acl_create(dir, &inode->i_mode, &default_acl, &acl);
feda821e76f3b (Christoph Hellwig 2013-12-20 05:16:54 -0800 992) if (error)
feda821e76f3b (Christoph Hellwig 2013-12-20 05:16:54 -0800 993) return error;
feda821e76f3b (Christoph Hellwig 2013-12-20 05:16:54 -0800 994)
feda821e76f3b (Christoph Hellwig 2013-12-20 05:16:54 -0800 995) set_cached_acl(inode, ACL_TYPE_DEFAULT, default_acl);
feda821e76f3b (Christoph Hellwig 2013-12-20 05:16:54 -0800 996) set_cached_acl(inode, ACL_TYPE_ACCESS, acl);
feda821e76f3b (Christoph Hellwig 2013-12-20 05:16:54 -0800 997)
feda821e76f3b (Christoph Hellwig 2013-12-20 05:16:54 -0800 998) if (default_acl)
feda821e76f3b (Christoph Hellwig 2013-12-20 05:16:54 -0800 999) posix_acl_release(default_acl);
feda821e76f3b (Christoph Hellwig 2013-12-20 05:16:54 -0800 1000) if (acl)
feda821e76f3b (Christoph Hellwig 2013-12-20 05:16:54 -0800 1001) posix_acl_release(acl);
feda821e76f3b (Christoph Hellwig 2013-12-20 05:16:54 -0800 1002) return 0;
feda821e76f3b (Christoph Hellwig 2013-12-20 05:16:54 -0800 1003) }