diff mbox series

fsnotify: fix false positive warning on inode delete

Message ID 1534682106-26538-1-git-send-email-amir73il@gmail.com (mailing list archive)
State New, archived
Headers show
Series fsnotify: fix false positive warning on inode delete | expand

Commit Message

Amir Goldstein Aug. 19, 2018, 12:35 p.m. UTC
Reported-and-tested-by: syzbot+c34692a51b9a6ca93540@syzkaller.appspotmail.com
Fixes: 3ac70bfcde81 ("fsnotify: add helper to get mask from connector")
Signed-off-by: Amir Goldstein <amir73il@gmail.com>
---

Jan,

syzbot reported (in private email) that the reproducer did not trigger
the warning, so added tested-by.

Thanks,
Amir.

 fs/notify/mark.c | 7 +++++++
 1 file changed, 7 insertions(+)

Comments

Jan Kara Aug. 20, 2018, 10:07 a.m. UTC | #1
On Sun 19-08-18 15:35:06, Amir Goldstein wrote:
> Reported-and-tested-by: syzbot+c34692a51b9a6ca93540@syzkaller.appspotmail.com
> Fixes: 3ac70bfcde81 ("fsnotify: add helper to get mask from connector")
> Signed-off-by: Amir Goldstein <amir73il@gmail.com>
> ---
> 
> Jan,
> 
> syzbot reported (in private email) that the reproducer did not trigger
> the warning, so added tested-by.

Thanks for looking into this Amir! I was thinking about this for a while
and I'm not sure that __fsnotify_recalc_mask() call from
fsnotify_put_mark() is the only place calling __fsnotify_recalc_mask() that
can happen on detached connector. unlink(2) can get called pretty much at
any time so places like inotify_update_existing_watch() can easily work on
inode that is getting unlinked and by the time we get to
fsnotify_recalc_mask(), we can pass detached connector to it AFAICT.
conn->lock we hold in __fsnotify_recalc_mask() protecs us from
fsnotify_detach_connector_from_object() so we can reliably check connector
state in __fsnotify_recalc_mask() and just don't do anything when the
connector is already detached without issuing a warning. What do you think?

								Honza

>  fs/notify/mark.c | 7 +++++++
>  1 file changed, 7 insertions(+)
> 
> diff --git a/fs/notify/mark.c b/fs/notify/mark.c
> index 05506d60131c..d559a8ffe7ed 100644
> --- a/fs/notify/mark.c
> +++ b/fs/notify/mark.c
> @@ -236,6 +236,13 @@ void fsnotify_put_mark(struct fsnotify_mark *mark)
>  	if (hlist_empty(&conn->list)) {
>  		inode = fsnotify_detach_connector_from_object(conn);
>  		free_conn = true;
> +	} else if (conn->type == FSNOTIFY_OBJ_TYPE_DETACHED) {
> +		/*
> +		 * fsnotify_destroy_marks() detaches conn from object before
> +		 * put on last mark of object list and other marks on the list
> +		 * may still have elevated refcounts. We don't need to recalc
> +		 * mask nor to free_conn in that case.
> +		 */
>  	} else {
>  		__fsnotify_recalc_mask(conn);
>  	}
> -- 
> 2.7.4
>
Amir Goldstein Aug. 20, 2018, 10:32 a.m. UTC | #2
On Mon, Aug 20, 2018 at 1:07 PM Jan Kara <jack@suse.cz> wrote:
>
> On Sun 19-08-18 15:35:06, Amir Goldstein wrote:
> > Reported-and-tested-by: syzbot+c34692a51b9a6ca93540@syzkaller.appspotmail.com
> > Fixes: 3ac70bfcde81 ("fsnotify: add helper to get mask from connector")
> > Signed-off-by: Amir Goldstein <amir73il@gmail.com>
> > ---
> >
> > Jan,
> >
> > syzbot reported (in private email) that the reproducer did not trigger
> > the warning, so added tested-by.
>
> Thanks for looking into this Amir! I was thinking about this for a while
> and I'm not sure that __fsnotify_recalc_mask() call from
> fsnotify_put_mark() is the only place calling __fsnotify_recalc_mask() that
> can happen on detached connector. unlink(2) can get called pretty much at
> any time so places like inotify_update_existing_watch() can easily work on
> inode that is getting unlinked and by the time we get to
> fsnotify_recalc_mask(), we can pass detached connector to it AFAICT.
> conn->lock we hold in __fsnotify_recalc_mask() protecs us from
> fsnotify_detach_connector_from_object() so we can reliably check connector
> state in __fsnotify_recalc_mask() and just don't do anything when the
> connector is already detached without issuing a warning. What do you think?
>

Makes sense. WARN_ON() is a new addition by cleanup patches
and the fact that disconnected state is valid in __fsnotify_recalc_mask()
was an oversight.

Feel free to apply the simpler fix with reported-by attribution to syzbot ;-)

Thanks,
Amir.
diff mbox series

Patch

diff --git a/fs/notify/mark.c b/fs/notify/mark.c
index 05506d60131c..d559a8ffe7ed 100644
--- a/fs/notify/mark.c
+++ b/fs/notify/mark.c
@@ -236,6 +236,13 @@  void fsnotify_put_mark(struct fsnotify_mark *mark)
 	if (hlist_empty(&conn->list)) {
 		inode = fsnotify_detach_connector_from_object(conn);
 		free_conn = true;
+	} else if (conn->type == FSNOTIFY_OBJ_TYPE_DETACHED) {
+		/*
+		 * fsnotify_destroy_marks() detaches conn from object before
+		 * put on last mark of object list and other marks on the list
+		 * may still have elevated refcounts. We don't need to recalc
+		 * mask nor to free_conn in that case.
+		 */
 	} else {
 		__fsnotify_recalc_mask(conn);
 	}