Bug 219988

Summary: UBSAN: shift-out-of-bounds in xprt_calc_majortimeo
Product: File System Reporter: wangzhaolong1
Component: NFSAssignee: Trond Myklebust (trondmy)
Status: NEW ---    
Severity: normal    
Priority: P3    
Hardware: All   
OS: Linux   
Kernel Version: Subsystem:
Regression: No Bisected commit-id:

Description wangzhaolong1 2025-04-07 10:10:45 UTC
UBSAN and The UDP support of NFS must be enabled to reproduce the problem.

```
CONFIG_NFS_DISABLE_UDP_SUPPORT=n

CONFIG_ARCH_HAS_UBSAN=y
CONFIG_UBSAN=y
CONFIG_CC_HAS_UBSAN_BOUNDS_STRICT=y
CONFIG_UBSAN_BOUNDS=y
CONFIG_UBSAN_BOUNDS_STRICT=y
CONFIG_UBSAN_SHIFT=y
CONFIG_UBSAN_BOOL=y
CONFIG_UBSAN_ENUM=y
```

# Reproduction

```c
#define _GNU_SOURCE

#include <endian.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/syscall.h>
#include <sys/types.h>
#include <unistd.h>

#ifndef __NR_mkdirat
#define __NR_mkdirat 34
#endif
#ifndef __NR_mmap
#define __NR_mmap 222
#endif
#ifndef __NR_mount
#define __NR_mount 40
#endif

int main(void)
{
  syscall(__NR_mmap, 0x1ffff000ul, 0x1000ul, 0ul, 0x32ul, -1, 0ul);
  syscall(__NR_mmap, 0x20000000ul, 0x1000000ul, 7ul, 0x32ul, -1, 0ul);
  syscall(__NR_mmap, 0x21000000ul, 0x1000ul, 0ul, 0x32ul, -1, 0ul);

  memcpy((void*)0x200000c0, "./file0\000", 8);
  syscall(__NR_mkdirat, 0xffffff9c, 0x200000c0ul, 0ul);
  memcpy(
      (void*)0x20000300,
      "[\312\214M\276\341w5\016\177\002F9\327]:\024J\020\341m\3053\232S\""
      "\270+\037\255\363\035G\342\230\371~\257\375\273\231\252@A\017. "
      "|s\304Q^\324\324me\215O\026\307\276\336\262\234`\234\220g#\205q\rK.\203|"
      "R|9\352\025A`F\217\031\234Y\220\364V\267\2013\006 "
      "\246\201\363@wh/"
      "H\325\026W\023]M\263\3558\223\242^\302\356\035\010\224\0040\027^"
      "\363\226\342\334n\362\2006\033\030\341\226\345\346\356\374\355\247d3\203"
      "S",
      147);
  memcpy((void*)0x20000180, "./file0\000", 8);
  memcpy((void*)0x20000140, "nfs\000", 4);
  memcpy((void*)0x200003c0,
         "\001\000\000\000\016\364\253.\3540 "
         "\210\320\030*\245zN1\252\035\324hl\343\014\345\355\206\375\345\333\005`"
         "\372\367m\006\030\2068\332J\244\246\013\251\273Z\002r\034\230\202\253"
         "\231\307\201j\227\341\'aiE\\\346\003xi\2039Z\177\2408\002\000W\204$"
         "\t\366%\265\026\265|\3526\250U#\350N\213*\254\376\347\267\002]%"
         "\265\277\207\024\236AR\251\224_\026K\226\372gP5\226\007t\350h4}"
         "9\004\347\037\0262\307::\000\'\235\202\023`|"
         "NQtf\374J\036\237\212\013EQ=T\344\305\226\026I",
         163);
  *(uint8_t*)0x20000463 = 0x2c;
  *(uint8_t*)0x20000464 = 0;

   do {
     printf("Press the Enter key to continue.\n");
   } while (getchar() != '\n');

  syscall(__NR_mount, 0x20000300ul, 0x20000180ul, 0x20000140ul, 0x8000ul,
          0x200003c0ul);
  return 0;
}
```

# Reproduction Result

```
[   17.604361][  T291] UBSAN: shift-out-of-bounds in net/sunrpc/xprt.c:660:14
[   17.604375][  T291] shift exponent 2540339655 is too large for 64-bit type 'long unsigned int'
[   17.604388][  T291] CPU: 3 UID: 0 PID: 291 Comm: a.out Not tainted 6.15.0-rc1 #11 NONE 
[   17.604398][  T291] Hardware name: linux,dummy-virt (DT)
[   17.604402][  T291] Call trace:
[   17.604406][  T291]  show_stack+0x1c/0x30 (C)
[   17.604418][  T291]  dump_stack_lvl+0x80/0xe8
[   17.604428][  T291]  dump_stack+0x18/0x20
[   17.604435][  T291]  __ubsan_handle_shift_out_of_bounds+0x11c/0x200
[   17.604444][  T291]  xprt_init_majortimeo+0x198/0x1c0
[   17.604452][  T291]  xprt_request_init+0x124/0x1c0
[   17.604459][  T291]  xprt_reserve+0xb4/0x110
[   17.604466][  T291]  call_reserve+0x40/0x58
[   17.604474][  T291]  __rpc_execute+0x11c/0x630
[   17.604481][  T291]  rpc_execute+0x16c/0x280
[   17.604487][  T291]  rpc_run_task+0x1ec/0x2d0
[   17.604495][  T291]  rpc_call_null_helper+0x100/0x148
[   17.604504][  T291]  rpc_ping+0x74/0xb0
[   17.604511][  T291]  rpc_create_xprt+0x198/0x200
[   17.604519][  T291]  rpc_create+0x20c/0x3d8
[   17.604526][  T291]  nfs_create_rpc_client+0x328/0x3c8
[   17.604534][  T291]  nfs_init_client+0x58/0xb8
[   17.604541][  T291]  nfs_get_client+0x230/0x290
[   17.604547][  T291]  nfs_init_server.isra.0+0x178/0x698
[   17.604554][  T291]  nfs_create_server+0xac/0x350
[   17.604561][  T291]  nfs_try_get_tree+0x6c/0xc8
[   17.604568][  T291]  nfs_get_tree+0x78/0xc8
[   17.604576][  T291]  vfs_get_tree+0x50/0x160
[   17.604584][  T291]  do_new_mount+0x224/0x428
[   17.604593][  T291]  path_mount+0x244/0xaf8
[   17.604600][  T291]  __arm64_sys_mount+0x29c/0x3b0
[   17.604608][  T291]  invoke_syscall+0x64/0x190
[   17.604616][  T291]  el0_svc_common.constprop.0+0x7c/0x140
[   17.604623][  T291]  do_el0_svc+0x38/0x50
[   17.604629][  T291]  el0_svc+0x30/0xc0
[   17.604636][  T291]  el0t_64_sync_handler+0x13c/0x160
[   17.604644][  T291]  el0t_64_sync+0x17c/0x180
[   17.604651][  T291] ---[ end trace ]---
```
Comment 1 wangzhaolong1 2025-04-10 07:33:28 UTC
This problem can be easily reproduced by running the following command:

Ensure that UDP support is enabled for NFS server.

# grep udp= /etc/nfs.conf 
udp=y



Run the following command:

mount -t nfs 127.0.0.1:/s_test /mnt -o vers=3,proto=udp,retrans=101



[   96.658260] ------------[ cut here ]------------
[   96.658984] UBSAN: shift-out-of-bounds in net/sunrpc/xprt.c:660:14
[   96.659902] shift exponent 101 is too large for 64-bit type 'long unsigned int'
[   96.660983] CPU: 2 UID: 0 PID: 791 Comm: mount.nfs Not tainted 6.15.0-rc1+ #225 PREEMPT(undef) 
[   96.660988] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.16.1-2.fc37 04/01/2014
[   96.660990] Call Trace:
[   96.661007]  <TASK>
[   96.661021]  dump_stack_lvl+0x53/0x70
[   96.661035]  __ubsan_handle_shift_out_of_bounds+0x16a/0x320
[   96.661048]  ? d_instantiate+0x41/0x60
[   96.661054]  ? debugfs_create_symlink+0xde/0x150
[   96.661059]  xprt_init_majortimeo.cold+0x11/0x20 [sunrpc]
[   96.661170]  xprt_request_init+0xbe/0x110 [sunrpc]
[   96.661232]  ? __pfx_call_reserve+0x10/0x10 [sunrpc]
[   96.661271]  __rpc_execute+0xa6/0x300 [sunrpc]
[   96.661351]  rpc_execute+0x12f/0x150 [sunrpc]
[   96.661410]  rpc_run_task+0x103/0x160 [sunrpc]
[   96.661475]  rpc_call_null_helper+0x96/0xc0 [sunrpc]
[   96.661523]  rpc_ping+0x2d/0x50 [sunrpc]
[   96.661570]  rpc_create_xprt+0x12b/0x180 [sunrpc]
[   96.661617]  rpc_create+0x152/0x290 [sunrpc]
[   96.661664]  ? finish_task_switch.isra.0+0x21c/0x2d0
[   96.661670]  ? kmem_cache_free+0x356/0x400
[   96.661674]  ? finish_task_switch.isra.0+0x21c/0x2d0
[   96.661676]  ? __schedule+0x2fb/0x870
[   96.661680]  ? ttwu_queue_wakelist+0x10c/0x190
[   96.661683]  nfs_mount+0x150/0x2e0 [nfs]
[   96.661757]  nfs_request_mount.constprop.0.isra.0+0x16d/0x240 [nfs]
[   96.661794]  nfs_try_mount_request+0x73/0x320 [nfs]
[   96.661826]  ? find_nfs_version+0x4a/0xe0 [nfs]
[   96.661857]  nfs_try_get_tree+0x5e/0x60 [nfs]
[   96.661888]  vfs_get_tree+0x29/0xf0
[   96.661893]  do_new_mount+0x180/0x310
[   96.661897]  __x64_sys_mount+0x103/0x140
[   96.661900]  do_syscall_64+0x5f/0x170
[   96.661904]  entry_SYSCALL_64_after_hwframe+0x76/0x7e
[   96.661908] RIP: 0033:0x7f01dcead21e
[   96.661912] Code: 48 8b 0d 5d 1c 0c 00 f7 d8 64 89 01 48 83 c8 ff c3 66 2e 0f 1f 84 00 00 00 00 00 90 f3 0f 1e fa 49 89 ca b8 a5 00 00 00 0f 05 <48> 3d 01 f0 ff ff 73 01 c3 48 8b 0d 2a 1c 0c 00 f7 d8 64 89 01 48
[   96.661914] RSP: 002b:00007ffd0b70f698 EFLAGS: 00000246 ORIG_RAX: 00000000000000a5
[   96.661917] RAX: ffffffffffffffda RBX: 00007ffd0b70f890 RCX: 00007f01dcead21e
[   96.661918] RDX: 000056090e41fd90 RSI: 000056090e41fde0 RDI: 000056090e41fb70
[   96.661919] RBP: 000056090e421bf0 R08: 000056090e423180 R09: fefeff37332f2f31
[   96.661920] R10: 0000000000000000 R11: 0000000000000246 R12: 000056090e423180
[   96.661921] R13: 00007f01dcaf44c8 R14: 00005608f7bdc940 R15: 00007ffd0b70f890
[   96.661923]  </TASK>
[   96.694790] ---[ end trace ]---