History

unfuck proc_sysctl ->d_compare()

a) struct inode is not going to be freed under ->d_compare(); however, the thing PROC_I(inode)->sysctl points to just might. Fortunately, it's enough to make freeing that sucker delayed, provided that we don't step on its ->unregistering, clear the pointer to it in PROC_I(inode) before dropping the reference and check if it's NULL in ->d_compare(). b) I'm not sure that we *can* walk into NULL inode here (we recheck dentry->seq between verifying that it's still hashed / fetching dentry->d_inode and passing it to ->d_compare() and there's no negative hashed dentries in /proc/sys/*), but if we can walk into that, we really should not have ->d_compare() return 0 on it! Said that, I really suspect that this check can be simply killed. Nick?

Al Viro committed 15 years ago

Commit dfef6dc1 parent 1858efd4 files · +31 −13Browse files

Showing the changes to include (1 of 4 files). Show all

Unified · Split

include/linux/sysctl.h+10−4
@@ -25,6 +25,7 @@ · 24 unmodified lines
2525 #include <linux/kernel.h>
2626 #include <linux/types.h>
2727 #include <linux/compiler.h>
28+#include <linux/rcupdate.h>
2829
2930 struct completion;
3031
@@ -1037,10 +1038,15 @@ struct ctl_table_root { · 1006 unmodified lines
10371038 struct ctl_table trees. */
10381039 struct ctl_table_header
10391040 {
1040− struct ctl_table *ctl_table;
1041− struct list_head ctl_entry;
1042− int used;
1043− int count;
1041+ union {
1042+ struct {
1043+ struct ctl_table *ctl_table;
1044+ struct list_head ctl_entry;
1045+ int used;
1046+ int count;
1047+ };
1048+ struct rcu_head rcu;
1049+ };
10441050 struct completion *unregistering;
10451051 struct ctl_table *ctl_table_arg;
10461052 struct ctl_table_root *root;