-----BEGIN PGP SIGNATURE-----
 
 iQEzBAABCAAdFiEEq1nRK9aeMoq1VSgcnJ2qBz9kQNkFAl0kWgwACgkQnJ2qBz9k
 QNkkdggA7bdy6xZRPdumZMxtASGDs1JJ4diNs+apgyc6wUfsT1lCE2ap20EdzfzK
 drAvlJt1vYEW+6apOzUXJ0qWXMVRzy4XRl+jVMO9GW6BoY4OyJQ86AQZlEv1zZ4n
 vxeYnlbxA7JyfkWgup0ZSb5EKRSO1eSxZKEZou0wu2jRCRr/E5RyjPQHXaiE5ihc
 7ilEtTI3Qg3nnAK30F0Iy0X3lGqgXj+rlJ0TgR8BBEDllct2wV16vvMl/Sy+BXip
 5sSWjSy8zntMnkSN8yH/oJN0D+fqmCsnYafwqTpPek8izvEz4xpjshbWTDnPm0HM
 eiMC1U3ZJoD3Z4/wxRZ91m60VYgJBA==
 =SVKR
 -----END PGP SIGNATURE-----

Merge tag 'fsnotify_for_v5.3-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/jack/linux-fs

Pull fsnotify updates from Jan Kara:
 "This contains cleanups of the fsnotify name removal hook and also a
  patch to disable fanotify permission events for 'proc' filesystem"

* tag 'fsnotify_for_v5.3-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/jack/linux-fs:
  fsnotify: get rid of fsnotify_nameremove()
  fsnotify: move fsnotify_nameremove() hook out of d_delete()
  configfs: call fsnotify_rmdir() hook
  debugfs: call fsnotify_{unlink,rmdir}() hooks
  debugfs: simplify __debugfs_remove_file()
  devpts: call fsnotify_unlink() hook
  tracefs: call fsnotify_{unlink,rmdir}() hooks
  rpc_pipefs: call fsnotify_{unlink,rmdir}() hooks
  btrfs: call fsnotify_rmdir() hook
  fsnotify: add empty fsnotify_{unlink,rmdir}() hooks
  fanotify: Disallow permission events for proc filesystem
This commit is contained in:
Linus Torvalds 2019-07-10 20:09:17 -07:00
Родитель 988052f47a 7377f5bec1
Коммит e6983afd92
16 изменённых файлов: 76 добавлений и 71 удалений

Просмотреть файл

@ -60,11 +60,6 @@ static int afs_do_silly_rename(struct afs_vnode *dvnode, struct afs_vnode *vnode
if (test_bit(AFS_VNODE_DIR_VALID, &dvnode->flags))
afs_edit_dir_add(dvnode, &new->d_name,
&vnode->fid, afs_edit_dir_for_silly_1);
/* vfs_unlink and the like do not issue this when a file is
* sillyrenamed, so do it here.
*/
fsnotify_nameremove(old, 0);
}
kfree(scb);

Просмотреть файл

@ -2928,8 +2928,10 @@ static noinline int btrfs_ioctl_snap_destroy(struct file *file,
inode_lock(inode);
err = btrfs_delete_subvolume(dir, dentry);
inode_unlock(inode);
if (!err)
if (!err) {
fsnotify_rmdir(dir, dentry);
d_delete(dentry);
}
out_dput:
dput(dentry);

Просмотреть файл

@ -13,6 +13,7 @@
#undef DEBUG
#include <linux/fs.h>
#include <linux/fsnotify.h>
#include <linux/mount.h>
#include <linux/module.h>
#include <linux/slab.h>
@ -1788,6 +1789,7 @@ void configfs_unregister_group(struct config_group *group)
configfs_detach_group(&group->cg_item);
d_inode(dentry)->i_flags |= S_DEAD;
dont_mount(dentry);
fsnotify_rmdir(d_inode(parent), dentry);
d_delete(dentry);
inode_unlock(d_inode(parent));
@ -1916,6 +1918,7 @@ void configfs_unregister_subsystem(struct configfs_subsystem *subsys)
configfs_detach_group(&group->cg_item);
d_inode(dentry)->i_flags |= S_DEAD;
dont_mount(dentry);
fsnotify_rmdir(d_inode(root), dentry);
inode_unlock(d_inode(dentry));
d_delete(dentry);

Просмотреть файл

@ -2372,7 +2372,6 @@ EXPORT_SYMBOL(d_hash_and_lookup);
void d_delete(struct dentry * dentry)
{
struct inode *inode = dentry->d_inode;
int isdir = d_is_dir(dentry);
spin_lock(&inode->i_lock);
spin_lock(&dentry->d_lock);
@ -2387,7 +2386,6 @@ void d_delete(struct dentry * dentry)
spin_unlock(&dentry->d_lock);
spin_unlock(&inode->i_lock);
}
fsnotify_nameremove(dentry, isdir);
}
EXPORT_SYMBOL(d_delete);

Просмотреть файл

@ -617,13 +617,10 @@ struct dentry *debugfs_create_symlink(const char *name, struct dentry *parent,
}
EXPORT_SYMBOL_GPL(debugfs_create_symlink);
static void __debugfs_remove_file(struct dentry *dentry, struct dentry *parent)
static void __debugfs_file_removed(struct dentry *dentry)
{
struct debugfs_fsdata *fsd;
simple_unlink(d_inode(parent), dentry);
d_delete(dentry);
/*
* Paired with the closing smp_mb() implied by a successful
* cmpxchg() in debugfs_file_get(): either
@ -644,16 +641,18 @@ static int __debugfs_remove(struct dentry *dentry, struct dentry *parent)
if (simple_positive(dentry)) {
dget(dentry);
if (!d_is_reg(dentry)) {
if (d_is_dir(dentry))
ret = simple_rmdir(d_inode(parent), dentry);
else
simple_unlink(d_inode(parent), dentry);
if (d_is_dir(dentry)) {
ret = simple_rmdir(d_inode(parent), dentry);
if (!ret)
d_delete(dentry);
fsnotify_rmdir(d_inode(parent), dentry);
} else {
__debugfs_remove_file(dentry, parent);
simple_unlink(d_inode(parent), dentry);
fsnotify_unlink(d_inode(parent), dentry);
}
if (!ret)
d_delete(dentry);
if (d_is_reg(dentry))
__debugfs_file_removed(dentry);
dput(dentry);
}
return ret;

Просмотреть файл

@ -621,6 +621,7 @@ void devpts_pty_kill(struct dentry *dentry)
dentry->d_fsdata = NULL;
drop_nlink(dentry->d_inode);
fsnotify_unlink(d_inode(dentry->d_parent), dentry);
d_delete(dentry);
dput(dentry); /* d_alloc_name() in devpts_pty_new() */
}

Просмотреть файл

@ -3883,6 +3883,7 @@ int vfs_rmdir(struct inode *dir, struct dentry *dentry)
dentry->d_inode->i_flags |= S_DEAD;
dont_mount(dentry);
detach_mounts(dentry);
fsnotify_rmdir(dir, dentry);
out:
inode_unlock(dentry->d_inode);
@ -3999,6 +4000,7 @@ int vfs_unlink(struct inode *dir, struct dentry *dentry, struct inode **delegate
if (!error) {
dont_mount(dentry);
detach_mounts(dentry);
fsnotify_unlink(dir, dentry);
}
}
}

Просмотреть файл

@ -396,12 +396,6 @@ nfs_complete_sillyrename(struct rpc_task *task, struct nfs_renamedata *data)
nfs_cancel_async_unlink(dentry);
return;
}
/*
* vfs_unlink and the like do not issue this when a file is
* sillyrenamed, so do it here.
*/
fsnotify_nameremove(dentry, 0);
}
#define SILLYNAME_PREFIX ".nfs"

Просмотреть файл

@ -920,6 +920,22 @@ static int fanotify_test_fid(struct path *path, __kernel_fsid_t *fsid)
return 0;
}
static int fanotify_events_supported(struct path *path, __u64 mask)
{
/*
* Some filesystems such as 'proc' acquire unusual locks when opening
* files. For them fanotify permission events have high chances of
* deadlocking the system - open done when reporting fanotify event
* blocks on this "unusual" lock while another process holding the lock
* waits for fanotify permission event to be answered. Just disallow
* permission events for such filesystems.
*/
if (mask & FANOTIFY_PERM_EVENTS &&
path->mnt->mnt_sb->s_type->fs_flags & FS_DISALLOW_NOTIFY_PERM)
return -EINVAL;
return 0;
}
static int do_fanotify_mark(int fanotify_fd, unsigned int flags, __u64 mask,
int dfd, const char __user *pathname)
{
@ -1018,6 +1034,12 @@ static int do_fanotify_mark(int fanotify_fd, unsigned int flags, __u64 mask,
if (ret)
goto fput_and_out;
if (flags & FAN_MARK_ADD) {
ret = fanotify_events_supported(&path, mask);
if (ret)
goto path_put_and_out;
}
if (FAN_GROUP_FLAG(group, FAN_REPORT_FID)) {
ret = fanotify_test_fid(&path, &__fsid);
if (ret)

Просмотреть файл

@ -94,47 +94,6 @@ void fsnotify_sb_delete(struct super_block *sb)
fsnotify_clear_marks_by_sb(sb);
}
/*
* fsnotify_nameremove - a filename was removed from a directory
*
* This is mostly called under parent vfs inode lock so name and
* dentry->d_parent should be stable. However there are some corner cases where
* inode lock is not held. So to be on the safe side and be reselient to future
* callers and out of tree users of d_delete(), we do not assume that d_parent
* and d_name are stable and we use dget_parent() and
* take_dentry_name_snapshot() to grab stable references.
*/
void fsnotify_nameremove(struct dentry *dentry, int isdir)
{
struct dentry *parent;
struct name_snapshot name;
__u32 mask = FS_DELETE;
/* d_delete() of pseudo inode? (e.g. __ns_get_path() playing tricks) */
if (IS_ROOT(dentry))
return;
if (isdir)
mask |= FS_ISDIR;
parent = dget_parent(dentry);
/* Avoid unneeded take_dentry_name_snapshot() */
if (!(d_inode(parent)->i_fsnotify_mask & FS_DELETE) &&
!(dentry->d_sb->s_fsnotify_mask & FS_DELETE))
goto out_dput;
take_dentry_name_snapshot(&name, dentry);
fsnotify(d_inode(parent), mask, d_inode(dentry), FSNOTIFY_EVENT_INODE,
&name.name, 0);
release_dentry_name_snapshot(&name);
out_dput:
dput(parent);
}
EXPORT_SYMBOL(fsnotify_nameremove);
/*
* Given an inode, first check if we care what happens to our children. Inotify
* and dnotify both tell their parents about events. If we care about any event

Просмотреть файл

@ -211,7 +211,7 @@ static struct file_system_type proc_fs_type = {
.init_fs_context = proc_init_fs_context,
.parameters = &proc_fs_parameters,
.kill_sb = proc_kill_sb,
.fs_flags = FS_USERNS_MOUNT,
.fs_flags = FS_USERNS_MOUNT | FS_DISALLOW_NOTIFY_PERM,
};
void __init proc_root_init(void)

Просмотреть файл

@ -505,9 +505,12 @@ static int __tracefs_remove(struct dentry *dentry, struct dentry *parent)
switch (dentry->d_inode->i_mode & S_IFMT) {
case S_IFDIR:
ret = simple_rmdir(parent->d_inode, dentry);
if (!ret)
fsnotify_rmdir(parent->d_inode, dentry);
break;
default:
simple_unlink(parent->d_inode, dentry);
fsnotify_unlink(parent->d_inode, dentry);
break;
}
if (!ret)

Просмотреть файл

@ -2184,6 +2184,7 @@ struct file_system_type {
#define FS_BINARY_MOUNTDATA 2
#define FS_HAS_SUBTYPE 4
#define FS_USERNS_MOUNT 8 /* Can be mounted by userns root */
#define FS_DISALLOW_NOTIFY_PERM 16 /* Disable fanotify permission events */
#define FS_RENAME_DOES_D_MOVE 32768 /* FS will handle d_move() during rename() internally. */
int (*init_fs_context)(struct fs_context *);
const struct fs_parameter_description *parameters;

Просмотреть файл

@ -188,6 +188,19 @@ static inline void fsnotify_link(struct inode *dir, struct inode *inode, struct
fsnotify(dir, FS_CREATE, inode, FSNOTIFY_EVENT_INODE, &new_dentry->d_name, 0);
}
/*
* fsnotify_unlink - 'name' was unlinked
*
* Caller must make sure that dentry->d_name is stable.
*/
static inline void fsnotify_unlink(struct inode *dir, struct dentry *dentry)
{
/* Expected to be called before d_delete() */
WARN_ON_ONCE(d_is_negative(dentry));
fsnotify_dirent(dir, dentry, FS_DELETE);
}
/*
* fsnotify_mkdir - directory 'name' was created
*/
@ -198,6 +211,19 @@ static inline void fsnotify_mkdir(struct inode *inode, struct dentry *dentry)
fsnotify_dirent(inode, dentry, FS_CREATE | FS_ISDIR);
}
/*
* fsnotify_rmdir - directory 'name' was removed
*
* Caller must make sure that dentry->d_name is stable.
*/
static inline void fsnotify_rmdir(struct inode *dir, struct dentry *dentry)
{
/* Expected to be called before d_delete() */
WARN_ON_ONCE(d_is_negative(dentry));
fsnotify_dirent(dir, dentry, FS_DELETE | FS_ISDIR);
}
/*
* fsnotify_access - file was read
*/

Просмотреть файл

@ -357,7 +357,6 @@ extern int __fsnotify_parent(const struct path *path, struct dentry *dentry, __u
extern void __fsnotify_inode_delete(struct inode *inode);
extern void __fsnotify_vfsmount_delete(struct vfsmount *mnt);
extern void fsnotify_sb_delete(struct super_block *sb);
extern void fsnotify_nameremove(struct dentry *dentry, int isdir);
extern u32 fsnotify_get_cookie(void);
static inline int fsnotify_inode_watches_children(struct inode *inode)
@ -527,9 +526,6 @@ static inline void __fsnotify_vfsmount_delete(struct vfsmount *mnt)
static inline void fsnotify_sb_delete(struct super_block *sb)
{}
static inline void fsnotify_nameremove(struct dentry *dentry, int isdir)
{}
static inline void fsnotify_update_flags(struct dentry *dentry)
{}

Просмотреть файл

@ -598,6 +598,8 @@ static int __rpc_rmdir(struct inode *dir, struct dentry *dentry)
dget(dentry);
ret = simple_rmdir(dir, dentry);
if (!ret)
fsnotify_rmdir(dir, dentry);
d_delete(dentry);
dput(dentry);
return ret;
@ -609,6 +611,8 @@ static int __rpc_unlink(struct inode *dir, struct dentry *dentry)
dget(dentry);
ret = simple_unlink(dir, dentry);
if (!ret)
fsnotify_unlink(dir, dentry);
d_delete(dentry);
dput(dentry);
return ret;