Merge tag 'pull-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs
Pull /proc/sys dcache lookup fix from Al Viro: "Fix for the breakage spotted by Neil in the interplay between /proc/sys ->d_compare() weirdness and parallel lookups" * tag 'pull-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs: fix proc_sys_compare() handling of in-lookup dentries
This commit is contained in:
@@ -42,7 +42,7 @@ static void proc_evict_inode(struct inode *inode)
|
||||
|
||||
head = ei->sysctl;
|
||||
if (head) {
|
||||
RCU_INIT_POINTER(ei->sysctl, NULL);
|
||||
WRITE_ONCE(ei->sysctl, NULL);
|
||||
proc_sys_evict_inode(inode, head);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -918,17 +918,21 @@ static int proc_sys_compare(const struct dentry *dentry,
|
||||
struct ctl_table_header *head;
|
||||
struct inode *inode;
|
||||
|
||||
/* Although proc doesn't have negative dentries, rcu-walk means
|
||||
* that inode here can be NULL */
|
||||
/* AV: can it, indeed? */
|
||||
inode = d_inode_rcu(dentry);
|
||||
if (!inode)
|
||||
return 1;
|
||||
if (name->len != len)
|
||||
return 1;
|
||||
if (memcmp(name->name, str, len))
|
||||
return 1;
|
||||
head = rcu_dereference(PROC_I(inode)->sysctl);
|
||||
|
||||
// false positive is fine here - we'll recheck anyway
|
||||
if (d_in_lookup(dentry))
|
||||
return 0;
|
||||
|
||||
inode = d_inode_rcu(dentry);
|
||||
// we just might have run into dentry in the middle of __dentry_kill()
|
||||
if (!inode)
|
||||
return 1;
|
||||
|
||||
head = READ_ONCE(PROC_I(inode)->sysctl);
|
||||
return !head || !sysctl_is_seen(head);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user