Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

fs: split fileattr related helpers into separate file

This patch moves function related to file extended attributes
manipulations to separate file. Refactoring only.

Signed-off-by: Andrey Albershteyn <aalbersh@kernel.org>
Link: https://lore.kernel.org/20250630-xattrat-syscall-v6-1-c4e3bc35227b@kernel.org
Reviewed-by: Amir Goldstein <amir73il@gmail.com>
Reviewed-by: Darrick J. Wong <djwong@kernel.org>
Reviewed-by: Jan Kara <jack@suse.cz>
Signed-off-by: Christian Brauner <brauner@kernel.org>

authored by

Andrey Albershteyn and committed by
Christian Brauner
2f952c9e 19272b37

+325 -310
+2 -1
fs/Makefile
··· 15 15 pnode.o splice.o sync.o utimes.o d_path.o \ 16 16 stack.o fs_struct.o statfs.o fs_pin.o nsfs.o \ 17 17 fs_types.o fs_context.o fs_parser.o fsopen.o init.o \ 18 - kernel_read_file.o mnt_idmapping.o remap_range.o pidfs.o 18 + kernel_read_file.o mnt_idmapping.o remap_range.o pidfs.o \ 19 + file_attr.o 19 20 20 21 obj-$(CONFIG_BUFFER_HEAD) += buffer.o mpage.o 21 22 obj-$(CONFIG_PROC_FS) += proc_namespace.o
+319
fs/file_attr.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + #include <linux/fs.h> 3 + #include <linux/security.h> 4 + #include <linux/fscrypt.h> 5 + #include <linux/fileattr.h> 6 + #include <linux/export.h> 7 + 8 + /** 9 + * fileattr_fill_xflags - initialize fileattr with xflags 10 + * @fa: fileattr pointer 11 + * @xflags: FS_XFLAG_* flags 12 + * 13 + * Set ->fsx_xflags, ->fsx_valid and ->flags (translated xflags). All 14 + * other fields are zeroed. 15 + */ 16 + void fileattr_fill_xflags(struct fileattr *fa, u32 xflags) 17 + { 18 + memset(fa, 0, sizeof(*fa)); 19 + fa->fsx_valid = true; 20 + fa->fsx_xflags = xflags; 21 + if (fa->fsx_xflags & FS_XFLAG_IMMUTABLE) 22 + fa->flags |= FS_IMMUTABLE_FL; 23 + if (fa->fsx_xflags & FS_XFLAG_APPEND) 24 + fa->flags |= FS_APPEND_FL; 25 + if (fa->fsx_xflags & FS_XFLAG_SYNC) 26 + fa->flags |= FS_SYNC_FL; 27 + if (fa->fsx_xflags & FS_XFLAG_NOATIME) 28 + fa->flags |= FS_NOATIME_FL; 29 + if (fa->fsx_xflags & FS_XFLAG_NODUMP) 30 + fa->flags |= FS_NODUMP_FL; 31 + if (fa->fsx_xflags & FS_XFLAG_DAX) 32 + fa->flags |= FS_DAX_FL; 33 + if (fa->fsx_xflags & FS_XFLAG_PROJINHERIT) 34 + fa->flags |= FS_PROJINHERIT_FL; 35 + } 36 + EXPORT_SYMBOL(fileattr_fill_xflags); 37 + 38 + /** 39 + * fileattr_fill_flags - initialize fileattr with flags 40 + * @fa: fileattr pointer 41 + * @flags: FS_*_FL flags 42 + * 43 + * Set ->flags, ->flags_valid and ->fsx_xflags (translated flags). 44 + * All other fields are zeroed. 45 + */ 46 + void fileattr_fill_flags(struct fileattr *fa, u32 flags) 47 + { 48 + memset(fa, 0, sizeof(*fa)); 49 + fa->flags_valid = true; 50 + fa->flags = flags; 51 + if (fa->flags & FS_SYNC_FL) 52 + fa->fsx_xflags |= FS_XFLAG_SYNC; 53 + if (fa->flags & FS_IMMUTABLE_FL) 54 + fa->fsx_xflags |= FS_XFLAG_IMMUTABLE; 55 + if (fa->flags & FS_APPEND_FL) 56 + fa->fsx_xflags |= FS_XFLAG_APPEND; 57 + if (fa->flags & FS_NODUMP_FL) 58 + fa->fsx_xflags |= FS_XFLAG_NODUMP; 59 + if (fa->flags & FS_NOATIME_FL) 60 + fa->fsx_xflags |= FS_XFLAG_NOATIME; 61 + if (fa->flags & FS_DAX_FL) 62 + fa->fsx_xflags |= FS_XFLAG_DAX; 63 + if (fa->flags & FS_PROJINHERIT_FL) 64 + fa->fsx_xflags |= FS_XFLAG_PROJINHERIT; 65 + } 66 + EXPORT_SYMBOL(fileattr_fill_flags); 67 + 68 + /** 69 + * vfs_fileattr_get - retrieve miscellaneous file attributes 70 + * @dentry: the object to retrieve from 71 + * @fa: fileattr pointer 72 + * 73 + * Call i_op->fileattr_get() callback, if exists. 74 + * 75 + * Return: 0 on success, or a negative error on failure. 76 + */ 77 + int vfs_fileattr_get(struct dentry *dentry, struct fileattr *fa) 78 + { 79 + struct inode *inode = d_inode(dentry); 80 + 81 + if (!inode->i_op->fileattr_get) 82 + return -ENOIOCTLCMD; 83 + 84 + return inode->i_op->fileattr_get(dentry, fa); 85 + } 86 + EXPORT_SYMBOL(vfs_fileattr_get); 87 + 88 + /** 89 + * copy_fsxattr_to_user - copy fsxattr to userspace. 90 + * @fa: fileattr pointer 91 + * @ufa: fsxattr user pointer 92 + * 93 + * Return: 0 on success, or -EFAULT on failure. 94 + */ 95 + int copy_fsxattr_to_user(const struct fileattr *fa, struct fsxattr __user *ufa) 96 + { 97 + struct fsxattr xfa; 98 + 99 + memset(&xfa, 0, sizeof(xfa)); 100 + xfa.fsx_xflags = fa->fsx_xflags; 101 + xfa.fsx_extsize = fa->fsx_extsize; 102 + xfa.fsx_nextents = fa->fsx_nextents; 103 + xfa.fsx_projid = fa->fsx_projid; 104 + xfa.fsx_cowextsize = fa->fsx_cowextsize; 105 + 106 + if (copy_to_user(ufa, &xfa, sizeof(xfa))) 107 + return -EFAULT; 108 + 109 + return 0; 110 + } 111 + EXPORT_SYMBOL(copy_fsxattr_to_user); 112 + 113 + static int copy_fsxattr_from_user(struct fileattr *fa, 114 + struct fsxattr __user *ufa) 115 + { 116 + struct fsxattr xfa; 117 + 118 + if (copy_from_user(&xfa, ufa, sizeof(xfa))) 119 + return -EFAULT; 120 + 121 + fileattr_fill_xflags(fa, xfa.fsx_xflags); 122 + fa->fsx_extsize = xfa.fsx_extsize; 123 + fa->fsx_nextents = xfa.fsx_nextents; 124 + fa->fsx_projid = xfa.fsx_projid; 125 + fa->fsx_cowextsize = xfa.fsx_cowextsize; 126 + 127 + return 0; 128 + } 129 + 130 + /* 131 + * Generic function to check FS_IOC_FSSETXATTR/FS_IOC_SETFLAGS values and reject 132 + * any invalid configurations. 133 + * 134 + * Note: must be called with inode lock held. 135 + */ 136 + static int fileattr_set_prepare(struct inode *inode, 137 + const struct fileattr *old_ma, 138 + struct fileattr *fa) 139 + { 140 + int err; 141 + 142 + /* 143 + * The IMMUTABLE and APPEND_ONLY flags can only be changed by 144 + * the relevant capability. 145 + */ 146 + if ((fa->flags ^ old_ma->flags) & (FS_APPEND_FL | FS_IMMUTABLE_FL) && 147 + !capable(CAP_LINUX_IMMUTABLE)) 148 + return -EPERM; 149 + 150 + err = fscrypt_prepare_setflags(inode, old_ma->flags, fa->flags); 151 + if (err) 152 + return err; 153 + 154 + /* 155 + * Project Quota ID state is only allowed to change from within the init 156 + * namespace. Enforce that restriction only if we are trying to change 157 + * the quota ID state. Everything else is allowed in user namespaces. 158 + */ 159 + if (current_user_ns() != &init_user_ns) { 160 + if (old_ma->fsx_projid != fa->fsx_projid) 161 + return -EINVAL; 162 + if ((old_ma->fsx_xflags ^ fa->fsx_xflags) & 163 + FS_XFLAG_PROJINHERIT) 164 + return -EINVAL; 165 + } else { 166 + /* 167 + * Caller is allowed to change the project ID. If it is being 168 + * changed, make sure that the new value is valid. 169 + */ 170 + if (old_ma->fsx_projid != fa->fsx_projid && 171 + !projid_valid(make_kprojid(&init_user_ns, fa->fsx_projid))) 172 + return -EINVAL; 173 + } 174 + 175 + /* Check extent size hints. */ 176 + if ((fa->fsx_xflags & FS_XFLAG_EXTSIZE) && !S_ISREG(inode->i_mode)) 177 + return -EINVAL; 178 + 179 + if ((fa->fsx_xflags & FS_XFLAG_EXTSZINHERIT) && 180 + !S_ISDIR(inode->i_mode)) 181 + return -EINVAL; 182 + 183 + if ((fa->fsx_xflags & FS_XFLAG_COWEXTSIZE) && 184 + !S_ISREG(inode->i_mode) && !S_ISDIR(inode->i_mode)) 185 + return -EINVAL; 186 + 187 + /* 188 + * It is only valid to set the DAX flag on regular files and 189 + * directories on filesystems. 190 + */ 191 + if ((fa->fsx_xflags & FS_XFLAG_DAX) && 192 + !(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode))) 193 + return -EINVAL; 194 + 195 + /* Extent size hints of zero turn off the flags. */ 196 + if (fa->fsx_extsize == 0) 197 + fa->fsx_xflags &= ~(FS_XFLAG_EXTSIZE | FS_XFLAG_EXTSZINHERIT); 198 + if (fa->fsx_cowextsize == 0) 199 + fa->fsx_xflags &= ~FS_XFLAG_COWEXTSIZE; 200 + 201 + return 0; 202 + } 203 + 204 + /** 205 + * vfs_fileattr_set - change miscellaneous file attributes 206 + * @idmap: idmap of the mount 207 + * @dentry: the object to change 208 + * @fa: fileattr pointer 209 + * 210 + * After verifying permissions, call i_op->fileattr_set() callback, if 211 + * exists. 212 + * 213 + * Verifying attributes involves retrieving current attributes with 214 + * i_op->fileattr_get(), this also allows initializing attributes that have 215 + * not been set by the caller to current values. Inode lock is held 216 + * thoughout to prevent racing with another instance. 217 + * 218 + * Return: 0 on success, or a negative error on failure. 219 + */ 220 + int vfs_fileattr_set(struct mnt_idmap *idmap, struct dentry *dentry, 221 + struct fileattr *fa) 222 + { 223 + struct inode *inode = d_inode(dentry); 224 + struct fileattr old_ma = {}; 225 + int err; 226 + 227 + if (!inode->i_op->fileattr_set) 228 + return -ENOIOCTLCMD; 229 + 230 + if (!inode_owner_or_capable(idmap, inode)) 231 + return -EPERM; 232 + 233 + inode_lock(inode); 234 + err = vfs_fileattr_get(dentry, &old_ma); 235 + if (!err) { 236 + /* initialize missing bits from old_ma */ 237 + if (fa->flags_valid) { 238 + fa->fsx_xflags |= old_ma.fsx_xflags & ~FS_XFLAG_COMMON; 239 + fa->fsx_extsize = old_ma.fsx_extsize; 240 + fa->fsx_nextents = old_ma.fsx_nextents; 241 + fa->fsx_projid = old_ma.fsx_projid; 242 + fa->fsx_cowextsize = old_ma.fsx_cowextsize; 243 + } else { 244 + fa->flags |= old_ma.flags & ~FS_COMMON_FL; 245 + } 246 + err = fileattr_set_prepare(inode, &old_ma, fa); 247 + if (!err) 248 + err = inode->i_op->fileattr_set(idmap, dentry, fa); 249 + } 250 + inode_unlock(inode); 251 + 252 + return err; 253 + } 254 + EXPORT_SYMBOL(vfs_fileattr_set); 255 + 256 + int ioctl_getflags(struct file *file, unsigned int __user *argp) 257 + { 258 + struct fileattr fa = { .flags_valid = true }; /* hint only */ 259 + int err; 260 + 261 + err = vfs_fileattr_get(file->f_path.dentry, &fa); 262 + if (!err) 263 + err = put_user(fa.flags, argp); 264 + return err; 265 + } 266 + EXPORT_SYMBOL(ioctl_getflags); 267 + 268 + int ioctl_setflags(struct file *file, unsigned int __user *argp) 269 + { 270 + struct mnt_idmap *idmap = file_mnt_idmap(file); 271 + struct dentry *dentry = file->f_path.dentry; 272 + struct fileattr fa; 273 + unsigned int flags; 274 + int err; 275 + 276 + err = get_user(flags, argp); 277 + if (!err) { 278 + err = mnt_want_write_file(file); 279 + if (!err) { 280 + fileattr_fill_flags(&fa, flags); 281 + err = vfs_fileattr_set(idmap, dentry, &fa); 282 + mnt_drop_write_file(file); 283 + } 284 + } 285 + return err; 286 + } 287 + EXPORT_SYMBOL(ioctl_setflags); 288 + 289 + int ioctl_fsgetxattr(struct file *file, void __user *argp) 290 + { 291 + struct fileattr fa = { .fsx_valid = true }; /* hint only */ 292 + int err; 293 + 294 + err = vfs_fileattr_get(file->f_path.dentry, &fa); 295 + if (!err) 296 + err = copy_fsxattr_to_user(&fa, argp); 297 + 298 + return err; 299 + } 300 + EXPORT_SYMBOL(ioctl_fsgetxattr); 301 + 302 + int ioctl_fssetxattr(struct file *file, void __user *argp) 303 + { 304 + struct mnt_idmap *idmap = file_mnt_idmap(file); 305 + struct dentry *dentry = file->f_path.dentry; 306 + struct fileattr fa; 307 + int err; 308 + 309 + err = copy_fsxattr_from_user(&fa, argp); 310 + if (!err) { 311 + err = mnt_want_write_file(file); 312 + if (!err) { 313 + err = vfs_fileattr_set(idmap, dentry, &fa); 314 + mnt_drop_write_file(file); 315 + } 316 + } 317 + return err; 318 + } 319 + EXPORT_SYMBOL(ioctl_fssetxattr);
-309
fs/ioctl.c
··· 453 453 return ret; 454 454 } 455 455 456 - /** 457 - * fileattr_fill_xflags - initialize fileattr with xflags 458 - * @fa: fileattr pointer 459 - * @xflags: FS_XFLAG_* flags 460 - * 461 - * Set ->fsx_xflags, ->fsx_valid and ->flags (translated xflags). All 462 - * other fields are zeroed. 463 - */ 464 - void fileattr_fill_xflags(struct fileattr *fa, u32 xflags) 465 - { 466 - memset(fa, 0, sizeof(*fa)); 467 - fa->fsx_valid = true; 468 - fa->fsx_xflags = xflags; 469 - if (fa->fsx_xflags & FS_XFLAG_IMMUTABLE) 470 - fa->flags |= FS_IMMUTABLE_FL; 471 - if (fa->fsx_xflags & FS_XFLAG_APPEND) 472 - fa->flags |= FS_APPEND_FL; 473 - if (fa->fsx_xflags & FS_XFLAG_SYNC) 474 - fa->flags |= FS_SYNC_FL; 475 - if (fa->fsx_xflags & FS_XFLAG_NOATIME) 476 - fa->flags |= FS_NOATIME_FL; 477 - if (fa->fsx_xflags & FS_XFLAG_NODUMP) 478 - fa->flags |= FS_NODUMP_FL; 479 - if (fa->fsx_xflags & FS_XFLAG_DAX) 480 - fa->flags |= FS_DAX_FL; 481 - if (fa->fsx_xflags & FS_XFLAG_PROJINHERIT) 482 - fa->flags |= FS_PROJINHERIT_FL; 483 - } 484 - EXPORT_SYMBOL(fileattr_fill_xflags); 485 - 486 - /** 487 - * fileattr_fill_flags - initialize fileattr with flags 488 - * @fa: fileattr pointer 489 - * @flags: FS_*_FL flags 490 - * 491 - * Set ->flags, ->flags_valid and ->fsx_xflags (translated flags). 492 - * All other fields are zeroed. 493 - */ 494 - void fileattr_fill_flags(struct fileattr *fa, u32 flags) 495 - { 496 - memset(fa, 0, sizeof(*fa)); 497 - fa->flags_valid = true; 498 - fa->flags = flags; 499 - if (fa->flags & FS_SYNC_FL) 500 - fa->fsx_xflags |= FS_XFLAG_SYNC; 501 - if (fa->flags & FS_IMMUTABLE_FL) 502 - fa->fsx_xflags |= FS_XFLAG_IMMUTABLE; 503 - if (fa->flags & FS_APPEND_FL) 504 - fa->fsx_xflags |= FS_XFLAG_APPEND; 505 - if (fa->flags & FS_NODUMP_FL) 506 - fa->fsx_xflags |= FS_XFLAG_NODUMP; 507 - if (fa->flags & FS_NOATIME_FL) 508 - fa->fsx_xflags |= FS_XFLAG_NOATIME; 509 - if (fa->flags & FS_DAX_FL) 510 - fa->fsx_xflags |= FS_XFLAG_DAX; 511 - if (fa->flags & FS_PROJINHERIT_FL) 512 - fa->fsx_xflags |= FS_XFLAG_PROJINHERIT; 513 - } 514 - EXPORT_SYMBOL(fileattr_fill_flags); 515 - 516 - /** 517 - * vfs_fileattr_get - retrieve miscellaneous file attributes 518 - * @dentry: the object to retrieve from 519 - * @fa: fileattr pointer 520 - * 521 - * Call i_op->fileattr_get() callback, if exists. 522 - * 523 - * Return: 0 on success, or a negative error on failure. 524 - */ 525 - int vfs_fileattr_get(struct dentry *dentry, struct fileattr *fa) 526 - { 527 - struct inode *inode = d_inode(dentry); 528 - 529 - if (!inode->i_op->fileattr_get) 530 - return -ENOIOCTLCMD; 531 - 532 - return inode->i_op->fileattr_get(dentry, fa); 533 - } 534 - EXPORT_SYMBOL(vfs_fileattr_get); 535 - 536 - /** 537 - * copy_fsxattr_to_user - copy fsxattr to userspace. 538 - * @fa: fileattr pointer 539 - * @ufa: fsxattr user pointer 540 - * 541 - * Return: 0 on success, or -EFAULT on failure. 542 - */ 543 - int copy_fsxattr_to_user(const struct fileattr *fa, struct fsxattr __user *ufa) 544 - { 545 - struct fsxattr xfa; 546 - 547 - memset(&xfa, 0, sizeof(xfa)); 548 - xfa.fsx_xflags = fa->fsx_xflags; 549 - xfa.fsx_extsize = fa->fsx_extsize; 550 - xfa.fsx_nextents = fa->fsx_nextents; 551 - xfa.fsx_projid = fa->fsx_projid; 552 - xfa.fsx_cowextsize = fa->fsx_cowextsize; 553 - 554 - if (copy_to_user(ufa, &xfa, sizeof(xfa))) 555 - return -EFAULT; 556 - 557 - return 0; 558 - } 559 - EXPORT_SYMBOL(copy_fsxattr_to_user); 560 - 561 - static int copy_fsxattr_from_user(struct fileattr *fa, 562 - struct fsxattr __user *ufa) 563 - { 564 - struct fsxattr xfa; 565 - 566 - if (copy_from_user(&xfa, ufa, sizeof(xfa))) 567 - return -EFAULT; 568 - 569 - fileattr_fill_xflags(fa, xfa.fsx_xflags); 570 - fa->fsx_extsize = xfa.fsx_extsize; 571 - fa->fsx_nextents = xfa.fsx_nextents; 572 - fa->fsx_projid = xfa.fsx_projid; 573 - fa->fsx_cowextsize = xfa.fsx_cowextsize; 574 - 575 - return 0; 576 - } 577 - 578 - /* 579 - * Generic function to check FS_IOC_FSSETXATTR/FS_IOC_SETFLAGS values and reject 580 - * any invalid configurations. 581 - * 582 - * Note: must be called with inode lock held. 583 - */ 584 - static int fileattr_set_prepare(struct inode *inode, 585 - const struct fileattr *old_ma, 586 - struct fileattr *fa) 587 - { 588 - int err; 589 - 590 - /* 591 - * The IMMUTABLE and APPEND_ONLY flags can only be changed by 592 - * the relevant capability. 593 - */ 594 - if ((fa->flags ^ old_ma->flags) & (FS_APPEND_FL | FS_IMMUTABLE_FL) && 595 - !capable(CAP_LINUX_IMMUTABLE)) 596 - return -EPERM; 597 - 598 - err = fscrypt_prepare_setflags(inode, old_ma->flags, fa->flags); 599 - if (err) 600 - return err; 601 - 602 - /* 603 - * Project Quota ID state is only allowed to change from within the init 604 - * namespace. Enforce that restriction only if we are trying to change 605 - * the quota ID state. Everything else is allowed in user namespaces. 606 - */ 607 - if (current_user_ns() != &init_user_ns) { 608 - if (old_ma->fsx_projid != fa->fsx_projid) 609 - return -EINVAL; 610 - if ((old_ma->fsx_xflags ^ fa->fsx_xflags) & 611 - FS_XFLAG_PROJINHERIT) 612 - return -EINVAL; 613 - } else { 614 - /* 615 - * Caller is allowed to change the project ID. If it is being 616 - * changed, make sure that the new value is valid. 617 - */ 618 - if (old_ma->fsx_projid != fa->fsx_projid && 619 - !projid_valid(make_kprojid(&init_user_ns, fa->fsx_projid))) 620 - return -EINVAL; 621 - } 622 - 623 - /* Check extent size hints. */ 624 - if ((fa->fsx_xflags & FS_XFLAG_EXTSIZE) && !S_ISREG(inode->i_mode)) 625 - return -EINVAL; 626 - 627 - if ((fa->fsx_xflags & FS_XFLAG_EXTSZINHERIT) && 628 - !S_ISDIR(inode->i_mode)) 629 - return -EINVAL; 630 - 631 - if ((fa->fsx_xflags & FS_XFLAG_COWEXTSIZE) && 632 - !S_ISREG(inode->i_mode) && !S_ISDIR(inode->i_mode)) 633 - return -EINVAL; 634 - 635 - /* 636 - * It is only valid to set the DAX flag on regular files and 637 - * directories on filesystems. 638 - */ 639 - if ((fa->fsx_xflags & FS_XFLAG_DAX) && 640 - !(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode))) 641 - return -EINVAL; 642 - 643 - /* Extent size hints of zero turn off the flags. */ 644 - if (fa->fsx_extsize == 0) 645 - fa->fsx_xflags &= ~(FS_XFLAG_EXTSIZE | FS_XFLAG_EXTSZINHERIT); 646 - if (fa->fsx_cowextsize == 0) 647 - fa->fsx_xflags &= ~FS_XFLAG_COWEXTSIZE; 648 - 649 - return 0; 650 - } 651 - 652 - /** 653 - * vfs_fileattr_set - change miscellaneous file attributes 654 - * @idmap: idmap of the mount 655 - * @dentry: the object to change 656 - * @fa: fileattr pointer 657 - * 658 - * After verifying permissions, call i_op->fileattr_set() callback, if 659 - * exists. 660 - * 661 - * Verifying attributes involves retrieving current attributes with 662 - * i_op->fileattr_get(), this also allows initializing attributes that have 663 - * not been set by the caller to current values. Inode lock is held 664 - * thoughout to prevent racing with another instance. 665 - * 666 - * Return: 0 on success, or a negative error on failure. 667 - */ 668 - int vfs_fileattr_set(struct mnt_idmap *idmap, struct dentry *dentry, 669 - struct fileattr *fa) 670 - { 671 - struct inode *inode = d_inode(dentry); 672 - struct fileattr old_ma = {}; 673 - int err; 674 - 675 - if (!inode->i_op->fileattr_set) 676 - return -ENOIOCTLCMD; 677 - 678 - if (!inode_owner_or_capable(idmap, inode)) 679 - return -EPERM; 680 - 681 - inode_lock(inode); 682 - err = vfs_fileattr_get(dentry, &old_ma); 683 - if (!err) { 684 - /* initialize missing bits from old_ma */ 685 - if (fa->flags_valid) { 686 - fa->fsx_xflags |= old_ma.fsx_xflags & ~FS_XFLAG_COMMON; 687 - fa->fsx_extsize = old_ma.fsx_extsize; 688 - fa->fsx_nextents = old_ma.fsx_nextents; 689 - fa->fsx_projid = old_ma.fsx_projid; 690 - fa->fsx_cowextsize = old_ma.fsx_cowextsize; 691 - } else { 692 - fa->flags |= old_ma.flags & ~FS_COMMON_FL; 693 - } 694 - err = fileattr_set_prepare(inode, &old_ma, fa); 695 - if (!err) 696 - err = inode->i_op->fileattr_set(idmap, dentry, fa); 697 - } 698 - inode_unlock(inode); 699 - 700 - return err; 701 - } 702 - EXPORT_SYMBOL(vfs_fileattr_set); 703 - 704 - static int ioctl_getflags(struct file *file, unsigned int __user *argp) 705 - { 706 - struct fileattr fa = { .flags_valid = true }; /* hint only */ 707 - int err; 708 - 709 - err = vfs_fileattr_get(file->f_path.dentry, &fa); 710 - if (!err) 711 - err = put_user(fa.flags, argp); 712 - return err; 713 - } 714 - 715 - static int ioctl_setflags(struct file *file, unsigned int __user *argp) 716 - { 717 - struct mnt_idmap *idmap = file_mnt_idmap(file); 718 - struct dentry *dentry = file->f_path.dentry; 719 - struct fileattr fa; 720 - unsigned int flags; 721 - int err; 722 - 723 - err = get_user(flags, argp); 724 - if (!err) { 725 - err = mnt_want_write_file(file); 726 - if (!err) { 727 - fileattr_fill_flags(&fa, flags); 728 - err = vfs_fileattr_set(idmap, dentry, &fa); 729 - mnt_drop_write_file(file); 730 - } 731 - } 732 - return err; 733 - } 734 - 735 - static int ioctl_fsgetxattr(struct file *file, void __user *argp) 736 - { 737 - struct fileattr fa = { .fsx_valid = true }; /* hint only */ 738 - int err; 739 - 740 - err = vfs_fileattr_get(file->f_path.dentry, &fa); 741 - if (!err) 742 - err = copy_fsxattr_to_user(&fa, argp); 743 - 744 - return err; 745 - } 746 - 747 - static int ioctl_fssetxattr(struct file *file, void __user *argp) 748 - { 749 - struct mnt_idmap *idmap = file_mnt_idmap(file); 750 - struct dentry *dentry = file->f_path.dentry; 751 - struct fileattr fa; 752 - int err; 753 - 754 - err = copy_fsxattr_from_user(&fa, argp); 755 - if (!err) { 756 - err = mnt_want_write_file(file); 757 - if (!err) { 758 - err = vfs_fileattr_set(idmap, dentry, &fa); 759 - mnt_drop_write_file(file); 760 - } 761 - } 762 - return err; 763 - } 764 - 765 456 static int ioctl_getfsuuid(struct file *file, void __user *argp) 766 457 { 767 458 struct super_block *sb = file_inode(file)->i_sb;
+4
include/linux/fileattr.h
··· 55 55 int vfs_fileattr_get(struct dentry *dentry, struct fileattr *fa); 56 56 int vfs_fileattr_set(struct mnt_idmap *idmap, struct dentry *dentry, 57 57 struct fileattr *fa); 58 + int ioctl_getflags(struct file *file, unsigned int __user *argp); 59 + int ioctl_setflags(struct file *file, unsigned int __user *argp); 60 + int ioctl_fsgetxattr(struct file *file, void __user *argp); 61 + int ioctl_fssetxattr(struct file *file, void __user *argp); 58 62 59 63 #endif /* _LINUX_FILEATTR_H */