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>

authored by Jozsef Kadlecsik and committed by Patrick McHardy 5c1aba46 5e0c1eb7

+17 -5
+17 -5
net/netfilter/ipset/ip_set_core.c
··· 94 94 find_set_type_get(const char *name, u8 family, u8 revision, 95 95 struct ip_set_type **found) 96 96 { 97 + struct ip_set_type *type; 98 + int err; 99 + 97 100 rcu_read_lock(); 98 101 *found = find_set_type(name, family, revision); 99 102 if (*found) { 100 - int err = !try_module_get((*found)->me); 101 - rcu_read_unlock(); 102 - return err ? -EFAULT : 0; 103 + err = !try_module_get((*found)->me) ? -EFAULT : 0; 104 + goto unlock; 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 112 rcu_read_unlock(); 105 113 106 114 return try_to_load_type(name); 115 + 116 + unlock: 117 + rcu_read_unlock(); 118 + return err; 107 119 } 108 120 109 121 /* Find a given set type by name and family. ··· 128 116 struct ip_set_type *type; 129 117 bool found = false; 130 118 131 - *min = *max = 0; 119 + *min = 255; *max = 0; 132 120 rcu_read_lock(); 133 121 list_for_each_entry_rcu(type, &ip_set_type_list, list) 134 122 if (STREQ(type->name, name) && ··· 136 124 found = true; 137 125 if (type->revision < *min) 138 126 *min = type->revision; 139 - else if (type->revision > *max) 127 + if (type->revision > *max) 140 128 *max = type->revision; 141 129 } 142 130 rcu_read_unlock();