xref: /linux/io_uring/xattr.c (revision 9cc8d0ecdd2aad42e377e971e3bb114339df609e)
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 
19 struct io_xattr {
20 	struct file			*file;
21 	struct kernel_xattr_ctx		ctx;
22 	struct filename			*filename;
23 };
24 
25 void 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 
36 static 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 
44 static 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 
76 int io_fgetxattr_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe)
77 {
78 	return __io_getxattr_prep(req, sqe);
79 }
80 
81 int 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 
103 int 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 
115 int 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 
128 static 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 
157 int 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 
179 int io_fsetxattr_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe)
180 {
181 	return __io_setxattr_prep(req, sqe);
182 }
183 
184 int 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 
196 int 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 }
208