mirror of
git://git.yoctoproject.org/linux-yocto.git
synced 2025-10-22 23:13:01 +02:00
\n
-----BEGIN PGP SIGNATURE----- iQEzBAABCAAdFiEEq1nRK9aeMoq1VSgcnJ2qBz9kQNkFAmiHoygACgkQnJ2qBz9k QNnQCwf9Et0BcGgtcE9bUPJMlK5AEJ2nsEGT24ajRPcJ9DtcpO5KY8htshPwvRBc KeSW3bjYaBluKK6LmbvDbaDi4lBwFNKh+dfi8PeVwBECNn2DLNv+EOB6VPgxREWw zmC3SL2oh7eGTtJq0h1XeI/s/AFYukOsjKcjoKmT3NyxkCwxYUoY3E1mePutBsW6 /2CjVdQoMUgw1kLcezdccOJi6IkAk5Vfr8gIRFucQiR49YIICYk17bhYBH/Gx5PJ eJkqncq8FLv8gLaaHq5W8lC05nVnpNDFxUxKiN6YcuYUrUC7jFi7ad1EriZP3Zsr y8pDAmVUHgzpiMYiPHhP2zG8xK06TQ== =ZyXo -----END PGP SIGNATURE----- Merge tag 'fsnotify_for_v6.17-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/jack/linux-fs Pull fsnotify updates from Jan Kara: "A couple of small improvements for fsnotify subsystem. The most interesting is probably Amir's change modifying the meaning of fsnotify fmode bits (and I spell it out specifically because I know you care about those). There's no change for the common cases of no fsnotify watches or no permission event watches. But when there are permission watches (either for open or for pre-content events) but no FAN_ACCESS_PERM watch (which nobody uses in practice) we are now able optimize away unnecessary cache loads from the read path" * tag 'fsnotify_for_v6.17-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/jack/linux-fs: fsnotify: optimize FMODE_NONOTIFY_PERM for the common cases fsnotify: merge file_set_fsnotify_mode_from_watchers() with open perm hook samples: fix building fs-monitor on musl systems fanotify: sanitize handle_type values when reporting fid
This commit is contained in:
commit
d6084bb815
|
@ -199,7 +199,7 @@ static int init_file(struct file *f, int flags, const struct cred *cred)
|
|||
file_ref_init(&f->f_ref, 1);
|
||||
/*
|
||||
* Disable permission and pre-content events for all files by default.
|
||||
* They may be enabled later by file_set_fsnotify_mode_from_watchers().
|
||||
* They may be enabled later by fsnotify_open_perm_and_set_mode().
|
||||
*/
|
||||
file_set_fsnotify_mode(f, FMODE_NONOTIFY_PERM);
|
||||
return 0;
|
||||
|
|
|
@ -454,7 +454,13 @@ static int fanotify_encode_fh(struct fanotify_fh *fh, struct inode *inode,
|
|||
dwords = fh_len >> 2;
|
||||
type = exportfs_encode_fid(inode, buf, &dwords);
|
||||
err = -EINVAL;
|
||||
if (type <= 0 || type == FILEID_INVALID || fh_len != dwords << 2)
|
||||
/*
|
||||
* Unlike file_handle, type and len of struct fanotify_fh are u8.
|
||||
* Traditionally, filesystem return handle_type < 0xff, but there
|
||||
* is no enforecement for that in vfs.
|
||||
*/
|
||||
BUILD_BUG_ON(MAX_HANDLE_SZ > 0xff || FILEID_INVALID > 0xff);
|
||||
if (type <= 0 || type >= FILEID_INVALID || fh_len != dwords << 2)
|
||||
goto out_err;
|
||||
|
||||
fh->type = type;
|
||||
|
|
|
@ -199,8 +199,8 @@ static bool fsnotify_event_needs_parent(struct inode *inode, __u32 mnt_mask,
|
|||
}
|
||||
|
||||
/* Are there any inode/mount/sb objects that watch for these events? */
|
||||
static inline bool fsnotify_object_watched(struct inode *inode, __u32 mnt_mask,
|
||||
__u32 mask)
|
||||
static inline __u32 fsnotify_object_watched(struct inode *inode, __u32 mnt_mask,
|
||||
__u32 mask)
|
||||
{
|
||||
__u32 marks_mask = READ_ONCE(inode->i_fsnotify_mask) | mnt_mask |
|
||||
READ_ONCE(inode->i_sb->s_fsnotify_mask);
|
||||
|
@ -656,20 +656,20 @@ EXPORT_SYMBOL_GPL(fsnotify);
|
|||
|
||||
#ifdef CONFIG_FANOTIFY_ACCESS_PERMISSIONS
|
||||
/*
|
||||
* At open time we check fsnotify_sb_has_priority_watchers() and set the
|
||||
* FMODE_NONOTIFY_ mode bits accordignly.
|
||||
* At open time we check fsnotify_sb_has_priority_watchers(), call the open perm
|
||||
* hook and set the FMODE_NONOTIFY_ mode bits accordignly.
|
||||
* Later, fsnotify permission hooks do not check if there are permission event
|
||||
* watches, but that there were permission event watches at open time.
|
||||
*/
|
||||
void file_set_fsnotify_mode_from_watchers(struct file *file)
|
||||
int fsnotify_open_perm_and_set_mode(struct file *file)
|
||||
{
|
||||
struct dentry *dentry = file->f_path.dentry, *parent;
|
||||
struct super_block *sb = dentry->d_sb;
|
||||
__u32 mnt_mask, p_mask;
|
||||
__u32 mnt_mask, p_mask = 0;
|
||||
|
||||
/* Is it a file opened by fanotify? */
|
||||
if (FMODE_FSNOTIFY_NONE(file->f_mode))
|
||||
return;
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* Permission events is a super set of pre-content events, so if there
|
||||
|
@ -679,45 +679,64 @@ void file_set_fsnotify_mode_from_watchers(struct file *file)
|
|||
if (likely(!fsnotify_sb_has_priority_watchers(sb,
|
||||
FSNOTIFY_PRIO_CONTENT))) {
|
||||
file_set_fsnotify_mode(file, FMODE_NONOTIFY_PERM);
|
||||
return;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* If there are permission event watchers but no pre-content event
|
||||
* watchers, set FMODE_NONOTIFY | FMODE_NONOTIFY_PERM to indicate that.
|
||||
*/
|
||||
if ((!d_is_dir(dentry) && !d_is_reg(dentry)) ||
|
||||
likely(!fsnotify_sb_has_priority_watchers(sb,
|
||||
FSNOTIFY_PRIO_PRE_CONTENT))) {
|
||||
file_set_fsnotify_mode(file, FMODE_NONOTIFY | FMODE_NONOTIFY_PERM);
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* OK, there are some pre-content watchers. Check if anybody is
|
||||
* watching for pre-content events on *this* file.
|
||||
* OK, there are some permission event watchers. Check if anybody is
|
||||
* watching for permission events on *this* file.
|
||||
*/
|
||||
mnt_mask = READ_ONCE(real_mount(file->f_path.mnt)->mnt_fsnotify_mask);
|
||||
if (unlikely(fsnotify_object_watched(d_inode(dentry), mnt_mask,
|
||||
FSNOTIFY_PRE_CONTENT_EVENTS))) {
|
||||
/* Enable pre-content events */
|
||||
file_set_fsnotify_mode(file, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Is parent watching for pre-content events on this file? */
|
||||
p_mask = fsnotify_object_watched(d_inode(dentry), mnt_mask,
|
||||
ALL_FSNOTIFY_PERM_EVENTS);
|
||||
if (dentry->d_flags & DCACHE_FSNOTIFY_PARENT_WATCHED) {
|
||||
parent = dget_parent(dentry);
|
||||
p_mask = fsnotify_inode_watches_children(d_inode(parent));
|
||||
p_mask |= fsnotify_inode_watches_children(d_inode(parent));
|
||||
dput(parent);
|
||||
if (p_mask & FSNOTIFY_PRE_CONTENT_EVENTS) {
|
||||
/* Enable pre-content events */
|
||||
file_set_fsnotify_mode(file, 0);
|
||||
return;
|
||||
}
|
||||
}
|
||||
/* Nobody watching for pre-content events from this file */
|
||||
file_set_fsnotify_mode(file, FMODE_NONOTIFY | FMODE_NONOTIFY_PERM);
|
||||
|
||||
/*
|
||||
* Legacy FAN_ACCESS_PERM events have very high performance overhead,
|
||||
* so unlikely to be used in the wild. If they are used there will be
|
||||
* no optimizations at all.
|
||||
*/
|
||||
if (unlikely(p_mask & FS_ACCESS_PERM)) {
|
||||
/* Enable all permission and pre-content events */
|
||||
file_set_fsnotify_mode(file, 0);
|
||||
goto open_perm;
|
||||
}
|
||||
|
||||
/*
|
||||
* Pre-content events are only supported on regular files.
|
||||
* If there are pre-content event watchers and no permission access
|
||||
* watchers, set FMODE_NONOTIFY | FMODE_NONOTIFY_PERM to indicate that.
|
||||
* That is the common case with HSM service.
|
||||
*/
|
||||
if (d_is_reg(dentry) && (p_mask & FSNOTIFY_PRE_CONTENT_EVENTS)) {
|
||||
file_set_fsnotify_mode(file, FMODE_NONOTIFY |
|
||||
FMODE_NONOTIFY_PERM);
|
||||
goto open_perm;
|
||||
}
|
||||
|
||||
/* Nobody watching permission and pre-content events on this file */
|
||||
file_set_fsnotify_mode(file, FMODE_NONOTIFY_PERM);
|
||||
|
||||
open_perm:
|
||||
/*
|
||||
* Send open perm events depending on object masks and regardless of
|
||||
* FMODE_NONOTIFY_PERM.
|
||||
*/
|
||||
if (file->f_flags & __FMODE_EXEC && p_mask & FS_OPEN_EXEC_PERM) {
|
||||
int ret = fsnotify_path(&file->f_path, FS_OPEN_EXEC_PERM);
|
||||
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (p_mask & FS_OPEN_PERM)
|
||||
return fsnotify_path(&file->f_path, FS_OPEN_PERM);
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
|
@ -944,12 +944,12 @@ static int do_dentry_open(struct file *f,
|
|||
goto cleanup_all;
|
||||
|
||||
/*
|
||||
* Set FMODE_NONOTIFY_* bits according to existing permission watches.
|
||||
* Call fsnotify open permission hook and set FMODE_NONOTIFY_* bits
|
||||
* according to existing permission watches.
|
||||
* If FMODE_NONOTIFY mode was already set for an fanotify fd or for a
|
||||
* pseudo file, this call will not change the mode.
|
||||
*/
|
||||
file_set_fsnotify_mode_from_watchers(f);
|
||||
error = fsnotify_open_perm(f);
|
||||
error = fsnotify_open_perm_and_set_mode(f);
|
||||
if (error)
|
||||
goto cleanup_all;
|
||||
|
||||
|
|
|
@ -200,12 +200,12 @@ typedef int (dio_iodone_t)(struct kiocb *iocb, loff_t offset,
|
|||
|
||||
/*
|
||||
* The two FMODE_NONOTIFY* define which fsnotify events should not be generated
|
||||
* for a file. These are the possible values of (f->f_mode &
|
||||
* FMODE_FSNOTIFY_MASK) and their meaning:
|
||||
* for an open file. These are the possible values of
|
||||
* (f->f_mode & FMODE_FSNOTIFY_MASK) and their meaning:
|
||||
*
|
||||
* FMODE_NONOTIFY - suppress all (incl. non-permission) events.
|
||||
* FMODE_NONOTIFY_PERM - suppress permission (incl. pre-content) events.
|
||||
* FMODE_NONOTIFY | FMODE_NONOTIFY_PERM - suppress only pre-content events.
|
||||
* FMODE_NONOTIFY | FMODE_NONOTIFY_PERM - suppress only FAN_ACCESS_PERM.
|
||||
*/
|
||||
#define FMODE_FSNOTIFY_MASK \
|
||||
(FMODE_NONOTIFY | FMODE_NONOTIFY_PERM)
|
||||
|
@ -213,13 +213,13 @@ typedef int (dio_iodone_t)(struct kiocb *iocb, loff_t offset,
|
|||
#define FMODE_FSNOTIFY_NONE(mode) \
|
||||
((mode & FMODE_FSNOTIFY_MASK) == FMODE_NONOTIFY)
|
||||
#ifdef CONFIG_FANOTIFY_ACCESS_PERMISSIONS
|
||||
#define FMODE_FSNOTIFY_PERM(mode) \
|
||||
#define FMODE_FSNOTIFY_HSM(mode) \
|
||||
((mode & FMODE_FSNOTIFY_MASK) == 0 || \
|
||||
(mode & FMODE_FSNOTIFY_MASK) == (FMODE_NONOTIFY | FMODE_NONOTIFY_PERM))
|
||||
#define FMODE_FSNOTIFY_HSM(mode) \
|
||||
#define FMODE_FSNOTIFY_ACCESS_PERM(mode) \
|
||||
((mode & FMODE_FSNOTIFY_MASK) == 0)
|
||||
#else
|
||||
#define FMODE_FSNOTIFY_PERM(mode) 0
|
||||
#define FMODE_FSNOTIFY_ACCESS_PERM(mode) 0
|
||||
#define FMODE_FSNOTIFY_HSM(mode) 0
|
||||
#endif
|
||||
|
||||
|
|
|
@ -129,7 +129,7 @@ static inline int fsnotify_file(struct file *file, __u32 mask)
|
|||
|
||||
#ifdef CONFIG_FANOTIFY_ACCESS_PERMISSIONS
|
||||
|
||||
void file_set_fsnotify_mode_from_watchers(struct file *file);
|
||||
int fsnotify_open_perm_and_set_mode(struct file *file);
|
||||
|
||||
/*
|
||||
* fsnotify_file_area_perm - permission hook before access to file range
|
||||
|
@ -147,9 +147,6 @@ static inline int fsnotify_file_area_perm(struct file *file, int perm_mask,
|
|||
if (!(perm_mask & (MAY_READ | MAY_WRITE | MAY_ACCESS)))
|
||||
return 0;
|
||||
|
||||
if (likely(!FMODE_FSNOTIFY_PERM(file->f_mode)))
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* read()/write() and other types of access generate pre-content events.
|
||||
*/
|
||||
|
@ -160,7 +157,8 @@ static inline int fsnotify_file_area_perm(struct file *file, int perm_mask,
|
|||
return ret;
|
||||
}
|
||||
|
||||
if (!(perm_mask & MAY_READ))
|
||||
if (!(perm_mask & MAY_READ) ||
|
||||
likely(!FMODE_FSNOTIFY_ACCESS_PERM(file->f_mode)))
|
||||
return 0;
|
||||
|
||||
/*
|
||||
|
@ -208,28 +206,10 @@ static inline int fsnotify_file_perm(struct file *file, int perm_mask)
|
|||
return fsnotify_file_area_perm(file, perm_mask, NULL, 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* fsnotify_open_perm - permission hook before file open
|
||||
*/
|
||||
static inline int fsnotify_open_perm(struct file *file)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (likely(!FMODE_FSNOTIFY_PERM(file->f_mode)))
|
||||
return 0;
|
||||
|
||||
if (file->f_flags & __FMODE_EXEC) {
|
||||
ret = fsnotify_path(&file->f_path, FS_OPEN_EXEC_PERM);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
return fsnotify_path(&file->f_path, FS_OPEN_PERM);
|
||||
}
|
||||
|
||||
#else
|
||||
static inline void file_set_fsnotify_mode_from_watchers(struct file *file)
|
||||
static inline int fsnotify_open_perm_and_set_mode(struct file *file)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int fsnotify_file_area_perm(struct file *file, int perm_mask,
|
||||
|
@ -253,11 +233,6 @@ static inline int fsnotify_file_perm(struct file *file, int perm_mask)
|
|||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int fsnotify_open_perm(struct file *file)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
|
|
|
@ -12,6 +12,9 @@
|
|||
#include <sys/fanotify.h>
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
#ifndef __GLIBC__
|
||||
#include <asm-generic/int-ll64.h>
|
||||
#endif
|
||||
|
||||
#ifndef FAN_FS_ERROR
|
||||
#define FAN_FS_ERROR 0x00008000
|
||||
|
@ -95,7 +98,11 @@ static void handle_notifications(char *buffer, int len)
|
|||
fid = (struct fanotify_event_info_fid *) info;
|
||||
|
||||
printf("\tfsid: %x%x\n",
|
||||
#if defined(__GLIBC__)
|
||||
fid->fsid.val[0], fid->fsid.val[1]);
|
||||
#else
|
||||
fid->fsid.__val[0], fid->fsid.__val[1]);
|
||||
#endif
|
||||
print_fh((struct file_handle *) &fid->handle);
|
||||
break;
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user