luainkernel / lunatik

Lunatik is a framework for scripting the Linux kernel with Lua.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

investigate UBSAN: array-index-out-of-bounds

lneto opened this issue · comments

[ 6852.106541] UBSAN: array-index-out-of-bounds in /home/ubuntu/lunatik/lua/lstring.c:152:13
[ 6852.106959] index 17 is out of range for type 'char [1]'
[ 6852.107059] CPU: 5 PID: 3151 Comm: modprobe Tainted: P           OE      6.5.0-25-generic #25~22.04.1-Ubuntu
[ 6852.107060] Hardware name: QEMU QEMU Virtual Machine, BIOS 0.0.0 02/06/2015
[ 6852.107061] Call trace:
[ 6852.107067]  dump_backtrace+0xa4/0x150
[ 6852.107071]  show_stack+0x24/0x50
[ 6852.107084]  dump_stack_lvl+0x78/0xf8
[ 6852.107103]  dump_stack+0x1c/0x38
[ 6852.107104]  __ubsan_handle_out_of_bounds+0xe0/0x138
[ 6852.107117]  internshrstr+0x1dc/0x1f8 [lunatik]
[ 6852.107130]  luaS_init+0x6c/0x118 [lunatik]
[ 6852.107138]  f_luaopen+0x8c/0xe0 [lunatik]
[ 6852.107146]  luaD_rawrunprotected+0x6c/0xb8 [lunatik]
[ 6852.107154]  lua_newstate+0x150/0x1b8 [lunatik]
[ 6852.107161]  luaL_newstate+0x2c/0x88 [lunatik]
[ 6852.107170]  lunatik_newruntime+0x38/0x308 [lunatik]
[ 6852.107178]  lunatik_runtime+0x2c/0x60 [lunatik]
[ 6852.107186]  lunatik_run_init+0x30/0xff8 [lunatik_run]
[ 6852.107189]  do_one_initcall+0x64/0x3b8
[ 6852.107190]  do_init_module+0x64/0x258
[ 6852.107196]  load_module+0x7b0/0x8e0
[ 6852.107197]  init_module_from_file+0x94/0x110
[ 6852.107199]  idempotent_init_module+0x194/0x2b0
[ 6852.107200]  __arm64_sys_finit_module+0x74/0x100
[ 6852.107202]  invoke_syscall+0x7c/0x130
[ 6852.107203]  el0_svc_common.constprop.0+0x5c/0x170
[ 6852.107203]  do_el0_svc+0x38/0x68
[ 6852.107204]  el0_svc+0x30/0xe0
[ 6852.107206]  el0t_64_sync_handler+0x128/0x158
[ 6852.107208]  el0t_64_sync+0x1b0/0x1b8
[ 6852.107209] ================================================================================
[ 6852.107384] ================================================================================
[ 6852.107540] UBSAN: array-index-out-of-bounds in /home/ubuntu/lunatik/lua/lstring.c:152:13
[ 6852.107691] index 50 is out of range for type 'char [1]'
[ 6852.107790] CPU: 5 PID: 3151 Comm: modprobe Tainted: P           OE      6.5.0-25-generic #25~22.04.1-Ubuntu
[ 6852.107791] Hardware name: QEMU QEMU Virtual Machine, BIOS 0.0.0 02/06/2015
[ 6852.107791] Call trace:
[ 6852.107791]  dump_backtrace+0xa4/0x150
[ 6852.107792]  show_stack+0x24/0x50
[ 6852.107801]  dump_stack_lvl+0x78/0xf8
[ 6852.107802]  dump_stack+0x1c/0x38
[ 6852.107804]  __ubsan_handle_out_of_bounds+0xe0/0x138
[ 6852.107805]  luaS_newlstr+0x110/0x120 [lunatik]
[ 6852.107813]  luaS_new+0xb8/0x120 [lunatik]
[ 6852.107821]  lua_pushstring+0x28/0xa0 [lunatik]
[ 6852.107829]  luaopen_package+0x170/0x2a8 [lunatik]
[ 6852.107837]  luaD_precall+0xc0/0x2b8 [lunatik]
[ 6852.107845]  luaD_callnoyield+0x58/0xf8 [lunatik]
[ 6852.107852]  lua_callk+0x50/0x100 [lunatik]
[ 6852.107860]  luaL_requiref+0xf8/0x188 [lunatik]
[ 6852.107868]  luaL_openlibs+0x48/0xb0 [lunatik]
[ 6852.107876]  lunatik_newruntime+0xc8/0x308 [lunatik]
[ 6852.107884]  lunatik_runtime+0x2c/0x60 [lunatik]
[ 6852.107891]  lunatik_run_init+0x30/0xff8 [lunatik_run]
[ 6852.107894]  do_one_initcall+0x64/0x3b8
[ 6852.107895]  do_init_module+0x64/0x258
[ 6852.107896]  load_module+0x7b0/0x8e0
[ 6852.107898]  init_module_from_file+0x94/0x110
[ 6852.107899]  idempotent_init_module+0x194/0x2b0
[ 6852.107900]  __arm64_sys_finit_module+0x74/0x100
[ 6852.107902]  invoke_syscall+0x7c/0x130
[ 6852.107902]  el0_svc_common.constprop.0+0x5c/0x170
[ 6852.107903]  do_el0_svc+0x38/0x68
[ 6852.107904]  el0_svc+0x30/0xe0
[ 6852.107906]  el0t_64_sync_handler+0x128/0x158
[ 6852.107908]  el0t_64_sync+0x1b0/0x1b8
[ 6852.107908] ================================================================================
================================================================================
[ 6852.108377] UBSAN: array-index-out-of-bounds in /home/ubuntu/lunatik/lua/lfunc.c:40:30
[ 6852.108524] index 1 is out of range for type 'UpVal *[1]'
[ 6852.108624] CPU: 5 PID: 3151 Comm: modprobe Tainted: P           OE      6.5.0-25-generic #25~22.04.1-Ubuntu
[ 6852.108625] Hardware name: QEMU QEMU Virtual Machine, BIOS 0.0.0 02/06/2015
[ 6852.108625] Call trace:
[ 6852.108625]  dump_backtrace+0xa4/0x150
[ 6852.108627]  show_stack+0x24/0x50
[ 6852.108628]  dump_stack_lvl+0x78/0xf8
[ 6852.108629]  dump_stack+0x1c/0x38
[ 6852.108630]  __ubsan_handle_out_of_bounds+0xe0/0x138
[ 6852.108632]  luaF_newLclosure+0xa8/0xb8 [lunatik]
[ 6852.108641]  luaV_execute+0xed8/0x3bb8 [lunatik]
[ 6852.108648]  luaD_callnoyield+0x70/0xf8 [lunatik]
[ 6852.108656]  f_call+0x28/0x58 [lunatik]
[ 6852.108664]  luaD_rawrunprotected+0x6c/0xb8 [lunatik]
[ 6852.108672]  luaD_pcall+0x44/0xf8 [lunatik]
[ 6852.108679]  lua_pcallk+0xa0/0x198 [lunatik]
[ 6852.108687]  lunatik_newruntime+0x118/0x308 [lunatik]
[ 6852.108695]  lunatik_runtime+0x2c/0x60 [lunatik]
[ 6852.108703]  lunatik_run_init+0x30/0xff8 [lunatik_run]
[ 6852.108705]  do_one_initcall+0x64/0x3b8
[ 6852.108706]  do_init_module+0x64/0x258
[ 6852.108707]  load_module+0x7b0/0x8e0
[ 6852.108709]  init_module_from_file+0x94/0x110
[ 6852.108710]  idempotent_init_module+0x194/0x2b0
[ 6852.108711]  __arm64_sys_finit_module+0x74/0x100
[ 6852.108713]  invoke_syscall+0x7c/0x130
[ 6852.108713]  el0_svc_common.constprop.0+0x5c/0x170
[ 6852.108714]  do_el0_svc+0x38/0x68
[ 6852.108715]  el0_svc+0x30/0xe0
[ 6852.108717]  el0t_64_sync_handler+0x128/0x158
[ 6852.108719]  el0t_64_sync+0x1b0/0x1b8
[ 6852.108719] ================================================================================
[ 6852.108875] ================================================================================
[ 6852.109030] UBSAN: array-index-out-of-bounds in /home/ubuntu/lunatik/lua/lvm.c:842:18
[ 6852.109175] index 1 is out of range for type 'UpVal *[1]'
[ 6852.109275] CPU: 5 PID: 3151 Comm: modprobe Tainted: P           OE      6.5.0-25-generic #25~22.04.1-Ubuntu
[ 6852.109275] Hardware name: QEMU QEMU Virtual Machine, BIOS 0.0.0 02/06/2015
[ 6852.109276] Call trace:
[ 6852.109276]  dump_backtrace+0xa4/0x150
[ 6852.109277]  show_stack+0x24/0x50
[ 6852.109278]  dump_stack_lvl+0x78/0xf8
[ 6852.109279]  dump_stack+0x1c/0x38
[ 6852.109281]  __ubsan_handle_out_of_bounds+0xe0/0x138
[ 6852.109282]  luaV_execute+0x3b08/0x3bb8 [lunatik]
[ 6852.109290]  luaD_callnoyield+0x70/0xf8 [lunatik]
[ 6852.109298]  f_call+0x28/0x58 [lunatik]
[ 6852.109305]  luaD_rawrunprotected+0x6c/0xb8 [lunatik]
[ 6852.109313]  luaD_pcall+0x44/0xf8 [lunatik]
[ 6852.109321]  lua_pcallk+0xa0/0x198 [lunatik]
[ 6852.109329]  lunatik_newruntime+0x118/0x308 [lunatik]
[ 6852.109336]  lunatik_runtime+0x2c/0x60 [lunatik]
[ 6852.109344]  lunatik_run_init+0x30/0xff8 [lunatik_run]
[ 6852.109347]  do_one_initcall+0x64/0x3b8
[ 6852.109348]  do_init_module+0x64/0x258
[ 6852.109349]  load_module+0x7b0/0x8e0
[ 6852.109350]  init_module_from_file+0x94/0x110
[ 6852.109351]  idempotent_init_module+0x194/0x2b0
[ 6852.109353]  __arm64_sys_finit_module+0x74/0x100
[ 6852.109354]  invoke_syscall+0x7c/0x130
[ 6852.109355]  el0_svc_common.constprop.0+0x5c/0x170
[ 6852.109356]  do_el0_svc+0x38/0x68
[ 6852.109357]  el0_svc+0x30/0xe0
[ 6852.109358]  el0t_64_sync_handler+0x128/0x158
[ 6852.109360]  el0t_64_sync+0x1b0/0x1b8
[ 6852.109361] ================================================================================
commented

I think it's the same kind of error as mentioned here, due to the definition of TString here as

typedef struct TString {
  CommonHeader;
  lu_byte extra;  /* reserved words for short strings; "has hash" for longs */
  lu_byte shrlen;  /* length for short strings */
  unsigned int hash;
  union {
    size_t lnglen;  /* length for long strings */
    struct TString *hnext;  /* linked list for hash table */
  } u;
  char contents[1];
} TString;

The undefined behavior sanitizer is comparing the compile-time definition of the size of contents as 1, and the writing at arbitrary indexes that Lua do at runtime, after allocating the struct dynamically. Could be safely ignored, (I think), or the declarations could be updated to C99 flexible array members, given that Lunatik embedded Lua does not maintain the c89 build target ? I found only 4 of them ...

$ grep -r '\[1\]' *.h
lobject.h:  char contents[1];
lobject.h:  UValue uv[1];  /* user values */
lobject.h:  TValue upvalue[1];  /* list of upvalues */
lobject.h:  UpVal *upvals[1];  /* list of upvalues */

perhaps it's a good idea to change it to flexible array members to get rid of this warning..

commented

I'll submit a pull request soon then.

I would put more thoughts on pros and cons on doing that change.. and if we have the proper motivation, we need to implement it with "#ifdefs" on Lua code to make it explicit that they are our changes.. this facilitates the synchronization with upstream Lua..

commented

OK. Checking for _KERNEL to enable it then ?

commented

@lneto I can't replicate the issue on my side (checked my log, no occurences). I just sent the pull request to the luainkernel/lua repo. Can you check if the messages go away on your side ?

@lneto I can't replicate the issue on my side (checked my log, no occurences). I just sent the pull request to the luainkernel/lua repo. Can you check if the messages go away on your side ?

you should enable UBSAN on your kernel to reproduce.. will take a look..

@glk0 I think the best path is to try to disable the verification for those particular files.. the real work for this issue is to reproduce the problem and play around with build parameters.. the change for flexible array members is really simple, but not desirable as we would need to maintain the patch every time we update Lua..

commented

you should enable UBSAN on your kernel to reproduce.. will take a look..

Did on Linux 6.8. Getting segfault each time I'm running lunatik load

[  125.007460] invalid opcode: 0000 [#1] PREEMPT SMP NOPTI
[  125.007963] CPU: 1 PID: 504 Comm: modprobe Tainted: G           O       6.8.0-g9187210eee7d #4 ccddf0a51eaa1b0fcc156206c1de6c52c29c381f
[  125.007963] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS Arch Linux 1.16.3-1-1 04/01/2014
[  125.007963] RIP: 0010:internshrstr+0x175/0x190 [lunatik]
[  125.007963] Code: 8b 45 3c 89 44 24 04 eb ce 48 8b 7c 24 08 be 01 00 00 00 e8 ad 81 ff ff 81 7d 38 ff ff ff 7f 74 0b 8b 45 3c 89 44 24 04 eb a3 <0f4
[  125.007963] RSP: 0018:ffff9a24003cfbd0 EFLAGS: 00000206
[  125.007963] RAX: ffff98a9c37d0700 RBX: ffff98a9c37d0700 RCX: 00000000001a5401
[  125.007963] RDX: ffff98a9c37d02c0 RSI: ffffffff9b82a85b RDI: 0000000000000000
[  125.007963] RBP: ffff98a9c263e0d0 R08: 0000000000000000 R09: 0000000000000000
[  125.007963] R10: ffff9a24003cfb60 R11: 0000000000000000 R12: ffffffffc01c7fe2
[  125.007963] R13: 000000002820938c R14: 0000000000000011 R15: ffff98a9c244a060
[  125.007963] FS:  00007ffaf7110540(0000) GS:ffff98a9df480000(0000) knlGS:0000000000000000
[  125.007963] CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[  125.007963] CR2: 0000562037aa7398 CR3: 0000000010860000 CR4: 00000000000006f0
[  125.007963] Call Trace:
[  125.007963]  <TASK>
[  125.007963]  ? die+0x31/0x80
[  125.007963]  ? do_trap+0xd8/0x100
[  125.007963]  ? internshrstr+0x175/0x190 [lunatik 26c3df8339cb59a16167ffc9cbb4d5b022a41098]
[  125.007963]  ? do_error_trap+0x60/0x80
[  125.007963]  ? internshrstr+0x175/0x190 [lunatik 26c3df8339cb59a16167ffc9cbb4d5b022a41098]
[  125.007963]  ? exc_invalid_op+0x51/0x70
[  125.007963]  ? internshrstr+0x175/0x190 [lunatik 26c3df8339cb59a16167ffc9cbb4d5b022a41098]
[  125.007963]  ? asm_exc_invalid_op+0x1a/0x20
[  125.007963]  ? krealloc+0x7b/0xc0
[  125.007963]  ? internshrstr+0x175/0x190 [lunatik 26c3df8339cb59a16167ffc9cbb4d5b022a41098]
[  125.007963]  ? __pfx_l_alloc+0x10/0x10 [lunatik 26c3df8339cb59a16167ffc9cbb4d5b022a41098]
[  125.007963]  luaS_init+0x63/0xb0 [lunatik 26c3df8339cb59a16167ffc9cbb4d5b022a41098]
[  125.007963]  f_luaopen+0x66/0x90 [lunatik 26c3df8339cb59a16167ffc9cbb4d5b022a41098]
[  125.007963]  luaD_rawrunprotected+0x7f/0xc0 [lunatik 26c3df8339cb59a16167ffc9cbb4d5b022a41098]
[  125.007963]  ? __pfx_f_luaopen+0x10/0x10 [lunatik 26c3df8339cb59a16167ffc9cbb4d5b022a41098]
[  125.007963]  ? __pfx_l_alloc+0x10/0x10 [lunatik 26c3df8339cb59a16167ffc9cbb4d5b022a41098]
[  125.007963]  ? luaD_rawrunprotected+0x64/0xc0 [lunatik 26c3df8339cb59a16167ffc9cbb4d5b022a41098]
[  125.007963]  lua_newstate+0x263/0x290 [lunatik 26c3df8339cb59a16167ffc9cbb4d5b022a41098]
[  125.007963]  ? __pfx_lunatik_run_init+0x10/0x10 [lunatik_run 0e7d1dab41ed695d9d28d89ba6b1549bd2b69e03]
[  125.007963]  luaL_newstate+0x13/0x50 [lunatik 26c3df8339cb59a16167ffc9cbb4d5b022a41098]
[  125.007963]  ? __pfx_lunatik_run_init+0x10/0x10 [lunatik_run 0e7d1dab41ed695d9d28d89ba6b1549bd2b69e03]
[  125.007963]  lunatik_newruntime+0x2f/0x2a0 [lunatik 26c3df8339cb59a16167ffc9cbb4d5b022a41098]
[  125.007963]  ? __pfx_lunatik_run_init+0x10/0x10 [lunatik_run 0e7d1dab41ed695d9d28d89ba6b1549bd2b69e03]
[  125.007963]  do_one_initcall+0x56/0x220
[  125.007963]  do_init_module+0x5b/0x210
[  125.007963]  init_module_from_file+0x81/0xc0
[  125.007963]  idempotent_init_module+0x11b/0x2b0
[  125.007963]  __x64_sys_finit_module+0x51/0x90
[  125.007963]  do_syscall_64+0xa5/0x1b0
[  125.007963]  entry_SYSCALL_64_after_hwframe+0x6d/0x75
[  125.007963] RIP: 0033:0x7ffaf6c1d539
[  125.007963] Code: 00 f3 c3 66 2e 0f 1f 84 00 00 00 00 00 0f 1f 40 00 48 89 f8 48 89 f7 48 89 d6 48 89 ca 4d 89 c2 4d 89 c8 4c 8b 4c 24 08 0f 05 <488
[  125.007963] RSP: 002b:00007fffe254c738 EFLAGS: 00000246 ORIG_RAX: 0000000000000139
[  125.007963] RAX: ffffffffffffffda RBX: 0000562037aa2a80 RCX: 00007ffaf6c1d539
[  125.007963] RDX: 0000000000000000 RSI: 000056201821bcee RDI: 0000000000000003
[  125.007963] RBP: 000056201821bcee R08: 0000000000000000 R09: 0000562037aa2a80
[  125.007963] R10: 0000000000000003 R11: 0000000000000246 R12: 0000000000000000
[  125.007963] R13: 0000562037aaa630 R14: 0000000000040000 R15: 0000562037aa2a80
[  125.007963]  </TASK>
[  125.007963] Modules linked in: lunatik_run(O+) luasyscall(O) luaprobe(O) luadata(O) luafib(O) luathread(O) luarcu(O) luasocket(O) luanotifier(O) lu)

The source seems to be the internshrstr function, and I'm not seeing any informative message ...

can you indicate the exact steps you are making to enable it?

is it running normally without UBSAN?

are you running master?

commented

can you indicate the exact steps you are making to enable it?
I edited .config and recompiled the kernel. After,

$ zcat /proc/config.gz |  grep -i ubsan 
CONFIG_ARCH_HAS_UBSAN=y
CONFIG_UBSAN=y
CONFIG_UBSAN_TRAP=y
CONFIG_CC_HAS_UBSAN_BOUNDS_STRICT=y
CONFIG_UBSAN_BOUNDS=y
CONFIG_UBSAN_BOUNDS_STRICT=y
CONFIG_UBSAN_SHIFT=y
CONFIG_UBSAN_DIV_ZERO=y
CONFIG_UBSAN_SIGNED_WRAP=y
CONFIG_UBSAN_BOOL=y
CONFIG_UBSAN_ENUM=y
CONFIG_TEST_UBSAN=m

I'm running master, and it was running normally before. I initlally just enabled all of them, but I'm recompiling without CONFIG_UBSAN_TRAP now.

you may try my config..

CONFIG_ARCH_HAS_UBSAN_SANITIZE_ALL=y
CONFIG_UBSAN=y
# CONFIG_UBSAN_TRAP is not set
CONFIG_CC_HAS_UBSAN_BOUNDS_STRICT=y
CONFIG_UBSAN_BOUNDS=y
CONFIG_UBSAN_BOUNDS_STRICT=y
CONFIG_UBSAN_SHIFT=y
# CONFIG_UBSAN_DIV_ZERO is not set
# CONFIG_UBSAN_UNREACHABLE is not set
CONFIG_UBSAN_BOOL=y
CONFIG_UBSAN_ENUM=y
# CONFIG_UBSAN_ALIGNMENT is not set
CONFIG_UBSAN_SANITIZE_ALL=y
# CONFIG_TEST_UBSAN is not set
commented

I can now replicate the issue.