Skip to content

Commit 4d97f7d

Browse files
Henry Wilsonjankara
authored andcommitted
inotify: Add flag IN_MASK_CREATE for inotify_add_watch()
The flag IN_MASK_CREATE is introduced as a flag for inotiy_add_watch() which prevents inotify from modifying any existing watches when invoked. If the pathname specified in the call has a watched inode associated with it and IN_MASK_CREATE is specified, fail with an errno of EEXIST. Use of IN_MASK_CREATE with IN_MASK_ADD is reserved for future use and will return EINVAL. RATIONALE In the current implementation, there is no way to prevent inotify_add_watch() from modifying existing watch descriptors. Even if the caller keeps a record of all watch descriptors collected, this is only sufficient to detect that an existing watch descriptor may have been modified. The assumption that a particular path will map to the same inode over multiple calls to inotify_add_watch() cannot be made as files can be renamed or deleted. It is also not possible to assume that two distinct paths do no map to the same inode, due to hard-links or a dereferenced symbolic link. Further uses of inotify_add_watch() to revert the change may cause other watch descriptors to be modified or created, merely compunding the problem. There is currently no system call such as inotify_modify_watch() to explicity modify a watch descriptor, which would be able to revert unwanted changes. Thus the caller cannot guarantee to be able to revert any changes to existing watch decriptors. Additionally the caller cannot assume that the events that are associated with a watch descriptor are within the set requested, as any future calls to inotify_add_watch() may unintentionally modify a watch descriptor's mask. Thus it cannot currently be guaranteed that a watch descriptor will only generate events which have been requested. The program must filter events which come through its watch descriptor to within its expected range. Reviewed-by: Amir Goldstein <amir73il@gmail.com> Signed-off-by: Henry Wilson <henry.wilson@acentic.com> Signed-off-by: Jan Kara <jack@suse.cz>
1 parent eaa2c6b commit 4d97f7d

File tree

3 files changed

+10
-2
lines changed

3 files changed

+10
-2
lines changed

fs/notify/inotify/inotify_user.c

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -510,13 +510,16 @@ static int inotify_update_existing_watch(struct fsnotify_group *group,
510510
__u32 old_mask, new_mask;
511511
__u32 mask;
512512
int add = (arg & IN_MASK_ADD);
513+
int create = (arg & IN_MASK_CREATE);
513514
int ret;
514515

515516
mask = inotify_arg_to_mask(arg);
516517

517518
fsn_mark = fsnotify_find_mark(&inode->i_fsnotify_marks, group);
518519
if (!fsn_mark)
519520
return -ENOENT;
521+
else if (create)
522+
return -EEXIST;
520523

521524
i_mark = container_of(fsn_mark, struct inotify_inode_mark, fsn_mark);
522525

@@ -718,6 +721,10 @@ SYSCALL_DEFINE3(inotify_add_watch, int, fd, const char __user *, pathname,
718721
if (unlikely(!f.file))
719722
return -EBADF;
720723

724+
/* IN_MASK_ADD and IN_MASK_CREATE don't make sense together */
725+
if (unlikely((mask & IN_MASK_ADD) && (mask & IN_MASK_CREATE)))
726+
return -EINVAL;
727+
721728
/* verify that this is indeed an inotify instance */
722729
if (unlikely(f.file->f_op != &inotify_fops)) {
723730
ret = -EINVAL;
@@ -806,7 +813,7 @@ static int __init inotify_user_setup(void)
806813
BUILD_BUG_ON(IN_ISDIR != FS_ISDIR);
807814
BUILD_BUG_ON(IN_ONESHOT != FS_IN_ONESHOT);
808815

809-
BUG_ON(hweight32(ALL_INOTIFY_BITS) != 21);
816+
BUG_ON(hweight32(ALL_INOTIFY_BITS) != 22);
810817

811818
inotify_inode_mark_cachep = KMEM_CACHE(inotify_inode_mark, SLAB_PANIC);
812819

include/linux/inotify.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,6 @@ extern struct ctl_table inotify_table[]; /* for sysctl */
1818
IN_DELETE_SELF | IN_MOVE_SELF | IN_UNMOUNT | \
1919
IN_Q_OVERFLOW | IN_IGNORED | IN_ONLYDIR | \
2020
IN_DONT_FOLLOW | IN_EXCL_UNLINK | IN_MASK_ADD | \
21-
IN_ISDIR | IN_ONESHOT)
21+
IN_MASK_CREATE | IN_ISDIR | IN_ONESHOT)
2222

2323
#endif /* _LINUX_INOTIFY_H */

include/uapi/linux/inotify.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ struct inotify_event {
5353
#define IN_ONLYDIR 0x01000000 /* only watch the path if it is a directory */
5454
#define IN_DONT_FOLLOW 0x02000000 /* don't follow a sym link */
5555
#define IN_EXCL_UNLINK 0x04000000 /* exclude events on unlinked objects */
56+
#define IN_MASK_CREATE 0x10000000 /* only create watches */
5657
#define IN_MASK_ADD 0x20000000 /* add to the mask of an already existing watch */
5758
#define IN_ISDIR 0x40000000 /* event occurred against dir */
5859
#define IN_ONESHOT 0x80000000 /* only send event once */

0 commit comments

Comments
 (0)