Linux Audio

Check our new training course

Loading...
v6.2
  1// SPDX-License-Identifier: GPL-2.0
  2#include <linux/kernel.h>
  3#include <linux/errno.h>
  4#include <linux/fs.h>
  5#include <linux/file.h>
  6#include <linux/mm.h>
  7#include <linux/slab.h>
  8#include <linux/namei.h>
  9#include <linux/io_uring.h>
 10#include <linux/xattr.h>
 11
 12#include <uapi/linux/io_uring.h>
 13
 14#include "../fs/internal.h"
 15
 16#include "io_uring.h"
 17#include "xattr.h"
 18
 19struct io_xattr {
 20	struct file			*file;
 21	struct xattr_ctx		ctx;
 22	struct filename			*filename;
 23};
 24
 25void io_xattr_cleanup(struct io_kiocb *req)
 26{
 27	struct io_xattr *ix = io_kiocb_to_cmd(req, struct io_xattr);
 28
 29	if (ix->filename)
 30		putname(ix->filename);
 31
 32	kfree(ix->ctx.kname);
 33	kvfree(ix->ctx.kvalue);
 34}
 35
 36static void io_xattr_finish(struct io_kiocb *req, int ret)
 37{
 38	req->flags &= ~REQ_F_NEED_CLEANUP;
 39
 40	io_xattr_cleanup(req);
 41	io_req_set_res(req, ret, 0);
 42}
 43
 44static int __io_getxattr_prep(struct io_kiocb *req,
 45			      const struct io_uring_sqe *sqe)
 46{
 47	struct io_xattr *ix = io_kiocb_to_cmd(req, struct io_xattr);
 48	const char __user *name;
 49	int ret;
 50
 51	if (unlikely(req->flags & REQ_F_FIXED_FILE))
 52		return -EBADF;
 53
 54	ix->filename = NULL;
 55	ix->ctx.kvalue = NULL;
 56	name = u64_to_user_ptr(READ_ONCE(sqe->addr));
 57	ix->ctx.cvalue = u64_to_user_ptr(READ_ONCE(sqe->addr2));
 58	ix->ctx.size = READ_ONCE(sqe->len);
 59	ix->ctx.flags = READ_ONCE(sqe->xattr_flags);
 60
 61	if (ix->ctx.flags)
 62		return -EINVAL;
 63
 64	ix->ctx.kname = kmalloc(sizeof(*ix->ctx.kname), GFP_KERNEL);
 65	if (!ix->ctx.kname)
 66		return -ENOMEM;
 67
 68	ret = strncpy_from_user(ix->ctx.kname->name, name,
 69				sizeof(ix->ctx.kname->name));
 70	if (!ret || ret == sizeof(ix->ctx.kname->name))
 71		ret = -ERANGE;
 72	if (ret < 0) {
 73		kfree(ix->ctx.kname);
 74		return ret;
 75	}
 76
 77	req->flags |= REQ_F_NEED_CLEANUP;
 
 78	return 0;
 79}
 80
 81int io_fgetxattr_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe)
 82{
 83	return __io_getxattr_prep(req, sqe);
 84}
 85
 86int io_getxattr_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe)
 87{
 88	struct io_xattr *ix = io_kiocb_to_cmd(req, struct io_xattr);
 89	const char __user *path;
 90	int ret;
 91
 
 
 
 92	ret = __io_getxattr_prep(req, sqe);
 93	if (ret)
 94		return ret;
 95
 96	path = u64_to_user_ptr(READ_ONCE(sqe->addr3));
 97
 98	ix->filename = getname_flags(path, LOOKUP_FOLLOW, NULL);
 99	if (IS_ERR(ix->filename)) {
100		ret = PTR_ERR(ix->filename);
101		ix->filename = NULL;
102	}
103
104	return ret;
105}
106
107int io_fgetxattr(struct io_kiocb *req, unsigned int issue_flags)
108{
109	struct io_xattr *ix = io_kiocb_to_cmd(req, struct io_xattr);
110	int ret;
111
112	if (issue_flags & IO_URING_F_NONBLOCK)
113		return -EAGAIN;
114
115	ret = do_getxattr(mnt_idmap(req->file->f_path.mnt),
116			req->file->f_path.dentry,
117			&ix->ctx);
118
 
119	io_xattr_finish(req, ret);
120	return IOU_OK;
121}
122
123int io_getxattr(struct io_kiocb *req, unsigned int issue_flags)
124{
125	struct io_xattr *ix = io_kiocb_to_cmd(req, struct io_xattr);
126	unsigned int lookup_flags = LOOKUP_FOLLOW;
127	struct path path;
128	int ret;
129
130	if (issue_flags & IO_URING_F_NONBLOCK)
131		return -EAGAIN;
132
133retry:
134	ret = filename_lookup(AT_FDCWD, ix->filename, lookup_flags, &path, NULL);
135	if (!ret) {
136		ret = do_getxattr(mnt_idmap(path.mnt), path.dentry, &ix->ctx);
137
138		path_put(&path);
139		if (retry_estale(ret, lookup_flags)) {
140			lookup_flags |= LOOKUP_REVAL;
141			goto retry;
142		}
143	}
144
 
 
145	io_xattr_finish(req, ret);
146	return IOU_OK;
147}
148
149static int __io_setxattr_prep(struct io_kiocb *req,
150			const struct io_uring_sqe *sqe)
151{
152	struct io_xattr *ix = io_kiocb_to_cmd(req, struct io_xattr);
153	const char __user *name;
154	int ret;
155
156	if (unlikely(req->flags & REQ_F_FIXED_FILE))
157		return -EBADF;
158
159	ix->filename = NULL;
160	name = u64_to_user_ptr(READ_ONCE(sqe->addr));
161	ix->ctx.cvalue = u64_to_user_ptr(READ_ONCE(sqe->addr2));
162	ix->ctx.kvalue = NULL;
163	ix->ctx.size = READ_ONCE(sqe->len);
164	ix->ctx.flags = READ_ONCE(sqe->xattr_flags);
165
166	ix->ctx.kname = kmalloc(sizeof(*ix->ctx.kname), GFP_KERNEL);
167	if (!ix->ctx.kname)
168		return -ENOMEM;
169
170	ret = setxattr_copy(name, &ix->ctx);
171	if (ret) {
172		kfree(ix->ctx.kname);
173		return ret;
174	}
175
176	req->flags |= REQ_F_NEED_CLEANUP;
 
177	return 0;
178}
179
180int io_setxattr_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe)
181{
182	struct io_xattr *ix = io_kiocb_to_cmd(req, struct io_xattr);
183	const char __user *path;
184	int ret;
185
 
 
 
186	ret = __io_setxattr_prep(req, sqe);
187	if (ret)
188		return ret;
189
190	path = u64_to_user_ptr(READ_ONCE(sqe->addr3));
191
192	ix->filename = getname_flags(path, LOOKUP_FOLLOW, NULL);
193	if (IS_ERR(ix->filename)) {
194		ret = PTR_ERR(ix->filename);
195		ix->filename = NULL;
196	}
197
198	return ret;
199}
200
201int io_fsetxattr_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe)
202{
203	return __io_setxattr_prep(req, sqe);
204}
205
206static int __io_setxattr(struct io_kiocb *req, unsigned int issue_flags,
207			const struct path *path)
208{
209	struct io_xattr *ix = io_kiocb_to_cmd(req, struct io_xattr);
210	int ret;
211
212	ret = mnt_want_write(path->mnt);
213	if (!ret) {
214		ret = do_setxattr(mnt_idmap(path->mnt), path->dentry, &ix->ctx);
215		mnt_drop_write(path->mnt);
216	}
217
218	return ret;
219}
220
221int io_fsetxattr(struct io_kiocb *req, unsigned int issue_flags)
222{
 
223	int ret;
224
225	if (issue_flags & IO_URING_F_NONBLOCK)
226		return -EAGAIN;
227
228	ret = __io_setxattr(req, issue_flags, &req->file->f_path);
229	io_xattr_finish(req, ret);
230	return IOU_OK;
231}
232
233int io_setxattr(struct io_kiocb *req, unsigned int issue_flags)
234{
235	struct io_xattr *ix = io_kiocb_to_cmd(req, struct io_xattr);
236	unsigned int lookup_flags = LOOKUP_FOLLOW;
237	struct path path;
238	int ret;
239
240	if (issue_flags & IO_URING_F_NONBLOCK)
241		return -EAGAIN;
242
243retry:
244	ret = filename_lookup(AT_FDCWD, ix->filename, lookup_flags, &path, NULL);
245	if (!ret) {
246		ret = __io_setxattr(req, issue_flags, &path);
247		path_put(&path);
248		if (retry_estale(ret, lookup_flags)) {
249			lookup_flags |= LOOKUP_REVAL;
250			goto retry;
251		}
252	}
253
 
 
254	io_xattr_finish(req, ret);
255	return IOU_OK;
256}
v6.13.7
  1// SPDX-License-Identifier: GPL-2.0
  2#include <linux/kernel.h>
  3#include <linux/errno.h>
  4#include <linux/fs.h>
  5#include <linux/file.h>
  6#include <linux/mm.h>
  7#include <linux/slab.h>
  8#include <linux/namei.h>
  9#include <linux/io_uring.h>
 10#include <linux/xattr.h>
 11
 12#include <uapi/linux/io_uring.h>
 13
 14#include "../fs/internal.h"
 15
 16#include "io_uring.h"
 17#include "xattr.h"
 18
 19struct io_xattr {
 20	struct file			*file;
 21	struct kernel_xattr_ctx		ctx;
 22	struct filename			*filename;
 23};
 24
 25void io_xattr_cleanup(struct io_kiocb *req)
 26{
 27	struct io_xattr *ix = io_kiocb_to_cmd(req, struct io_xattr);
 28
 29	if (ix->filename)
 30		putname(ix->filename);
 31
 32	kfree(ix->ctx.kname);
 33	kvfree(ix->ctx.kvalue);
 34}
 35
 36static void io_xattr_finish(struct io_kiocb *req, int ret)
 37{
 38	req->flags &= ~REQ_F_NEED_CLEANUP;
 39
 40	io_xattr_cleanup(req);
 41	io_req_set_res(req, ret, 0);
 42}
 43
 44static int __io_getxattr_prep(struct io_kiocb *req,
 45			      const struct io_uring_sqe *sqe)
 46{
 47	struct io_xattr *ix = io_kiocb_to_cmd(req, struct io_xattr);
 48	const char __user *name;
 49	int ret;
 50
 
 
 
 51	ix->filename = NULL;
 52	ix->ctx.kvalue = NULL;
 53	name = u64_to_user_ptr(READ_ONCE(sqe->addr));
 54	ix->ctx.value = u64_to_user_ptr(READ_ONCE(sqe->addr2));
 55	ix->ctx.size = READ_ONCE(sqe->len);
 56	ix->ctx.flags = READ_ONCE(sqe->xattr_flags);
 57
 58	if (ix->ctx.flags)
 59		return -EINVAL;
 60
 61	ix->ctx.kname = kmalloc(sizeof(*ix->ctx.kname), GFP_KERNEL);
 62	if (!ix->ctx.kname)
 63		return -ENOMEM;
 64
 65	ret = import_xattr_name(ix->ctx.kname, name);
 66	if (ret) {
 
 
 
 67		kfree(ix->ctx.kname);
 68		return ret;
 69	}
 70
 71	req->flags |= REQ_F_NEED_CLEANUP;
 72	req->flags |= REQ_F_FORCE_ASYNC;
 73	return 0;
 74}
 75
 76int io_fgetxattr_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe)
 77{
 78	return __io_getxattr_prep(req, sqe);
 79}
 80
 81int io_getxattr_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe)
 82{
 83	struct io_xattr *ix = io_kiocb_to_cmd(req, struct io_xattr);
 84	const char __user *path;
 85	int ret;
 86
 87	if (unlikely(req->flags & REQ_F_FIXED_FILE))
 88		return -EBADF;
 89
 90	ret = __io_getxattr_prep(req, sqe);
 91	if (ret)
 92		return ret;
 93
 94	path = u64_to_user_ptr(READ_ONCE(sqe->addr3));
 95
 96	ix->filename = getname(path);
 97	if (IS_ERR(ix->filename))
 98		return PTR_ERR(ix->filename);
 
 
 99
100	return 0;
101}
102
103int io_fgetxattr(struct io_kiocb *req, unsigned int issue_flags)
104{
105	struct io_xattr *ix = io_kiocb_to_cmd(req, struct io_xattr);
106	int ret;
107
108	WARN_ON_ONCE(issue_flags & IO_URING_F_NONBLOCK);
 
 
 
 
 
109
110	ret = file_getxattr(req->file, &ix->ctx);
111	io_xattr_finish(req, ret);
112	return IOU_OK;
113}
114
115int io_getxattr(struct io_kiocb *req, unsigned int issue_flags)
116{
117	struct io_xattr *ix = io_kiocb_to_cmd(req, struct io_xattr);
 
 
118	int ret;
119
120	WARN_ON_ONCE(issue_flags & IO_URING_F_NONBLOCK);
 
 
 
 
 
 
 
 
 
 
 
 
 
121
122	ret = filename_getxattr(AT_FDCWD, ix->filename, LOOKUP_FOLLOW, &ix->ctx);
123	ix->filename = NULL;
124	io_xattr_finish(req, ret);
125	return IOU_OK;
126}
127
128static int __io_setxattr_prep(struct io_kiocb *req,
129			const struct io_uring_sqe *sqe)
130{
131	struct io_xattr *ix = io_kiocb_to_cmd(req, struct io_xattr);
132	const char __user *name;
133	int ret;
134
 
 
 
135	ix->filename = NULL;
136	name = u64_to_user_ptr(READ_ONCE(sqe->addr));
137	ix->ctx.cvalue = u64_to_user_ptr(READ_ONCE(sqe->addr2));
138	ix->ctx.kvalue = NULL;
139	ix->ctx.size = READ_ONCE(sqe->len);
140	ix->ctx.flags = READ_ONCE(sqe->xattr_flags);
141
142	ix->ctx.kname = kmalloc(sizeof(*ix->ctx.kname), GFP_KERNEL);
143	if (!ix->ctx.kname)
144		return -ENOMEM;
145
146	ret = setxattr_copy(name, &ix->ctx);
147	if (ret) {
148		kfree(ix->ctx.kname);
149		return ret;
150	}
151
152	req->flags |= REQ_F_NEED_CLEANUP;
153	req->flags |= REQ_F_FORCE_ASYNC;
154	return 0;
155}
156
157int io_setxattr_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe)
158{
159	struct io_xattr *ix = io_kiocb_to_cmd(req, struct io_xattr);
160	const char __user *path;
161	int ret;
162
163	if (unlikely(req->flags & REQ_F_FIXED_FILE))
164		return -EBADF;
165
166	ret = __io_setxattr_prep(req, sqe);
167	if (ret)
168		return ret;
169
170	path = u64_to_user_ptr(READ_ONCE(sqe->addr3));
171
172	ix->filename = getname(path);
173	if (IS_ERR(ix->filename))
174		return PTR_ERR(ix->filename);
 
 
175
176	return 0;
177}
178
179int io_fsetxattr_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe)
180{
181	return __io_setxattr_prep(req, sqe);
182}
183
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
184int io_fsetxattr(struct io_kiocb *req, unsigned int issue_flags)
185{
186	struct io_xattr *ix = io_kiocb_to_cmd(req, struct io_xattr);
187	int ret;
188
189	WARN_ON_ONCE(issue_flags & IO_URING_F_NONBLOCK);
 
190
191	ret = file_setxattr(req->file, &ix->ctx);
192	io_xattr_finish(req, ret);
193	return IOU_OK;
194}
195
196int io_setxattr(struct io_kiocb *req, unsigned int issue_flags)
197{
198	struct io_xattr *ix = io_kiocb_to_cmd(req, struct io_xattr);
 
 
199	int ret;
200
201	WARN_ON_ONCE(issue_flags & IO_URING_F_NONBLOCK);
 
 
 
 
 
 
 
 
 
 
 
 
202
203	ret = filename_setxattr(AT_FDCWD, ix->filename, LOOKUP_FOLLOW, &ix->ctx);
204	ix->filename = NULL;
205	io_xattr_finish(req, ret);
206	return IOU_OK;
207}