Patch Detail
get:
Show a patch.
patch:
Update a patch.
put:
Update a patch.
GET /api/patches/2216568/?format=api
{ "id": 2216568, "url": "http://patchwork.ozlabs.org/api/patches/2216568/?format=api", "web_url": "http://patchwork.ozlabs.org/project/netfilter-devel/patch/20260326200935.729750-1-pablo@netfilter.org/", "project": { "id": 26, "url": "http://patchwork.ozlabs.org/api/projects/26/?format=api", "name": "Netfilter Development", "link_name": "netfilter-devel", "list_id": "netfilter-devel.vger.kernel.org", "list_email": "netfilter-devel@vger.kernel.org", "web_url": null, "scm_url": null, "webscm_url": null, "list_archive_url": "", "list_archive_url_format": "", "commit_url_format": "" }, "msgid": "<20260326200935.729750-1-pablo@netfilter.org>", "list_archive_url": null, "date": "2026-03-26T20:09:35", "name": "[nf] netfilter: flowtable: strictly check for maximum number of actions", "commit_ref": null, "pull_url": null, "state": "not-applicable", "archived": false, "hash": "58f4930731ec8e17f23928e0a7a7c828f2808a8e", "submitter": { "id": 1315, "url": "http://patchwork.ozlabs.org/api/people/1315/?format=api", "name": "Pablo Neira Ayuso", "email": "pablo@netfilter.org" }, "delegate": null, "mbox": "http://patchwork.ozlabs.org/project/netfilter-devel/patch/20260326200935.729750-1-pablo@netfilter.org/mbox/", "series": [ { "id": 497644, "url": "http://patchwork.ozlabs.org/api/series/497644/?format=api", "web_url": "http://patchwork.ozlabs.org/project/netfilter-devel/list/?series=497644", "date": "2026-03-26T20:09:35", "name": "[nf] netfilter: flowtable: strictly check for maximum number of actions", "version": 1, "mbox": "http://patchwork.ozlabs.org/series/497644/mbox/" } ], "comments": "http://patchwork.ozlabs.org/api/patches/2216568/comments/", "check": "pending", "checks": "http://patchwork.ozlabs.org/api/patches/2216568/checks/", "tags": {}, "related": [], "headers": { "Return-Path": "\n <netfilter-devel+bounces-11459-incoming=patchwork.ozlabs.org@vger.kernel.org>", "X-Original-To": [ "incoming@patchwork.ozlabs.org", "netfilter-devel@vger.kernel.org" ], "Delivered-To": "patchwork-incoming@legolas.ozlabs.org", "Authentication-Results": [ "legolas.ozlabs.org;\n\tdkim=pass (2048-bit key;\n unprotected) header.d=netfilter.org header.i=@netfilter.org\n header.a=rsa-sha256 header.s=2025 header.b=QWIG77za;\n\tdkim-atps=neutral", "legolas.ozlabs.org;\n spf=pass (sender SPF authorized) smtp.mailfrom=vger.kernel.org\n (client-ip=2600:3c0a:e001:db::12fc:5321; helo=sea.lore.kernel.org;\n envelope-from=netfilter-devel+bounces-11459-incoming=patchwork.ozlabs.org@vger.kernel.org;\n receiver=patchwork.ozlabs.org)", "smtp.subspace.kernel.org;\n\tdkim=pass (2048-bit key) header.d=netfilter.org header.i=@netfilter.org\n header.b=\"QWIG77za\"", "smtp.subspace.kernel.org;\n arc=none smtp.client-ip=217.70.190.124", "smtp.subspace.kernel.org;\n dmarc=none (p=none dis=none) header.from=netfilter.org", "smtp.subspace.kernel.org;\n spf=pass smtp.mailfrom=netfilter.org" ], "Received": [ "from sea.lore.kernel.org (sea.lore.kernel.org\n [IPv6:2600:3c0a:e001:db::12fc:5321])\n\t(using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)\n\t key-exchange x25519)\n\t(No client certificate requested)\n\tby legolas.ozlabs.org (Postfix) with ESMTPS id 4fhZls41z8z1yFp\n\tfor <incoming@patchwork.ozlabs.org>; Fri, 27 Mar 2026 07:15:53 +1100 (AEDT)", "from smtp.subspace.kernel.org (conduit.subspace.kernel.org\n [100.90.174.1])\n\tby sea.lore.kernel.org (Postfix) with ESMTP id 1ACAD303829B\n\tfor <incoming@patchwork.ozlabs.org>; Thu, 26 Mar 2026 20:09:46 +0000 (UTC)", "from localhost.localdomain (localhost.localdomain [127.0.0.1])\n\tby smtp.subspace.kernel.org (Postfix) with ESMTP id 8019A378D71;\n\tThu, 26 Mar 2026 20:09:45 +0000 (UTC)", "from mail.netfilter.org (mail.netfilter.org [217.70.190.124])\n\t(using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits))\n\t(No client certificate requested)\n\tby smtp.subspace.kernel.org (Postfix) with ESMTPS id 552271A9FB7\n\tfor <netfilter-devel@vger.kernel.org>; Thu, 26 Mar 2026 20:09:42 +0000 (UTC)", "from localhost.localdomain (mail-agni [217.70.190.124])\n\tby mail.netfilter.org (Postfix) with ESMTPSA id 946DA600B9;\n\tThu, 26 Mar 2026 21:09:39 +0100 (CET)" ], "ARC-Seal": "i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116;\n\tt=1774555785; cv=none;\n b=WsTuDFUvkknSyEJucxUFl+Dv0NJ1dND/D83l3RIVusmmGMtsnN+zfQ6aOl9xhisHC/ma3sza+FDO3pZPIHrmcK8l+bOlSXcnyZzoNlUBd6HpHZTAZvZkUJ582kc6mnTCuHORs1bEmBxKjBLEiJZzXPy18e67LOc01EPAhHaK4J4=", "ARC-Message-Signature": "i=1; a=rsa-sha256; d=subspace.kernel.org;\n\ts=arc-20240116; t=1774555785; c=relaxed/simple;\n\tbh=EojgAT4QJNvbg5uKJdPlZJrZCgGKojCB5w0AGESIK94=;\n\th=From:To:Cc:Subject:Date:Message-ID:MIME-Version;\n b=OAhKl5dfLp5olAcIuLFbqKkxeehvMaZ3F7ltVHM+OQ/TPvDePRNL5+NhFCMHbCDOtEs0de30/ny7IiXNoRBiesj6/8er7y6O8f8B+qdWEDpm6FooU99PSETg65axj5gJaNV0AcJcAGSlbODYdqQjIxov8ldtcXdPm8NtzRxZg2E=", "ARC-Authentication-Results": "i=1; smtp.subspace.kernel.org;\n dmarc=none (p=none dis=none) header.from=netfilter.org;\n spf=pass smtp.mailfrom=netfilter.org;\n dkim=pass (2048-bit key) header.d=netfilter.org header.i=@netfilter.org\n header.b=QWIG77za; arc=none smtp.client-ip=217.70.190.124", "DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed; d=netfilter.org;\n\ts=2025; t=1774555779;\n\tbh=60ksNI8F8ohIhwyua0icaAg02psqdMpkQrcIdgkLNH4=;\n\th=From:To:Cc:Subject:Date:From;\n\tb=QWIG77zaUR5OqvdleKxSVKmou0RQMzYWmWGXb0wOdG3IdWr1887Mal/EnLbiQBPDK\n\t 6lAk1UUELASVWfrkA8G/ih7aL7A7oCve7VWAV1yl0Dfly6xfxdoKQl4a+IHaXsT3Z4\n\t Z7Do85VxMPJmsxJumVBgg6m+iWTbi3DaAnee4MvBxUgeb/siev3zgU5jDNdxoIsqMX\n\t fevHyGiMTAvsFq8s2dt87GIB6eR9hSKL3EToaDlqOwvhJpCceUxKqzcz/bqRLY3blD\n\t NKj3WP/br4TwtzdDZKXP1yn802SetlFPWG3QgEcdF0L3Jb+0X6mCkVhl3K+EAxVNIo\n\t yRfL4QJ8AZqyw==", "From": "Pablo Neira Ayuso <pablo@netfilter.org>", "To": "netfilter-devel@vger.kernel.org", "Cc": "fw@strlen.de", "Subject": "[PATCH nf] netfilter: flowtable: strictly check for maximum number of\n actions", "Date": "Thu, 26 Mar 2026 21:09:35 +0100", "Message-ID": "<20260326200935.729750-1-pablo@netfilter.org>", "X-Mailer": "git-send-email 2.47.3", "Precedence": "bulk", "X-Mailing-List": "netfilter-devel@vger.kernel.org", "List-Id": "<netfilter-devel.vger.kernel.org>", "List-Subscribe": "<mailto:netfilter-devel+subscribe@vger.kernel.org>", "List-Unsubscribe": "<mailto:netfilter-devel+unsubscribe@vger.kernel.org>", "MIME-Version": "1.0", "Content-Transfer-Encoding": "8bit" }, "content": "The maximum number of flowtable hardware offload actions in IPv6 is:\n\n* ethernet mangling (4 payload actions, 2 for each ethernet address)\n* SNAT (4 payload actions)\n* DNAT (4 payload actions)\n* Double VLAN (4 vlan actions, 2 for popping vlan, and 2 for pushing)\n for QinQ.\n* Redirect (1 action)\n\nWhich makes 17, while the maximum is 16. But act_ct supports for tunnels\nactions too. Note that payload action operates at 32-bit word level, so\nmangling an IPv6 address take 4 payload actions.\n\nUpdate flow_action_entry_next() calls to check for the maximum number of\nsupported actions.\n\nWhile at it, rise the maximum number of actions per flow from 16 to 24\nso this works fine with IPv6 setups.\n\nFixes: c29f74e0df7a (\"netfilter: nf_flow_table: hardware offload support\")\nReported-by: Hyunwoo Kim <imv4bel@gmail.com>\nSigned-off-by: Pablo Neira Ayuso <pablo@netfilter.org>\n---\nThis is the large version of this fix, it should be possible to make a\nmuch smaller workaround patch. This codebase did not change much since\n2019, backports should be not too complicated.\n\n net/netfilter/nf_flow_table_offload.c | 190 +++++++++++++++++---------\n 1 file changed, 125 insertions(+), 65 deletions(-)", "diff": "diff --git a/net/netfilter/nf_flow_table_offload.c b/net/netfilter/nf_flow_table_offload.c\nindex 9b677e116487..eea77e0d1416 100644\n--- a/net/netfilter/nf_flow_table_offload.c\n+++ b/net/netfilter/nf_flow_table_offload.c\n@@ -14,6 +14,8 @@\n #include <net/netfilter/nf_conntrack_core.h>\n #include <net/netfilter/nf_conntrack_tuple.h>\n \n+#define NF_FLOW_RULE_ACTION_MAX\t24\n+\n static struct workqueue_struct *nf_flow_offload_add_wq;\n static struct workqueue_struct *nf_flow_offload_del_wq;\n static struct workqueue_struct *nf_flow_offload_stats_wq;\n@@ -218,6 +220,9 @@ flow_action_entry_next(struct nf_flow_rule *flow_rule)\n {\n \tint i = flow_rule->rule->action.num_entries++;\n \n+\tif (unlikely(i >= NF_FLOW_RULE_ACTION_MAX))\n+\t\treturn NULL;\n+\n \treturn &flow_rule->rule->action.entries[i];\n }\n \n@@ -234,6 +239,9 @@ static int flow_offload_eth_src(struct net *net,\n \tu32 mask, val;\n \tu16 val16;\n \n+\tif (!entry0 || !entry1)\n+\t\treturn -E2BIG;\n+\n \tthis_tuple = &flow->tuplehash[dir].tuple;\n \n \tswitch (this_tuple->xmit_type) {\n@@ -284,6 +292,9 @@ static int flow_offload_eth_dst(struct net *net,\n \tu8 nud_state;\n \tu16 val16;\n \n+\tif (!entry0 || !entry1)\n+\t\treturn -E2BIG;\n+\n \tthis_tuple = &flow->tuplehash[dir].tuple;\n \n \tswitch (this_tuple->xmit_type) {\n@@ -325,16 +336,19 @@ static int flow_offload_eth_dst(struct net *net,\n \treturn 0;\n }\n \n-static void flow_offload_ipv4_snat(struct net *net,\n-\t\t\t\t const struct flow_offload *flow,\n-\t\t\t\t enum flow_offload_tuple_dir dir,\n-\t\t\t\t struct nf_flow_rule *flow_rule)\n+static int flow_offload_ipv4_snat(struct net *net,\n+\t\t\t\t const struct flow_offload *flow,\n+\t\t\t\t enum flow_offload_tuple_dir dir,\n+\t\t\t\t struct nf_flow_rule *flow_rule)\n {\n \tstruct flow_action_entry *entry = flow_action_entry_next(flow_rule);\n \tu32 mask = ~htonl(0xffffffff);\n \t__be32 addr;\n \tu32 offset;\n \n+\tif (!entry)\n+\t\treturn -E2BIG;\n+\n \tswitch (dir) {\n \tcase FLOW_OFFLOAD_DIR_ORIGINAL:\n \t\taddr = flow->tuplehash[FLOW_OFFLOAD_DIR_REPLY].tuple.dst_v4.s_addr;\n@@ -345,23 +359,27 @@ static void flow_offload_ipv4_snat(struct net *net,\n \t\toffset = offsetof(struct iphdr, daddr);\n \t\tbreak;\n \tdefault:\n-\t\treturn;\n+\t\treturn -EOPNOTSUPP;\n \t}\n \n \tflow_offload_mangle(entry, FLOW_ACT_MANGLE_HDR_TYPE_IP4, offset,\n \t\t\t &addr, &mask);\n+\treturn 0;\n }\n \n-static void flow_offload_ipv4_dnat(struct net *net,\n-\t\t\t\t const struct flow_offload *flow,\n-\t\t\t\t enum flow_offload_tuple_dir dir,\n-\t\t\t\t struct nf_flow_rule *flow_rule)\n+static int flow_offload_ipv4_dnat(struct net *net,\n+\t\t\t\t const struct flow_offload *flow,\n+\t\t\t\t enum flow_offload_tuple_dir dir,\n+\t\t\t\t struct nf_flow_rule *flow_rule)\n {\n \tstruct flow_action_entry *entry = flow_action_entry_next(flow_rule);\n \tu32 mask = ~htonl(0xffffffff);\n \t__be32 addr;\n \tu32 offset;\n \n+\tif (!entry)\n+\t\treturn -E2BIG;\n+\n \tswitch (dir) {\n \tcase FLOW_OFFLOAD_DIR_ORIGINAL:\n \t\taddr = flow->tuplehash[FLOW_OFFLOAD_DIR_REPLY].tuple.src_v4.s_addr;\n@@ -372,14 +390,15 @@ static void flow_offload_ipv4_dnat(struct net *net,\n \t\toffset = offsetof(struct iphdr, saddr);\n \t\tbreak;\n \tdefault:\n-\t\treturn;\n+\t\treturn -EOPNOTSUPP;\n \t}\n \n \tflow_offload_mangle(entry, FLOW_ACT_MANGLE_HDR_TYPE_IP4, offset,\n \t\t\t &addr, &mask);\n+\treturn 0;\n }\n \n-static void flow_offload_ipv6_mangle(struct nf_flow_rule *flow_rule,\n+static int flow_offload_ipv6_mangle(struct nf_flow_rule *flow_rule,\n \t\t\t\t unsigned int offset,\n \t\t\t\t const __be32 *addr, const __be32 *mask)\n {\n@@ -388,15 +407,20 @@ static void flow_offload_ipv6_mangle(struct nf_flow_rule *flow_rule,\n \n \tfor (i = 0; i < sizeof(struct in6_addr) / sizeof(u32); i++) {\n \t\tentry = flow_action_entry_next(flow_rule);\n+\t\tif (!entry)\n+\t\t\treturn -E2BIG;\n+\n \t\tflow_offload_mangle(entry, FLOW_ACT_MANGLE_HDR_TYPE_IP6,\n \t\t\t\t offset + i * sizeof(u32), &addr[i], mask);\n \t}\n+\n+\treturn 0;\n }\n \n-static void flow_offload_ipv6_snat(struct net *net,\n-\t\t\t\t const struct flow_offload *flow,\n-\t\t\t\t enum flow_offload_tuple_dir dir,\n-\t\t\t\t struct nf_flow_rule *flow_rule)\n+static int flow_offload_ipv6_snat(struct net *net,\n+\t\t\t\t const struct flow_offload *flow,\n+\t\t\t\t enum flow_offload_tuple_dir dir,\n+\t\t\t\t struct nf_flow_rule *flow_rule)\n {\n \tu32 mask = ~htonl(0xffffffff);\n \tconst __be32 *addr;\n@@ -412,16 +436,16 @@ static void flow_offload_ipv6_snat(struct net *net,\n \t\toffset = offsetof(struct ipv6hdr, daddr);\n \t\tbreak;\n \tdefault:\n-\t\treturn;\n+\t\treturn -EOPNOTSUPP;\n \t}\n \n-\tflow_offload_ipv6_mangle(flow_rule, offset, addr, &mask);\n+\treturn flow_offload_ipv6_mangle(flow_rule, offset, addr, &mask);\n }\n \n-static void flow_offload_ipv6_dnat(struct net *net,\n-\t\t\t\t const struct flow_offload *flow,\n-\t\t\t\t enum flow_offload_tuple_dir dir,\n-\t\t\t\t struct nf_flow_rule *flow_rule)\n+static int flow_offload_ipv6_dnat(struct net *net,\n+\t\t\t\t const struct flow_offload *flow,\n+\t\t\t\t enum flow_offload_tuple_dir dir,\n+\t\t\t\t struct nf_flow_rule *flow_rule)\n {\n \tu32 mask = ~htonl(0xffffffff);\n \tconst __be32 *addr;\n@@ -437,10 +461,10 @@ static void flow_offload_ipv6_dnat(struct net *net,\n \t\toffset = offsetof(struct ipv6hdr, saddr);\n \t\tbreak;\n \tdefault:\n-\t\treturn;\n+\t\treturn -EOPNOTSUPP;\n \t}\n \n-\tflow_offload_ipv6_mangle(flow_rule, offset, addr, &mask);\n+\treturn flow_offload_ipv6_mangle(flow_rule, offset, addr, &mask);\n }\n \n static int flow_offload_l4proto(const struct flow_offload *flow)\n@@ -462,15 +486,18 @@ static int flow_offload_l4proto(const struct flow_offload *flow)\n \treturn type;\n }\n \n-static void flow_offload_port_snat(struct net *net,\n-\t\t\t\t const struct flow_offload *flow,\n-\t\t\t\t enum flow_offload_tuple_dir dir,\n-\t\t\t\t struct nf_flow_rule *flow_rule)\n+static int flow_offload_port_snat(struct net *net,\n+\t\t\t\t const struct flow_offload *flow,\n+\t\t\t\t enum flow_offload_tuple_dir dir,\n+\t\t\t\t struct nf_flow_rule *flow_rule)\n {\n \tstruct flow_action_entry *entry = flow_action_entry_next(flow_rule);\n \tu32 mask, port;\n \tu32 offset;\n \n+\tif (!entry)\n+\t\treturn -E2BIG;\n+\n \tswitch (dir) {\n \tcase FLOW_OFFLOAD_DIR_ORIGINAL:\n \t\tport = ntohs(flow->tuplehash[FLOW_OFFLOAD_DIR_REPLY].tuple.dst_port);\n@@ -485,22 +512,26 @@ static void flow_offload_port_snat(struct net *net,\n \t\tmask = ~htonl(0xffff);\n \t\tbreak;\n \tdefault:\n-\t\treturn;\n+\t\treturn -EOPNOTSUPP;\n \t}\n \n \tflow_offload_mangle(entry, flow_offload_l4proto(flow), offset,\n \t\t\t &port, &mask);\n+\treturn 0;\n }\n \n-static void flow_offload_port_dnat(struct net *net,\n-\t\t\t\t const struct flow_offload *flow,\n-\t\t\t\t enum flow_offload_tuple_dir dir,\n-\t\t\t\t struct nf_flow_rule *flow_rule)\n+static int flow_offload_port_dnat(struct net *net,\n+\t\t\t\t const struct flow_offload *flow,\n+\t\t\t\t enum flow_offload_tuple_dir dir,\n+\t\t\t\t struct nf_flow_rule *flow_rule)\n {\n \tstruct flow_action_entry *entry = flow_action_entry_next(flow_rule);\n \tu32 mask, port;\n \tu32 offset;\n \n+\tif (!entry)\n+\t\treturn -E2BIG;\n+\n \tswitch (dir) {\n \tcase FLOW_OFFLOAD_DIR_ORIGINAL:\n \t\tport = ntohs(flow->tuplehash[FLOW_OFFLOAD_DIR_REPLY].tuple.src_port);\n@@ -515,20 +546,24 @@ static void flow_offload_port_dnat(struct net *net,\n \t\tmask = ~htonl(0xffff0000);\n \t\tbreak;\n \tdefault:\n-\t\treturn;\n+\t\treturn -EOPNOTSUPP;\n \t}\n \n \tflow_offload_mangle(entry, flow_offload_l4proto(flow), offset,\n \t\t\t &port, &mask);\n+\treturn 0;\n }\n \n-static void flow_offload_ipv4_checksum(struct net *net,\n-\t\t\t\t const struct flow_offload *flow,\n-\t\t\t\t struct nf_flow_rule *flow_rule)\n+static int flow_offload_ipv4_checksum(struct net *net,\n+\t\t\t\t const struct flow_offload *flow,\n+\t\t\t\t struct nf_flow_rule *flow_rule)\n {\n \tu8 protonum = flow->tuplehash[FLOW_OFFLOAD_DIR_ORIGINAL].tuple.l4proto;\n \tstruct flow_action_entry *entry = flow_action_entry_next(flow_rule);\n \n+\tif (!entry)\n+\t\treturn E2BIG;\n+\n \tentry->id = FLOW_ACTION_CSUM;\n \tentry->csum_flags = TCA_CSUM_UPDATE_FLAG_IPV4HDR;\n \n@@ -540,12 +575,14 @@ static void flow_offload_ipv4_checksum(struct net *net,\n \t\tentry->csum_flags |= TCA_CSUM_UPDATE_FLAG_UDP;\n \t\tbreak;\n \t}\n+\n+\treturn 0;\n }\n \n-static void flow_offload_redirect(struct net *net,\n-\t\t\t\t const struct flow_offload *flow,\n-\t\t\t\t enum flow_offload_tuple_dir dir,\n-\t\t\t\t struct nf_flow_rule *flow_rule)\n+static int flow_offload_redirect(struct net *net,\n+\t\t\t\t const struct flow_offload *flow,\n+\t\t\t\t enum flow_offload_tuple_dir dir,\n+\t\t\t\t struct nf_flow_rule *flow_rule)\n {\n \tconst struct flow_offload_tuple *this_tuple, *other_tuple;\n \tstruct flow_action_entry *entry;\n@@ -563,21 +600,26 @@ static void flow_offload_redirect(struct net *net,\n \t\tifindex = other_tuple->iifidx;\n \t\tbreak;\n \tdefault:\n-\t\treturn;\n+\t\treturn -EOPNOTSUPP;\n \t}\n \n \tdev = dev_get_by_index(net, ifindex);\n \tif (!dev)\n-\t\treturn;\n+\t\treturn -ENODEV;\n \n \tentry = flow_action_entry_next(flow_rule);\n+\tif (!entry)\n+\t\treturn -E2BIG;\n+\n \tentry->id = FLOW_ACTION_REDIRECT;\n \tentry->dev = dev;\n+\n+\treturn 0;\n }\n \n-static void flow_offload_encap_tunnel(const struct flow_offload *flow,\n-\t\t\t\t enum flow_offload_tuple_dir dir,\n-\t\t\t\t struct nf_flow_rule *flow_rule)\n+static int flow_offload_encap_tunnel(const struct flow_offload *flow,\n+\t\t\t\t enum flow_offload_tuple_dir dir,\n+\t\t\t\t struct nf_flow_rule *flow_rule)\n {\n \tconst struct flow_offload_tuple *this_tuple;\n \tstruct flow_action_entry *entry;\n@@ -585,7 +627,7 @@ static void flow_offload_encap_tunnel(const struct flow_offload *flow,\n \n \tthis_tuple = &flow->tuplehash[dir].tuple;\n \tif (this_tuple->xmit_type == FLOW_OFFLOAD_XMIT_DIRECT)\n-\t\treturn;\n+\t\treturn 0;\n \n \tdst = this_tuple->dst_cache;\n \tif (dst && dst->lwtstate) {\n@@ -594,15 +636,19 @@ static void flow_offload_encap_tunnel(const struct flow_offload *flow,\n \t\ttun_info = lwt_tun_info(dst->lwtstate);\n \t\tif (tun_info && (tun_info->mode & IP_TUNNEL_INFO_TX)) {\n \t\t\tentry = flow_action_entry_next(flow_rule);\n+\t\t\tif (!entry)\n+\t\t\t\treturn -E2BIG;\n \t\t\tentry->id = FLOW_ACTION_TUNNEL_ENCAP;\n \t\t\tentry->tunnel = tun_info;\n \t\t}\n \t}\n+\n+\treturn 0;\n }\n \n-static void flow_offload_decap_tunnel(const struct flow_offload *flow,\n-\t\t\t\t enum flow_offload_tuple_dir dir,\n-\t\t\t\t struct nf_flow_rule *flow_rule)\n+static int flow_offload_decap_tunnel(const struct flow_offload *flow,\n+\t\t\t\t enum flow_offload_tuple_dir dir,\n+\t\t\t\t struct nf_flow_rule *flow_rule)\n {\n \tconst struct flow_offload_tuple *other_tuple;\n \tstruct flow_action_entry *entry;\n@@ -610,7 +656,7 @@ static void flow_offload_decap_tunnel(const struct flow_offload *flow,\n \n \tother_tuple = &flow->tuplehash[!dir].tuple;\n \tif (other_tuple->xmit_type == FLOW_OFFLOAD_XMIT_DIRECT)\n-\t\treturn;\n+\t\treturn 0;\n \n \tdst = other_tuple->dst_cache;\n \tif (dst && dst->lwtstate) {\n@@ -619,9 +665,13 @@ static void flow_offload_decap_tunnel(const struct flow_offload *flow,\n \t\ttun_info = lwt_tun_info(dst->lwtstate);\n \t\tif (tun_info && (tun_info->mode & IP_TUNNEL_INFO_TX)) {\n \t\t\tentry = flow_action_entry_next(flow_rule);\n+\t\t\tif (!entry)\n+\t\t\t\treturn -E2BIG;\n \t\t\tentry->id = FLOW_ACTION_TUNNEL_DECAP;\n \t\t}\n \t}\n+\n+\treturn 0;\n }\n \n static int\n@@ -633,8 +683,9 @@ nf_flow_rule_route_common(struct net *net, const struct flow_offload *flow,\n \tconst struct flow_offload_tuple *tuple;\n \tint i;\n \n-\tflow_offload_decap_tunnel(flow, dir, flow_rule);\n-\tflow_offload_encap_tunnel(flow, dir, flow_rule);\n+\tif (flow_offload_decap_tunnel(flow, dir, flow_rule) < 0 ||\n+\t flow_offload_encap_tunnel(flow, dir, flow_rule) < 0)\n+\t\treturn -1;\n \n \tif (flow_offload_eth_src(net, flow, dir, flow_rule) < 0 ||\n \t flow_offload_eth_dst(net, flow, dir, flow_rule) < 0)\n@@ -650,6 +701,8 @@ nf_flow_rule_route_common(struct net *net, const struct flow_offload *flow,\n \n \t\tif (tuple->encap[i].proto == htons(ETH_P_8021Q)) {\n \t\t\tentry = flow_action_entry_next(flow_rule);\n+\t\t\tif (!entry)\n+\t\t\t\treturn -1;\n \t\t\tentry->id = FLOW_ACTION_VLAN_POP;\n \t\t}\n \t}\n@@ -663,6 +716,8 @@ nf_flow_rule_route_common(struct net *net, const struct flow_offload *flow,\n \t\t\tcontinue;\n \n \t\tentry = flow_action_entry_next(flow_rule);\n+\t\tif (!entry)\n+\t\t\treturn -1;\n \n \t\tswitch (other_tuple->encap[i].proto) {\n \t\tcase htons(ETH_P_PPP_SES):\n@@ -688,18 +743,22 @@ int nf_flow_rule_route_ipv4(struct net *net, struct flow_offload *flow,\n \t\treturn -1;\n \n \tif (test_bit(NF_FLOW_SNAT, &flow->flags)) {\n-\t\tflow_offload_ipv4_snat(net, flow, dir, flow_rule);\n-\t\tflow_offload_port_snat(net, flow, dir, flow_rule);\n+\t\tif (flow_offload_ipv4_snat(net, flow, dir, flow_rule) < 0 ||\n+\t\t flow_offload_port_snat(net, flow, dir, flow_rule) < 0)\n+\t\t\treturn -1;\n \t}\n \tif (test_bit(NF_FLOW_DNAT, &flow->flags)) {\n-\t\tflow_offload_ipv4_dnat(net, flow, dir, flow_rule);\n-\t\tflow_offload_port_dnat(net, flow, dir, flow_rule);\n+\t\tif (flow_offload_ipv4_dnat(net, flow, dir, flow_rule) < 0 ||\n+\t\t flow_offload_port_dnat(net, flow, dir, flow_rule) < 0)\n+\t\t\treturn -1;\n \t}\n \tif (test_bit(NF_FLOW_SNAT, &flow->flags) ||\n \t test_bit(NF_FLOW_DNAT, &flow->flags))\n-\t\tflow_offload_ipv4_checksum(net, flow, flow_rule);\n+\t\tif (flow_offload_ipv4_checksum(net, flow, flow_rule) < 0)\n+\t\t\treturn -1;\n \n-\tflow_offload_redirect(net, flow, dir, flow_rule);\n+\tif (flow_offload_redirect(net, flow, dir, flow_rule) < 0)\n+\t\treturn -1;\n \n \treturn 0;\n }\n@@ -713,22 +772,23 @@ int nf_flow_rule_route_ipv6(struct net *net, struct flow_offload *flow,\n \t\treturn -1;\n \n \tif (test_bit(NF_FLOW_SNAT, &flow->flags)) {\n-\t\tflow_offload_ipv6_snat(net, flow, dir, flow_rule);\n-\t\tflow_offload_port_snat(net, flow, dir, flow_rule);\n+\t\tif (flow_offload_ipv6_snat(net, flow, dir, flow_rule) < 0 ||\n+\t\t flow_offload_port_snat(net, flow, dir, flow_rule) < 0)\n+\t\t\treturn -1;\n \t}\n \tif (test_bit(NF_FLOW_DNAT, &flow->flags)) {\n-\t\tflow_offload_ipv6_dnat(net, flow, dir, flow_rule);\n-\t\tflow_offload_port_dnat(net, flow, dir, flow_rule);\n+\t\tif (flow_offload_ipv6_dnat(net, flow, dir, flow_rule) < 0 ||\n+\t\t flow_offload_port_dnat(net, flow, dir, flow_rule) < 0)\n+\t\t\treturn -1;\n \t}\n \n-\tflow_offload_redirect(net, flow, dir, flow_rule);\n+\tif (flow_offload_redirect(net, flow, dir, flow_rule) < 0)\n+\t\treturn -1;\n \n \treturn 0;\n }\n EXPORT_SYMBOL_GPL(nf_flow_rule_route_ipv6);\n \n-#define NF_FLOW_RULE_ACTION_MAX\t16\n-\n static struct nf_flow_rule *\n nf_flow_offload_rule_alloc(struct net *net,\n \t\t\t const struct flow_offload_work *offload,\n", "prefixes": [ "nf" ] }