Skip to content

Commit fa2b906

Browse files
committed
Merge tag 'vfs-6.7-rc3.fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/vfs/vfs
Pull vfs fixes from Christian Brauner: - Avoid calling back into LSMs from vfs_getattr_nosec() calls. IMA used to query inode properties accessing raw inode fields without dedicated helpers. That was finally fixed a few releases ago by forcing IMA to use vfs_getattr_nosec() helpers. The goal of the vfs_getattr_nosec() helper is to query for attributes without calling into the LSM layer which would be quite problematic because incredibly IMA is called from __fput()... __fput() -> ima_file_free() What it does is to call back into the filesystem to update the file's IMA xattr. Querying the inode without using vfs_getattr_nosec() meant that IMA didn't handle stacking filesystems such as overlayfs correctly. So the switch to vfs_getattr_nosec() is quite correct. But the switch to vfs_getattr_nosec() revealed another bug when used on stacking filesystems: __fput() -> ima_file_free() -> vfs_getattr_nosec() -> i_op->getattr::ovl_getattr() -> vfs_getattr() -> i_op->getattr::$WHATEVER_UNDERLYING_FS_getattr() -> security_inode_getattr() # calls back into LSMs Now, if that __fput() happens from task_work_run() of an exiting task current->fs and various other pointer could already be NULL. So anything in the LSM layer relying on that not being NULL would be quite surprised. Fix that by passing the information that this is a security request through to the stacking filesystem by adding a new internal ATT_GETATTR_NOSEC flag. Now the callchain becomes: __fput() -> ima_file_free() -> vfs_getattr_nosec() -> i_op->getattr::ovl_getattr() -> if (AT_GETATTR_NOSEC) vfs_getattr_nosec() else vfs_getattr() -> i_op->getattr::$WHATEVER_UNDERLYING_FS_getattr() - Fix a bug introduced with the iov_iter rework from last cycle. This broke /proc/kcore by copying too much and without the correct offset. - Add a missing NULL check when allocating the root inode in autofs_fill_super(). - Fix stable writes for multi-device filesystems (xfs, btrfs etc) and the block device pseudo filesystem. Stable writes used to be a superblock flag only, making it a per filesystem property. Add an additional AS_STABLE_WRITES mapping flag to allow for fine-grained control. - Ensure that offset_iterate_dir() returns 0 after reaching the end of a directory so it adheres to getdents() convention. * tag 'vfs-6.7-rc3.fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/vfs/vfs: libfs: getdents() should return 0 after reaching EOD xfs: respect the stable writes flag on the RT device xfs: clean up FS_XFLAG_REALTIME handling in xfs_ioctl_setattr_xflags block: update the stable_writes flag in bdev_add filemap: add a per-mapping stable writes flag autofs: add: new_inode check in autofs_fill_super() iov_iter: fix copy_page_to_iter_nofault() fs: Pass AT_GETATTR_NOSEC flag to getattr interface function
2 parents afa0f6e + 796432e commit fa2b906

File tree

15 files changed

+121
-58
lines changed

15 files changed

+121
-58
lines changed

block/bdev.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -425,6 +425,8 @@ void bdev_set_nr_sectors(struct block_device *bdev, sector_t sectors)
425425

426426
void bdev_add(struct block_device *bdev, dev_t dev)
427427
{
428+
if (bdev_stable_writes(bdev))
429+
mapping_set_stable_writes(bdev->bd_inode->i_mapping);
428430
bdev->bd_dev = dev;
429431
bdev->bd_inode->i_rdev = dev;
430432
bdev->bd_inode->i_ino = dev;

fs/autofs/inode.c

Lines changed: 21 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -309,9 +309,7 @@ static int autofs_fill_super(struct super_block *s, struct fs_context *fc)
309309
struct autofs_fs_context *ctx = fc->fs_private;
310310
struct autofs_sb_info *sbi = s->s_fs_info;
311311
struct inode *root_inode;
312-
struct dentry *root;
313312
struct autofs_info *ino;
314-
int ret = -ENOMEM;
315313

316314
pr_debug("starting up, sbi = %p\n", sbi);
317315

@@ -328,56 +326,44 @@ static int autofs_fill_super(struct super_block *s, struct fs_context *fc)
328326
*/
329327
ino = autofs_new_ino(sbi);
330328
if (!ino)
331-
goto fail;
329+
return -ENOMEM;
332330

333331
root_inode = autofs_get_inode(s, S_IFDIR | 0755);
332+
if (!root_inode)
333+
return -ENOMEM;
334+
334335
root_inode->i_uid = ctx->uid;
335336
root_inode->i_gid = ctx->gid;
337+
root_inode->i_fop = &autofs_root_operations;
338+
root_inode->i_op = &autofs_dir_inode_operations;
336339

337-
root = d_make_root(root_inode);
338-
if (!root)
339-
goto fail_ino;
340-
341-
root->d_fsdata = ino;
340+
s->s_root = d_make_root(root_inode);
341+
if (unlikely(!s->s_root)) {
342+
autofs_free_ino(ino);
343+
return -ENOMEM;
344+
}
345+
s->s_root->d_fsdata = ino;
342346

343347
if (ctx->pgrp_set) {
344348
sbi->oz_pgrp = find_get_pid(ctx->pgrp);
345-
if (!sbi->oz_pgrp) {
346-
ret = invalf(fc, "Could not find process group %d",
347-
ctx->pgrp);
348-
goto fail_dput;
349-
}
350-
} else {
349+
if (!sbi->oz_pgrp)
350+
return invalf(fc, "Could not find process group %d",
351+
ctx->pgrp);
352+
} else
351353
sbi->oz_pgrp = get_task_pid(current, PIDTYPE_PGID);
352-
}
353354

354355
if (autofs_type_trigger(sbi->type))
355-
__managed_dentry_set_managed(root);
356-
357-
root_inode->i_fop = &autofs_root_operations;
358-
root_inode->i_op = &autofs_dir_inode_operations;
356+
/* s->s_root won't be contended so there's little to
357+
* be gained by not taking the d_lock when setting
358+
* d_flags, even when a lot mounts are being done.
359+
*/
360+
managed_dentry_set_managed(s->s_root);
359361

360362
pr_debug("pipe fd = %d, pgrp = %u\n",
361363
sbi->pipefd, pid_nr(sbi->oz_pgrp));
362364

363365
sbi->flags &= ~AUTOFS_SBI_CATATONIC;
364-
365-
/*
366-
* Success! Install the root dentry now to indicate completion.
367-
*/
368-
s->s_root = root;
369366
return 0;
370-
371-
/*
372-
* Failure ... clean up.
373-
*/
374-
fail_dput:
375-
dput(root);
376-
goto fail;
377-
fail_ino:
378-
autofs_free_ino(ino);
379-
fail:
380-
return ret;
381367
}
382368

383369
/*

fs/ecryptfs/inode.c

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -998,6 +998,14 @@ static int ecryptfs_getattr_link(struct mnt_idmap *idmap,
998998
return rc;
999999
}
10001000

1001+
static int ecryptfs_do_getattr(const struct path *path, struct kstat *stat,
1002+
u32 request_mask, unsigned int flags)
1003+
{
1004+
if (flags & AT_GETATTR_NOSEC)
1005+
return vfs_getattr_nosec(path, stat, request_mask, flags);
1006+
return vfs_getattr(path, stat, request_mask, flags);
1007+
}
1008+
10011009
static int ecryptfs_getattr(struct mnt_idmap *idmap,
10021010
const struct path *path, struct kstat *stat,
10031011
u32 request_mask, unsigned int flags)
@@ -1006,8 +1014,8 @@ static int ecryptfs_getattr(struct mnt_idmap *idmap,
10061014
struct kstat lower_stat;
10071015
int rc;
10081016

1009-
rc = vfs_getattr(ecryptfs_dentry_to_lower_path(dentry), &lower_stat,
1010-
request_mask, flags);
1017+
rc = ecryptfs_do_getattr(ecryptfs_dentry_to_lower_path(dentry),
1018+
&lower_stat, request_mask, flags);
10111019
if (!rc) {
10121020
fsstack_copy_attr_all(d_inode(dentry),
10131021
ecryptfs_inode_to_lower(d_inode(dentry)));

fs/inode.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -215,6 +215,8 @@ int inode_init_always(struct super_block *sb, struct inode *inode)
215215
lockdep_set_class_and_name(&mapping->invalidate_lock,
216216
&sb->s_type->invalidate_lock_key,
217217
"mapping.invalidate_lock");
218+
if (sb->s_iflags & SB_I_STABLE_WRITES)
219+
mapping_set_stable_writes(mapping);
218220
inode->i_private = NULL;
219221
inode->i_mapping = mapping;
220222
INIT_HLIST_HEAD(&inode->i_dentry); /* buggered by rcu freeing */

fs/libfs.c

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -399,6 +399,8 @@ static loff_t offset_dir_llseek(struct file *file, loff_t offset, int whence)
399399
return -EINVAL;
400400
}
401401

402+
/* In this case, ->private_data is protected by f_pos_lock */
403+
file->private_data = NULL;
402404
return vfs_setpos(file, offset, U32_MAX);
403405
}
404406

@@ -428,7 +430,7 @@ static bool offset_dir_emit(struct dir_context *ctx, struct dentry *dentry)
428430
inode->i_ino, fs_umode_to_dtype(inode->i_mode));
429431
}
430432

431-
static void offset_iterate_dir(struct inode *inode, struct dir_context *ctx)
433+
static void *offset_iterate_dir(struct inode *inode, struct dir_context *ctx)
432434
{
433435
struct offset_ctx *so_ctx = inode->i_op->get_offset_ctx(inode);
434436
XA_STATE(xas, &so_ctx->xa, ctx->pos);
@@ -437,7 +439,7 @@ static void offset_iterate_dir(struct inode *inode, struct dir_context *ctx)
437439
while (true) {
438440
dentry = offset_find_next(&xas);
439441
if (!dentry)
440-
break;
442+
return ERR_PTR(-ENOENT);
441443

442444
if (!offset_dir_emit(ctx, dentry)) {
443445
dput(dentry);
@@ -447,6 +449,7 @@ static void offset_iterate_dir(struct inode *inode, struct dir_context *ctx)
447449
dput(dentry);
448450
ctx->pos = xas.xa_index + 1;
449451
}
452+
return NULL;
450453
}
451454

452455
/**
@@ -479,7 +482,12 @@ static int offset_readdir(struct file *file, struct dir_context *ctx)
479482
if (!dir_emit_dots(file, ctx))
480483
return 0;
481484

482-
offset_iterate_dir(d_inode(dir), ctx);
485+
/* In this case, ->private_data is protected by f_pos_lock */
486+
if (ctx->pos == 2)
487+
file->private_data = NULL;
488+
else if (file->private_data == ERR_PTR(-ENOENT))
489+
return 0;
490+
file->private_data = offset_iterate_dir(d_inode(dir), ctx);
483491
return 0;
484492
}
485493

fs/overlayfs/inode.c

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -171,7 +171,7 @@ int ovl_getattr(struct mnt_idmap *idmap, const struct path *path,
171171

172172
type = ovl_path_real(dentry, &realpath);
173173
old_cred = ovl_override_creds(dentry->d_sb);
174-
err = vfs_getattr(&realpath, stat, request_mask, flags);
174+
err = ovl_do_getattr(&realpath, stat, request_mask, flags);
175175
if (err)
176176
goto out;
177177

@@ -196,8 +196,8 @@ int ovl_getattr(struct mnt_idmap *idmap, const struct path *path,
196196
(!is_dir ? STATX_NLINK : 0);
197197

198198
ovl_path_lower(dentry, &realpath);
199-
err = vfs_getattr(&realpath, &lowerstat,
200-
lowermask, flags);
199+
err = ovl_do_getattr(&realpath, &lowerstat, lowermask,
200+
flags);
201201
if (err)
202202
goto out;
203203

@@ -249,8 +249,8 @@ int ovl_getattr(struct mnt_idmap *idmap, const struct path *path,
249249

250250
ovl_path_lowerdata(dentry, &realpath);
251251
if (realpath.dentry) {
252-
err = vfs_getattr(&realpath, &lowerdatastat,
253-
lowermask, flags);
252+
err = ovl_do_getattr(&realpath, &lowerdatastat,
253+
lowermask, flags);
254254
if (err)
255255
goto out;
256256
} else {

fs/overlayfs/overlayfs.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -408,6 +408,14 @@ static inline bool ovl_open_flags_need_copy_up(int flags)
408408
return ((OPEN_FMODE(flags) & FMODE_WRITE) || (flags & O_TRUNC));
409409
}
410410

411+
static inline int ovl_do_getattr(const struct path *path, struct kstat *stat,
412+
u32 request_mask, unsigned int flags)
413+
{
414+
if (flags & AT_GETATTR_NOSEC)
415+
return vfs_getattr_nosec(path, stat, request_mask, flags);
416+
return vfs_getattr(path, stat, request_mask, flags);
417+
}
418+
411419
/* util.c */
412420
int ovl_get_write_access(struct dentry *dentry);
413421
void ovl_put_write_access(struct dentry *dentry);

fs/stat.c

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,8 @@ int vfs_getattr_nosec(const struct path *path, struct kstat *stat,
133133
idmap = mnt_idmap(path->mnt);
134134
if (inode->i_op->getattr)
135135
return inode->i_op->getattr(idmap, path, stat,
136-
request_mask, query_flags);
136+
request_mask,
137+
query_flags | AT_GETATTR_NOSEC);
137138

138139
generic_fillattr(idmap, request_mask, inode, stat);
139140
return 0;
@@ -166,6 +167,9 @@ int vfs_getattr(const struct path *path, struct kstat *stat,
166167
{
167168
int retval;
168169

170+
if (WARN_ON_ONCE(query_flags & AT_GETATTR_NOSEC))
171+
return -EPERM;
172+
169173
retval = security_inode_getattr(path);
170174
if (retval)
171175
return retval;

fs/xfs/xfs_inode.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -569,6 +569,14 @@ extern void xfs_setup_inode(struct xfs_inode *ip);
569569
extern void xfs_setup_iops(struct xfs_inode *ip);
570570
extern void xfs_diflags_to_iflags(struct xfs_inode *ip, bool init);
571571

572+
static inline void xfs_update_stable_writes(struct xfs_inode *ip)
573+
{
574+
if (bdev_stable_writes(xfs_inode_buftarg(ip)->bt_bdev))
575+
mapping_set_stable_writes(VFS_I(ip)->i_mapping);
576+
else
577+
mapping_clear_stable_writes(VFS_I(ip)->i_mapping);
578+
}
579+
572580
/*
573581
* When setting up a newly allocated inode, we need to call
574582
* xfs_finish_inode_setup() once the inode is fully instantiated at

fs/xfs/xfs_ioctl.c

Lines changed: 20 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1121,23 +1121,25 @@ xfs_ioctl_setattr_xflags(
11211121
struct fileattr *fa)
11221122
{
11231123
struct xfs_mount *mp = ip->i_mount;
1124+
bool rtflag = (fa->fsx_xflags & FS_XFLAG_REALTIME);
11241125
uint64_t i_flags2;
11251126

1126-
/* Can't change realtime flag if any extents are allocated. */
1127-
if ((ip->i_df.if_nextents || ip->i_delayed_blks) &&
1128-
XFS_IS_REALTIME_INODE(ip) != (fa->fsx_xflags & FS_XFLAG_REALTIME))
1129-
return -EINVAL;
1127+
if (rtflag != XFS_IS_REALTIME_INODE(ip)) {
1128+
/* Can't change realtime flag if any extents are allocated. */
1129+
if (ip->i_df.if_nextents || ip->i_delayed_blks)
1130+
return -EINVAL;
1131+
}
11301132

1131-
/* If realtime flag is set then must have realtime device */
1132-
if (fa->fsx_xflags & FS_XFLAG_REALTIME) {
1133+
if (rtflag) {
1134+
/* If realtime flag is set then must have realtime device */
11331135
if (mp->m_sb.sb_rblocks == 0 || mp->m_sb.sb_rextsize == 0 ||
11341136
xfs_extlen_to_rtxmod(mp, ip->i_extsize))
11351137
return -EINVAL;
1136-
}
11371138

1138-
/* Clear reflink if we are actually able to set the rt flag. */
1139-
if ((fa->fsx_xflags & FS_XFLAG_REALTIME) && xfs_is_reflink_inode(ip))
1140-
ip->i_diflags2 &= ~XFS_DIFLAG2_REFLINK;
1139+
/* Clear reflink if we are actually able to set the rt flag. */
1140+
if (xfs_is_reflink_inode(ip))
1141+
ip->i_diflags2 &= ~XFS_DIFLAG2_REFLINK;
1142+
}
11411143

11421144
/* diflags2 only valid for v3 inodes. */
11431145
i_flags2 = xfs_flags2diflags2(ip, fa->fsx_xflags);
@@ -1148,6 +1150,14 @@ xfs_ioctl_setattr_xflags(
11481150
ip->i_diflags2 = i_flags2;
11491151

11501152
xfs_diflags_to_iflags(ip, false);
1153+
1154+
/*
1155+
* Make the stable writes flag match that of the device the inode
1156+
* resides on when flipping the RT flag.
1157+
*/
1158+
if (rtflag != XFS_IS_REALTIME_INODE(ip) && S_ISREG(VFS_I(ip)->i_mode))
1159+
xfs_update_stable_writes(ip);
1160+
11511161
xfs_trans_ichgtime(tp, ip, XFS_ICHGTIME_CHG);
11521162
xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
11531163
XFS_STATS_INC(mp, xs_ig_attrchg);

0 commit comments

Comments
 (0)