Skip to content

Commit fc11078

Browse files
committed
Merge git://git.kernel.org/pub/scm/linux/kernel/git/pablo/nf
Pablo Neira Ayuso says: ==================== Netfilter/IPVS fixes for net The following patchset contains Netfilter/IPVS fixes for net: 1) Fix crash on flowtable due to race between garbage collection and insertion. 2) Restore callback unbinding in netfilter offloads. 3) Fix races on IPVS module removal, from Davide Caratti. 4) Make old_secure_tcp per-netns to fix sysbot report, from Eric Dumazet. 5) Validate matching length in netfilter offloads, from wenxu. ==================== Signed-off-by: David S. Miller <[email protected]>
2 parents 1a51a47 + 52b33b4 commit fc11078

File tree

9 files changed

+77
-27
lines changed

9 files changed

+77
-27
lines changed

include/net/ip_vs.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -889,6 +889,7 @@ struct netns_ipvs {
889889
struct delayed_work defense_work; /* Work handler */
890890
int drop_rate;
891891
int drop_counter;
892+
int old_secure_tcp;
892893
atomic_t dropentry;
893894
/* locks in ctl.c */
894895
spinlock_t dropentry_lock; /* drop entry handling */

net/netfilter/ipvs/ip_vs_app.c

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -193,21 +193,29 @@ struct ip_vs_app *register_ip_vs_app(struct netns_ipvs *ipvs, struct ip_vs_app *
193193

194194
mutex_lock(&__ip_vs_app_mutex);
195195

196+
/* increase the module use count */
197+
if (!ip_vs_use_count_inc()) {
198+
err = -ENOENT;
199+
goto out_unlock;
200+
}
201+
196202
list_for_each_entry(a, &ipvs->app_list, a_list) {
197203
if (!strcmp(app->name, a->name)) {
198204
err = -EEXIST;
205+
/* decrease the module use count */
206+
ip_vs_use_count_dec();
199207
goto out_unlock;
200208
}
201209
}
202210
a = kmemdup(app, sizeof(*app), GFP_KERNEL);
203211
if (!a) {
204212
err = -ENOMEM;
213+
/* decrease the module use count */
214+
ip_vs_use_count_dec();
205215
goto out_unlock;
206216
}
207217
INIT_LIST_HEAD(&a->incs_list);
208218
list_add(&a->a_list, &ipvs->app_list);
209-
/* increase the module use count */
210-
ip_vs_use_count_inc();
211219

212220
out_unlock:
213221
mutex_unlock(&__ip_vs_app_mutex);

net/netfilter/ipvs/ip_vs_ctl.c

Lines changed: 11 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,6 @@ static bool __ip_vs_addr_is_local_v6(struct net *net,
9393
static void update_defense_level(struct netns_ipvs *ipvs)
9494
{
9595
struct sysinfo i;
96-
static int old_secure_tcp = 0;
9796
int availmem;
9897
int nomem;
9998
int to_change = -1;
@@ -174,35 +173,35 @@ static void update_defense_level(struct netns_ipvs *ipvs)
174173
spin_lock(&ipvs->securetcp_lock);
175174
switch (ipvs->sysctl_secure_tcp) {
176175
case 0:
177-
if (old_secure_tcp >= 2)
176+
if (ipvs->old_secure_tcp >= 2)
178177
to_change = 0;
179178
break;
180179
case 1:
181180
if (nomem) {
182-
if (old_secure_tcp < 2)
181+
if (ipvs->old_secure_tcp < 2)
183182
to_change = 1;
184183
ipvs->sysctl_secure_tcp = 2;
185184
} else {
186-
if (old_secure_tcp >= 2)
185+
if (ipvs->old_secure_tcp >= 2)
187186
to_change = 0;
188187
}
189188
break;
190189
case 2:
191190
if (nomem) {
192-
if (old_secure_tcp < 2)
191+
if (ipvs->old_secure_tcp < 2)
193192
to_change = 1;
194193
} else {
195-
if (old_secure_tcp >= 2)
194+
if (ipvs->old_secure_tcp >= 2)
196195
to_change = 0;
197196
ipvs->sysctl_secure_tcp = 1;
198197
}
199198
break;
200199
case 3:
201-
if (old_secure_tcp < 2)
200+
if (ipvs->old_secure_tcp < 2)
202201
to_change = 1;
203202
break;
204203
}
205-
old_secure_tcp = ipvs->sysctl_secure_tcp;
204+
ipvs->old_secure_tcp = ipvs->sysctl_secure_tcp;
206205
if (to_change >= 0)
207206
ip_vs_protocol_timeout_change(ipvs,
208207
ipvs->sysctl_secure_tcp > 1);
@@ -1275,7 +1274,8 @@ ip_vs_add_service(struct netns_ipvs *ipvs, struct ip_vs_service_user_kern *u,
12751274
struct ip_vs_service *svc = NULL;
12761275

12771276
/* increase the module use count */
1278-
ip_vs_use_count_inc();
1277+
if (!ip_vs_use_count_inc())
1278+
return -ENOPROTOOPT;
12791279

12801280
/* Lookup the scheduler by 'u->sched_name' */
12811281
if (strcmp(u->sched_name, "none")) {
@@ -2435,9 +2435,6 @@ do_ip_vs_set_ctl(struct sock *sk, int cmd, void __user *user, unsigned int len)
24352435
if (copy_from_user(arg, user, len) != 0)
24362436
return -EFAULT;
24372437

2438-
/* increase the module use count */
2439-
ip_vs_use_count_inc();
2440-
24412438
/* Handle daemons since they have another lock */
24422439
if (cmd == IP_VS_SO_SET_STARTDAEMON ||
24432440
cmd == IP_VS_SO_SET_STOPDAEMON) {
@@ -2450,13 +2447,13 @@ do_ip_vs_set_ctl(struct sock *sk, int cmd, void __user *user, unsigned int len)
24502447
ret = -EINVAL;
24512448
if (strscpy(cfg.mcast_ifn, dm->mcast_ifn,
24522449
sizeof(cfg.mcast_ifn)) <= 0)
2453-
goto out_dec;
2450+
return ret;
24542451
cfg.syncid = dm->syncid;
24552452
ret = start_sync_thread(ipvs, &cfg, dm->state);
24562453
} else {
24572454
ret = stop_sync_thread(ipvs, dm->state);
24582455
}
2459-
goto out_dec;
2456+
return ret;
24602457
}
24612458

24622459
mutex_lock(&__ip_vs_mutex);
@@ -2551,10 +2548,6 @@ do_ip_vs_set_ctl(struct sock *sk, int cmd, void __user *user, unsigned int len)
25512548

25522549
out_unlock:
25532550
mutex_unlock(&__ip_vs_mutex);
2554-
out_dec:
2555-
/* decrease the module use count */
2556-
ip_vs_use_count_dec();
2557-
25582551
return ret;
25592552
}
25602553

net/netfilter/ipvs/ip_vs_pe.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,8 @@ int register_ip_vs_pe(struct ip_vs_pe *pe)
6868
struct ip_vs_pe *tmp;
6969

7070
/* increase the module use count */
71-
ip_vs_use_count_inc();
71+
if (!ip_vs_use_count_inc())
72+
return -ENOENT;
7273

7374
mutex_lock(&ip_vs_pe_mutex);
7475
/* Make sure that the pe with this name doesn't exist

net/netfilter/ipvs/ip_vs_sched.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -179,7 +179,8 @@ int register_ip_vs_scheduler(struct ip_vs_scheduler *scheduler)
179179
}
180180

181181
/* increase the module use count */
182-
ip_vs_use_count_inc();
182+
if (!ip_vs_use_count_inc())
183+
return -ENOENT;
183184

184185
mutex_lock(&ip_vs_sched_mutex);
185186

net/netfilter/ipvs/ip_vs_sync.c

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1762,6 +1762,10 @@ int start_sync_thread(struct netns_ipvs *ipvs, struct ipvs_sync_daemon_cfg *c,
17621762
IP_VS_DBG(7, "Each ip_vs_sync_conn entry needs %zd bytes\n",
17631763
sizeof(struct ip_vs_sync_conn_v0));
17641764

1765+
/* increase the module use count */
1766+
if (!ip_vs_use_count_inc())
1767+
return -ENOPROTOOPT;
1768+
17651769
/* Do not hold one mutex and then to block on another */
17661770
for (;;) {
17671771
rtnl_lock();
@@ -1892,9 +1896,6 @@ int start_sync_thread(struct netns_ipvs *ipvs, struct ipvs_sync_daemon_cfg *c,
18921896
mutex_unlock(&ipvs->sync_mutex);
18931897
rtnl_unlock();
18941898

1895-
/* increase the module use count */
1896-
ip_vs_use_count_inc();
1897-
18981899
return 0;
18991900

19001901
out:
@@ -1924,11 +1925,17 @@ int start_sync_thread(struct netns_ipvs *ipvs, struct ipvs_sync_daemon_cfg *c,
19241925
}
19251926
kfree(ti);
19261927
}
1928+
1929+
/* decrease the module use count */
1930+
ip_vs_use_count_dec();
19271931
return result;
19281932

19291933
out_early:
19301934
mutex_unlock(&ipvs->sync_mutex);
19311935
rtnl_unlock();
1936+
1937+
/* decrease the module use count */
1938+
ip_vs_use_count_dec();
19321939
return result;
19331940
}
19341941

net/netfilter/nf_flow_table_core.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -202,6 +202,8 @@ int flow_offload_add(struct nf_flowtable *flow_table, struct flow_offload *flow)
202202
{
203203
int err;
204204

205+
flow->timeout = (u32)jiffies + NF_FLOW_TIMEOUT;
206+
205207
err = rhashtable_insert_fast(&flow_table->rhashtable,
206208
&flow->tuplehash[0].node,
207209
nf_flow_offload_rhash_params);
@@ -218,7 +220,6 @@ int flow_offload_add(struct nf_flowtable *flow_table, struct flow_offload *flow)
218220
return err;
219221
}
220222

221-
flow->timeout = (u32)jiffies + NF_FLOW_TIMEOUT;
222223
return 0;
223224
}
224225
EXPORT_SYMBOL_GPL(flow_offload_add);

net/netfilter/nf_tables_offload.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -347,7 +347,7 @@ int nft_flow_rule_offload_commit(struct net *net)
347347

348348
policy = nft_trans_chain_policy(trans);
349349
err = nft_flow_offload_chain(trans->ctx.chain, &policy,
350-
FLOW_BLOCK_BIND);
350+
FLOW_BLOCK_UNBIND);
351351
break;
352352
case NFT_MSG_NEWRULE:
353353
if (!(trans->ctx.chain->flags & NFT_CHAIN_HW_OFFLOAD))

net/netfilter/nft_payload.c

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -161,13 +161,21 @@ static int nft_payload_offload_ll(struct nft_offload_ctx *ctx,
161161

162162
switch (priv->offset) {
163163
case offsetof(struct ethhdr, h_source):
164+
if (priv->len != ETH_ALEN)
165+
return -EOPNOTSUPP;
166+
164167
NFT_OFFLOAD_MATCH(FLOW_DISSECTOR_KEY_ETH_ADDRS, eth_addrs,
165168
src, ETH_ALEN, reg);
166169
break;
167170
case offsetof(struct ethhdr, h_dest):
171+
if (priv->len != ETH_ALEN)
172+
return -EOPNOTSUPP;
173+
168174
NFT_OFFLOAD_MATCH(FLOW_DISSECTOR_KEY_ETH_ADDRS, eth_addrs,
169175
dst, ETH_ALEN, reg);
170176
break;
177+
default:
178+
return -EOPNOTSUPP;
171179
}
172180

173181
return 0;
@@ -181,14 +189,23 @@ static int nft_payload_offload_ip(struct nft_offload_ctx *ctx,
181189

182190
switch (priv->offset) {
183191
case offsetof(struct iphdr, saddr):
192+
if (priv->len != sizeof(struct in_addr))
193+
return -EOPNOTSUPP;
194+
184195
NFT_OFFLOAD_MATCH(FLOW_DISSECTOR_KEY_IPV4_ADDRS, ipv4, src,
185196
sizeof(struct in_addr), reg);
186197
break;
187198
case offsetof(struct iphdr, daddr):
199+
if (priv->len != sizeof(struct in_addr))
200+
return -EOPNOTSUPP;
201+
188202
NFT_OFFLOAD_MATCH(FLOW_DISSECTOR_KEY_IPV4_ADDRS, ipv4, dst,
189203
sizeof(struct in_addr), reg);
190204
break;
191205
case offsetof(struct iphdr, protocol):
206+
if (priv->len != sizeof(__u8))
207+
return -EOPNOTSUPP;
208+
192209
NFT_OFFLOAD_MATCH(FLOW_DISSECTOR_KEY_BASIC, basic, ip_proto,
193210
sizeof(__u8), reg);
194211
nft_offload_set_dependency(ctx, NFT_OFFLOAD_DEP_TRANSPORT);
@@ -208,14 +225,23 @@ static int nft_payload_offload_ip6(struct nft_offload_ctx *ctx,
208225

209226
switch (priv->offset) {
210227
case offsetof(struct ipv6hdr, saddr):
228+
if (priv->len != sizeof(struct in6_addr))
229+
return -EOPNOTSUPP;
230+
211231
NFT_OFFLOAD_MATCH(FLOW_DISSECTOR_KEY_IPV6_ADDRS, ipv6, src,
212232
sizeof(struct in6_addr), reg);
213233
break;
214234
case offsetof(struct ipv6hdr, daddr):
235+
if (priv->len != sizeof(struct in6_addr))
236+
return -EOPNOTSUPP;
237+
215238
NFT_OFFLOAD_MATCH(FLOW_DISSECTOR_KEY_IPV6_ADDRS, ipv6, dst,
216239
sizeof(struct in6_addr), reg);
217240
break;
218241
case offsetof(struct ipv6hdr, nexthdr):
242+
if (priv->len != sizeof(__u8))
243+
return -EOPNOTSUPP;
244+
219245
NFT_OFFLOAD_MATCH(FLOW_DISSECTOR_KEY_BASIC, basic, ip_proto,
220246
sizeof(__u8), reg);
221247
nft_offload_set_dependency(ctx, NFT_OFFLOAD_DEP_TRANSPORT);
@@ -255,10 +281,16 @@ static int nft_payload_offload_tcp(struct nft_offload_ctx *ctx,
255281

256282
switch (priv->offset) {
257283
case offsetof(struct tcphdr, source):
284+
if (priv->len != sizeof(__be16))
285+
return -EOPNOTSUPP;
286+
258287
NFT_OFFLOAD_MATCH(FLOW_DISSECTOR_KEY_PORTS, tp, src,
259288
sizeof(__be16), reg);
260289
break;
261290
case offsetof(struct tcphdr, dest):
291+
if (priv->len != sizeof(__be16))
292+
return -EOPNOTSUPP;
293+
262294
NFT_OFFLOAD_MATCH(FLOW_DISSECTOR_KEY_PORTS, tp, dst,
263295
sizeof(__be16), reg);
264296
break;
@@ -277,10 +309,16 @@ static int nft_payload_offload_udp(struct nft_offload_ctx *ctx,
277309

278310
switch (priv->offset) {
279311
case offsetof(struct udphdr, source):
312+
if (priv->len != sizeof(__be16))
313+
return -EOPNOTSUPP;
314+
280315
NFT_OFFLOAD_MATCH(FLOW_DISSECTOR_KEY_PORTS, tp, src,
281316
sizeof(__be16), reg);
282317
break;
283318
case offsetof(struct udphdr, dest):
319+
if (priv->len != sizeof(__be16))
320+
return -EOPNOTSUPP;
321+
284322
NFT_OFFLOAD_MATCH(FLOW_DISSECTOR_KEY_PORTS, tp, dst,
285323
sizeof(__be16), reg);
286324
break;

0 commit comments

Comments
 (0)