aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2019-10-27 15:13:16 -0400
committerDavid S. Miller <davem@davemloft.net>2019-10-27 15:13:16 -0400
commitfc11078dd3514c65eabce166b8431a56d8a667cb (patch)
tree2278a2e0137a0165b3684338a21a0ab3d38e751f
parent1a51a47491a5a23f0625b03ad6dc84cf39bf6a82 (diff)
parent52b33b4f8186669ab88b56cf5b2812e3996ef289 (diff)
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 <davem@davemloft.net>
-rw-r--r--include/net/ip_vs.h1
-rw-r--r--net/netfilter/ipvs/ip_vs_app.c12
-rw-r--r--net/netfilter/ipvs/ip_vs_ctl.c29
-rw-r--r--net/netfilter/ipvs/ip_vs_pe.c3
-rw-r--r--net/netfilter/ipvs/ip_vs_sched.c3
-rw-r--r--net/netfilter/ipvs/ip_vs_sync.c13
-rw-r--r--net/netfilter/nf_flow_table_core.c3
-rw-r--r--net/netfilter/nf_tables_offload.c2
-rw-r--r--net/netfilter/nft_payload.c38
9 files changed, 77 insertions, 27 deletions
diff --git a/include/net/ip_vs.h b/include/net/ip_vs.h
index 3759167f91f5..078887c8c586 100644
--- a/include/net/ip_vs.h
+++ b/include/net/ip_vs.h
@@ -889,6 +889,7 @@ struct netns_ipvs {
889 struct delayed_work defense_work; /* Work handler */ 889 struct delayed_work defense_work; /* Work handler */
890 int drop_rate; 890 int drop_rate;
891 int drop_counter; 891 int drop_counter;
892 int old_secure_tcp;
892 atomic_t dropentry; 893 atomic_t dropentry;
893 /* locks in ctl.c */ 894 /* locks in ctl.c */
894 spinlock_t dropentry_lock; /* drop entry handling */ 895 spinlock_t dropentry_lock; /* drop entry handling */
diff --git a/net/netfilter/ipvs/ip_vs_app.c b/net/netfilter/ipvs/ip_vs_app.c
index 4515056ef1c2..f9b16f2b2219 100644
--- a/net/netfilter/ipvs/ip_vs_app.c
+++ b/net/netfilter/ipvs/ip_vs_app.c
@@ -193,21 +193,29 @@ struct ip_vs_app *register_ip_vs_app(struct netns_ipvs *ipvs, struct ip_vs_app *
193 193
194 mutex_lock(&__ip_vs_app_mutex); 194 mutex_lock(&__ip_vs_app_mutex);
195 195
196 /* increase the module use count */
197 if (!ip_vs_use_count_inc()) {
198 err = -ENOENT;
199 goto out_unlock;
200 }
201
196 list_for_each_entry(a, &ipvs->app_list, a_list) { 202 list_for_each_entry(a, &ipvs->app_list, a_list) {
197 if (!strcmp(app->name, a->name)) { 203 if (!strcmp(app->name, a->name)) {
198 err = -EEXIST; 204 err = -EEXIST;
205 /* decrease the module use count */
206 ip_vs_use_count_dec();
199 goto out_unlock; 207 goto out_unlock;
200 } 208 }
201 } 209 }
202 a = kmemdup(app, sizeof(*app), GFP_KERNEL); 210 a = kmemdup(app, sizeof(*app), GFP_KERNEL);
203 if (!a) { 211 if (!a) {
204 err = -ENOMEM; 212 err = -ENOMEM;
213 /* decrease the module use count */
214 ip_vs_use_count_dec();
205 goto out_unlock; 215 goto out_unlock;
206 } 216 }
207 INIT_LIST_HEAD(&a->incs_list); 217 INIT_LIST_HEAD(&a->incs_list);
208 list_add(&a->a_list, &ipvs->app_list); 218 list_add(&a->a_list, &ipvs->app_list);
209 /* increase the module use count */
210 ip_vs_use_count_inc();
211 219
212out_unlock: 220out_unlock:
213 mutex_unlock(&__ip_vs_app_mutex); 221 mutex_unlock(&__ip_vs_app_mutex);
diff --git a/net/netfilter/ipvs/ip_vs_ctl.c b/net/netfilter/ipvs/ip_vs_ctl.c
index 8b48e7ce1c2c..3cccc88ef817 100644
--- a/net/netfilter/ipvs/ip_vs_ctl.c
+++ b/net/netfilter/ipvs/ip_vs_ctl.c
@@ -93,7 +93,6 @@ static bool __ip_vs_addr_is_local_v6(struct net *net,
93static void update_defense_level(struct netns_ipvs *ipvs) 93static void update_defense_level(struct netns_ipvs *ipvs)
94{ 94{
95 struct sysinfo i; 95 struct sysinfo i;
96 static int old_secure_tcp = 0;
97 int availmem; 96 int availmem;
98 int nomem; 97 int nomem;
99 int to_change = -1; 98 int to_change = -1;
@@ -174,35 +173,35 @@ static void update_defense_level(struct netns_ipvs *ipvs)
174 spin_lock(&ipvs->securetcp_lock); 173 spin_lock(&ipvs->securetcp_lock);
175 switch (ipvs->sysctl_secure_tcp) { 174 switch (ipvs->sysctl_secure_tcp) {
176 case 0: 175 case 0:
177 if (old_secure_tcp >= 2) 176 if (ipvs->old_secure_tcp >= 2)
178 to_change = 0; 177 to_change = 0;
179 break; 178 break;
180 case 1: 179 case 1:
181 if (nomem) { 180 if (nomem) {
182 if (old_secure_tcp < 2) 181 if (ipvs->old_secure_tcp < 2)
183 to_change = 1; 182 to_change = 1;
184 ipvs->sysctl_secure_tcp = 2; 183 ipvs->sysctl_secure_tcp = 2;
185 } else { 184 } else {
186 if (old_secure_tcp >= 2) 185 if (ipvs->old_secure_tcp >= 2)
187 to_change = 0; 186 to_change = 0;
188 } 187 }
189 break; 188 break;
190 case 2: 189 case 2:
191 if (nomem) { 190 if (nomem) {
192 if (old_secure_tcp < 2) 191 if (ipvs->old_secure_tcp < 2)
193 to_change = 1; 192 to_change = 1;
194 } else { 193 } else {
195 if (old_secure_tcp >= 2) 194 if (ipvs->old_secure_tcp >= 2)
196 to_change = 0; 195 to_change = 0;
197 ipvs->sysctl_secure_tcp = 1; 196 ipvs->sysctl_secure_tcp = 1;
198 } 197 }
199 break; 198 break;
200 case 3: 199 case 3:
201 if (old_secure_tcp < 2) 200 if (ipvs->old_secure_tcp < 2)
202 to_change = 1; 201 to_change = 1;
203 break; 202 break;
204 } 203 }
205 old_secure_tcp = ipvs->sysctl_secure_tcp; 204 ipvs->old_secure_tcp = ipvs->sysctl_secure_tcp;
206 if (to_change >= 0) 205 if (to_change >= 0)
207 ip_vs_protocol_timeout_change(ipvs, 206 ip_vs_protocol_timeout_change(ipvs,
208 ipvs->sysctl_secure_tcp > 1); 207 ipvs->sysctl_secure_tcp > 1);
@@ -1275,7 +1274,8 @@ ip_vs_add_service(struct netns_ipvs *ipvs, struct ip_vs_service_user_kern *u,
1275 struct ip_vs_service *svc = NULL; 1274 struct ip_vs_service *svc = NULL;
1276 1275
1277 /* increase the module use count */ 1276 /* increase the module use count */
1278 ip_vs_use_count_inc(); 1277 if (!ip_vs_use_count_inc())
1278 return -ENOPROTOOPT;
1279 1279
1280 /* Lookup the scheduler by 'u->sched_name' */ 1280 /* Lookup the scheduler by 'u->sched_name' */
1281 if (strcmp(u->sched_name, "none")) { 1281 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)
2435 if (copy_from_user(arg, user, len) != 0) 2435 if (copy_from_user(arg, user, len) != 0)
2436 return -EFAULT; 2436 return -EFAULT;
2437 2437
2438 /* increase the module use count */
2439 ip_vs_use_count_inc();
2440
2441 /* Handle daemons since they have another lock */ 2438 /* Handle daemons since they have another lock */
2442 if (cmd == IP_VS_SO_SET_STARTDAEMON || 2439 if (cmd == IP_VS_SO_SET_STARTDAEMON ||
2443 cmd == IP_VS_SO_SET_STOPDAEMON) { 2440 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)
2450 ret = -EINVAL; 2447 ret = -EINVAL;
2451 if (strscpy(cfg.mcast_ifn, dm->mcast_ifn, 2448 if (strscpy(cfg.mcast_ifn, dm->mcast_ifn,
2452 sizeof(cfg.mcast_ifn)) <= 0) 2449 sizeof(cfg.mcast_ifn)) <= 0)
2453 goto out_dec; 2450 return ret;
2454 cfg.syncid = dm->syncid; 2451 cfg.syncid = dm->syncid;
2455 ret = start_sync_thread(ipvs, &cfg, dm->state); 2452 ret = start_sync_thread(ipvs, &cfg, dm->state);
2456 } else { 2453 } else {
2457 ret = stop_sync_thread(ipvs, dm->state); 2454 ret = stop_sync_thread(ipvs, dm->state);
2458 } 2455 }
2459 goto out_dec; 2456 return ret;
2460 } 2457 }
2461 2458
2462 mutex_lock(&__ip_vs_mutex); 2459 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)
2551 2548
2552 out_unlock: 2549 out_unlock:
2553 mutex_unlock(&__ip_vs_mutex); 2550 mutex_unlock(&__ip_vs_mutex);
2554 out_dec:
2555 /* decrease the module use count */
2556 ip_vs_use_count_dec();
2557
2558 return ret; 2551 return ret;
2559} 2552}
2560 2553
diff --git a/net/netfilter/ipvs/ip_vs_pe.c b/net/netfilter/ipvs/ip_vs_pe.c
index 8e104dff7abc..166c669f0763 100644
--- a/net/netfilter/ipvs/ip_vs_pe.c
+++ b/net/netfilter/ipvs/ip_vs_pe.c
@@ -68,7 +68,8 @@ int register_ip_vs_pe(struct ip_vs_pe *pe)
68 struct ip_vs_pe *tmp; 68 struct ip_vs_pe *tmp;
69 69
70 /* increase the module use count */ 70 /* increase the module use count */
71 ip_vs_use_count_inc(); 71 if (!ip_vs_use_count_inc())
72 return -ENOENT;
72 73
73 mutex_lock(&ip_vs_pe_mutex); 74 mutex_lock(&ip_vs_pe_mutex);
74 /* Make sure that the pe with this name doesn't exist 75 /* Make sure that the pe with this name doesn't exist
diff --git a/net/netfilter/ipvs/ip_vs_sched.c b/net/netfilter/ipvs/ip_vs_sched.c
index 2f9d5cd5daee..d4903723be7e 100644
--- a/net/netfilter/ipvs/ip_vs_sched.c
+++ b/net/netfilter/ipvs/ip_vs_sched.c
@@ -179,7 +179,8 @@ int register_ip_vs_scheduler(struct ip_vs_scheduler *scheduler)
179 } 179 }
180 180
181 /* increase the module use count */ 181 /* increase the module use count */
182 ip_vs_use_count_inc(); 182 if (!ip_vs_use_count_inc())
183 return -ENOENT;
183 184
184 mutex_lock(&ip_vs_sched_mutex); 185 mutex_lock(&ip_vs_sched_mutex);
185 186
diff --git a/net/netfilter/ipvs/ip_vs_sync.c b/net/netfilter/ipvs/ip_vs_sync.c
index a4a78c4b06de..8dc892a9dc91 100644
--- a/net/netfilter/ipvs/ip_vs_sync.c
+++ b/net/netfilter/ipvs/ip_vs_sync.c
@@ -1762,6 +1762,10 @@ int start_sync_thread(struct netns_ipvs *ipvs, struct ipvs_sync_daemon_cfg *c,
1762 IP_VS_DBG(7, "Each ip_vs_sync_conn entry needs %zd bytes\n", 1762 IP_VS_DBG(7, "Each ip_vs_sync_conn entry needs %zd bytes\n",
1763 sizeof(struct ip_vs_sync_conn_v0)); 1763 sizeof(struct ip_vs_sync_conn_v0));
1764 1764
1765 /* increase the module use count */
1766 if (!ip_vs_use_count_inc())
1767 return -ENOPROTOOPT;
1768
1765 /* Do not hold one mutex and then to block on another */ 1769 /* Do not hold one mutex and then to block on another */
1766 for (;;) { 1770 for (;;) {
1767 rtnl_lock(); 1771 rtnl_lock();
@@ -1892,9 +1896,6 @@ int start_sync_thread(struct netns_ipvs *ipvs, struct ipvs_sync_daemon_cfg *c,
1892 mutex_unlock(&ipvs->sync_mutex); 1896 mutex_unlock(&ipvs->sync_mutex);
1893 rtnl_unlock(); 1897 rtnl_unlock();
1894 1898
1895 /* increase the module use count */
1896 ip_vs_use_count_inc();
1897
1898 return 0; 1899 return 0;
1899 1900
1900out: 1901out:
@@ -1924,11 +1925,17 @@ out:
1924 } 1925 }
1925 kfree(ti); 1926 kfree(ti);
1926 } 1927 }
1928
1929 /* decrease the module use count */
1930 ip_vs_use_count_dec();
1927 return result; 1931 return result;
1928 1932
1929out_early: 1933out_early:
1930 mutex_unlock(&ipvs->sync_mutex); 1934 mutex_unlock(&ipvs->sync_mutex);
1931 rtnl_unlock(); 1935 rtnl_unlock();
1936
1937 /* decrease the module use count */
1938 ip_vs_use_count_dec();
1932 return result; 1939 return result;
1933} 1940}
1934 1941
diff --git a/net/netfilter/nf_flow_table_core.c b/net/netfilter/nf_flow_table_core.c
index 132f5228b431..128245efe84a 100644
--- a/net/netfilter/nf_flow_table_core.c
+++ b/net/netfilter/nf_flow_table_core.c
@@ -202,6 +202,8 @@ int flow_offload_add(struct nf_flowtable *flow_table, struct flow_offload *flow)
202{ 202{
203 int err; 203 int err;
204 204
205 flow->timeout = (u32)jiffies + NF_FLOW_TIMEOUT;
206
205 err = rhashtable_insert_fast(&flow_table->rhashtable, 207 err = rhashtable_insert_fast(&flow_table->rhashtable,
206 &flow->tuplehash[0].node, 208 &flow->tuplehash[0].node,
207 nf_flow_offload_rhash_params); 209 nf_flow_offload_rhash_params);
@@ -218,7 +220,6 @@ int flow_offload_add(struct nf_flowtable *flow_table, struct flow_offload *flow)
218 return err; 220 return err;
219 } 221 }
220 222
221 flow->timeout = (u32)jiffies + NF_FLOW_TIMEOUT;
222 return 0; 223 return 0;
223} 224}
224EXPORT_SYMBOL_GPL(flow_offload_add); 225EXPORT_SYMBOL_GPL(flow_offload_add);
diff --git a/net/netfilter/nf_tables_offload.c b/net/netfilter/nf_tables_offload.c
index e546f759b7a7..ad783f4840ef 100644
--- a/net/netfilter/nf_tables_offload.c
+++ b/net/netfilter/nf_tables_offload.c
@@ -347,7 +347,7 @@ int nft_flow_rule_offload_commit(struct net *net)
347 347
348 policy = nft_trans_chain_policy(trans); 348 policy = nft_trans_chain_policy(trans);
349 err = nft_flow_offload_chain(trans->ctx.chain, &policy, 349 err = nft_flow_offload_chain(trans->ctx.chain, &policy,
350 FLOW_BLOCK_BIND); 350 FLOW_BLOCK_UNBIND);
351 break; 351 break;
352 case NFT_MSG_NEWRULE: 352 case NFT_MSG_NEWRULE:
353 if (!(trans->ctx.chain->flags & NFT_CHAIN_HW_OFFLOAD)) 353 if (!(trans->ctx.chain->flags & NFT_CHAIN_HW_OFFLOAD))
diff --git a/net/netfilter/nft_payload.c b/net/netfilter/nft_payload.c
index 22a80eb60222..5cb2d8908d2a 100644
--- a/net/netfilter/nft_payload.c
+++ b/net/netfilter/nft_payload.c
@@ -161,13 +161,21 @@ static int nft_payload_offload_ll(struct nft_offload_ctx *ctx,
161 161
162 switch (priv->offset) { 162 switch (priv->offset) {
163 case offsetof(struct ethhdr, h_source): 163 case offsetof(struct ethhdr, h_source):
164 if (priv->len != ETH_ALEN)
165 return -EOPNOTSUPP;
166
164 NFT_OFFLOAD_MATCH(FLOW_DISSECTOR_KEY_ETH_ADDRS, eth_addrs, 167 NFT_OFFLOAD_MATCH(FLOW_DISSECTOR_KEY_ETH_ADDRS, eth_addrs,
165 src, ETH_ALEN, reg); 168 src, ETH_ALEN, reg);
166 break; 169 break;
167 case offsetof(struct ethhdr, h_dest): 170 case offsetof(struct ethhdr, h_dest):
171 if (priv->len != ETH_ALEN)
172 return -EOPNOTSUPP;
173
168 NFT_OFFLOAD_MATCH(FLOW_DISSECTOR_KEY_ETH_ADDRS, eth_addrs, 174 NFT_OFFLOAD_MATCH(FLOW_DISSECTOR_KEY_ETH_ADDRS, eth_addrs,
169 dst, ETH_ALEN, reg); 175 dst, ETH_ALEN, reg);
170 break; 176 break;
177 default:
178 return -EOPNOTSUPP;
171 } 179 }
172 180
173 return 0; 181 return 0;
@@ -181,14 +189,23 @@ static int nft_payload_offload_ip(struct nft_offload_ctx *ctx,
181 189
182 switch (priv->offset) { 190 switch (priv->offset) {
183 case offsetof(struct iphdr, saddr): 191 case offsetof(struct iphdr, saddr):
192 if (priv->len != sizeof(struct in_addr))
193 return -EOPNOTSUPP;
194
184 NFT_OFFLOAD_MATCH(FLOW_DISSECTOR_KEY_IPV4_ADDRS, ipv4, src, 195 NFT_OFFLOAD_MATCH(FLOW_DISSECTOR_KEY_IPV4_ADDRS, ipv4, src,
185 sizeof(struct in_addr), reg); 196 sizeof(struct in_addr), reg);
186 break; 197 break;
187 case offsetof(struct iphdr, daddr): 198 case offsetof(struct iphdr, daddr):
199 if (priv->len != sizeof(struct in_addr))
200 return -EOPNOTSUPP;
201
188 NFT_OFFLOAD_MATCH(FLOW_DISSECTOR_KEY_IPV4_ADDRS, ipv4, dst, 202 NFT_OFFLOAD_MATCH(FLOW_DISSECTOR_KEY_IPV4_ADDRS, ipv4, dst,
189 sizeof(struct in_addr), reg); 203 sizeof(struct in_addr), reg);
190 break; 204 break;
191 case offsetof(struct iphdr, protocol): 205 case offsetof(struct iphdr, protocol):
206 if (priv->len != sizeof(__u8))
207 return -EOPNOTSUPP;
208
192 NFT_OFFLOAD_MATCH(FLOW_DISSECTOR_KEY_BASIC, basic, ip_proto, 209 NFT_OFFLOAD_MATCH(FLOW_DISSECTOR_KEY_BASIC, basic, ip_proto,
193 sizeof(__u8), reg); 210 sizeof(__u8), reg);
194 nft_offload_set_dependency(ctx, NFT_OFFLOAD_DEP_TRANSPORT); 211 nft_offload_set_dependency(ctx, NFT_OFFLOAD_DEP_TRANSPORT);
@@ -208,14 +225,23 @@ static int nft_payload_offload_ip6(struct nft_offload_ctx *ctx,
208 225
209 switch (priv->offset) { 226 switch (priv->offset) {
210 case offsetof(struct ipv6hdr, saddr): 227 case offsetof(struct ipv6hdr, saddr):
228 if (priv->len != sizeof(struct in6_addr))
229 return -EOPNOTSUPP;
230
211 NFT_OFFLOAD_MATCH(FLOW_DISSECTOR_KEY_IPV6_ADDRS, ipv6, src, 231 NFT_OFFLOAD_MATCH(FLOW_DISSECTOR_KEY_IPV6_ADDRS, ipv6, src,
212 sizeof(struct in6_addr), reg); 232 sizeof(struct in6_addr), reg);
213 break; 233 break;
214 case offsetof(struct ipv6hdr, daddr): 234 case offsetof(struct ipv6hdr, daddr):
235 if (priv->len != sizeof(struct in6_addr))
236 return -EOPNOTSUPP;
237
215 NFT_OFFLOAD_MATCH(FLOW_DISSECTOR_KEY_IPV6_ADDRS, ipv6, dst, 238 NFT_OFFLOAD_MATCH(FLOW_DISSECTOR_KEY_IPV6_ADDRS, ipv6, dst,
216 sizeof(struct in6_addr), reg); 239 sizeof(struct in6_addr), reg);
217 break; 240 break;
218 case offsetof(struct ipv6hdr, nexthdr): 241 case offsetof(struct ipv6hdr, nexthdr):
242 if (priv->len != sizeof(__u8))
243 return -EOPNOTSUPP;
244
219 NFT_OFFLOAD_MATCH(FLOW_DISSECTOR_KEY_BASIC, basic, ip_proto, 245 NFT_OFFLOAD_MATCH(FLOW_DISSECTOR_KEY_BASIC, basic, ip_proto,
220 sizeof(__u8), reg); 246 sizeof(__u8), reg);
221 nft_offload_set_dependency(ctx, NFT_OFFLOAD_DEP_TRANSPORT); 247 nft_offload_set_dependency(ctx, NFT_OFFLOAD_DEP_TRANSPORT);
@@ -255,10 +281,16 @@ static int nft_payload_offload_tcp(struct nft_offload_ctx *ctx,
255 281
256 switch (priv->offset) { 282 switch (priv->offset) {
257 case offsetof(struct tcphdr, source): 283 case offsetof(struct tcphdr, source):
284 if (priv->len != sizeof(__be16))
285 return -EOPNOTSUPP;
286
258 NFT_OFFLOAD_MATCH(FLOW_DISSECTOR_KEY_PORTS, tp, src, 287 NFT_OFFLOAD_MATCH(FLOW_DISSECTOR_KEY_PORTS, tp, src,
259 sizeof(__be16), reg); 288 sizeof(__be16), reg);
260 break; 289 break;
261 case offsetof(struct tcphdr, dest): 290 case offsetof(struct tcphdr, dest):
291 if (priv->len != sizeof(__be16))
292 return -EOPNOTSUPP;
293
262 NFT_OFFLOAD_MATCH(FLOW_DISSECTOR_KEY_PORTS, tp, dst, 294 NFT_OFFLOAD_MATCH(FLOW_DISSECTOR_KEY_PORTS, tp, dst,
263 sizeof(__be16), reg); 295 sizeof(__be16), reg);
264 break; 296 break;
@@ -277,10 +309,16 @@ static int nft_payload_offload_udp(struct nft_offload_ctx *ctx,
277 309
278 switch (priv->offset) { 310 switch (priv->offset) {
279 case offsetof(struct udphdr, source): 311 case offsetof(struct udphdr, source):
312 if (priv->len != sizeof(__be16))
313 return -EOPNOTSUPP;
314
280 NFT_OFFLOAD_MATCH(FLOW_DISSECTOR_KEY_PORTS, tp, src, 315 NFT_OFFLOAD_MATCH(FLOW_DISSECTOR_KEY_PORTS, tp, src,
281 sizeof(__be16), reg); 316 sizeof(__be16), reg);
282 break; 317 break;
283 case offsetof(struct udphdr, dest): 318 case offsetof(struct udphdr, dest):
319 if (priv->len != sizeof(__be16))
320 return -EOPNOTSUPP;
321
284 NFT_OFFLOAD_MATCH(FLOW_DISSECTOR_KEY_PORTS, tp, dst, 322 NFT_OFFLOAD_MATCH(FLOW_DISSECTOR_KEY_PORTS, tp, dst,
285 sizeof(__be16), reg); 323 sizeof(__be16), reg);
286 break; 324 break;