Commit 4fc4c3ce authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'for-linus' of git://git.infradead.org/users/eparis/notify

* 'for-linus' of git://git.infradead.org/users/eparis/notify:
  inotify: don't leak user struct on inotify release
  inotify: race use after free/double free in inotify inode marks
  inotify: clean up the inotify_add_watch out path
  Inotify: undefined reference to `anon_inode_getfd'

Manual merge to remove duplicate "select ANON_INODES" from Kconfig file
parents 97b2073f b3b38d84
...@@ -28,6 +28,7 @@ ...@@ -28,6 +28,7 @@
#include <linux/path.h> /* struct path */ #include <linux/path.h> /* struct path */
#include <linux/slab.h> /* kmem_* */ #include <linux/slab.h> /* kmem_* */
#include <linux/types.h> #include <linux/types.h>
#include <linux/sched.h>
#include "inotify.h" #include "inotify.h"
...@@ -146,6 +147,7 @@ static void inotify_free_group_priv(struct fsnotify_group *group) ...@@ -146,6 +147,7 @@ static void inotify_free_group_priv(struct fsnotify_group *group)
idr_for_each(&group->inotify_data.idr, idr_callback, group); idr_for_each(&group->inotify_data.idr, idr_callback, group);
idr_remove_all(&group->inotify_data.idr); idr_remove_all(&group->inotify_data.idr);
idr_destroy(&group->inotify_data.idr); idr_destroy(&group->inotify_data.idr);
free_uid(group->inotify_data.user);
} }
void inotify_free_event_priv(struct fsnotify_event_private_data *fsn_event_priv) void inotify_free_event_priv(struct fsnotify_event_private_data *fsn_event_priv)
......
...@@ -546,21 +546,24 @@ static int inotify_new_watch(struct fsnotify_group *group, ...@@ -546,21 +546,24 @@ static int inotify_new_watch(struct fsnotify_group *group,
if (unlikely(!idr_pre_get(&group->inotify_data.idr, GFP_KERNEL))) if (unlikely(!idr_pre_get(&group->inotify_data.idr, GFP_KERNEL)))
goto out_err; goto out_err;
/* we are putting the mark on the idr, take a reference */
fsnotify_get_mark(&tmp_ientry->fsn_entry);
spin_lock(&group->inotify_data.idr_lock); spin_lock(&group->inotify_data.idr_lock);
ret = idr_get_new_above(&group->inotify_data.idr, &tmp_ientry->fsn_entry, ret = idr_get_new_above(&group->inotify_data.idr, &tmp_ientry->fsn_entry,
group->inotify_data.last_wd+1, group->inotify_data.last_wd+1,
&tmp_ientry->wd); &tmp_ientry->wd);
spin_unlock(&group->inotify_data.idr_lock); spin_unlock(&group->inotify_data.idr_lock);
if (ret) { if (ret) {
/* we didn't get on the idr, drop the idr reference */
fsnotify_put_mark(&tmp_ientry->fsn_entry);
/* idr was out of memory allocate and try again */ /* idr was out of memory allocate and try again */
if (ret == -EAGAIN) if (ret == -EAGAIN)
goto retry; goto retry;
goto out_err; goto out_err;
} }
/* we put the mark on the idr, take a reference */
fsnotify_get_mark(&tmp_ientry->fsn_entry);
/* we are on the idr, now get on the inode */ /* we are on the idr, now get on the inode */
ret = fsnotify_add_mark(&tmp_ientry->fsn_entry, group, inode); ret = fsnotify_add_mark(&tmp_ientry->fsn_entry, group, inode);
if (ret) { if (ret) {
...@@ -578,16 +581,13 @@ static int inotify_new_watch(struct fsnotify_group *group, ...@@ -578,16 +581,13 @@ static int inotify_new_watch(struct fsnotify_group *group,
/* return the watch descriptor for this new entry */ /* return the watch descriptor for this new entry */
ret = tmp_ientry->wd; ret = tmp_ientry->wd;
/* match the ref from fsnotify_init_markentry() */
fsnotify_put_mark(&tmp_ientry->fsn_entry);
/* if this mark added a new event update the group mask */ /* if this mark added a new event update the group mask */
if (mask & ~group->mask) if (mask & ~group->mask)
fsnotify_recalc_group_mask(group); fsnotify_recalc_group_mask(group);
out_err: out_err:
if (ret < 0) /* match the ref from fsnotify_init_markentry() */
kmem_cache_free(inotify_inode_mark_cachep, tmp_ientry); fsnotify_put_mark(&tmp_ientry->fsn_entry);
return ret; return ret;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment