aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/notify/fanotify/fanotify_user.c54
-rw-r--r--include/linux/fanotify.h4
2 files changed, 39 insertions, 19 deletions
diff --git a/fs/notify/fanotify/fanotify_user.c b/fs/notify/fanotify/fanotify_user.c
index 3320f0c57e31..ad02d475770f 100644
--- a/fs/notify/fanotify/fanotify_user.c
+++ b/fs/notify/fanotify/fanotify_user.c
@@ -296,13 +296,20 @@ out:
296 return ret; 296 return ret;
297} 297}
298 298
299static __u32 fanotify_mark_remove_from_mask(struct fsnotify_mark *fsn_mark, __u32 mask) 299static __u32 fanotify_mark_remove_from_mask(struct fsnotify_mark *fsn_mark,
300 __u32 mask,
301 unsigned int flags)
300{ 302{
301 __u32 oldmask; 303 __u32 oldmask;
302 304
303 spin_lock(&fsn_mark->lock); 305 spin_lock(&fsn_mark->lock);
304 oldmask = fsn_mark->mask; 306 if (!(flags & FAN_MARK_IGNORED_MASK)) {
305 fsnotify_set_mark_mask_locked(fsn_mark, (oldmask & ~mask)); 307 oldmask = fsn_mark->mask;
308 fsnotify_set_mark_mask_locked(fsn_mark, (oldmask & ~mask));
309 } else {
310 oldmask = fsn_mark->ignored_mask;
311 fsnotify_set_mark_ignored_mask_locked(fsn_mark, (oldmask & ~mask));
312 }
306 spin_unlock(&fsn_mark->lock); 313 spin_unlock(&fsn_mark->lock);
307 314
308 if (!(oldmask & ~mask)) 315 if (!(oldmask & ~mask))
@@ -312,7 +319,8 @@ static __u32 fanotify_mark_remove_from_mask(struct fsnotify_mark *fsn_mark, __u3
312} 319}
313 320
314static int fanotify_remove_vfsmount_mark(struct fsnotify_group *group, 321static int fanotify_remove_vfsmount_mark(struct fsnotify_group *group,
315 struct vfsmount *mnt, __u32 mask) 322 struct vfsmount *mnt, __u32 mask,
323 unsigned int flags)
316{ 324{
317 struct fsnotify_mark *fsn_mark = NULL; 325 struct fsnotify_mark *fsn_mark = NULL;
318 __u32 removed; 326 __u32 removed;
@@ -321,7 +329,7 @@ static int fanotify_remove_vfsmount_mark(struct fsnotify_group *group,
321 if (!fsn_mark) 329 if (!fsn_mark)
322 return -ENOENT; 330 return -ENOENT;
323 331
324 removed = fanotify_mark_remove_from_mask(fsn_mark, mask); 332 removed = fanotify_mark_remove_from_mask(fsn_mark, mask, flags);
325 fsnotify_put_mark(fsn_mark); 333 fsnotify_put_mark(fsn_mark);
326 if (removed & group->mask) 334 if (removed & group->mask)
327 fsnotify_recalc_group_mask(group); 335 fsnotify_recalc_group_mask(group);
@@ -332,7 +340,8 @@ static int fanotify_remove_vfsmount_mark(struct fsnotify_group *group,
332} 340}
333 341
334static int fanotify_remove_inode_mark(struct fsnotify_group *group, 342static int fanotify_remove_inode_mark(struct fsnotify_group *group,
335 struct inode *inode, __u32 mask) 343 struct inode *inode, __u32 mask,
344 unsigned int flags)
336{ 345{
337 struct fsnotify_mark *fsn_mark = NULL; 346 struct fsnotify_mark *fsn_mark = NULL;
338 __u32 removed; 347 __u32 removed;
@@ -341,7 +350,7 @@ static int fanotify_remove_inode_mark(struct fsnotify_group *group,
341 if (!fsn_mark) 350 if (!fsn_mark)
342 return -ENOENT; 351 return -ENOENT;
343 352
344 removed = fanotify_mark_remove_from_mask(fsn_mark, mask); 353 removed = fanotify_mark_remove_from_mask(fsn_mark, mask, flags);
345 /* matches the fsnotify_find_inode_mark() */ 354 /* matches the fsnotify_find_inode_mark() */
346 fsnotify_put_mark(fsn_mark); 355 fsnotify_put_mark(fsn_mark);
347 356
@@ -353,20 +362,28 @@ static int fanotify_remove_inode_mark(struct fsnotify_group *group,
353 return 0; 362 return 0;
354} 363}
355 364
356static __u32 fanotify_mark_add_to_mask(struct fsnotify_mark *fsn_mark, __u32 mask) 365static __u32 fanotify_mark_add_to_mask(struct fsnotify_mark *fsn_mark,
366 __u32 mask,
367 unsigned int flags)
357{ 368{
358 __u32 oldmask; 369 __u32 oldmask;
359 370
360 spin_lock(&fsn_mark->lock); 371 spin_lock(&fsn_mark->lock);
361 oldmask = fsn_mark->mask; 372 if (!(flags & FAN_MARK_IGNORED_MASK)) {
362 fsnotify_set_mark_mask_locked(fsn_mark, (oldmask | mask)); 373 oldmask = fsn_mark->mask;
374 fsnotify_set_mark_mask_locked(fsn_mark, (oldmask | mask));
375 } else {
376 oldmask = fsn_mark->ignored_mask;
377 fsnotify_set_mark_ignored_mask_locked(fsn_mark, (oldmask | mask));
378 }
363 spin_unlock(&fsn_mark->lock); 379 spin_unlock(&fsn_mark->lock);
364 380
365 return mask & ~oldmask; 381 return mask & ~oldmask;
366} 382}
367 383
368static int fanotify_add_vfsmount_mark(struct fsnotify_group *group, 384static int fanotify_add_vfsmount_mark(struct fsnotify_group *group,
369 struct vfsmount *mnt, __u32 mask) 385 struct vfsmount *mnt, __u32 mask,
386 unsigned int flags)
370{ 387{
371 struct fsnotify_mark *fsn_mark; 388 struct fsnotify_mark *fsn_mark;
372 __u32 added; 389 __u32 added;
@@ -386,7 +403,7 @@ static int fanotify_add_vfsmount_mark(struct fsnotify_group *group,
386 return ret; 403 return ret;
387 } 404 }
388 } 405 }
389 added = fanotify_mark_add_to_mask(fsn_mark, mask); 406 added = fanotify_mark_add_to_mask(fsn_mark, mask, flags);
390 fsnotify_put_mark(fsn_mark); 407 fsnotify_put_mark(fsn_mark);
391 if (added) { 408 if (added) {
392 if (added & ~group->mask) 409 if (added & ~group->mask)
@@ -398,7 +415,8 @@ static int fanotify_add_vfsmount_mark(struct fsnotify_group *group,
398} 415}
399 416
400static int fanotify_add_inode_mark(struct fsnotify_group *group, 417static int fanotify_add_inode_mark(struct fsnotify_group *group,
401 struct inode *inode, __u32 mask) 418 struct inode *inode, __u32 mask,
419 unsigned int flags)
402{ 420{
403 struct fsnotify_mark *fsn_mark; 421 struct fsnotify_mark *fsn_mark;
404 __u32 added; 422 __u32 added;
@@ -420,7 +438,7 @@ static int fanotify_add_inode_mark(struct fsnotify_group *group,
420 return ret; 438 return ret;
421 } 439 }
422 } 440 }
423 added = fanotify_mark_add_to_mask(fsn_mark, mask); 441 added = fanotify_mark_add_to_mask(fsn_mark, mask, flags);
424 fsnotify_put_mark(fsn_mark); 442 fsnotify_put_mark(fsn_mark);
425 if (added) { 443 if (added) {
426 if (added & ~group->mask) 444 if (added & ~group->mask)
@@ -528,15 +546,15 @@ SYSCALL_DEFINE(fanotify_mark)(int fanotify_fd, unsigned int flags,
528 switch (flags & (FAN_MARK_ADD | FAN_MARK_REMOVE)) { 546 switch (flags & (FAN_MARK_ADD | FAN_MARK_REMOVE)) {
529 case FAN_MARK_ADD: 547 case FAN_MARK_ADD:
530 if (flags & FAN_MARK_MOUNT) 548 if (flags & FAN_MARK_MOUNT)
531 ret = fanotify_add_vfsmount_mark(group, mnt, mask); 549 ret = fanotify_add_vfsmount_mark(group, mnt, mask, flags);
532 else 550 else
533 ret = fanotify_add_inode_mark(group, inode, mask); 551 ret = fanotify_add_inode_mark(group, inode, mask, flags);
534 break; 552 break;
535 case FAN_MARK_REMOVE: 553 case FAN_MARK_REMOVE:
536 if (flags & FAN_MARK_MOUNT) 554 if (flags & FAN_MARK_MOUNT)
537 ret = fanotify_remove_vfsmount_mark(group, mnt, mask); 555 ret = fanotify_remove_vfsmount_mark(group, mnt, mask, flags);
538 else 556 else
539 ret = fanotify_remove_inode_mark(group, inode, mask); 557 ret = fanotify_remove_inode_mark(group, inode, mask, flags);
540 break; 558 break;
541 default: 559 default:
542 ret = -EINVAL; 560 ret = -EINVAL;
diff --git a/include/linux/fanotify.h b/include/linux/fanotify.h
index 90e59b24fd04..b8daa9f9b560 100644
--- a/include/linux/fanotify.h
+++ b/include/linux/fanotify.h
@@ -30,12 +30,14 @@
30#define FAN_MARK_DONT_FOLLOW 0x00000004 30#define FAN_MARK_DONT_FOLLOW 0x00000004
31#define FAN_MARK_ONLYDIR 0x00000008 31#define FAN_MARK_ONLYDIR 0x00000008
32#define FAN_MARK_MOUNT 0x00000010 32#define FAN_MARK_MOUNT 0x00000010
33#define FAN_MARK_IGNORED_MASK 0x00000020
33 34
34#define FAN_ALL_MARK_FLAGS (FAN_MARK_ADD |\ 35#define FAN_ALL_MARK_FLAGS (FAN_MARK_ADD |\
35 FAN_MARK_REMOVE |\ 36 FAN_MARK_REMOVE |\
36 FAN_MARK_DONT_FOLLOW |\ 37 FAN_MARK_DONT_FOLLOW |\
37 FAN_MARK_ONLYDIR |\ 38 FAN_MARK_ONLYDIR |\
38 FAN_MARK_MOUNT) 39 FAN_MARK_MOUNT |\
40 FAN_MARK_IGNORED_MASK)
39 41
40/* 42/*
41 * All of the events - we build the list by hand so that we can add flags in 43 * All of the events - we build the list by hand so that we can add flags in