Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

netfilter: add missing error handling code for register functions

register_{netdevice/inetaddr/inet6addr}_notifier may return an error
value, this patch adds the code to handle these error paths.

Signed-off-by: Taehee Yoo <ap420073@gmail.com>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>

authored by

Taehee Yoo and committed by
Pablo Neira Ayuso
584eab29 508b0904

+63 -22
+1 -1
include/net/netfilter/ipv4/nf_nat_masquerade.h
··· 9 9 const struct nf_nat_range2 *range, 10 10 const struct net_device *out); 11 11 12 - void nf_nat_masquerade_ipv4_register_notifier(void); 12 + int nf_nat_masquerade_ipv4_register_notifier(void); 13 13 void nf_nat_masquerade_ipv4_unregister_notifier(void); 14 14 15 15 #endif /*_NF_NAT_MASQUERADE_IPV4_H_ */
+1 -1
include/net/netfilter/ipv6/nf_nat_masquerade.h
··· 5 5 unsigned int 6 6 nf_nat_masquerade_ipv6(struct sk_buff *skb, const struct nf_nat_range2 *range, 7 7 const struct net_device *out); 8 - void nf_nat_masquerade_ipv6_register_notifier(void); 8 + int nf_nat_masquerade_ipv6_register_notifier(void); 9 9 void nf_nat_masquerade_ipv6_unregister_notifier(void); 10 10 11 11 #endif /* _NF_NAT_MASQUERADE_IPV6_H_ */
+5 -2
net/ipv4/netfilter/ipt_MASQUERADE.c
··· 81 81 int ret; 82 82 83 83 ret = xt_register_target(&masquerade_tg_reg); 84 + if (ret) 85 + return ret; 84 86 85 - if (ret == 0) 86 - nf_nat_masquerade_ipv4_register_notifier(); 87 + ret = nf_nat_masquerade_ipv4_register_notifier(); 88 + if (ret) 89 + xt_unregister_target(&masquerade_tg_reg); 87 90 88 91 return ret; 89 92 }
+17 -4
net/ipv4/netfilter/nf_nat_masquerade_ipv4.c
··· 149 149 150 150 static atomic_t masquerade_notifier_refcount = ATOMIC_INIT(0); 151 151 152 - void nf_nat_masquerade_ipv4_register_notifier(void) 152 + int nf_nat_masquerade_ipv4_register_notifier(void) 153 153 { 154 + int ret; 155 + 154 156 /* check if the notifier was already set */ 155 157 if (atomic_inc_return(&masquerade_notifier_refcount) > 1) 156 - return; 158 + return 0; 157 159 158 160 /* Register for device down reports */ 159 - register_netdevice_notifier(&masq_dev_notifier); 161 + ret = register_netdevice_notifier(&masq_dev_notifier); 162 + if (ret) 163 + goto err_dec; 160 164 /* Register IP address change reports */ 161 - register_inetaddr_notifier(&masq_inet_notifier); 165 + ret = register_inetaddr_notifier(&masq_inet_notifier); 166 + if (ret) 167 + goto err_unregister; 168 + 169 + return ret; 170 + err_unregister: 171 + unregister_netdevice_notifier(&masq_dev_notifier); 172 + err_dec: 173 + atomic_dec(&masquerade_notifier_refcount); 174 + return ret; 162 175 } 163 176 EXPORT_SYMBOL_GPL(nf_nat_masquerade_ipv4_register_notifier); 164 177
+3 -1
net/ipv4/netfilter/nft_masq_ipv4.c
··· 69 69 if (ret < 0) 70 70 return ret; 71 71 72 - nf_nat_masquerade_ipv4_register_notifier(); 72 + ret = nf_nat_masquerade_ipv4_register_notifier(); 73 + if (ret) 74 + nft_unregister_expr(&nft_masq_ipv4_type); 73 75 74 76 return ret; 75 77 }
+6 -2
net/ipv6/netfilter/ip6t_MASQUERADE.c
··· 58 58 int err; 59 59 60 60 err = xt_register_target(&masquerade_tg6_reg); 61 - if (err == 0) 62 - nf_nat_masquerade_ipv6_register_notifier(); 61 + if (err) 62 + return err; 63 + 64 + err = nf_nat_masquerade_ipv6_register_notifier(); 65 + if (err) 66 + xt_unregister_target(&masquerade_tg6_reg); 63 67 64 68 return err; 65 69 }
+23 -9
net/ipv6/netfilter/nf_nat_masquerade_ipv6.c
··· 132 132 * of ipv6 addresses being deleted), we also need to add an upper 133 133 * limit to the number of queued work items. 134 134 */ 135 - static int masq_inet_event(struct notifier_block *this, 136 - unsigned long event, void *ptr) 135 + static int masq_inet6_event(struct notifier_block *this, 136 + unsigned long event, void *ptr) 137 137 { 138 138 struct inet6_ifaddr *ifa = ptr; 139 139 const struct net_device *dev; ··· 171 171 return NOTIFY_DONE; 172 172 } 173 173 174 - static struct notifier_block masq_inet_notifier = { 175 - .notifier_call = masq_inet_event, 174 + static struct notifier_block masq_inet6_notifier = { 175 + .notifier_call = masq_inet6_event, 176 176 }; 177 177 178 178 static atomic_t masquerade_notifier_refcount = ATOMIC_INIT(0); 179 179 180 - void nf_nat_masquerade_ipv6_register_notifier(void) 180 + int nf_nat_masquerade_ipv6_register_notifier(void) 181 181 { 182 + int ret; 183 + 182 184 /* check if the notifier is already set */ 183 185 if (atomic_inc_return(&masquerade_notifier_refcount) > 1) 184 - return; 186 + return 0; 185 187 186 - register_netdevice_notifier(&masq_dev_notifier); 187 - register_inet6addr_notifier(&masq_inet_notifier); 188 + ret = register_netdevice_notifier(&masq_dev_notifier); 189 + if (ret) 190 + goto err_dec; 191 + 192 + ret = register_inet6addr_notifier(&masq_inet6_notifier); 193 + if (ret) 194 + goto err_unregister; 195 + 196 + return ret; 197 + err_unregister: 198 + unregister_netdevice_notifier(&masq_dev_notifier); 199 + err_dec: 200 + atomic_dec(&masquerade_notifier_refcount); 201 + return ret; 188 202 } 189 203 EXPORT_SYMBOL_GPL(nf_nat_masquerade_ipv6_register_notifier); 190 204 ··· 208 194 if (atomic_dec_return(&masquerade_notifier_refcount) > 0) 209 195 return; 210 196 211 - unregister_inet6addr_notifier(&masq_inet_notifier); 197 + unregister_inet6addr_notifier(&masq_inet6_notifier); 212 198 unregister_netdevice_notifier(&masq_dev_notifier); 213 199 } 214 200 EXPORT_SYMBOL_GPL(nf_nat_masquerade_ipv6_unregister_notifier);
+3 -1
net/ipv6/netfilter/nft_masq_ipv6.c
··· 70 70 if (ret < 0) 71 71 return ret; 72 72 73 - nf_nat_masquerade_ipv6_register_notifier(); 73 + ret = nf_nat_masquerade_ipv6_register_notifier(); 74 + if (ret) 75 + nft_unregister_expr(&nft_masq_ipv6_type); 74 76 75 77 return ret; 76 78 }
+4 -1
net/netfilter/nft_flow_offload.c
··· 214 214 { 215 215 int err; 216 216 217 - register_netdevice_notifier(&flow_offload_netdev_notifier); 217 + err = register_netdevice_notifier(&flow_offload_netdev_notifier); 218 + if (err) 219 + goto err; 218 220 219 221 err = nft_register_expr(&nft_flow_offload_type); 220 222 if (err < 0) ··· 226 224 227 225 register_expr: 228 226 unregister_netdevice_notifier(&flow_offload_netdev_notifier); 227 + err: 229 228 return err; 230 229 } 231 230