Skip to content

Commit 8c67da5

Browse files
committed
Merge tag 'vfs-6.14-rc2.fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/vfs/vfs
Pull vfs fixes from Christian Brauner: - Fix fsnotify FMODE_NONOTIFY* handling. This also disables fsnotify on all pseudo files by default apart from very select exceptions. This carries a regression risk so we need to watch out and adapt accordingly. However, it is overall a significant improvement over the current status quo where every rando file can get fsnotify enabled. - Cleanup and simplify lockref_init() after recent lockref changes. - Fix vboxfs build with gcc-15. - Add an assert into inode_set_cached_link() to catch corrupt links. - Allow users to also use an empty string check to detect whether a given mount option string was empty or not. - Fix how security options were appended to statmount()'s ->mnt_opt field. - Fix statmount() selftests to always check the returned mask. - Fix uninitialized value in vfs_statx_path(). - Fix pidfs_ioctl() sanity checks to guard against ioctl() overloading and preserve extensibility. * tag 'vfs-6.14-rc2.fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/vfs/vfs: vfs: sanity check the length passed to inode_set_cached_link() pidfs: improve ioctl handling fsnotify: disable pre-content and permission events by default selftests: always check mask returned by statmount(2) fsnotify: disable notification by default for all pseudo files fs: fix adding security options to statmount.mnt_opt fsnotify: use accessor to set FMODE_NONOTIFY_* lockref: remove count argument of lockref_init gfs2: switch to lockref_init(..., 1) gfs2: use lockref_init for gl_lockref statmount: let unset strings be empty vboxsf: fix building with GCC 15 fs/stat.c: avoid harmless garbage value problem in vfs_statx_path()
2 parents 94b481f + 37d11cf commit 8c67da5

File tree

19 files changed

+143
-52
lines changed

19 files changed

+143
-52
lines changed

drivers/tty/pty.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -798,7 +798,7 @@ static int ptmx_open(struct inode *inode, struct file *filp)
798798
nonseekable_open(inode, filp);
799799

800800
/* We refuse fsnotify events on ptmx, since it's a shared resource */
801-
filp->f_mode |= FMODE_NONOTIFY;
801+
file_set_fsnotify_mode(filp, FMODE_NONOTIFY);
802802

803803
retval = tty_alloc_file(filp);
804804
if (retval)

fs/dcache.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -1700,7 +1700,7 @@ static struct dentry *__d_alloc(struct super_block *sb, const struct qstr *name)
17001700
smp_store_release(&dentry->d_name.name, dname); /* ^^^ */
17011701

17021702
dentry->d_flags = 0;
1703-
lockref_init(&dentry->d_lockref, 1);
1703+
lockref_init(&dentry->d_lockref);
17041704
seqcount_spinlock_init(&dentry->d_seq, &dentry->d_lock);
17051705
dentry->d_inode = NULL;
17061706
dentry->d_parent = dentry;

fs/erofs/zdata.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -726,7 +726,7 @@ static int z_erofs_register_pcluster(struct z_erofs_frontend *fe)
726726
if (IS_ERR(pcl))
727727
return PTR_ERR(pcl);
728728

729-
lockref_init(&pcl->lockref, 1); /* one ref for this request */
729+
lockref_init(&pcl->lockref); /* one ref for this request */
730730
pcl->algorithmformat = map->m_algorithmformat;
731731
pcl->length = 0;
732732
pcl->partial = true;

fs/file_table.c

+16
Original file line numberDiff line numberDiff line change
@@ -194,6 +194,11 @@ static int init_file(struct file *f, int flags, const struct cred *cred)
194194
* refcount bumps we should reinitialize the reused file first.
195195
*/
196196
file_ref_init(&f->f_ref, 1);
197+
/*
198+
* Disable permission and pre-content events for all files by default.
199+
* They may be enabled later by file_set_fsnotify_mode_from_watchers().
200+
*/
201+
file_set_fsnotify_mode(f, FMODE_NONOTIFY_PERM);
197202
return 0;
198203
}
199204

@@ -375,7 +380,13 @@ struct file *alloc_file_pseudo(struct inode *inode, struct vfsmount *mnt,
375380
if (IS_ERR(file)) {
376381
ihold(inode);
377382
path_put(&path);
383+
return file;
378384
}
385+
/*
386+
* Disable all fsnotify events for pseudo files by default.
387+
* They may be enabled by caller with file_set_fsnotify_mode().
388+
*/
389+
file_set_fsnotify_mode(file, FMODE_NONOTIFY);
379390
return file;
380391
}
381392
EXPORT_SYMBOL(alloc_file_pseudo);
@@ -400,6 +411,11 @@ struct file *alloc_file_pseudo_noaccount(struct inode *inode,
400411
return file;
401412
}
402413
file_init_path(file, &path, fops);
414+
/*
415+
* Disable all fsnotify events for pseudo files by default.
416+
* They may be enabled by caller with file_set_fsnotify_mode().
417+
*/
418+
file_set_fsnotify_mode(file, FMODE_NONOTIFY);
403419
return file;
404420
}
405421
EXPORT_SYMBOL_GPL(alloc_file_pseudo_noaccount);

fs/gfs2/glock.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -1201,8 +1201,8 @@ int gfs2_glock_get(struct gfs2_sbd *sdp, u64 number,
12011201
if (glops->go_instantiate)
12021202
gl->gl_flags |= BIT(GLF_INSTANTIATE_NEEDED);
12031203
gl->gl_name = name;
1204+
lockref_init(&gl->gl_lockref);
12041205
lockdep_set_subclass(&gl->gl_lockref.lock, glops->go_subclass);
1205-
gl->gl_lockref.count = 1;
12061206
gl->gl_state = LM_ST_UNLOCKED;
12071207
gl->gl_target = LM_ST_UNLOCKED;
12081208
gl->gl_demote_state = LM_ST_EXCLUSIVE;

fs/gfs2/main.c

-1
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,6 @@ static void gfs2_init_glock_once(void *foo)
5151
{
5252
struct gfs2_glock *gl = foo;
5353

54-
spin_lock_init(&gl->gl_lockref.lock);
5554
INIT_LIST_HEAD(&gl->gl_holders);
5655
INIT_LIST_HEAD(&gl->gl_lru);
5756
INIT_LIST_HEAD(&gl->gl_ail_list);

fs/gfs2/quota.c

+2-2
Original file line numberDiff line numberDiff line change
@@ -236,7 +236,7 @@ static struct gfs2_quota_data *qd_alloc(unsigned hash, struct gfs2_sbd *sdp, str
236236
return NULL;
237237

238238
qd->qd_sbd = sdp;
239-
lockref_init(&qd->qd_lockref, 0);
239+
lockref_init(&qd->qd_lockref);
240240
qd->qd_id = qid;
241241
qd->qd_slot = -1;
242242
INIT_LIST_HEAD(&qd->qd_lru);
@@ -297,7 +297,6 @@ static int qd_get(struct gfs2_sbd *sdp, struct kqid qid,
297297
spin_lock_bucket(hash);
298298
*qdp = qd = gfs2_qd_search_bucket(hash, sdp, qid);
299299
if (qd == NULL) {
300-
new_qd->qd_lockref.count++;
301300
*qdp = new_qd;
302301
list_add(&new_qd->qd_list, &sdp->sd_quota_list);
303302
hlist_bl_add_head_rcu(&new_qd->qd_hlist, &qd_hash_table[hash]);
@@ -1450,6 +1449,7 @@ int gfs2_quota_init(struct gfs2_sbd *sdp)
14501449
if (qd == NULL)
14511450
goto fail_brelse;
14521451

1452+
qd->qd_lockref.count = 0;
14531453
set_bit(QDF_CHANGE, &qd->qd_flags);
14541454
qd->qd_change = qc_change;
14551455
qd->qd_slot = slot;

fs/namespace.c

+30-24
Original file line numberDiff line numberDiff line change
@@ -5087,30 +5087,29 @@ static int statmount_mnt_opts(struct kstatmount *s, struct seq_file *seq)
50875087
{
50885088
struct vfsmount *mnt = s->mnt;
50895089
struct super_block *sb = mnt->mnt_sb;
5090+
size_t start = seq->count;
50905091
int err;
50915092

5092-
if (sb->s_op->show_options) {
5093-
size_t start = seq->count;
5094-
5095-
err = security_sb_show_options(seq, sb);
5096-
if (err)
5097-
return err;
5093+
err = security_sb_show_options(seq, sb);
5094+
if (err)
5095+
return err;
50985096

5097+
if (sb->s_op->show_options) {
50995098
err = sb->s_op->show_options(seq, mnt->mnt_root);
51005099
if (err)
51015100
return err;
5101+
}
51025102

5103-
if (unlikely(seq_has_overflowed(seq)))
5104-
return -EAGAIN;
5103+
if (unlikely(seq_has_overflowed(seq)))
5104+
return -EAGAIN;
51055105

5106-
if (seq->count == start)
5107-
return 0;
5106+
if (seq->count == start)
5107+
return 0;
51085108

5109-
/* skip leading comma */
5110-
memmove(seq->buf + start, seq->buf + start + 1,
5111-
seq->count - start - 1);
5112-
seq->count--;
5113-
}
5109+
/* skip leading comma */
5110+
memmove(seq->buf + start, seq->buf + start + 1,
5111+
seq->count - start - 1);
5112+
seq->count--;
51145113

51155114
return 0;
51165115
}
@@ -5191,39 +5190,45 @@ static int statmount_string(struct kstatmount *s, u64 flag)
51915190
size_t kbufsize;
51925191
struct seq_file *seq = &s->seq;
51935192
struct statmount *sm = &s->sm;
5194-
u32 start = seq->count;
5193+
u32 start, *offp;
5194+
5195+
/* Reserve an empty string at the beginning for any unset offsets */
5196+
if (!seq->count)
5197+
seq_putc(seq, 0);
5198+
5199+
start = seq->count;
51955200

51965201
switch (flag) {
51975202
case STATMOUNT_FS_TYPE:
5198-
sm->fs_type = start;
5203+
offp = &sm->fs_type;
51995204
ret = statmount_fs_type(s, seq);
52005205
break;
52015206
case STATMOUNT_MNT_ROOT:
5202-
sm->mnt_root = start;
5207+
offp = &sm->mnt_root;
52035208
ret = statmount_mnt_root(s, seq);
52045209
break;
52055210
case STATMOUNT_MNT_POINT:
5206-
sm->mnt_point = start;
5211+
offp = &sm->mnt_point;
52075212
ret = statmount_mnt_point(s, seq);
52085213
break;
52095214
case STATMOUNT_MNT_OPTS:
5210-
sm->mnt_opts = start;
5215+
offp = &sm->mnt_opts;
52115216
ret = statmount_mnt_opts(s, seq);
52125217
break;
52135218
case STATMOUNT_OPT_ARRAY:
5214-
sm->opt_array = start;
5219+
offp = &sm->opt_array;
52155220
ret = statmount_opt_array(s, seq);
52165221
break;
52175222
case STATMOUNT_OPT_SEC_ARRAY:
5218-
sm->opt_sec_array = start;
5223+
offp = &sm->opt_sec_array;
52195224
ret = statmount_opt_sec_array(s, seq);
52205225
break;
52215226
case STATMOUNT_FS_SUBTYPE:
5222-
sm->fs_subtype = start;
5227+
offp = &sm->fs_subtype;
52235228
statmount_fs_subtype(s, seq);
52245229
break;
52255230
case STATMOUNT_SB_SOURCE:
5226-
sm->sb_source = start;
5231+
offp = &sm->sb_source;
52275232
ret = statmount_sb_source(s, seq);
52285233
break;
52295234
default:
@@ -5251,6 +5256,7 @@ static int statmount_string(struct kstatmount *s, u64 flag)
52515256

52525257
seq->buf[seq->count++] = '\0';
52535258
sm->mask |= flag;
5259+
*offp = start;
52545260
return 0;
52555261
}
52565262

fs/notify/fsnotify.c

+12-6
Original file line numberDiff line numberDiff line change
@@ -648,7 +648,7 @@ EXPORT_SYMBOL_GPL(fsnotify);
648648
* Later, fsnotify permission hooks do not check if there are permission event
649649
* watches, but that there were permission event watches at open time.
650650
*/
651-
void file_set_fsnotify_mode(struct file *file)
651+
void file_set_fsnotify_mode_from_watchers(struct file *file)
652652
{
653653
struct dentry *dentry = file->f_path.dentry, *parent;
654654
struct super_block *sb = dentry->d_sb;
@@ -665,7 +665,7 @@ void file_set_fsnotify_mode(struct file *file)
665665
*/
666666
if (likely(!fsnotify_sb_has_priority_watchers(sb,
667667
FSNOTIFY_PRIO_CONTENT))) {
668-
file->f_mode |= FMODE_NONOTIFY_PERM;
668+
file_set_fsnotify_mode(file, FMODE_NONOTIFY_PERM);
669669
return;
670670
}
671671

@@ -676,7 +676,7 @@ void file_set_fsnotify_mode(struct file *file)
676676
if ((!d_is_dir(dentry) && !d_is_reg(dentry)) ||
677677
likely(!fsnotify_sb_has_priority_watchers(sb,
678678
FSNOTIFY_PRIO_PRE_CONTENT))) {
679-
file->f_mode |= FMODE_NONOTIFY | FMODE_NONOTIFY_PERM;
679+
file_set_fsnotify_mode(file, FMODE_NONOTIFY | FMODE_NONOTIFY_PERM);
680680
return;
681681
}
682682

@@ -686,19 +686,25 @@ void file_set_fsnotify_mode(struct file *file)
686686
*/
687687
mnt_mask = READ_ONCE(real_mount(file->f_path.mnt)->mnt_fsnotify_mask);
688688
if (unlikely(fsnotify_object_watched(d_inode(dentry), mnt_mask,
689-
FSNOTIFY_PRE_CONTENT_EVENTS)))
689+
FSNOTIFY_PRE_CONTENT_EVENTS))) {
690+
/* Enable pre-content events */
691+
file_set_fsnotify_mode(file, 0);
690692
return;
693+
}
691694

692695
/* Is parent watching for pre-content events on this file? */
693696
if (dentry->d_flags & DCACHE_FSNOTIFY_PARENT_WATCHED) {
694697
parent = dget_parent(dentry);
695698
p_mask = fsnotify_inode_watches_children(d_inode(parent));
696699
dput(parent);
697-
if (p_mask & FSNOTIFY_PRE_CONTENT_EVENTS)
700+
if (p_mask & FSNOTIFY_PRE_CONTENT_EVENTS) {
701+
/* Enable pre-content events */
702+
file_set_fsnotify_mode(file, 0);
698703
return;
704+
}
699705
}
700706
/* Nobody watching for pre-content events from this file */
701-
file->f_mode |= FMODE_NONOTIFY | FMODE_NONOTIFY_PERM;
707+
file_set_fsnotify_mode(file, FMODE_NONOTIFY | FMODE_NONOTIFY_PERM);
702708
}
703709
#endif
704710

fs/open.c

+6-5
Original file line numberDiff line numberDiff line change
@@ -905,7 +905,8 @@ static int do_dentry_open(struct file *f,
905905
f->f_sb_err = file_sample_sb_err(f);
906906

907907
if (unlikely(f->f_flags & O_PATH)) {
908-
f->f_mode = FMODE_PATH | FMODE_OPENED | FMODE_NONOTIFY;
908+
f->f_mode = FMODE_PATH | FMODE_OPENED;
909+
file_set_fsnotify_mode(f, FMODE_NONOTIFY);
909910
f->f_op = &empty_fops;
910911
return 0;
911912
}
@@ -935,10 +936,10 @@ static int do_dentry_open(struct file *f,
935936

936937
/*
937938
* Set FMODE_NONOTIFY_* bits according to existing permission watches.
938-
* If FMODE_NONOTIFY was already set for an fanotify fd, this doesn't
939-
* change anything.
939+
* If FMODE_NONOTIFY mode was already set for an fanotify fd or for a
940+
* pseudo file, this call will not change the mode.
940941
*/
941-
file_set_fsnotify_mode(f);
942+
file_set_fsnotify_mode_from_watchers(f);
942943
error = fsnotify_open_perm(f);
943944
if (error)
944945
goto cleanup_all;
@@ -1122,7 +1123,7 @@ struct file *dentry_open_nonotify(const struct path *path, int flags,
11221123
if (!IS_ERR(f)) {
11231124
int error;
11241125

1125-
f->f_mode |= FMODE_NONOTIFY;
1126+
file_set_fsnotify_mode(f, FMODE_NONOTIFY);
11261127
error = vfs_open(path, f);
11271128
if (error) {
11281129
fput(f);

fs/pidfs.c

+11-1
Original file line numberDiff line numberDiff line change
@@ -287,7 +287,6 @@ static bool pidfs_ioctl_valid(unsigned int cmd)
287287
switch (cmd) {
288288
case FS_IOC_GETVERSION:
289289
case PIDFD_GET_CGROUP_NAMESPACE:
290-
case PIDFD_GET_INFO:
291290
case PIDFD_GET_IPC_NAMESPACE:
292291
case PIDFD_GET_MNT_NAMESPACE:
293292
case PIDFD_GET_NET_NAMESPACE:
@@ -300,6 +299,17 @@ static bool pidfs_ioctl_valid(unsigned int cmd)
300299
return true;
301300
}
302301

302+
/* Extensible ioctls require some more careful checks. */
303+
switch (_IOC_NR(cmd)) {
304+
case _IOC_NR(PIDFD_GET_INFO):
305+
/*
306+
* Try to prevent performing a pidfd ioctl when someone
307+
* erronously mistook the file descriptor for a pidfd.
308+
* This is not perfect but will catch most cases.
309+
*/
310+
return (_IOC_TYPE(cmd) == _IOC_TYPE(PIDFD_GET_INFO));
311+
}
312+
303313
return false;
304314
}
305315

fs/pipe.c

+6
Original file line numberDiff line numberDiff line change
@@ -960,6 +960,12 @@ int create_pipe_files(struct file **res, int flags)
960960
res[1] = f;
961961
stream_open(inode, res[0]);
962962
stream_open(inode, res[1]);
963+
/*
964+
* Disable permission and pre-content events, but enable legacy
965+
* inotify events for legacy users.
966+
*/
967+
file_set_fsnotify_mode(res[0], FMODE_NONOTIFY_PERM);
968+
file_set_fsnotify_mode(res[1], FMODE_NONOTIFY_PERM);
963969
return 0;
964970
}
965971

fs/stat.c

+3-1
Original file line numberDiff line numberDiff line change
@@ -281,6 +281,8 @@ static int vfs_statx_path(struct path *path, int flags, struct kstat *stat,
281281
u32 request_mask)
282282
{
283283
int error = vfs_getattr(path, stat, request_mask, flags);
284+
if (error)
285+
return error;
284286

285287
if (request_mask & STATX_MNT_ID_UNIQUE) {
286288
stat->mnt_id = real_mount(path->mnt)->mnt_id_unique;
@@ -302,7 +304,7 @@ static int vfs_statx_path(struct path *path, int flags, struct kstat *stat,
302304
if (S_ISBLK(stat->mode))
303305
bdev_statx(path, stat, request_mask);
304306

305-
return error;
307+
return 0;
306308
}
307309

308310
static int vfs_statx_fd(int fd, int flags, struct kstat *stat,

fs/vboxsf/super.c

+2-1
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,8 @@
2121

2222
#define VBOXSF_SUPER_MAGIC 0x786f4256 /* 'VBox' little endian */
2323

24-
static const unsigned char VBSF_MOUNT_SIGNATURE[4] = "\000\377\376\375";
24+
static const unsigned char VBSF_MOUNT_SIGNATURE[4] = { '\000', '\377', '\376',
25+
'\375' };
2526

2627
static int follow_symlinks;
2728
module_param(follow_symlinks, int, 0444);

0 commit comments

Comments
 (0)