Skip to content

Commit 894d084

Browse files
committed
Merge git://git.kernel.org/pub/scm/linux/kernel/git/pablo/nf-next
Pablo Neira Ayuso says: ==================== Netfilter updates for net-next The following patchset contains Netfilter updates for net-next: 1) Use array_size() in ebtables, from Gustavo A. R. Silva. 2) Attach IPS_ASSURED to internal UDP stream state, reported by Maciej Zenczykowski. 3) Add NFT_META_IFTYPE to match on the interface type either from ingress or egress. 4) Generalize pktinfo->tprot_set to flags field. 5) Allow to match on inner headers / payload data. ==================== Signed-off-by: David S. Miller <[email protected]>
2 parents 2aec919 + c46b38d commit 894d084

File tree

10 files changed

+94
-23
lines changed

10 files changed

+94
-23
lines changed

include/net/netfilter/nf_tables.h

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,13 +21,19 @@ struct module;
2121

2222
#define NFT_JUMP_STACK_SIZE 16
2323

24+
enum {
25+
NFT_PKTINFO_L4PROTO = (1 << 0),
26+
NFT_PKTINFO_INNER = (1 << 1),
27+
};
28+
2429
struct nft_pktinfo {
2530
struct sk_buff *skb;
2631
const struct nf_hook_state *state;
27-
bool tprot_set;
32+
u8 flags;
2833
u8 tprot;
2934
u16 fragoff;
3035
unsigned int thoff;
36+
unsigned int inneroff;
3137
};
3238

3339
static inline struct sock *nft_sk(const struct nft_pktinfo *pkt)
@@ -75,7 +81,7 @@ static inline void nft_set_pktinfo(struct nft_pktinfo *pkt,
7581

7682
static inline void nft_set_pktinfo_unspec(struct nft_pktinfo *pkt)
7783
{
78-
pkt->tprot_set = false;
84+
pkt->flags = 0;
7985
pkt->tprot = 0;
8086
pkt->thoff = 0;
8187
pkt->fragoff = 0;

include/net/netfilter/nf_tables_ipv4.h

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ static inline void nft_set_pktinfo_ipv4(struct nft_pktinfo *pkt)
1010
struct iphdr *ip;
1111

1212
ip = ip_hdr(pkt->skb);
13-
pkt->tprot_set = true;
13+
pkt->flags = NFT_PKTINFO_L4PROTO;
1414
pkt->tprot = ip->protocol;
1515
pkt->thoff = ip_hdrlen(pkt->skb);
1616
pkt->fragoff = ntohs(ip->frag_off) & IP_OFFSET;
@@ -36,7 +36,7 @@ static inline int __nft_set_pktinfo_ipv4_validate(struct nft_pktinfo *pkt)
3636
else if (len < thoff)
3737
return -1;
3838

39-
pkt->tprot_set = true;
39+
pkt->flags = NFT_PKTINFO_L4PROTO;
4040
pkt->tprot = iph->protocol;
4141
pkt->thoff = thoff;
4242
pkt->fragoff = ntohs(iph->frag_off) & IP_OFFSET;
@@ -71,7 +71,7 @@ static inline int nft_set_pktinfo_ipv4_ingress(struct nft_pktinfo *pkt)
7171
goto inhdr_error;
7272
}
7373

74-
pkt->tprot_set = true;
74+
pkt->flags = NFT_PKTINFO_L4PROTO;
7575
pkt->tprot = iph->protocol;
7676
pkt->thoff = thoff;
7777
pkt->fragoff = ntohs(iph->frag_off) & IP_OFFSET;
@@ -82,4 +82,5 @@ static inline int nft_set_pktinfo_ipv4_ingress(struct nft_pktinfo *pkt)
8282
__IP_INC_STATS(nft_net(pkt), IPSTATS_MIB_INHDRERRORS);
8383
return -1;
8484
}
85+
8586
#endif

include/net/netfilter/nf_tables_ipv6.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ static inline void nft_set_pktinfo_ipv6(struct nft_pktinfo *pkt)
1818
return;
1919
}
2020

21-
pkt->tprot_set = true;
21+
pkt->flags = NFT_PKTINFO_L4PROTO;
2222
pkt->tprot = protohdr;
2323
pkt->thoff = thoff;
2424
pkt->fragoff = frag_off;
@@ -50,7 +50,7 @@ static inline int __nft_set_pktinfo_ipv6_validate(struct nft_pktinfo *pkt)
5050
if (protohdr < 0)
5151
return -1;
5252

53-
pkt->tprot_set = true;
53+
pkt->flags = NFT_PKTINFO_L4PROTO;
5454
pkt->tprot = protohdr;
5555
pkt->thoff = thoff;
5656
pkt->fragoff = frag_off;
@@ -96,7 +96,7 @@ static inline int nft_set_pktinfo_ipv6_ingress(struct nft_pktinfo *pkt)
9696
if (protohdr < 0)
9797
goto inhdr_error;
9898

99-
pkt->tprot_set = true;
99+
pkt->flags = NFT_PKTINFO_L4PROTO;
100100
pkt->tprot = protohdr;
101101
pkt->thoff = thoff;
102102
pkt->fragoff = frag_off;

include/uapi/linux/netfilter/nf_tables.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -753,11 +753,13 @@ enum nft_dynset_attributes {
753753
* @NFT_PAYLOAD_LL_HEADER: link layer header
754754
* @NFT_PAYLOAD_NETWORK_HEADER: network header
755755
* @NFT_PAYLOAD_TRANSPORT_HEADER: transport header
756+
* @NFT_PAYLOAD_INNER_HEADER: inner header / payload
756757
*/
757758
enum nft_payload_bases {
758759
NFT_PAYLOAD_LL_HEADER,
759760
NFT_PAYLOAD_NETWORK_HEADER,
760761
NFT_PAYLOAD_TRANSPORT_HEADER,
762+
NFT_PAYLOAD_INNER_HEADER,
761763
};
762764

763765
/**
@@ -896,7 +898,8 @@ enum nft_meta_keys {
896898
NFT_META_OIF,
897899
NFT_META_IIFNAME,
898900
NFT_META_OIFNAME,
899-
NFT_META_IIFTYPE,
901+
NFT_META_IFTYPE,
902+
#define NFT_META_IIFTYPE NFT_META_IFTYPE
900903
NFT_META_OIFTYPE,
901904
NFT_META_SKUID,
902905
NFT_META_SKGID,
@@ -923,6 +926,7 @@ enum nft_meta_keys {
923926
NFT_META_TIME_HOUR,
924927
NFT_META_SDIF,
925928
NFT_META_SDIFNAME,
929+
__NFT_META_IIFTYPE,
926930
};
927931

928932
/**

net/bridge/netfilter/ebtables.c

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1073,7 +1073,7 @@ static int do_replace_finish(struct net *net, struct ebt_replace *repl,
10731073
*/
10741074
if (repl->num_counters &&
10751075
copy_to_user(repl->counters, counterstmp,
1076-
repl->num_counters * sizeof(struct ebt_counter))) {
1076+
array_size(repl->num_counters, sizeof(struct ebt_counter)))) {
10771077
/* Silent error, can't fail, new table is already in place */
10781078
net_warn_ratelimited("ebtables: counters copy to user failed while replacing table\n");
10791079
}
@@ -1401,7 +1401,8 @@ static int do_update_counters(struct net *net, const char *name,
14011401
goto unlock_mutex;
14021402
}
14031403

1404-
if (copy_from_user(tmp, counters, num_counters * sizeof(*counters))) {
1404+
if (copy_from_user(tmp, counters,
1405+
array_size(num_counters, sizeof(*counters)))) {
14051406
ret = -EFAULT;
14061407
goto unlock_mutex;
14071408
}
@@ -1534,7 +1535,7 @@ static int copy_counters_to_user(struct ebt_table *t,
15341535
write_unlock_bh(&t->lock);
15351536

15361537
if (copy_to_user(user, counterstmp,
1537-
nentries * sizeof(struct ebt_counter)))
1538+
array_size(nentries, sizeof(struct ebt_counter))))
15381539
ret = -EFAULT;
15391540
vfree(counterstmp);
15401541
return ret;

net/netfilter/nf_conntrack_proto_udp.c

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -104,10 +104,13 @@ int nf_conntrack_udp_packet(struct nf_conn *ct,
104104
*/
105105
if (test_bit(IPS_SEEN_REPLY_BIT, &ct->status)) {
106106
unsigned long extra = timeouts[UDP_CT_UNREPLIED];
107+
bool stream = false;
107108

108109
/* Still active after two seconds? Extend timeout. */
109-
if (time_after(jiffies, ct->proto.udp.stream_ts))
110+
if (time_after(jiffies, ct->proto.udp.stream_ts)) {
110111
extra = timeouts[UDP_CT_REPLIED];
112+
stream = true;
113+
}
111114

112115
nf_ct_refresh_acct(ct, ctinfo, skb, extra);
113116

@@ -116,7 +119,7 @@ int nf_conntrack_udp_packet(struct nf_conn *ct,
116119
return NF_ACCEPT;
117120

118121
/* Also, more likely to be important, and not a probe */
119-
if (!test_and_set_bit(IPS_ASSURED_BIT, &ct->status))
122+
if (stream && !test_and_set_bit(IPS_ASSURED_BIT, &ct->status))
120123
nf_conntrack_event_cache(IPCT_ASSURED, ct);
121124
} else {
122125
nf_ct_refresh_acct(ct, ctinfo, skb, timeouts[UDP_CT_UNREPLIED]);

net/netfilter/nf_tables_core.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ static bool nft_payload_fast_eval(const struct nft_expr *expr,
7979
if (priv->base == NFT_PAYLOAD_NETWORK_HEADER)
8080
ptr = skb_network_header(skb);
8181
else {
82-
if (!pkt->tprot_set)
82+
if (!(pkt->flags & NFT_PKTINFO_L4PROTO))
8383
return false;
8484
ptr = skb_network_header(skb) + nft_thoff(pkt);
8585
}

net/netfilter/nf_tables_trace.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -113,13 +113,13 @@ static int nf_trace_fill_pkt_info(struct sk_buff *nlskb,
113113
int off = skb_network_offset(skb);
114114
unsigned int len, nh_end;
115115

116-
nh_end = pkt->tprot_set ? nft_thoff(pkt) : skb->len;
116+
nh_end = pkt->flags & NFT_PKTINFO_L4PROTO ? nft_thoff(pkt) : skb->len;
117117
len = min_t(unsigned int, nh_end - skb_network_offset(skb),
118118
NFT_TRACETYPE_NETWORK_HSIZE);
119119
if (trace_fill_header(nlskb, NFTA_TRACE_NETWORK_HEADER, skb, off, len))
120120
return -1;
121121

122-
if (pkt->tprot_set) {
122+
if (pkt->flags & NFT_PKTINFO_L4PROTO) {
123123
len = min_t(unsigned int, skb->len - nft_thoff(pkt),
124124
NFT_TRACETYPE_TRANSPORT_HSIZE);
125125
if (trace_fill_header(nlskb, NFTA_TRACE_TRANSPORT_HEADER, skb,

net/netfilter/nft_meta.c

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -244,7 +244,11 @@ static bool nft_meta_get_eval_ifname(enum nft_meta_keys key, u32 *dest,
244244
case NFT_META_OIF:
245245
nft_meta_store_ifindex(dest, nft_out(pkt));
246246
break;
247-
case NFT_META_IIFTYPE:
247+
case NFT_META_IFTYPE:
248+
if (!nft_meta_store_iftype(dest, pkt->skb->dev))
249+
return false;
250+
break;
251+
case __NFT_META_IIFTYPE:
248252
if (!nft_meta_store_iftype(dest, nft_in(pkt)))
249253
return false;
250254
break;
@@ -329,7 +333,7 @@ void nft_meta_get_eval(const struct nft_expr *expr,
329333
nft_reg_store8(dest, nft_pf(pkt));
330334
break;
331335
case NFT_META_L4PROTO:
332-
if (!pkt->tprot_set)
336+
if (!(pkt->flags & NFT_PKTINFO_L4PROTO))
333337
goto err;
334338
nft_reg_store8(dest, pkt->tprot);
335339
break;

net/netfilter/nft_payload.c

Lines changed: 56 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
#include <linux/icmpv6.h>
2323
#include <linux/ip.h>
2424
#include <linux/ipv6.h>
25+
#include <linux/ip.h>
2526
#include <net/sctp/checksum.h>
2627

2728
static bool nft_payload_rebuild_vlan_hdr(const struct sk_buff *skb, int mac_off,
@@ -79,6 +80,45 @@ nft_payload_copy_vlan(u32 *d, const struct sk_buff *skb, u8 offset, u8 len)
7980
return skb_copy_bits(skb, offset + mac_off, dst_u8, len) == 0;
8081
}
8182

83+
static int __nft_payload_inner_offset(struct nft_pktinfo *pkt)
84+
{
85+
unsigned int thoff = nft_thoff(pkt);
86+
87+
if (!(pkt->flags & NFT_PKTINFO_L4PROTO))
88+
return -1;
89+
90+
switch (pkt->tprot) {
91+
case IPPROTO_UDP:
92+
pkt->inneroff = thoff + sizeof(struct udphdr);
93+
break;
94+
case IPPROTO_TCP: {
95+
struct tcphdr *th, _tcph;
96+
97+
th = skb_header_pointer(pkt->skb, thoff, sizeof(_tcph), &_tcph);
98+
if (!th)
99+
return -1;
100+
101+
pkt->inneroff = thoff + __tcp_hdrlen(th);
102+
}
103+
break;
104+
default:
105+
return -1;
106+
}
107+
108+
pkt->flags |= NFT_PKTINFO_INNER;
109+
110+
return 0;
111+
}
112+
113+
static int nft_payload_inner_offset(const struct nft_pktinfo *pkt)
114+
{
115+
if (!(pkt->flags & NFT_PKTINFO_INNER) &&
116+
__nft_payload_inner_offset((struct nft_pktinfo *)pkt) < 0)
117+
return -1;
118+
119+
return pkt->inneroff;
120+
}
121+
82122
void nft_payload_eval(const struct nft_expr *expr,
83123
struct nft_regs *regs,
84124
const struct nft_pktinfo *pkt)
@@ -108,10 +148,15 @@ void nft_payload_eval(const struct nft_expr *expr,
108148
offset = skb_network_offset(skb);
109149
break;
110150
case NFT_PAYLOAD_TRANSPORT_HEADER:
111-
if (!pkt->tprot_set)
151+
if (!(pkt->flags & NFT_PKTINFO_L4PROTO))
112152
goto err;
113153
offset = nft_thoff(pkt);
114154
break;
155+
case NFT_PAYLOAD_INNER_HEADER:
156+
offset = nft_payload_inner_offset(pkt);
157+
if (offset < 0)
158+
goto err;
159+
break;
115160
default:
116161
BUG();
117162
}
@@ -610,10 +655,15 @@ static void nft_payload_set_eval(const struct nft_expr *expr,
610655
offset = skb_network_offset(skb);
611656
break;
612657
case NFT_PAYLOAD_TRANSPORT_HEADER:
613-
if (!pkt->tprot_set)
658+
if (!(pkt->flags & NFT_PKTINFO_L4PROTO))
614659
goto err;
615660
offset = nft_thoff(pkt);
616661
break;
662+
case NFT_PAYLOAD_INNER_HEADER:
663+
offset = nft_payload_inner_offset(pkt);
664+
if (offset < 0)
665+
goto err;
666+
break;
617667
default:
618668
BUG();
619669
}
@@ -622,7 +672,8 @@ static void nft_payload_set_eval(const struct nft_expr *expr,
622672
offset += priv->offset;
623673

624674
if ((priv->csum_type == NFT_PAYLOAD_CSUM_INET || priv->csum_flags) &&
625-
(priv->base != NFT_PAYLOAD_TRANSPORT_HEADER ||
675+
((priv->base != NFT_PAYLOAD_TRANSPORT_HEADER &&
676+
priv->base != NFT_PAYLOAD_INNER_HEADER) ||
626677
skb->ip_summed != CHECKSUM_PARTIAL)) {
627678
fsum = skb_checksum(skb, offset, priv->len, 0);
628679
tsum = csum_partial(src, priv->len, 0);
@@ -741,6 +792,7 @@ nft_payload_select_ops(const struct nft_ctx *ctx,
741792
case NFT_PAYLOAD_LL_HEADER:
742793
case NFT_PAYLOAD_NETWORK_HEADER:
743794
case NFT_PAYLOAD_TRANSPORT_HEADER:
795+
case NFT_PAYLOAD_INNER_HEADER:
744796
break;
745797
default:
746798
return ERR_PTR(-EOPNOTSUPP);
@@ -759,7 +811,7 @@ nft_payload_select_ops(const struct nft_ctx *ctx,
759811
len = ntohl(nla_get_be32(tb[NFTA_PAYLOAD_LEN]));
760812

761813
if (len <= 4 && is_power_of_2(len) && IS_ALIGNED(offset, len) &&
762-
base != NFT_PAYLOAD_LL_HEADER)
814+
base != NFT_PAYLOAD_LL_HEADER && base != NFT_PAYLOAD_INNER_HEADER)
763815
return &nft_payload_fast_ops;
764816
else
765817
return &nft_payload_ops;

0 commit comments

Comments
 (0)