diff options
author | Jozsef Kadlecsik <kadlec@blackhole.kfki.hu> | 2011-03-20 10:35:01 -0400 |
---|---|---|
committer | Patrick McHardy <kaber@trash.net> | 2011-03-20 10:35:01 -0400 |
commit | 5c1aba467828bf0574ec5754c84884d573f590af (patch) | |
tree | 12973d3d9f15cb6e1f95e2e9f8dd930ad36aa629 /net | |
parent | 5e0c1eb7e6b61998c7ecd39b7f69a15773d894d4 (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.c | 22 |
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 | |||
94 | find_set_type_get(const char *name, u8 family, u8 revision, | 94 | find_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 | |||
116 | unlock: | ||
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(); |