1eda14cbcSMatt Macy /*
2eda14cbcSMatt Macy  * CDDL HEADER START
3eda14cbcSMatt Macy  *
4eda14cbcSMatt Macy  * The contents of this file are subject to the terms of the
5eda14cbcSMatt Macy  * Common Development and Distribution License (the "License").
6eda14cbcSMatt Macy  * You may not use this file except in compliance with the License.
7eda14cbcSMatt Macy  *
8eda14cbcSMatt Macy  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9271171e0SMartin Matuska  * or https://opensource.org/licenses/CDDL-1.0.
10eda14cbcSMatt Macy  * See the License for the specific language governing permissions
11eda14cbcSMatt Macy  * and limitations under the License.
12eda14cbcSMatt Macy  *
13eda14cbcSMatt Macy  * When distributing Covered Code, include this CDDL HEADER in each
14eda14cbcSMatt Macy  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15eda14cbcSMatt Macy  * If applicable, add the following below this CDDL HEADER, with the
16eda14cbcSMatt Macy  * fields enclosed by brackets "[]" replaced with your own identifying
17eda14cbcSMatt Macy  * information: Portions Copyright [yyyy] [name of copyright owner]
18eda14cbcSMatt Macy  *
19eda14cbcSMatt Macy  * CDDL HEADER END
20eda14cbcSMatt Macy  */
21eda14cbcSMatt Macy /*
22eda14cbcSMatt Macy  * Copyright (c) 2011, Lawrence Livermore National Security, LLC.
23eda14cbcSMatt Macy  *
24eda14cbcSMatt Macy  * Extended attributes (xattr) on Solaris are implemented as files
25eda14cbcSMatt Macy  * which exist in a hidden xattr directory.  These extended attributes
26eda14cbcSMatt Macy  * can be accessed using the attropen() system call which opens
27eda14cbcSMatt Macy  * the extended attribute.  It can then be manipulated just like
28eda14cbcSMatt Macy  * a standard file descriptor.  This has a couple advantages such
29eda14cbcSMatt Macy  * as practically no size limit on the file, and the extended
30eda14cbcSMatt Macy  * attributes permissions may differ from those of the parent file.
31eda14cbcSMatt Macy  * This interface is really quite clever, but it's also completely
32eda14cbcSMatt Macy  * different than what is supported on Linux.  It also comes with a
33eda14cbcSMatt Macy  * steep performance penalty when accessing small xattrs because they
34eda14cbcSMatt Macy  * are not stored with the parent file.
35eda14cbcSMatt Macy  *
36eda14cbcSMatt Macy  * Under Linux extended attributes are manipulated by the system
37eda14cbcSMatt Macy  * calls getxattr(2), setxattr(2), and listxattr(2).  They consider
38eda14cbcSMatt Macy  * extended attributes to be name/value pairs where the name is a
39eda14cbcSMatt Macy  * NULL terminated string.  The name must also include one of the
40eda14cbcSMatt Macy  * following namespace prefixes:
41eda14cbcSMatt Macy  *
42eda14cbcSMatt Macy  *   user     - No restrictions and is available to user applications.
43eda14cbcSMatt Macy  *   trusted  - Restricted to kernel and root (CAP_SYS_ADMIN) use.
44eda14cbcSMatt Macy  *   system   - Used for access control lists (system.nfs4_acl, etc).
45eda14cbcSMatt Macy  *   security - Used by SELinux to store a files security context.
46eda14cbcSMatt Macy  *
47eda14cbcSMatt Macy  * The value under Linux to limited to 65536 bytes of binary data.
48eda14cbcSMatt Macy  * In practice, individual xattrs tend to be much smaller than this
49eda14cbcSMatt Macy  * and are typically less than 100 bytes.  A good example of this
50eda14cbcSMatt Macy  * are the security.selinux xattrs which are less than 100 bytes and
51eda14cbcSMatt Macy  * exist for every file when xattr labeling is enabled.
52eda14cbcSMatt Macy  *
53eda14cbcSMatt Macy  * The Linux xattr implementation has been written to take advantage of
54eda14cbcSMatt Macy  * this typical usage.  When the dataset property 'xattr=sa' is set,
55eda14cbcSMatt Macy  * then xattrs will be preferentially stored as System Attributes (SA).
56eda14cbcSMatt Macy  * This allows tiny xattrs (~100 bytes) to be stored with the dnode and
57eda14cbcSMatt Macy  * up to 64k of xattrs to be stored in the spill block.  If additional
58eda14cbcSMatt Macy  * xattr space is required, which is unlikely under Linux, they will
59eda14cbcSMatt Macy  * be stored using the traditional directory approach.
60eda14cbcSMatt Macy  *
61eda14cbcSMatt Macy  * This optimization results in roughly a 3x performance improvement
62eda14cbcSMatt Macy  * when accessing xattrs because it avoids the need to perform a seek
63eda14cbcSMatt Macy  * for every xattr value.  When multiple xattrs are stored per-file
64eda14cbcSMatt Macy  * the performance improvements are even greater because all of the
65eda14cbcSMatt Macy  * xattrs stored in the spill block will be cached.
66eda14cbcSMatt Macy  *
67eda14cbcSMatt Macy  * However, by default SA based xattrs are disabled in the Linux port
68eda14cbcSMatt Macy  * to maximize compatibility with other implementations.  If you do
69eda14cbcSMatt Macy  * enable SA based xattrs then they will not be visible on platforms
70eda14cbcSMatt Macy  * which do not support this feature.
71eda14cbcSMatt Macy  *
72eda14cbcSMatt Macy  * NOTE: One additional consequence of the xattr directory implementation
73eda14cbcSMatt Macy  * is that when an extended attribute is manipulated an inode is created.
74eda14cbcSMatt Macy  * This inode will exist in the Linux inode cache but there will be no
75eda14cbcSMatt Macy  * associated entry in the dentry cache which references it.  This is
76eda14cbcSMatt Macy  * safe but it may result in some confusion.  Enabling SA based xattrs
77eda14cbcSMatt Macy  * largely avoids the issue except in the overflow case.
78eda14cbcSMatt Macy  */
79eda14cbcSMatt Macy 
80eda14cbcSMatt Macy #include <sys/zfs_znode.h>
81eda14cbcSMatt Macy #include <sys/zfs_vfsops.h>
82eda14cbcSMatt Macy #include <sys/zfs_vnops.h>
83eda14cbcSMatt Macy #include <sys/zap.h>
84eda14cbcSMatt Macy #include <sys/vfs.h>
85eda14cbcSMatt Macy #include <sys/zpl.h>
861f1e2261SMartin Matuska #include <linux/vfs_compat.h>
87eda14cbcSMatt Macy 
88c03c5b1cSMartin Matuska enum xattr_permission {
89c03c5b1cSMartin Matuska 	XAPERM_DENY,
90c03c5b1cSMartin Matuska 	XAPERM_ALLOW,
91c03c5b1cSMartin Matuska 	XAPERM_COMPAT,
92c03c5b1cSMartin Matuska };
93c03c5b1cSMartin Matuska 
94eda14cbcSMatt Macy typedef struct xattr_filldir {
95eda14cbcSMatt Macy 	size_t size;
96eda14cbcSMatt Macy 	size_t offset;
97eda14cbcSMatt Macy 	char *buf;
98eda14cbcSMatt Macy 	struct dentry *dentry;
99eda14cbcSMatt Macy } xattr_filldir_t;
100eda14cbcSMatt Macy 
101c03c5b1cSMartin Matuska static enum xattr_permission zpl_xattr_permission(xattr_filldir_t *,
102c03c5b1cSMartin Matuska     const char *, int);
103eda14cbcSMatt Macy 
104c03c5b1cSMartin Matuska static int zfs_xattr_compat = 0;
105eda14cbcSMatt Macy 
106eda14cbcSMatt Macy /*
107eda14cbcSMatt Macy  * Determine is a given xattr name should be visible and if so copy it
108eda14cbcSMatt Macy  * in to the provided buffer (xf->buf).
109eda14cbcSMatt Macy  */
110eda14cbcSMatt Macy static int
zpl_xattr_filldir(xattr_filldir_t * xf,const char * name,int name_len)111eda14cbcSMatt Macy zpl_xattr_filldir(xattr_filldir_t *xf, const char *name, int name_len)
112eda14cbcSMatt Macy {
113c03c5b1cSMartin Matuska 	enum xattr_permission perm;
114c03c5b1cSMartin Matuska 
115eda14cbcSMatt Macy 	/* Check permissions using the per-namespace list xattr handler. */
116c03c5b1cSMartin Matuska 	perm = zpl_xattr_permission(xf, name, name_len);
117c03c5b1cSMartin Matuska 	if (perm == XAPERM_DENY)
118eda14cbcSMatt Macy 		return (0);
119eda14cbcSMatt Macy 
120c03c5b1cSMartin Matuska 	/* Prefix the name with "user." if it does not have a namespace. */
121c03c5b1cSMartin Matuska 	if (perm == XAPERM_COMPAT) {
122c03c5b1cSMartin Matuska 		if (xf->buf) {
123c03c5b1cSMartin Matuska 			if (xf->offset + XATTR_USER_PREFIX_LEN + 1 > xf->size)
124c03c5b1cSMartin Matuska 				return (-ERANGE);
125c03c5b1cSMartin Matuska 
126c03c5b1cSMartin Matuska 			memcpy(xf->buf + xf->offset, XATTR_USER_PREFIX,
127c03c5b1cSMartin Matuska 			    XATTR_USER_PREFIX_LEN);
128c03c5b1cSMartin Matuska 			xf->buf[xf->offset + XATTR_USER_PREFIX_LEN] = '\0';
129c03c5b1cSMartin Matuska 		}
130c03c5b1cSMartin Matuska 
131c03c5b1cSMartin Matuska 		xf->offset += XATTR_USER_PREFIX_LEN;
132c03c5b1cSMartin Matuska 	}
133c03c5b1cSMartin Matuska 
134eda14cbcSMatt Macy 	/* When xf->buf is NULL only calculate the required size. */
135eda14cbcSMatt Macy 	if (xf->buf) {
136eda14cbcSMatt Macy 		if (xf->offset + name_len + 1 > xf->size)
137eda14cbcSMatt Macy 			return (-ERANGE);
138eda14cbcSMatt Macy 
139eda14cbcSMatt Macy 		memcpy(xf->buf + xf->offset, name, name_len);
140eda14cbcSMatt Macy 		xf->buf[xf->offset + name_len] = '\0';
141eda14cbcSMatt Macy 	}
142eda14cbcSMatt Macy 
143eda14cbcSMatt Macy 	xf->offset += (name_len + 1);
144eda14cbcSMatt Macy 
145eda14cbcSMatt Macy 	return (0);
146eda14cbcSMatt Macy }
147eda14cbcSMatt Macy 
148eda14cbcSMatt Macy /*
149eda14cbcSMatt Macy  * Read as many directory entry names as will fit in to the provided buffer,
150eda14cbcSMatt Macy  * or when no buffer is provided calculate the required buffer size.
151eda14cbcSMatt Macy  */
152eda14cbcSMatt Macy static int
zpl_xattr_readdir(struct inode * dxip,xattr_filldir_t * xf)153eda14cbcSMatt Macy zpl_xattr_readdir(struct inode *dxip, xattr_filldir_t *xf)
154eda14cbcSMatt Macy {
155eda14cbcSMatt Macy 	zap_cursor_t zc;
156eda14cbcSMatt Macy 	zap_attribute_t	zap;
157eda14cbcSMatt Macy 	int error;
158eda14cbcSMatt Macy 
159eda14cbcSMatt Macy 	zap_cursor_init(&zc, ITOZSB(dxip)->z_os, ITOZ(dxip)->z_id);
160eda14cbcSMatt Macy 
161eda14cbcSMatt Macy 	while ((error = -zap_cursor_retrieve(&zc, &zap)) == 0) {
162eda14cbcSMatt Macy 
163eda14cbcSMatt Macy 		if (zap.za_integer_length != 8 || zap.za_num_integers != 1) {
164eda14cbcSMatt Macy 			error = -ENXIO;
165eda14cbcSMatt Macy 			break;
166eda14cbcSMatt Macy 		}
167eda14cbcSMatt Macy 
168eda14cbcSMatt Macy 		error = zpl_xattr_filldir(xf, zap.za_name, strlen(zap.za_name));
169eda14cbcSMatt Macy 		if (error)
170eda14cbcSMatt Macy 			break;
171eda14cbcSMatt Macy 
172eda14cbcSMatt Macy 		zap_cursor_advance(&zc);
173eda14cbcSMatt Macy 	}
174eda14cbcSMatt Macy 
175eda14cbcSMatt Macy 	zap_cursor_fini(&zc);
176eda14cbcSMatt Macy 
177eda14cbcSMatt Macy 	if (error == -ENOENT)
178eda14cbcSMatt Macy 		error = 0;
179eda14cbcSMatt Macy 
180eda14cbcSMatt Macy 	return (error);
181eda14cbcSMatt Macy }
182eda14cbcSMatt Macy 
183eda14cbcSMatt Macy static ssize_t
zpl_xattr_list_dir(xattr_filldir_t * xf,cred_t * cr)184eda14cbcSMatt Macy zpl_xattr_list_dir(xattr_filldir_t *xf, cred_t *cr)
185eda14cbcSMatt Macy {
186eda14cbcSMatt Macy 	struct inode *ip = xf->dentry->d_inode;
187eda14cbcSMatt Macy 	struct inode *dxip = NULL;
188eda14cbcSMatt Macy 	znode_t *dxzp;
189eda14cbcSMatt Macy 	int error;
190eda14cbcSMatt Macy 
191eda14cbcSMatt Macy 	/* Lookup the xattr directory */
192eda14cbcSMatt Macy 	error = -zfs_lookup(ITOZ(ip), NULL, &dxzp, LOOKUP_XATTR,
193eda14cbcSMatt Macy 	    cr, NULL, NULL);
194eda14cbcSMatt Macy 	if (error) {
195eda14cbcSMatt Macy 		if (error == -ENOENT)
196eda14cbcSMatt Macy 			error = 0;
197eda14cbcSMatt Macy 
198eda14cbcSMatt Macy 		return (error);
199eda14cbcSMatt Macy 	}
200eda14cbcSMatt Macy 
201eda14cbcSMatt Macy 	dxip = ZTOI(dxzp);
202eda14cbcSMatt Macy 	error = zpl_xattr_readdir(dxip, xf);
203eda14cbcSMatt Macy 	iput(dxip);
204eda14cbcSMatt Macy 
205eda14cbcSMatt Macy 	return (error);
206eda14cbcSMatt Macy }
207eda14cbcSMatt Macy 
208eda14cbcSMatt Macy static ssize_t
zpl_xattr_list_sa(xattr_filldir_t * xf)209eda14cbcSMatt Macy zpl_xattr_list_sa(xattr_filldir_t *xf)
210eda14cbcSMatt Macy {
211eda14cbcSMatt Macy 	znode_t *zp = ITOZ(xf->dentry->d_inode);
212eda14cbcSMatt Macy 	nvpair_t *nvp = NULL;
213eda14cbcSMatt Macy 	int error = 0;
214eda14cbcSMatt Macy 
215eda14cbcSMatt Macy 	mutex_enter(&zp->z_lock);
216eda14cbcSMatt Macy 	if (zp->z_xattr_cached == NULL)
217eda14cbcSMatt Macy 		error = -zfs_sa_get_xattr(zp);
218eda14cbcSMatt Macy 	mutex_exit(&zp->z_lock);
219eda14cbcSMatt Macy 
220eda14cbcSMatt Macy 	if (error)
221eda14cbcSMatt Macy 		return (error);
222eda14cbcSMatt Macy 
223eda14cbcSMatt Macy 	ASSERT(zp->z_xattr_cached);
224eda14cbcSMatt Macy 
225eda14cbcSMatt Macy 	while ((nvp = nvlist_next_nvpair(zp->z_xattr_cached, nvp)) != NULL) {
226eda14cbcSMatt Macy 		ASSERT3U(nvpair_type(nvp), ==, DATA_TYPE_BYTE_ARRAY);
227eda14cbcSMatt Macy 
228eda14cbcSMatt Macy 		error = zpl_xattr_filldir(xf, nvpair_name(nvp),
229eda14cbcSMatt Macy 		    strlen(nvpair_name(nvp)));
230eda14cbcSMatt Macy 		if (error)
231eda14cbcSMatt Macy 			return (error);
232eda14cbcSMatt Macy 	}
233eda14cbcSMatt Macy 
234eda14cbcSMatt Macy 	return (0);
235eda14cbcSMatt Macy }
236eda14cbcSMatt Macy 
237eda14cbcSMatt Macy ssize_t
zpl_xattr_list(struct dentry * dentry,char * buffer,size_t buffer_size)238eda14cbcSMatt Macy zpl_xattr_list(struct dentry *dentry, char *buffer, size_t buffer_size)
239eda14cbcSMatt Macy {
240eda14cbcSMatt Macy 	znode_t *zp = ITOZ(dentry->d_inode);
241eda14cbcSMatt Macy 	zfsvfs_t *zfsvfs = ZTOZSB(zp);
242eda14cbcSMatt Macy 	xattr_filldir_t xf = { buffer_size, 0, buffer, dentry };
243eda14cbcSMatt Macy 	cred_t *cr = CRED();
244eda14cbcSMatt Macy 	fstrans_cookie_t cookie;
245eda14cbcSMatt Macy 	int error = 0;
246eda14cbcSMatt Macy 
247eda14cbcSMatt Macy 	crhold(cr);
248eda14cbcSMatt Macy 	cookie = spl_fstrans_mark();
249c7046f76SMartin Matuska 	if ((error = zpl_enter_verify_zp(zfsvfs, zp, FTAG)) != 0)
250c7046f76SMartin Matuska 		goto out1;
251eda14cbcSMatt Macy 	rw_enter(&zp->z_xattr_lock, RW_READER);
252eda14cbcSMatt Macy 
253eda14cbcSMatt Macy 	if (zfsvfs->z_use_sa && zp->z_is_sa) {
254eda14cbcSMatt Macy 		error = zpl_xattr_list_sa(&xf);
255eda14cbcSMatt Macy 		if (error)
256eda14cbcSMatt Macy 			goto out;
257eda14cbcSMatt Macy 	}
258eda14cbcSMatt Macy 
259eda14cbcSMatt Macy 	error = zpl_xattr_list_dir(&xf, cr);
260eda14cbcSMatt Macy 	if (error)
261eda14cbcSMatt Macy 		goto out;
262eda14cbcSMatt Macy 
263eda14cbcSMatt Macy 	error = xf.offset;
264eda14cbcSMatt Macy out:
265eda14cbcSMatt Macy 
266eda14cbcSMatt Macy 	rw_exit(&zp->z_xattr_lock);
267c7046f76SMartin Matuska 	zpl_exit(zfsvfs, FTAG);
268c7046f76SMartin Matuska out1:
269eda14cbcSMatt Macy 	spl_fstrans_unmark(cookie);
270eda14cbcSMatt Macy 	crfree(cr);
271eda14cbcSMatt Macy 
272eda14cbcSMatt Macy 	return (error);
273eda14cbcSMatt Macy }
274eda14cbcSMatt Macy 
275eda14cbcSMatt Macy static int
zpl_xattr_get_dir(struct inode * ip,const char * name,void * value,size_t size,cred_t * cr)276eda14cbcSMatt Macy zpl_xattr_get_dir(struct inode *ip, const char *name, void *value,
277eda14cbcSMatt Macy     size_t size, cred_t *cr)
278eda14cbcSMatt Macy {
2797877fdebSMatt Macy 	fstrans_cookie_t cookie;
280eda14cbcSMatt Macy 	struct inode *xip = NULL;
281eda14cbcSMatt Macy 	znode_t *dxzp = NULL;
282eda14cbcSMatt Macy 	znode_t *xzp = NULL;
283eda14cbcSMatt Macy 	int error;
284eda14cbcSMatt Macy 
285eda14cbcSMatt Macy 	/* Lookup the xattr directory */
286eda14cbcSMatt Macy 	error = -zfs_lookup(ITOZ(ip), NULL, &dxzp, LOOKUP_XATTR,
287eda14cbcSMatt Macy 	    cr, NULL, NULL);
288eda14cbcSMatt Macy 	if (error)
289eda14cbcSMatt Macy 		goto out;
290eda14cbcSMatt Macy 
291eda14cbcSMatt Macy 	/* Lookup a specific xattr name in the directory */
292eda14cbcSMatt Macy 	error = -zfs_lookup(dxzp, (char *)name, &xzp, 0, cr, NULL, NULL);
293eda14cbcSMatt Macy 	if (error)
294eda14cbcSMatt Macy 		goto out;
295eda14cbcSMatt Macy 
296eda14cbcSMatt Macy 	xip = ZTOI(xzp);
297eda14cbcSMatt Macy 	if (!size) {
298eda14cbcSMatt Macy 		error = i_size_read(xip);
299eda14cbcSMatt Macy 		goto out;
300eda14cbcSMatt Macy 	}
301eda14cbcSMatt Macy 
302eda14cbcSMatt Macy 	if (size < i_size_read(xip)) {
303eda14cbcSMatt Macy 		error = -ERANGE;
304eda14cbcSMatt Macy 		goto out;
305eda14cbcSMatt Macy 	}
306eda14cbcSMatt Macy 
3077877fdebSMatt Macy 	struct iovec iov;
3087877fdebSMatt Macy 	iov.iov_base = (void *)value;
3097877fdebSMatt Macy 	iov.iov_len = size;
3107877fdebSMatt Macy 
311184c1b94SMartin Matuska 	zfs_uio_t uio;
312184c1b94SMartin Matuska 	zfs_uio_iovec_init(&uio, &iov, 1, 0, UIO_SYSSPACE, size, 0);
3137877fdebSMatt Macy 
3147877fdebSMatt Macy 	cookie = spl_fstrans_mark();
3157877fdebSMatt Macy 	error = -zfs_read(ITOZ(xip), &uio, 0, cr);
3167877fdebSMatt Macy 	spl_fstrans_unmark(cookie);
3177877fdebSMatt Macy 
3187877fdebSMatt Macy 	if (error == 0)
319184c1b94SMartin Matuska 		error = size - zfs_uio_resid(&uio);
320eda14cbcSMatt Macy out:
321eda14cbcSMatt Macy 	if (xzp)
322eda14cbcSMatt Macy 		zrele(xzp);
323eda14cbcSMatt Macy 
324eda14cbcSMatt Macy 	if (dxzp)
325eda14cbcSMatt Macy 		zrele(dxzp);
326eda14cbcSMatt Macy 
327eda14cbcSMatt Macy 	return (error);
328eda14cbcSMatt Macy }
329eda14cbcSMatt Macy 
330eda14cbcSMatt Macy static int
zpl_xattr_get_sa(struct inode * ip,const char * name,void * value,size_t size)331eda14cbcSMatt Macy zpl_xattr_get_sa(struct inode *ip, const char *name, void *value, size_t size)
332eda14cbcSMatt Macy {
333eda14cbcSMatt Macy 	znode_t *zp = ITOZ(ip);
334eda14cbcSMatt Macy 	uchar_t *nv_value;
335eda14cbcSMatt Macy 	uint_t nv_size;
336eda14cbcSMatt Macy 	int error = 0;
337eda14cbcSMatt Macy 
338eda14cbcSMatt Macy 	ASSERT(RW_LOCK_HELD(&zp->z_xattr_lock));
339eda14cbcSMatt Macy 
340eda14cbcSMatt Macy 	mutex_enter(&zp->z_lock);
341eda14cbcSMatt Macy 	if (zp->z_xattr_cached == NULL)
342eda14cbcSMatt Macy 		error = -zfs_sa_get_xattr(zp);
343eda14cbcSMatt Macy 	mutex_exit(&zp->z_lock);
344eda14cbcSMatt Macy 
345eda14cbcSMatt Macy 	if (error)
346eda14cbcSMatt Macy 		return (error);
347eda14cbcSMatt Macy 
348eda14cbcSMatt Macy 	ASSERT(zp->z_xattr_cached);
349eda14cbcSMatt Macy 	error = -nvlist_lookup_byte_array(zp->z_xattr_cached, name,
350eda14cbcSMatt Macy 	    &nv_value, &nv_size);
351eda14cbcSMatt Macy 	if (error)
352eda14cbcSMatt Macy 		return (error);
353eda14cbcSMatt Macy 
354eda14cbcSMatt Macy 	if (size == 0 || value == NULL)
355eda14cbcSMatt Macy 		return (nv_size);
356eda14cbcSMatt Macy 
357eda14cbcSMatt Macy 	if (size < nv_size)
358eda14cbcSMatt Macy 		return (-ERANGE);
359eda14cbcSMatt Macy 
360eda14cbcSMatt Macy 	memcpy(value, nv_value, nv_size);
361eda14cbcSMatt Macy 
362eda14cbcSMatt Macy 	return (nv_size);
363eda14cbcSMatt Macy }
364eda14cbcSMatt Macy 
365eda14cbcSMatt Macy static int
__zpl_xattr_get(struct inode * ip,const char * name,void * value,size_t size,cred_t * cr)366eda14cbcSMatt Macy __zpl_xattr_get(struct inode *ip, const char *name, void *value, size_t size,
367eda14cbcSMatt Macy     cred_t *cr)
368eda14cbcSMatt Macy {
369eda14cbcSMatt Macy 	znode_t *zp = ITOZ(ip);
370eda14cbcSMatt Macy 	zfsvfs_t *zfsvfs = ZTOZSB(zp);
371eda14cbcSMatt Macy 	int error;
372eda14cbcSMatt Macy 
373eda14cbcSMatt Macy 	ASSERT(RW_LOCK_HELD(&zp->z_xattr_lock));
374eda14cbcSMatt Macy 
375eda14cbcSMatt Macy 	if (zfsvfs->z_use_sa && zp->z_is_sa) {
376eda14cbcSMatt Macy 		error = zpl_xattr_get_sa(ip, name, value, size);
377eda14cbcSMatt Macy 		if (error != -ENOENT)
378eda14cbcSMatt Macy 			goto out;
379eda14cbcSMatt Macy 	}
380eda14cbcSMatt Macy 
381eda14cbcSMatt Macy 	error = zpl_xattr_get_dir(ip, name, value, size, cr);
382eda14cbcSMatt Macy out:
383eda14cbcSMatt Macy 	if (error == -ENOENT)
384eda14cbcSMatt Macy 		error = -ENODATA;
385eda14cbcSMatt Macy 
386eda14cbcSMatt Macy 	return (error);
387eda14cbcSMatt Macy }
388eda14cbcSMatt Macy 
389eda14cbcSMatt Macy #define	XATTR_NOENT	0x0
390eda14cbcSMatt Macy #define	XATTR_IN_SA	0x1
391eda14cbcSMatt Macy #define	XATTR_IN_DIR	0x2
392eda14cbcSMatt Macy /* check where the xattr resides */
393eda14cbcSMatt Macy static int
__zpl_xattr_where(struct inode * ip,const char * name,int * where,cred_t * cr)394eda14cbcSMatt Macy __zpl_xattr_where(struct inode *ip, const char *name, int *where, cred_t *cr)
395eda14cbcSMatt Macy {
396eda14cbcSMatt Macy 	znode_t *zp = ITOZ(ip);
397eda14cbcSMatt Macy 	zfsvfs_t *zfsvfs = ZTOZSB(zp);
398eda14cbcSMatt Macy 	int error;
399eda14cbcSMatt Macy 
400eda14cbcSMatt Macy 	ASSERT(where);
401eda14cbcSMatt Macy 	ASSERT(RW_LOCK_HELD(&zp->z_xattr_lock));
402eda14cbcSMatt Macy 
403eda14cbcSMatt Macy 	*where = XATTR_NOENT;
404eda14cbcSMatt Macy 	if (zfsvfs->z_use_sa && zp->z_is_sa) {
405eda14cbcSMatt Macy 		error = zpl_xattr_get_sa(ip, name, NULL, 0);
406eda14cbcSMatt Macy 		if (error >= 0)
407eda14cbcSMatt Macy 			*where |= XATTR_IN_SA;
408eda14cbcSMatt Macy 		else if (error != -ENOENT)
409eda14cbcSMatt Macy 			return (error);
410eda14cbcSMatt Macy 	}
411eda14cbcSMatt Macy 
412eda14cbcSMatt Macy 	error = zpl_xattr_get_dir(ip, name, NULL, 0, cr);
413eda14cbcSMatt Macy 	if (error >= 0)
414eda14cbcSMatt Macy 		*where |= XATTR_IN_DIR;
415eda14cbcSMatt Macy 	else if (error != -ENOENT)
416eda14cbcSMatt Macy 		return (error);
417eda14cbcSMatt Macy 
418eda14cbcSMatt Macy 	if (*where == (XATTR_IN_SA|XATTR_IN_DIR))
419eda14cbcSMatt Macy 		cmn_err(CE_WARN, "ZFS: inode %p has xattr \"%s\""
420eda14cbcSMatt Macy 		    " in both SA and dir", ip, name);
421eda14cbcSMatt Macy 	if (*where == XATTR_NOENT)
422eda14cbcSMatt Macy 		error = -ENODATA;
423eda14cbcSMatt Macy 	else
424eda14cbcSMatt Macy 		error = 0;
425eda14cbcSMatt Macy 	return (error);
426eda14cbcSMatt Macy }
427eda14cbcSMatt Macy 
428eda14cbcSMatt Macy static int
zpl_xattr_get(struct inode * ip,const char * name,void * value,size_t size)429eda14cbcSMatt Macy zpl_xattr_get(struct inode *ip, const char *name, void *value, size_t size)
430eda14cbcSMatt Macy {
431eda14cbcSMatt Macy 	znode_t *zp = ITOZ(ip);
432eda14cbcSMatt Macy 	zfsvfs_t *zfsvfs = ZTOZSB(zp);
433eda14cbcSMatt Macy 	cred_t *cr = CRED();
434eda14cbcSMatt Macy 	fstrans_cookie_t cookie;
435eda14cbcSMatt Macy 	int error;
436eda14cbcSMatt Macy 
437eda14cbcSMatt Macy 	crhold(cr);
438eda14cbcSMatt Macy 	cookie = spl_fstrans_mark();
439c7046f76SMartin Matuska 	if ((error = zpl_enter_verify_zp(zfsvfs, zp, FTAG)) != 0)
440c7046f76SMartin Matuska 		goto out;
441eda14cbcSMatt Macy 	rw_enter(&zp->z_xattr_lock, RW_READER);
442eda14cbcSMatt Macy 	error = __zpl_xattr_get(ip, name, value, size, cr);
443eda14cbcSMatt Macy 	rw_exit(&zp->z_xattr_lock);
444c7046f76SMartin Matuska 	zpl_exit(zfsvfs, FTAG);
445c7046f76SMartin Matuska out:
446eda14cbcSMatt Macy 	spl_fstrans_unmark(cookie);
447eda14cbcSMatt Macy 	crfree(cr);
448eda14cbcSMatt Macy 
449eda14cbcSMatt Macy 	return (error);
450eda14cbcSMatt Macy }
451eda14cbcSMatt Macy 
452eda14cbcSMatt Macy static int
zpl_xattr_set_dir(struct inode * ip,const char * name,const void * value,size_t size,int flags,cred_t * cr)453eda14cbcSMatt Macy zpl_xattr_set_dir(struct inode *ip, const char *name, const void *value,
454eda14cbcSMatt Macy     size_t size, int flags, cred_t *cr)
455eda14cbcSMatt Macy {
456eda14cbcSMatt Macy 	znode_t *dxzp = NULL;
457eda14cbcSMatt Macy 	znode_t *xzp = NULL;
458eda14cbcSMatt Macy 	vattr_t *vap = NULL;
459eda14cbcSMatt Macy 	int lookup_flags, error;
460eda14cbcSMatt Macy 	const int xattr_mode = S_IFREG | 0644;
461eda14cbcSMatt Macy 	loff_t pos = 0;
462eda14cbcSMatt Macy 
463eda14cbcSMatt Macy 	/*
464eda14cbcSMatt Macy 	 * Lookup the xattr directory.  When we're adding an entry pass
465eda14cbcSMatt Macy 	 * CREATE_XATTR_DIR to ensure the xattr directory is created.
466eda14cbcSMatt Macy 	 * When removing an entry this flag is not passed to avoid
467eda14cbcSMatt Macy 	 * unnecessarily creating a new xattr directory.
468eda14cbcSMatt Macy 	 */
469eda14cbcSMatt Macy 	lookup_flags = LOOKUP_XATTR;
470eda14cbcSMatt Macy 	if (value != NULL)
471eda14cbcSMatt Macy 		lookup_flags |= CREATE_XATTR_DIR;
472eda14cbcSMatt Macy 
473eda14cbcSMatt Macy 	error = -zfs_lookup(ITOZ(ip), NULL, &dxzp, lookup_flags,
474eda14cbcSMatt Macy 	    cr, NULL, NULL);
475eda14cbcSMatt Macy 	if (error)
476eda14cbcSMatt Macy 		goto out;
477eda14cbcSMatt Macy 
478eda14cbcSMatt Macy 	/* Lookup a specific xattr name in the directory */
479eda14cbcSMatt Macy 	error = -zfs_lookup(dxzp, (char *)name, &xzp, 0, cr, NULL, NULL);
480eda14cbcSMatt Macy 	if (error && (error != -ENOENT))
481eda14cbcSMatt Macy 		goto out;
482eda14cbcSMatt Macy 
483eda14cbcSMatt Macy 	error = 0;
484eda14cbcSMatt Macy 
485eda14cbcSMatt Macy 	/* Remove a specific name xattr when value is set to NULL. */
486eda14cbcSMatt Macy 	if (value == NULL) {
487eda14cbcSMatt Macy 		if (xzp)
488eda14cbcSMatt Macy 			error = -zfs_remove(dxzp, (char *)name, cr, 0);
489eda14cbcSMatt Macy 
490eda14cbcSMatt Macy 		goto out;
491eda14cbcSMatt Macy 	}
492eda14cbcSMatt Macy 
493eda14cbcSMatt Macy 	/* Lookup failed create a new xattr. */
494eda14cbcSMatt Macy 	if (xzp == NULL) {
495eda14cbcSMatt Macy 		vap = kmem_zalloc(sizeof (vattr_t), KM_SLEEP);
496eda14cbcSMatt Macy 		vap->va_mode = xattr_mode;
497eda14cbcSMatt Macy 		vap->va_mask = ATTR_MODE;
498da5137abSMartin Matuska 		vap->va_uid = crgetuid(cr);
499da5137abSMartin Matuska 		vap->va_gid = crgetgid(cr);
500eda14cbcSMatt Macy 
501eda14cbcSMatt Macy 		error = -zfs_create(dxzp, (char *)name, vap, 0, 0644, &xzp,
502d411c1d6SMartin Matuska 		    cr, ATTR_NOACLCHECK, NULL, zfs_init_idmap);
503eda14cbcSMatt Macy 		if (error)
504eda14cbcSMatt Macy 			goto out;
505eda14cbcSMatt Macy 	}
506eda14cbcSMatt Macy 
507eda14cbcSMatt Macy 	ASSERT(xzp != NULL);
508eda14cbcSMatt Macy 
509eda14cbcSMatt Macy 	error = -zfs_freesp(xzp, 0, 0, xattr_mode, TRUE);
510eda14cbcSMatt Macy 	if (error)
511eda14cbcSMatt Macy 		goto out;
512eda14cbcSMatt Macy 
5137877fdebSMatt Macy 	error = -zfs_write_simple(xzp, value, size, pos, NULL);
514eda14cbcSMatt Macy out:
515eda14cbcSMatt Macy 	if (error == 0) {
516abcdc1b9SMartin Matuska 		zpl_inode_set_ctime_to_ts(ip, current_time(ip));
517eda14cbcSMatt Macy 		zfs_mark_inode_dirty(ip);
518eda14cbcSMatt Macy 	}
519eda14cbcSMatt Macy 
520eda14cbcSMatt Macy 	if (vap)
521eda14cbcSMatt Macy 		kmem_free(vap, sizeof (vattr_t));
522eda14cbcSMatt Macy 
523eda14cbcSMatt Macy 	if (xzp)
524eda14cbcSMatt Macy 		zrele(xzp);
525eda14cbcSMatt Macy 
526eda14cbcSMatt Macy 	if (dxzp)
527eda14cbcSMatt Macy 		zrele(dxzp);
528eda14cbcSMatt Macy 
529eda14cbcSMatt Macy 	if (error == -ENOENT)
530eda14cbcSMatt Macy 		error = -ENODATA;
531eda14cbcSMatt Macy 
532eda14cbcSMatt Macy 	ASSERT3S(error, <=, 0);
533eda14cbcSMatt Macy 
534eda14cbcSMatt Macy 	return (error);
535eda14cbcSMatt Macy }
536eda14cbcSMatt Macy 
537eda14cbcSMatt Macy static int
zpl_xattr_set_sa(struct inode * ip,const char * name,const void * value,size_t size,int flags,cred_t * cr)538eda14cbcSMatt Macy zpl_xattr_set_sa(struct inode *ip, const char *name, const void *value,
539eda14cbcSMatt Macy     size_t size, int flags, cred_t *cr)
540eda14cbcSMatt Macy {
541eda14cbcSMatt Macy 	znode_t *zp = ITOZ(ip);
542eda14cbcSMatt Macy 	nvlist_t *nvl;
543eda14cbcSMatt Macy 	size_t sa_size;
544eda14cbcSMatt Macy 	int error = 0;
545eda14cbcSMatt Macy 
546eda14cbcSMatt Macy 	mutex_enter(&zp->z_lock);
547eda14cbcSMatt Macy 	if (zp->z_xattr_cached == NULL)
548eda14cbcSMatt Macy 		error = -zfs_sa_get_xattr(zp);
549eda14cbcSMatt Macy 	mutex_exit(&zp->z_lock);
550eda14cbcSMatt Macy 
551eda14cbcSMatt Macy 	if (error)
552eda14cbcSMatt Macy 		return (error);
553eda14cbcSMatt Macy 
554eda14cbcSMatt Macy 	ASSERT(zp->z_xattr_cached);
555eda14cbcSMatt Macy 	nvl = zp->z_xattr_cached;
556eda14cbcSMatt Macy 
557eda14cbcSMatt Macy 	if (value == NULL) {
558eda14cbcSMatt Macy 		error = -nvlist_remove(nvl, name, DATA_TYPE_BYTE_ARRAY);
559eda14cbcSMatt Macy 		if (error == -ENOENT)
560eda14cbcSMatt Macy 			error = zpl_xattr_set_dir(ip, name, NULL, 0, flags, cr);
561eda14cbcSMatt Macy 	} else {
562eda14cbcSMatt Macy 		/* Limited to 32k to keep nvpair memory allocations small */
563eda14cbcSMatt Macy 		if (size > DXATTR_MAX_ENTRY_SIZE)
564eda14cbcSMatt Macy 			return (-EFBIG);
565eda14cbcSMatt Macy 
566eda14cbcSMatt Macy 		/* Prevent the DXATTR SA from consuming the entire SA region */
567eda14cbcSMatt Macy 		error = -nvlist_size(nvl, &sa_size, NV_ENCODE_XDR);
568eda14cbcSMatt Macy 		if (error)
569eda14cbcSMatt Macy 			return (error);
570eda14cbcSMatt Macy 
571eda14cbcSMatt Macy 		if (sa_size > DXATTR_MAX_SA_SIZE)
572eda14cbcSMatt Macy 			return (-EFBIG);
573eda14cbcSMatt Macy 
574eda14cbcSMatt Macy 		error = -nvlist_add_byte_array(nvl, name,
575eda14cbcSMatt Macy 		    (uchar_t *)value, size);
576eda14cbcSMatt Macy 	}
577eda14cbcSMatt Macy 
578eda14cbcSMatt Macy 	/*
579eda14cbcSMatt Macy 	 * Update the SA for additions, modifications, and removals. On
580eda14cbcSMatt Macy 	 * error drop the inconsistent cached version of the nvlist, it
581eda14cbcSMatt Macy 	 * will be reconstructed from the ARC when next accessed.
582eda14cbcSMatt Macy 	 */
583eda14cbcSMatt Macy 	if (error == 0)
584c03c5b1cSMartin Matuska 		error = -zfs_sa_set_xattr(zp, name, value, size);
585eda14cbcSMatt Macy 
586eda14cbcSMatt Macy 	if (error) {
587eda14cbcSMatt Macy 		nvlist_free(nvl);
588eda14cbcSMatt Macy 		zp->z_xattr_cached = NULL;
589eda14cbcSMatt Macy 	}
590eda14cbcSMatt Macy 
591eda14cbcSMatt Macy 	ASSERT3S(error, <=, 0);
592eda14cbcSMatt Macy 
593eda14cbcSMatt Macy 	return (error);
594eda14cbcSMatt Macy }
595eda14cbcSMatt Macy 
596eda14cbcSMatt Macy static int
zpl_xattr_set(struct inode * ip,const char * name,const void * value,size_t size,int flags)597eda14cbcSMatt Macy zpl_xattr_set(struct inode *ip, const char *name, const void *value,
598eda14cbcSMatt Macy     size_t size, int flags)
599eda14cbcSMatt Macy {
600eda14cbcSMatt Macy 	znode_t *zp = ITOZ(ip);
601eda14cbcSMatt Macy 	zfsvfs_t *zfsvfs = ZTOZSB(zp);
602eda14cbcSMatt Macy 	cred_t *cr = CRED();
603eda14cbcSMatt Macy 	fstrans_cookie_t cookie;
604eda14cbcSMatt Macy 	int where;
605eda14cbcSMatt Macy 	int error;
606eda14cbcSMatt Macy 
607eda14cbcSMatt Macy 	crhold(cr);
608eda14cbcSMatt Macy 	cookie = spl_fstrans_mark();
609c7046f76SMartin Matuska 	if ((error = zpl_enter_verify_zp(zfsvfs, zp, FTAG)) != 0)
610c7046f76SMartin Matuska 		goto out1;
61116038816SMartin Matuska 	rw_enter(&zp->z_xattr_lock, RW_WRITER);
612eda14cbcSMatt Macy 
613eda14cbcSMatt Macy 	/*
614eda14cbcSMatt Macy 	 * Before setting the xattr check to see if it already exists.
615eda14cbcSMatt Macy 	 * This is done to ensure the following optional flags are honored.
616eda14cbcSMatt Macy 	 *
617eda14cbcSMatt Macy 	 *   XATTR_CREATE: fail if xattr already exists
618eda14cbcSMatt Macy 	 *   XATTR_REPLACE: fail if xattr does not exist
619eda14cbcSMatt Macy 	 *
620eda14cbcSMatt Macy 	 * We also want to know if it resides in sa or dir, so we can make
621eda14cbcSMatt Macy 	 * sure we don't end up with duplicate in both places.
622eda14cbcSMatt Macy 	 */
623eda14cbcSMatt Macy 	error = __zpl_xattr_where(ip, name, &where, cr);
624eda14cbcSMatt Macy 	if (error < 0) {
625eda14cbcSMatt Macy 		if (error != -ENODATA)
626eda14cbcSMatt Macy 			goto out;
627eda14cbcSMatt Macy 		if (flags & XATTR_REPLACE)
628eda14cbcSMatt Macy 			goto out;
629eda14cbcSMatt Macy 
630eda14cbcSMatt Macy 		/* The xattr to be removed already doesn't exist */
631eda14cbcSMatt Macy 		error = 0;
632eda14cbcSMatt Macy 		if (value == NULL)
633eda14cbcSMatt Macy 			goto out;
634eda14cbcSMatt Macy 	} else {
635eda14cbcSMatt Macy 		error = -EEXIST;
636eda14cbcSMatt Macy 		if (flags & XATTR_CREATE)
637eda14cbcSMatt Macy 			goto out;
638eda14cbcSMatt Macy 	}
639eda14cbcSMatt Macy 
640eda14cbcSMatt Macy 	/* Preferentially store the xattr as a SA for better performance */
641eda14cbcSMatt Macy 	if (zfsvfs->z_use_sa && zp->z_is_sa &&
642eda14cbcSMatt Macy 	    (zfsvfs->z_xattr_sa || (value == NULL && where & XATTR_IN_SA))) {
643eda14cbcSMatt Macy 		error = zpl_xattr_set_sa(ip, name, value, size, flags, cr);
644eda14cbcSMatt Macy 		if (error == 0) {
645eda14cbcSMatt Macy 			/*
646eda14cbcSMatt Macy 			 * Successfully put into SA, we need to clear the one
647eda14cbcSMatt Macy 			 * in dir.
648eda14cbcSMatt Macy 			 */
649eda14cbcSMatt Macy 			if (where & XATTR_IN_DIR)
650eda14cbcSMatt Macy 				zpl_xattr_set_dir(ip, name, NULL, 0, 0, cr);
651eda14cbcSMatt Macy 			goto out;
652eda14cbcSMatt Macy 		}
653eda14cbcSMatt Macy 	}
654eda14cbcSMatt Macy 
655eda14cbcSMatt Macy 	error = zpl_xattr_set_dir(ip, name, value, size, flags, cr);
656eda14cbcSMatt Macy 	/*
657eda14cbcSMatt Macy 	 * Successfully put into dir, we need to clear the one in SA.
658eda14cbcSMatt Macy 	 */
659eda14cbcSMatt Macy 	if (error == 0 && (where & XATTR_IN_SA))
660eda14cbcSMatt Macy 		zpl_xattr_set_sa(ip, name, NULL, 0, 0, cr);
661eda14cbcSMatt Macy out:
66216038816SMartin Matuska 	rw_exit(&zp->z_xattr_lock);
663c7046f76SMartin Matuska 	zpl_exit(zfsvfs, FTAG);
664c7046f76SMartin Matuska out1:
665eda14cbcSMatt Macy 	spl_fstrans_unmark(cookie);
666eda14cbcSMatt Macy 	crfree(cr);
667eda14cbcSMatt Macy 	ASSERT3S(error, <=, 0);
668eda14cbcSMatt Macy 
669eda14cbcSMatt Macy 	return (error);
670eda14cbcSMatt Macy }
671eda14cbcSMatt Macy 
672eda14cbcSMatt Macy /*
673eda14cbcSMatt Macy  * Extended user attributes
674eda14cbcSMatt Macy  *
675eda14cbcSMatt Macy  * "Extended user attributes may be assigned to files and directories for
676eda14cbcSMatt Macy  * storing arbitrary additional information such as the mime type,
677eda14cbcSMatt Macy  * character set or encoding of a file.  The access permissions for user
678eda14cbcSMatt Macy  * attributes are defined by the file permission bits: read permission
679eda14cbcSMatt Macy  * is required to retrieve the attribute value, and writer permission is
680eda14cbcSMatt Macy  * required to change it.
681eda14cbcSMatt Macy  *
682eda14cbcSMatt Macy  * The file permission bits of regular files and directories are
683eda14cbcSMatt Macy  * interpreted differently from the file permission bits of special
684eda14cbcSMatt Macy  * files and symbolic links.  For regular files and directories the file
685eda14cbcSMatt Macy  * permission bits define access to the file's contents, while for
686eda14cbcSMatt Macy  * device special files they define access to the device described by
687eda14cbcSMatt Macy  * the special file.  The file permissions of symbolic links are not
688eda14cbcSMatt Macy  * used in access checks.  These differences would allow users to
689eda14cbcSMatt Macy  * consume filesystem resources in a way not controllable by disk quotas
690eda14cbcSMatt Macy  * for group or world writable special files and directories.
691eda14cbcSMatt Macy  *
692eda14cbcSMatt Macy  * For this reason, extended user attributes are allowed only for
693eda14cbcSMatt Macy  * regular files and directories, and access to extended user attributes
694eda14cbcSMatt Macy  * is restricted to the owner and to users with appropriate capabilities
695eda14cbcSMatt Macy  * for directories with the sticky bit set (see the chmod(1) manual page
696eda14cbcSMatt Macy  * for an explanation of the sticky bit)." - xattr(7)
697eda14cbcSMatt Macy  *
698eda14cbcSMatt Macy  * ZFS allows extended user attributes to be disabled administratively
699eda14cbcSMatt Macy  * by setting the 'xattr=off' property on the dataset.
700eda14cbcSMatt Macy  */
701eda14cbcSMatt Macy static int
__zpl_xattr_user_list(struct inode * ip,char * list,size_t list_size,const char * name,size_t name_len)702eda14cbcSMatt Macy __zpl_xattr_user_list(struct inode *ip, char *list, size_t list_size,
703eda14cbcSMatt Macy     const char *name, size_t name_len)
704eda14cbcSMatt Macy {
705eda14cbcSMatt Macy 	return (ITOZSB(ip)->z_flags & ZSB_XATTR);
706eda14cbcSMatt Macy }
707eda14cbcSMatt Macy ZPL_XATTR_LIST_WRAPPER(zpl_xattr_user_list);
708eda14cbcSMatt Macy 
709eda14cbcSMatt Macy static int
__zpl_xattr_user_get(struct inode * ip,const char * name,void * value,size_t size)710eda14cbcSMatt Macy __zpl_xattr_user_get(struct inode *ip, const char *name,
711eda14cbcSMatt Macy     void *value, size_t size)
712eda14cbcSMatt Macy {
713eda14cbcSMatt Macy 	int error;
714eda14cbcSMatt Macy 	/* xattr_resolve_name will do this for us if this is defined */
715eda14cbcSMatt Macy #ifndef HAVE_XATTR_HANDLER_NAME
716eda14cbcSMatt Macy 	if (strcmp(name, "") == 0)
717eda14cbcSMatt Macy 		return (-EINVAL);
718eda14cbcSMatt Macy #endif
719c03c5b1cSMartin Matuska 	if (ZFS_XA_NS_PREFIX_FORBIDDEN(name))
720c03c5b1cSMartin Matuska 		return (-EINVAL);
721eda14cbcSMatt Macy 	if (!(ITOZSB(ip)->z_flags & ZSB_XATTR))
722eda14cbcSMatt Macy 		return (-EOPNOTSUPP);
723eda14cbcSMatt Macy 
724c03c5b1cSMartin Matuska 	/*
725c03c5b1cSMartin Matuska 	 * Try to look up the name with the namespace prefix first for
726c03c5b1cSMartin Matuska 	 * compatibility with xattrs from this platform.  If that fails,
727c03c5b1cSMartin Matuska 	 * try again without the namespace prefix for compatibility with
728c03c5b1cSMartin Matuska 	 * other platforms.
729c03c5b1cSMartin Matuska 	 */
730c03c5b1cSMartin Matuska 	char *xattr_name = kmem_asprintf("%s%s", XATTR_USER_PREFIX, name);
731eda14cbcSMatt Macy 	error = zpl_xattr_get(ip, xattr_name, value, size);
732eda14cbcSMatt Macy 	kmem_strfree(xattr_name);
733c03c5b1cSMartin Matuska 	if (error == -ENODATA)
734c03c5b1cSMartin Matuska 		error = zpl_xattr_get(ip, name, value, size);
735eda14cbcSMatt Macy 
736eda14cbcSMatt Macy 	return (error);
737eda14cbcSMatt Macy }
738eda14cbcSMatt Macy ZPL_XATTR_GET_WRAPPER(zpl_xattr_user_get);
739eda14cbcSMatt Macy 
740eda14cbcSMatt Macy static int
__zpl_xattr_user_set(zidmap_t * user_ns,struct inode * ip,const char * name,const void * value,size_t size,int flags)741d411c1d6SMartin Matuska __zpl_xattr_user_set(zidmap_t *user_ns,
742dbd5678dSMartin Matuska     struct inode *ip, const char *name,
743eda14cbcSMatt Macy     const void *value, size_t size, int flags)
744eda14cbcSMatt Macy {
745dbd5678dSMartin Matuska 	(void) user_ns;
746c03c5b1cSMartin Matuska 	int error = 0;
747eda14cbcSMatt Macy 	/* xattr_resolve_name will do this for us if this is defined */
748eda14cbcSMatt Macy #ifndef HAVE_XATTR_HANDLER_NAME
749eda14cbcSMatt Macy 	if (strcmp(name, "") == 0)
750eda14cbcSMatt Macy 		return (-EINVAL);
751eda14cbcSMatt Macy #endif
752c03c5b1cSMartin Matuska 	if (ZFS_XA_NS_PREFIX_FORBIDDEN(name))
753c03c5b1cSMartin Matuska 		return (-EINVAL);
754eda14cbcSMatt Macy 	if (!(ITOZSB(ip)->z_flags & ZSB_XATTR))
755eda14cbcSMatt Macy 		return (-EOPNOTSUPP);
756eda14cbcSMatt Macy 
757c03c5b1cSMartin Matuska 	/*
758c03c5b1cSMartin Matuska 	 * Remove alternate compat version of the xattr so we only set the
759c03c5b1cSMartin Matuska 	 * version specified by the zfs_xattr_compat tunable.
760c03c5b1cSMartin Matuska 	 *
761c03c5b1cSMartin Matuska 	 * The following flags must be handled correctly:
762c03c5b1cSMartin Matuska 	 *
763c03c5b1cSMartin Matuska 	 *   XATTR_CREATE: fail if xattr already exists
764c03c5b1cSMartin Matuska 	 *   XATTR_REPLACE: fail if xattr does not exist
765c03c5b1cSMartin Matuska 	 */
766c03c5b1cSMartin Matuska 	char *prefixed_name = kmem_asprintf("%s%s", XATTR_USER_PREFIX, name);
767c03c5b1cSMartin Matuska 	const char *clear_name, *set_name;
768c03c5b1cSMartin Matuska 	if (zfs_xattr_compat) {
769c03c5b1cSMartin Matuska 		clear_name = prefixed_name;
770c03c5b1cSMartin Matuska 		set_name = name;
771c03c5b1cSMartin Matuska 	} else {
772c03c5b1cSMartin Matuska 		clear_name = name;
773c03c5b1cSMartin Matuska 		set_name = prefixed_name;
774c03c5b1cSMartin Matuska 	}
775c03c5b1cSMartin Matuska 	/*
776c03c5b1cSMartin Matuska 	 * Clear the old value with the alternative name format, if it exists.
777c03c5b1cSMartin Matuska 	 */
778c03c5b1cSMartin Matuska 	error = zpl_xattr_set(ip, clear_name, NULL, 0, flags);
779c03c5b1cSMartin Matuska 	/*
780c03c5b1cSMartin Matuska 	 * XATTR_CREATE was specified and we failed to clear the xattr
781c03c5b1cSMartin Matuska 	 * because it already exists.  Stop here.
782c03c5b1cSMartin Matuska 	 */
783c03c5b1cSMartin Matuska 	if (error == -EEXIST)
784c03c5b1cSMartin Matuska 		goto out;
785c03c5b1cSMartin Matuska 	/*
786c03c5b1cSMartin Matuska 	 * If XATTR_REPLACE was specified and we succeeded to clear
787c03c5b1cSMartin Matuska 	 * an xattr, we don't need to replace anything when setting
788c03c5b1cSMartin Matuska 	 * the new value.  If we failed with -ENODATA that's fine,
789c03c5b1cSMartin Matuska 	 * there was nothing to be cleared and we can ignore the error.
790c03c5b1cSMartin Matuska 	 */
791c03c5b1cSMartin Matuska 	if (error == 0)
792c03c5b1cSMartin Matuska 		flags &= ~XATTR_REPLACE;
793c03c5b1cSMartin Matuska 	/*
794c03c5b1cSMartin Matuska 	 * Set the new value with the configured name format.
795c03c5b1cSMartin Matuska 	 */
796c03c5b1cSMartin Matuska 	error = zpl_xattr_set(ip, set_name, value, size, flags);
797c03c5b1cSMartin Matuska out:
798c03c5b1cSMartin Matuska 	kmem_strfree(prefixed_name);
799eda14cbcSMatt Macy 	return (error);
800eda14cbcSMatt Macy }
801eda14cbcSMatt Macy ZPL_XATTR_SET_WRAPPER(zpl_xattr_user_set);
802eda14cbcSMatt Macy 
803e92ffd9bSMartin Matuska static xattr_handler_t zpl_xattr_user_handler =
804eda14cbcSMatt Macy {
805eda14cbcSMatt Macy 	.prefix	= XATTR_USER_PREFIX,
806eda14cbcSMatt Macy 	.list	= zpl_xattr_user_list,
807eda14cbcSMatt Macy 	.get	= zpl_xattr_user_get,
808eda14cbcSMatt Macy 	.set	= zpl_xattr_user_set,
809eda14cbcSMatt Macy };
810eda14cbcSMatt Macy 
811eda14cbcSMatt Macy /*
812eda14cbcSMatt Macy  * Trusted extended attributes
813eda14cbcSMatt Macy  *
814eda14cbcSMatt Macy  * "Trusted extended attributes are visible and accessible only to
815eda14cbcSMatt Macy  * processes that have the CAP_SYS_ADMIN capability.  Attributes in this
816eda14cbcSMatt Macy  * class are used to implement mechanisms in user space (i.e., outside
817eda14cbcSMatt Macy  * the kernel) which keep information in extended attributes to which
818eda14cbcSMatt Macy  * ordinary processes should not have access." - xattr(7)
819eda14cbcSMatt Macy  */
820eda14cbcSMatt Macy static int
__zpl_xattr_trusted_list(struct inode * ip,char * list,size_t list_size,const char * name,size_t name_len)821eda14cbcSMatt Macy __zpl_xattr_trusted_list(struct inode *ip, char *list, size_t list_size,
822eda14cbcSMatt Macy     const char *name, size_t name_len)
823eda14cbcSMatt Macy {
824eda14cbcSMatt Macy 	return (capable(CAP_SYS_ADMIN));
825eda14cbcSMatt Macy }
826eda14cbcSMatt Macy ZPL_XATTR_LIST_WRAPPER(zpl_xattr_trusted_list);
827eda14cbcSMatt Macy 
828eda14cbcSMatt Macy static int
__zpl_xattr_trusted_get(struct inode * ip,const char * name,void * value,size_t size)829eda14cbcSMatt Macy __zpl_xattr_trusted_get(struct inode *ip, const char *name,
830eda14cbcSMatt Macy     void *value, size_t size)
831eda14cbcSMatt Macy {
832eda14cbcSMatt Macy 	char *xattr_name;
833eda14cbcSMatt Macy 	int error;
834eda14cbcSMatt Macy 
835eda14cbcSMatt Macy 	if (!capable(CAP_SYS_ADMIN))
836eda14cbcSMatt Macy 		return (-EACCES);
837eda14cbcSMatt Macy 	/* xattr_resolve_name will do this for us if this is defined */
838eda14cbcSMatt Macy #ifndef HAVE_XATTR_HANDLER_NAME
839eda14cbcSMatt Macy 	if (strcmp(name, "") == 0)
840eda14cbcSMatt Macy 		return (-EINVAL);
841eda14cbcSMatt Macy #endif
842eda14cbcSMatt Macy 	xattr_name = kmem_asprintf("%s%s", XATTR_TRUSTED_PREFIX, name);
843eda14cbcSMatt Macy 	error = zpl_xattr_get(ip, xattr_name, value, size);
844eda14cbcSMatt Macy 	kmem_strfree(xattr_name);
845eda14cbcSMatt Macy 
846eda14cbcSMatt Macy 	return (error);
847eda14cbcSMatt Macy }
848eda14cbcSMatt Macy ZPL_XATTR_GET_WRAPPER(zpl_xattr_trusted_get);
849eda14cbcSMatt Macy 
850eda14cbcSMatt Macy static int
__zpl_xattr_trusted_set(zidmap_t * user_ns,struct inode * ip,const char * name,const void * value,size_t size,int flags)851d411c1d6SMartin Matuska __zpl_xattr_trusted_set(zidmap_t *user_ns,
852dbd5678dSMartin Matuska     struct inode *ip, const char *name,
853eda14cbcSMatt Macy     const void *value, size_t size, int flags)
854eda14cbcSMatt Macy {
855dbd5678dSMartin Matuska 	(void) user_ns;
856eda14cbcSMatt Macy 	char *xattr_name;
857eda14cbcSMatt Macy 	int error;
858eda14cbcSMatt Macy 
859eda14cbcSMatt Macy 	if (!capable(CAP_SYS_ADMIN))
860eda14cbcSMatt Macy 		return (-EACCES);
861eda14cbcSMatt Macy 	/* xattr_resolve_name will do this for us if this is defined */
862eda14cbcSMatt Macy #ifndef HAVE_XATTR_HANDLER_NAME
863eda14cbcSMatt Macy 	if (strcmp(name, "") == 0)
864eda14cbcSMatt Macy 		return (-EINVAL);
865eda14cbcSMatt Macy #endif
866eda14cbcSMatt Macy 	xattr_name = kmem_asprintf("%s%s", XATTR_TRUSTED_PREFIX, name);
867eda14cbcSMatt Macy 	error = zpl_xattr_set(ip, xattr_name, value, size, flags);
868eda14cbcSMatt Macy 	kmem_strfree(xattr_name);
869eda14cbcSMatt Macy 
870eda14cbcSMatt Macy 	return (error);
871eda14cbcSMatt Macy }
872eda14cbcSMatt Macy ZPL_XATTR_SET_WRAPPER(zpl_xattr_trusted_set);
873eda14cbcSMatt Macy 
874e92ffd9bSMartin Matuska static xattr_handler_t zpl_xattr_trusted_handler = {
875eda14cbcSMatt Macy 	.prefix	= XATTR_TRUSTED_PREFIX,
876eda14cbcSMatt Macy 	.list	= zpl_xattr_trusted_list,
877eda14cbcSMatt Macy 	.get	= zpl_xattr_trusted_get,
878eda14cbcSMatt Macy 	.set	= zpl_xattr_trusted_set,
879eda14cbcSMatt Macy };
880eda14cbcSMatt Macy 
881eda14cbcSMatt Macy /*
882eda14cbcSMatt Macy  * Extended security attributes
883eda14cbcSMatt Macy  *
884eda14cbcSMatt Macy  * "The security attribute namespace is used by kernel security modules,
885eda14cbcSMatt Macy  * such as Security Enhanced Linux, and also to implement file
886eda14cbcSMatt Macy  * capabilities (see capabilities(7)).  Read and write access
887eda14cbcSMatt Macy  * permissions to security attributes depend on the policy implemented
888eda14cbcSMatt Macy  * for each security attribute by the security module.  When no security
889eda14cbcSMatt Macy  * module is loaded, all processes have read access to extended security
890eda14cbcSMatt Macy  * attributes, and write access is limited to processes that have the
891eda14cbcSMatt Macy  * CAP_SYS_ADMIN capability." - xattr(7)
892eda14cbcSMatt Macy  */
893eda14cbcSMatt Macy static int
__zpl_xattr_security_list(struct inode * ip,char * list,size_t list_size,const char * name,size_t name_len)894eda14cbcSMatt Macy __zpl_xattr_security_list(struct inode *ip, char *list, size_t list_size,
895eda14cbcSMatt Macy     const char *name, size_t name_len)
896eda14cbcSMatt Macy {
897eda14cbcSMatt Macy 	return (1);
898eda14cbcSMatt Macy }
899eda14cbcSMatt Macy ZPL_XATTR_LIST_WRAPPER(zpl_xattr_security_list);
900eda14cbcSMatt Macy 
901eda14cbcSMatt Macy static int
__zpl_xattr_security_get(struct inode * ip,const char * name,void * value,size_t size)902eda14cbcSMatt Macy __zpl_xattr_security_get(struct inode *ip, const char *name,
903eda14cbcSMatt Macy     void *value, size_t size)
904eda14cbcSMatt Macy {
905eda14cbcSMatt Macy 	char *xattr_name;
906eda14cbcSMatt Macy 	int error;
907eda14cbcSMatt Macy 	/* xattr_resolve_name will do this for us if this is defined */
908eda14cbcSMatt Macy #ifndef HAVE_XATTR_HANDLER_NAME
909eda14cbcSMatt Macy 	if (strcmp(name, "") == 0)
910eda14cbcSMatt Macy 		return (-EINVAL);
911eda14cbcSMatt Macy #endif
912eda14cbcSMatt Macy 	xattr_name = kmem_asprintf("%s%s", XATTR_SECURITY_PREFIX, name);
913eda14cbcSMatt Macy 	error = zpl_xattr_get(ip, xattr_name, value, size);
914eda14cbcSMatt Macy 	kmem_strfree(xattr_name);
915eda14cbcSMatt Macy 
916eda14cbcSMatt Macy 	return (error);
917eda14cbcSMatt Macy }
918eda14cbcSMatt Macy ZPL_XATTR_GET_WRAPPER(zpl_xattr_security_get);
919eda14cbcSMatt Macy 
920eda14cbcSMatt Macy static int
__zpl_xattr_security_set(zidmap_t * user_ns,struct inode * ip,const char * name,const void * value,size_t size,int flags)921d411c1d6SMartin Matuska __zpl_xattr_security_set(zidmap_t *user_ns,
922dbd5678dSMartin Matuska     struct inode *ip, const char *name,
923eda14cbcSMatt Macy     const void *value, size_t size, int flags)
924eda14cbcSMatt Macy {
925dbd5678dSMartin Matuska 	(void) user_ns;
926eda14cbcSMatt Macy 	char *xattr_name;
927eda14cbcSMatt Macy 	int error;
928eda14cbcSMatt Macy 	/* xattr_resolve_name will do this for us if this is defined */
929eda14cbcSMatt Macy #ifndef HAVE_XATTR_HANDLER_NAME
930eda14cbcSMatt Macy 	if (strcmp(name, "") == 0)
931eda14cbcSMatt Macy 		return (-EINVAL);
932eda14cbcSMatt Macy #endif
933eda14cbcSMatt Macy 	xattr_name = kmem_asprintf("%s%s", XATTR_SECURITY_PREFIX, name);
934eda14cbcSMatt Macy 	error = zpl_xattr_set(ip, xattr_name, value, size, flags);
935eda14cbcSMatt Macy 	kmem_strfree(xattr_name);
936eda14cbcSMatt Macy 
937eda14cbcSMatt Macy 	return (error);
938eda14cbcSMatt Macy }
939eda14cbcSMatt Macy ZPL_XATTR_SET_WRAPPER(zpl_xattr_security_set);
940eda14cbcSMatt Macy 
941eda14cbcSMatt Macy static int
zpl_xattr_security_init_impl(struct inode * ip,const struct xattr * xattrs,void * fs_info)942eda14cbcSMatt Macy zpl_xattr_security_init_impl(struct inode *ip, const struct xattr *xattrs,
943eda14cbcSMatt Macy     void *fs_info)
944eda14cbcSMatt Macy {
945eda14cbcSMatt Macy 	const struct xattr *xattr;
946eda14cbcSMatt Macy 	int error = 0;
947eda14cbcSMatt Macy 
948eda14cbcSMatt Macy 	for (xattr = xattrs; xattr->name != NULL; xattr++) {
949dbd5678dSMartin Matuska 		error = __zpl_xattr_security_set(NULL, ip,
950eda14cbcSMatt Macy 		    xattr->name, xattr->value, xattr->value_len, 0);
951eda14cbcSMatt Macy 
952eda14cbcSMatt Macy 		if (error < 0)
953eda14cbcSMatt Macy 			break;
954eda14cbcSMatt Macy 	}
955eda14cbcSMatt Macy 
956eda14cbcSMatt Macy 	return (error);
957eda14cbcSMatt Macy }
958eda14cbcSMatt Macy 
959eda14cbcSMatt Macy int
zpl_xattr_security_init(struct inode * ip,struct inode * dip,const struct qstr * qstr)960eda14cbcSMatt Macy zpl_xattr_security_init(struct inode *ip, struct inode *dip,
961eda14cbcSMatt Macy     const struct qstr *qstr)
962eda14cbcSMatt Macy {
963eda14cbcSMatt Macy 	return security_inode_init_security(ip, dip, qstr,
964eda14cbcSMatt Macy 	    &zpl_xattr_security_init_impl, NULL);
965eda14cbcSMatt Macy }
966eda14cbcSMatt Macy 
967eda14cbcSMatt Macy /*
968eda14cbcSMatt Macy  * Security xattr namespace handlers.
969eda14cbcSMatt Macy  */
970e92ffd9bSMartin Matuska static xattr_handler_t zpl_xattr_security_handler = {
971eda14cbcSMatt Macy 	.prefix	= XATTR_SECURITY_PREFIX,
972eda14cbcSMatt Macy 	.list	= zpl_xattr_security_list,
973eda14cbcSMatt Macy 	.get	= zpl_xattr_security_get,
974eda14cbcSMatt Macy 	.set	= zpl_xattr_security_set,
975eda14cbcSMatt Macy };
976eda14cbcSMatt Macy 
977eda14cbcSMatt Macy /*
978eda14cbcSMatt Macy  * Extended system attributes
979eda14cbcSMatt Macy  *
980eda14cbcSMatt Macy  * "Extended system attributes are used by the kernel to store system
981eda14cbcSMatt Macy  * objects such as Access Control Lists.  Read and write access permissions
982eda14cbcSMatt Macy  * to system attributes depend on the policy implemented for each system
983eda14cbcSMatt Macy  * attribute implemented by filesystems in the kernel." - xattr(7)
984eda14cbcSMatt Macy  */
985eda14cbcSMatt Macy #ifdef CONFIG_FS_POSIX_ACL
98616038816SMartin Matuska static int
zpl_set_acl_impl(struct inode * ip,struct posix_acl * acl,int type)98716038816SMartin Matuska zpl_set_acl_impl(struct inode *ip, struct posix_acl *acl, int type)
988eda14cbcSMatt Macy {
989eda14cbcSMatt Macy 	char *name, *value = NULL;
990eda14cbcSMatt Macy 	int error = 0;
991eda14cbcSMatt Macy 	size_t size = 0;
992eda14cbcSMatt Macy 
993eda14cbcSMatt Macy 	if (S_ISLNK(ip->i_mode))
994eda14cbcSMatt Macy 		return (-EOPNOTSUPP);
995eda14cbcSMatt Macy 
996eda14cbcSMatt Macy 	switch (type) {
997eda14cbcSMatt Macy 	case ACL_TYPE_ACCESS:
998eda14cbcSMatt Macy 		name = XATTR_NAME_POSIX_ACL_ACCESS;
999eda14cbcSMatt Macy 		if (acl) {
1000eda14cbcSMatt Macy 			umode_t mode = ip->i_mode;
1001eda14cbcSMatt Macy 			error = posix_acl_equiv_mode(acl, &mode);
1002eda14cbcSMatt Macy 			if (error < 0) {
1003eda14cbcSMatt Macy 				return (error);
1004eda14cbcSMatt Macy 			} else {
1005eda14cbcSMatt Macy 				/*
1006eda14cbcSMatt Macy 				 * The mode bits will have been set by
1007eda14cbcSMatt Macy 				 * ->zfs_setattr()->zfs_acl_chmod_setattr()
1008eda14cbcSMatt Macy 				 * using the ZFS ACL conversion.  If they
1009eda14cbcSMatt Macy 				 * differ from the Posix ACL conversion dirty
1010eda14cbcSMatt Macy 				 * the inode to write the Posix mode bits.
1011eda14cbcSMatt Macy 				 */
1012eda14cbcSMatt Macy 				if (ip->i_mode != mode) {
1013a0b956f5SMartin Matuska 					ip->i_mode = ITOZ(ip)->z_mode = mode;
1014abcdc1b9SMartin Matuska 					zpl_inode_set_ctime_to_ts(ip,
1015abcdc1b9SMartin Matuska 					    current_time(ip));
1016eda14cbcSMatt Macy 					zfs_mark_inode_dirty(ip);
1017eda14cbcSMatt Macy 				}
1018eda14cbcSMatt Macy 
1019eda14cbcSMatt Macy 				if (error == 0)
1020eda14cbcSMatt Macy 					acl = NULL;
1021eda14cbcSMatt Macy 			}
1022eda14cbcSMatt Macy 		}
1023eda14cbcSMatt Macy 		break;
1024eda14cbcSMatt Macy 
1025eda14cbcSMatt Macy 	case ACL_TYPE_DEFAULT:
1026eda14cbcSMatt Macy 		name = XATTR_NAME_POSIX_ACL_DEFAULT;
1027eda14cbcSMatt Macy 		if (!S_ISDIR(ip->i_mode))
1028eda14cbcSMatt Macy 			return (acl ? -EACCES : 0);
1029eda14cbcSMatt Macy 		break;
1030eda14cbcSMatt Macy 
1031eda14cbcSMatt Macy 	default:
1032eda14cbcSMatt Macy 		return (-EINVAL);
1033eda14cbcSMatt Macy 	}
1034eda14cbcSMatt Macy 
1035eda14cbcSMatt Macy 	if (acl) {
1036eda14cbcSMatt Macy 		size = posix_acl_xattr_size(acl->a_count);
1037eda14cbcSMatt Macy 		value = kmem_alloc(size, KM_SLEEP);
1038eda14cbcSMatt Macy 
1039eda14cbcSMatt Macy 		error = zpl_acl_to_xattr(acl, value, size);
1040eda14cbcSMatt Macy 		if (error < 0) {
1041eda14cbcSMatt Macy 			kmem_free(value, size);
1042eda14cbcSMatt Macy 			return (error);
1043eda14cbcSMatt Macy 		}
1044eda14cbcSMatt Macy 	}
1045eda14cbcSMatt Macy 
1046eda14cbcSMatt Macy 	error = zpl_xattr_set(ip, name, value, size, 0);
1047eda14cbcSMatt Macy 	if (value)
1048eda14cbcSMatt Macy 		kmem_free(value, size);
1049eda14cbcSMatt Macy 
1050eda14cbcSMatt Macy 	if (!error) {
1051eda14cbcSMatt Macy 		if (acl)
1052eda14cbcSMatt Macy 			zpl_set_cached_acl(ip, type, acl);
1053eda14cbcSMatt Macy 		else
1054eda14cbcSMatt Macy 			zpl_forget_cached_acl(ip, type);
1055eda14cbcSMatt Macy 	}
1056eda14cbcSMatt Macy 
1057eda14cbcSMatt Macy 	return (error);
1058eda14cbcSMatt Macy }
1059eda14cbcSMatt Macy 
106016038816SMartin Matuska #ifdef HAVE_SET_ACL
106116038816SMartin Matuska int
106216038816SMartin Matuska #ifdef HAVE_SET_ACL_USERNS
zpl_set_acl(struct user_namespace * userns,struct inode * ip,struct posix_acl * acl,int type)106316038816SMartin Matuska zpl_set_acl(struct user_namespace *userns, struct inode *ip,
106416038816SMartin Matuska     struct posix_acl *acl, int type)
1065d411c1d6SMartin Matuska #elif defined(HAVE_SET_ACL_IDMAP_DENTRY)
1066d411c1d6SMartin Matuska zpl_set_acl(struct mnt_idmap *userns, struct dentry *dentry,
1067d411c1d6SMartin Matuska     struct posix_acl *acl, int type)
106815f0b8c3SMartin Matuska #elif defined(HAVE_SET_ACL_USERNS_DENTRY_ARG2)
106915f0b8c3SMartin Matuska zpl_set_acl(struct user_namespace *userns, struct dentry *dentry,
107015f0b8c3SMartin Matuska     struct posix_acl *acl, int type)
107116038816SMartin Matuska #else
107216038816SMartin Matuska zpl_set_acl(struct inode *ip, struct posix_acl *acl, int type)
107316038816SMartin Matuska #endif /* HAVE_SET_ACL_USERNS */
107416038816SMartin Matuska {
107515f0b8c3SMartin Matuska #ifdef HAVE_SET_ACL_USERNS_DENTRY_ARG2
107615f0b8c3SMartin Matuska 	return (zpl_set_acl_impl(d_inode(dentry), acl, type));
1077d411c1d6SMartin Matuska #elif defined(HAVE_SET_ACL_IDMAP_DENTRY)
1078d411c1d6SMartin Matuska 	return (zpl_set_acl_impl(d_inode(dentry), acl, type));
107915f0b8c3SMartin Matuska #else
108016038816SMartin Matuska 	return (zpl_set_acl_impl(ip, acl, type));
108115f0b8c3SMartin Matuska #endif /* HAVE_SET_ACL_USERNS_DENTRY_ARG2 */
108216038816SMartin Matuska }
108316038816SMartin Matuska #endif /* HAVE_SET_ACL */
108416038816SMartin Matuska 
108553b70c86SMartin Matuska static struct posix_acl *
zpl_get_acl_impl(struct inode * ip,int type)108653b70c86SMartin Matuska zpl_get_acl_impl(struct inode *ip, int type)
1087eda14cbcSMatt Macy {
1088eda14cbcSMatt Macy 	struct posix_acl *acl;
1089eda14cbcSMatt Macy 	void *value = NULL;
1090eda14cbcSMatt Macy 	char *name;
1091eda14cbcSMatt Macy 
1092eda14cbcSMatt Macy 	/*
1093eda14cbcSMatt Macy 	 * As of Linux 3.14, the kernel get_acl will check this for us.
1094eda14cbcSMatt Macy 	 * Also as of Linux 4.7, comparing against ACL_NOT_CACHED is wrong
1095eda14cbcSMatt Macy 	 * as the kernel get_acl will set it to temporary sentinel value.
1096eda14cbcSMatt Macy 	 */
1097eda14cbcSMatt Macy #ifndef HAVE_KERNEL_GET_ACL_HANDLE_CACHE
1098eda14cbcSMatt Macy 	acl = get_cached_acl(ip, type);
1099eda14cbcSMatt Macy 	if (acl != ACL_NOT_CACHED)
1100eda14cbcSMatt Macy 		return (acl);
1101eda14cbcSMatt Macy #endif
1102eda14cbcSMatt Macy 
1103eda14cbcSMatt Macy 	switch (type) {
1104eda14cbcSMatt Macy 	case ACL_TYPE_ACCESS:
1105eda14cbcSMatt Macy 		name = XATTR_NAME_POSIX_ACL_ACCESS;
1106eda14cbcSMatt Macy 		break;
1107eda14cbcSMatt Macy 	case ACL_TYPE_DEFAULT:
1108eda14cbcSMatt Macy 		name = XATTR_NAME_POSIX_ACL_DEFAULT;
1109eda14cbcSMatt Macy 		break;
1110eda14cbcSMatt Macy 	default:
1111eda14cbcSMatt Macy 		return (ERR_PTR(-EINVAL));
1112eda14cbcSMatt Macy 	}
1113eda14cbcSMatt Macy 
111453b70c86SMartin Matuska 	int size = zpl_xattr_get(ip, name, NULL, 0);
1115eda14cbcSMatt Macy 	if (size > 0) {
1116eda14cbcSMatt Macy 		value = kmem_alloc(size, KM_SLEEP);
1117eda14cbcSMatt Macy 		size = zpl_xattr_get(ip, name, value, size);
1118eda14cbcSMatt Macy 	}
1119eda14cbcSMatt Macy 
1120eda14cbcSMatt Macy 	if (size > 0) {
1121eda14cbcSMatt Macy 		acl = zpl_acl_from_xattr(value, size);
1122eda14cbcSMatt Macy 	} else if (size == -ENODATA || size == -ENOSYS) {
1123eda14cbcSMatt Macy 		acl = NULL;
1124eda14cbcSMatt Macy 	} else {
1125eda14cbcSMatt Macy 		acl = ERR_PTR(-EIO);
1126eda14cbcSMatt Macy 	}
1127eda14cbcSMatt Macy 
1128eda14cbcSMatt Macy 	if (size > 0)
1129eda14cbcSMatt Macy 		kmem_free(value, size);
1130eda14cbcSMatt Macy 
1131eda14cbcSMatt Macy 	/* As of Linux 4.7, the kernel get_acl will set this for us */
1132eda14cbcSMatt Macy #ifndef HAVE_KERNEL_GET_ACL_HANDLE_CACHE
1133eda14cbcSMatt Macy 	if (!IS_ERR(acl))
1134eda14cbcSMatt Macy 		zpl_set_cached_acl(ip, type, acl);
1135eda14cbcSMatt Macy #endif
1136eda14cbcSMatt Macy 
1137eda14cbcSMatt Macy 	return (acl);
1138eda14cbcSMatt Macy }
1139eda14cbcSMatt Macy 
114015f0b8c3SMartin Matuska #if defined(HAVE_GET_ACL_RCU) || defined(HAVE_GET_INODE_ACL)
114153b70c86SMartin Matuska struct posix_acl *
zpl_get_acl(struct inode * ip,int type,bool rcu)114253b70c86SMartin Matuska zpl_get_acl(struct inode *ip, int type, bool rcu)
114353b70c86SMartin Matuska {
114453b70c86SMartin Matuska 	if (rcu)
114553b70c86SMartin Matuska 		return (ERR_PTR(-ECHILD));
114653b70c86SMartin Matuska 
114753b70c86SMartin Matuska 	return (zpl_get_acl_impl(ip, type));
114853b70c86SMartin Matuska }
114953b70c86SMartin Matuska #elif defined(HAVE_GET_ACL)
115053b70c86SMartin Matuska struct posix_acl *
zpl_get_acl(struct inode * ip,int type)115153b70c86SMartin Matuska zpl_get_acl(struct inode *ip, int type)
115253b70c86SMartin Matuska {
115353b70c86SMartin Matuska 	return (zpl_get_acl_impl(ip, type));
115453b70c86SMartin Matuska }
115553b70c86SMartin Matuska #else
115653b70c86SMartin Matuska #error "Unsupported iops->get_acl() implementation"
115753b70c86SMartin Matuska #endif /* HAVE_GET_ACL_RCU */
115853b70c86SMartin Matuska 
1159eda14cbcSMatt Macy int
zpl_init_acl(struct inode * ip,struct inode * dir)1160eda14cbcSMatt Macy zpl_init_acl(struct inode *ip, struct inode *dir)
1161eda14cbcSMatt Macy {
1162eda14cbcSMatt Macy 	struct posix_acl *acl = NULL;
1163eda14cbcSMatt Macy 	int error = 0;
1164eda14cbcSMatt Macy 
11652c48331dSMatt Macy 	if (ITOZSB(ip)->z_acl_type != ZFS_ACLTYPE_POSIX)
1166eda14cbcSMatt Macy 		return (0);
1167eda14cbcSMatt Macy 
1168eda14cbcSMatt Macy 	if (!S_ISLNK(ip->i_mode)) {
116953b70c86SMartin Matuska 		acl = zpl_get_acl_impl(dir, ACL_TYPE_DEFAULT);
1170eda14cbcSMatt Macy 		if (IS_ERR(acl))
1171eda14cbcSMatt Macy 			return (PTR_ERR(acl));
1172eda14cbcSMatt Macy 		if (!acl) {
1173a0b956f5SMartin Matuska 			ITOZ(ip)->z_mode = (ip->i_mode &= ~current_umask());
1174abcdc1b9SMartin Matuska 			zpl_inode_set_ctime_to_ts(ip, current_time(ip));
1175eda14cbcSMatt Macy 			zfs_mark_inode_dirty(ip);
1176eda14cbcSMatt Macy 			return (0);
1177eda14cbcSMatt Macy 		}
1178eda14cbcSMatt Macy 	}
1179eda14cbcSMatt Macy 
1180eda14cbcSMatt Macy 	if (acl) {
1181eda14cbcSMatt Macy 		umode_t mode;
1182eda14cbcSMatt Macy 
1183eda14cbcSMatt Macy 		if (S_ISDIR(ip->i_mode)) {
118416038816SMartin Matuska 			error = zpl_set_acl_impl(ip, acl, ACL_TYPE_DEFAULT);
1185eda14cbcSMatt Macy 			if (error)
1186eda14cbcSMatt Macy 				goto out;
1187eda14cbcSMatt Macy 		}
1188eda14cbcSMatt Macy 
1189eda14cbcSMatt Macy 		mode = ip->i_mode;
1190eda14cbcSMatt Macy 		error = __posix_acl_create(&acl, GFP_KERNEL, &mode);
1191eda14cbcSMatt Macy 		if (error >= 0) {
1192a0b956f5SMartin Matuska 			ip->i_mode = ITOZ(ip)->z_mode = mode;
1193eda14cbcSMatt Macy 			zfs_mark_inode_dirty(ip);
119416038816SMartin Matuska 			if (error > 0) {
119516038816SMartin Matuska 				error = zpl_set_acl_impl(ip, acl,
119616038816SMartin Matuska 				    ACL_TYPE_ACCESS);
119716038816SMartin Matuska 			}
1198eda14cbcSMatt Macy 		}
1199eda14cbcSMatt Macy 	}
1200eda14cbcSMatt Macy out:
1201eda14cbcSMatt Macy 	zpl_posix_acl_release(acl);
1202eda14cbcSMatt Macy 
1203eda14cbcSMatt Macy 	return (error);
1204eda14cbcSMatt Macy }
1205eda14cbcSMatt Macy 
1206eda14cbcSMatt Macy int
zpl_chmod_acl(struct inode * ip)1207eda14cbcSMatt Macy zpl_chmod_acl(struct inode *ip)
1208eda14cbcSMatt Macy {
1209eda14cbcSMatt Macy 	struct posix_acl *acl;
1210eda14cbcSMatt Macy 	int error;
1211eda14cbcSMatt Macy 
12122c48331dSMatt Macy 	if (ITOZSB(ip)->z_acl_type != ZFS_ACLTYPE_POSIX)
1213eda14cbcSMatt Macy 		return (0);
1214eda14cbcSMatt Macy 
1215eda14cbcSMatt Macy 	if (S_ISLNK(ip->i_mode))
1216eda14cbcSMatt Macy 		return (-EOPNOTSUPP);
1217eda14cbcSMatt Macy 
121853b70c86SMartin Matuska 	acl = zpl_get_acl_impl(ip, ACL_TYPE_ACCESS);
1219eda14cbcSMatt Macy 	if (IS_ERR(acl) || !acl)
1220eda14cbcSMatt Macy 		return (PTR_ERR(acl));
1221eda14cbcSMatt Macy 
1222eda14cbcSMatt Macy 	error = __posix_acl_chmod(&acl, GFP_KERNEL, ip->i_mode);
1223eda14cbcSMatt Macy 	if (!error)
122416038816SMartin Matuska 		error = zpl_set_acl_impl(ip, acl, ACL_TYPE_ACCESS);
1225eda14cbcSMatt Macy 
1226eda14cbcSMatt Macy 	zpl_posix_acl_release(acl);
1227eda14cbcSMatt Macy 
1228eda14cbcSMatt Macy 	return (error);
1229eda14cbcSMatt Macy }
1230eda14cbcSMatt Macy 
1231eda14cbcSMatt Macy static int
__zpl_xattr_acl_list_access(struct inode * ip,char * list,size_t list_size,const char * name,size_t name_len)1232eda14cbcSMatt Macy __zpl_xattr_acl_list_access(struct inode *ip, char *list, size_t list_size,
1233eda14cbcSMatt Macy     const char *name, size_t name_len)
1234eda14cbcSMatt Macy {
1235eda14cbcSMatt Macy 	char *xattr_name = XATTR_NAME_POSIX_ACL_ACCESS;
1236eda14cbcSMatt Macy 	size_t xattr_size = sizeof (XATTR_NAME_POSIX_ACL_ACCESS);
1237eda14cbcSMatt Macy 
12382c48331dSMatt Macy 	if (ITOZSB(ip)->z_acl_type != ZFS_ACLTYPE_POSIX)
1239eda14cbcSMatt Macy 		return (0);
1240eda14cbcSMatt Macy 
1241eda14cbcSMatt Macy 	if (list && xattr_size <= list_size)
1242eda14cbcSMatt Macy 		memcpy(list, xattr_name, xattr_size);
1243eda14cbcSMatt Macy 
1244eda14cbcSMatt Macy 	return (xattr_size);
1245eda14cbcSMatt Macy }
1246eda14cbcSMatt Macy ZPL_XATTR_LIST_WRAPPER(zpl_xattr_acl_list_access);
1247eda14cbcSMatt Macy 
1248eda14cbcSMatt Macy static int
__zpl_xattr_acl_list_default(struct inode * ip,char * list,size_t list_size,const char * name,size_t name_len)1249eda14cbcSMatt Macy __zpl_xattr_acl_list_default(struct inode *ip, char *list, size_t list_size,
1250eda14cbcSMatt Macy     const char *name, size_t name_len)
1251eda14cbcSMatt Macy {
1252eda14cbcSMatt Macy 	char *xattr_name = XATTR_NAME_POSIX_ACL_DEFAULT;
1253eda14cbcSMatt Macy 	size_t xattr_size = sizeof (XATTR_NAME_POSIX_ACL_DEFAULT);
1254eda14cbcSMatt Macy 
12552c48331dSMatt Macy 	if (ITOZSB(ip)->z_acl_type != ZFS_ACLTYPE_POSIX)
1256eda14cbcSMatt Macy 		return (0);
1257eda14cbcSMatt Macy 
1258eda14cbcSMatt Macy 	if (list && xattr_size <= list_size)
1259eda14cbcSMatt Macy 		memcpy(list, xattr_name, xattr_size);
1260eda14cbcSMatt Macy 
1261eda14cbcSMatt Macy 	return (xattr_size);
1262eda14cbcSMatt Macy }
1263eda14cbcSMatt Macy ZPL_XATTR_LIST_WRAPPER(zpl_xattr_acl_list_default);
1264eda14cbcSMatt Macy 
1265eda14cbcSMatt Macy static int
__zpl_xattr_acl_get_access(struct inode * ip,const char * name,void * buffer,size_t size)1266eda14cbcSMatt Macy __zpl_xattr_acl_get_access(struct inode *ip, const char *name,
1267eda14cbcSMatt Macy     void *buffer, size_t size)
1268eda14cbcSMatt Macy {
1269eda14cbcSMatt Macy 	struct posix_acl *acl;
1270eda14cbcSMatt Macy 	int type = ACL_TYPE_ACCESS;
1271eda14cbcSMatt Macy 	int error;
1272eda14cbcSMatt Macy 	/* xattr_resolve_name will do this for us if this is defined */
1273eda14cbcSMatt Macy #ifndef HAVE_XATTR_HANDLER_NAME
1274eda14cbcSMatt Macy 	if (strcmp(name, "") != 0)
1275eda14cbcSMatt Macy 		return (-EINVAL);
1276eda14cbcSMatt Macy #endif
12772c48331dSMatt Macy 	if (ITOZSB(ip)->z_acl_type != ZFS_ACLTYPE_POSIX)
1278eda14cbcSMatt Macy 		return (-EOPNOTSUPP);
1279eda14cbcSMatt Macy 
128053b70c86SMartin Matuska 	acl = zpl_get_acl_impl(ip, type);
1281eda14cbcSMatt Macy 	if (IS_ERR(acl))
1282eda14cbcSMatt Macy 		return (PTR_ERR(acl));
1283eda14cbcSMatt Macy 	if (acl == NULL)
1284eda14cbcSMatt Macy 		return (-ENODATA);
1285eda14cbcSMatt Macy 
1286eda14cbcSMatt Macy 	error = zpl_acl_to_xattr(acl, buffer, size);
1287eda14cbcSMatt Macy 	zpl_posix_acl_release(acl);
1288eda14cbcSMatt Macy 
1289eda14cbcSMatt Macy 	return (error);
1290eda14cbcSMatt Macy }
1291eda14cbcSMatt Macy ZPL_XATTR_GET_WRAPPER(zpl_xattr_acl_get_access);
1292eda14cbcSMatt Macy 
1293eda14cbcSMatt Macy static int
__zpl_xattr_acl_get_default(struct inode * ip,const char * name,void * buffer,size_t size)1294eda14cbcSMatt Macy __zpl_xattr_acl_get_default(struct inode *ip, const char *name,
1295eda14cbcSMatt Macy     void *buffer, size_t size)
1296eda14cbcSMatt Macy {
1297eda14cbcSMatt Macy 	struct posix_acl *acl;
1298eda14cbcSMatt Macy 	int type = ACL_TYPE_DEFAULT;
1299eda14cbcSMatt Macy 	int error;
1300eda14cbcSMatt Macy 	/* xattr_resolve_name will do this for us if this is defined */
1301eda14cbcSMatt Macy #ifndef HAVE_XATTR_HANDLER_NAME
1302eda14cbcSMatt Macy 	if (strcmp(name, "") != 0)
1303eda14cbcSMatt Macy 		return (-EINVAL);
1304eda14cbcSMatt Macy #endif
13052c48331dSMatt Macy 	if (ITOZSB(ip)->z_acl_type != ZFS_ACLTYPE_POSIX)
1306eda14cbcSMatt Macy 		return (-EOPNOTSUPP);
1307eda14cbcSMatt Macy 
130853b70c86SMartin Matuska 	acl = zpl_get_acl_impl(ip, type);
1309eda14cbcSMatt Macy 	if (IS_ERR(acl))
1310eda14cbcSMatt Macy 		return (PTR_ERR(acl));
1311eda14cbcSMatt Macy 	if (acl == NULL)
1312eda14cbcSMatt Macy 		return (-ENODATA);
1313eda14cbcSMatt Macy 
1314eda14cbcSMatt Macy 	error = zpl_acl_to_xattr(acl, buffer, size);
1315eda14cbcSMatt Macy 	zpl_posix_acl_release(acl);
1316eda14cbcSMatt Macy 
1317eda14cbcSMatt Macy 	return (error);
1318eda14cbcSMatt Macy }
1319eda14cbcSMatt Macy ZPL_XATTR_GET_WRAPPER(zpl_xattr_acl_get_default);
1320eda14cbcSMatt Macy 
1321eda14cbcSMatt Macy static int
__zpl_xattr_acl_set_access(zidmap_t * mnt_ns,struct inode * ip,const char * name,const void * value,size_t size,int flags)1322d411c1d6SMartin Matuska __zpl_xattr_acl_set_access(zidmap_t *mnt_ns,
1323dbd5678dSMartin Matuska     struct inode *ip, const char *name,
1324eda14cbcSMatt Macy     const void *value, size_t size, int flags)
1325eda14cbcSMatt Macy {
1326eda14cbcSMatt Macy 	struct posix_acl *acl;
1327eda14cbcSMatt Macy 	int type = ACL_TYPE_ACCESS;
1328eda14cbcSMatt Macy 	int error = 0;
1329eda14cbcSMatt Macy 	/* xattr_resolve_name will do this for us if this is defined */
1330eda14cbcSMatt Macy #ifndef HAVE_XATTR_HANDLER_NAME
1331eda14cbcSMatt Macy 	if (strcmp(name, "") != 0)
1332eda14cbcSMatt Macy 		return (-EINVAL);
1333eda14cbcSMatt Macy #endif
13342c48331dSMatt Macy 	if (ITOZSB(ip)->z_acl_type != ZFS_ACLTYPE_POSIX)
1335eda14cbcSMatt Macy 		return (-EOPNOTSUPP);
1336eda14cbcSMatt Macy 
1337d411c1d6SMartin Matuska #if defined(HAVE_XATTR_SET_USERNS) || defined(HAVE_XATTR_SET_IDMAP)
1338dbd5678dSMartin Matuska 	if (!zpl_inode_owner_or_capable(mnt_ns, ip))
1339dbd5678dSMartin Matuska 		return (-EPERM);
1340dbd5678dSMartin Matuska #else
1341dbd5678dSMartin Matuska 	(void) mnt_ns;
1342d411c1d6SMartin Matuska 	if (!zpl_inode_owner_or_capable(zfs_init_idmap, ip))
1343eda14cbcSMatt Macy 		return (-EPERM);
1344dbd5678dSMartin Matuska #endif
1345eda14cbcSMatt Macy 
1346eda14cbcSMatt Macy 	if (value) {
1347eda14cbcSMatt Macy 		acl = zpl_acl_from_xattr(value, size);
1348eda14cbcSMatt Macy 		if (IS_ERR(acl))
1349eda14cbcSMatt Macy 			return (PTR_ERR(acl));
1350eda14cbcSMatt Macy 		else if (acl) {
1351eda14cbcSMatt Macy 			error = zpl_posix_acl_valid(ip, acl);
1352eda14cbcSMatt Macy 			if (error) {
1353eda14cbcSMatt Macy 				zpl_posix_acl_release(acl);
1354eda14cbcSMatt Macy 				return (error);
1355eda14cbcSMatt Macy 			}
1356eda14cbcSMatt Macy 		}
1357eda14cbcSMatt Macy 	} else {
1358eda14cbcSMatt Macy 		acl = NULL;
1359eda14cbcSMatt Macy 	}
136016038816SMartin Matuska 	error = zpl_set_acl_impl(ip, acl, type);
1361eda14cbcSMatt Macy 	zpl_posix_acl_release(acl);
1362eda14cbcSMatt Macy 
1363eda14cbcSMatt Macy 	return (error);
1364eda14cbcSMatt Macy }
1365eda14cbcSMatt Macy ZPL_XATTR_SET_WRAPPER(zpl_xattr_acl_set_access);
1366eda14cbcSMatt Macy 
1367eda14cbcSMatt Macy static int
__zpl_xattr_acl_set_default(zidmap_t * mnt_ns,struct inode * ip,const char * name,const void * value,size_t size,int flags)1368d411c1d6SMartin Matuska __zpl_xattr_acl_set_default(zidmap_t *mnt_ns,
1369dbd5678dSMartin Matuska     struct inode *ip, const char *name,
1370eda14cbcSMatt Macy     const void *value, size_t size, int flags)
1371eda14cbcSMatt Macy {
1372eda14cbcSMatt Macy 	struct posix_acl *acl;
1373eda14cbcSMatt Macy 	int type = ACL_TYPE_DEFAULT;
1374eda14cbcSMatt Macy 	int error = 0;
1375eda14cbcSMatt Macy 	/* xattr_resolve_name will do this for us if this is defined */
1376eda14cbcSMatt Macy #ifndef HAVE_XATTR_HANDLER_NAME
1377eda14cbcSMatt Macy 	if (strcmp(name, "") != 0)
1378eda14cbcSMatt Macy 		return (-EINVAL);
1379eda14cbcSMatt Macy #endif
13802c48331dSMatt Macy 	if (ITOZSB(ip)->z_acl_type != ZFS_ACLTYPE_POSIX)
1381eda14cbcSMatt Macy 		return (-EOPNOTSUPP);
1382eda14cbcSMatt Macy 
1383d411c1d6SMartin Matuska #if defined(HAVE_XATTR_SET_USERNS) || defined(HAVE_XATTR_SET_IDMAP)
1384dbd5678dSMartin Matuska 	if (!zpl_inode_owner_or_capable(mnt_ns, ip))
1385dbd5678dSMartin Matuska 		return (-EPERM);
1386dbd5678dSMartin Matuska #else
1387dbd5678dSMartin Matuska 	(void) mnt_ns;
1388d411c1d6SMartin Matuska 	if (!zpl_inode_owner_or_capable(zfs_init_idmap, ip))
1389eda14cbcSMatt Macy 		return (-EPERM);
1390dbd5678dSMartin Matuska #endif
1391eda14cbcSMatt Macy 
1392eda14cbcSMatt Macy 	if (value) {
1393eda14cbcSMatt Macy 		acl = zpl_acl_from_xattr(value, size);
1394eda14cbcSMatt Macy 		if (IS_ERR(acl))
1395eda14cbcSMatt Macy 			return (PTR_ERR(acl));
1396eda14cbcSMatt Macy 		else if (acl) {
1397eda14cbcSMatt Macy 			error = zpl_posix_acl_valid(ip, acl);
1398eda14cbcSMatt Macy 			if (error) {
1399eda14cbcSMatt Macy 				zpl_posix_acl_release(acl);
1400eda14cbcSMatt Macy 				return (error);
1401eda14cbcSMatt Macy 			}
1402eda14cbcSMatt Macy 		}
1403eda14cbcSMatt Macy 	} else {
1404eda14cbcSMatt Macy 		acl = NULL;
1405eda14cbcSMatt Macy 	}
1406eda14cbcSMatt Macy 
140716038816SMartin Matuska 	error = zpl_set_acl_impl(ip, acl, type);
1408eda14cbcSMatt Macy 	zpl_posix_acl_release(acl);
1409eda14cbcSMatt Macy 
1410eda14cbcSMatt Macy 	return (error);
1411eda14cbcSMatt Macy }
1412eda14cbcSMatt Macy ZPL_XATTR_SET_WRAPPER(zpl_xattr_acl_set_default);
1413eda14cbcSMatt Macy 
1414eda14cbcSMatt Macy /*
1415eda14cbcSMatt Macy  * ACL access xattr namespace handlers.
1416eda14cbcSMatt Macy  *
1417eda14cbcSMatt Macy  * Use .name instead of .prefix when available. xattr_resolve_name will match
1418eda14cbcSMatt Macy  * whole name and reject anything that has .name only as prefix.
1419eda14cbcSMatt Macy  */
1420e92ffd9bSMartin Matuska static xattr_handler_t zpl_xattr_acl_access_handler = {
1421eda14cbcSMatt Macy #ifdef HAVE_XATTR_HANDLER_NAME
1422eda14cbcSMatt Macy 	.name	= XATTR_NAME_POSIX_ACL_ACCESS,
1423eda14cbcSMatt Macy #else
1424eda14cbcSMatt Macy 	.prefix	= XATTR_NAME_POSIX_ACL_ACCESS,
1425eda14cbcSMatt Macy #endif
1426eda14cbcSMatt Macy 	.list	= zpl_xattr_acl_list_access,
1427eda14cbcSMatt Macy 	.get	= zpl_xattr_acl_get_access,
1428eda14cbcSMatt Macy 	.set	= zpl_xattr_acl_set_access,
1429eda14cbcSMatt Macy #if defined(HAVE_XATTR_LIST_SIMPLE) || \
1430eda14cbcSMatt Macy     defined(HAVE_XATTR_LIST_DENTRY) || \
1431eda14cbcSMatt Macy     defined(HAVE_XATTR_LIST_HANDLER)
1432eda14cbcSMatt Macy 	.flags	= ACL_TYPE_ACCESS,
1433eda14cbcSMatt Macy #endif
1434eda14cbcSMatt Macy };
1435eda14cbcSMatt Macy 
1436eda14cbcSMatt Macy /*
1437eda14cbcSMatt Macy  * ACL default xattr namespace handlers.
1438eda14cbcSMatt Macy  *
1439eda14cbcSMatt Macy  * Use .name instead of .prefix when available. xattr_resolve_name will match
1440eda14cbcSMatt Macy  * whole name and reject anything that has .name only as prefix.
1441eda14cbcSMatt Macy  */
1442e92ffd9bSMartin Matuska static xattr_handler_t zpl_xattr_acl_default_handler = {
1443eda14cbcSMatt Macy #ifdef HAVE_XATTR_HANDLER_NAME
1444eda14cbcSMatt Macy 	.name	= XATTR_NAME_POSIX_ACL_DEFAULT,
1445eda14cbcSMatt Macy #else
1446eda14cbcSMatt Macy 	.prefix	= XATTR_NAME_POSIX_ACL_DEFAULT,
1447eda14cbcSMatt Macy #endif
1448eda14cbcSMatt Macy 	.list	= zpl_xattr_acl_list_default,
1449eda14cbcSMatt Macy 	.get	= zpl_xattr_acl_get_default,
1450eda14cbcSMatt Macy 	.set	= zpl_xattr_acl_set_default,
1451eda14cbcSMatt Macy #if defined(HAVE_XATTR_LIST_SIMPLE) || \
1452eda14cbcSMatt Macy     defined(HAVE_XATTR_LIST_DENTRY) || \
1453eda14cbcSMatt Macy     defined(HAVE_XATTR_LIST_HANDLER)
1454eda14cbcSMatt Macy 	.flags	= ACL_TYPE_DEFAULT,
1455eda14cbcSMatt Macy #endif
1456eda14cbcSMatt Macy };
1457eda14cbcSMatt Macy 
1458eda14cbcSMatt Macy #endif /* CONFIG_FS_POSIX_ACL */
1459eda14cbcSMatt Macy 
1460eda14cbcSMatt Macy xattr_handler_t *zpl_xattr_handlers[] = {
1461eda14cbcSMatt Macy 	&zpl_xattr_security_handler,
1462eda14cbcSMatt Macy 	&zpl_xattr_trusted_handler,
1463eda14cbcSMatt Macy 	&zpl_xattr_user_handler,
1464eda14cbcSMatt Macy #ifdef CONFIG_FS_POSIX_ACL
1465eda14cbcSMatt Macy 	&zpl_xattr_acl_access_handler,
1466eda14cbcSMatt Macy 	&zpl_xattr_acl_default_handler,
1467eda14cbcSMatt Macy #endif /* CONFIG_FS_POSIX_ACL */
1468eda14cbcSMatt Macy 	NULL
1469eda14cbcSMatt Macy };
1470eda14cbcSMatt Macy 
1471eda14cbcSMatt Macy static const struct xattr_handler *
zpl_xattr_handler(const char * name)1472eda14cbcSMatt Macy zpl_xattr_handler(const char *name)
1473eda14cbcSMatt Macy {
1474eda14cbcSMatt Macy 	if (strncmp(name, XATTR_USER_PREFIX,
1475eda14cbcSMatt Macy 	    XATTR_USER_PREFIX_LEN) == 0)
1476eda14cbcSMatt Macy 		return (&zpl_xattr_user_handler);
1477eda14cbcSMatt Macy 
1478eda14cbcSMatt Macy 	if (strncmp(name, XATTR_TRUSTED_PREFIX,
1479eda14cbcSMatt Macy 	    XATTR_TRUSTED_PREFIX_LEN) == 0)
1480eda14cbcSMatt Macy 		return (&zpl_xattr_trusted_handler);
1481eda14cbcSMatt Macy 
1482eda14cbcSMatt Macy 	if (strncmp(name, XATTR_SECURITY_PREFIX,
1483eda14cbcSMatt Macy 	    XATTR_SECURITY_PREFIX_LEN) == 0)
1484eda14cbcSMatt Macy 		return (&zpl_xattr_security_handler);
1485eda14cbcSMatt Macy 
1486eda14cbcSMatt Macy #ifdef CONFIG_FS_POSIX_ACL
1487eda14cbcSMatt Macy 	if (strncmp(name, XATTR_NAME_POSIX_ACL_ACCESS,
1488eda14cbcSMatt Macy 	    sizeof (XATTR_NAME_POSIX_ACL_ACCESS)) == 0)
1489eda14cbcSMatt Macy 		return (&zpl_xattr_acl_access_handler);
1490eda14cbcSMatt Macy 
1491eda14cbcSMatt Macy 	if (strncmp(name, XATTR_NAME_POSIX_ACL_DEFAULT,
1492eda14cbcSMatt Macy 	    sizeof (XATTR_NAME_POSIX_ACL_DEFAULT)) == 0)
1493eda14cbcSMatt Macy 		return (&zpl_xattr_acl_default_handler);
1494eda14cbcSMatt Macy #endif /* CONFIG_FS_POSIX_ACL */
1495eda14cbcSMatt Macy 
1496eda14cbcSMatt Macy 	return (NULL);
1497eda14cbcSMatt Macy }
1498eda14cbcSMatt Macy 
1499c03c5b1cSMartin Matuska static enum xattr_permission
zpl_xattr_permission(xattr_filldir_t * xf,const char * name,int name_len)1500c03c5b1cSMartin Matuska zpl_xattr_permission(xattr_filldir_t *xf, const char *name, int name_len)
1501c03c5b1cSMartin Matuska {
1502c03c5b1cSMartin Matuska 	const struct xattr_handler *handler;
1503c03c5b1cSMartin Matuska 	struct dentry *d __maybe_unused = xf->dentry;
1504c03c5b1cSMartin Matuska 	enum xattr_permission perm = XAPERM_ALLOW;
1505c03c5b1cSMartin Matuska 
1506c03c5b1cSMartin Matuska 	handler = zpl_xattr_handler(name);
1507c03c5b1cSMartin Matuska 	if (handler == NULL) {
1508c03c5b1cSMartin Matuska 		/* Do not expose FreeBSD system namespace xattrs. */
1509c03c5b1cSMartin Matuska 		if (ZFS_XA_NS_PREFIX_MATCH(FREEBSD, name))
1510c03c5b1cSMartin Matuska 			return (XAPERM_DENY);
1511c03c5b1cSMartin Matuska 		/*
1512c03c5b1cSMartin Matuska 		 * Anything that doesn't match a known namespace gets put in the
1513c03c5b1cSMartin Matuska 		 * user namespace for compatibility with other platforms.
1514c03c5b1cSMartin Matuska 		 */
1515c03c5b1cSMartin Matuska 		perm = XAPERM_COMPAT;
1516c03c5b1cSMartin Matuska 		handler = &zpl_xattr_user_handler;
1517c03c5b1cSMartin Matuska 	}
1518c03c5b1cSMartin Matuska 
1519c03c5b1cSMartin Matuska 	if (handler->list) {
1520c03c5b1cSMartin Matuska #if defined(HAVE_XATTR_LIST_SIMPLE)
1521c03c5b1cSMartin Matuska 		if (!handler->list(d))
1522c03c5b1cSMartin Matuska 			return (XAPERM_DENY);
1523c03c5b1cSMartin Matuska #elif defined(HAVE_XATTR_LIST_DENTRY)
1524c03c5b1cSMartin Matuska 		if (!handler->list(d, NULL, 0, name, name_len, 0))
1525c03c5b1cSMartin Matuska 			return (XAPERM_DENY);
1526c03c5b1cSMartin Matuska #elif defined(HAVE_XATTR_LIST_HANDLER)
1527c03c5b1cSMartin Matuska 		if (!handler->list(handler, d, NULL, 0, name, name_len))
1528c03c5b1cSMartin Matuska 			return (XAPERM_DENY);
1529c03c5b1cSMartin Matuska #endif
1530c03c5b1cSMartin Matuska 	}
1531c03c5b1cSMartin Matuska 
1532c03c5b1cSMartin Matuska 	return (perm);
1533c03c5b1cSMartin Matuska }
1534c03c5b1cSMartin Matuska 
15351f1e2261SMartin Matuska #if defined(CONFIG_FS_POSIX_ACL) && \
15361f1e2261SMartin Matuska 	(!defined(HAVE_POSIX_ACL_RELEASE) || \
15371f1e2261SMartin Matuska 		defined(HAVE_POSIX_ACL_RELEASE_GPL_ONLY))
1538eda14cbcSMatt Macy struct acl_rel_struct {
1539eda14cbcSMatt Macy 	struct acl_rel_struct *next;
1540eda14cbcSMatt Macy 	struct posix_acl *acl;
1541eda14cbcSMatt Macy 	clock_t time;
1542eda14cbcSMatt Macy };
1543eda14cbcSMatt Macy 
1544eda14cbcSMatt Macy #define	ACL_REL_GRACE	(60*HZ)
1545eda14cbcSMatt Macy #define	ACL_REL_WINDOW	(1*HZ)
1546eda14cbcSMatt Macy #define	ACL_REL_SCHED	(ACL_REL_GRACE+ACL_REL_WINDOW)
1547eda14cbcSMatt Macy 
1548eda14cbcSMatt Macy /*
1549eda14cbcSMatt Macy  * Lockless multi-producer single-consumer fifo list.
1550eda14cbcSMatt Macy  * Nodes are added to tail and removed from head. Tail pointer is our
1551eda14cbcSMatt Macy  * synchronization point. It always points to the next pointer of the last
1552eda14cbcSMatt Macy  * node, or head if list is empty.
1553eda14cbcSMatt Macy  */
1554eda14cbcSMatt Macy static struct acl_rel_struct *acl_rel_head = NULL;
1555eda14cbcSMatt Macy static struct acl_rel_struct **acl_rel_tail = &acl_rel_head;
1556eda14cbcSMatt Macy 
1557eda14cbcSMatt Macy static void
zpl_posix_acl_free(void * arg)1558eda14cbcSMatt Macy zpl_posix_acl_free(void *arg)
1559eda14cbcSMatt Macy {
1560eda14cbcSMatt Macy 	struct acl_rel_struct *freelist = NULL;
1561eda14cbcSMatt Macy 	struct acl_rel_struct *a;
1562eda14cbcSMatt Macy 	clock_t new_time;
1563eda14cbcSMatt Macy 	boolean_t refire = B_FALSE;
1564eda14cbcSMatt Macy 
1565eda14cbcSMatt Macy 	ASSERT3P(acl_rel_head, !=, NULL);
1566eda14cbcSMatt Macy 	while (acl_rel_head) {
1567eda14cbcSMatt Macy 		a = acl_rel_head;
1568eda14cbcSMatt Macy 		if (ddi_get_lbolt() - a->time >= ACL_REL_GRACE) {
1569eda14cbcSMatt Macy 			/*
1570eda14cbcSMatt Macy 			 * If a is the last node we need to reset tail, but we
1571eda14cbcSMatt Macy 			 * need to use cmpxchg to make sure it is still the
1572eda14cbcSMatt Macy 			 * last node.
1573eda14cbcSMatt Macy 			 */
1574eda14cbcSMatt Macy 			if (acl_rel_tail == &a->next) {
1575eda14cbcSMatt Macy 				acl_rel_head = NULL;
1576eda14cbcSMatt Macy 				if (cmpxchg(&acl_rel_tail, &a->next,
1577eda14cbcSMatt Macy 				    &acl_rel_head) == &a->next) {
1578eda14cbcSMatt Macy 					ASSERT3P(a->next, ==, NULL);
1579eda14cbcSMatt Macy 					a->next = freelist;
1580eda14cbcSMatt Macy 					freelist = a;
1581eda14cbcSMatt Macy 					break;
1582eda14cbcSMatt Macy 				}
1583eda14cbcSMatt Macy 			}
1584eda14cbcSMatt Macy 			/*
1585eda14cbcSMatt Macy 			 * a is not last node, make sure next pointer is set
1586eda14cbcSMatt Macy 			 * by the adder and advance the head.
1587eda14cbcSMatt Macy 			 */
1588eda14cbcSMatt Macy 			while (READ_ONCE(a->next) == NULL)
1589eda14cbcSMatt Macy 				cpu_relax();
1590eda14cbcSMatt Macy 			acl_rel_head = a->next;
1591eda14cbcSMatt Macy 			a->next = freelist;
1592eda14cbcSMatt Macy 			freelist = a;
1593eda14cbcSMatt Macy 		} else {
1594eda14cbcSMatt Macy 			/*
1595eda14cbcSMatt Macy 			 * a is still in grace period. We are responsible to
1596eda14cbcSMatt Macy 			 * reschedule the free task, since adder will only do
1597eda14cbcSMatt Macy 			 * so if list is empty.
1598eda14cbcSMatt Macy 			 */
1599eda14cbcSMatt Macy 			new_time = a->time + ACL_REL_SCHED;
1600eda14cbcSMatt Macy 			refire = B_TRUE;
1601eda14cbcSMatt Macy 			break;
1602eda14cbcSMatt Macy 		}
1603eda14cbcSMatt Macy 	}
1604eda14cbcSMatt Macy 
1605eda14cbcSMatt Macy 	if (refire)
1606eda14cbcSMatt Macy 		taskq_dispatch_delay(system_delay_taskq, zpl_posix_acl_free,
1607eda14cbcSMatt Macy 		    NULL, TQ_SLEEP, new_time);
1608eda14cbcSMatt Macy 
1609eda14cbcSMatt Macy 	while (freelist) {
1610eda14cbcSMatt Macy 		a = freelist;
1611eda14cbcSMatt Macy 		freelist = a->next;
1612eda14cbcSMatt Macy 		kfree(a->acl);
1613eda14cbcSMatt Macy 		kmem_free(a, sizeof (struct acl_rel_struct));
1614eda14cbcSMatt Macy 	}
1615eda14cbcSMatt Macy }
1616eda14cbcSMatt Macy 
1617eda14cbcSMatt Macy void
zpl_posix_acl_release_impl(struct posix_acl * acl)1618eda14cbcSMatt Macy zpl_posix_acl_release_impl(struct posix_acl *acl)
1619eda14cbcSMatt Macy {
1620eda14cbcSMatt Macy 	struct acl_rel_struct *a, **prev;
1621eda14cbcSMatt Macy 
1622eda14cbcSMatt Macy 	a = kmem_alloc(sizeof (struct acl_rel_struct), KM_SLEEP);
1623eda14cbcSMatt Macy 	a->next = NULL;
1624eda14cbcSMatt Macy 	a->acl = acl;
1625eda14cbcSMatt Macy 	a->time = ddi_get_lbolt();
1626eda14cbcSMatt Macy 	/* atomically points tail to us and get the previous tail */
1627eda14cbcSMatt Macy 	prev = xchg(&acl_rel_tail, &a->next);
1628eda14cbcSMatt Macy 	ASSERT3P(*prev, ==, NULL);
1629eda14cbcSMatt Macy 	*prev = a;
1630eda14cbcSMatt Macy 	/* if it was empty before, schedule the free task */
1631eda14cbcSMatt Macy 	if (prev == &acl_rel_head)
1632eda14cbcSMatt Macy 		taskq_dispatch_delay(system_delay_taskq, zpl_posix_acl_free,
1633eda14cbcSMatt Macy 		    NULL, TQ_SLEEP, ddi_get_lbolt() + ACL_REL_SCHED);
1634eda14cbcSMatt Macy }
1635eda14cbcSMatt Macy #endif
1636c03c5b1cSMartin Matuska 
1637c03c5b1cSMartin Matuska ZFS_MODULE_PARAM(zfs, zfs_, xattr_compat, INT, ZMOD_RW,
1638c03c5b1cSMartin Matuska 	"Use legacy ZFS xattr naming for writing new user namespace xattrs");
1639