Pull vfs stable fodder fixes from Al Viro: - acct_on() fix for deadlock caught by overlayfs folks - autofs RCU use-after-free SNAFU (->d_manage() can be called locklessly, so we need to RCU-delay freeing the objects it looks at) - (hopefully) the end of "do we need freeing this dentry RCU-delayed" whack-a-mole. * 'stable-fodder' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs: autofs: fix use-after-free in lockless ->d_manage() dcache: sort the freeing-without-RCU-delay mess for good. acct_on(): don't mess with freeze protection
Unified · Split
| @@ -663,3 +663,8 @@ in your dentry operations instead. · 662 unmodified lines | ||
| 663 | 663 | there, but that's it. Freeing memory in the callback is fine; doing |
| 664 | 664 | more than that is possible, but requires a lot of care and is best |
| 665 | 665 | avoided. |
| 666 | +-- | |
| 667 | +[mandatory] | |
| 668 | + DCACHE_RCUACCESS is gone; having an RCU delay on dentry freeing is the | |
| 669 | + default. DCACHE_NORCU opts out, and only d_alloc_pseudo() has any | |
| 670 | + business doing so. | |
| @@ -71,6 +71,7 @@ struct autofs_info { · 70 unmodified lines | ||
| 71 | 71 | |
| 72 | 72 | kuid_t uid; |
| 73 | 73 | kgid_t gid; |
| 74 | + struct rcu_head rcu; | |
| 74 | 75 | }; |
| 75 | 76 | |
| 76 | 77 | #define AUTOFS_INF_EXPIRING (1<<0) /* dentry in the process of expiring */ |
| @@ -36,7 +36,7 @@ void autofs_clean_ino(struct autofs_info *ino) · 35 unmodified lines | ||
| 36 | 36 | |
| 37 | 37 | void autofs_free_ino(struct autofs_info *ino) |
| 38 | 38 | { |
| 39 | − kfree(ino); | |
| 39 | + kfree_rcu(ino, rcu); | |
| 40 | 40 | } |
| 41 | 41 | |
| 42 | 42 | void autofs_kill_sb(struct super_block *sb) |
| @@ -344,7 +344,7 @@ static void dentry_free(struct dentry *dentry) · 343 unmodified lines | ||
| 344 | 344 | } |
| 345 | 345 | } |
| 346 | 346 | /* if dentry was never visible to RCU, immediate free is OK */ |
| 347 | − if (!(dentry->d_flags & DCACHE_RCUACCESS)) | |
| 347 | + if (dentry->d_flags & DCACHE_NORCU) | |
| 348 | 348 | __d_free(&dentry->d_u.d_rcu); |
| 349 | 349 | else |
| 350 | 350 | call_rcu(&dentry->d_u.d_rcu, __d_free); |
| @@ -1701,7 +1701,6 @@ struct dentry *d_alloc(struct dentry * parent, const struct qstr *name) · 1350 unmodified lines | ||
| 1701 | 1701 | struct dentry *dentry = __d_alloc(parent->d_sb, name); |
| 1702 | 1702 | if (!dentry) |
| 1703 | 1703 | return NULL; |
| 1704 | − dentry->d_flags |= DCACHE_RCUACCESS; | |
| 1705 | 1704 | spin_lock(&parent->d_lock); |
| 1706 | 1705 | /* |
| 1707 | 1706 | * don't need child lock because it is not subject |
| @@ -1726,7 +1725,7 @@ struct dentry *d_alloc_cursor(struct dentry * parent) · 18 unmodified lines | ||
| 1726 | 1725 | { |
| 1727 | 1726 | struct dentry *dentry = d_alloc_anon(parent->d_sb); |
| 1728 | 1727 | if (dentry) { |
| 1729 | − dentry->d_flags |= DCACHE_RCUACCESS | DCACHE_DENTRY_CURSOR; | |
| 1728 | + dentry->d_flags |= DCACHE_DENTRY_CURSOR; | |
| 1730 | 1729 | dentry->d_parent = dget(parent); |
| 1731 | 1730 | } |
| 1732 | 1731 | return dentry; |
| @@ -1739,10 +1738,17 @@ struct dentry *d_alloc_cursor(struct dentry * parent) · 6 unmodified lines | ||
| 1739 | 1738 | * |
| 1740 | 1739 | * For a filesystem that just pins its dentries in memory and never |
| 1741 | 1740 | * performs lookups at all, return an unhashed IS_ROOT dentry. |
| 1741 | + * This is used for pipes, sockets et.al. - the stuff that should | |
| 1742 | + * never be anyone's children or parents. Unlike all other | |
| 1743 | + * dentries, these will not have RCU delay between dropping the | |
| 1744 | + * last reference and freeing them. | |
| 1742 | 1745 | */ |
| 1743 | 1746 | struct dentry *d_alloc_pseudo(struct super_block *sb, const struct qstr *name) |
| 1744 | 1747 | { |
| 1745 | − return __d_alloc(sb, name); | |
| 1748 | + struct dentry *dentry = __d_alloc(sb, name); | |
| 1749 | + if (likely(dentry)) | |
| 1750 | + dentry->d_flags |= DCACHE_NORCU; | |
| 1751 | + return dentry; | |
| 1746 | 1752 | } |
| 1747 | 1753 | EXPORT_SYMBOL(d_alloc_pseudo); |
| 1748 | 1754 | |
| @@ -1911,12 +1917,10 @@ struct dentry *d_make_root(struct inode *root_inode) · 162 unmodified lines | ||
| 1911 | 1917 | |
| 1912 | 1918 | if (root_inode) { |
| 1913 | 1919 | res = d_alloc_anon(root_inode->i_sb); |
| 1914 | − if (res) { | |
| 1915 | − res->d_flags |= DCACHE_RCUACCESS; | |
| 1920 | + if (res) | |
| 1916 | 1921 | d_instantiate(res, root_inode); |
| 1917 | − } else { | |
| 1922 | + else | |
| 1918 | 1923 | iput(root_inode); |
| 1919 | − } | |
| 1920 | 1924 | } |
| 1921 | 1925 | return res; |
| 1922 | 1926 | } |
| @@ -2781,9 +2785,7 @@ static void __d_move(struct dentry *dentry, struct dentry *target, · 858 unmodified lines | ||
| 2781 | 2785 | copy_name(dentry, target); |
| 2782 | 2786 | target->d_hash.pprev = NULL; |
| 2783 | 2787 | dentry->d_parent->d_lockref.count++; |
| 2784 | − if (dentry == old_parent) | |
| 2785 | − dentry->d_flags |= DCACHE_RCUACCESS; | |
| 2786 | − else | |
| 2788 | + if (dentry != old_parent) /* wasn't IS_ROOT */ | |
| 2787 | 2789 | WARN_ON(!--old_parent->d_lockref.count); |
| 2788 | 2790 | } else { |
| 2789 | 2791 | target->d_parent = old_parent; |
| @@ -89,9 +89,7 @@ extern int sb_prepare_remount_readonly(struct super_block *); · 88 unmodified lines | ||
| 89 | 89 | |
| 90 | 90 | extern void __init mnt_init(void); |
| 91 | 91 | |
| 92 | −extern int __mnt_want_write(struct vfsmount *); | |
| 93 | 92 | extern int __mnt_want_write_file(struct file *); |
| 94 | −extern void __mnt_drop_write(struct vfsmount *); | |
| 95 | 93 | extern void __mnt_drop_write_file(struct file *); |
| 96 | 94 | |
| 97 | 95 | /* |
| @@ -85,13 +85,12 @@ slow: · 84 unmodified lines | ||
| 85 | 85 | inode->i_fop = &ns_file_operations; |
| 86 | 86 | inode->i_private = ns; |
| 87 | 87 | |
| 88 | − dentry = d_alloc_pseudo(mnt->mnt_sb, &empty_name); | |
| 88 | + dentry = d_alloc_anon(mnt->mnt_sb); | |
| 89 | 89 | if (!dentry) { |
| 90 | 90 | iput(inode); |
| 91 | 91 | return ERR_PTR(-ENOMEM); |
| 92 | 92 | } |
| 93 | 93 | d_instantiate(dentry, inode); |
| 94 | − dentry->d_flags |= DCACHE_RCUACCESS; | |
| 95 | 94 | dentry->d_fsdata = (void *)ns->ops; |
| 96 | 95 | d = atomic_long_cmpxchg(&ns->stashed, 0, (unsigned long)dentry); |
| 97 | 96 | if (d) { |
| @@ -176,7 +176,6 @@ struct dentry_operations { · 175 unmodified lines | ||
| 176 | 176 | * typically using d_splice_alias. */ |
| 177 | 177 | |
| 178 | 178 | #define DCACHE_REFERENCED 0x00000040 /* Recently used, don't discard. */ |
| 179 | −#define DCACHE_RCUACCESS 0x00000080 /* Entry has ever been RCU-visible */ | |
| 180 | 179 | |
| 181 | 180 | #define DCACHE_CANT_MOUNT 0x00000100 |
| 182 | 181 | #define DCACHE_GENOCIDE 0x00000200 |
| @@ -217,6 +216,7 @@ struct dentry_operations { · 34 unmodified lines | ||
| 217 | 216 | |
| 218 | 217 | #define DCACHE_PAR_LOOKUP 0x10000000 /* being looked up (with parent locked shared) */ |
| 219 | 218 | #define DCACHE_DENTRY_CURSOR 0x20000000 |
| 219 | +#define DCACHE_NORCU 0x40000000 /* No RCU delay for freeing */ | |
| 220 | 220 | |
| 221 | 221 | extern seqlock_t rename_lock; |
| 222 | 222 | |
| @@ -87,6 +87,8 @@ extern bool mnt_may_suid(struct vfsmount *mnt); · 86 unmodified lines | ||
| 87 | 87 | |
| 88 | 88 | struct path; |
| 89 | 89 | extern struct vfsmount *clone_private_mount(const struct path *path); |
| 90 | +extern int __mnt_want_write(struct vfsmount *); | |
| 91 | +extern void __mnt_drop_write(struct vfsmount *); | |
| 90 | 92 | |
| 91 | 93 | struct file_system_type; |
| 92 | 94 | extern struct vfsmount *fc_mount(struct fs_context *fc); |
| @@ -227,7 +227,7 @@ static int acct_on(struct filename *pathname) · 226 unmodified lines | ||
| 227 | 227 | filp_close(file, NULL); |
| 228 | 228 | return PTR_ERR(internal); |
| 229 | 229 | } |
| 230 | − err = mnt_want_write(internal); | |
| 230 | + err = __mnt_want_write(internal); | |
| 231 | 231 | if (err) { |
| 232 | 232 | mntput(internal); |
| 233 | 233 | kfree(acct); |
| @@ -252,7 +252,7 @@ static int acct_on(struct filename *pathname) · 18 unmodified lines | ||
| 252 | 252 | old = xchg(&ns->bacct, &acct->pin); |
| 253 | 253 | mutex_unlock(&acct->lock); |
| 254 | 254 | pin_kill(old); |
| 255 | − mnt_drop_write(mnt); | |
| 255 | + __mnt_drop_write(mnt); | |
| 256 | 256 | mntput(mnt); |
| 257 | 257 | return 0; |
| 258 | 258 | } |