Subsystems (2)
Andrew Morton
maintainer(switched to email. Please respond via emailed reply-to-all, not via the bugzilla web interface).
Quoted 32 lines · On Fri, 22 Jun 2018 23:37:27 +0000 [email protected] wrote:
https://bugzilla.kernel.org/show_bug.cgi?id=200209
Bug ID: 200209
Summary: UBSAN: Undefined behaviour in mm/fadvise.c:LINE
Product: Memory Management
Version: 2.5
Kernel Version: v4.18-rc2
Hardware: All
OS: Linux
Tree: Mainline
Status: NEW
Severity: normal
Priority: P1
Component: Page Allocator
Assignee: [email protected]
Reporter: [email protected]
Regression: NoHi,
This bug was found in Linux Kernel v4.18-rc2$ cat report0 ================================================================================ UBSAN: Undefined behaviour in mm/fadvise.c:76:10 signed integer overflow: 4 + 9223372036854775805 cannot be represented in type 'long long int' CPU: 0 PID: 13477 Comm: syz-executor1 Not tainted 4.18.0-rc1 #2 Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS rel-1.10.2-0-g5f4c7b1-prebuilt.qemu-project.org 04/01/2014 Call Trace: __dump_stack lib/dump_stack.c:77 [inline] dump_stack+0x122/0x1c8 lib/dump_stack.c:113
Quoted 8 lines
ubsan_epilogue+0x12/0x86 lib/ubsan.c:159 handle_overflow+0x1c2/0x21f lib/ubsan.c:190 __ubsan_handle_add_overflow+0x2a/0x31 lib/ubsan.c:198 ksys_fadvise64_64+0xbf0/0xd10 mm/fadvise.c:76 __do_sys_fadvise64 mm/fadvise.c:198 [inline] __se_sys_fadvise64 mm/fadvise.c:196 [inline] __x64_sys_fadvise64+0xa9/0x120 mm/fadvise.c:196 do_syscall_64+0xb8/0x3a0 arch/x86/entry/common.c:290
That overflow is deliberate:
endbyte = offset + len; if (!len || endbyte < len) endbyte = -1; else endbyte--; /* inclusive */
Or is there a hole in this logic?
If not, I guess ee can do this another way to keep the checker happy.
Quoted 31 lines · Andrew Morton
Quoted 14 lines
Hi,
This bug was found in Linux Kernel v4.18-rc2$ cat report0 ================================================================================ UBSAN: Undefined behaviour in mm/fadvise.c:76:10 signed integer overflow: 4 + 9223372036854775805 cannot be represented in type 'long long int' CPU: 0 PID: 13477 Comm: syz-executor1 Not tainted 4.18.0-rc1 #2 Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS rel-1.10.2-0-g5f4c7b1-prebuilt.qemu-project.org 04/01/2014 Call Trace: __dump_stack lib/dump_stack.c:77 [inline] dump_stack+0x122/0x1c8 lib/dump_stack.c:113Quoted 8 lines
ubsan_epilogue+0x12/0x86 lib/ubsan.c:159 handle_overflow+0x1c2/0x21f lib/ubsan.c:190 __ubsan_handle_add_overflow+0x2a/0x31 lib/ubsan.c:198 ksys_fadvise64_64+0xbf0/0xd10 mm/fadvise.c:76 __do_sys_fadvise64 mm/fadvise.c:198 [inline] __se_sys_fadvise64 mm/fadvise.c:196 [inline] __x64_sys_fadvise64+0xa9/0x120 mm/fadvise.c:196 do_syscall_64+0xb8/0x3a0 arch/x86/entry/common.c:290That overflow is deliberate:
endbyte = offset + len; if (!len || endbyte < len) endbyte = -1; else endbyte--; /* inclusive */
Quoted 3 lines
Or is there a hole in this logic?
If not, I guess ee can do this another way to keep the checker happy.
It should be enough to make overflow unsigned. Unsigned overflow is defined by the C standard.
PATCH 1/1 mm/fadvise: Fix signed overflow UBSAN complaint
In reply to Andrew MortonSigned integer overflow is undefined according to the C standard. The overflow in ksys_fadvise64_64() is deliberate, but since it is signed overflow, UBSAN complains:
UBSAN: Undefined behaviour in mm/fadvise.c:76:10 signed integer overflow: 4 + 9223372036854775805 cannot be represented in type 'long long int'
Use unsigned types to do math. Unsigned overflow is defined so UBSAN will not complain about it. This patch doesn't change generated code.
--- mm/fadvise.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
mm/fadvise.c +1 -1
@@ -73,7 +73,7 @@ int ksys_fadvise64_64(int fd, loff_t offset, loff_t len, int advice) }/* Careful about overflows. Len == 0 means "as much as possible" */ - endbyte = offset + len; + endbyte = (u64 )offset + (u64 )len;if (!len || endbyte < len) endbyte =-1 ;else
Signature · 1 line
2.16.4
Andrew Morton
maintainerRe: [PATCH] mm/fadvise: Fix signed overflow UBSAN complaint
Quoted 15 lines · On Fri, 29 Jun 2018 21:44:53 +0300 Andrey Ryabinin <[email protected]>…
Signed integer overflow is undefined according to the C standard. The overflow in
ksys_fadvise64_64()is deliberate, but since it is signed overflow, UBSAN complains:UBSAN: Undefined behaviour in mm/fadvise.c:76:10 signed integer overflow: 4 + 9223372036854775805 cannot be represented in type 'long long int'Use unsigned types to do math. Unsigned overflow is defined so UBSAN will not complain about it. This patch doesn't change generated code.
...
mm/fadvise.c int ksys_fadvise64_64(int fd, loff_t offset, loff_t len, int advice) · line 79
Quoted 8 lines
mm/fadvise.c +1
-1@@ -73,7 +73,7 @@ int ksys_fadvise64_64(int fd, loff_t offset, loff_t len, int advice) }/* Careful about overflows. Len == 0 means "as much as possible" */ - endbyte = offset + len; + endbyte = (u64 )offset + (u64 )len;if (!len || endbyte < len) endbyte =-1 ;else
Readers of this code will wonder "what the heck are those casts for". Therefore:
mm/fadvise.c renamed from mm/fadvise.c~mm-fadvise-fix-signed-overflow-ubsan-complaint-fix +5 -1
@@ -72,7 +72,11 @@ int ksys_fadvise64_64(int fd, loff_t off goto out; } -/* Careful about overflows. Len == 0 means "as much as possible" */ +/* +* Careful about overflows. Len == 0 means "as much as possible". Use +* unsigned math because signed overflows are undefined and UBSan +* complains. +*/ endbyte = (u64 )offset + (u64 )len;if (!len || endbyte < len) endbyte =-1 ;
_