1 // SPDX-License-Identifier: GPL-2.0
2 #include <linux/kernel.h>
3 #include <linux/errno.h>
5 #include <linux/file.h>
7 #include <linux/slab.h>
8 #include <linux/namei.h>
9 #include <linux/io_uring.h>
10 #include <linux/xattr.h>
12 #include <uapi/linux/io_uring.h>
14 #include "../fs/internal.h"
21 struct kernel_xattr_ctx ctx
;
22 struct filename
*filename
;
25 void io_xattr_cleanup(struct io_kiocb
*req
)
27 struct io_xattr
*ix
= io_kiocb_to_cmd(req
, struct io_xattr
);
30 putname(ix
->filename
);
33 kvfree(ix
->ctx
.kvalue
);
36 static void io_xattr_finish(struct io_kiocb
*req
, int ret
)
38 req
->flags
&= ~REQ_F_NEED_CLEANUP
;
40 io_xattr_cleanup(req
);
41 io_req_set_res(req
, ret
, 0);
44 static int __io_getxattr_prep(struct io_kiocb
*req
,
45 const struct io_uring_sqe
*sqe
)
47 struct io_xattr
*ix
= io_kiocb_to_cmd(req
, struct io_xattr
);
48 const char __user
*name
;
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
);
61 ix
->ctx
.kname
= kmalloc(sizeof(*ix
->ctx
.kname
), GFP_KERNEL
);
65 ret
= import_xattr_name(ix
->ctx
.kname
, name
);
71 req
->flags
|= REQ_F_NEED_CLEANUP
;
72 req
->flags
|= REQ_F_FORCE_ASYNC
;
76 int io_fgetxattr_prep(struct io_kiocb
*req
, const struct io_uring_sqe
*sqe
)
78 return __io_getxattr_prep(req
, sqe
);
81 int io_getxattr_prep(struct io_kiocb
*req
, const struct io_uring_sqe
*sqe
)
83 struct io_xattr
*ix
= io_kiocb_to_cmd(req
, struct io_xattr
);
84 const char __user
*path
;
87 if (unlikely(req
->flags
& REQ_F_FIXED_FILE
))
90 ret
= __io_getxattr_prep(req
, sqe
);
94 path
= u64_to_user_ptr(READ_ONCE(sqe
->addr3
));
96 ix
->filename
= getname(path
);
97 if (IS_ERR(ix
->filename
))
98 return PTR_ERR(ix
->filename
);
103 int io_fgetxattr(struct io_kiocb
*req
, unsigned int issue_flags
)
105 struct io_xattr
*ix
= io_kiocb_to_cmd(req
, struct io_xattr
);
108 WARN_ON_ONCE(issue_flags
& IO_URING_F_NONBLOCK
);
110 ret
= file_getxattr(req
->file
, &ix
->ctx
);
111 io_xattr_finish(req
, ret
);
115 int io_getxattr(struct io_kiocb
*req
, unsigned int issue_flags
)
117 struct io_xattr
*ix
= io_kiocb_to_cmd(req
, struct io_xattr
);
120 WARN_ON_ONCE(issue_flags
& IO_URING_F_NONBLOCK
);
122 ret
= filename_getxattr(AT_FDCWD
, ix
->filename
, LOOKUP_FOLLOW
, &ix
->ctx
);
124 io_xattr_finish(req
, ret
);
128 static int __io_setxattr_prep(struct io_kiocb
*req
,
129 const struct io_uring_sqe
*sqe
)
131 struct io_xattr
*ix
= io_kiocb_to_cmd(req
, struct io_xattr
);
132 const char __user
*name
;
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
);
142 ix
->ctx
.kname
= kmalloc(sizeof(*ix
->ctx
.kname
), GFP_KERNEL
);
146 ret
= setxattr_copy(name
, &ix
->ctx
);
148 kfree(ix
->ctx
.kname
);
152 req
->flags
|= REQ_F_NEED_CLEANUP
;
153 req
->flags
|= REQ_F_FORCE_ASYNC
;
157 int io_setxattr_prep(struct io_kiocb
*req
, const struct io_uring_sqe
*sqe
)
159 struct io_xattr
*ix
= io_kiocb_to_cmd(req
, struct io_xattr
);
160 const char __user
*path
;
163 if (unlikely(req
->flags
& REQ_F_FIXED_FILE
))
166 ret
= __io_setxattr_prep(req
, sqe
);
170 path
= u64_to_user_ptr(READ_ONCE(sqe
->addr3
));
172 ix
->filename
= getname(path
);
173 if (IS_ERR(ix
->filename
))
174 return PTR_ERR(ix
->filename
);
179 int io_fsetxattr_prep(struct io_kiocb
*req
, const struct io_uring_sqe
*sqe
)
181 return __io_setxattr_prep(req
, sqe
);
184 int io_fsetxattr(struct io_kiocb
*req
, unsigned int issue_flags
)
186 struct io_xattr
*ix
= io_kiocb_to_cmd(req
, struct io_xattr
);
189 WARN_ON_ONCE(issue_flags
& IO_URING_F_NONBLOCK
);
191 ret
= file_setxattr(req
->file
, &ix
->ctx
);
192 io_xattr_finish(req
, ret
);
196 int io_setxattr(struct io_kiocb
*req
, unsigned int issue_flags
)
198 struct io_xattr
*ix
= io_kiocb_to_cmd(req
, struct io_xattr
);
201 WARN_ON_ONCE(issue_flags
& IO_URING_F_NONBLOCK
);
203 ret
= filename_setxattr(AT_FDCWD
, ix
->filename
, LOOKUP_FOLLOW
, &ix
->ctx
);
205 io_xattr_finish(req
, ret
);