diff options
-rw-r--r-- | fs/notify/fanotify/fanotify_user.c | 54 | ||||
-rw-r--r-- | include/linux/fanotify.h | 4 |
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 | ||
299 | static __u32 fanotify_mark_remove_from_mask(struct fsnotify_mark *fsn_mark, __u32 mask) | 299 | static __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 | ||
314 | static int fanotify_remove_vfsmount_mark(struct fsnotify_group *group, | 321 | static 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 | ||
334 | static int fanotify_remove_inode_mark(struct fsnotify_group *group, | 342 | static 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 | ||
356 | static __u32 fanotify_mark_add_to_mask(struct fsnotify_mark *fsn_mark, __u32 mask) | 365 | static __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 | ||
368 | static int fanotify_add_vfsmount_mark(struct fsnotify_group *group, | 384 | static 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 | ||
400 | static int fanotify_add_inode_mark(struct fsnotify_group *group, | 417 | static 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 |