|
26 | 26 | */ |
27 | 27 |
|
28 | 28 | #include <sys/param.h> |
| 29 | +#include <sys/capsicum.h> |
29 | 30 | #include <sys/extattr.h> |
30 | 31 | #include <sys/fcntl.h> |
| 32 | +#include <sys/file.h> |
31 | 33 | #include <sys/namei.h> |
32 | 34 | #include <sys/proc.h> |
33 | 35 | #include <sys/syscallsubr.h> |
@@ -84,6 +86,19 @@ struct removexattr_args { |
84 | 86 | int follow; |
85 | 87 | }; |
86 | 88 |
|
| 89 | +static int |
| 90 | +linux_xattr_check_fd(struct thread *td, int fd, cap_rights_t *rights) |
| 91 | +{ |
| 92 | + struct file *fp; |
| 93 | + int error; |
| 94 | + |
| 95 | + error = getvnode(td, fd, rights, &fp); |
| 96 | + if (error != 0) |
| 97 | + return (error); |
| 98 | + fdrop(fp, td); |
| 99 | + return (0); |
| 100 | +} |
| 101 | + |
87 | 102 | static char *extattr_namespace_names[] = EXTATTR_NAMESPACE_NAMES; |
88 | 103 |
|
89 | 104 |
|
@@ -132,12 +147,20 @@ listxattr(struct thread *td, struct listxattr_args *args) |
132 | 147 | { |
133 | 148 | char attrname[LINUX_XATTR_NAME_MAX + 1]; |
134 | 149 | char *data, *prefix, *key; |
| 150 | + cap_rights_t rights; |
135 | 151 | struct uio auio; |
136 | 152 | struct iovec aiov; |
137 | 153 | unsigned char keylen; |
138 | 154 | size_t sz, cnt, rs, prefixlen, pairlen; |
139 | 155 | int attrnamespace, error; |
140 | 156 |
|
| 157 | + if (args->path == NULL) { |
| 158 | + error = linux_xattr_check_fd(td, args->fd, |
| 159 | + cap_rights_init_one(&rights, CAP_EXTATTR_LIST)); |
| 160 | + if (error != 0) |
| 161 | + return (error); |
| 162 | + } |
| 163 | + |
141 | 164 | if (args->size != 0) |
142 | 165 | sz = min(LINUX_XATTR_LIST_MAX, args->size); |
143 | 166 | else |
@@ -253,8 +276,16 @@ static int |
253 | 276 | removexattr(struct thread *td, struct removexattr_args *args) |
254 | 277 | { |
255 | 278 | char attrname[LINUX_XATTR_NAME_MAX + 1]; |
| 279 | + cap_rights_t rights; |
256 | 280 | int attrnamespace, error; |
257 | 281 |
|
| 282 | + if (args->path == NULL) { |
| 283 | + error = linux_xattr_check_fd(td, args->fd, |
| 284 | + cap_rights_init_one(&rights, CAP_EXTATTR_DELETE)); |
| 285 | + if (error != 0) |
| 286 | + return (error); |
| 287 | + } |
| 288 | + |
258 | 289 | error = xattr_to_extattr(args->name, &attrnamespace, attrname); |
259 | 290 | if (error != 0) |
260 | 291 | return (error); |
@@ -310,8 +341,16 @@ static int |
310 | 341 | getxattr(struct thread *td, struct getxattr_args *args) |
311 | 342 | { |
312 | 343 | char attrname[LINUX_XATTR_NAME_MAX + 1]; |
| 344 | + cap_rights_t rights; |
313 | 345 | int attrnamespace, error; |
314 | 346 |
|
| 347 | + if (args->path == NULL) { |
| 348 | + error = linux_xattr_check_fd(td, args->fd, |
| 349 | + cap_rights_init_one(&rights, CAP_EXTATTR_GET)); |
| 350 | + if (error != 0) |
| 351 | + return (error); |
| 352 | + } |
| 353 | + |
315 | 354 | error = xattr_to_extattr(args->name, &attrnamespace, attrname); |
316 | 355 | if (error != 0) |
317 | 356 | return (error); |
@@ -373,8 +412,16 @@ static int |
373 | 412 | setxattr(struct thread *td, struct setxattr_args *args) |
374 | 413 | { |
375 | 414 | char attrname[LINUX_XATTR_NAME_MAX + 1]; |
| 415 | + cap_rights_t rights; |
376 | 416 | int attrnamespace, error; |
377 | 417 |
|
| 418 | + if (args->path == NULL) { |
| 419 | + error = linux_xattr_check_fd(td, args->fd, |
| 420 | + cap_rights_init_one(&rights, CAP_EXTATTR_SET)); |
| 421 | + if (error != 0) |
| 422 | + return (error); |
| 423 | + } |
| 424 | + |
378 | 425 | if ((args->flags & ~(LINUX_XATTR_FLAGS)) != 0 || |
379 | 426 | args->flags == (LINUX_XATTR_FLAGS)) |
380 | 427 | return (EINVAL); |
|
0 commit comments