Re: [Linux Kernel Bugs] KASAN: slab-use-after-free Read in cec_queue_msg_fh and 4 other crashes in the cec device (`cec_ioctl`)

From: Yang, Chenyuan
Date: Wed Jan 24 2024 - 08:34:11 EST


Hi Hans,

Thanks for your prompt response!

After applying the new patch, the system hang issue persists. I also tested with the latest Linux version, but the problem remains. The error displayed is 'INFO: task syz-executor372:16736 blocked for more than 143 seconds.' Could it be that the timeout setting for the CEC is too extensive, contributing to this hang?

Here is the report, trace and reproducible program for the hang:

```
Syzkaller hit 'INFO: task hung in cec_claim_log_addrs' bug.

INFO: task syz-executor372:16736 blocked for more than 143 seconds.
Not tainted 6.8.0-rc1-00029-g615d30064886-dirty #1
"echo 0 > /proc/sys/kernel/hung_task_timeout_secs" disables this message.
task:syz-executor372 state:D stack:27872 pid:16736 tgid:16734 ppid:8035 flags:0x00004006
Call Trace:
<TASK>
context_switch kernel/sched/core.c:5400 [inline]
__schedule+0xd24/0x5b10 kernel/sched/core.c:6727
__schedule_loop kernel/sched/core.c:6802 [inline]
schedule+0xe9/0x270 kernel/sched/core.c:6817
schedule_timeout+0x250/0x290 kernel/time/timer.c:2159
do_wait_for_common kernel/sched/completion.c:95 [inline]
__wait_for_common+0x1cd/0x5d0 kernel/sched/completion.c:116
cec_claim_log_addrs+0x192/0x260 drivers/media/cec/core/cec-adap.c:1606
__cec_s_log_addrs+0xdfc/0x16e0 drivers/media/cec/core/cec-adap.c:1920
cec_adap_s_log_addrs drivers/media/cec/core/cec-api.c:184 [inline]
cec_ioctl+0x1e7c/0x2690 drivers/media/cec/core/cec-api.c:528
vfs_ioctl fs/ioctl.c:51 [inline]
__do_sys_ioctl fs/ioctl.c:871 [inline]
__se_sys_ioctl fs/ioctl.c:857 [inline]
__x64_sys_ioctl+0x19d/0x210 fs/ioctl.c:857
do_syscall_x64 arch/x86/entry/common.c:52 [inline]
do_syscall_64+0xd2/0x250 arch/x86/entry/common.c:83
entry_SYSCALL_64_after_hwframe+0x63/0x6b
RIP: 0033:0x7fed9d78f23d
RSP: 002b:00007fed9d712198 EFLAGS: 00000246 ORIG_RAX: 0000000000000010
RAX: ffffffffffffffda RBX: 00007fed9d8242f0 RCX: 00007fed9d78f23d
RDX: 0000000020000100 RSI: 00000000c05c6104 RDI: 0000000000000004
RBP: 00007fed9d7ef08c R08: 0000000000000000 R09: 0000000000000000
R10: 0000000000000000 R11: 0000000000000246 R12: 55803a8253a605c5
R13: 956cd5a763ae25af R14: 8158e34c95c29778 R15: 00007fed9d8242f8
</TASK>

Showing all locks held in the system:
1 lock held by khungtaskd/29:
#0: ffffffff8cfabf20 (rcu_read_lock){....}-{1:2}, at: rcu_lock_acquire include/linux/rcupdate.h:298 [inline]
#0: ffffffff8cfabf20 (rcu_read_lock){....}-{1:2}, at: rcu_read_lock include/linux/rcupdate.h:750 [inline]
#0: ffffffff8cfabf20 (rcu_read_lock){....}-{1:2}, at: debug_show_all_locks+0x75/0x340 kernel/locking/lockdep.c:6614
3 locks held by systemd-journal/4510:
1 lock held by in:imklog/7580:
#0: ffff8880132ef9c8 (&f->f_pos_lock){+.+.}-{3:3}, at: __fdget_pos+0xdb/0x160 fs/file.c:1191

=============================================

NMI backtrace for cpu 1
CPU: 1 PID: 29 Comm: khungtaskd Not tainted 6.8.0-rc1-00029-g615d30064886-dirty #1
Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.15.0-1 04/01/2014
Call Trace:
<TASK>
__dump_stack lib/dump_stack.c:88 [inline]
dump_stack_lvl+0xd9/0x150 lib/dump_stack.c:106
nmi_cpu_backtrace+0x29c/0x350 lib/nmi_backtrace.c:113
nmi_trigger_cpumask_backtrace+0x299/0x300 lib/nmi_backtrace.c:62
trigger_all_cpu_backtrace include/linux/nmi.h:160 [inline]
check_hung_uninterruptible_tasks kernel/hung_task.c:222 [inline]
watchdog+0xe7a/0x1100 kernel/hung_task.c:379
kthread+0x2cc/0x3b0 kernel/kthread.c:388
ret_from_fork+0x45/0x80 arch/x86/kernel/process.c:147
ret_from_fork_asm+0x11/0x20 arch/x86/entry/entry_64.S:242
</TASK>
Sending NMI from CPU 1 to CPUs 0:
NMI backtrace for cpu 0
CPU: 0 PID: 7583 Comm: rs:main Q:Reg Not tainted 6.8.0-rc1-00029-g615d30064886-dirty #1
Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.15.0-1 04/01/2014
RIP: 0033:0x7f0236ea76ac
Code: 08 48 8d 4d 08 48 89 d0 48 d1 e8 48 39 04 24 72 3d 44 89 e6 48 89 ef e8 42 fc ff ff 48 8b 44 24 78 64 48 2b 04 25 28 00 00 00 <0f> 85 e6 01 00 00 48 81 c4 88 00 00 00 4c 89 ef 5b 5d 41 5c 41 5d
RSP: 002b:00007f0235bffac0 EFLAGS: 00000246
RAX: 0000000000000000 RBX: 000000000000011f RCX: 0000561d7d1f6e70
RDX: 000000000000011e RSI: 0000000000000000 RDI: 0000561d7d1f6e8c
RBP: 0000561d7d1f6e68 R08: 0000000000000001 R09: 000000000000000a
R10: 0000000000000000 R11: 0000000000000001 R12: 0000000000000000
R13: 0000561d7d1f6c50 R14: 0000561d7d1f6e94 R15: 00007f0235bffaf0
FS: 00007f0235c00700 GS: 0000000000000000


Syzkaller reproducer:
# {Threaded:true Repeat:true RepeatTimes:0 Procs:1 Slowdown:1 Sandbox: SandboxArg:0 Leak:false NetInjection:false NetDevices:false NetReset:false Cgroups:false BinfmtMisc:false CloseFDs:false KCSAN:false DevlinkPCI:false NicVF:false USB:false VhciInjection:false Wifi:false IEEE802154:false Sysctl:false Swap:false UseTmpDir:false HandleSegv:false Repro:false Trace:false LegacyOptions:{Collide:false Fault:false FaultCall:0 FaultNth:0}}
r0 = syz_open_dev$cec_llm_open(&(0x7f0000000240), 0x0, 0x0)
ioctl$CEC_ADAP_S_LOG_ADDRS(r0, 0xc05c6104, &(0x7f0000000000)={"1157fbfa", 0x7, 0x5, 0xd4, 0xfffffffd, 0x5, "020000000a3ac8d3f653fc5bfc63a9", "8c3500", "0000e600", "519a84f1", ["1d10000000ffffffffff00", "b2c5d7e70561fbc4c39b5908", "d9f08668551414911a90c022", "6822c4c1322b547b17359592"]}) (async)
r1 = syz_open_dev$cec_llm_open(&(0x7f00000002c0), 0x0, 0x0)
ioctl$CEC_ADAP_S_LOG_ADDRS(r1, 0xc05c6104, &(0x7f0000000100)={"6b2dbba0", 0x0, 0x6, 0x9, 0x0, 0x5, "8b9fc0d5f029b78f8d31f64ac97f9d", "28f232c0", "efb2fcf5", "97541973", ["5c72b16343317b0b23e10116", "e9b6d0cfaa7cca88684a584d", "586b8e57a6be0da0ae2f27eb", "cda634d3d560667bdac2e046"]}) (async)
ioctl$CEC_ADAP_S_LOG_ADDRS(r1, 0xc05c6104, &(0x7f0000000080)={"5df5676a", 0x0, 0x81, 0x0, 0x0, 0x0, "7897c2954ce35881e0810c5295ad35", "2becffd0", "b195f683", "c9667930", ["af25ae63a7d56c95987751c2", "c505a653823a8055df682105", "7bb64494ee0de68901476d55", "f16f1b8989a5e7abd92df4a4"]})


C reproducer:
// autogenerated by syzkaller (https://github.com/google/syzkaller)

#define _GNU_SOURCE

#include <dirent.h>
#include <endian.h>
#include <errno.h>
#include <fcntl.h>
#include <pthread.h>
#include <signal.h>
#include <stdarg.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/prctl.h>
#include <sys/stat.h>
#include <sys/syscall.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <time.h>
#include <unistd.h>

#include <linux/futex.h>

static void sleep_ms(uint64_t ms)
{
usleep(ms * 1000);
}

static uint64_t current_time_ms(void)
{
struct timespec ts;
if (clock_gettime(CLOCK_MONOTONIC, &ts))
exit(1);
return (uint64_t)ts.tv_sec * 1000 + (uint64_t)ts.tv_nsec / 1000000;
}

static void thread_start(void* (*fn)(void*), void* arg)
{
pthread_t th;
pthread_attr_t attr;
pthread_attr_init(&attr);
pthread_attr_setstacksize(&attr, 128 << 10);
int i = 0;
for (; i < 100; i++) {
if (pthread_create(&th, &attr, fn, arg) == 0) {
pthread_attr_destroy(&attr);
return;
}
if (errno == EAGAIN) {
usleep(50);
continue;
}
break;
}
exit(1);
}

typedef struct {
int state;
} event_t;

static void event_init(event_t* ev)
{
ev->state = 0;
}

static void event_reset(event_t* ev)
{
ev->state = 0;
}

static void event_set(event_t* ev)
{
if (ev->state)
exit(1);
__atomic_store_n(&ev->state, 1, __ATOMIC_RELEASE);
syscall(SYS_futex, &ev->state, FUTEX_WAKE | FUTEX_PRIVATE_FLAG, 1000000);
}

static void event_wait(event_t* ev)
{
while (!__atomic_load_n(&ev->state, __ATOMIC_ACQUIRE))
syscall(SYS_futex, &ev->state, FUTEX_WAIT | FUTEX_PRIVATE_FLAG, 0, 0);
}

static int event_isset(event_t* ev)
{
return __atomic_load_n(&ev->state, __ATOMIC_ACQUIRE);
}

static int event_timedwait(event_t* ev, uint64_t timeout)
{
uint64_t start = current_time_ms();
uint64_t now = start;
for (;;) {
uint64_t remain = timeout - (now - start);
struct timespec ts;
ts.tv_sec = remain / 1000;
ts.tv_nsec = (remain % 1000) * 1000 * 1000;
syscall(SYS_futex, &ev->state, FUTEX_WAIT | FUTEX_PRIVATE_FLAG, 0, &ts);
if (__atomic_load_n(&ev->state, __ATOMIC_ACQUIRE))
return 1;
now = current_time_ms();
if (now - start > timeout)
return 0;
}
}

static bool write_file(const char* file, const char* what, ...)
{
char buf[1024];
va_list args;
va_start(args, what);
vsnprintf(buf, sizeof(buf), what, args);
va_end(args);
buf[sizeof(buf) - 1] = 0;
int len = strlen(buf);
int fd = open(file, O_WRONLY | O_CLOEXEC);
if (fd == -1)
return false;
if (write(fd, buf, len) != len) {
int err = errno;
close(fd);
errno = err;
return false;
}
close(fd);
return true;
}

static long syz_open_dev(volatile long a0, volatile long a1, volatile long a2)
{
if (a0 == 0xc || a0 == 0xb) {
char buf[128];
sprintf(buf, "/dev/%s/%d:%d", a0 == 0xc ? "char" : "block", (uint8_t)a1, (uint8_t)a2);
return open(buf, O_RDWR, 0);
} else {
char buf[1024];
char* hash;
strncpy(buf, (char*)a0, sizeof(buf) - 1);
buf[sizeof(buf) - 1] = 0;
while ((hash = strchr(buf, '#'))) {
*hash = '0' + (char)(a1 % 10);
a1 /= 10;
}
return open(buf, a2, 0);
}
}

static void kill_and_wait(int pid, int* status)
{
kill(-pid, SIGKILL);
kill(pid, SIGKILL);
for (int i = 0; i < 100; i++) {
if (waitpid(-1, status, WNOHANG | __WALL) == pid)
return;
usleep(1000);
}
DIR* dir = opendir("/sys/fs/fuse/connections");
if (dir) {
for (;;) {
struct dirent* ent = readdir(dir);
if (!ent)
break;
if (strcmp(ent->d_name, ".") == 0 || strcmp(ent->d_name, "..") == 0)
continue;
char abort[300];
snprintf(abort, sizeof(abort), "/sys/fs/fuse/connections/%s/abort", ent->d_name);
int fd = open(abort, O_WRONLY);
if (fd == -1) {
continue;
}
if (write(fd, abort, 1) < 0) {
}
close(fd);
}
closedir(dir);
} else {
}
while (waitpid(-1, status, __WALL) != pid) {
}
}

static void setup_test()
{
prctl(PR_SET_PDEATHSIG, SIGKILL, 0, 0, 0);
setpgrp();
write_file("/proc/self/oom_score_adj", "1000");
}

struct thread_t {
int created, call;
event_t ready, done;
};

static struct thread_t threads[16];
static void execute_call(int call);
static int running;

static void* thr(void* arg)
{
struct thread_t* th = (struct thread_t*)arg;
for (;;) {
event_wait(&th->ready);
event_reset(&th->ready);
execute_call(th->call);
__atomic_fetch_sub(&running, 1, __ATOMIC_RELAXED);
event_set(&th->done);
}
return 0;
}

static void execute_one(void)
{
int i, call, thread;
for (call = 0; call < 5; call++) {
for (thread = 0; thread < (int)(sizeof(threads) / sizeof(threads[0])); thread++) {
struct thread_t* th = &threads[thread];
if (!th->created) {
th->created = 1;
event_init(&th->ready);
event_init(&th->done);
event_set(&th->done);
thread_start(thr, th);
}
if (!event_isset(&th->done))
continue;
event_reset(&th->done);
th->call = call;
__atomic_fetch_add(&running, 1, __ATOMIC_RELAXED);
event_set(&th->ready);
if (call == 1 || call == 3)
break;
event_timedwait(&th->done, 50);
break;
}
}
for (i = 0; i < 100 && __atomic_load_n(&running, __ATOMIC_RELAXED); i++)
sleep_ms(1);
}

static void execute_one(void);

#define WAIT_FLAGS __WALL

static void loop(void)
{
int iter = 0;
for (;; iter++) {
int pid = fork();
if (pid < 0)
exit(1);
if (pid == 0) {
setup_test();
execute_one();
exit(0);
}
int status = 0;
uint64_t start = current_time_ms();
for (;;) {
if (waitpid(-1, &status, WNOHANG | WAIT_FLAGS) == pid)
break;
sleep_ms(1);
if (current_time_ms() - start < 5000)
continue;
kill_and_wait(pid, &status);
break;
}
}
}

uint64_t r[2] = {0xffffffffffffffff, 0xffffffffffffffff};

void execute_call(int call)
{
intptr_t res = 0;
switch (call) {
case 0:
memcpy((void*)0x20000240, "/dev/cec#\000", 10);
res = -1;
res = syz_open_dev(/*dev=*/0x20000240, /*id=*/0, /*flags=*/0);
if (res != -1)
r[0] = res;
break;
case 1:
memcpy((void*)0x20000000, "\x11\x57\xfb\xfa", 4);
*(uint16_t*)0x20000004 = 7;
*(uint8_t*)0x20000006 = 5;
*(uint8_t*)0x20000007 = 0xd4;
*(uint32_t*)0x20000008 = 0xfffffffd;
*(uint32_t*)0x2000000c = 5;
memcpy((void*)0x20000010, "\x02\x00\x00\x00\x0a\x3a\xc8\xd3\xf6\x53\xfc\x5b\xfc\x63\xa9", 15);
memcpy((void*)0x2000001f, "\x8c\x35\x00\x00", 4);
memcpy((void*)0x20000023, "\x00\x00\xe6\x00", 4);
memcpy((void*)0x20000027, "\x51\x9a\x84\xf1", 4);
memcpy((void*)0x2000002b, "\x1d\x10\x00\x00\x00\xff\xff\xff\xff\xff\x00\x00", 12);
memcpy((void*)0x20000037, "\xb2\xc5\xd7\xe7\x05\x61\xfb\xc4\xc3\x9b\x59\x08", 12);
memcpy((void*)0x20000043, "\xd9\xf0\x86\x68\x55\x14\x14\x91\x1a\x90\xc0\x22", 12);
memcpy((void*)0x2000004f, "\x68\x22\xc4\xc1\x32\x2b\x54\x7b\x17\x35\x95\x92", 12);
syscall(__NR_ioctl, /*fd=*/r[0], /*cmd=*/0xc05c6104, /*arg=*/0x20000000ul);
break;
case 2:
memcpy((void*)0x200002c0, "/dev/cec#\000", 10);
res = -1;
res = syz_open_dev(/*dev=*/0x200002c0, /*id=*/0, /*flags=*/0);
if (res != -1)
r[1] = res;
break;
case 3:
memcpy((void*)0x20000100, "\x6b\x2d\xbb\xa0", 4);
*(uint16_t*)0x20000104 = 0;
*(uint8_t*)0x20000106 = 6;
*(uint8_t*)0x20000107 = 9;
*(uint32_t*)0x20000108 = 0;
*(uint32_t*)0x2000010c = 5;
memcpy((void*)0x20000110, "\x8b\x9f\xc0\xd5\xf0\x29\xb7\x8f\x8d\x31\xf6\x4a\xc9\x7f\x9d", 15);
memcpy((void*)0x2000011f, "\x28\xf2\x32\xc0", 4);
memcpy((void*)0x20000123, "\xef\xb2\xfc\xf5", 4);
memcpy((void*)0x20000127, "\x97\x54\x19\x73", 4);
memcpy((void*)0x2000012b, "\x5c\x72\xb1\x63\x43\x31\x7b\x0b\x23\xe1\x01\x16", 12);
memcpy((void*)0x20000137, "\xe9\xb6\xd0\xcf\xaa\x7c\xca\x88\x68\x4a\x58\x4d", 12);
memcpy((void*)0x20000143, "\x58\x6b\x8e\x57\xa6\xbe\x0d\xa0\xae\x2f\x27\xeb", 12);
memcpy((void*)0x2000014f, "\xcd\xa6\x34\xd3\xd5\x60\x66\x7b\xda\xc2\xe0\x46", 12);
syscall(__NR_ioctl, /*fd=*/r[1], /*cmd=*/0xc05c6104, /*arg=*/0x20000100ul);
break;
case 4:
memcpy((void*)0x20000080, "\x5d\xf5\x67\x6a", 4);
*(uint16_t*)0x20000084 = 0;
*(uint8_t*)0x20000086 = 0x81;
*(uint8_t*)0x20000087 = 0;
*(uint32_t*)0x20000088 = 0;
*(uint32_t*)0x2000008c = 0;
memcpy((void*)0x20000090, "\x78\x97\xc2\x95\x4c\xe3\x58\x81\xe0\x81\x0c\x52\x95\xad\x35", 15);
memcpy((void*)0x2000009f, "\x2b\xec\xff\xd0", 4);
memcpy((void*)0x200000a3, "\xb1\x95\xf6\x83", 4);
memcpy((void*)0x200000a7, "\xc9\x66\x79\x30", 4);
memcpy((void*)0x200000ab, "\xaf\x25\xae\x63\xa7\xd5\x6c\x95\x98\x77\x51\xc2", 12);
memcpy((void*)0x200000b7, "\xc5\x05\xa6\x53\x82\x3a\x80\x55\xdf\x68\x21\x05", 12);
memcpy((void*)0x200000c3, "\x7b\xb6\x44\x94\xee\x0d\xe6\x89\x01\x47\x6d\x55", 12);
memcpy((void*)0x200000cf, "\xf1\x6f\x1b\x89\x89\xa5\xe7\xab\xd9\x2d\xf4\xa4", 12);
syscall(__NR_ioctl, /*fd=*/r[1], /*cmd=*/0xc05c6104, /*arg=*/0x20000080ul);
break;
}

}
int main(void)
{
syscall(__NR_mmap, /*addr=*/0x1ffff000ul, /*len=*/0x1000ul, /*prot=*/0ul, /*flags=*/0x32ul, /*fd=*/-1, /*offset=*/0ul);
syscall(__NR_mmap, /*addr=*/0x20000000ul, /*len=*/0x1000000ul, /*prot=*/7ul, /*flags=*/0x32ul, /*fd=*/-1, /*offset=*/0ul);
syscall(__NR_mmap, /*addr=*/0x21000000ul, /*len=*/0x1000ul, /*prot=*/0ul, /*flags=*/0x32ul, /*fd=*/-1, /*offset=*/0ul);
loop();
return 0;
}
```

Best,
Chenyuan

On 1/19/24, 2:17 AM, "Hans Verkuil" <hverkuil-cisco@xxxxxxxxx <mailto:hverkuil-cisco@xxxxxxxxx>> wrote:


Hi Chenyuan,


On 28/12/2023 03:33, Yang, Chenyuan wrote:
> Hello,
>
>
>
> We encountered 5 different crashes in the cec device by using our generated syscall specification for it, here are the descriptions of these 5 crashes and the related files are attached:
>
> 1. KASAN: slab-use-after-free Read in cec_queue_msg_fh (Reproducible)
>
> 2. WARNING: ODEBUG bug in cec_transmit_msg_fh
>
> 3. WARNING in cec_data_cancel
>
> 4. INFO: task hung in cec_claim_log_addrs (Reproducible)
>
> 5. general protection fault in cec_transmit_done_ts
>
>
>
> For “KASAN: slab-use-after-free Read in cec_queue_msg_fh”, we attached a syzkaller program to reproduce it. This crash is caused by ` list_add_tail(&entry->list, &fh->msgs);`
> (https://urldefense.com/v3/__https://elixir.bootlin.com/linux/v6.7-rc7/source/drivers/media/cec/core/cec-adap.c <https://urldefense.com/v3/__https://elixir.bootlin.com/linux/v6.7-rc7/source/drivers/media/cec/core/cec-adap.c>*L224__;Iw!!DZ3fjg!9_O4Tm7W1dKV8lXOcDFUTmIqAd6eUmsffQg3gwvypxBR3WFuQkIlRr2vAsIpwMt7lt86UlzdOTV_jBaVO8pkIiZxZMf3fVQ$ <https://urldefense.com/v3/__https://elixir.bootlin.com/linux/v6.7-rc7/source/drivers/media/cec/core/cec-adap.c <https://urldefense.com/v3/__https://elixir.bootlin.com/linux/v6.7-rc7/source/drivers/media/cec/core/cec-adap.c>*L224__;Iw!!DZ3fjg!9_O4Tm7W1dKV8lXOcDFUTmIqAd6eUmsffQg3gwvypxBR3WFuQkIlRr2vAsIpwMt7lt86UlzdOTV_jBaVO8pkIiZxZMf3fVQ$ >), which reads a
> variable freed by `kfree(fh);` (https://urldefense.com/v3/__https://elixir.bootlin.com/linux/v6.7-rc7/source/drivers/media/cec/core/cec-api.c <https://urldefense.com/v3/__https://elixir.bootlin.com/linux/v6.7-rc7/source/drivers/media/cec/core/cec-api.c>*L684__;Iw!!DZ3fjg!9_O4Tm7W1dKV8lXOcDFUTmIqAd6eUmsffQg3gwvypxBR3WFuQkIlRr2vAsIpwMt7lt86UlzdOTV_jBaVO8pkIiZxT0xaxsY$
> <https://urldefense.com/v3/__https://elixir.bootlin.com/linux/v6.7-rc7/source/drivers/media/cec/core/cec-api.c <https://urldefense.com/v3/__https://elixir.bootlin.com/linux/v6.7-rc7/source/drivers/media/cec/core/cec-api.c>*L684__;Iw!!DZ3fjg!9_O4Tm7W1dKV8lXOcDFUTmIqAd6eUmsffQg3gwvypxBR3WFuQkIlRr2vAsIpwMt7lt86UlzdOTV_jBaVO8pkIiZxT0xaxsY$ >). The reproducible program is a Syzkaller program, which can be executed following this document:
> https://urldefense.com/v3/__https://github.com/google/syzkaller/blob/master/docs/executing_syzkaller_programs.md__;!!DZ3fjg!9_O4Tm7W1dKV8lXOcDFUTmIqAd6eUmsffQg3gwvypxBR3WFuQkIlRr2vAsIpwMt7lt86UlzdOTV_jBaVO8pkIiZx32PwCDs$ <https://urldefense.com/v3/__https://github.com/google/syzkaller/blob/master/docs/executing_syzkaller_programs.md__;!!DZ3fjg!9_O4Tm7W1dKV8lXOcDFUTmIqAd6eUmsffQg3gwvypxBR3WFuQkIlRr2vAsIpwMt7lt86UlzdOTV_jBaVO8pkIiZx32PwCDs$> <https://urldefense.com/v3/__https://github.com/google/syzkaller/blob/master/docs/executing_syzkaller_programs.md__;!!DZ3fjg!9_O4Tm7W1dKV8lXOcDFUTmIqAd6eUmsffQg3gwvypxBR3WFuQkIlRr2vAsIpwMt7lt86UlzdOTV_jBaVO8pkIiZx32PwCDs$ <https://urldefense.com/v3/__https://github.com/google/syzkaller/blob/master/docs/executing_syzkaller_programs.md__;!!DZ3fjg!9_O4Tm7W1dKV8lXOcDFUTmIqAd6eUmsffQg3gwvypxBR3WFuQkIlRr2vAsIpwMt7lt86UlzdOTV_jBaVO8pkIiZx32PwCDs$> >.
>
>
>
> For “WARNING: ODEBUG bug in cec_transmit_msg_fh”, unfortunately we failed to reproduce it but we indeed trigger this crash almost every time when we fuzz the cec device only. We attached the report
> and log for this bug. It tries freeing an active object by using `kfree(data);` (https://urldefense.com/v3/__https://elixir.bootlin.com/linux/v6.7-rc7/source/drivers/media/cec/core/cec-adap.c <https://urldefense.com/v3/__https://elixir.bootlin.com/linux/v6.7-rc7/source/drivers/media/cec/core/cec-adap.c>*L930__;Iw!!DZ3fjg!9_O4Tm7W1dKV8lXOcDFUTmIqAd6eUmsffQg3gwvypxBR3WFuQkIlRr2vAsIpwMt7lt86UlzdOTV_jBaVO8pkIiZxhwnuzFw$
> <https://urldefense.com/v3/__https://elixir.bootlin.com/linux/v6.7-rc7/source/drivers/media/cec/core/cec-adap.c <https://urldefense.com/v3/__https://elixir.bootlin.com/linux/v6.7-rc7/source/drivers/media/cec/core/cec-adap.c>*L930__;Iw!!DZ3fjg!9_O4Tm7W1dKV8lXOcDFUTmIqAd6eUmsffQg3gwvypxBR3WFuQkIlRr2vAsIpwMt7lt86UlzdOTV_jBaVO8pkIiZxhwnuzFw$ >).
>
>
>
> For “WARNING in cec_data_cancel”, it is an internal warning used in cec_data_cancel (https://urldefense.com/v3/__https://elixir.bootlin.com/linux/v6.7-rc7/source/drivers/media/cec/core/cec-adap.c <https://urldefense.com/v3/__https://elixir.bootlin.com/linux/v6.7-rc7/source/drivers/media/cec/core/cec-adap.c>*L365__;Iw!!DZ3fjg!9_O4Tm7W1dKV8lXOcDFUTmIqAd6eUmsffQg3gwvypxBR3WFuQkIlRr2vAsIpwMt7lt86UlzdOTV_jBaVO8pkIiZxJ9Jw4fU$
> <https://urldefense.com/v3/__https://elixir.bootlin.com/linux/v6.7-rc7/source/drivers/media/cec/core/cec-adap.c <https://urldefense.com/v3/__https://elixir.bootlin.com/linux/v6.7-rc7/source/drivers/media/cec/core/cec-adap.c>*L365__;Iw!!DZ3fjg!9_O4Tm7W1dKV8lXOcDFUTmIqAd6eUmsffQg3gwvypxBR3WFuQkIlRr2vAsIpwMt7lt86UlzdOTV_jBaVO8pkIiZxJ9Jw4fU$ >), which checks whether the transmit is the current or pending. Unfortunately, we also don't have the
> reproducible program for this bug, but we attach the report and log.
>
>
>
> For “INFO: task hung in cec_claim_log_addrs”, the kernel hangs when the cec device ` wait_for_completion(&adap->config_completion);`
> (https://urldefense.com/v3/__https://elixir.bootlin.com/linux/v6.7-rc7/source/drivers/media/cec/core/cec-adap.c <https://urldefense.com/v3/__https://elixir.bootlin.com/linux/v6.7-rc7/source/drivers/media/cec/core/cec-adap.c>*L1579__;Iw!!DZ3fjg!9_O4Tm7W1dKV8lXOcDFUTmIqAd6eUmsffQg3gwvypxBR3WFuQkIlRr2vAsIpwMt7lt86UlzdOTV_jBaVO8pkIiZxKP44OE0$ <https://urldefense.com/v3/__https://elixir.bootlin.com/linux/v6.7-rc7/source/drivers/media/cec/core/cec-adap.c <https://urldefense.com/v3/__https://elixir.bootlin.com/linux/v6.7-rc7/source/drivers/media/cec/core/cec-adap.c>*L1579__;Iw!!DZ3fjg!9_O4Tm7W1dKV8lXOcDFUTmIqAd6eUmsffQg3gwvypxBR3WFuQkIlRr2vAsIpwMt7lt86UlzdOTV_jBaVO8pkIiZxKP44OE0$ >). We have a
> reproducible C program for this.
>
>
>
> For “general protection fault in cec_transmit_done_ts”, the cec device tries derefencing a non-canonical address 0xdffffc00000000e0: 0000 [#1], which is related to the invocation `
> cec_transmit_attempt_done_ts ` (https://urldefense.com/v3/__https://elixir.bootlin.com/linux/v6.7-rc7/source/drivers/media/cec/core/cec-adap.c <https://urldefense.com/v3/__https://elixir.bootlin.com/linux/v6.7-rc7/source/drivers/media/cec/core/cec-adap.c>*L697__;Iw!!DZ3fjg!9_O4Tm7W1dKV8lXOcDFUTmIqAd6eUmsffQg3gwvypxBR3WFuQkIlRr2vAsIpwMt7lt86UlzdOTV_jBaVO8pkIiZxGnBFZv0$
> <https://urldefense.com/v3/__https://elixir.bootlin.com/linux/v6.7-rc7/source/drivers/media/cec/core/cec-adap.c <https://urldefense.com/v3/__https://elixir.bootlin.com/linux/v6.7-rc7/source/drivers/media/cec/core/cec-adap.c>*L697__;Iw!!DZ3fjg!9_O4Tm7W1dKV8lXOcDFUTmIqAd6eUmsffQg3gwvypxBR3WFuQkIlRr2vAsIpwMt7lt86UlzdOTV_jBaVO8pkIiZxGnBFZv0$ >). It seems that the address of cec_adapter is totally wrong. We do not have a reproducible program for this
> bug, but the log and report for it are attached.
>
>
>
> If you have any questions or require more information, please feel free to contact us.


Can you retest with the patch below? I'm fairly certain this will fix issues 1 and 2.
I suspect at least some of the others are related to 1 & 2, but since I could never
get the reproducers working reliably, I had a hard time determining if there are more
bugs or if this patch resolves everything.


Your help testing this patch will be appreciated!


Regards,


Hans


Signed-off-by: Hans Verkuil <hverkuil-cisco@xxxxxxxxx <mailto:hverkuil-cisco@xxxxxxxxx>>
---
drivers/media/cec/core/cec-adap.c | 3 +--
drivers/media/cec/core/cec-api.c | 3 +++
2 files changed, 4 insertions(+), 2 deletions(-)


diff --git a/drivers/media/cec/core/cec-adap.c b/drivers/media/cec/core/cec-adap.c
index 5741adf09a2e..079c3b142d91 100644
--- a/drivers/media/cec/core/cec-adap.c
+++ b/drivers/media/cec/core/cec-adap.c
@@ -936,8 +936,7 @@ int cec_transmit_msg_fh(struct cec_adapter *adap, struct cec_msg *msg,
*/
mutex_unlock(&adap->lock);
wait_for_completion_killable(&data->c);
- if (!data->completed)
- cancel_delayed_work_sync(&data->work);
+ cancel_delayed_work_sync(&data->work);
mutex_lock(&adap->lock);


/* Cancel the transmit if it was interrupted */
diff --git a/drivers/media/cec/core/cec-api.c b/drivers/media/cec/core/cec-api.c
index 67dc79ef1705..d64bb716f9c6 100644
--- a/drivers/media/cec/core/cec-api.c
+++ b/drivers/media/cec/core/cec-api.c
@@ -664,6 +664,8 @@ static int cec_release(struct inode *inode, struct file *filp)
list_del_init(&data->xfer_list);
}
mutex_unlock(&adap->lock);
+
+ mutex_lock(&fh->lock);
while (!list_empty(&fh->msgs)) {
struct cec_msg_entry *entry =
list_first_entry(&fh->msgs, struct cec_msg_entry, list);
@@ -681,6 +683,7 @@ static int cec_release(struct inode *inode, struct file *filp)
kfree(entry);
}
}
+ mutex_unlock(&fh->lock);
kfree(fh);


cec_put_device(devnode);
--
2.42.0