Commit bab5cac6 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
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
parents 772b78c2 b969f961
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -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);
	}
}
+11 −7
Original line number Diff line number Diff line
@@ -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);
}