xref: /openbmc/linux/fs/9p/xattr.c (revision b97d6790d03b763eca08847a9a5869a4291b9f9a)
1024b7d6aSDominique Martinet // SPDX-License-Identifier: LGPL-2.1
2ebf46264SAneesh Kumar K.V /*
3ebf46264SAneesh Kumar K.V  * Copyright IBM Corporation, 2010
4ebf46264SAneesh Kumar K.V  * Author Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
5ebf46264SAneesh Kumar K.V  */
6ebf46264SAneesh Kumar K.V 
7ebf46264SAneesh Kumar K.V #include <linux/module.h>
8ebf46264SAneesh Kumar K.V #include <linux/fs.h>
9ebf46264SAneesh Kumar K.V #include <linux/sched.h>
10070b3656SAl Viro #include <linux/uio.h>
1139a6497aSChristian Brauner #include <linux/posix_acl_xattr.h>
12ebf46264SAneesh Kumar K.V #include <net/9p/9p.h>
13ebf46264SAneesh Kumar K.V #include <net/9p/client.h>
14ebf46264SAneesh Kumar K.V 
15ebf46264SAneesh Kumar K.V #include "fid.h"
16ebf46264SAneesh Kumar K.V #include "xattr.h"
17ebf46264SAneesh Kumar K.V 
v9fs_fid_xattr_get(struct p9_fid * fid,const char * name,void * buffer,size_t buffer_size)1885ff872dSAneesh Kumar K.V ssize_t v9fs_fid_xattr_get(struct p9_fid *fid, const char *name,
19ebf46264SAneesh Kumar K.V 			   void *buffer, size_t buffer_size)
20ebf46264SAneesh Kumar K.V {
21ebf46264SAneesh Kumar K.V 	ssize_t retval;
22e1200fe6SAl Viro 	u64 attr_size;
2385ff872dSAneesh Kumar K.V 	struct p9_fid *attr_fid;
24e1200fe6SAl Viro 	struct kvec kvec = {.iov_base = buffer, .iov_len = buffer_size};
25e1200fe6SAl Viro 	struct iov_iter to;
26e1200fe6SAl Viro 	int err;
27e1200fe6SAl Viro 
28de4eda9dSAl Viro 	iov_iter_kvec(&to, ITER_DEST, &kvec, 1, buffer_size);
29ebf46264SAneesh Kumar K.V 
30ebf46264SAneesh Kumar K.V 	attr_fid = p9_client_xattrwalk(fid, name, &attr_size);
31ebf46264SAneesh Kumar K.V 	if (IS_ERR(attr_fid)) {
32ebf46264SAneesh Kumar K.V 		retval = PTR_ERR(attr_fid);
335d385153SJoe Perches 		p9_debug(P9_DEBUG_VFS, "p9_client_attrwalk failed %zd\n",
345d385153SJoe Perches 			 retval);
35e1200fe6SAl Viro 		return retval;
36ebf46264SAneesh Kumar K.V 	}
37ebf46264SAneesh Kumar K.V 	if (attr_size > buffer_size) {
38707823e7SIvan Orlov 		if (buffer_size)
39e1200fe6SAl Viro 			retval = -ERANGE;
40707823e7SIvan Orlov 		else if (attr_size > SSIZE_MAX)
41707823e7SIvan Orlov 			retval = -EOVERFLOW;
42707823e7SIvan Orlov 		else /* request to get the attr_size */
43707823e7SIvan Orlov 			retval = attr_size;
44e1200fe6SAl Viro 	} else {
45e1200fe6SAl Viro 		iov_iter_truncate(&to, attr_size);
46e1200fe6SAl Viro 		retval = p9_client_read(attr_fid, 0, &to, &err);
47e1200fe6SAl Viro 		if (err)
48e1200fe6SAl Viro 			retval = err;
49ebf46264SAneesh Kumar K.V 	}
50b48dbb99SDominique Martinet 	p9_fid_put(attr_fid);
51ebf46264SAneesh Kumar K.V 	return retval;
52ebf46264SAneesh Kumar K.V }
53ebf46264SAneesh Kumar K.V 
5485ff872dSAneesh Kumar K.V 
5585ff872dSAneesh Kumar K.V /*
5685ff872dSAneesh Kumar K.V  * v9fs_xattr_get()
5785ff872dSAneesh Kumar K.V  *
5885ff872dSAneesh Kumar K.V  * Copy an extended attribute into the buffer
5985ff872dSAneesh Kumar K.V  * provided, or compute the buffer size required.
6085ff872dSAneesh Kumar K.V  * Buffer is NULL to compute the size of the buffer required.
6185ff872dSAneesh Kumar K.V  *
6285ff872dSAneesh Kumar K.V  * Returns a negative error number on failure, or the number of bytes
6385ff872dSAneesh Kumar K.V  * used / required on success.
6485ff872dSAneesh Kumar K.V  */
v9fs_xattr_get(struct dentry * dentry,const char * name,void * buffer,size_t buffer_size)6585ff872dSAneesh Kumar K.V ssize_t v9fs_xattr_get(struct dentry *dentry, const char *name,
6685ff872dSAneesh Kumar K.V 		       void *buffer, size_t buffer_size)
6785ff872dSAneesh Kumar K.V {
6885ff872dSAneesh Kumar K.V 	struct p9_fid *fid;
696636b6dcSJianyong Wu 	int ret;
7085ff872dSAneesh Kumar K.V 
71*35663b6bSDominique Martinet 	p9_debug(P9_DEBUG_VFS, "name = '%s' value_len = %zu\n",
725d385153SJoe Perches 		 name, buffer_size);
7385ff872dSAneesh Kumar K.V 	fid = v9fs_fid_lookup(dentry);
7485ff872dSAneesh Kumar K.V 	if (IS_ERR(fid))
7585ff872dSAneesh Kumar K.V 		return PTR_ERR(fid);
766636b6dcSJianyong Wu 	ret = v9fs_fid_xattr_get(fid, name, buffer, buffer_size);
77b48dbb99SDominique Martinet 	p9_fid_put(fid);
7885ff872dSAneesh Kumar K.V 
796636b6dcSJianyong Wu 	return ret;
8085ff872dSAneesh Kumar K.V }
8185ff872dSAneesh Kumar K.V 
82ebf46264SAneesh Kumar K.V /*
83ebf46264SAneesh Kumar K.V  * v9fs_xattr_set()
84ebf46264SAneesh Kumar K.V  *
85ebf46264SAneesh Kumar K.V  * Create, replace or remove an extended attribute for this inode. Buffer
86ebf46264SAneesh Kumar K.V  * is NULL to remove an existing extended attribute, and non-NULL to
87ebf46264SAneesh Kumar K.V  * either replace an existing extended attribute, or create a new extended
88ebf46264SAneesh Kumar K.V  * attribute. The flags XATTR_REPLACE and XATTR_CREATE
89ebf46264SAneesh Kumar K.V  * specify that an extended attribute must exist and must not exist
90ebf46264SAneesh Kumar K.V  * previous to the call, respectively.
91ebf46264SAneesh Kumar K.V  *
92ebf46264SAneesh Kumar K.V  * Returns 0, or a negative error number on failure.
93ebf46264SAneesh Kumar K.V  */
v9fs_xattr_set(struct dentry * dentry,const char * name,const void * value,size_t value_len,int flags)94ebf46264SAneesh Kumar K.V int v9fs_xattr_set(struct dentry *dentry, const char *name,
95ebf46264SAneesh Kumar K.V 		   const void *value, size_t value_len, int flags)
96ebf46264SAneesh Kumar K.V {
976636b6dcSJianyong Wu 	int ret;
986636b6dcSJianyong Wu 	struct p9_fid *fid;
996636b6dcSJianyong Wu 
1006636b6dcSJianyong Wu 	fid  = v9fs_fid_lookup(dentry);
1016636b6dcSJianyong Wu 	if (IS_ERR(fid))
1026636b6dcSJianyong Wu 		return PTR_ERR(fid);
1036636b6dcSJianyong Wu 	ret = v9fs_fid_xattr_set(fid, name, value, value_len, flags);
104b48dbb99SDominique Martinet 	p9_fid_put(fid);
1056636b6dcSJianyong Wu 	return ret;
10638baba9eSAl Viro }
10738baba9eSAl Viro 
v9fs_fid_xattr_set(struct p9_fid * fid,const char * name,const void * value,size_t value_len,int flags)10838baba9eSAl Viro int v9fs_fid_xattr_set(struct p9_fid *fid, const char *name,
10938baba9eSAl Viro 		   const void *value, size_t value_len, int flags)
11038baba9eSAl Viro {
111070b3656SAl Viro 	struct kvec kvec = {.iov_base = (void *)value, .iov_len = value_len};
112070b3656SAl Viro 	struct iov_iter from;
1133111784bSpiaojun 	int retval, err;
114070b3656SAl Viro 
115de4eda9dSAl Viro 	iov_iter_kvec(&from, ITER_SOURCE, &kvec, 1, value_len);
116ebf46264SAneesh Kumar K.V 
1175d385153SJoe Perches 	p9_debug(P9_DEBUG_VFS, "name = %s value_len = %zu flags = %d\n",
1185d385153SJoe Perches 		 name, value_len, flags);
119ebf46264SAneesh Kumar K.V 
12038baba9eSAl Viro 	/* Clone it */
1217d50a29fSAl Viro 	fid = clone_fid(fid);
12238baba9eSAl Viro 	if (IS_ERR(fid))
12338baba9eSAl Viro 		return PTR_ERR(fid);
12438baba9eSAl Viro 
125ebf46264SAneesh Kumar K.V 	/*
126ebf46264SAneesh Kumar K.V 	 * On success fid points to xattr
127ebf46264SAneesh Kumar K.V 	 */
128ebf46264SAneesh Kumar K.V 	retval = p9_client_xattrcreate(fid, name, value_len, flags);
129070b3656SAl Viro 	if (retval < 0)
1305d385153SJoe Perches 		p9_debug(P9_DEBUG_VFS, "p9_client_xattrcreate failed %d\n",
1315d385153SJoe Perches 			 retval);
132ebf46264SAneesh Kumar K.V 	else
133070b3656SAl Viro 		p9_client_write(fid, 0, &from, &retval);
134b48dbb99SDominique Martinet 	err = p9_fid_put(fid);
1353111784bSpiaojun 	if (!retval && err)
1363111784bSpiaojun 		retval = err;
137bdd5c28dSGeyslan G. Bem 	return retval;
138ebf46264SAneesh Kumar K.V }
139ebf46264SAneesh Kumar K.V 
v9fs_listxattr(struct dentry * dentry,char * buffer,size_t buffer_size)140ebf46264SAneesh Kumar K.V ssize_t v9fs_listxattr(struct dentry *dentry, char *buffer, size_t buffer_size)
141ebf46264SAneesh Kumar K.V {
142*35663b6bSDominique Martinet 	/* Txattrwalk with an empty string lists xattrs instead */
143*35663b6bSDominique Martinet 	return v9fs_xattr_get(dentry, "", buffer, buffer_size);
144ebf46264SAneesh Kumar K.V }
145ebf46264SAneesh Kumar K.V 
v9fs_xattr_handler_get(const struct xattr_handler * handler,struct dentry * dentry,struct inode * inode,const char * name,void * buffer,size_t size)146e409de99SAndreas Gruenbacher static int v9fs_xattr_handler_get(const struct xattr_handler *handler,
147b296821aSAl Viro 				  struct dentry *dentry, struct inode *inode,
148b296821aSAl Viro 				  const char *name, void *buffer, size_t size)
149e409de99SAndreas Gruenbacher {
150e409de99SAndreas Gruenbacher 	const char *full_name = xattr_full_name(handler, name);
151e409de99SAndreas Gruenbacher 
152e409de99SAndreas Gruenbacher 	return v9fs_xattr_get(dentry, full_name, buffer, size);
153e409de99SAndreas Gruenbacher }
154e409de99SAndreas Gruenbacher 
v9fs_xattr_handler_set(const struct xattr_handler * handler,struct mnt_idmap * idmap,struct dentry * dentry,struct inode * inode,const char * name,const void * value,size_t size,int flags)155e409de99SAndreas Gruenbacher static int v9fs_xattr_handler_set(const struct xattr_handler *handler,
15639f60c1cSChristian Brauner 				  struct mnt_idmap *idmap,
15759301226SAl Viro 				  struct dentry *dentry, struct inode *inode,
15859301226SAl Viro 				  const char *name, const void *value,
15959301226SAl Viro 				  size_t size, int flags)
160e409de99SAndreas Gruenbacher {
161e409de99SAndreas Gruenbacher 	const char *full_name = xattr_full_name(handler, name);
162e409de99SAndreas Gruenbacher 
163e409de99SAndreas Gruenbacher 	return v9fs_xattr_set(dentry, full_name, value, size, flags);
164e409de99SAndreas Gruenbacher }
165e409de99SAndreas Gruenbacher 
166e409de99SAndreas Gruenbacher static struct xattr_handler v9fs_xattr_user_handler = {
167e409de99SAndreas Gruenbacher 	.prefix	= XATTR_USER_PREFIX,
168e409de99SAndreas Gruenbacher 	.get	= v9fs_xattr_handler_get,
169e409de99SAndreas Gruenbacher 	.set	= v9fs_xattr_handler_set,
170e409de99SAndreas Gruenbacher };
171e409de99SAndreas Gruenbacher 
172e409de99SAndreas Gruenbacher static struct xattr_handler v9fs_xattr_trusted_handler = {
173e409de99SAndreas Gruenbacher 	.prefix	= XATTR_TRUSTED_PREFIX,
174e409de99SAndreas Gruenbacher 	.get	= v9fs_xattr_handler_get,
175e409de99SAndreas Gruenbacher 	.set	= v9fs_xattr_handler_set,
176e409de99SAndreas Gruenbacher };
177e409de99SAndreas Gruenbacher 
178e409de99SAndreas Gruenbacher #ifdef CONFIG_9P_FS_SECURITY
179e409de99SAndreas Gruenbacher static struct xattr_handler v9fs_xattr_security_handler = {
180e409de99SAndreas Gruenbacher 	.prefix	= XATTR_SECURITY_PREFIX,
181e409de99SAndreas Gruenbacher 	.get	= v9fs_xattr_handler_get,
182e409de99SAndreas Gruenbacher 	.set	= v9fs_xattr_handler_set,
183e409de99SAndreas Gruenbacher };
184e409de99SAndreas Gruenbacher #endif
185e409de99SAndreas Gruenbacher 
186ebf46264SAneesh Kumar K.V const struct xattr_handler *v9fs_xattr_handlers[] = {
187ebf46264SAneesh Kumar K.V 	&v9fs_xattr_user_handler,
188d9a73859SJim Garlick 	&v9fs_xattr_trusted_handler,
189d9a73859SJim Garlick #ifdef CONFIG_9P_FS_SECURITY
190d9a73859SJim Garlick 	&v9fs_xattr_security_handler,
191d9a73859SJim Garlick #endif
192ebf46264SAneesh Kumar K.V 	NULL
193ebf46264SAneesh Kumar K.V };
194