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/fsnotify.h> 6 #include <linux/fileattr.h> 7 #include <linux/export.h> 8 #include <linux/syscalls.h> 9 #include <linux/namei.h> 10 11 #include "internal.h" 12 13 /** 14 * fileattr_fill_xflags - initialize fileattr with xflags 15 * @fa: fileattr pointer 16 * @xflags: FS_XFLAG_* flags 17 * 18 * Set ->fsx_xflags, ->fsx_valid and ->flags (translated xflags). 19 */ 20 void fileattr_fill_xflags(struct file_kattr *fa, u32 xflags) 21 { 22 fa->fsx_valid = true; 23 fa->fsx_xflags = xflags; 24 if (fa->fsx_xflags & FS_XFLAG_IMMUTABLE) 25 fa->flags |= FS_IMMUTABLE_FL; 26 if (fa->fsx_xflags & FS_XFLAG_APPEND) 27 fa->flags |= FS_APPEND_FL; 28 if (fa->fsx_xflags & FS_XFLAG_SYNC) 29 fa->flags |= FS_SYNC_FL; 30 if (fa->fsx_xflags & FS_XFLAG_NOATIME) 31 fa->flags |= FS_NOATIME_FL; 32 if (fa->fsx_xflags & FS_XFLAG_NODUMP) 33 fa->flags |= FS_NODUMP_FL; 34 if (fa->fsx_xflags & FS_XFLAG_DAX) 35 fa->flags |= FS_DAX_FL; 36 if (fa->fsx_xflags & FS_XFLAG_PROJINHERIT) 37 fa->flags |= FS_PROJINHERIT_FL; 38 if (fa->fsx_xflags & FS_XFLAG_VERITY) 39 fa->flags |= FS_VERITY_FL; 40 if (fa->fsx_xflags & FS_XFLAG_CASEFOLD) 41 fa->flags |= FS_CASEFOLD_FL; 42 } 43 EXPORT_SYMBOL(fileattr_fill_xflags); 44 45 /** 46 * fileattr_fill_flags - initialize fileattr with flags 47 * @fa: fileattr pointer 48 * @flags: FS_*_FL flags 49 * 50 * Set ->flags, ->flags_valid and ->fsx_xflags (translated flags). 51 */ 52 void fileattr_fill_flags(struct file_kattr *fa, u32 flags) 53 { 54 fa->flags_valid = true; 55 fa->flags = flags; 56 if (fa->flags & FS_SYNC_FL) 57 fa->fsx_xflags |= FS_XFLAG_SYNC; 58 if (fa->flags & FS_IMMUTABLE_FL) 59 fa->fsx_xflags |= FS_XFLAG_IMMUTABLE; 60 if (fa->flags & FS_APPEND_FL) 61 fa->fsx_xflags |= FS_XFLAG_APPEND; 62 if (fa->flags & FS_NODUMP_FL) 63 fa->fsx_xflags |= FS_XFLAG_NODUMP; 64 if (fa->flags & FS_NOATIME_FL) 65 fa->fsx_xflags |= FS_XFLAG_NOATIME; 66 if (fa->flags & FS_DAX_FL) 67 fa->fsx_xflags |= FS_XFLAG_DAX; 68 if (fa->flags & FS_PROJINHERIT_FL) 69 fa->fsx_xflags |= FS_XFLAG_PROJINHERIT; 70 if (fa->flags & FS_VERITY_FL) 71 fa->fsx_xflags |= FS_XFLAG_VERITY; 72 if (fa->flags & FS_CASEFOLD_FL) 73 fa->fsx_xflags |= FS_XFLAG_CASEFOLD; 74 } 75 EXPORT_SYMBOL(fileattr_fill_flags); 76 77 /** 78 * vfs_fileattr_get - retrieve miscellaneous file attributes 79 * @dentry: the object to retrieve from 80 * @fa: fileattr pointer 81 * 82 * Call i_op->fileattr_get() callback, if exists. 83 * 84 * Return: 0 on success, or a negative error on failure. 85 */ 86 int vfs_fileattr_get(struct dentry *dentry, struct file_kattr *fa) 87 { 88 struct inode *inode = d_inode(dentry); 89 int error; 90 91 if (!inode->i_op->fileattr_get) 92 return -ENOIOCTLCMD; 93 94 error = security_inode_file_getattr(dentry, fa); 95 if (error) 96 return error; 97 98 return inode->i_op->fileattr_get(dentry, fa); 99 } 100 EXPORT_SYMBOL(vfs_fileattr_get); 101 102 static void fileattr_to_file_attr(const struct file_kattr *fa, 103 struct file_attr *fattr) 104 { 105 __u32 mask = FS_XFLAGS_MASK; 106 107 memset(fattr, 0, sizeof(struct file_attr)); 108 fattr->fa_xflags = fa->fsx_xflags & mask; 109 fattr->fa_extsize = fa->fsx_extsize; 110 fattr->fa_nextents = fa->fsx_nextents; 111 fattr->fa_projid = fa->fsx_projid; 112 fattr->fa_cowextsize = fa->fsx_cowextsize; 113 } 114 115 /** 116 * copy_fsxattr_to_user - copy fsxattr to userspace. 117 * @fa: fileattr pointer 118 * @ufa: fsxattr user pointer 119 * 120 * Return: 0 on success, or -EFAULT on failure. 121 */ 122 int copy_fsxattr_to_user(const struct file_kattr *fa, struct fsxattr __user *ufa) 123 { 124 struct fsxattr xfa; 125 __u32 mask = FS_XFLAGS_MASK; 126 127 memset(&xfa, 0, sizeof(xfa)); 128 xfa.fsx_xflags = fa->fsx_xflags & mask; 129 xfa.fsx_extsize = fa->fsx_extsize; 130 xfa.fsx_nextents = fa->fsx_nextents; 131 xfa.fsx_projid = fa->fsx_projid; 132 xfa.fsx_cowextsize = fa->fsx_cowextsize; 133 134 if (copy_to_user(ufa, &xfa, sizeof(xfa))) 135 return -EFAULT; 136 137 return 0; 138 } 139 EXPORT_SYMBOL(copy_fsxattr_to_user); 140 141 static int file_attr_to_fileattr(const struct file_attr *fattr, 142 struct file_kattr *fa) 143 { 144 __u64 mask = FS_XFLAGS_MASK; 145 146 if (fattr->fa_xflags & ~mask) 147 return -EINVAL; 148 149 fileattr_fill_xflags(fa, fattr->fa_xflags & ~FS_XFLAG_RDONLY_MASK); 150 fa->fsx_extsize = fattr->fa_extsize; 151 fa->fsx_projid = fattr->fa_projid; 152 fa->fsx_cowextsize = fattr->fa_cowextsize; 153 154 return 0; 155 } 156 157 static int copy_fsxattr_from_user(struct file_kattr *fa, 158 struct fsxattr __user *ufa) 159 { 160 struct fsxattr xfa; 161 __u32 mask = FS_XFLAGS_MASK; 162 163 if (copy_from_user(&xfa, ufa, sizeof(xfa))) 164 return -EFAULT; 165 166 if (xfa.fsx_xflags & ~mask) 167 return -EOPNOTSUPP; 168 169 fileattr_fill_xflags(fa, xfa.fsx_xflags & ~FS_XFLAG_RDONLY_MASK); 170 fa->fsx_extsize = xfa.fsx_extsize; 171 fa->fsx_nextents = xfa.fsx_nextents; 172 fa->fsx_projid = xfa.fsx_projid; 173 fa->fsx_cowextsize = xfa.fsx_cowextsize; 174 175 return 0; 176 } 177 178 /* 179 * Generic function to check FS_IOC_FSSETXATTR/FS_IOC_SETFLAGS values and reject 180 * any invalid configurations. 181 * 182 * Note: must be called with inode lock held. 183 */ 184 static int fileattr_set_prepare(struct inode *inode, 185 const struct file_kattr *old_ma, 186 struct file_kattr *fa) 187 { 188 int err; 189 190 /* 191 * The IMMUTABLE and APPEND_ONLY flags can only be changed by 192 * the relevant capability. 193 */ 194 if ((fa->flags ^ old_ma->flags) & (FS_APPEND_FL | FS_IMMUTABLE_FL) && 195 !capable(CAP_LINUX_IMMUTABLE)) 196 return -EPERM; 197 198 err = fscrypt_prepare_setflags(inode, old_ma->flags, fa->flags); 199 if (err) 200 return err; 201 202 /* 203 * Project Quota ID state is only allowed to change from within the init 204 * namespace. Enforce that restriction only if we are trying to change 205 * the quota ID state. Everything else is allowed in user namespaces. 206 */ 207 if (current_user_ns() != &init_user_ns) { 208 if (old_ma->fsx_projid != fa->fsx_projid) 209 return -EINVAL; 210 if ((old_ma->fsx_xflags ^ fa->fsx_xflags) & 211 FS_XFLAG_PROJINHERIT) 212 return -EINVAL; 213 } else { 214 /* 215 * Caller is allowed to change the project ID. If it is being 216 * changed, make sure that the new value is valid. 217 */ 218 if (old_ma->fsx_projid != fa->fsx_projid && 219 !projid_valid(make_kprojid(&init_user_ns, fa->fsx_projid))) 220 return -EINVAL; 221 } 222 223 /* Check extent size hints. */ 224 if ((fa->fsx_xflags & FS_XFLAG_EXTSIZE) && !S_ISREG(inode->i_mode)) 225 return -EINVAL; 226 227 if ((fa->fsx_xflags & FS_XFLAG_EXTSZINHERIT) && 228 !S_ISDIR(inode->i_mode)) 229 return -EINVAL; 230 231 if ((fa->fsx_xflags & FS_XFLAG_COWEXTSIZE) && 232 !S_ISREG(inode->i_mode) && !S_ISDIR(inode->i_mode)) 233 return -EINVAL; 234 235 /* 236 * It is only valid to set the DAX flag on regular files and 237 * directories on filesystems. 238 * 239 * DAX and fsverity are incompatible. 240 */ 241 if (fa->fsx_xflags & FS_XFLAG_DAX) { 242 if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode))) 243 return -EINVAL; 244 if (old_ma->fsx_xflags & FS_XFLAG_VERITY) 245 return -EINVAL; 246 } 247 248 /* Extent size hints of zero turn off the flags. */ 249 if (fa->fsx_extsize == 0) 250 fa->fsx_xflags &= ~(FS_XFLAG_EXTSIZE | FS_XFLAG_EXTSZINHERIT); 251 if (fa->fsx_cowextsize == 0) 252 fa->fsx_xflags &= ~FS_XFLAG_COWEXTSIZE; 253 254 return 0; 255 } 256 257 /** 258 * vfs_fileattr_set - change miscellaneous file attributes 259 * @idmap: idmap of the mount 260 * @dentry: the object to change 261 * @fa: fileattr pointer 262 * 263 * After verifying permissions, call i_op->fileattr_set() callback, if 264 * exists. 265 * 266 * Verifying attributes involves retrieving current attributes with 267 * i_op->fileattr_get(), this also allows initializing attributes that have 268 * not been set by the caller to current values. Inode lock is held 269 * thoughout to prevent racing with another instance. 270 * 271 * Return: 0 on success, or a negative error on failure. 272 */ 273 int vfs_fileattr_set(const struct mnt_idmap *idmap, struct dentry *dentry, 274 struct file_kattr *fa) 275 { 276 struct inode *inode = d_inode(dentry); 277 struct file_kattr old_ma = {}; 278 int err; 279 280 if (!inode->i_op->fileattr_set) 281 return -ENOIOCTLCMD; 282 283 if (!inode_owner_or_capable(idmap, inode)) 284 return -EPERM; 285 286 inode_lock(inode); 287 err = vfs_fileattr_get(dentry, &old_ma); 288 if (!err) { 289 /* initialize missing bits from old_ma */ 290 if (fa->flags_valid) { 291 fa->fsx_xflags |= old_ma.fsx_xflags & ~FS_XFLAG_COMMON; 292 fa->fsx_extsize = old_ma.fsx_extsize; 293 fa->fsx_nextents = old_ma.fsx_nextents; 294 fa->fsx_projid = old_ma.fsx_projid; 295 fa->fsx_cowextsize = old_ma.fsx_cowextsize; 296 } else { 297 fa->flags |= old_ma.flags & ~FS_COMMON_FL; 298 } 299 300 err = fileattr_set_prepare(inode, &old_ma, fa); 301 if (err) 302 goto out; 303 err = security_inode_file_setattr(dentry, fa); 304 if (err) 305 goto out; 306 err = inode->i_op->fileattr_set(idmap, dentry, fa); 307 if (err) 308 goto out; 309 fsnotify_xattr(dentry); 310 } 311 312 out: 313 inode_unlock(inode); 314 return err; 315 } 316 EXPORT_SYMBOL(vfs_fileattr_set); 317 318 int ioctl_getflags(struct file *file, unsigned int __user *argp) 319 { 320 struct file_kattr fa = { .flags_valid = true }; /* hint only */ 321 int err; 322 323 err = vfs_fileattr_get(file->f_path.dentry, &fa); 324 if (!err) 325 err = put_user(fa.flags, argp); 326 return err; 327 } 328 329 int ioctl_setflags(struct file *file, unsigned int __user *argp) 330 { 331 const struct mnt_idmap *idmap = file_mnt_idmap(file); 332 struct dentry *dentry = file->f_path.dentry; 333 struct file_kattr fa = {}; 334 unsigned int flags; 335 int err; 336 337 err = get_user(flags, argp); 338 if (!err) { 339 err = mnt_want_write_file(file); 340 if (!err) { 341 fileattr_fill_flags(&fa, flags); 342 err = vfs_fileattr_set(idmap, dentry, &fa); 343 mnt_drop_write_file(file); 344 } 345 } 346 return err; 347 } 348 349 int ioctl_fsgetxattr(struct file *file, void __user *argp) 350 { 351 struct file_kattr fa = { .fsx_valid = true }; /* hint only */ 352 int err; 353 354 err = vfs_fileattr_get(file->f_path.dentry, &fa); 355 if (!err) 356 err = copy_fsxattr_to_user(&fa, argp); 357 358 return err; 359 } 360 361 int ioctl_fssetxattr(struct file *file, void __user *argp) 362 { 363 const struct mnt_idmap *idmap = file_mnt_idmap(file); 364 struct dentry *dentry = file->f_path.dentry; 365 struct file_kattr fa = {}; 366 int err; 367 368 err = copy_fsxattr_from_user(&fa, argp); 369 if (!err) { 370 err = mnt_want_write_file(file); 371 if (!err) { 372 err = vfs_fileattr_set(idmap, dentry, &fa); 373 mnt_drop_write_file(file); 374 } 375 } 376 return err; 377 } 378 379 SYSCALL_DEFINE5(file_getattr, int, dfd, const char __user *, filename, 380 struct file_attr __user *, ufattr, size_t, usize, 381 unsigned int, at_flags) 382 { 383 struct path filepath __free(path_put) = {}; 384 unsigned int lookup_flags = 0; 385 struct file_attr fattr; 386 struct file_kattr fa = { .flags_valid = true }; /* hint only */ 387 int error; 388 389 BUILD_BUG_ON(sizeof(struct file_attr) < FILE_ATTR_SIZE_VER0); 390 BUILD_BUG_ON(sizeof(struct file_attr) != FILE_ATTR_SIZE_LATEST); 391 392 if ((at_flags & ~(AT_SYMLINK_NOFOLLOW | AT_EMPTY_PATH)) != 0) 393 return -EINVAL; 394 395 if (!(at_flags & AT_SYMLINK_NOFOLLOW)) 396 lookup_flags |= LOOKUP_FOLLOW; 397 398 if (usize > PAGE_SIZE) 399 return -E2BIG; 400 401 if (usize < FILE_ATTR_SIZE_VER0) 402 return -EINVAL; 403 404 CLASS(filename_maybe_null, name)(filename, at_flags); 405 if (!name && dfd >= 0) { 406 CLASS(fd, f)(dfd); 407 if (fd_empty(f)) 408 return -EBADF; 409 410 filepath = fd_file(f)->f_path; 411 path_get(&filepath); 412 } else { 413 error = filename_lookup(dfd, name, lookup_flags, &filepath, 414 NULL); 415 if (error) 416 return error; 417 } 418 419 error = vfs_fileattr_get(filepath.dentry, &fa); 420 if (error == -ENOIOCTLCMD || error == -ENOTTY) 421 error = -EOPNOTSUPP; 422 if (error) 423 return error; 424 425 fileattr_to_file_attr(&fa, &fattr); 426 error = copy_struct_to_user(ufattr, usize, &fattr, 427 sizeof(struct file_attr), NULL); 428 429 return error; 430 } 431 432 SYSCALL_DEFINE5(file_setattr, int, dfd, const char __user *, filename, 433 struct file_attr __user *, ufattr, size_t, usize, 434 unsigned int, at_flags) 435 { 436 struct path filepath __free(path_put) = {}; 437 unsigned int lookup_flags = 0; 438 struct file_attr fattr; 439 struct file_kattr fa = {}; 440 int error; 441 442 BUILD_BUG_ON(sizeof(struct file_attr) < FILE_ATTR_SIZE_VER0); 443 BUILD_BUG_ON(sizeof(struct file_attr) != FILE_ATTR_SIZE_LATEST); 444 445 if ((at_flags & ~(AT_SYMLINK_NOFOLLOW | AT_EMPTY_PATH)) != 0) 446 return -EINVAL; 447 448 if (!(at_flags & AT_SYMLINK_NOFOLLOW)) 449 lookup_flags |= LOOKUP_FOLLOW; 450 451 if (usize > PAGE_SIZE) 452 return -E2BIG; 453 454 if (usize < FILE_ATTR_SIZE_VER0) 455 return -EINVAL; 456 457 error = copy_struct_from_user(&fattr, sizeof(struct file_attr), ufattr, 458 usize); 459 if (error) 460 return error; 461 462 error = file_attr_to_fileattr(&fattr, &fa); 463 if (error) 464 return error; 465 466 CLASS(filename_maybe_null, name)(filename, at_flags); 467 if (!name && dfd >= 0) { 468 CLASS(fd, f)(dfd); 469 if (fd_empty(f)) 470 return -EBADF; 471 472 filepath = fd_file(f)->f_path; 473 path_get(&filepath); 474 } else { 475 error = filename_lookup(dfd, name, lookup_flags, &filepath, 476 NULL); 477 if (error) 478 return error; 479 } 480 481 error = mnt_want_write(filepath.mnt); 482 if (!error) { 483 error = vfs_fileattr_set(mnt_idmap(filepath.mnt), 484 filepath.dentry, &fa); 485 if (error == -ENOIOCTLCMD || error == -ENOTTY) 486 error = -EOPNOTSUPP; 487 mnt_drop_write(filepath.mnt); 488 } 489 490 return error; 491 } 492