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