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