* [PATCH] net/ipv4/ip_fragment:fix missing Flags reserved bit set in iphdr
@ 2021-05-05 13:25 meijusan
2021-05-05 17:39 ` kernel test robot
` (2 more replies)
0 siblings, 3 replies; 7+ messages in thread
From: meijusan @ 2021-05-05 13:25 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 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
^ permalink raw reply related [flat|nested] 7+ messages in thread
* Re: [PATCH] net/ipv4/ip_fragment:fix missing Flags reserved bit set in iphdr
2021-05-05 13:25 [PATCH] net/ipv4/ip_fragment:fix missing Flags reserved bit set in iphdr meijusan
@ 2021-05-05 17:39 ` kernel test robot
2021-05-05 17:59 ` kernel test robot
2021-05-06 9:37 ` Dan Carpenter
2 siblings, 0 replies; 7+ messages in thread
From: kernel test robot @ 2021-05-05 17:39 UTC (permalink / raw)
To: meijusan, davem, yoshfuji, dsahern, kuba
Cc: kbuild-all, clang-built-linux, netdev, linux-kernel, meijusan
[-- Attachment #1: Type: text/plain, Size: 4246 bytes --]
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 <lkp@intel.com>
All warnings (new ones prefixed by >>):
>> 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
[-- Attachment #2: .config.gz --]
[-- Type: application/gzip, Size: 35924 bytes --]
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH] net/ipv4/ip_fragment:fix missing Flags reserved bit set in iphdr
2021-05-05 13:25 [PATCH] net/ipv4/ip_fragment:fix missing Flags reserved bit set in iphdr meijusan
2021-05-05 17:39 ` kernel test robot
@ 2021-05-05 17:59 ` kernel test robot
2021-05-06 9:37 ` Dan Carpenter
2 siblings, 0 replies; 7+ messages in thread
From: kernel test robot @ 2021-05-05 17:59 UTC (permalink / raw)
To: meijusan, davem, yoshfuji, dsahern, kuba
Cc: kbuild-all, clang-built-linux, netdev, linux-kernel, meijusan
[-- Attachment #1: Type: text/plain, Size: 4246 bytes --]
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 <lkp@intel.com>
All warnings (new ones prefixed by >>):
>> 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
[-- Attachment #2: .config.gz --]
[-- Type: application/gzip, Size: 37995 bytes --]
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH] net/ipv4/ip_fragment:fix missing Flags reserved bit set in iphdr
2021-05-05 13:25 [PATCH] net/ipv4/ip_fragment:fix missing Flags reserved bit set in iphdr meijusan
2021-05-05 17:39 ` kernel test robot
2021-05-05 17:59 ` kernel test robot
@ 2021-05-06 9:37 ` Dan Carpenter
2 siblings, 0 replies; 7+ messages in thread
From: Dan Carpenter @ 2021-05-06 9:37 UTC (permalink / raw)
To: kbuild, meijusan, davem, yoshfuji, dsahern, kuba
Cc: lkp, kbuild-all, netdev, linux-kernel, meijusan
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 <lkp@intel.com>
Reported-by: Dan Carpenter <dan.carpenter@oracle.com>
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
^ permalink raw reply [flat|nested] 7+ 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
0 siblings, 0 replies; 7+ 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] 7+ messages in thread
* Re: [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
2021-05-11 1:18 ` meijusan
0 siblings, 1 reply; 7+ 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] 7+ messages in thread
* [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; 7+ 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] 7+ messages in thread
end of thread, other threads:[~2021-05-11 3:06 UTC | newest]
Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-05-05 13:25 [PATCH] net/ipv4/ip_fragment:fix missing Flags reserved bit set in iphdr meijusan
2021-05-05 17:39 ` kernel test robot
2021-05-05 17:59 ` kernel test robot
2021-05-06 9:37 ` Dan Carpenter
2021-05-06 14:59 meijusan
2021-05-07 22:59 ` Jakub Kicinski
2021-05-11 1:18 ` meijusan
2021-05-11 3:05 ` David Ahern
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).