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). All 19 * other fields are zeroed. 20 */ 21 void fileattr_fill_xflags(struct file_kattr *fa, u32 xflags) 22 { 23 memset(fa, 0, sizeof(*fa)); 24 fa->fsx_valid = true; 25 fa->fsx_xflags = xflags; 26 if (fa->fsx_xflags & FS_XFLAG_IMMUTABLE) 27 fa->flags |= FS_IMMUTABLE_FL; 28 if (fa->fsx_xflags & FS_XFLAG_APPEND) 29 fa->flags |= FS_APPEND_FL; 30 if (fa->fsx_xflags & FS_XFLAG_SYNC) 31 fa->flags |= FS_SYNC_FL; 32 if (fa->fsx_xflags & FS_XFLAG_NOATIME) 33 fa->flags |= FS_NOATIME_FL; 34 if (fa->fsx_xflags & FS_XFLAG_NODUMP) 35 fa->flags |= FS_NODUMP_FL; 36 if (fa->fsx_xflags & FS_XFLAG_DAX) 37 fa->flags |= FS_DAX_FL; 38 if (fa->fsx_xflags & FS_XFLAG_PROJINHERIT) 39 fa->flags |= FS_PROJINHERIT_FL; 40 if (fa->fsx_xflags & FS_XFLAG_VERITY) 41 fa->flags |= FS_VERITY_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 * All other fields are zeroed. 52 */ 53 void fileattr_fill_flags(struct file_kattr *fa, u32 flags) 54 { 55 memset(fa, 0, sizeof(*fa)); 56 fa->flags_valid = true; 57 fa->flags = flags; 58 if (fa->flags & FS_SYNC_FL) 59 fa->fsx_xflags |= FS_XFLAG_SYNC; 60 if (fa->flags & FS_IMMUTABLE_FL) 61 fa->fsx_xflags |= FS_XFLAG_IMMUTABLE; 62 if (fa->flags & FS_APPEND_FL) 63 fa->fsx_xflags |= FS_XFLAG_APPEND; 64 if (fa->flags & FS_NODUMP_FL) 65 fa->fsx_xflags |= FS_XFLAG_NODUMP; 66 if (fa->flags & FS_NOATIME_FL) 67 fa->fsx_xflags |= FS_XFLAG_NOATIME; 68 if (fa->flags & FS_DAX_FL) 69 fa->fsx_xflags |= FS_XFLAG_DAX; 70 if (fa->flags & FS_PROJINHERIT_FL) 71 fa->fsx_xflags |= FS_XFLAG_PROJINHERIT; 72 if (fa->flags & FS_VERITY_FL) 73 fa->fsx_xflags |= FS_XFLAG_VERITY; 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 if ((fa->fsx_xflags & FS_XFLAG_DAX) && 240 !(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode))) 241 return -EINVAL; 242 243 /* Extent size hints of zero turn off the flags. */ 244 if (fa->fsx_extsize == 0) 245 fa->fsx_xflags &= ~(FS_XFLAG_EXTSIZE | FS_XFLAG_EXTSZINHERIT); 246 if (fa->fsx_cowextsize == 0) 247 fa->fsx_xflags &= ~FS_XFLAG_COWEXTSIZE; 248 249 return 0; 250 } 251 252 /** 253 * vfs_fileattr_set - change miscellaneous file attributes 254 * @idmap: idmap of the mount 255 * @dentry: the object to change 256 * @fa: fileattr pointer 257 * 258 * After verifying permissions, call i_op->fileattr_set() callback, if 259 * exists. 260 * 261 * Verifying attributes involves retrieving current attributes with 262 * i_op->fileattr_get(), this also allows initializing attributes that have 263 * not been set by the caller to current values. Inode lock is held 264 * thoughout to prevent racing with another instance. 265 * 266 * Return: 0 on success, or a negative error on failure. 267 */ 268 int vfs_fileattr_set(struct mnt_idmap *idmap, struct dentry *dentry, 269 struct file_kattr *fa) 270 { 271 struct inode *inode = d_inode(dentry); 272 struct file_kattr old_ma = {}; 273 int err; 274 275 if (!inode->i_op->fileattr_set) 276 return -ENOIOCTLCMD; 277 278 if (!inode_owner_or_capable(idmap, inode)) 279 return -EPERM; 280 281 inode_lock(inode); 282 err = vfs_fileattr_get(dentry, &old_ma); 283 if (!err) { 284 /* initialize missing bits from old_ma */ 285 if (fa->flags_valid) { 286 fa->fsx_xflags |= old_ma.fsx_xflags & ~FS_XFLAG_COMMON; 287 fa->fsx_extsize = old_ma.fsx_extsize; 288 fa->fsx_nextents = old_ma.fsx_nextents; 289 fa->fsx_projid = old_ma.fsx_projid; 290 fa->fsx_cowextsize = old_ma.fsx_cowextsize; 291 } else { 292 fa->flags |= old_ma.flags & ~FS_COMMON_FL; 293 } 294 295 err = fileattr_set_prepare(inode, &old_ma, fa); 296 if (err) 297 goto out; 298 err = security_inode_file_setattr(dentry, fa); 299 if (err) 300 goto out; 301 err = inode->i_op->fileattr_set(idmap, dentry, fa); 302 if (err) 303 goto out; 304 fsnotify_xattr(dentry); 305 } 306 307 out: 308 inode_unlock(inode); 309 return err; 310 } 311 EXPORT_SYMBOL(vfs_fileattr_set); 312 313 int ioctl_getflags(struct file *file, unsigned int __user *argp) 314 { 315 struct file_kattr fa = { .flags_valid = true }; /* hint only */ 316 int err; 317 318 err = vfs_fileattr_get(file->f_path.dentry, &fa); 319 if (!err) 320 err = put_user(fa.flags, argp); 321 return err; 322 } 323 324 int ioctl_setflags(struct file *file, unsigned int __user *argp) 325 { 326 struct mnt_idmap *idmap = file_mnt_idmap(file); 327 struct dentry *dentry = file->f_path.dentry; 328 struct file_kattr fa; 329 unsigned int flags; 330 int err; 331 332 err = get_user(flags, argp); 333 if (!err) { 334 err = mnt_want_write_file(file); 335 if (!err) { 336 fileattr_fill_flags(&fa, flags); 337 err = vfs_fileattr_set(idmap, dentry, &fa); 338 mnt_drop_write_file(file); 339 } 340 } 341 return err; 342 } 343 344 int ioctl_fsgetxattr(struct file *file, void __user *argp) 345 { 346 struct file_kattr fa = { .fsx_valid = true }; /* hint only */ 347 int err; 348 349 err = vfs_fileattr_get(file->f_path.dentry, &fa); 350 if (!err) 351 err = copy_fsxattr_to_user(&fa, argp); 352 353 return err; 354 } 355 356 int ioctl_fssetxattr(struct file *file, void __user *argp) 357 { 358 struct mnt_idmap *idmap = file_mnt_idmap(file); 359 struct dentry *dentry = file->f_path.dentry; 360 struct file_kattr fa; 361 int err; 362 363 err = copy_fsxattr_from_user(&fa, argp); 364 if (!err) { 365 err = mnt_want_write_file(file); 366 if (!err) { 367 err = vfs_fileattr_set(idmap, dentry, &fa); 368 mnt_drop_write_file(file); 369 } 370 } 371 return err; 372 } 373 374 SYSCALL_DEFINE5(file_getattr, int, dfd, const char __user *, filename, 375 struct file_attr __user *, ufattr, size_t, usize, 376 unsigned int, at_flags) 377 { 378 struct path filepath __free(path_put) = {}; 379 unsigned int lookup_flags = 0; 380 struct file_attr fattr; 381 struct file_kattr fa; 382 int error; 383 384 BUILD_BUG_ON(sizeof(struct file_attr) < FILE_ATTR_SIZE_VER0); 385 BUILD_BUG_ON(sizeof(struct file_attr) != FILE_ATTR_SIZE_LATEST); 386 387 if ((at_flags & ~(AT_SYMLINK_NOFOLLOW | AT_EMPTY_PATH)) != 0) 388 return -EINVAL; 389 390 if (!(at_flags & AT_SYMLINK_NOFOLLOW)) 391 lookup_flags |= LOOKUP_FOLLOW; 392 393 if (usize > PAGE_SIZE) 394 return -E2BIG; 395 396 if (usize < FILE_ATTR_SIZE_VER0) 397 return -EINVAL; 398 399 CLASS(filename_maybe_null, name)(filename, at_flags); 400 if (!name && dfd >= 0) { 401 CLASS(fd, f)(dfd); 402 if (fd_empty(f)) 403 return -EBADF; 404 405 filepath = fd_file(f)->f_path; 406 path_get(&filepath); 407 } else { 408 error = filename_lookup(dfd, name, lookup_flags, &filepath, 409 NULL); 410 if (error) 411 return error; 412 } 413 414 error = vfs_fileattr_get(filepath.dentry, &fa); 415 if (error == -ENOIOCTLCMD || error == -ENOTTY) 416 error = -EOPNOTSUPP; 417 if (error) 418 return error; 419 420 fileattr_to_file_attr(&fa, &fattr); 421 error = copy_struct_to_user(ufattr, usize, &fattr, 422 sizeof(struct file_attr), NULL); 423 424 return error; 425 } 426 427 SYSCALL_DEFINE5(file_setattr, int, dfd, const char __user *, filename, 428 struct file_attr __user *, ufattr, size_t, usize, 429 unsigned int, at_flags) 430 { 431 struct path filepath __free(path_put) = {}; 432 unsigned int lookup_flags = 0; 433 struct file_attr fattr; 434 struct file_kattr fa; 435 int error; 436 437 BUILD_BUG_ON(sizeof(struct file_attr) < FILE_ATTR_SIZE_VER0); 438 BUILD_BUG_ON(sizeof(struct file_attr) != FILE_ATTR_SIZE_LATEST); 439 440 if ((at_flags & ~(AT_SYMLINK_NOFOLLOW | AT_EMPTY_PATH)) != 0) 441 return -EINVAL; 442 443 if (!(at_flags & AT_SYMLINK_NOFOLLOW)) 444 lookup_flags |= LOOKUP_FOLLOW; 445 446 if (usize > PAGE_SIZE) 447 return -E2BIG; 448 449 if (usize < FILE_ATTR_SIZE_VER0) 450 return -EINVAL; 451 452 error = copy_struct_from_user(&fattr, sizeof(struct file_attr), ufattr, 453 usize); 454 if (error) 455 return error; 456 457 error = file_attr_to_fileattr(&fattr, &fa); 458 if (error) 459 return error; 460 461 CLASS(filename_maybe_null, name)(filename, at_flags); 462 if (!name && dfd >= 0) { 463 CLASS(fd, f)(dfd); 464 if (fd_empty(f)) 465 return -EBADF; 466 467 filepath = fd_file(f)->f_path; 468 path_get(&filepath); 469 } else { 470 error = filename_lookup(dfd, name, lookup_flags, &filepath, 471 NULL); 472 if (error) 473 return error; 474 } 475 476 error = mnt_want_write(filepath.mnt); 477 if (!error) { 478 error = vfs_fileattr_set(mnt_idmap(filepath.mnt), 479 filepath.dentry, &fa); 480 if (error == -ENOIOCTLCMD || error == -ENOTTY) 481 error = -EOPNOTSUPP; 482 mnt_drop_write(filepath.mnt); 483 } 484 485 return error; 486 } 487