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
25#include <linux/kernel.h>25#include <linux/kernel.h>
26#include <linux/types.h>26#include <linux/types.h>
27#include <linux/compiler.h>27#include <linux/compiler.h>
28#include <linux/rcupdate.h>
28 29
29struct completion;30struct completion;
30 31
@@ -1037,10 +1038,15 @@ struct ctl_table_root { · 1006 unmodified lines
1037 struct ctl_table trees. */1038 struct ctl_table trees. */
1038struct ctl_table_header1039struct ctl_table_header
1039{1040{
1040 struct ctl_table *ctl_table;1041 union {
1041 struct list_head ctl_entry;1042 struct {
1042 int used;1043 struct ctl_table *ctl_table;
1043 int count;1044 struct list_head ctl_entry;
1045 int used;
1046 int count;
1047 };
1048 struct rcu_head rcu;
1049 };
1044 struct completion *unregistering;1050 struct completion *unregistering;
1045 struct ctl_table *ctl_table_arg;1051 struct ctl_table *ctl_table_arg;
1046 struct ctl_table_root *root;1052 struct ctl_table_root *root;