Skip to content

Commit 963bdfc

Browse files
committed
Merge git://git.kernel.org/pub/scm/linux/kernel/git/pablo/nf
Pablo Neira Ayuso says: ==================== Netfilter fixes for net The following patchset contains Netfilter fixes for net: 1) Set VLAN tag in tcp reset/icmp unreachable packets to reject connections in the bridge family, from Michael Braun. 2) Incorrect subcounter flag update in ipset, from Phil Sutter. 3) Possible buffer overflow in the pptp conntrack helper, based on patch from Dan Carpenter. 4) Restore userspace conntrack helper hook logic that broke after hook consolidation rework. 5) Unbreak userspace conntrack helper registration via nfnetlink_cthelper. ==================== Signed-off-by: David S. Miller <[email protected]>
2 parents 1a6da4f + 703acd7 commit 963bdfc

File tree

7 files changed

+119
-41
lines changed

7 files changed

+119
-41
lines changed

include/linux/netfilter/nf_conntrack_pptp.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
#include <net/netfilter/nf_conntrack_expect.h>
1111
#include <uapi/linux/netfilter/nf_conntrack_tuple_common.h>
1212

13-
extern const char *const pptp_msg_name[];
13+
extern const char *const pptp_msg_name(u_int16_t msg);
1414

1515
/* state of the control session */
1616
enum pptp_ctrlsess_state {

net/bridge/netfilter/nft_reject_bridge.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,12 @@ static void nft_reject_br_push_etherhdr(struct sk_buff *oldskb,
3131
ether_addr_copy(eth->h_dest, eth_hdr(oldskb)->h_source);
3232
eth->h_proto = eth_hdr(oldskb)->h_proto;
3333
skb_pull(nskb, ETH_HLEN);
34+
35+
if (skb_vlan_tag_present(oldskb)) {
36+
u16 vid = skb_vlan_tag_get(oldskb);
37+
38+
__vlan_hwaccel_put_tag(nskb, oldskb->vlan_proto, vid);
39+
}
3440
}
3541

3642
static int nft_bridge_iphdr_validate(struct sk_buff *skb)

net/ipv4/netfilter/nf_nat_pptp.c

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -166,8 +166,7 @@ pptp_outbound_pkt(struct sk_buff *skb,
166166
break;
167167
default:
168168
pr_debug("unknown outbound packet 0x%04x:%s\n", msg,
169-
msg <= PPTP_MSG_MAX ? pptp_msg_name[msg] :
170-
pptp_msg_name[0]);
169+
pptp_msg_name(msg));
171170
fallthrough;
172171
case PPTP_SET_LINK_INFO:
173172
/* only need to NAT in case PAC is behind NAT box */
@@ -268,9 +267,7 @@ pptp_inbound_pkt(struct sk_buff *skb,
268267
pcid_off = offsetof(union pptp_ctrl_union, setlink.peersCallID);
269268
break;
270269
default:
271-
pr_debug("unknown inbound packet %s\n",
272-
msg <= PPTP_MSG_MAX ? pptp_msg_name[msg] :
273-
pptp_msg_name[0]);
270+
pr_debug("unknown inbound packet %s\n", pptp_msg_name(msg));
274271
fallthrough;
275272
case PPTP_START_SESSION_REQUEST:
276273
case PPTP_START_SESSION_REPLY:

net/netfilter/ipset/ip_set_list_set.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ list_set_ktest(struct ip_set *set, const struct sk_buff *skb,
5959
/* Don't lookup sub-counters at all */
6060
opt->cmdflags &= ~IPSET_FLAG_MATCH_COUNTERS;
6161
if (opt->cmdflags & IPSET_FLAG_SKIP_SUBCOUNTER_UPDATE)
62-
opt->cmdflags &= ~IPSET_FLAG_SKIP_COUNTER_UPDATE;
62+
opt->cmdflags |= IPSET_FLAG_SKIP_COUNTER_UPDATE;
6363
list_for_each_entry_rcu(e, &map->members, list) {
6464
ret = ip_set_test(e->id, skb, par, opt);
6565
if (ret <= 0)

net/netfilter/nf_conntrack_core.c

Lines changed: 72 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2016,22 +2016,18 @@ static void nf_conntrack_attach(struct sk_buff *nskb, const struct sk_buff *skb)
20162016
nf_conntrack_get(skb_nfct(nskb));
20172017
}
20182018

2019-
static int nf_conntrack_update(struct net *net, struct sk_buff *skb)
2019+
static int __nf_conntrack_update(struct net *net, struct sk_buff *skb,
2020+
struct nf_conn *ct)
20202021
{
20212022
struct nf_conntrack_tuple_hash *h;
20222023
struct nf_conntrack_tuple tuple;
20232024
enum ip_conntrack_info ctinfo;
20242025
struct nf_nat_hook *nat_hook;
20252026
unsigned int status;
2026-
struct nf_conn *ct;
20272027
int dataoff;
20282028
u16 l3num;
20292029
u8 l4num;
20302030

2031-
ct = nf_ct_get(skb, &ctinfo);
2032-
if (!ct || nf_ct_is_confirmed(ct))
2033-
return 0;
2034-
20352031
l3num = nf_ct_l3num(ct);
20362032

20372033
dataoff = get_l4proto(skb, skb_network_offset(skb), l3num, &l4num);
@@ -2088,6 +2084,76 @@ static int nf_conntrack_update(struct net *net, struct sk_buff *skb)
20882084
return 0;
20892085
}
20902086

2087+
/* This packet is coming from userspace via nf_queue, complete the packet
2088+
* processing after the helper invocation in nf_confirm().
2089+
*/
2090+
static int nf_confirm_cthelper(struct sk_buff *skb, struct nf_conn *ct,
2091+
enum ip_conntrack_info ctinfo)
2092+
{
2093+
const struct nf_conntrack_helper *helper;
2094+
const struct nf_conn_help *help;
2095+
unsigned int protoff;
2096+
2097+
help = nfct_help(ct);
2098+
if (!help)
2099+
return 0;
2100+
2101+
helper = rcu_dereference(help->helper);
2102+
if (!(helper->flags & NF_CT_HELPER_F_USERSPACE))
2103+
return 0;
2104+
2105+
switch (nf_ct_l3num(ct)) {
2106+
case NFPROTO_IPV4:
2107+
protoff = skb_network_offset(skb) + ip_hdrlen(skb);
2108+
break;
2109+
#if IS_ENABLED(CONFIG_IPV6)
2110+
case NFPROTO_IPV6: {
2111+
__be16 frag_off;
2112+
u8 pnum;
2113+
2114+
pnum = ipv6_hdr(skb)->nexthdr;
2115+
protoff = ipv6_skip_exthdr(skb, sizeof(struct ipv6hdr), &pnum,
2116+
&frag_off);
2117+
if (protoff < 0 || (frag_off & htons(~0x7)) != 0)
2118+
return 0;
2119+
break;
2120+
}
2121+
#endif
2122+
default:
2123+
return 0;
2124+
}
2125+
2126+
if (test_bit(IPS_SEQ_ADJUST_BIT, &ct->status) &&
2127+
!nf_is_loopback_packet(skb)) {
2128+
if (!nf_ct_seq_adjust(skb, ct, ctinfo, protoff)) {
2129+
NF_CT_STAT_INC_ATOMIC(nf_ct_net(ct), drop);
2130+
return -1;
2131+
}
2132+
}
2133+
2134+
/* We've seen it coming out the other side: confirm it */
2135+
return nf_conntrack_confirm(skb) == NF_DROP ? - 1 : 0;
2136+
}
2137+
2138+
static int nf_conntrack_update(struct net *net, struct sk_buff *skb)
2139+
{
2140+
enum ip_conntrack_info ctinfo;
2141+
struct nf_conn *ct;
2142+
int err;
2143+
2144+
ct = nf_ct_get(skb, &ctinfo);
2145+
if (!ct)
2146+
return 0;
2147+
2148+
if (!nf_ct_is_confirmed(ct)) {
2149+
err = __nf_conntrack_update(net, skb, ct);
2150+
if (err < 0)
2151+
return err;
2152+
}
2153+
2154+
return nf_confirm_cthelper(skb, ct, ctinfo);
2155+
}
2156+
20912157
static bool nf_conntrack_get_tuple_skb(struct nf_conntrack_tuple *dst_tuple,
20922158
const struct sk_buff *skb)
20932159
{

net/netfilter/nf_conntrack_pptp.c

Lines changed: 35 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -72,24 +72,32 @@ EXPORT_SYMBOL_GPL(nf_nat_pptp_hook_expectfn);
7272

7373
#if defined(DEBUG) || defined(CONFIG_DYNAMIC_DEBUG)
7474
/* PptpControlMessageType names */
75-
const char *const pptp_msg_name[] = {
76-
"UNKNOWN_MESSAGE",
77-
"START_SESSION_REQUEST",
78-
"START_SESSION_REPLY",
79-
"STOP_SESSION_REQUEST",
80-
"STOP_SESSION_REPLY",
81-
"ECHO_REQUEST",
82-
"ECHO_REPLY",
83-
"OUT_CALL_REQUEST",
84-
"OUT_CALL_REPLY",
85-
"IN_CALL_REQUEST",
86-
"IN_CALL_REPLY",
87-
"IN_CALL_CONNECT",
88-
"CALL_CLEAR_REQUEST",
89-
"CALL_DISCONNECT_NOTIFY",
90-
"WAN_ERROR_NOTIFY",
91-
"SET_LINK_INFO"
75+
static const char *const pptp_msg_name_array[PPTP_MSG_MAX + 1] = {
76+
[0] = "UNKNOWN_MESSAGE",
77+
[PPTP_START_SESSION_REQUEST] = "START_SESSION_REQUEST",
78+
[PPTP_START_SESSION_REPLY] = "START_SESSION_REPLY",
79+
[PPTP_STOP_SESSION_REQUEST] = "STOP_SESSION_REQUEST",
80+
[PPTP_STOP_SESSION_REPLY] = "STOP_SESSION_REPLY",
81+
[PPTP_ECHO_REQUEST] = "ECHO_REQUEST",
82+
[PPTP_ECHO_REPLY] = "ECHO_REPLY",
83+
[PPTP_OUT_CALL_REQUEST] = "OUT_CALL_REQUEST",
84+
[PPTP_OUT_CALL_REPLY] = "OUT_CALL_REPLY",
85+
[PPTP_IN_CALL_REQUEST] = "IN_CALL_REQUEST",
86+
[PPTP_IN_CALL_REPLY] = "IN_CALL_REPLY",
87+
[PPTP_IN_CALL_CONNECT] = "IN_CALL_CONNECT",
88+
[PPTP_CALL_CLEAR_REQUEST] = "CALL_CLEAR_REQUEST",
89+
[PPTP_CALL_DISCONNECT_NOTIFY] = "CALL_DISCONNECT_NOTIFY",
90+
[PPTP_WAN_ERROR_NOTIFY] = "WAN_ERROR_NOTIFY",
91+
[PPTP_SET_LINK_INFO] = "SET_LINK_INFO"
9292
};
93+
94+
const char *const pptp_msg_name(u_int16_t msg)
95+
{
96+
if (msg > PPTP_MSG_MAX)
97+
return pptp_msg_name_array[0];
98+
99+
return pptp_msg_name_array[msg];
100+
}
93101
EXPORT_SYMBOL(pptp_msg_name);
94102
#endif
95103

@@ -276,7 +284,7 @@ pptp_inbound_pkt(struct sk_buff *skb, unsigned int protoff,
276284
typeof(nf_nat_pptp_hook_inbound) nf_nat_pptp_inbound;
277285

278286
msg = ntohs(ctlh->messageType);
279-
pr_debug("inbound control message %s\n", pptp_msg_name[msg]);
287+
pr_debug("inbound control message %s\n", pptp_msg_name(msg));
280288

281289
switch (msg) {
282290
case PPTP_START_SESSION_REPLY:
@@ -311,7 +319,7 @@ pptp_inbound_pkt(struct sk_buff *skb, unsigned int protoff,
311319
pcid = pptpReq->ocack.peersCallID;
312320
if (info->pns_call_id != pcid)
313321
goto invalid;
314-
pr_debug("%s, CID=%X, PCID=%X\n", pptp_msg_name[msg],
322+
pr_debug("%s, CID=%X, PCID=%X\n", pptp_msg_name(msg),
315323
ntohs(cid), ntohs(pcid));
316324

317325
if (pptpReq->ocack.resultCode == PPTP_OUTCALL_CONNECT) {
@@ -328,7 +336,7 @@ pptp_inbound_pkt(struct sk_buff *skb, unsigned int protoff,
328336
goto invalid;
329337

330338
cid = pptpReq->icreq.callID;
331-
pr_debug("%s, CID=%X\n", pptp_msg_name[msg], ntohs(cid));
339+
pr_debug("%s, CID=%X\n", pptp_msg_name(msg), ntohs(cid));
332340
info->cstate = PPTP_CALL_IN_REQ;
333341
info->pac_call_id = cid;
334342
break;
@@ -347,7 +355,7 @@ pptp_inbound_pkt(struct sk_buff *skb, unsigned int protoff,
347355
if (info->pns_call_id != pcid)
348356
goto invalid;
349357

350-
pr_debug("%s, PCID=%X\n", pptp_msg_name[msg], ntohs(pcid));
358+
pr_debug("%s, PCID=%X\n", pptp_msg_name(msg), ntohs(pcid));
351359
info->cstate = PPTP_CALL_IN_CONF;
352360

353361
/* we expect a GRE connection from PAC to PNS */
@@ -357,7 +365,7 @@ pptp_inbound_pkt(struct sk_buff *skb, unsigned int protoff,
357365
case PPTP_CALL_DISCONNECT_NOTIFY:
358366
/* server confirms disconnect */
359367
cid = pptpReq->disc.callID;
360-
pr_debug("%s, CID=%X\n", pptp_msg_name[msg], ntohs(cid));
368+
pr_debug("%s, CID=%X\n", pptp_msg_name(msg), ntohs(cid));
361369
info->cstate = PPTP_CALL_NONE;
362370

363371
/* untrack this call id, unexpect GRE packets */
@@ -384,7 +392,7 @@ pptp_inbound_pkt(struct sk_buff *skb, unsigned int protoff,
384392
invalid:
385393
pr_debug("invalid %s: type=%d cid=%u pcid=%u "
386394
"cstate=%d sstate=%d pns_cid=%u pac_cid=%u\n",
387-
msg <= PPTP_MSG_MAX ? pptp_msg_name[msg] : pptp_msg_name[0],
395+
pptp_msg_name(msg),
388396
msg, ntohs(cid), ntohs(pcid), info->cstate, info->sstate,
389397
ntohs(info->pns_call_id), ntohs(info->pac_call_id));
390398
return NF_ACCEPT;
@@ -404,7 +412,7 @@ pptp_outbound_pkt(struct sk_buff *skb, unsigned int protoff,
404412
typeof(nf_nat_pptp_hook_outbound) nf_nat_pptp_outbound;
405413

406414
msg = ntohs(ctlh->messageType);
407-
pr_debug("outbound control message %s\n", pptp_msg_name[msg]);
415+
pr_debug("outbound control message %s\n", pptp_msg_name(msg));
408416

409417
switch (msg) {
410418
case PPTP_START_SESSION_REQUEST:
@@ -426,7 +434,7 @@ pptp_outbound_pkt(struct sk_buff *skb, unsigned int protoff,
426434
info->cstate = PPTP_CALL_OUT_REQ;
427435
/* track PNS call id */
428436
cid = pptpReq->ocreq.callID;
429-
pr_debug("%s, CID=%X\n", pptp_msg_name[msg], ntohs(cid));
437+
pr_debug("%s, CID=%X\n", pptp_msg_name(msg), ntohs(cid));
430438
info->pns_call_id = cid;
431439
break;
432440

@@ -440,7 +448,7 @@ pptp_outbound_pkt(struct sk_buff *skb, unsigned int protoff,
440448
pcid = pptpReq->icack.peersCallID;
441449
if (info->pac_call_id != pcid)
442450
goto invalid;
443-
pr_debug("%s, CID=%X PCID=%X\n", pptp_msg_name[msg],
451+
pr_debug("%s, CID=%X PCID=%X\n", pptp_msg_name(msg),
444452
ntohs(cid), ntohs(pcid));
445453

446454
if (pptpReq->icack.resultCode == PPTP_INCALL_ACCEPT) {
@@ -480,7 +488,7 @@ pptp_outbound_pkt(struct sk_buff *skb, unsigned int protoff,
480488
invalid:
481489
pr_debug("invalid %s: type=%d cid=%u pcid=%u "
482490
"cstate=%d sstate=%d pns_cid=%u pac_cid=%u\n",
483-
msg <= PPTP_MSG_MAX ? pptp_msg_name[msg] : pptp_msg_name[0],
491+
pptp_msg_name(msg),
484492
msg, ntohs(cid), ntohs(pcid), info->cstate, info->sstate,
485493
ntohs(info->pns_call_id), ntohs(info->pac_call_id));
486494
return NF_ACCEPT;

net/netfilter/nfnetlink_cthelper.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@ nfnl_cthelper_from_nlattr(struct nlattr *attr, struct nf_conn *ct)
103103
if (help->helper->data_len == 0)
104104
return -EINVAL;
105105

106-
nla_memcpy(help->data, nla_data(attr), sizeof(help->data));
106+
nla_memcpy(help->data, attr, sizeof(help->data));
107107
return 0;
108108
}
109109

@@ -240,6 +240,7 @@ nfnl_cthelper_create(const struct nlattr * const tb[],
240240
ret = -ENOMEM;
241241
goto err2;
242242
}
243+
helper->data_len = size;
243244

244245
helper->flags |= NF_CT_HELPER_F_USERSPACE;
245246
memcpy(&helper->tuple, tuple, sizeof(struct nf_conntrack_tuple));

0 commit comments

Comments
 (0)