* [BUG] KASAN: slab-out-of-bounds Write in gb_hid_raw_request
@ 2026-09-10 1:38 Farhad Alemi
2026-09-10 6:10 ` Greg Kroah-Hartman
0 siblings, 1 reply; 2+ messages in thread
From: Farhad Alemi @ 2026-09-10 1:38 UTC (permalink / raw)
To: Viresh Kumar, Johan Hovold, Alex Elder, Greg Kroah-Hartman
Cc: Farhad Alemi, greybus-dev, linux-staging, linux-kernel
[-- Attachment #1: Type: text/plain, Size: 11087 bytes --]
Hello,
We are reporting the following crash (reproducer and a proposed patch attached):
Linux version 7.3.0-rc2 50d05c7c76c96b90462f24debacca971d2e86713
Build Config: UpstreamAppArmorKASAN (KASAN + UBSAN, panic_on_warn=1)
[ 44.000772][ T804] usb 3-1: new high-speed USB device number 2
using dummy_hcd
[ 44.163699][ T804] usb 3-1: New USB device found, idVendor=18d1,
idProduct=1eaf, bcdDevice= 1.00
[ 44.169786][ T804] usb 3-1: New USB device strings: Mfr=0,
Product=0, SerialNumber=0
[ 44.212054][ T12] greybus 1-svc: set power mode = 0
[ 44.212064][ T12] greybus 1-svc: power mode change failed on AP
to switch link: -5
[ 44.213758][ C1] greybus greybus1: 0/0:0: short response 0x94
received (8 < 9)
[ 44.215179][ T9337] greybus greybus1: 0/0:0: synchronous operation
id 0x0003 of type 0x14 failed: -90
[ 44.215216][ T9337] greybus 1-svc: failed to get rail count: -90
[ 44.234071][ T9337] greybus 1-2.2: Interface added (greybus)
[ 44.234080][ T9337] greybus 1-2.2: GMP VID=0x00000001, PID=0x00000001
[ 44.234087][ T9337] greybus 1-2.2: DDBL1 Manufacturer=0x00000126,
Product=0x00000001
[ 44.256005][ T9337] hid-generic 0000:0001:0002.0001: hidraw0:
<UNKNOWN> HID v1.11 Device [1-2.2.1 0001:0002] on
[ 44.295710][ T9495]
==================================================================
[ 44.295718][ T9495] BUG: KASAN: slab-out-of-bounds in
gb_hid_raw_request+0x29c/0x860
[ 44.295741][ T9495] Write of size 2 at addr ffff88810d471a0a by
task repro/9495
[ 44.295747][ T9495]
[ 44.295758][ T9495] CPU: 1 UID: 0 PID: 9495 Comm: repro Not tainted
7.3.0-rc2-00099-g50d05c7c76c9 #1 PREEMPT(full)
[ 44.295767][ T9495] Hardware name: QEMU Standard PC (Q35 + ICH9,
2009), BIOS 1.17.0-debian-1.17.0-1ubuntu1 04/01/2014
[ 44.295775][ T9495] Call Trace:
[ 44.295779][ T9495] <TASK>
[ 44.295784][ T9495] dump_stack_lvl+0xe8/0x150
[ 44.295794][ T9495] print_address_description+0x55/0x1e0
[ 44.295802][ T9495] ? gb_hid_raw_request+0x29c/0x860
[ 44.295809][ T9495] print_report+0x58/0x70
[ 44.295815][ T9495] kasan_report+0x117/0x150
[ 44.295826][ T9495] ? gb_hid_raw_request+0x29c/0x860
[ 44.295834][ T9495] kasan_check_range+0x264/0x2c0
[ 44.295843][ T9495] ? gb_hid_raw_request+0x29c/0x860
[ 44.295849][ T9495] __asan_memcpy+0x40/0x70
[ 44.295858][ T9495] gb_hid_raw_request+0x29c/0x860
[ 44.295865][ T9495] ? __pfx_gb_hid_raw_request+0x10/0x10
[ 44.295873][ T9495] ? __hid_hw_raw_request+0xa7/0x140
[ 44.295883][ T9495] hidraw_send_report+0x2bf/0x540
[ 44.295892][ T9495] ? bpf_lsm_file_permission+0x9/0x20
[ 44.295901][ T9495] hidraw_write+0x91/0xd0
[ 44.295908][ T9495] ? __pfx_hidraw_write+0x10/0x10
[ 44.295916][ T9495] vfs_write+0x29a/0xb90
[ 44.295924][ T9495] ? __pfx_vfs_write+0x10/0x10
[ 44.295931][ T9495] ? __fget_files+0x2a/0x420
[ 44.295939][ T9495] ? __fget_files+0x2a/0x420
[ 44.295944][ T9495] ? __fget_files+0x3a0/0x420
[ 44.295950][ T9495] ? __fget_files+0x2a/0x420
[ 44.295958][ T9495] ksys_write+0x150/0x270
[ 44.295965][ T9495] ? __pfx_ksys_write+0x10/0x10
[ 44.295973][ T9495] do_syscall_64+0x155/0x510
[ 44.295984][ T9495] ? trace_irq_disable+0x3b/0x140
[ 44.295993][ T9495] ? entry_SYSCALL_64_after_hwframe+0x77/0x7f
[ 44.296000][ T9495] ? clear_bhb_loop+0x30/0x80
[ 44.296007][ T9495] entry_SYSCALL_64_after_hwframe+0x77/0x7f
[ 44.296014][ T9495] RIP: 0033:0x4521d2
[ 44.296024][ T9495] Code: 08 0f 85 e1 df ff ff 49 89 fb 48 89 f0 48
89 d7 48 89 ce 4c 89 c2 4d 89 ca 4c 8b 44 24 08 4c 8b 4c 24 10 4c 89
5c 24 08 0f 05 <c3> 66 2e 0f 1f 84 00 00 00 00 00 0f 1f 00 f3 0f 1e fa
55 48 89 e5
[ 44.296032][ T9495] RSP: 002b:00007ffcc5937968 EFLAGS: 00000246
ORIG_RAX: 0000000000000001
[ 44.296042][ T9495] RAX: ffffffffffffffda RBX: 0000000000000001
RCX: 00000000004521d2
[ 44.296046][ T9495] RDX: 0000000000000002 RSI: 00007ffcc5937af6
RDI: 0000000000000004
[ 44.296051][ T9495] RBP: 00007ffcc5937990 R08: 0000000000000000
R09: 0000000000000000
[ 44.296055][ T9495] R10: 0000000000000000 R11: 0000000000000246
R12: 00007ffcc5937c28
[ 44.296059][ T9495] R13: 00007ffcc5937c38 R14: 0000000000000002
R15: 00000000004cba40
[ 44.296066][ T9495] </TASK>
[ 44.296068][ T9495]
[ 44.296071][ T9495] Allocated by task 9495:
[ 44.296075][ T9495] kasan_save_track+0x3e/0x80
[ 44.296082][ T9495] __kasan_kmalloc+0x93/0xb0
[ 44.296090][ T9495] __kmalloc_noprof+0x36f/0x720
[ 44.296097][ T9495] gb_operation_message_alloc+0x8c/0x280
[ 44.296104][ T9495] gb_operation_create_common+0xa9/0x650
[ 44.296111][ T9495] gb_operation_create_flags+0xa2/0x2d0
[ 44.296117][ T9495] gb_hid_raw_request+0x1e6/0x860
[ 44.296123][ T9495] hidraw_send_report+0x2bf/0x540
[ 44.296130][ T9495] hidraw_write+0x91/0xd0
[ 44.296137][ T9495] vfs_write+0x29a/0xb90
[ 44.296142][ T9495] ksys_write+0x150/0x270
[ 44.296148][ T9495] do_syscall_64+0x155/0x510
[ 44.296156][ T9495] entry_SYSCALL_64_after_hwframe+0x77/0x7f
[ 44.296162][ T9495]
[ 44.296163][ T9495] The buggy address belongs to the object at
ffff88810d471a00
[ 44.296163][ T9495] which belongs to the cache kmalloc-16 of size 16
[ 44.296170][ T9495] The buggy address is located 10 bytes inside of
[ 44.296170][ T9495] allocated 11-byte region [ffff88810d471a00,
ffff88810d471a0b)
[ 44.296177][ T9495]
[ 44.296179][ T9495] The buggy address belongs to the physical page:
[ 44.296186][ T9495] page: refcount:0 mapcount:0
mapping:0000000000000000 index:0x0 pfn:0x10d471
[ 44.296193][ T9495] flags: 0x57ff00000000000(node=1|zone=2|lastcpupid=0x7ff)
[ 44.296202][ T9495] page_type: f5(slab)
[ 44.296212][ T9495] raw: 057ff00000000000 ffff88801b041640
dead000000000100 dead000000000122
[ 44.296217][ T9495] raw: 0000000000000000 0000000000800080
00000000f5000000 0000000000000000
[ 44.296220][ T9495] page dumped because: kasan: bad access detected
[ 44.296226][ T9495] page_owner tracks the page as allocated
[ 44.296229][ T9495] page last allocated via order 0, migratetype
Unmovable, gfp_mask
0xd2c00(GFP_NOIO|__GFP_NOWARN|__GFP_NORETRY|__GFP_COMP|__GFP_NOMEMALLOC),
pid 1, tgid 1 (swapper/0), ts 3657058998
[ 44.296240][ T9495] post_alloc_hook+0x1f9/0x250
[ 44.296247][ T9495] get_page_from_freelist+0x235a/0x23e0
[ 44.296255][ T9495] __alloc_frozen_pages_noprof+0x217/0x5a0
[ 44.296262][ T9495] allocate_slab+0x7d/0x610
[ 44.296267][ T9495] refill_objects+0x2d6/0x350
[ 44.296272][ T9495] __pcs_replace_empty_main+0x2c9/0x6c0
[ 44.296281][ T9495] __kmalloc_noprof+0x48b/0x720
[ 44.296288][ T9495] usb_hcd_submit_urb+0x7a3/0x1b40
[ 44.296301][ T9495] usb_start_wait_urb+0x13f/0x5b0
[ 44.296308][ T9495] usb_control_msg+0x234/0x3e0
[ 44.296314][ T9495] hub_power_on+0x1b6/0x460
[ 44.296320][ T9495] hub_activate+0x345/0x1a80
[ 44.296327][ T9495] hub_probe+0x291e/0x3c10
[ 44.296334][ T9495] usb_probe_interface+0x71f/0xe00
[ 44.296342][ T9495] really_probe+0x267/0xaf0
[ 44.296366][ T9495] __driver_probe_device+0x1e2/0x350
[ 44.296372][ T9495] page_owner free stack trace missing
[ 44.296375][ T9495]
[ 44.296377][ T9495] Memory state around the buggy address:
[ 44.296381][ T9495] ffff88810d471900: 00 04 fc fc 00 07 fc fc 00
00 fc fc 00 01 fc fc
[ 44.296385][ T9495] ffff88810d471980: 00 01 fc fc 00 01 fc fc fa
fb fc fc 00 01 fc fc
[ 44.296389][ T9495] >ffff88810d471a00: 00 03 fc fc fa fb fc fc fa
fb fc fc 00 01 fc fc
[ 44.296393][ T9495] ^
[ 44.296396][ T9495] ffff88810d471a80: fa fb fc fc fa fb fc fc 00
00 fc fc 00 01 fc fc
[ 44.296400][ T9495] ffff88810d471b00: 00 01 fc fc 00 01 fc fc 00
05 fc fc 00 05 fc fc
[ 44.296404][ T9495]
==================================================================
[ 44.297569][ T9495] Kernel panic - not syncing: KASAN: panic_on_warn set ...
[ 44.352486][ T9495] CPU: 1 UID: 0 PID: 9495 Comm: repro Not tainted
7.3.0-rc2-00099-g50d05c7c76c9 #1 PREEMPT(full)
[ 44.353650][ T9495] Hardware name: QEMU Standard PC (Q35 + ICH9,
2009), BIOS 1.17.0-debian-1.17.0-1ubuntu1 04/01/2014
[ 44.354609][ T9495] Call Trace:
[ 44.354919][ T9495] <TASK>
[ 44.355192][ T9495] vpanic+0x56d/0xa60
[ 44.355639][ T9495] ? __pfx_vpanic+0x10/0x10
[ 44.356061][ T9495] panic+0xc5/0xd0
[ 44.356407][ T9495] ? __pfx_panic+0x10/0x10
[ 44.356831][ T9495] ? preempt_schedule_thunk+0x16/0x40
[ 44.357323][ T9495] ? gb_hid_raw_request+0x29c/0x860
[ 44.357800][ T9495] ? preempt_schedule_thunk+0x16/0x40
[ 44.358291][ T9495] ? gb_hid_raw_request+0x29c/0x860
[ 44.358771][ T9495] check_panic_on_warn+0x89/0xb0
[ 44.359225][ T9495] ? gb_hid_raw_request+0x29c/0x860
[ 44.359702][ T9495] end_report+0x73/0x170
[ 44.360095][ T9495] ? gb_hid_raw_request+0x29c/0x860
[ 44.360566][ T9495] kasan_report+0x128/0x150
[ 44.360998][ T9495] ? gb_hid_raw_request+0x29c/0x860
[ 44.361471][ T9495] kasan_check_range+0x264/0x2c0
[ 44.361929][ T9495] ? gb_hid_raw_request+0x29c/0x860
[ 44.362430][ T9495] __asan_memcpy+0x40/0x70
[ 44.362863][ T9495] gb_hid_raw_request+0x29c/0x860
[ 44.363348][ T9495] ? __pfx_gb_hid_raw_request+0x10/0x10
[ 44.363865][ T9495] ? __hid_hw_raw_request+0xa7/0x140
[ 44.364348][ T9495] hidraw_send_report+0x2bf/0x540
[ 44.364825][ T9495] ? bpf_lsm_file_permission+0x9/0x20
[ 44.365314][ T9495] hidraw_write+0x91/0xd0
[ 44.365786][ T9495] ? __pfx_hidraw_write+0x10/0x10
[ 44.366245][ T9495] vfs_write+0x29a/0xb90
[ 44.366636][ T9495] ? __pfx_vfs_write+0x10/0x10
[ 44.367076][ T9495] ? __fget_files+0x2a/0x420
[ 44.367500][ T9495] ? __fget_files+0x2a/0x420
[ 44.367924][ T9495] ? __fget_files+0x3a0/0x420
[ 44.368352][ T9495] ? __fget_files+0x2a/0x420
[ 44.368791][ T9495] ksys_write+0x150/0x270
[ 44.369188][ T9495] ? __pfx_ksys_write+0x10/0x10
[ 44.369633][ T9495] do_syscall_64+0x155/0x510
[ 44.370063][ T9495] ? trace_irq_disable+0x3b/0x140
[ 44.370523][ T9495] ? entry_SYSCALL_64_after_hwframe+0x77/0x7f
[ 44.371077][ T9495] ? clear_bhb_loop+0x30/0x80
[ 44.371509][ T9495] entry_SYSCALL_64_after_hwframe+0x77/0x7f
[ 44.372046][ T9495] RIP: 0033:0x4521d2
[ 44.372407][ T9495] Code: 08 0f 85 e1 df ff ff 49 89 fb 48 89 f0 48
89 d7 48 89 ce 4c 89 c2 4d 89 ca 4c 8b 44 24 08 4c 8b 4c 24 10 4c 89
5c 24 08 0f 05 <c3> 66 2e 0f 1f 84 00 00 00 00 00 0f 1f 00 f3 0f 1e fa
55 48 89 e5
[ 44.374131][ T9495] RSP: 002b:00007ffcc5937968 EFLAGS: 00000246
ORIG_RAX: 0000000000000001
[ 44.374887][ T9495] RAX: ffffffffffffffda RBX: 0000000000000001
RCX: 00000000004521d2
[ 44.375673][ T9495] RDX: 0000000000000002 RSI: 00007ffcc5937af6
RDI: 0000000000000004
[ 44.376381][ T9495] RBP: 00007ffcc5937990 R08: 0000000000000000
R09: 0000000000000000
[ 44.377101][ T9495] R10: 0000000000000000 R11: 0000000000000246
R12: 00007ffcc5937c28
[ 44.377812][ T9495] R13: 00007ffcc5937c38 R14: 0000000000000002
R15: 00000000004cba40
[ 44.378522][ T9495] </TASK>
[ 44.379100][ T9495] Kernel Offset: disabled
[ 44.379644][ T9495] Rebooting in 86400 seconds..
Regards,
SEFCOM Lab @ ASU
[-- Attachment #2: 211.patch --]
[-- Type: application/octet-stream, Size: 399 bytes --]
--- a/drivers/staging/greybus/hid.c
+++ b/drivers/staging/greybus/hid.c
@@ -97,7 +97,7 @@ static int gb_hid_set_report(struct gb_hid *ghid, u8 report_type, u8 report_id,
{
struct gb_hid_set_report_request *request;
struct gb_operation *operation;
- int ret, size = sizeof(*request) + len - 1;
+ int ret, size = sizeof(*request) + len;
ret = gb_pm_runtime_get_sync(ghid->bundle);
if (ret)
[-- Attachment #3: reproducer.c --]
[-- Type: application/octet-stream, Size: 16705 bytes --]
/*
* 211-kasan-slab-out-of-bounds-write-in-gb-hid-raw-request
*/
#define _GNU_SOURCE
#include <dirent.h>
#include <errno.h>
#include <fcntl.h>
#include <pthread.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <sys/ioctl.h>
#include <time.h>
#include <unistd.h>
#include <linux/usb/ch9.h>
#include <linux/usb/raw_gadget.h>
#define GREYBUS_HEADER_SIZE 8
#define GREYBUS_TYPE_RESPONSE_FLAG 0x80
#define GREYBUS_SVC_CPORT 0
#define GB_SVC_TYPE_PROTOCOL_VERSION 0x01
#define GB_SVC_TYPE_SVC_HELLO 0x02
#define GB_SVC_TYPE_CONN_CREATE 0x07
#define GB_SVC_TYPE_DME_PEER_GET 0x09
#define GB_SVC_TYPE_DME_PEER_SET 0x0a
#define GB_SVC_TYPE_INTF_SET_PWRM 0x10
#define GB_SVC_TYPE_MODULE_INSERTED 0x1f
#define GB_SVC_TYPE_INTF_VSYS_ENABLE 0x21
#define GB_SVC_TYPE_INTF_REFCLK_ENABLE 0x23
#define GB_SVC_TYPE_INTF_REFCLK_DISABLE 0x24
#define GB_SVC_TYPE_INTF_UNIPRO_ENABLE 0x25
#define GB_SVC_TYPE_INTF_ACTIVATE 0x27
#define GB_SVC_TYPE_INTF_RESUME 0x28
#define GB_CONTROL_TYPE_VERSION 0x01
#define GB_CONTROL_TYPE_GET_MANIFEST_SIZE 0x03
#define GB_CONTROL_TYPE_GET_MANIFEST 0x04
#define GB_CONTROL_TYPE_BUNDLE_SUSPEND 0x0f
#define GB_CONTROL_TYPE_BUNDLE_RESUME 0x10
#define GB_CONTROL_TYPE_BUNDLE_ACTIVATE 0x12
#define GB_CONTROL_TYPE_INTF_SUSPEND_PREPARE 0x13
#define GB_HID_TYPE_GET_DESC 0x02
#define GB_HID_TYPE_GET_REPORT_DESC 0x03
#define GB_APB_REQUEST_CPORT_COUNT 0x04
#define GB_APB_REQUEST_ARPC_RUN 0x12
#define AP_INTERFACE_ID 1
#define MODULE_INTERFACE_ID 2
#define MODULE_CPORT_HID 1 /* remote cport our manifest uses */
/* the three bulk endpoints es2_ap_probe() insists on, in descriptor order */
#define EP_ADDR_CPORT_IN 0x81
#define EP_ADDR_ARPC_IN 0x86
#define EP_ADDR_CPORT_OUT 0x02
static int raw_gadget_fd = -1;
static int cport_in_endpoint = -1, arpc_in_endpoint = -1, cport_out_endpoint = -1;
/* AP-side cport the SVC bound to our HID cport; -1 until CONN_CREATE says so */
static int hid_ap_cport = -1;
static uint16_t next_operation_id = 1;
static void die(const char *what)
{
fprintf(stderr, "%s: %s\n", what, strerror(errno));
_exit(1);
}
static void msleep(int milliseconds)
{
struct timespec duration = { milliseconds / 1000,
(long)(milliseconds % 1000) * 1000000L };
nanosleep(&duration, NULL);
}
/*
* One helper for all four raw-gadget transfers: EP0_WRITE / EP0_READ and
* EP_WRITE / EP_READ share the usb_raw_ep_io layout and differ only in the
* direction the payload travels.
*/
static int raw_gadget_ep_io(unsigned long ioctl_request, int endpoint,
void *data, uint32_t length, int is_read)
{
uint8_t buffer[sizeof(struct usb_raw_ep_io) + 4096];
struct usb_raw_ep_io *io = (void *)buffer;
int ret;
if (length > 4096)
length = 4096;
io->ep = endpoint;
io->flags = 0;
io->length = length;
if (!is_read && length)
memcpy(io->data, data, length);
ret = ioctl(raw_gadget_fd, ioctl_request, io);
if (is_read && ret > 0 && data)
memcpy(data, io->data, ret < (int)length ? ret : length);
return ret;
}
#define ep0_write(data, length) \
raw_gadget_ep_io(USB_RAW_IOCTL_EP0_WRITE, 0, (void *)(data), (length), 0)
#define ep0_read(data, length) \
raw_gadget_ep_io(USB_RAW_IOCTL_EP0_READ, 0, (data), (length), 1)
#define ep_write(endpoint, data, length) \
raw_gadget_ep_io(USB_RAW_IOCTL_EP_WRITE, (endpoint), (void *)(data), (length), 0)
#define ep_read(endpoint, data, length) \
raw_gadget_ep_io(USB_RAW_IOCTL_EP_READ, (endpoint), (data), (length), 1)
static int enable_bulk_endpoint(uint8_t address)
{
struct usb_endpoint_descriptor descriptor = {
.bLength = USB_DT_ENDPOINT_SIZE,
.bDescriptorType = USB_DT_ENDPOINT,
.bEndpointAddress = address,
.bmAttributes = USB_ENDPOINT_XFER_BULK,
.wMaxPacketSize = 512,
};
return ioctl(raw_gadget_fd, USB_RAW_IOCTL_EP_ENABLE, &descriptor);
}
/* the es2 driver binds 18d1:1eaf ("APBridge") */
static struct usb_device_descriptor apbridge_device_descriptor = {
.bLength = sizeof(struct usb_device_descriptor),
.bDescriptorType = USB_DT_DEVICE,
.bcdUSB = 0x0200,
.bMaxPacketSize0 = 64,
.idVendor = 0x18d1,
.idProduct = 0x1eaf,
.bcdDevice = 0x0100,
.bNumConfigurations = 1,
};
static const uint8_t apbridge_config_descriptor[] = {
9, USB_DT_CONFIG, (9 + 9 + 7 * 3) & 0xff, 0, 1, 1, 0, 0xa0, 0x32,
9, USB_DT_INTERFACE, 0, 0, 3, 0xff, 0xff, 0xff, 0,
7, USB_DT_ENDPOINT, EP_ADDR_CPORT_IN, USB_ENDPOINT_XFER_BULK, 0x00, 0x02, 0,
7, USB_DT_ENDPOINT, EP_ADDR_ARPC_IN, USB_ENDPOINT_XFER_BULK, 0x00, 0x02, 0,
7, USB_DT_ENDPOINT, EP_ADDR_CPORT_OUT, USB_ENDPOINT_XFER_BULK, 0x00, 0x02, 0,
};
/* the module-side manifest: one interface, one HID bundle, one cport */
static const uint8_t hid_module_manifest[] = {
28, 0, 0x00, 0x01, /* size, version 0.1 */
8, 0, 0x01 /* INTERFACE */, 0, 0, 0, 0, 0,
8, 0, 0x03 /* BUNDLE */, 0, 1, 0x05 /* class HID */, 0, 0,
8, 0, 0x04 /* CPORT */, 0, MODULE_CPORT_HID, 0, 1, 0x05,
};
/*
* One vendor-defined output report and nothing else. An input or feature
* report would make gb_hid_start() issue a GB_HID_TYPE_GET_REPORT per report
* before the hidraw node appears; with neither, that round trip never happens.
*/
static const uint8_t hid_report_descriptor[] = {
0x06, 0x00, 0xff, /* Usage Page (Vendor Defined 0xff00) */
0x09, 0x01, /* Usage (0x01) */
0xa1, 0x01, /* Collection (Application) */
0x09, 0x02, /* Usage (0x02) */
0x15, 0x00, /* Logical Minimum (0) */
0x26, 0xff, 0x00, /* Logical Maximum (255) */
0x75, 0x08, /* Report Size (8) */
0x95, 0x08, /* Report Count (8) */
0x91, 0x02, /* Output (Data,Var,Abs) */
0xc0, /* End Collection */
};
static void greybus_send(uint8_t hd_cport, uint8_t type, uint16_t operation_id,
const void *payload, uint16_t payload_len)
{
uint8_t buffer[2048];
uint16_t size = GREYBUS_HEADER_SIZE + payload_len;
if (size > sizeof(buffer))
return;
buffer[0] = size & 0xff;
buffer[1] = size >> 8;
buffer[2] = operation_id & 0xff;
buffer[3] = operation_id >> 8;
buffer[4] = type;
buffer[5] = 0; /* result */
buffer[6] = hd_cport; /* es2 packs the cport id into pad[0] */
buffer[7] = 0;
if (payload_len)
memcpy(buffer + GREYBUS_HEADER_SIZE, payload, payload_len);
ep_write(cport_in_endpoint, buffer, size);
}
static void greybus_send_request(uint8_t hd_cport, uint8_t type,
const void *payload, uint16_t payload_len)
{
greybus_send(hd_cport, type, next_operation_id++, payload, payload_len);
}
static void greybus_send_response(uint8_t hd_cport, uint16_t operation_id,
uint8_t type, const void *payload,
uint16_t payload_len)
{
greybus_send(hd_cport, type | GREYBUS_TYPE_RESPONSE_FLAG, operation_id,
payload, payload_len);
}
static void handle_svc_request(uint16_t operation_id, uint8_t type,
const uint8_t *payload, int payload_len)
{
uint8_t response[8] = { 0 };
uint16_t response_len = 0;
switch (type) {
case GB_SVC_TYPE_CONN_CREATE:
/* intf1, cport1(le16), intf2, cport2(le16), tc, flags */
if (payload_len >= 8 &&
(payload[4] | (payload[5] << 8)) == MODULE_CPORT_HID)
hid_ap_cport = payload[1] | (payload[2] << 8);
break;
case GB_SVC_TYPE_DME_PEER_GET: {
/*
* gb_interface_read_dme() rejects any DDBL1_MANUFACTURERID
* other than TOSHIBA_DMID, so 0x5003 must read back 0x126.
* GMP_INIT_STATUS (0x6101) must be nonzero and its top byte is
* the init status; 0x02 selects the ES3-bootrom quirk set.
* Every other attribute the AP reads is cosmetic but nonzero.
*/
uint16_t attribute = payload_len >= 3 ?
(payload[1] | (payload[2] << 8)) : 0;
uint32_t value = attribute == 0x5003 ? 0x0126 :
attribute == 0x6101 ? 0x02000000 : 1;
response[2] = value; /* [0..1] is result_code == 0 */
response[3] = value >> 8;
response[4] = value >> 16;
response[5] = value >> 24;
response_len = 6;
break;
}
case GB_SVC_TYPE_DME_PEER_SET:
response_len = 2; /* le16 result_code */
break;
case GB_SVC_TYPE_INTF_ACTIVATE:
response[1] = 0x03; /* GB_SVC_INTF_TYPE_GREYBUS */
response_len = 2; /* status, intf_type */
break;
case GB_SVC_TYPE_INTF_VSYS_ENABLE:
case GB_SVC_TYPE_INTF_REFCLK_ENABLE:
case GB_SVC_TYPE_INTF_REFCLK_DISABLE:
case GB_SVC_TYPE_INTF_UNIPRO_ENABLE:
case GB_SVC_TYPE_INTF_SET_PWRM:
case GB_SVC_TYPE_INTF_RESUME:
response_len = 1; /* bare status byte */
break;
default:
break; /* device-id, route-create, ping, ... */
}
greybus_send_response(GREYBUS_SVC_CPORT, operation_id, type,
response, response_len);
}
static void handle_control_request(uint8_t hd_cport, uint16_t operation_id,
uint8_t type)
{
uint8_t response[2] = { 0 };
const uint8_t *payload = response;
uint16_t payload_len = 0;
switch (type) {
case GB_CONTROL_TYPE_VERSION:
response[1] = 1; /* major 0, minor 1 */
payload_len = 2;
break;
case GB_CONTROL_TYPE_GET_MANIFEST_SIZE:
response[0] = sizeof(hid_module_manifest);
payload_len = 2;
break;
case GB_CONTROL_TYPE_GET_MANIFEST:
payload = hid_module_manifest;
payload_len = sizeof(hid_module_manifest);
break;
case GB_CONTROL_TYPE_BUNDLE_SUSPEND:
case GB_CONTROL_TYPE_BUNDLE_RESUME:
case GB_CONTROL_TYPE_BUNDLE_ACTIVATE:
case GB_CONTROL_TYPE_INTF_SUSPEND_PREPARE:
payload_len = 1; /* bare status byte */
break;
default:
break; /* connected, disconnected, ... */
}
greybus_send_response(hd_cport, operation_id, type, payload, payload_len);
}
static void handle_hid_request(uint8_t hd_cport, uint16_t operation_id,
uint8_t type)
{
uint8_t descriptor_response[10] = { 0 };
const uint8_t *payload = descriptor_response;
uint16_t payload_len = 0;
switch (type) {
case GB_HID_TYPE_GET_DESC:
descriptor_response[0] = 10; /* bLength */
descriptor_response[1] = sizeof(hid_report_descriptor); /* wReportDescLength */
descriptor_response[3] = 0x11; /* bcdHID 0x0111 */
descriptor_response[4] = 0x01;
descriptor_response[5] = 0x02; /* wProductID */
descriptor_response[7] = 0x01; /* wVendorID */
payload_len = 10;
break;
case GB_HID_TYPE_GET_REPORT_DESC:
payload = hid_report_descriptor;
payload_len = sizeof(hid_report_descriptor);
break;
default:
break; /* power on/off, ... */
}
greybus_send_response(hd_cport, operation_id, type, payload, payload_len);
}
static void *cport_out_reader_thread(void *unused)
{
uint8_t buffer[2048];
uint8_t svc_version[2] = { 0x00, 0x01 };
/* kick the SVC handshake off */
greybus_send_request(GREYBUS_SVC_CPORT, GB_SVC_TYPE_PROTOCOL_VERSION,
svc_version, 2);
for (;;) {
int nbytes = ep_read(cport_out_endpoint, buffer, sizeof(buffer));
uint16_t operation_id;
uint8_t type, hd_cport;
if (nbytes < GREYBUS_HEADER_SIZE) {
if (nbytes < 0 && (errno == ESHUTDOWN || errno == ENODEV))
break;
if (nbytes < 0)
msleep(5);
continue;
}
operation_id = buffer[2] | (buffer[3] << 8);
type = buffer[4];
hd_cport = buffer[6];
if (type & GREYBUS_TYPE_RESPONSE_FLAG) {
/* the only responses we act on chain the SVC handshake */
if (hd_cport != GREYBUS_SVC_CPORT)
continue;
if (type == (GB_SVC_TYPE_PROTOCOL_VERSION |
GREYBUS_TYPE_RESPONSE_FLAG)) {
uint8_t hello[3] = { 0x55, 0x47, AP_INTERFACE_ID };
greybus_send_request(GREYBUS_SVC_CPORT,
GB_SVC_TYPE_SVC_HELLO,
hello, 3);
} else if (type == (GB_SVC_TYPE_SVC_HELLO |
GREYBUS_TYPE_RESPONSE_FLAG)) {
uint8_t module_inserted[4] = {
MODULE_INTERFACE_ID, 1, 0, 0
};
greybus_send_request(GREYBUS_SVC_CPORT,
GB_SVC_TYPE_MODULE_INSERTED,
module_inserted, 4);
}
continue;
}
if (hd_cport == GREYBUS_SVC_CPORT)
handle_svc_request(operation_id, type,
buffer + GREYBUS_HEADER_SIZE,
nbytes - GREYBUS_HEADER_SIZE);
else if (hd_cport == hid_ap_cport)
handle_hid_request(hd_cport, operation_id, type);
else
handle_control_request(hd_cport, operation_id, type);
}
return NULL;
}
static void handle_ep0_control_request(const struct usb_ctrlrequest *ctrl)
{
uint8_t data[4096];
uint16_t wLength = ctrl->wLength;
int length = -1;
if ((ctrl->bRequestType & USB_TYPE_MASK) == USB_TYPE_STANDARD) {
switch (ctrl->bRequest) {
case USB_REQ_GET_DESCRIPTOR:
if ((ctrl->wValue >> 8) == USB_DT_DEVICE) {
length = sizeof(apbridge_device_descriptor);
memcpy(data, &apbridge_device_descriptor, length);
} else if ((ctrl->wValue >> 8) == USB_DT_CONFIG) {
length = sizeof(apbridge_config_descriptor);
memcpy(data, apbridge_config_descriptor, length);
}
break;
case USB_REQ_SET_CONFIGURATION:
ioctl(raw_gadget_fd, USB_RAW_IOCTL_CONFIGURE, 0);
cport_in_endpoint = enable_bulk_endpoint(EP_ADDR_CPORT_IN);
arpc_in_endpoint = enable_bulk_endpoint(EP_ADDR_ARPC_IN);
cport_out_endpoint = enable_bulk_endpoint(EP_ADDR_CPORT_OUT);
length = 0;
break;
}
} else if ((ctrl->bRequestType & USB_TYPE_MASK) == USB_TYPE_VENDOR) {
if (ctrl->bRequestType & USB_DIR_IN) {
/* CPORT_COUNT is the only vendor IN request es2 makes */
if (ctrl->bRequest == GB_APB_REQUEST_CPORT_COUNT) {
data[0] = 32; /* plenty; must exceed 17 */
data[1] = 0;
length = 2;
}
} else {
memset(data, 0, sizeof(data));
ep0_read(data, wLength);
if (ctrl->bRequest == GB_APB_REQUEST_ARPC_RUN &&
wLength >= 5) {
/* echo the le16 ARPC id back, then ARPC_SUCCESS */
uint8_t arpc_response[3] = { data[0], data[1], 0 };
ep_write(arpc_in_endpoint, arpc_response, 3);
}
return; /* data stage already consumed */
}
}
if (length < 0) {
ioctl(raw_gadget_fd, USB_RAW_IOCTL_EP0_STALL, 0);
return;
}
/*
* raw-gadget marks a transfer with no IN data stage as "out pending",
* so the status stage of a 0-length request is acknowledged with
* EP0_READ, not EP0_WRITE.
*/
if ((ctrl->bRequestType & USB_DIR_IN) && wLength) {
if (length > wLength)
length = wLength;
ep0_write(data, length);
} else {
ep0_read(data, wLength);
}
}
static void *ep0_control_thread(void *unused)
{
uint8_t buffer[sizeof(struct usb_raw_event) + 4096];
struct usb_raw_event *event = (void *)buffer;
for (;;) {
event->type = 0;
event->length = 4096;
if (ioctl(raw_gadget_fd, USB_RAW_IOCTL_EVENT_FETCH, event) < 0) {
if (errno == EINTR)
continue;
break;
}
if (event->type == USB_RAW_EVENT_CONTROL)
handle_ep0_control_request(
(struct usb_ctrlrequest *)event->data);
else if (event->type == USB_RAW_EVENT_DISCONNECT)
break;
}
return NULL;
}
int main(void)
{
struct usb_raw_init init;
struct dirent *udc_entry;
DIR *udc_dir;
pthread_t thread;
unsigned char report[2];
char *udc_index;
int hidraw_fd = -1, i;
/* dummy_hcd numbers its UDCs, so the name must be discovered:
* device "dummy_udc.2" belongs to driver "dummy_udc". */
udc_dir = opendir("/sys/class/udc");
while (udc_dir && (udc_entry = readdir(udc_dir)) && udc_entry->d_name[0] == '.')
;
if (!udc_dir || !udc_entry)
die("no UDC in /sys/class/udc (dummy_hcd missing?)");
memset(&init, 0, sizeof(init));
snprintf((char *)init.device_name, UDC_NAME_LENGTH_MAX, "%s", udc_entry->d_name);
snprintf((char *)init.driver_name, UDC_NAME_LENGTH_MAX, "%s", udc_entry->d_name);
closedir(udc_dir);
udc_index = strrchr((char *)init.driver_name, '.');
if (udc_index)
*udc_index = 0;
init.speed = USB_SPEED_HIGH;
raw_gadget_fd = open("/dev/raw-gadget", O_RDWR);
if (raw_gadget_fd < 0)
die("open(/dev/raw-gadget)");
if (ioctl(raw_gadget_fd, USB_RAW_IOCTL_INIT, &init) < 0)
die("USB_RAW_IOCTL_INIT");
if (ioctl(raw_gadget_fd, USB_RAW_IOCTL_RUN, 0) < 0)
die("USB_RAW_IOCTL_RUN");
pthread_create(&thread, NULL, ep0_control_thread, NULL);
for (i = 0; i < 500 && cport_out_endpoint < 0; i++)
msleep(10);
if (cport_in_endpoint < 0 || arpc_in_endpoint < 0 || cport_out_endpoint < 0)
die("gadget never got configured");
pthread_create(&thread, NULL, cport_out_reader_thread, NULL);
/* wait for gb-hid to enumerate the bundle and register a hidraw node */
for (i = 0; i < 300 && hidraw_fd < 0; i++) {
hidraw_fd = open("/dev/hidraw0", O_RDWR);
if (hidraw_fd < 0)
msleep(100);
}
if (hidraw_fd < 0)
die("no hidraw device appeared");
/*
* Report id 0, 2 bytes. gb_hid_set_report() sizes the greybus request
* as sizeof(struct gb_hid_set_report_request) + len - 1, but that
* struct ends in a true flexible array, so the payload has room for
* only len - 1 report bytes while the memcpy copies len of them.
* hidraw_write() rejects anything shorter than 2 bytes, and buf[0]
* must equal the report number for gb_hid_raw_request() to take the
* HID_REQ_SET_REPORT path.
*/
report[0] = 0x00;
report[1] = 0x41;
write(hidraw_fd, report, sizeof(report));
return 0;
}
^ permalink raw reply [flat|nested] 2+ messages in thread* Re: [BUG] KASAN: slab-out-of-bounds Write in gb_hid_raw_request
2026-09-10 1:38 [BUG] KASAN: slab-out-of-bounds Write in gb_hid_raw_request Farhad Alemi
@ 2026-09-10 6:10 ` Greg Kroah-Hartman
0 siblings, 0 replies; 2+ messages in thread
From: Greg Kroah-Hartman @ 2026-09-10 6:10 UTC (permalink / raw)
To: Farhad Alemi
Cc: Viresh Kumar, Johan Hovold, Alex Elder, Farhad Alemi,
greybus-dev, linux-staging, linux-kernel
On Wed, Sep 09, 2026 at 06:38:02PM -0700, Farhad Alemi wrote:
> Hello,
>
> We are reporting the following crash (reproducer and a proposed patch attached):
Great, please submit the patch properly so that we can review and apply
it if it works.
> Linux version 7.3.0-rc2 50d05c7c76c96b90462f24debacca971d2e86713
> Build Config: UpstreamAppArmorKASAN (KASAN + UBSAN, panic_on_warn=1)
>
> [ 44.000772][ T804] usb 3-1: new high-speed USB device number 2
> using dummy_hcd
> [ 44.163699][ T804] usb 3-1: New USB device found, idVendor=18d1,
> idProduct=1eaf, bcdDevice= 1.00
> [ 44.169786][ T804] usb 3-1: New USB device strings: Mfr=0,
> Product=0, SerialNumber=0
> [ 44.212054][ T12] greybus 1-svc: set power mode = 0
> [ 44.212064][ T12] greybus 1-svc: power mode change failed on AP
> to switch link: -5
> [ 44.213758][ C1] greybus greybus1: 0/0:0: short response 0x94
> received (8 < 9)
> [ 44.215179][ T9337] greybus greybus1: 0/0:0: synchronous operation
> id 0x0003 of type 0x14 failed: -90
> [ 44.215216][ T9337] greybus 1-svc: failed to get rail count: -90
> [ 44.234071][ T9337] greybus 1-2.2: Interface added (greybus)
> [ 44.234080][ T9337] greybus 1-2.2: GMP VID=0x00000001, PID=0x00000001
> [ 44.234087][ T9337] greybus 1-2.2: DDBL1 Manufacturer=0x00000126,
I'm guessing this is an emulated device, not a real one?
thanks,
greg k-h
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2026-09-10 6:12 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-09-10 1:38 [BUG] KASAN: slab-out-of-bounds Write in gb_hid_raw_request Farhad Alemi
2026-09-10 6:10 ` Greg Kroah-Hartman
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®