aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorJozsef Kadlecsik <kadlec@blackhole.kfki.hu>2011-03-20 10:35:01 -0400
committerPatrick McHardy <kaber@trash.net>2011-03-20 10:35:01 -0400
commit5c1aba467828bf0574ec5754c84884d573f590af (patch)
tree12973d3d9f15cb6e1f95e2e9f8dd930ad36aa629 /net
parent5e0c1eb7e6b61998c7ecd39b7f69a15773d894d4 (diff)
netfilter: ipset: fix checking the type revision at create command
The revision of the set type was not checked at the create command: if the userspace sent a valid set type but with not supported revision number, it'd create a loop. Signed-off-by: Jozsef Kadlecsik <kadlec@blackhole.kfki.hu> Signed-off-by: Patrick McHardy <kaber@trash.net>
Diffstat (limited to 'net')
-rw-r--r--net/netfilter/ipset/ip_set_core.c22
1 files changed, 17 insertions, 5 deletions
diff --git a/net/netfilter/ipset/ip_set_core.c b/net/netfilter/ipset/ip_set_core.c
index 618a615acc9d..d6b48230a540 100644
--- a/net/netfilter/ipset/ip_set_core.c
+++ b/net/netfilter/ipset/ip_set_core.c
@@ -94,16 +94,28 @@ static int
94find_set_type_get(const char *name, u8 family, u8 revision, 94find_set_type_get(const char *name, u8 family, u8 revision,
95 struct ip_set_type **found) 95 struct ip_set_type **found)
96{ 96{
97 struct ip_set_type *type;
98 int err;
99
97 rcu_read_lock(); 100 rcu_read_lock();
98 *found = find_set_type(name, family, revision); 101 *found = find_set_type(name, family, revision);
99 if (*found) { 102 if (*found) {
100 int err = !try_module_get((*found)->me); 103 err = !try_module_get((*found)->me) ? -EFAULT : 0;
101 rcu_read_unlock(); 104 goto unlock;
102 return err ? -EFAULT : 0;
103 } 105 }
106 /* Make sure the type is loaded but we don't support the revision */
107 list_for_each_entry_rcu(type, &ip_set_type_list, list)
108 if (STREQ(type->name, name)) {
109 err = -IPSET_ERR_FIND_TYPE;
110 goto unlock;
111 }
104 rcu_read_unlock(); 112 rcu_read_unlock();
105 113
106 return try_to_load_type(name); 114 return try_to_load_type(name);
115
116unlock:
117 rcu_read_unlock();
118 return err;
107} 119}
108 120
109/* Find a given set type by name and family. 121/* Find a given set type by name and family.
@@ -116,7 +128,7 @@ find_set_type_minmax(const char *name, u8 family, u8 *min, u8 *max)
116 struct ip_set_type *type; 128 struct ip_set_type *type;
117 bool found = false; 129 bool found = false;
118 130
119 *min = *max = 0; 131 *min = 255; *max = 0;
120 rcu_read_lock(); 132 rcu_read_lock();
121 list_for_each_entry_rcu(type, &ip_set_type_list, list) 133 list_for_each_entry_rcu(type, &ip_set_type_list, list)
122 if (STREQ(type->name, name) && 134 if (STREQ(type->name, name) &&
@@ -124,7 +136,7 @@ find_set_type_minmax(const char *name, u8 family, u8 *min, u8 *max)
124 found = true; 136 found = true;
125 if (type->revision < *min) 137 if (type->revision < *min)
126 *min = type->revision; 138 *min = type->revision;
127 else if (type->revision > *max) 139 if (type->revision > *max)
128 *max = type->revision; 140 *max = type->revision;
129 } 141 }
130 rcu_read_unlock(); 142 rcu_read_unlock();