lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Date:   Tue, 17 Nov 2020 01:32:19 +0800
From:   Zhaoxiu Zeng <zengzhaoxiu@....com>
To:     kernel test robot <oliver.sang@...el.com>
Cc:     Jann Horn <jannh@...gle.com>,
        Andrew Morton <akpm@...ux-foundation.org>,
        linux-kernel@...r.kernel.org,
        Zhaoxiu Zeng <zhaoxiu.zeng@...il.com>,
        0day robot <lkp@...el.com>, lkp@...ts.01.org
Subject: Re: [lib] 6ee736dc92: BUG:unable_to_handle_page_fault_for_address

在 2020/11/12 14:45, kernel test robot 写道:
> 
> Greeting,
> 
> FYI, we noticed the following commit (built with gcc-9):
> 
> commit: 6ee736dc922a5f81a3a60a72a54ec9392ccfe787 ("[PATCH 2/3] lib: zlib_inflate: improves decompression performance")
> url: https://github.com/0day-ci/linux/commits/zengzhaoxiu-163-com/lib-Introduce-copy_from_back/20201110-033522
> base: https://git.kernel.org/cgit/linux/kernel/git/soc/soc.git for-next
> 
> in testcase: nvml
> version: nvml-x86_64-9a558d859-1_20201111
> with following parameters:
> 
> 	test: pmem
> 	group: util
> 	nr_pmem: 1
> 	fs: ext4
> 	mount_option: dax
> 	bp_memmap: 32G!4G
> 	ucode: 0x7000019
> 
> 
> 
> on test machine: 16 threads Intel(R) Xeon(R) CPU D-1541 @ 2.10GHz with 48G memory
> 
> caused below changes (please refer to attached dmesg/kmsg for entire log/backtrace):
> 
> 
> If you fix the issue, kindly add following tag
> Reported-by: kernel test robot <oliver.sang@...el.com>
> 
> 
> [    5.134501] BUG: unable to handle page fault for address: ffff88880249a4bf
> [    5.134783] #PF: supervisor read access in kernel mode
> [    5.134783] #PF: error_code(0x0000) - not-present page
> [    5.134783] PGD c7f401067 P4D c7f401067 PUD 0 
> [    5.134783] Oops: 0000 [#1] SMP PTI
> [    5.134783] CPU: 0 PID: 1 Comm: swapper/0 Not tainted 5.10.0-rc1-00071-g6ee736dc922a #1
> [    5.134783] Hardware name: Supermicro SYS-5018D-FN4T/X10SDV-8C-TLN4F, BIOS 1.1 03/02/2016
> [    5.134783] RIP: 0010:inflate_fast+0x474/0x600
> [    5.134783] Code: cc fd ff ff 48 c7 43 30 e5 6d 5a 82 c7 07 1b 00 00 00 e9 ff fc ff ff 48 c7 43 30 cf 6d 5a 82 c7 07 1b 00 00 00 e9 ec fc ff ff <0f> b6 09 48 83 ed 01 49 83 c0 01 41 88 48 ff 48 83 fd 01 76 3f 44
> [    5.134783] RSP: 0000:ffffc90000047c38 EFLAGS: 00010246
> [    5.134783] RAX: 000000000000000d RBX: ffff888901886780 RCX: ffff88880249a4bf
> [    5.134783] RDX: ffffffff0001a4bd RSI: 0000000000000006 RDI: ffff888902490000
> [    5.134783] RBP: 0000000000000007 R08: ffff888902480002 R09: 0000000000000001
> [    5.134783] R10: ffff888902490548 R11: ffff888c5af6a3bf R12: 00000000fffe5b43
> [    5.134783] R13: 0000000000000007 R14: ffff888c7c9ffe23 R15: ffff888902490ef0
> [    5.134783] FS:  0000000000000000(0000) GS:ffff888c7fa00000(0000) knlGS:0000000000000000
> [    5.134783] CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
> [    5.134783] CR2: ffff88880249a4bf CR3: 0000000c7e20a001 CR4: 00000000003706f0
> [    5.134783] DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
> [    5.134783] DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400
> [    5.134783] Call Trace:
> [    5.134783]  zlib_inflate+0x99a/0x1780
> [    5.134783]  ? do_copy+0xe3/0x103
> [    5.134783]  ? write_buffer+0x37/0x37
> [    5.134783]  ? initrd_load+0x3f/0x3f
> [    5.134783]  ? write_buffer+0x37/0x37
> [    5.134783]  __gunzip+0x242/0x30c
> [    5.134783]  ? bunzip2+0x39d/0x39d
> [    5.134783]  ? __gunzip+0x30c/0x30c
> [    5.134783]  gunzip+0xe/0x11
> [    5.134783]  ? initrd_load+0x3f/0x3f
> [    5.134783]  unpack_to_rootfs+0x17d/0x2c1
> [    5.134783]  ? initrd_load+0x3f/0x3f
> [    5.134783]  ? do_copy+0x103/0x103
> [    5.134783]  populate_rootfs+0x59/0x109
> [    5.134783]  ? do_copy+0x103/0x103
> [    5.134783]  do_one_initcall+0x44/0x200
> [    5.134783]  kernel_init_freeable+0x1da/0x241
> [    5.134783]  ? rest_init+0xd0/0xd0
> [    5.134783]  kernel_init+0xa/0x110
> [    5.134783]  ret_from_fork+0x22/0x30
> [    5.134783] Modules linked in:
> [    5.134783] CR2: ffff88880249a4bf
> [    5.134783] ---[ end trace a0a85397603c3dac ]---
> 
> 
> To reproduce:
> 
>         git clone https://github.com/intel/lkp-tests.git
>         cd lkp-tests
>         bin/lkp install job.yaml  # job file is attached in this email
>         bin/lkp run     job.yaml
> 
> 
> 
> Thanks,
> Oliver Sang
> 

It's not common for copying from the window.
This new patch maybe fix the bug, I build the fedora33's kernel and started it successfully.


Signed-off-by: Zhaoxiu Zeng <zhaoxiu.zeng@...il.com>
Reported-by: kernel test robot <oliver.sang@...el.com>
---
 lib/zlib_inflate/inffast.c | 115 ++++++-------------------------------
 1 file changed, 19 insertions(+), 96 deletions(-)

diff --git a/lib/zlib_inflate/inffast.c b/lib/zlib_inflate/inffast.c
index ed1f3df27260..8c9cc928cf71 100644
--- a/lib/zlib_inflate/inffast.c
+++ b/lib/zlib_inflate/inffast.c
@@ -4,29 +4,13 @@
  */
 
 #include <linux/zutil.h>
+#include <asm/copy_from_back.h>
 #include "inftrees.h"
 #include "inflate.h"
 #include "inffast.h"
 
 #ifndef ASMINF
 
-union uu {
-	unsigned short us;
-	unsigned char b[2];
-};
-
-/* Endian independed version */
-static inline unsigned short
-get_unaligned16(const unsigned short *p)
-{
-	union uu  mm;
-	unsigned char *b = (unsigned char *)p;
-
-	mm.b[0] = b[0];
-	mm.b[1] = b[1];
-	return mm.us;
-}
-
 /*
    Decode literal, length, and distance codes and write out the resulting
    literal and match bytes until either not enough input or output is
@@ -177,52 +161,34 @@ void inflate_fast(z_streamp strm, unsigned start)
                 hold >>= op;
                 bits -= op;
                 op = (unsigned)(out - beg);     /* max distance in output */
-                if (dist > op) {                /* see if copy from window */
+                if (unlikely(dist > op)) {      /* see if copy from window */
                     op = dist - op;             /* distance back in window */
                     if (op > whave) {
                         strm->msg = (char *)"invalid distance too far back";
                         state->mode = BAD;
                         break;
                     }
-                    from = window;
-                    if (write == 0) {           /* very common case */
-                        from += wsize - op;
-                        if (op < len) {         /* some from window */
-                            len -= op;
-                            do {
-                                *out++ = *from++;
-                            } while (--op);
-                            from = out - dist;  /* rest from output */
-                        }
-                    }
-                    else if (write < op) {      /* wrap around window */
-                        from += wsize + write - op;
-                        op -= write;
-                        if (op < len) {         /* some from end of window */
-                            len -= op;
-                            do {
-                                *out++ = *from++;
-                            } while (--op);
-                            from = window;
-                            if (write < len) {  /* some from start of window */
-                                op = write;
+                    from = window + write - op;
+                    if (write < op) {           /* very common case */
+                        from += wsize;
+                        if (write) {            /* wrap around window */
+                            op -= write;
+                            if (op < len) {     /* some from end of window */
                                 len -= op;
                                 do {
                                     *out++ = *from++;
                                 } while (--op);
-                                from = out - dist;      /* rest from output */
+                                from = window;  /* some from start of window */
+                                op = write;
                             }
                         }
                     }
-                    else {                      /* contiguous in window */
-                        from += write - op;
-                        if (op < len) {         /* some from window */
-                            len -= op;
-                            do {
-                                *out++ = *from++;
-                            } while (--op);
-                            from = out - dist;  /* rest from output */
-                        }
+                    if (op < len) {             /* some from window */
+                        len -= op;
+                        do {
+                            *out++ = *from++;
+                        } while (--op);
+                        from = out - dist;      /* rest from output */
                     }
                     while (len > 2) {
                         *out++ = *from++;
@@ -235,52 +201,9 @@ void inflate_fast(z_streamp strm, unsigned start)
                         if (len > 1)
                             *out++ = *from++;
                     }
-                }
-                else {
-		    unsigned short *sout;
-		    unsigned long loops;
-
-                    from = out - dist;          /* copy direct from output */
-		    /* minimum length is three */
-		    /* Align out addr */
-		    if (!((long)(out - 1) & 1)) {
-			*out++ = *from++;
-			len--;
-		    }
-		    sout = (unsigned short *)(out);
-		    if (dist > 2) {
-			unsigned short *sfrom;
-
-			sfrom = (unsigned short *)(from);
-			loops = len >> 1;
-			do
-#ifdef CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS
-			    *sout++ = *sfrom++;
-#else
-			    *sout++ = get_unaligned16(sfrom++);
-#endif
-			while (--loops);
-			out = (unsigned char *)sout;
-			from = (unsigned char *)sfrom;
-		    } else { /* dist == 1 or dist == 2 */
-			unsigned short pat16;
-
-			pat16 = *(sout-1);
-			if (dist == 1) {
-				union uu mm;
-				/* copy one char pattern to both bytes */
-				mm.us = pat16;
-				mm.b[0] = mm.b[1];
-				pat16 = mm.us;
-			}
-			loops = len >> 1;
-			do
-			    *sout++ = pat16;
-			while (--loops);
-			out = (unsigned char *)sout;
-		    }
-		    if (len & 1)
-			*out++ = *from++;
+                } else {
+                    /* copy direct from output */
+                    out = copy_from_back(out, dist, len);
                 }
             }
             else if ((op & 64) == 0) {          /* 2nd level distance code */
-- 
2.28.0


Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ