All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] net/ipv4/ip_fragment:fix missing Flags reserved bit set in iphdr
@ 2021-05-06 14:59 meijusan
  2021-05-07 22:59 ` Jakub Kicinski
  0 siblings, 1 reply; 5+ messages in thread
From: meijusan @ 2021-05-06 14:59 UTC (permalink / raw)
  To: davem, yoshfuji, dsahern, kuba; +Cc: netdev, linux-kernel, meijusan

ip frag with the iphdr flags reserved bit set,via router,ip frag reasm or
fragment,causing the reserved bit is reset to zero.

Keep reserved bit set is not modified in ip frag  defrag or fragment.

Signed-off-by: meijusan <meijusan@163.com>
---
 include/net/ip.h       |  3 ++-
 net/ipv4/ip_fragment.c |  9 +++++++++
 net/ipv4/ip_output.c   | 14 ++++++++++++++
 3 files changed, 25 insertions(+), 1 deletion(-)

diff --git a/include/net/ip.h b/include/net/ip.h
index e20874059f82..ae0c75fca61d 100644
--- a/include/net/ip.h
+++ b/include/net/ip.h
@@ -134,7 +134,7 @@ struct ip_ra_chain {
 #define IP_DF		0x4000		/* Flag: "Don't Fragment"	*/
 #define IP_MF		0x2000		/* Flag: "More Fragments"	*/
 #define IP_OFFSET	0x1FFF		/* "Fragment Offset" part	*/
-
+#define IP_EVIL	0x8000		/* Flag: "reserve bit"	*/
 #define IP_FRAG_TIME	(30 * HZ)		/* fragment lifetime	*/
 
 struct msghdr;
@@ -194,6 +194,7 @@ struct ip_frag_state {
 	int		offset;
 	int		ptr;
 	__be16		not_last_frag;
+	bool		ip_evil;
 };
 
 void ip_frag_init(struct sk_buff *skb, unsigned int hlen, unsigned int ll_rs,
diff --git a/net/ipv4/ip_fragment.c b/net/ipv4/ip_fragment.c
index cfeb8890f94e..52eb53007c48 100644
--- a/net/ipv4/ip_fragment.c
+++ b/net/ipv4/ip_fragment.c
@@ -62,6 +62,7 @@ struct ipq {
 	struct inet_frag_queue q;
 
 	u8		ecn; /* RFC3168 support */
+	bool		ip_evil; /*frag with evil bit set */
 	u16		max_df_size; /* largest frag with DF set seen */
 	int             iif;
 	unsigned int    rid;
@@ -88,6 +89,7 @@ static void ip4_frag_init(struct inet_frag_queue *q, const void *a)
 
 	q->key.v4 = *key;
 	qp->ecn = 0;
+	qp->ip_evil = false;
 	qp->peer = q->fqdir->max_dist ?
 		inet_getpeer_v4(net->ipv4.peers, key->saddr, key->vif, 1) :
 		NULL;
@@ -278,6 +280,7 @@ static int ip_frag_queue(struct ipq *qp, struct sk_buff *skb)
 	unsigned int fragsize;
 	int err = -ENOENT;
 	u8 ecn;
+	bool  ip_evil;
 
 	if (qp->q.flags & INET_FRAG_COMPLETE)
 		goto err;
@@ -295,6 +298,7 @@ static int ip_frag_queue(struct ipq *qp, struct sk_buff *skb)
 	offset &= IP_OFFSET;
 	offset <<= 3;		/* offset is in 8-byte chunks */
 	ihl = ip_hdrlen(skb);
+	ip_evil = flags & IP_EVIL ?  true : false;
 
 	/* Determine the position of this fragment. */
 	end = offset + skb->len - skb_network_offset(skb) - ihl;
@@ -350,6 +354,7 @@ static int ip_frag_queue(struct ipq *qp, struct sk_buff *skb)
 	qp->q.stamp = skb->tstamp;
 	qp->q.meat += skb->len;
 	qp->ecn |= ecn;
+	qp->ip_evil = ip_evil;
 	add_frag_mem_limit(qp->q.fqdir, skb->truesize);
 	if (offset == 0)
 		qp->q.flags |= INET_FRAG_FIRST_IN;
@@ -451,6 +456,10 @@ static int ip_frag_reasm(struct ipq *qp, struct sk_buff *skb,
 		iph->frag_off = 0;
 	}
 
+	/*when ip or bridge forward, keep the origin evil bit set*/
+	if (qp->ip_evil)
+		iph->frag_off |= htons(IP_EVIL);
+
 	ip_send_check(iph);
 
 	__IP_INC_STATS(net, IPSTATS_MIB_REASMOKS);
diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c
index 3aab53beb4ea..a8a9a0af29b2 100644
--- a/net/ipv4/ip_output.c
+++ b/net/ipv4/ip_output.c
@@ -610,6 +610,8 @@ void ip_fraglist_init(struct sk_buff *skb, struct iphdr *iph,
 	skb->len = first_len;
 	iph->tot_len = htons(first_len);
 	iph->frag_off = htons(IP_MF);
+	if (ntohs(iph->frag_off) & IP_EVIL)
+		iph->frag_off |= htons(IP_EVIL);
 	ip_send_check(iph);
 }
 EXPORT_SYMBOL(ip_fraglist_init);
@@ -631,6 +633,7 @@ void ip_fraglist_prepare(struct sk_buff *skb, struct ip_fraglist_iter *iter)
 	unsigned int hlen = iter->hlen;
 	struct iphdr *iph = iter->iph;
 	struct sk_buff *frag;
+	bool ip_evil = false;
 
 	frag = iter->frag;
 	frag->ip_summed = CHECKSUM_NONE;
@@ -638,6 +641,8 @@ void ip_fraglist_prepare(struct sk_buff *skb, struct ip_fraglist_iter *iter)
 	__skb_push(frag, hlen);
 	skb_reset_network_header(frag);
 	memcpy(skb_network_header(frag), iph, hlen);
+	if (ntohs(iph->frag_off) & IP_EVIL)
+		ip_evil = true;
 	iter->iph = ip_hdr(frag);
 	iph = iter->iph;
 	iph->tot_len = htons(frag->len);
@@ -646,6 +651,10 @@ void ip_fraglist_prepare(struct sk_buff *skb, struct ip_fraglist_iter *iter)
 	iph->frag_off = htons(iter->offset >> 3);
 	if (frag->next)
 		iph->frag_off |= htons(IP_MF);
+
+	if (ip_evil)
+		iph->frag_off |= htons(IP_EVIL);
+
 	/* Ready, complete checksum */
 	ip_send_check(iph);
 }
@@ -667,6 +676,7 @@ void ip_frag_init(struct sk_buff *skb, unsigned int hlen,
 
 	state->offset = (ntohs(iph->frag_off) & IP_OFFSET) << 3;
 	state->not_last_frag = iph->frag_off & htons(IP_MF);
+	state->ip_evil = (ntohs(iph->frag_off) & IP_EVIL) ? true : false;
 }
 EXPORT_SYMBOL(ip_frag_init);
 
@@ -752,6 +762,10 @@ struct sk_buff *ip_frag_next(struct sk_buff *skb, struct ip_frag_state *state)
 	 */
 	if (state->left > 0 || state->not_last_frag)
 		iph->frag_off |= htons(IP_MF);
+
+	if (state->ip_evil)
+		iph->frag_off |= htons(IP_EVIL);
+
 	state->ptr += len;
 	state->offset += len;
 
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 5+ messages in thread

* Re: [PATCH] net/ipv4/ip_fragment:fix missing Flags reserved bit set in iphdr
  2021-05-06 14:59 [PATCH] net/ipv4/ip_fragment:fix missing Flags reserved bit set in iphdr meijusan
@ 2021-05-07 22:59 ` Jakub Kicinski
  2021-05-11  1:18   ` meijusan
  0 siblings, 1 reply; 5+ messages in thread
From: Jakub Kicinski @ 2021-05-07 22:59 UTC (permalink / raw)
  To: meijusan; +Cc: davem, yoshfuji, dsahern, netdev, linux-kernel

On Thu,  6 May 2021 22:59:05 +0800 meijusan wrote:
> ip frag with the iphdr flags reserved bit set,via router,ip frag reasm or
> fragment,causing the reserved bit is reset to zero.
> 
> Keep reserved bit set is not modified in ip frag  defrag or fragment.
> 
> Signed-off-by: meijusan <meijusan@163.com>

Could you please provide more background on why we'd want to do this?
Preferably with references to relevant (non-April Fools' Day) RFCs.

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re:Re: [PATCH] net/ipv4/ip_fragment:fix missing Flags reserved bit set in iphdr
  2021-05-07 22:59 ` Jakub Kicinski
@ 2021-05-11  1:18   ` meijusan
  2021-05-11  3:05     ` David Ahern
  0 siblings, 1 reply; 5+ messages in thread
From: meijusan @ 2021-05-11  1:18 UTC (permalink / raw)
  To: Jakub Kicinski; +Cc: davem, yoshfuji, dsahern, netdev, linux-kernel


At 2021-05-08 06:59:00, "Jakub Kicinski" <kuba@kernel.org> wrote:
>On Thu,  6 May 2021 22:59:05 +0800 meijusan wrote:
>> ip frag with the iphdr flags reserved bit set,via router,ip frag reasm or
>> fragment,causing the reserved bit is reset to zero.
>> 
>> Keep reserved bit set is not modified in ip frag  defrag or fragment.
>> 
>> Signed-off-by: meijusan <meijusan@163.com>
>
>Could you please provide more background on why we'd want to do this?

>Preferably with references to relevant (non-April Fools' Day) RFCs.

[background]
the Simple network usage scenarios: the one PC software<--->linux router(L3)/linux bridege(L2,bridge-nf-call-iptables)<--->the other PC software
1)the PC software send the ip packet with the iphdr flags reserved bit is set, when ip packet(not fragments ) via the one linux router/linux bridge,and the iphdr flags reserved bit is not modified;
2)but the ip fragments via router,the linux IP reassembly or fragmentation ,causing the reserved bit is reset to zero,Which leads to The other PC software depending on the reserved bit set  process the Packet failed.
[rfc]
RFC791
Bit 0: reserved, must be zero
RFC3514
Introduction This bit , but The scene seems different from us,we expect Keep reserved bit set is not modified when forward the linux router






^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH] net/ipv4/ip_fragment:fix missing Flags reserved bit set in iphdr
  2021-05-11  1:18   ` meijusan
@ 2021-05-11  3:05     ` David Ahern
  2021-05-12  4:43       ` meijusan
  0 siblings, 1 reply; 5+ messages in thread
From: David Ahern @ 2021-05-11  3:05 UTC (permalink / raw)
  To: meijusan, Jakub Kicinski; +Cc: davem, yoshfuji, dsahern, netdev, linux-kernel

On 5/10/21 7:18 PM, meijusan wrote:
> 
> At 2021-05-08 06:59:00, "Jakub Kicinski" <kuba@kernel.org> wrote:
>> On Thu,  6 May 2021 22:59:05 +0800 meijusan wrote:
>>> ip frag with the iphdr flags reserved bit set,via router,ip frag reasm or
>>> fragment,causing the reserved bit is reset to zero.
>>>
>>> Keep reserved bit set is not modified in ip frag  defrag or fragment.
>>>
>>> Signed-off-by: meijusan <meijusan@163.com>
>>
>> Could you please provide more background on why we'd want to do this?
> 
>> Preferably with references to relevant (non-April Fools' Day) RFCs.
> 
> [background]
> the Simple network usage scenarios: the one PC software<--->linux router(L3)/linux bridege(L2,bridge-nf-call-iptables)<--->the other PC software
> 1)the PC software send the ip packet with the iphdr flags reserved bit is set, when ip packet(not fragments ) via the one linux router/linux bridge,and the iphdr flags reserved bit is not modified;
> 2)but the ip fragments via router,the linux IP reassembly or fragmentation ,causing the reserved bit is reset to zero,Which leads to The other PC software depending on the reserved bit set  process the Packet failed.
> [rfc]
> RFC791
> Bit 0: reserved, must be zero
> RFC3514
> Introduction This bit , but The scene seems different from us,we expect Keep reserved bit set is not modified when forward the linux router
> 
> 
> 
> 
> 

Why process the packet at all? If a reserved bit must be 0 and it is
not, drop the packet.

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re:Re: [PATCH] net/ipv4/ip_fragment:fix missing Flags reserved bit set in iphdr
  2021-05-11  3:05     ` David Ahern
@ 2021-05-12  4:43       ` meijusan
  0 siblings, 0 replies; 5+ messages in thread
From: meijusan @ 2021-05-12  4:43 UTC (permalink / raw)
  To: David Ahern
  Cc: Jakub Kicinski, davem, yoshfuji, dsahern, netdev, linux-kernel


At 2021-05-11 11:05:54, "David Ahern" <dsahern@gmail.com> wrote:
>On 5/10/21 7:18 PM, meijusan wrote:
>> 
>> At 2021-05-08 06:59:00, "Jakub Kicinski" <kuba@kernel.org> wrote:
>>> On Thu,  6 May 2021 22:59:05 +0800 meijusan wrote:
>>>> ip frag with the iphdr flags reserved bit set,via router,ip frag reasm or
>>>> fragment,causing the reserved bit is reset to zero.
>>>>
>>>> Keep reserved bit set is not modified in ip frag  defrag or fragment.
>>>>
>>>> Signed-off-by: meijusan <meijusan@163.com>
>>>
>>> Could you please provide more background on why we'd want to do this?
>> 
>>> Preferably with references to relevant (non-April Fools' Day) RFCs.
>> 
>> [background]
>> the Simple network usage scenarios: the one PC software<--->linux router(L3)/linux bridege(L2,bridge-nf-call-iptables)<--->the other PC software
>> 1)the PC software send the ip packet with the iphdr flags reserved bit is set, when ip packet(not fragments ) via the one linux router/linux bridge,and the iphdr flags reserved bit is not modified;
>> 2)but the ip fragments via router,the linux IP reassembly or fragmentation ,causing the reserved bit is reset to zero,Which leads to The other PC software depending on the reserved bit set  process the Packet failed.
>> [rfc]
>> RFC791
>> Bit 0: reserved, must be zero
>> RFC3514
>> Introduction This bit , but The scene seems different from us,we expect Keep reserved bit set is not modified when forward the linux router
>> 
>> 
>> 
>> 
>> 
>
>Why process the packet at all? If a reserved bit must be 0 and it is

>not, drop the packet.

Sorry, my background description is not clearly described

 the Simple network usage scenarios: one PC software<--->linux router(L3)/linux bridege(L2,bridge-nf-call-iptables)<--->the other PC software
 1)the PC software send the ip packet with the iphdr flags reserved bit is set 1,The packet can pass through the router normally, and the reserved flags bit have not been modified;
 2)When the ip fragment packet passes through the linux router, the linux network protocol stack's re-fragmentation function of the IP fragment causes the first bit of the reserved field of the ip header to be cleared to 0. When the packet reaches the software of another pc, the PC software checks the reserved bit and finds that the reserved bit is not 0,  discard the packet.

 If according to rfc791, the reserved bit must be 0, how does the kernel protocol stack deal with fragmented packets or non-fragmented packets that carry the reserved field bit as 1? I personally think that either all of them are transmitted transparently or all of them are discarded. This needs to be discussed.


^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2021-05-12  4:59 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-05-06 14:59 [PATCH] net/ipv4/ip_fragment:fix missing Flags reserved bit set in iphdr meijusan
2021-05-07 22:59 ` Jakub Kicinski
2021-05-11  1:18   ` meijusan
2021-05-11  3:05     ` David Ahern
2021-05-12  4:43       ` meijusan

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.