lists.openwall.net | lists / announce owl-users owl-dev john-users john-dev passwdqc-users yescrypt popa3d-users / oss-security kernel-hardening musl sabotage tlsify passwords / crypt-dev xvendor / Bugtraq Full-Disclosure linux-kernel linux-netdev linux-ext4 linux-hardening linux-cve-announce PHC | |
Open Source and information security mailing list archives
| ||
|
Date: Wed, 12 Nov 2008 11:10:42 -0500 From: Eric Paris <eparis@...hat.com> To: linux-kernel@...r.kernel.org, malware-list@...ts.printk.net Cc: viro@...iv.linux.org.uk, alan@...rguk.ukuu.org.uk, arjan@...radead.org, greg@...ah.com, tytso@....edu, akpm@...ux-foundation.org Subject: [PATCH =-v3 03/21] fanotify: fscking all notify, system wide file access notification A new system wide file access notification system. Signed-off-by: Eric Paris <eparis@...hat.com> --- fs/notify/Kconfig | 14 ++ fs/notify/Makefile | 2 fs/notify/fanotify.c | 99 +++++++++++++++++ fs/notify/fanotify.h | 63 +++++++++++ fs/notify/group.c | 110 +++++++++++++++++++ fs/notify/notification.c | 266 ++++++++++++++++++++++++++++++++++++++++++++++ include/linux/Kbuild | 1 include/linux/fanotify.h | 95 ++++++++++++++++ include/linux/fsnotify.h | 14 ++ include/linux/sched.h | 1 10 files changed, 661 insertions(+), 4 deletions(-) create mode 100644 fs/notify/fanotify.c create mode 100644 fs/notify/fanotify.h create mode 100644 fs/notify/group.c create mode 100644 fs/notify/notification.c create mode 100644 include/linux/fanotify.h diff --git a/fs/notify/Kconfig b/fs/notify/Kconfig index 23415de..97cc832 100644 --- a/fs/notify/Kconfig +++ b/fs/notify/Kconfig @@ -36,3 +36,17 @@ config INOTIFY_USER For more information, see <file:Documentation/filesystems/inotify.txt> If unsure, say Y. + +config FANOTIFY + bool "Filesystem wide access notification" + select SECURITY + default y + ---help--- + Say Y here to enable fanotify suport. fanotify is a system wide + file access notification interface. Events are read from from a + single open fd and in doing so a fd is created in the reading process + which points to the same data as the one on which the event occured. + + For more information, see <file:Documentation/filesystems/fanotify.txt> + + If unsure, say Y. diff --git a/fs/notify/Makefile b/fs/notify/Makefile index 882ecf9..c467c97 100644 --- a/fs/notify/Makefile +++ b/fs/notify/Makefile @@ -2,3 +2,5 @@ obj-$(CONFIG_INOTIFY) += inotify.o obj-$(CONFIG_INOTIFY_USER) += inotify_user.o obj-$(CONFIG_DNOTIFY) += dnotify.o + +obj-$(CONFIG_FANOTIFY) += fanotify.o notification.o group.o diff --git a/fs/notify/fanotify.c b/fs/notify/fanotify.c new file mode 100644 index 0000000..e2a338e --- /dev/null +++ b/fs/notify/fanotify.c @@ -0,0 +1,99 @@ +/* + * Copyright (C) 2008 Red Hat, Inc., Eric Paris <eparis@...hat.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include <linux/file.h> +#include <linux/fs.h> +#include <linux/init.h> +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/mutex.h> +#include <linux/namei.h> +#include <linux/poll.h> +#include <linux/rculist.h> +#include <linux/sched.h> +#include <linux/slab.h> +#include <linux/security.h> +#include <linux/uaccess.h> + +#include <linux/fanotify.h> +#include "fanotify.h" + +struct dentry *fanotify_fs_root; + +void fanotify(struct file *file, unsigned int mask) +{ + struct fanotify_group *group; + struct fanotify_event *event = NULL; + struct task_struct *tsk = current; + struct inode *inode = file->f_path.dentry->d_inode; + int idx; + + if (likely(list_empty(&fanotify_groups))) + return; + + if (tsk->flags & PF_NOFACCESS) + return; + + if (!S_ISREG(inode->i_mode)) + return; + + /* + * SRCU!! the groups list is very very much read only and the path is + * very hot (assuming something is using fanotify) Not blocking while + * walking this list is ugly. We could preallocate an event and an + * event holder for every group that event might need to be put on, but + * all that possibly wasted allocation is nuts. For all we know there + * are already fastpath entries, groups don't need this event, or all + * sorts of reasons to believe not every kernel action is going to get + * sent to userspace. Hopefully this won't get shit on too much, + * because going to a mutex here is really going to needlessly serialize + * read/write/open/close across the whole system.... + */ + idx = srcu_read_lock(&fanotify_grp_srcu_struct); + list_for_each_entry_rcu(group, &fanotify_groups, group_list) { + if (mask & group->mask) { + if (!event) { + event = create_event(file, mask); + /* shit, we OOM'd and now we can't tell, lets hope something else blows up */ + if (!event) + break; + } + fanotify_add_event_to_notif(group, event); + } + } + srcu_read_unlock(&fanotify_grp_srcu_struct, idx); + /* + * create_event() take a reference so the event can't be cleaned up while + * we are still trying to add it to lists + */ + if (event) + fanotify_put_event(event); +} +EXPORT_SYMBOL_GPL(fanotify); + +static __init int fanotify_init(void) +{ + int ret; + + ret = fanotify_notification_init(); + if (ret) + return ret; + + return init_srcu_struct(&fanotify_grp_srcu_struct); +} +__initcall(fanotify_init); diff --git a/fs/notify/fanotify.h b/fs/notify/fanotify.h new file mode 100644 index 0000000..2cbe0ba --- /dev/null +++ b/fs/notify/fanotify.h @@ -0,0 +1,63 @@ +#ifndef _LINUX_FANOTIFY_PRIVATE_H +#define _LINUX_FANOTIFY_PRIVATE_H + +#include <linux/fanotify.h> + + +#include <asm/atomic.h> +#include <linux/dcache.h> +#include <linux/list.h> +#include <linux/mutex.h> +#include <linux/path.h> +#include <linux/spinlock.h> +#include <linux/types.h> +#include <linux/wait.h> + +/* + * A single event can be queued in multiple group->notification_lists. + * + * each group->notification_list will point to an event_holer which in turns points + * to the actual event that needs to be sent to userspace. + * + * Seemed cheaper to create a refcnt'd event and a small holder for every group + * than create a different event for every group + * + */ +struct fanotify_event_holder { + struct fanotify_event *event; + struct list_head event_list; +}; + +/* + * all of the information about the original object we want to now send to + * a scanner. If you want to carry more info from the accessing task to the + * listener this structure is where you need to be adding fields. + */ +struct fanotify_event { + /* + * If we create an event we are also going to need to create a holder + * to link to a group. So embed one holder in the event. Means only + * one allocation for the common case where we only have one group + */ + struct fanotify_event_holder holder; + spinlock_t holder_spinlock; /* protection for the associated event_holder */ + struct path path; /* path from the original access */ + unsigned int mask; /* the type of access */ + atomic_t refcnt; /* how many groups still are using/need to send this event */ +}; + +extern struct srcu_struct fanotify_grp_srcu_struct; +extern struct list_head fanotify_groups; + +extern int fanotify_check_notif_queue(struct fanotify_group *group); +extern void fanotify_get_event(struct fanotify_event *event); +extern void fanotify_put_event(struct fanotify_event *event); +extern int fanotify_add_event_to_notif(struct fanotify_group *group, struct fanotify_event *event); +extern struct fanotify_event *remove_event_from_group_notification(struct fanotify_group *group); +extern void fanotify_notification_clear_group(struct fanotify_group *group); +extern struct fanotify_event *create_event(struct file *file, unsigned int mask); +extern struct fanotify_event_holder *alloc_event_holder(void); +extern void fanotify_destroy_event_holder(struct fanotify_event_holder *holder); +extern __init int fanotify_notification_init(void); +extern __init int fanotify_notification_uninit(void); +#endif /* _LINUX_FANOTIFY_PRIVATE_H */ diff --git a/fs/notify/group.c b/fs/notify/group.c new file mode 100644 index 0000000..fc3d736 --- /dev/null +++ b/fs/notify/group.c @@ -0,0 +1,110 @@ +/* + * Copyright (C) 2008 Red Hat, Inc., Eric Paris <eparis@...hat.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include <linux/file.h> +#include <linux/fs.h> +#include <linux/init.h> +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/mutex.h> +#include <linux/namei.h> +#include <linux/poll.h> +#include <linux/rculist.h> +#include <linux/sched.h> +#include <linux/slab.h> +#include <linux/security.h> +#include <linux/uaccess.h> + +#include <linux/fanotify.h> +#include "fanotify.h" + +DEFINE_MUTEX(fanotify_grp_mutex); +struct srcu_struct fanotify_grp_srcu_struct; +LIST_HEAD(fanotify_groups); + +void fanotify_get_group(struct fanotify_group *group) +{ + atomic_inc(&group->refcnt); +} + +struct fanotify_group *fanotify_find_group(unsigned int group_num, unsigned int mask) +{ + struct fanotify_group *group_iter; + struct fanotify_group *group = NULL; + + mutex_lock(&fanotify_grp_mutex); + list_for_each_entry_rcu(group_iter, &fanotify_groups, group_list) { + if (group_iter->group_num == group_num) { + if (group_iter->mask == mask) { + fanotify_get_group(group_iter); + group = group_iter; + } else + group = ERR_PTR(-EEXIST); + goto out; + } + } + + group = kmalloc(sizeof(struct fanotify_group), GFP_KERNEL); + if (!group) { + group = ERR_PTR(-ENOMEM); + goto out; + } + + atomic_set(&group->refcnt, 1); + + group->group_num = group_num; + group->mask = mask; + + mutex_init(&group->notification_mutex); + INIT_LIST_HEAD(&group->notification_list); + init_waitqueue_head(&group->notification_waitq); + + /* add it */ + list_add_rcu(&group->group_list, &fanotify_groups); + +out: + mutex_unlock(&fanotify_grp_mutex); + return group; +} + +void fanotify_kill_group(struct fanotify_group *group) +{ + /* clear the notification queue of all events */ + fanotify_notification_clear_group(group); + + kfree(group); +} + +void fanotify_put_group(struct fanotify_group *group) +{ + mutex_lock(&fanotify_grp_mutex); + if (atomic_dec_and_test(&group->refcnt)) { + + list_del_rcu(&group->group_list); + mutex_unlock(&fanotify_grp_mutex); + + synchronize_srcu(&fanotify_grp_srcu_struct); + + fanotify_kill_group(group); + + return; + } + mutex_unlock(&fanotify_grp_mutex); + + return; +} diff --git a/fs/notify/notification.c b/fs/notify/notification.c new file mode 100644 index 0000000..3dd69ef --- /dev/null +++ b/fs/notify/notification.c @@ -0,0 +1,266 @@ +/* + * Copyright (C) 2008 Red Hat, Inc., Eric Paris <eparis@...hat.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include <asm/atomic.h> +#include <linux/file.h> +#include <linux/fs.h> +#include <linux/init.h> +#include <linux/kernel.h> +#include <linux/list.h> +#include <linux/mount.h> +#include <linux/mutex.h> +#include <linux/path.h> +#include <linux/sched.h> +#include <linux/slab.h> + +#include <linux/fanotify.h> +#include "fanotify.h" + +static struct kmem_cache *event_kmem_cache; +static struct kmem_cache *event_holder_kmem_cache; + +int fanotify_check_notif_queue(struct fanotify_group *group) +{ + mutex_lock(&group->notification_mutex); + if (!list_empty(&group->notification_list)) + return 1; + mutex_unlock(&group->notification_mutex); + return 0; +} + +void fanotify_get_event(struct fanotify_event *event) +{ + atomic_inc(&event->refcnt); +} + +void fanotify_put_event(struct fanotify_event *event) +{ + if (!event) + return; + + if (atomic_dec_and_test(&event->refcnt)) { + path_put(&event->path); + event->path.dentry = NULL; + event->path.mnt = NULL; + + event->mask = 0; + kmem_cache_free(event_kmem_cache, event); + } +} + +struct fanotify_event_holder *alloc_event_holder(void) +{ + return kmem_cache_alloc(event_holder_kmem_cache, GFP_KERNEL); +} + +void fanotify_destroy_event_holder(struct fanotify_event_holder *holder) +{ + kmem_cache_free(event_holder_kmem_cache, holder); +} + +int fanotify_add_event_to_notif(struct fanotify_group *group, struct fanotify_event *event) +{ + struct fanotify_event_holder *holder; + + /* + * holder locking!!! + * + * only this task is going to be adding events to lists. fanotify + * listeners may be removing events from groups and freeing holders + * but only we will be adding. So locking is pretty easy. We don't + * need to lock when we check the list. We don't really care what + * order we see things from the freeing tasks. If we see the holder + * list is empty we know after we take the spinlock that holder will + * be safe to use. + * + * When only looking at the notification list this is all useless since + * everything meaningful is already being protected by the + * notification_mutex but since access lists also use event_holders we + * need this. + */ + if (list_empty(&event->holder.event_list)) + holder = (struct fanotify_event_holder *)event; + else + holder = alloc_event_holder(); + if (!holder) + return -ENOMEM; + + fanotify_get_event(event); + + + mutex_lock(&group->notification_mutex); + spin_lock(&event->holder_spinlock); + holder->event = event; + list_add_tail(&holder->event_list, &group->notification_list); + spin_unlock(&event->holder_spinlock); + mutex_unlock(&group->notification_mutex); + + + wake_up(&group->notification_waitq); + + return 0; +} + +/* + * must be called with group->notification_mutex held and must know event is present. + * it is the responsibility of the caller to call put_event() on the returned + * structure + */ +struct fanotify_event *remove_event_from_group_notification(struct fanotify_group *group) +{ + struct fanotify_event *event; + struct fanotify_event_holder *holder; + + holder = list_first_entry(&group->notification_list, struct fanotify_event_holder, event_list); + + event = holder->event; + + spin_lock(&event->holder_spinlock); + holder->event = NULL; + /* + * be sure you are done with holder, since after this point it + * could be reused in another group + */ + list_del_init(&holder->event_list); + spin_unlock(&event->holder_spinlock); + + /* event == holder means we are referenced through the in event holder */ + if (event != (struct fanotify_event *)holder) + fanotify_destroy_event_holder(holder); + + return event; +} + +void fanotify_notification_clear_group(struct fanotify_group *group) +{ + struct fanotify_event *event; + + while (fanotify_check_notif_queue(group)) { + event = remove_event_from_group_notification(group); + fanotify_put_event(event); + /* fanotify_check_notif_queue() took this lock */ + mutex_unlock(&group->notification_mutex); + } +} + +struct fanotify_event *create_event(struct file *file, unsigned int mask) +{ + struct fanotify_event *event; + + event = kmem_cache_alloc(event_kmem_cache, GFP_KERNEL); + if (!event) + return NULL; + + event->holder.event = NULL; + INIT_LIST_HEAD(&event->holder.event_list); + atomic_set(&event->refcnt, 1); + + spin_lock_init(&event->holder_spinlock); + + event->path.dentry = file->f_path.dentry; + event->path.mnt = file->f_path.mnt; + path_get(&event->path); + + event->mask = mask; + + WARN_ON(!event->path.dentry); + WARN_ON(!event->path.mnt); + + return event; +} + +int fanotify_create_event_fd(struct fanotify_group *group, struct fanotify_event_metadata *data, int nonblock) +{ + int rc; + int client_fd; + struct dentry *dentry; + struct vfsmount *mnt; + struct file *new_file; + + struct fanotify_event *event; + + memset(data, 0, sizeof(struct fanotify_event_metadata)); + + /* get a notification off the queue blocking if we can/should */ + if (fanotify_check_notif_queue(group)) { + event = remove_event_from_group_notification(group); + mutex_unlock(&group->notification_mutex); + } else { + if (nonblock) + return -EAGAIN; + rc = wait_event_interruptible(group->notification_waitq, fanotify_check_notif_queue(group)); + if (!rc) { + event = remove_event_from_group_notification(group); + mutex_unlock(&group->notification_mutex); + } else { + return rc; + } + } + + BUG_ON(!event); + + client_fd = get_unused_fd(); + if (client_fd < 0) + return client_fd; + + /* + * we need a new file handle for the userspace program so it can read even if it was + * originally opened O_WRONLY. + */ + dentry = dget(event->path.dentry); + mnt = mntget(event->path.mnt); + new_file = dentry_open(dentry, mnt, O_RDONLY); + if (IS_ERR(new_file)) { + /* + * we still send an event even if we can't open the file. this + * can happen for say tasks are gone and we try to open their + * /proc entries or we try to open a WRONLY file like in sysfs + * we just send the errno to userspace since there isn't much + * else we can do. + */ + put_unused_fd(client_fd); + client_fd = PTR_ERR(new_file); + } else { + fd_install(client_fd, new_file); + } + + data->fd = client_fd; + data->mask = event->mask; + + fanotify_put_event(event); + + return 0; +} + +__init int fanotify_notification_uninit(void) +{ + kmem_cache_destroy(event_kmem_cache); + event_kmem_cache = NULL; + kmem_cache_destroy(event_holder_kmem_cache); + event_holder_kmem_cache = NULL; + + return 0; +} + +__init int fanotify_notification_init(void) +{ + event_kmem_cache = kmem_cache_create("fanotify_event", sizeof(struct fanotify_event), 0, SLAB_PANIC, NULL); + event_holder_kmem_cache = kmem_cache_create("fanotify_event_holder", sizeof(struct fanotify_event_holder), 0, SLAB_PANIC, NULL); + + return 0; +} diff --git a/include/linux/Kbuild b/include/linux/Kbuild index e531783..9f6d7d9 100644 --- a/include/linux/Kbuild +++ b/include/linux/Kbuild @@ -246,6 +246,7 @@ unifdef-y += inet_diag.h unifdef-y += in.h unifdef-y += in6.h unifdef-y += inotify.h +unifdef-y += fanotify.h unifdef-y += input.h unifdef-y += ip.h unifdef-y += ipc.h diff --git a/include/linux/fanotify.h b/include/linux/fanotify.h new file mode 100644 index 0000000..7f1179e --- /dev/null +++ b/include/linux/fanotify.h @@ -0,0 +1,95 @@ +/* + * Filesystem access notification for Linux + * + * Copyright (C) 2008 Red Hat, Inc., Eric Paris <eparis@...hat.com> + * + * Basis of file stolen from inotify.h + */ + +#ifndef _LINUX_FANOTIFY_H +#define _LINUX_FANOTIFY_H + +/* the following events that user-space can register for */ +#define FAN_ACCESS 0x00000001 /* File was accessed */ +#define FAN_MODIFY 0x00000002 /* File was modified */ +#define FAN_CLOSE_NOWRITE 0x00000004 /* Unwrittable file closed */ +#define FAN_CLOSE_WRITE 0x00000008 /* Writtable file closed */ +#define FAN_OPEN 0x00000010 /* File was opened */ + +/* FIXME currently Q's have no limit.... */ +#define FAN_Q_OVERFLOW 0x80000000 /* Event queued overflowed */ + +/* helper events */ +#define FAN_CLOSE (FAN_CLOSE_WRITE | FAN_CLOSE_NOWRITE) /* close */ + +/* + * All of the events - we build the list by hand so that we can add flags in + * the future and not break backward compatibility. Apps will get only the + * events that they originally wanted. Be sure to add new events here! + */ +#define FAN_ALL_EVENTS (FAN_ACCESS |\ + FAN_MODIFY |\ + FAN_CLOSE |\ + FAN_OPEN) + +#ifdef __KERNEL__ +#include <linux/types.h> +#else +#include <stdint.h> +#include <sys/types.h> +#endif + +struct fanotify_event_metadata { + int32_t fd; + uint32_t mask; +}; + +#ifdef __KERNEL__ + +#include <linux/fs.h> +#include <linux/list.h> +#include <linux/mutex.h> +#include <linux/wait.h> + +#include <asm/atomic.h> + +struct fanotify_group { + struct list_head group_list; /* list of all groups on the system */ + unsigned int group_num; /* the 'name' of the event */ + unsigned int mask; /* mask of events this group cares about */ + atomic_t refcnt; /* num of processes with a special file open */ + + /* needed to send notification to userspace */ + struct mutex notification_mutex;/* protect the notification_list */ + struct list_head notification_list; /* list of event_holder this group needs to send to userspace */ + wait_queue_head_t notification_waitq; /* read() on the notification file blocks on this waitq */ +}; + +#ifdef CONFIG_FANOTIFY + +extern void fanotify(struct file *file, unsigned int mask); + +extern void fanotify_get_group(struct fanotify_group *group); +extern struct fanotify_group *fanotify_find_group(unsigned int group_num, unsigned int mask); +extern void fanotify_put_group(struct fanotify_group *group); +#else + +static inline void fanotify(struct file *file, unsigned int mask) +{} + +static inline void fanotify_get_group(struct fanotify_group *group) +{} + +static inline struct fanotify_group *fanotify_find_group(unsigned int group_num, unsigned int mask) +{ + return NULL; +} + +static inline extern void fanotify_put_group(struct fanotify_group *group) +{} + +#endif /* CONFIG_FANOTIFY */ + +#endif /* __KERNEL __ */ + +#endif /* _LINUX_FANOTIFY_H */ diff --git a/include/linux/fsnotify.h b/include/linux/fsnotify.h index dec1afb..3a1b0dc 100644 --- a/include/linux/fsnotify.h +++ b/include/linux/fsnotify.h @@ -13,6 +13,7 @@ #include <linux/dnotify.h> #include <linux/inotify.h> +#include <linux/fanotify.h> #include <linux/audit.h> /* @@ -148,6 +149,7 @@ static inline void fsnotify_access(struct file *file) dnotify_parent(dentry, DN_ACCESS); inotify_dentry_parent_queue_event(dentry, mask, 0, dentry->d_name.name); inotify_inode_queue_event(inode, mask, 0, NULL, NULL); + fanotify(file, FAN_ACCESS); } /* @@ -165,6 +167,7 @@ static inline void fsnotify_modify(struct file *file) dnotify_parent(dentry, DN_MODIFY); inotify_dentry_parent_queue_event(dentry, mask, 0, dentry->d_name.name); inotify_inode_queue_event(inode, mask, 0, NULL, NULL); + fanotify(file, FAN_MODIFY); } /* @@ -181,6 +184,7 @@ static inline void fsnotify_open(struct file *file) inotify_dentry_parent_queue_event(dentry, mask, 0, dentry->d_name.name); inotify_inode_queue_event(inode, mask, 0, NULL, NULL); + fanotify(file, FAN_OPEN); } /* @@ -192,13 +196,15 @@ static inline void fsnotify_close(struct file *file) struct inode *inode = dentry->d_inode; const char *name = dentry->d_name.name; fmode_t mode = file->f_mode; - u32 mask = (mode & FMODE_WRITE) ? IN_CLOSE_WRITE : IN_CLOSE_NOWRITE; + u32 in_mask = (mode & FMODE_WRITE) ? IN_CLOSE_WRITE : IN_CLOSE_NOWRITE; + u32 fan_mask = (mode & FMODE_WRITE) ? FAN_CLOSE_WRITE : FAN_CLOSE_NOWRITE; if (S_ISDIR(inode->i_mode)) - mask |= IN_ISDIR; + in_mask |= IN_ISDIR; - inotify_dentry_parent_queue_event(dentry, mask, 0, name); - inotify_inode_queue_event(inode, mask, 0, NULL, NULL); + inotify_dentry_parent_queue_event(dentry, in_mask, 0, name); + inotify_inode_queue_event(inode, in_mask, 0, NULL, NULL); + fanotify(file, fan_mask); } /* diff --git a/include/linux/sched.h b/include/linux/sched.h index 295b7c7..7e889f1 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -1538,6 +1538,7 @@ extern cputime_t task_gtime(struct task_struct *p); #define PF_EXITING 0x00000004 /* getting shut down */ #define PF_EXITPIDONE 0x00000008 /* pi exit done on shut down */ #define PF_VCPU 0x00000010 /* I'm a virtual CPU */ +#define PF_NOFACCESS 0x00000020 /* exclude from all faccesses */ #define PF_FORKNOEXEC 0x00000040 /* forked but didn't exec */ #define PF_SUPERPRIV 0x00000100 /* used super-user privileges */ #define PF_DUMPCORE 0x00000200 /* dumped core */ -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@...r.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Powered by blists - more mailing lists