* '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
Unified · Split
| @@ -28,6 +28,7 @@ · 27 unmodified lines | ||
| 28 | 28 | #include <linux/path.h> /* struct path */ |
| 29 | 29 | #include <linux/slab.h> /* kmem_* */ |
| 30 | 30 | #include <linux/types.h> |
| 31 | +#include <linux/sched.h> | |
| 31 | 32 | |
| 32 | 33 | #include "inotify.h" |
| 33 | 34 | |
| @@ -146,6 +147,7 @@ static void inotify_free_group_priv(struct fsnotify_group *group) · 112 unmodified lines | ||
| 146 | 147 | idr_for_each(&group->inotify_data.idr, idr_callback, group); |
| 147 | 148 | idr_remove_all(&group->inotify_data.idr); |
| 148 | 149 | idr_destroy(&group->inotify_data.idr); |
| 150 | + free_uid(group->inotify_data.user); | |
| 149 | 151 | } |
| 150 | 152 | |
| 151 | 153 | void inotify_free_event_priv(struct fsnotify_event_private_data *fsn_event_priv) |
| @@ -546,21 +546,24 @@ retry: · 545 unmodified lines | ||
| 546 | 546 | if (unlikely(!idr_pre_get(&group->inotify_data.idr, GFP_KERNEL))) |
| 547 | 547 | goto out_err; |
| 548 | 548 | |
| 549 | + /* we are putting the mark on the idr, take a reference */ | |
| 550 | + fsnotify_get_mark(&tmp_ientry->fsn_entry); | |
| 551 | + | |
| 549 | 552 | spin_lock(&group->inotify_data.idr_lock); |
| 550 | 553 | ret = idr_get_new_above(&group->inotify_data.idr, &tmp_ientry->fsn_entry, |
| 551 | 554 | group->inotify_data.last_wd+1, |
| 552 | 555 | &tmp_ientry->wd); |
| 553 | 556 | spin_unlock(&group->inotify_data.idr_lock); |
| 554 | 557 | if (ret) { |
| 558 | + /* we didn't get on the idr, drop the idr reference */ | |
| 559 | + fsnotify_put_mark(&tmp_ientry->fsn_entry); | |
| 560 | + | |
| 555 | 561 | /* idr was out of memory allocate and try again */ |
| 556 | 562 | if (ret == -EAGAIN) |
| 557 | 563 | goto retry; |
| 558 | 564 | goto out_err; |
| 559 | 565 | } |
| 560 | 566 | |
| 561 | − /* we put the mark on the idr, take a reference */ | |
| 562 | − fsnotify_get_mark(&tmp_ientry->fsn_entry); | |
| 563 | − | |
| 564 | 567 | /* we are on the idr, now get on the inode */ |
| 565 | 568 | ret = fsnotify_add_mark(&tmp_ientry->fsn_entry, group, inode); |
| 566 | 569 | if (ret) { |
| @@ -578,16 +581,13 @@ retry: · 11 unmodified lines | ||
| 578 | 581 | /* return the watch descriptor for this new entry */ |
| 579 | 582 | ret = tmp_ientry->wd; |
| 580 | 583 | |
| 581 | − /* match the ref from fsnotify_init_markentry() */ | |
| 582 | − fsnotify_put_mark(&tmp_ientry->fsn_entry); | |
| 583 | − | |
| 584 | 584 | /* if this mark added a new event update the group mask */ |
| 585 | 585 | if (mask & ~group->mask) |
| 586 | 586 | fsnotify_recalc_group_mask(group); |
| 587 | 587 | |
| 588 | 588 | out_err: |
| 589 | − if (ret < 0) | |
| 590 | − kmem_cache_free(inotify_inode_mark_cachep, tmp_ientry); | |
| 589 | + /* match the ref from fsnotify_init_markentry() */ | |
| 590 | + fsnotify_put_mark(&tmp_ientry->fsn_entry); | |
| 591 | 591 | |
| 592 | 592 | return ret; |
| 593 | 593 | } |