Skip to content

Commit 3f802b1

Browse files
Leon Romanovskyjgunthorpe
Leon Romanovsky
authored andcommitted
RDMA/uverbs: Protect from command mask overflow
The command number is not bounds checked against the command mask before it is shifted, resulting in an ubsan hit. This does not cause malfunction since the command number is eventually bounds checked, but we can make this ubsan clean by moving the bounds check to before the mask check. ================================================================================ UBSAN: Undefined behaviour in drivers/infiniband/core/uverbs_main.c:647:21 shift exponent 207 is too large for 64-bit type 'long long unsigned int' CPU: 0 PID: 446 Comm: syz-executor3 Not tainted 4.15.0-rc2+ #61 Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS rel-1.7.5-0-ge51488c-20140602_164612-nilsson.home.kraxel.org 04/01/2014 Call Trace: dump_stack+0xde/0x164 ? dma_virt_map_sg+0x22c/0x22c ubsan_epilogue+0xe/0x81 __ubsan_handle_shift_out_of_bounds+0x293/0x2f7 ? debug_check_no_locks_freed+0x340/0x340 ? __ubsan_handle_load_invalid_value+0x19b/0x19b ? lock_acquire+0x440/0x440 ? lock_acquire+0x19d/0x440 ? __might_fault+0xf4/0x240 ? ib_uverbs_write+0x68d/0xe20 ib_uverbs_write+0x68d/0xe20 ? __lock_acquire+0xcf7/0x3940 ? uverbs_devnode+0x110/0x110 ? cyc2ns_read_end+0x10/0x10 ? sched_clock_cpu+0x18/0x200 ? sched_clock_cpu+0x18/0x200 __vfs_write+0x10d/0x700 ? uverbs_devnode+0x110/0x110 ? kernel_read+0x170/0x170 ? __fget+0x35b/0x5d0 ? security_file_permission+0x93/0x260 vfs_write+0x1b0/0x550 SyS_write+0xc7/0x1a0 ? SyS_read+0x1a0/0x1a0 ? trace_hardirqs_on_thunk+0x1a/0x1c entry_SYSCALL_64_fastpath+0x18/0x85 RIP: 0033:0x448e29 RSP: 002b:00007f033f567c58 EFLAGS: 00000246 ORIG_RAX: 0000000000000001 RAX: ffffffffffffffda RBX: 00007f033f5686bc RCX: 0000000000448e29 RDX: 0000000000000060 RSI: 0000000020001000 RDI: 0000000000000012 RBP: 000000000070bea0 R08: 0000000000000000 R09: 0000000000000000 R10: 0000000000000000 R11: 0000000000000246 R12: 00000000ffffffff R13: 00000000000056a0 R14: 00000000006e8740 R15: 0000000000000000 ================================================================================ Cc: syzkaller <syzkaller@googlegroups.com> Cc: <stable@vger.kernel.org> # 4.5 Fixes: 2dbd518 ("IB/core: IB/core: Allow legacy verbs through extended interfaces") Reported-by: Noa Osherovich <noaos@mellanox.com> Reviewed-by: Matan Barak <matanb@mellanox.com> Signed-off-by: Leon Romanovsky <leonro@mellanox.com> Signed-off-by: Jason Gunthorpe <jgg@mellanox.com>
1 parent ec6f840 commit 3f802b1

File tree

1 file changed

+20
-7
lines changed

1 file changed

+20
-7
lines changed

drivers/infiniband/core/uverbs_main.c

Lines changed: 20 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -650,12 +650,21 @@ static int verify_command_mask(struct ib_device *ib_dev, __u32 command)
650650
return -1;
651651
}
652652

653+
static bool verify_command_idx(u32 command, bool extended)
654+
{
655+
if (extended)
656+
return command < ARRAY_SIZE(uverbs_ex_cmd_table);
657+
658+
return command < ARRAY_SIZE(uverbs_cmd_table);
659+
}
660+
653661
static ssize_t ib_uverbs_write(struct file *filp, const char __user *buf,
654662
size_t count, loff_t *pos)
655663
{
656664
struct ib_uverbs_file *file = filp->private_data;
657665
struct ib_device *ib_dev;
658666
struct ib_uverbs_cmd_hdr hdr;
667+
bool extended_command;
659668
__u32 command;
660669
__u32 flags;
661670
int srcu_key;
@@ -688,6 +697,15 @@ static ssize_t ib_uverbs_write(struct file *filp, const char __user *buf,
688697
}
689698

690699
command = hdr.command & IB_USER_VERBS_CMD_COMMAND_MASK;
700+
flags = (hdr.command &
701+
IB_USER_VERBS_CMD_FLAGS_MASK) >> IB_USER_VERBS_CMD_FLAGS_SHIFT;
702+
703+
extended_command = flags & IB_USER_VERBS_CMD_FLAG_EXTENDED;
704+
if (!verify_command_idx(command, extended_command)) {
705+
ret = -EINVAL;
706+
goto out;
707+
}
708+
691709
if (verify_command_mask(ib_dev, command)) {
692710
ret = -EOPNOTSUPP;
693711
goto out;
@@ -699,12 +717,8 @@ static ssize_t ib_uverbs_write(struct file *filp, const char __user *buf,
699717
goto out;
700718
}
701719

702-
flags = (hdr.command &
703-
IB_USER_VERBS_CMD_FLAGS_MASK) >> IB_USER_VERBS_CMD_FLAGS_SHIFT;
704-
705720
if (!flags) {
706-
if (command >= ARRAY_SIZE(uverbs_cmd_table) ||
707-
!uverbs_cmd_table[command]) {
721+
if (!uverbs_cmd_table[command]) {
708722
ret = -EINVAL;
709723
goto out;
710724
}
@@ -725,8 +739,7 @@ static ssize_t ib_uverbs_write(struct file *filp, const char __user *buf,
725739
struct ib_udata uhw;
726740
size_t written_count = count;
727741

728-
if (command >= ARRAY_SIZE(uverbs_ex_cmd_table) ||
729-
!uverbs_ex_cmd_table[command]) {
742+
if (!uverbs_ex_cmd_table[command]) {
730743
ret = -ENOSYS;
731744
goto out;
732745
}

0 commit comments

Comments
 (0)