Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit e11607aa authored by David S. Miller's avatar David S. Miller
Browse files


Pablo Neira Ayuso says:

====================
Netfilter fixes for net

The following patchset contains Netfilter fixes for your net tree, a
rather large batch of fixes targeted to nf_tables, conntrack and bridge
netfilter. More specifically, they are:

1) Don't track fragmented packets if the socket option IP_NODEFRAG is set.
   From Florian Westphal.

2) SCTP protocol tracker assumes that ICMP error messages contain the
   checksum field, what results in packet drops. From Ying Xue.

3) Fix inconsistent handling of AH traffic from nf_tables.

4) Fix new bitmap set representation with big endian. Fix mismatches in
   nf_tables due to incorrect big endian handling too. Both patches
   from Liping Zhang.

5) Bridge netfilter doesn't honor maximum fragment size field, cap to
   largest fragment seen. From Florian Westphal.

6) Fake conntrack entry needs to be aligned to 8 bytes since the 3 LSB
   bits are now used to store the ctinfo. From Steven Rostedt.

7) Fix element comments with the bitmap set type. Revert the flush
   field in the nft_set_iter structure, not required anymore after
   fixing up element comments.

8) Missing error on invalid conntrack direction from nft_ct, also from
   Liping Zhang.
====================

Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 3d20f1f7 4494dbc6
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -244,7 +244,7 @@ extern s32 (*nf_ct_nat_offset)(const struct nf_conn *ct,
			       u32 seq);

/* Fake conntrack entry for untracked connections */
DECLARE_PER_CPU(struct nf_conn, nf_conntrack_untracked);
DECLARE_PER_CPU_ALIGNED(struct nf_conn, nf_conntrack_untracked);
static inline struct nf_conn *nf_ct_untracked_get(void)
{
	return raw_cpu_ptr(&nf_conntrack_untracked);
+29 −1
Original line number Diff line number Diff line
@@ -103,6 +103,35 @@ struct nft_regs {
	};
};

/* Store/load an u16 or u8 integer to/from the u32 data register.
 *
 * Note, when using concatenations, register allocation happens at 32-bit
 * level. So for store instruction, pad the rest part with zero to avoid
 * garbage values.
 */

static inline void nft_reg_store16(u32 *dreg, u16 val)
{
	*dreg = 0;
	*(u16 *)dreg = val;
}

static inline void nft_reg_store8(u32 *dreg, u8 val)
{
	*dreg = 0;
	*(u8 *)dreg = val;
}

static inline u16 nft_reg_load16(u32 *sreg)
{
	return *(u16 *)sreg;
}

static inline u8 nft_reg_load8(u32 *sreg)
{
	return *(u8 *)sreg;
}

static inline void nft_data_copy(u32 *dst, const struct nft_data *src,
				 unsigned int len)
{
@@ -203,7 +232,6 @@ struct nft_set_elem {
struct nft_set;
struct nft_set_iter {
	u8		genmask;
	bool		flush;
	unsigned int	count;
	unsigned int	skip;
	int		err;
+4 −2
Original line number Diff line number Diff line
@@ -9,12 +9,13 @@ nft_set_pktinfo_ipv6(struct nft_pktinfo *pkt,
		     struct sk_buff *skb,
		     const struct nf_hook_state *state)
{
	unsigned int flags = IP6_FH_F_AUTH;
	int protohdr, thoff = 0;
	unsigned short frag_off;

	nft_set_pktinfo(pkt, skb, state);

	protohdr = ipv6_find_hdr(pkt->skb, &thoff, -1, &frag_off, NULL);
	protohdr = ipv6_find_hdr(pkt->skb, &thoff, -1, &frag_off, &flags);
	if (protohdr < 0) {
		nft_set_pktinfo_proto_unspec(pkt, skb);
		return;
@@ -32,6 +33,7 @@ __nft_set_pktinfo_ipv6_validate(struct nft_pktinfo *pkt,
				const struct nf_hook_state *state)
{
#if IS_ENABLED(CONFIG_IPV6)
	unsigned int flags = IP6_FH_F_AUTH;
	struct ipv6hdr *ip6h, _ip6h;
	unsigned int thoff = 0;
	unsigned short frag_off;
@@ -50,7 +52,7 @@ __nft_set_pktinfo_ipv6_validate(struct nft_pktinfo *pkt,
	if (pkt_len + sizeof(*ip6h) > skb->len)
		return -1;

	protohdr = ipv6_find_hdr(pkt->skb, &thoff, -1, &frag_off, NULL);
	protohdr = ipv6_find_hdr(pkt->skb, &thoff, -1, &frag_off, &flags);
	if (protohdr < 0)
		return -1;

+7 −5
Original line number Diff line number Diff line
@@ -706,18 +706,20 @@ static unsigned int nf_bridge_mtu_reduction(const struct sk_buff *skb)

static int br_nf_dev_queue_xmit(struct net *net, struct sock *sk, struct sk_buff *skb)
{
	struct nf_bridge_info *nf_bridge;
	unsigned int mtu_reserved;
	struct nf_bridge_info *nf_bridge = nf_bridge_info_get(skb);
	unsigned int mtu, mtu_reserved;

	mtu_reserved = nf_bridge_mtu_reduction(skb);
	mtu = skb->dev->mtu;

	if (nf_bridge->frag_max_size && nf_bridge->frag_max_size < mtu)
		mtu = nf_bridge->frag_max_size;

	if (skb_is_gso(skb) || skb->len + mtu_reserved <= skb->dev->mtu) {
	if (skb_is_gso(skb) || skb->len + mtu_reserved <= mtu) {
		nf_bridge_info_free(skb);
		return br_dev_queue_push_xmit(net, sk, skb);
	}

	nf_bridge = nf_bridge_info_get(skb);

	/* This is wrong! We should preserve the original fragment
	 * boundaries by preserving frag_list rather than refragmenting.
	 */
+4 −0
Original line number Diff line number Diff line
@@ -165,6 +165,10 @@ static unsigned int ipv4_conntrack_local(void *priv,
	if (skb->len < sizeof(struct iphdr) ||
	    ip_hdrlen(skb) < sizeof(struct iphdr))
		return NF_ACCEPT;

	if (ip_is_fragment(ip_hdr(skb))) /* IP_NODEFRAG setsockopt set */
		return NF_ACCEPT;

	return nf_conntrack_in(state->net, PF_INET, state->hook, skb);
}

Loading