Skip to content

Commit ec6164a

Browse files
committed
Merge patch series "Fix for huge faults regression"
Amir Goldstein <[email protected]> says: The two Fix patches have been tested by Alex together and each one independently. I also verified that they pass the LTP inoityf/fanotify tests. * patches from https://lore.kernel.org/r/[email protected]: fsnotify: disable pre-content and permission events by default fsnotify: disable notification by default for all pseudo files fsnotify: use accessor to set FMODE_NONOTIFY_* Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Christian Brauner <[email protected]>
2 parents 2cc0205 + 711f9b8 commit ec6164a

File tree

8 files changed

+54
-15
lines changed

8 files changed

+54
-15
lines changed

Diff for: 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)

Diff for: 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);

Diff for: 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

Diff for: 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);

Diff for: 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

Diff for: include/linux/fs.h

+6-1
Original file line numberDiff line numberDiff line change
@@ -222,7 +222,6 @@ typedef int (dio_iodone_t)(struct kiocb *iocb, loff_t offset,
222222
#define FMODE_FSNOTIFY_HSM(mode) 0
223223
#endif
224224

225-
226225
/*
227226
* Attribute flags. These should be or-ed together to figure out what
228227
* has been changed!
@@ -3140,6 +3139,12 @@ static inline void exe_file_allow_write_access(struct file *exe_file)
31403139
allow_write_access(exe_file);
31413140
}
31423141

3142+
static inline void file_set_fsnotify_mode(struct file *file, fmode_t mode)
3143+
{
3144+
file->f_mode &= ~FMODE_FSNOTIFY_MASK;
3145+
file->f_mode |= mode;
3146+
}
3147+
31433148
static inline bool inode_is_open_for_write(const struct inode *inode)
31443149
{
31453150
return atomic_read(&inode->i_writecount) > 0;

Diff for: include/linux/fsnotify.h

+2-2
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,7 @@ static inline int fsnotify_file(struct file *file, __u32 mask)
129129

130130
#ifdef CONFIG_FANOTIFY_ACCESS_PERMISSIONS
131131

132-
void file_set_fsnotify_mode(struct file *file);
132+
void file_set_fsnotify_mode_from_watchers(struct file *file);
133133

134134
/*
135135
* fsnotify_file_area_perm - permission hook before access to file range
@@ -213,7 +213,7 @@ static inline int fsnotify_open_perm(struct file *file)
213213
}
214214

215215
#else
216-
static inline void file_set_fsnotify_mode(struct file *file)
216+
static inline void file_set_fsnotify_mode_from_watchers(struct file *file)
217217
{
218218
}
219219

Diff for: net/socket.c

+5
Original file line numberDiff line numberDiff line change
@@ -479,6 +479,11 @@ struct file *sock_alloc_file(struct socket *sock, int flags, const char *dname)
479479
sock->file = file;
480480
file->private_data = sock;
481481
stream_open(SOCK_INODE(sock), file);
482+
/*
483+
* Disable permission and pre-content events, but enable legacy
484+
* inotify events for legacy users.
485+
*/
486+
file_set_fsnotify_mode(file, FMODE_NONOTIFY_PERM);
482487
return file;
483488
}
484489
EXPORT_SYMBOL(sock_alloc_file);

0 commit comments

Comments
 (0)