[PATCH] net/ipv4/ip_fragment:fix missing Flags reserved bit set in iphdr

Subsystems: networking [general], networking [ipv4/ipv6], the rest

STALE1928d

4 messages, 3 authors, 2021-05-06 · open the first message on its own page

[PATCH] net/ipv4/ip_fragment:fix missing Flags reserved bit set in iphdr

From: meijusan <hidden>
Date: 2021-05-05 13:27:27

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 <redacted>
---
 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 c3efc7d658f6..d9ab750f9110 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;
 
 	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

Re: [PATCH] net/ipv4/ip_fragment:fix missing Flags reserved bit set in iphdr

From: kernel test robot <hidden>
Date: 2021-05-05 17:49:46

Hi meijusan,

Thank you for the patch! Perhaps something to improve:

[auto build test WARNING on ipvs/master]
[also build test WARNING on linus/master sparc-next/master v5.12 next-20210505]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch]

url:    https://github.com/0day-ci/linux/commits/meijusan/net-ipv4-ip_fragment-fix-missing-Flags-reserved-bit-set-in-iphdr/20210505-212826
base:   https://git.kernel.org/pub/scm/linux/kernel/git/horms/ipvs.git master
config: x86_64-randconfig-a014-20210505 (attached as .config)
compiler: clang version 13.0.0 (https://github.com/llvm/llvm-project 8f5a2a5836cc8e4c1def2bdeb022e7b496623439)
reproduce (this is a W=1 build):
        wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # install x86_64 cross compiling tool for clang build
        # apt-get install binutils-x86-64-linux-gnu
        # https://github.com/0day-ci/linux/commit/c6cde148fcd3bfdfa4ce7beac56893165236fd4e
        git remote add linux-review https://github.com/0day-ci/linux
        git fetch --no-tags linux-review meijusan/net-ipv4-ip_fragment-fix-missing-Flags-reserved-bit-set-in-iphdr/20210505-212826
        git checkout c6cde148fcd3bfdfa4ce7beac56893165236fd4e
        # save the attached .config to linux build tree
        COMPILER_INSTALL_PATH=$HOME/0day COMPILER=clang make.cross W=1 ARCH=x86_64 

If you fix the issue, kindly add following tag as appropriate
Reported-by: kernel test robot <redacted>

All warnings (new ones prefixed by >>):
quoted
net/ipv4/ip_output.c:644:6: warning: variable 'ip_evil' is used uninitialized whenever 'if' condition is false [-Wsometimes-uninitialized]
           if (ntohs(iph->frag_off) & IP_EVIL)
               ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   include/linux/byteorder/generic.h:142:18: note: expanded from macro 'ntohs'
   #define ntohs(x) ___ntohs(x)
                    ^
   include/linux/byteorder/generic.h:137:21: note: expanded from macro '___ntohs'
   #define ___ntohs(x) __be16_to_cpu(x)
                       ^
   include/uapi/linux/byteorder/little_endian.h:42:26: note: expanded from macro '__be16_to_cpu'
   #define __be16_to_cpu(x) __swab16((__force __u16)(__be16)(x))
                            ^
   include/uapi/linux/swab.h:102:21: note: expanded from macro '__swab16'
   #define __swab16(x) (__u16)__builtin_bswap16((__u16)(x))
                       ^
   net/ipv4/ip_output.c:655:6: note: uninitialized use occurs here
           if (ip_evil)
               ^~~~~~~
   net/ipv4/ip_output.c:644:2: note: remove the 'if' if its condition is always true
           if (ntohs(iph->frag_off) & IP_EVIL)
           ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   net/ipv4/ip_output.c:636:14: note: initialize the variable 'ip_evil' to silence this warning
           bool ip_evil;
                       ^
                        = 0
   1 warning generated.


vim +644 net/ipv4/ip_output.c

   630	
   631	void ip_fraglist_prepare(struct sk_buff *skb, struct ip_fraglist_iter *iter)
   632	{
   633		unsigned int hlen = iter->hlen;
   634		struct iphdr *iph = iter->iph;
   635		struct sk_buff *frag;
   636		bool ip_evil;
   637	
   638		frag = iter->frag;
   639		frag->ip_summed = CHECKSUM_NONE;
   640		skb_reset_transport_header(frag);
   641		__skb_push(frag, hlen);
   642		skb_reset_network_header(frag);
   643		memcpy(skb_network_header(frag), iph, hlen);
 > 644		if (ntohs(iph->frag_off) & IP_EVIL)
   645			ip_evil = true;
   646		iter->iph = ip_hdr(frag);
   647		iph = iter->iph;
   648		iph->tot_len = htons(frag->len);
   649		ip_copy_metadata(frag, skb);
   650		iter->offset += skb->len - hlen;
   651		iph->frag_off = htons(iter->offset >> 3);
   652		if (frag->next)
   653			iph->frag_off |= htons(IP_MF);
   654	
   655		if (ip_evil)
   656			iph->frag_off |= htons(IP_EVIL);
   657	
   658		/* Ready, complete checksum */
   659		ip_send_check(iph);
   660	}
   661	EXPORT_SYMBOL(ip_fraglist_prepare);
   662	

---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all@lists.01.org

Re: [PATCH] net/ipv4/ip_fragment:fix missing Flags reserved bit set in iphdr

From: kernel test robot <hidden>
Date: 2021-05-05 18:00:52

Hi meijusan,

Thank you for the patch! Perhaps something to improve:

[auto build test WARNING on ipvs/master]
[also build test WARNING on linus/master sparc-next/master v5.12 next-20210505]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch]

url:    https://github.com/0day-ci/linux/commits/meijusan/net-ipv4-ip_fragment-fix-missing-Flags-reserved-bit-set-in-iphdr/20210505-212826
base:   https://git.kernel.org/pub/scm/linux/kernel/git/horms/ipvs.git master
config: x86_64-randconfig-r024-20210505 (attached as .config)
compiler: clang version 13.0.0 (https://github.com/llvm/llvm-project 8f5a2a5836cc8e4c1def2bdeb022e7b496623439)
reproduce (this is a W=1 build):
        wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # install x86_64 cross compiling tool for clang build
        # apt-get install binutils-x86-64-linux-gnu
        # https://github.com/0day-ci/linux/commit/c6cde148fcd3bfdfa4ce7beac56893165236fd4e
        git remote add linux-review https://github.com/0day-ci/linux
        git fetch --no-tags linux-review meijusan/net-ipv4-ip_fragment-fix-missing-Flags-reserved-bit-set-in-iphdr/20210505-212826
        git checkout c6cde148fcd3bfdfa4ce7beac56893165236fd4e
        # save the attached .config to linux build tree
        COMPILER_INSTALL_PATH=$HOME/0day COMPILER=clang make.cross W=1 ARCH=x86_64 

If you fix the issue, kindly add following tag as appropriate
Reported-by: kernel test robot <redacted>

All warnings (new ones prefixed by >>):
quoted
net/ipv4/ip_output.c:644:6: warning: variable 'ip_evil' is used uninitialized whenever 'if' condition is false [-Wsometimes-uninitialized]
           if (ntohs(iph->frag_off) & IP_EVIL)
               ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   include/linux/byteorder/generic.h:142:18: note: expanded from macro 'ntohs'
   #define ntohs(x) ___ntohs(x)
                    ^
   include/linux/byteorder/generic.h:137:21: note: expanded from macro '___ntohs'
   #define ___ntohs(x) __be16_to_cpu(x)
                       ^
   include/uapi/linux/byteorder/little_endian.h:42:26: note: expanded from macro '__be16_to_cpu'
   #define __be16_to_cpu(x) __swab16((__force __u16)(__be16)(x))
                            ^
   include/uapi/linux/swab.h:102:21: note: expanded from macro '__swab16'
   #define __swab16(x) (__u16)__builtin_bswap16((__u16)(x))
                       ^
   net/ipv4/ip_output.c:655:6: note: uninitialized use occurs here
           if (ip_evil)
               ^~~~~~~
   net/ipv4/ip_output.c:644:2: note: remove the 'if' if its condition is always true
           if (ntohs(iph->frag_off) & IP_EVIL)
           ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   net/ipv4/ip_output.c:636:14: note: initialize the variable 'ip_evil' to silence this warning
           bool ip_evil;
                       ^
                        = 0
   1 warning generated.


vim +644 net/ipv4/ip_output.c

   630	
   631	void ip_fraglist_prepare(struct sk_buff *skb, struct ip_fraglist_iter *iter)
   632	{
   633		unsigned int hlen = iter->hlen;
   634		struct iphdr *iph = iter->iph;
   635		struct sk_buff *frag;
   636		bool ip_evil;
   637	
   638		frag = iter->frag;
   639		frag->ip_summed = CHECKSUM_NONE;
   640		skb_reset_transport_header(frag);
   641		__skb_push(frag, hlen);
   642		skb_reset_network_header(frag);
   643		memcpy(skb_network_header(frag), iph, hlen);
 > 644		if (ntohs(iph->frag_off) & IP_EVIL)
   645			ip_evil = true;
   646		iter->iph = ip_hdr(frag);
   647		iph = iter->iph;
   648		iph->tot_len = htons(frag->len);
   649		ip_copy_metadata(frag, skb);
   650		iter->offset += skb->len - hlen;
   651		iph->frag_off = htons(iter->offset >> 3);
   652		if (frag->next)
   653			iph->frag_off |= htons(IP_MF);
   654	
   655		if (ip_evil)
   656			iph->frag_off |= htons(IP_EVIL);
   657	
   658		/* Ready, complete checksum */
   659		ip_send_check(iph);
   660	}
   661	EXPORT_SYMBOL(ip_fraglist_prepare);
   662	

---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all@lists.01.org

Re: [PATCH] net/ipv4/ip_fragment:fix missing Flags reserved bit set in iphdr

From: Dan Carpenter <hidden>
Date: 2021-05-06 09:38:17

Hi meijusan,

url:    https://github.com/0day-ci/linux/commits/meijusan/net-ipv4-ip_fragment-fix-missing-Flags-reserved-bit-set-in-iphdr/20210505-212826
base:   https://git.kernel.org/pub/scm/linux/kernel/git/horms/ipvs.git master
config: i386-randconfig-m021-20210505 (attached as .config)
compiler: gcc-9 (Debian 9.3.0-22) 9.3.0

If you fix the issue, kindly add following tag as appropriate
Reported-by: kernel test robot <redacted>
Reported-by: Dan Carpenter <redacted>

smatch warnings:
net/ipv4/ip_output.c:655 ip_fraglist_prepare() error: uninitialized symbol 'ip_evil'.

vim +/ip_evil +655 net/ipv4/ip_output.c

c8b17be0b7a45d Pablo Neira Ayuso 2019-05-29  631  void ip_fraglist_prepare(struct sk_buff *skb, struct ip_fraglist_iter *iter)
c8b17be0b7a45d Pablo Neira Ayuso 2019-05-29  632  {
c8b17be0b7a45d Pablo Neira Ayuso 2019-05-29  633  	unsigned int hlen = iter->hlen;
c8b17be0b7a45d Pablo Neira Ayuso 2019-05-29  634  	struct iphdr *iph = iter->iph;
c8b17be0b7a45d Pablo Neira Ayuso 2019-05-29  635  	struct sk_buff *frag;
c6cde148fcd3bf meijusan          2021-05-05  636  	bool ip_evil;
c8b17be0b7a45d Pablo Neira Ayuso 2019-05-29  637  
c8b17be0b7a45d Pablo Neira Ayuso 2019-05-29  638  	frag = iter->frag;
c8b17be0b7a45d Pablo Neira Ayuso 2019-05-29  639  	frag->ip_summed = CHECKSUM_NONE;
c8b17be0b7a45d Pablo Neira Ayuso 2019-05-29  640  	skb_reset_transport_header(frag);
c8b17be0b7a45d Pablo Neira Ayuso 2019-05-29  641  	__skb_push(frag, hlen);
c8b17be0b7a45d Pablo Neira Ayuso 2019-05-29  642  	skb_reset_network_header(frag);
c8b17be0b7a45d Pablo Neira Ayuso 2019-05-29  643  	memcpy(skb_network_header(frag), iph, hlen);
c6cde148fcd3bf meijusan          2021-05-05  644  	if (ntohs(iph->frag_off) & IP_EVIL)
c6cde148fcd3bf meijusan          2021-05-05  645  		ip_evil = true;

"ip_evil" is never set to false.

c8b17be0b7a45d Pablo Neira Ayuso 2019-05-29  646  	iter->iph = ip_hdr(frag);
c8b17be0b7a45d Pablo Neira Ayuso 2019-05-29  647  	iph = iter->iph;
c8b17be0b7a45d Pablo Neira Ayuso 2019-05-29  648  	iph->tot_len = htons(frag->len);
c8b17be0b7a45d Pablo Neira Ayuso 2019-05-29  649  	ip_copy_metadata(frag, skb);
c8b17be0b7a45d Pablo Neira Ayuso 2019-05-29  650  	iter->offset += skb->len - hlen;
c8b17be0b7a45d Pablo Neira Ayuso 2019-05-29  651  	iph->frag_off = htons(iter->offset >> 3);
c8b17be0b7a45d Pablo Neira Ayuso 2019-05-29  652  	if (frag->next)
c8b17be0b7a45d Pablo Neira Ayuso 2019-05-29  653  		iph->frag_off |= htons(IP_MF);
c6cde148fcd3bf meijusan          2021-05-05  654  
c6cde148fcd3bf meijusan          2021-05-05 @655  	if (ip_evil)
c6cde148fcd3bf meijusan          2021-05-05  656  		iph->frag_off |= htons(IP_EVIL);
c6cde148fcd3bf meijusan          2021-05-05  657  
c8b17be0b7a45d Pablo Neira Ayuso 2019-05-29  658  	/* Ready, complete checksum */
c8b17be0b7a45d Pablo Neira Ayuso 2019-05-29  659  	ip_send_check(iph);
c8b17be0b7a45d Pablo Neira Ayuso 2019-05-29  660  }

---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all@lists.01.org
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help