mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-08-31 11:41:29 -04:00
Merge tag 'fsnotify_for_v7.3-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/jack/linux-fs
Pull fsnotify updates from Jan Kara: "A couple of assorted fixes (mostly stuff spotted by Sashiko) for fsnotify subsystem. I'm also removing Matt as a reviewer because he was not active in fsnotify in last years and after he stopped working for Google I don't have a working contact to him" * tag 'fsnotify_for_v7.3-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/jack/linux-fs: fsnotify: Fix stale object mask after concurrent mark updates fanotify: report full event length for FIONREAD fanotify: fix use-after-free of file range info fanotify: stop permission watchdog when timeout is zero fsnotify: Remove Matt Bobrowski as a reviewer fanotify: initialize permission event watchdog state
This commit is contained in:
@@ -9915,7 +9915,6 @@ F: net/core/failover.c
|
||||
FANOTIFY
|
||||
M: Jan Kara <jack@suse.cz>
|
||||
R: Amir Goldstein <amir73il@gmail.com>
|
||||
R: Matthew Bobrowski <repnop@google.com>
|
||||
L: linux-fsdevel@vger.kernel.org
|
||||
S: Maintained
|
||||
F: fs/notify/fanotify/
|
||||
|
||||
@@ -599,9 +599,9 @@ static struct fanotify_event *fanotify_alloc_perm_event(const void *data,
|
||||
pevent->hdr.pad = 0;
|
||||
pevent->hdr.len = 0;
|
||||
pevent->state = FAN_EVENT_INIT;
|
||||
pevent->watchdog_cnt = 0;
|
||||
pevent->path = *path;
|
||||
/* NULL ppos means no range info */
|
||||
pevent->ppos = range ? &range->pos : NULL;
|
||||
pevent->pos = range ? range->pos : FANOTIFY_NO_RANGE;
|
||||
pevent->count = range ? range->count : 0;
|
||||
path_get(path);
|
||||
|
||||
|
||||
@@ -428,6 +428,8 @@ FANOTIFY_ME(struct fanotify_event *event)
|
||||
return container_of(event, struct fanotify_mnt_event, fae);
|
||||
}
|
||||
|
||||
#define FANOTIFY_NO_RANGE ((loff_t)-1)
|
||||
|
||||
/*
|
||||
* Structure for permission fanotify events. It gets allocated and freed in
|
||||
* fanotify_handle_event() since we wait there for user response. When the
|
||||
@@ -438,7 +440,7 @@ FANOTIFY_ME(struct fanotify_event *event)
|
||||
struct fanotify_perm_event {
|
||||
struct fanotify_event fae;
|
||||
struct path path;
|
||||
const loff_t *ppos; /* optional file range info */
|
||||
loff_t pos; /* FANOTIFY_NO_RANGE if unavailable */
|
||||
size_t count;
|
||||
u32 response; /* userspace answer to the event */
|
||||
unsigned short state; /* state of the event */
|
||||
@@ -468,7 +470,7 @@ static inline bool fanotify_event_has_access_range(struct fanotify_event *event)
|
||||
if (!(event->mask & FANOTIFY_PRE_CONTENT_EVENTS))
|
||||
return false;
|
||||
|
||||
return FANOTIFY_PERM(event)->ppos;
|
||||
return FANOTIFY_PERM(event)->pos != FANOTIFY_NO_RANGE;
|
||||
}
|
||||
|
||||
static inline struct fanotify_event *FANOTIFY_E(struct fsnotify_event *fse)
|
||||
|
||||
@@ -112,7 +112,12 @@ static DECLARE_DELAYED_WORK(perm_group_work, perm_group_watchdog);
|
||||
|
||||
static void perm_group_watchdog_schedule(void)
|
||||
{
|
||||
schedule_delayed_work(&perm_group_work, secs_to_jiffies(perm_group_timeout));
|
||||
int timeout = READ_ONCE(perm_group_timeout);
|
||||
|
||||
if (!timeout)
|
||||
return;
|
||||
|
||||
schedule_delayed_work(&perm_group_work, secs_to_jiffies(timeout));
|
||||
}
|
||||
|
||||
static void perm_group_watchdog(struct work_struct *work)
|
||||
@@ -675,12 +680,9 @@ static size_t copy_range_info_to_user(struct fanotify_event *event,
|
||||
if (WARN_ON_ONCE(info_len > count))
|
||||
return -EFAULT;
|
||||
|
||||
if (WARN_ON_ONCE(!pevent->ppos))
|
||||
return -EINVAL;
|
||||
|
||||
info.hdr.info_type = FAN_EVENT_INFO_TYPE_RANGE;
|
||||
info.hdr.len = info_len;
|
||||
info.offset = *(pevent->ppos);
|
||||
info.offset = pevent->pos;
|
||||
info.count = pevent->count;
|
||||
|
||||
if (copy_to_user(buf, &info, info_len))
|
||||
@@ -1145,11 +1147,13 @@ static long fanotify_ioctl(struct file *file, unsigned int cmd, unsigned long ar
|
||||
{
|
||||
struct fsnotify_group *group;
|
||||
struct fsnotify_event *fsn_event;
|
||||
unsigned int info_mode;
|
||||
void __user *p;
|
||||
int ret = -ENOTTY;
|
||||
size_t send_len = 0;
|
||||
|
||||
group = file->private_data;
|
||||
info_mode = FAN_GROUP_FLAG(group, FANOTIFY_INFO_MODES);
|
||||
|
||||
p = (void __user *) arg;
|
||||
|
||||
@@ -1157,7 +1161,8 @@ static long fanotify_ioctl(struct file *file, unsigned int cmd, unsigned long ar
|
||||
case FIONREAD:
|
||||
spin_lock(&group->notification_lock);
|
||||
list_for_each_entry(fsn_event, &group->notification_list, list)
|
||||
send_len += FAN_EVENT_METADATA_LEN;
|
||||
send_len += fanotify_event_len(info_mode,
|
||||
FANOTIFY_E(fsn_event));
|
||||
spin_unlock(&group->notification_lock);
|
||||
ret = put_user(send_len, (int __user *) p);
|
||||
break;
|
||||
@@ -1316,16 +1321,18 @@ static bool fanotify_mark_update_flags(struct fsnotify_mark *fsn_mark,
|
||||
static bool fanotify_mark_add_to_mask(struct fsnotify_mark *fsn_mark,
|
||||
__u32 mask, unsigned int fan_flags)
|
||||
{
|
||||
__u32 old_mask;
|
||||
bool recalc;
|
||||
|
||||
spin_lock(&fsn_mark->lock);
|
||||
if (!(fan_flags & FANOTIFY_MARK_IGNORE_BITS))
|
||||
if (!(fan_flags & FANOTIFY_MARK_IGNORE_BITS)) {
|
||||
old_mask = fsn_mark->mask;
|
||||
fsn_mark->mask |= mask;
|
||||
else
|
||||
recalc = old_mask != fsn_mark->mask;
|
||||
} else {
|
||||
fsn_mark->ignore_mask |= mask;
|
||||
|
||||
recalc = fsnotify_calc_mask(fsn_mark) &
|
||||
~fsnotify_conn_mask(fsn_mark->connector);
|
||||
recalc = true;
|
||||
}
|
||||
|
||||
recalc |= fanotify_mark_update_flags(fsn_mark, fan_flags);
|
||||
spin_unlock(&fsn_mark->lock);
|
||||
|
||||
@@ -539,7 +539,6 @@ static int inotify_update_existing_watch(struct fsnotify_group *group,
|
||||
{
|
||||
struct fsnotify_mark *fsn_mark;
|
||||
struct inotify_inode_mark *i_mark;
|
||||
__u32 old_mask, new_mask;
|
||||
int replace = !(arg & IN_MASK_ADD);
|
||||
int create = (arg & IN_MASK_CREATE);
|
||||
int ret;
|
||||
@@ -555,27 +554,15 @@ static int inotify_update_existing_watch(struct fsnotify_group *group,
|
||||
i_mark = container_of(fsn_mark, struct inotify_inode_mark, fsn_mark);
|
||||
|
||||
spin_lock(&fsn_mark->lock);
|
||||
old_mask = fsn_mark->mask;
|
||||
if (replace) {
|
||||
fsn_mark->mask = 0;
|
||||
fsn_mark->flags &= ~INOTIFY_MARK_FLAGS;
|
||||
}
|
||||
fsn_mark->mask |= inotify_arg_to_mask(inode, arg);
|
||||
fsn_mark->flags |= inotify_arg_to_flags(arg);
|
||||
new_mask = fsn_mark->mask;
|
||||
spin_unlock(&fsn_mark->lock);
|
||||
|
||||
if (old_mask != new_mask) {
|
||||
/* more bits in old than in new? */
|
||||
int dropped = (old_mask & ~new_mask);
|
||||
/* more bits in this fsn_mark than the inode's mask? */
|
||||
int do_inode = (new_mask & ~READ_ONCE(inode->i_fsnotify_mask));
|
||||
|
||||
/* update the inode with this new fsn_mark */
|
||||
if (dropped || do_inode)
|
||||
fsnotify_recalc_mask(fsn_mark->connector);
|
||||
|
||||
}
|
||||
fsnotify_recalc_mask(fsn_mark->connector);
|
||||
|
||||
/* return the wd */
|
||||
ret = i_mark->wd;
|
||||
|
||||
Reference in New Issue
Block a user