forked from Minki/linux
\n
-----BEGIN PGP SIGNATURE----- iQEzBAABCAAdFiEEq1nRK9aeMoq1VSgcnJ2qBz9kQNkFAlwbm5YACgkQnJ2qBz9k QNnF5wf+L9lWe4LzGf3sCc45JFtcsvLtcYd0XSn93ATRPSIxNYCCDEdvJ9UGfGhG +2y4Z42KBWkqg2Dx8W2yiQjP1RxJTbWIAEE7uKKyWIojNMbtpjSjRw/n7VmCG7m/ ZHhO3XITHYRCVruIKVfwC0a9zPNWD6RD4+IhHRrZomC1ZrfTzs0OBc6PADXLchdR 0QRkpWlomD3CASGVioYbOFqX3pcDJWUdoFvOyMu2sELkJzAJjC7spB+MfoFeRJsA QEUoRAdWCSFtxcuM6bkNMc1zXig3niLBka/ozXvwA0192rbOcyGvua3PwqYTdqnu Bea36CD2G+ta0cBv1M5s7e87surttw== =wdFw -----END PGP SIGNATURE----- Merge tag 'fsnotify_for_v4.21-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/jack/linux-fs Pull fsnotify updates from Jan Kara: "Support for new FAN_OPEN_EXEC event and couple of cleanups around fsnotify" * tag 'fsnotify_for_v4.21-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/jack/linux-fs: fanotify: Use inode_is_open_for_write fanotify: Make sure to check event_len when copying fsnotify/fdinfo: include fdinfo.h for inotify_show_fdinfo() fanotify: introduce new event mask FAN_OPEN_EXEC_PERM fsnotify: refactor fsnotify_parent()/fsnotify() paired calls when event is on path fanotify: introduce new event mask FAN_OPEN_EXEC fanotify: return only user requested event types in event mask
This commit is contained in:
commit
4b0a383ad7
@ -89,7 +89,13 @@ static int fanotify_get_response(struct fsnotify_group *group,
|
||||
return ret;
|
||||
}
|
||||
|
||||
static bool fanotify_should_send_event(struct fsnotify_iter_info *iter_info,
|
||||
/*
|
||||
* This function returns a mask for an event that only contains the flags
|
||||
* that have been specifically requested by the user. Flags that may have
|
||||
* been included within the event mask, but have not been explicitly
|
||||
* requested by the user, will not be present in the returned mask.
|
||||
*/
|
||||
static u32 fanotify_group_event_mask(struct fsnotify_iter_info *iter_info,
|
||||
u32 event_mask, const void *data,
|
||||
int data_type)
|
||||
{
|
||||
@ -101,14 +107,14 @@ static bool fanotify_should_send_event(struct fsnotify_iter_info *iter_info,
|
||||
pr_debug("%s: report_mask=%x mask=%x data=%p data_type=%d\n",
|
||||
__func__, iter_info->report_mask, event_mask, data, data_type);
|
||||
|
||||
/* if we don't have enough info to send an event to userspace say no */
|
||||
/* If we don't have enough info to send an event to userspace say no */
|
||||
if (data_type != FSNOTIFY_EVENT_PATH)
|
||||
return false;
|
||||
return 0;
|
||||
|
||||
/* sorry, fanotify only gives a damn about files and dirs */
|
||||
/* Sorry, fanotify only gives a damn about files and dirs */
|
||||
if (!d_is_reg(path->dentry) &&
|
||||
!d_can_lookup(path->dentry))
|
||||
return false;
|
||||
return 0;
|
||||
|
||||
fsnotify_foreach_obj_type(type) {
|
||||
if (!fsnotify_iter_should_report_type(iter_info, type))
|
||||
@ -129,13 +135,10 @@ static bool fanotify_should_send_event(struct fsnotify_iter_info *iter_info,
|
||||
|
||||
if (d_is_dir(path->dentry) &&
|
||||
!(marks_mask & FS_ISDIR & ~marks_ignored_mask))
|
||||
return false;
|
||||
return 0;
|
||||
|
||||
if (event_mask & FANOTIFY_OUTGOING_EVENTS &
|
||||
marks_mask & ~marks_ignored_mask)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
return event_mask & FANOTIFY_OUTGOING_EVENTS & marks_mask &
|
||||
~marks_ignored_mask;
|
||||
}
|
||||
|
||||
struct fanotify_event_info *fanotify_alloc_event(struct fsnotify_group *group,
|
||||
@ -207,10 +210,13 @@ static int fanotify_handle_event(struct fsnotify_group *group,
|
||||
BUILD_BUG_ON(FAN_OPEN_PERM != FS_OPEN_PERM);
|
||||
BUILD_BUG_ON(FAN_ACCESS_PERM != FS_ACCESS_PERM);
|
||||
BUILD_BUG_ON(FAN_ONDIR != FS_ISDIR);
|
||||
BUILD_BUG_ON(FAN_OPEN_EXEC != FS_OPEN_EXEC);
|
||||
BUILD_BUG_ON(FAN_OPEN_EXEC_PERM != FS_OPEN_EXEC_PERM);
|
||||
|
||||
BUILD_BUG_ON(HWEIGHT32(ALL_FANOTIFY_EVENT_BITS) != 10);
|
||||
BUILD_BUG_ON(HWEIGHT32(ALL_FANOTIFY_EVENT_BITS) != 12);
|
||||
|
||||
if (!fanotify_should_send_event(iter_info, mask, data, data_type))
|
||||
mask = fanotify_group_event_mask(iter_info, mask, data, data_type);
|
||||
if (!mask)
|
||||
return 0;
|
||||
|
||||
pr_debug("%s: group=%p inode=%p mask=%x\n", __func__, group, inode,
|
||||
|
@ -206,7 +206,7 @@ static int process_access_response(struct fsnotify_group *group,
|
||||
|
||||
static ssize_t copy_event_to_user(struct fsnotify_group *group,
|
||||
struct fsnotify_event *event,
|
||||
char __user *buf)
|
||||
char __user *buf, size_t count)
|
||||
{
|
||||
struct fanotify_event_metadata fanotify_event_metadata;
|
||||
struct file *f;
|
||||
@ -220,6 +220,12 @@ static ssize_t copy_event_to_user(struct fsnotify_group *group,
|
||||
|
||||
fd = fanotify_event_metadata.fd;
|
||||
ret = -EFAULT;
|
||||
/*
|
||||
* Sanity check copy size in case get_one_event() and
|
||||
* fill_event_metadata() event_len sizes ever get out of sync.
|
||||
*/
|
||||
if (WARN_ON_ONCE(fanotify_event_metadata.event_len > count))
|
||||
goto out_close_fd;
|
||||
if (copy_to_user(buf, &fanotify_event_metadata,
|
||||
fanotify_event_metadata.event_len))
|
||||
goto out_close_fd;
|
||||
@ -295,7 +301,7 @@ static ssize_t fanotify_read(struct file *file, char __user *buf,
|
||||
continue;
|
||||
}
|
||||
|
||||
ret = copy_event_to_user(group, kevent, buf);
|
||||
ret = copy_event_to_user(group, kevent, buf, count);
|
||||
if (unlikely(ret == -EOPENSTALE)) {
|
||||
/*
|
||||
* We cannot report events with stale fd so drop it.
|
||||
@ -669,7 +675,7 @@ static int fanotify_add_inode_mark(struct fsnotify_group *group,
|
||||
*/
|
||||
if ((flags & FAN_MARK_IGNORED_MASK) &&
|
||||
!(flags & FAN_MARK_IGNORED_SURV_MODIFY) &&
|
||||
(atomic_read(&inode->i_writecount) > 0))
|
||||
inode_is_open_for_write(inode))
|
||||
return 0;
|
||||
|
||||
return fanotify_add_mark(group, &inode->i_fsnotify_marks,
|
||||
|
@ -15,6 +15,7 @@
|
||||
#include <linux/exportfs.h>
|
||||
|
||||
#include "inotify/inotify.h"
|
||||
#include "fdinfo.h"
|
||||
#include "fsnotify.h"
|
||||
|
||||
#if defined(CONFIG_PROC_FS)
|
||||
|
@ -401,7 +401,7 @@ static __init int fsnotify_init(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
BUILD_BUG_ON(HWEIGHT32(ALL_FSNOTIFY_BITS) != 23);
|
||||
BUILD_BUG_ON(HWEIGHT32(ALL_FSNOTIFY_BITS) != 25);
|
||||
|
||||
ret = init_srcu_struct(&fsnotify_mark_srcu);
|
||||
if (ret)
|
||||
|
@ -37,10 +37,11 @@
|
||||
|
||||
/* Events that user can request to be notified on */
|
||||
#define FANOTIFY_EVENTS (FAN_ACCESS | FAN_MODIFY | \
|
||||
FAN_CLOSE | FAN_OPEN)
|
||||
FAN_CLOSE | FAN_OPEN | FAN_OPEN_EXEC)
|
||||
|
||||
/* Events that require a permission response from user */
|
||||
#define FANOTIFY_PERM_EVENTS (FAN_OPEN_PERM | FAN_ACCESS_PERM)
|
||||
#define FANOTIFY_PERM_EVENTS (FAN_OPEN_PERM | FAN_ACCESS_PERM | \
|
||||
FAN_OPEN_EXEC_PERM)
|
||||
|
||||
/* Extra flags that may be reported with event or control handling of events */
|
||||
#define FANOTIFY_EVENT_FLAGS (FAN_EVENT_ON_CHILD | FAN_ONDIR)
|
||||
|
@ -26,30 +26,46 @@ static inline int fsnotify_parent(const struct path *path, struct dentry *dentry
|
||||
return __fsnotify_parent(path, dentry, mask);
|
||||
}
|
||||
|
||||
/* simple call site for access decisions */
|
||||
/*
|
||||
* Simple wrapper to consolidate calls fsnotify_parent()/fsnotify() when
|
||||
* an event is on a path.
|
||||
*/
|
||||
static inline int fsnotify_path(struct inode *inode, const struct path *path,
|
||||
__u32 mask)
|
||||
{
|
||||
int ret = fsnotify_parent(path, NULL, mask);
|
||||
|
||||
if (ret)
|
||||
return ret;
|
||||
return fsnotify(inode, mask, path, FSNOTIFY_EVENT_PATH, NULL, 0);
|
||||
}
|
||||
|
||||
/* Simple call site for access decisions */
|
||||
static inline int fsnotify_perm(struct file *file, int mask)
|
||||
{
|
||||
int ret;
|
||||
const struct path *path = &file->f_path;
|
||||
struct inode *inode = file_inode(file);
|
||||
__u32 fsnotify_mask = 0;
|
||||
int ret;
|
||||
|
||||
if (file->f_mode & FMODE_NONOTIFY)
|
||||
return 0;
|
||||
if (!(mask & (MAY_READ | MAY_OPEN)))
|
||||
return 0;
|
||||
if (mask & MAY_OPEN)
|
||||
if (mask & MAY_OPEN) {
|
||||
fsnotify_mask = FS_OPEN_PERM;
|
||||
else if (mask & MAY_READ)
|
||||
|
||||
if (file->f_flags & __FMODE_EXEC) {
|
||||
ret = fsnotify_path(inode, path, FS_OPEN_EXEC_PERM);
|
||||
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
} else if (mask & MAY_READ) {
|
||||
fsnotify_mask = FS_ACCESS_PERM;
|
||||
else
|
||||
BUG();
|
||||
}
|
||||
|
||||
ret = fsnotify_parent(path, NULL, fsnotify_mask);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return fsnotify(inode, fsnotify_mask, path, FSNOTIFY_EVENT_PATH, NULL, 0);
|
||||
return fsnotify_path(inode, path, fsnotify_mask);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -180,10 +196,8 @@ static inline void fsnotify_access(struct file *file)
|
||||
if (S_ISDIR(inode->i_mode))
|
||||
mask |= FS_ISDIR;
|
||||
|
||||
if (!(file->f_mode & FMODE_NONOTIFY)) {
|
||||
fsnotify_parent(path, NULL, mask);
|
||||
fsnotify(inode, mask, path, FSNOTIFY_EVENT_PATH, NULL, 0);
|
||||
}
|
||||
if (!(file->f_mode & FMODE_NONOTIFY))
|
||||
fsnotify_path(inode, path, mask);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -198,10 +212,8 @@ static inline void fsnotify_modify(struct file *file)
|
||||
if (S_ISDIR(inode->i_mode))
|
||||
mask |= FS_ISDIR;
|
||||
|
||||
if (!(file->f_mode & FMODE_NONOTIFY)) {
|
||||
fsnotify_parent(path, NULL, mask);
|
||||
fsnotify(inode, mask, path, FSNOTIFY_EVENT_PATH, NULL, 0);
|
||||
}
|
||||
if (!(file->f_mode & FMODE_NONOTIFY))
|
||||
fsnotify_path(inode, path, mask);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -215,9 +227,10 @@ static inline void fsnotify_open(struct file *file)
|
||||
|
||||
if (S_ISDIR(inode->i_mode))
|
||||
mask |= FS_ISDIR;
|
||||
if (file->f_flags & __FMODE_EXEC)
|
||||
mask |= FS_OPEN_EXEC;
|
||||
|
||||
fsnotify_parent(path, NULL, mask);
|
||||
fsnotify(inode, mask, path, FSNOTIFY_EVENT_PATH, NULL, 0);
|
||||
fsnotify_path(inode, path, mask);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -233,10 +246,8 @@ static inline void fsnotify_close(struct file *file)
|
||||
if (S_ISDIR(inode->i_mode))
|
||||
mask |= FS_ISDIR;
|
||||
|
||||
if (!(file->f_mode & FMODE_NONOTIFY)) {
|
||||
fsnotify_parent(path, NULL, mask);
|
||||
fsnotify(inode, mask, path, FSNOTIFY_EVENT_PATH, NULL, 0);
|
||||
}
|
||||
if (!(file->f_mode & FMODE_NONOTIFY))
|
||||
fsnotify_path(inode, path, mask);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -38,6 +38,7 @@
|
||||
#define FS_DELETE 0x00000200 /* Subfile was deleted */
|
||||
#define FS_DELETE_SELF 0x00000400 /* Self was deleted */
|
||||
#define FS_MOVE_SELF 0x00000800 /* Self was moved */
|
||||
#define FS_OPEN_EXEC 0x00001000 /* File was opened for exec */
|
||||
|
||||
#define FS_UNMOUNT 0x00002000 /* inode on umount fs */
|
||||
#define FS_Q_OVERFLOW 0x00004000 /* Event queued overflowed */
|
||||
@ -45,6 +46,7 @@
|
||||
|
||||
#define FS_OPEN_PERM 0x00010000 /* open event in an permission hook */
|
||||
#define FS_ACCESS_PERM 0x00020000 /* access event in a permissions hook */
|
||||
#define FS_OPEN_EXEC_PERM 0x00040000 /* open/exec event in a permission hook */
|
||||
|
||||
#define FS_EXCL_UNLINK 0x04000000 /* do not send events if object is unlinked */
|
||||
#define FS_ISDIR 0x40000000 /* event occurred against dir */
|
||||
@ -62,11 +64,13 @@
|
||||
#define FS_EVENTS_POSS_ON_CHILD (FS_ACCESS | FS_MODIFY | FS_ATTRIB |\
|
||||
FS_CLOSE_WRITE | FS_CLOSE_NOWRITE | FS_OPEN |\
|
||||
FS_MOVED_FROM | FS_MOVED_TO | FS_CREATE |\
|
||||
FS_DELETE | FS_OPEN_PERM | FS_ACCESS_PERM)
|
||||
FS_DELETE | FS_OPEN_PERM | FS_ACCESS_PERM | \
|
||||
FS_OPEN_EXEC | FS_OPEN_EXEC_PERM)
|
||||
|
||||
#define FS_MOVE (FS_MOVED_FROM | FS_MOVED_TO)
|
||||
|
||||
#define ALL_FSNOTIFY_PERM_EVENTS (FS_OPEN_PERM | FS_ACCESS_PERM)
|
||||
#define ALL_FSNOTIFY_PERM_EVENTS (FS_OPEN_PERM | FS_ACCESS_PERM | \
|
||||
FS_OPEN_EXEC_PERM)
|
||||
|
||||
/* Events that can be reported to backends */
|
||||
#define ALL_FSNOTIFY_EVENTS (FS_ACCESS | FS_MODIFY | FS_ATTRIB | \
|
||||
@ -74,7 +78,8 @@
|
||||
FS_MOVED_FROM | FS_MOVED_TO | FS_CREATE | \
|
||||
FS_DELETE | FS_DELETE_SELF | FS_MOVE_SELF | \
|
||||
FS_UNMOUNT | FS_Q_OVERFLOW | FS_IN_IGNORED | \
|
||||
FS_OPEN_PERM | FS_ACCESS_PERM | FS_DN_RENAME)
|
||||
FS_OPEN_PERM | FS_ACCESS_PERM | FS_DN_RENAME | \
|
||||
FS_OPEN_EXEC | FS_OPEN_EXEC_PERM)
|
||||
|
||||
/* Extra flags that may be reported with event or control handling of events */
|
||||
#define ALL_FSNOTIFY_FLAGS (FS_EXCL_UNLINK | FS_ISDIR | FS_IN_ONESHOT | \
|
||||
|
@ -10,11 +10,13 @@
|
||||
#define FAN_CLOSE_WRITE 0x00000008 /* Writtable file closed */
|
||||
#define FAN_CLOSE_NOWRITE 0x00000010 /* Unwrittable file closed */
|
||||
#define FAN_OPEN 0x00000020 /* File was opened */
|
||||
#define FAN_OPEN_EXEC 0x00001000 /* File was opened for exec */
|
||||
|
||||
#define FAN_Q_OVERFLOW 0x00004000 /* Event queued overflowed */
|
||||
|
||||
#define FAN_OPEN_PERM 0x00010000 /* File open in perm check */
|
||||
#define FAN_ACCESS_PERM 0x00020000 /* File accessed in perm check */
|
||||
#define FAN_OPEN_EXEC_PERM 0x00040000 /* File open/exec in perm check */
|
||||
|
||||
#define FAN_ONDIR 0x40000000 /* event occurred against dir */
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user