VisionFive2 Linux kernel

StarFive Tech Linux Kernel for VisionFive (JH7110) boards (mirror)

More than 9999 Commits   35 Branches   59 Tags
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) }