diff mbox series

[-mm] mm: readahead: apply a default readahead size

Message ID 20201229212634.31307-1-rdunlap@infradead.org (mailing list archive)
State New
Headers show
Series [-mm] mm: readahead: apply a default readahead size | expand

Commit Message

Randy Dunlap Dec. 29, 2020, 9:26 p.m. UTC
UBSAN reports an invalid shift size:

mr-fox kernel: UBSAN: shift-out-of-bounds in ./include/linux/log2.h:57:13
mr-fox kernel: shift exponent 64 is too large for 64-bit type 'long unsigned int'

Original report:
https://lore.kernel.org/lkml/c6e5eb81-680f-dd5c-8a81-62041a5ce50c@gmx.de/

Follow-up report:
https://lore.kernel.org/lkml/0c283ea9-b446-0e40-6dc8-e9585ae171b4@gmx.de/T/#m9b604660925f9e8a544f7453130c31d083c1e5bb


Willy suggested that get_init_ra_size() was being called with a size of 0,
which would cause this (instead of some Huge value), so add a check in
that function for size == 0, and if 0, default it to 32 (pages).

Reported-by: Toralf Förster <toralf.foerster@gmx.de>
Signed-off-by: Randy Dunlap <rdunlap@infradead.org>
Cc: Andrew Morton <akpm@linux-foundation.org>
Cc: Jens Axboe <axboe@kernel.dk>
Cc: Matthew Wilcox <willy@infradead.org>
Cc: linux-mm@kvack.org
---
 mm/readahead.c |    6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)

Comments

Matthew Wilcox Dec. 29, 2020, 10:23 p.m. UTC | #1
On Tue, Dec 29, 2020 at 01:26:34PM -0800, Randy Dunlap wrote:
> UBSAN reports an invalid shift size:
> 
> mr-fox kernel: UBSAN: shift-out-of-bounds in ./include/linux/log2.h:57:13
> mr-fox kernel: shift exponent 64 is too large for 64-bit type 'long unsigned int'
> 
> Original report:
> https://lore.kernel.org/lkml/c6e5eb81-680f-dd5c-8a81-62041a5ce50c@gmx.de/
> 
> Follow-up report:
> https://lore.kernel.org/lkml/0c283ea9-b446-0e40-6dc8-e9585ae171b4@gmx.de/T/#m9b604660925f9e8a544f7453130c31d083c1e5bb
> 
> 
> Willy suggested that get_init_ra_size() was being called with a size of 0,
> which would cause this (instead of some Huge value), so add a check in
> that function for size == 0, and if 0, default it to 32 (pages).

No, this is wrong.  'size' in this case is the size of the read.
And it's zero.  Is this fixed by commit
3644e2d2dda78e21edd8f5415b6d7ab03f5f54f3
Randy Dunlap Dec. 29, 2020, 10:55 p.m. UTC | #2
On 12/29/20 2:23 PM, Matthew Wilcox wrote:
> On Tue, Dec 29, 2020 at 01:26:34PM -0800, Randy Dunlap wrote:
>> UBSAN reports an invalid shift size:
>>
>> mr-fox kernel: UBSAN: shift-out-of-bounds in ./include/linux/log2.h:57:13
>> mr-fox kernel: shift exponent 64 is too large for 64-bit type 'long unsigned int'
>>
>> Original report:
>> https://lore.kernel.org/lkml/c6e5eb81-680f-dd5c-8a81-62041a5ce50c@gmx.de/
>>
>> Follow-up report:
>> https://lore.kernel.org/lkml/0c283ea9-b446-0e40-6dc8-e9585ae171b4@gmx.de/T/#m9b604660925f9e8a544f7453130c31d083c1e5bb
>>
>>
>> Willy suggested that get_init_ra_size() was being called with a size of 0,
>> which would cause this (instead of some Huge value), so add a check in
>> that function for size == 0, and if 0, default it to 32 (pages).
> 
> No, this is wrong.  'size' in this case is the size of the read.
> And it's zero.  Is this fixed by commit
> 3644e2d2dda78e21edd8f5415b6d7ab03f5f54f3
> 

Toralf, can you test with 5.11-rc1 (or later)?

thanks.
Toralf Förster Dec. 30, 2020, 9:05 a.m. UTC | #3
On 12/29/20 11:55 PM, Randy Dunlap wrote:
>> No, this is wrong.  'size' in this case is the size of the read.
>> And it's zero.  Is this fixed by commit
>> 3644e2d2dda78e21edd8f5415b6d7ab03f5f54f3
>>
> Toralf, can you test with 5.11-rc1 (or later)?
>
> thanks.

My plan was to apply that commit on top of the upcoming 5.10.4 and test
that, just waiting in moment for Greg to release the stable version.

--
Toralf
Toralf Förster Jan. 3, 2021, 9:40 p.m. UTC | #4
On 12/30/20 10:05 AM, Toralf Förster wrote:
> On 12/29/20 11:55 PM, Randy Dunlap wrote:
>>> No, this is wrong.  'size' in this case is the size of the read.
>>> And it's zero.  Is this fixed by commit
>>> 3644e2d2dda78e21edd8f5415b6d7ab03f5f54f3
>>>
>> Toralf, can you test with 5.11-rc1 (or later)?
>>
>> thanks.
>
> My plan was to apply that commit on top of the upcoming 5.10.4 and test
> that, just waiting in moment for Greg to release the stable version.
>
I commit 3644e2d2dda on top of 5.10.4 at my server - no issue so far. I
did NOT patched my desktop (same stable hardened Gentoo Linux, same
software and kernel versions) - and there it happened under 5.10.4 too:

Jan  3 20:54:59 t44 kernel: [126159.494365] UBSAN: shift-out-of-bounds
in ./include/linux/log2.h:57:13
Jan  3 20:54:59 t44 kernel: [126159.494371] shift exponent 64 is too
large for 64-bit type 'long unsigned int'
Jan  3 20:54:59 t44 kernel: [126159.494378] CPU: 0 PID: 16651 Comm: cc1
Tainted: G        W       T 5.10.4 #5
Jan  3 20:54:59 t44 kernel: [126159.494381] Hardware name: LENOVO
20AQCTO1WW/20AQCTO1WW, BIOS GJETA4WW (2.54 ) 03/27/2020
Jan  3 20:54:59 t44 kernel: [126159.494383] Call Trace:
Jan  3 20:54:59 t44 kernel: [126159.494397]  dump_stack+0x57/0x6a
Jan  3 20:54:59 t44 kernel: [126159.494402]  ubsan_epilogue+0x5/0x40
Jan  3 20:54:59 t44 kernel: [126159.494408]
__ubsan_handle_shift_out_of_bounds.cold+0x61/0x10e
Jan  3 20:54:59 t44 kernel: [126159.494419]
ondemand_readahead.cold+0x16/0x21
Jan  3 20:54:59 t44 kernel: [126159.494427]
generic_file_buffered_read+0x43d/0x880
Jan  3 20:54:59 t44 kernel: [126159.494437]  new_sync_read+0x15d/0x1f0
Jan  3 20:54:59 t44 kernel: [126159.494442]  vfs_read+0xf5/0x190
Jan  3 20:54:59 t44 kernel: [126159.494447]  ksys_read+0x65/0xe0
Jan  3 20:54:59 t44 kernel: [126159.494453]  do_syscall_64+0x33/0x40
Jan  3 20:54:59 t44 kernel: [126159.494460]
entry_SYSCALL_64_after_hwframe+0x44/0xa9
Jan  3 20:54:59 t44 kernel: [126159.494466] RIP: 0033:0x7feace476dfe
Jan  3 20:54:59 t44 kernel: [126159.494472] Code: c0 e9 c6 fe ff ff 50
48 8d 3d de d6 09 00 e8 89 e4 01 00 66 0f 1f 84 00 00 00 00 00 64 8b 04
25 18 00 00 00 85 c0 75 14 0f 05 <48> 3d 00 f0 ff ff 77 5a c3 66 0f 1f
84 00 00 00 00 00 48 83 ec 28
Jan  3 20:54:59 t44 kernel: [126159.494476] RSP: 002b:00007ffe122f4318
EFLAGS: 00000246 ORIG_RAX: 0000000000000000
Jan  3 20:54:59 t44 kernel: [126159.494483] RAX: ffffffffffffffda RBX:
0000000000000000 RCX: 00007feace476dfe
Jan  3 20:54:59 t44 kernel: [126159.494486] RDX: 0000000000000000 RSI:
00000000047971a0 RDI: 0000000000000008
Jan  3 20:54:59 t44 kernel: [126159.494489] RBP: 00000000047ba600 R08:
00000000047971a0 R09: 000000000470d010
Jan  3 20:54:59 t44 kernel: [126159.494492] R10: 00007feace543a00 R11:
0000000000000246 R12: 0000000004721610
Jan  3 20:54:59 t44 kernel: [126159.494495] R13: 00000000047971a0 R14:
0000000000000000 R15: 0000000000000000
Jan  3 20:54:59 t44 kernel: [126159.494499]
================================================================================



--
Toralf
Randy Dunlap Jan. 3, 2021, 10:32 p.m. UTC | #5
On 1/3/21 1:40 PM, Toralf Förster wrote:
> On 12/30/20 10:05 AM, Toralf Förster wrote:
>> On 12/29/20 11:55 PM, Randy Dunlap wrote:
>>>> No, this is wrong.  'size' in this case is the size of the read.
>>>> And it's zero.  Is this fixed by commit
>>>> 3644e2d2dda78e21edd8f5415b6d7ab03f5f54f3
>>>>
>>> Toralf, can you test with 5.11-rc1 (or later)?
>>>
>>> thanks.
>>
>> My plan was to apply that commit on top of the upcoming 5.10.4 and test
>> that, just waiting in moment for Greg to release the stable version.
>>
> I commit 3644e2d2dda on top of 5.10.4 at my server - no issue so far. I
> did NOT patched my desktop (same stable hardened Gentoo Linux, same
> software and kernel versions) - and there it happened under 5.10.4 too:
> 
> Jan  3 20:54:59 t44 kernel: [126159.494365] UBSAN: shift-out-of-bounds
> in ./include/linux/log2.h:57:13
> Jan  3 20:54:59 t44 kernel: [126159.494371] shift exponent 64 is too
> large for 64-bit type 'long unsigned int'
> Jan  3 20:54:59 t44 kernel: [126159.494378] CPU: 0 PID: 16651 Comm: cc1
> Tainted: G        W       T 5.10.4 #5
> Jan  3 20:54:59 t44 kernel: [126159.494381] Hardware name: LENOVO
> 20AQCTO1WW/20AQCTO1WW, BIOS GJETA4WW (2.54 ) 03/27/2020
> Jan  3 20:54:59 t44 kernel: [126159.494383] Call Trace:
> Jan  3 20:54:59 t44 kernel: [126159.494397]  dump_stack+0x57/0x6a
> Jan  3 20:54:59 t44 kernel: [126159.494402]  ubsan_epilogue+0x5/0x40
> Jan  3 20:54:59 t44 kernel: [126159.494408]
> __ubsan_handle_shift_out_of_bounds.cold+0x61/0x10e
> Jan  3 20:54:59 t44 kernel: [126159.494419]
> ondemand_readahead.cold+0x16/0x21
> Jan  3 20:54:59 t44 kernel: [126159.494427]
> generic_file_buffered_read+0x43d/0x880
> Jan  3 20:54:59 t44 kernel: [126159.494437]  new_sync_read+0x15d/0x1f0
> Jan  3 20:54:59 t44 kernel: [126159.494442]  vfs_read+0xf5/0x190
> Jan  3 20:54:59 t44 kernel: [126159.494447]  ksys_read+0x65/0xe0
> Jan  3 20:54:59 t44 kernel: [126159.494453]  do_syscall_64+0x33/0x40
> Jan  3 20:54:59 t44 kernel: [126159.494460]
> entry_SYSCALL_64_after_hwframe+0x44/0xa9
> Jan  3 20:54:59 t44 kernel: [126159.494466] RIP: 0033:0x7feace476dfe
> Jan  3 20:54:59 t44 kernel: [126159.494472] Code: c0 e9 c6 fe ff ff 50
> 48 8d 3d de d6 09 00 e8 89 e4 01 00 66 0f 1f 84 00 00 00 00 00 64 8b 04
> 25 18 00 00 00 85 c0 75 14 0f 05 <48> 3d 00 f0 ff ff 77 5a c3 66 0f 1f
> 84 00 00 00 00 00 48 83 ec 28
> Jan  3 20:54:59 t44 kernel: [126159.494476] RSP: 002b:00007ffe122f4318
> EFLAGS: 00000246 ORIG_RAX: 0000000000000000
> Jan  3 20:54:59 t44 kernel: [126159.494483] RAX: ffffffffffffffda RBX:
> 0000000000000000 RCX: 00007feace476dfe
> Jan  3 20:54:59 t44 kernel: [126159.494486] RDX: 0000000000000000 RSI:
> 00000000047971a0 RDI: 0000000000000008
> Jan  3 20:54:59 t44 kernel: [126159.494489] RBP: 00000000047ba600 R08:
> 00000000047971a0 R09: 000000000470d010
> Jan  3 20:54:59 t44 kernel: [126159.494492] R10: 00007feace543a00 R11:
> 0000000000000246 R12: 0000000004721610
> Jan  3 20:54:59 t44 kernel: [126159.494495] R13: 00000000047971a0 R14:
> 0000000000000000 R15: 0000000000000000
> Jan  3 20:54:59 t44 kernel: [126159.494499]
> ================================================================================

OK, thanks for testing that commit and letting us know.
diff mbox series

Patch

--- linux-5.10.1.orig/mm/readahead.c
+++ linux-5.10.1/mm/readahead.c
@@ -310,7 +310,11 @@  void force_page_cache_ra(struct readahea
  */
 static unsigned long get_init_ra_size(unsigned long size, unsigned long max)
 {
-	unsigned long newsize = roundup_pow_of_two(size);
+	unsigned long newsize;
+
+	if (!size)
+		size = 32;
+	newsize = roundup_pow_of_two(size);
 
 	if (newsize <= max / 32)
 		newsize = newsize * 4;