The Linux Kernel Mailing List
 help / color / mirror / Atom feed
* [BUG] WARNING: refcount bug in sync_timeline_signal
@ 2026-08-24 15:56 Jaeyoung Chung
  2026-08-26  8:34 ` Christian König
  0 siblings, 1 reply; 2+ messages in thread
From: Jaeyoung Chung @ 2026-08-24 15:56 UTC (permalink / raw)
  To: christian.koenig, dri-devel, linaro-mm-sig, linux-media,
	sumit.semwal
  Cc: linux-kernel, eulgyukim, jjy600901

Hello,

We found a "WARNING: refcount bug in sync_timeline_signal" on Linux v7.2.
The issue was found by our own race fuzzer. We have not analyzed the root cause,
so we do not have a proposed fix to offer.

To reproduce the race reliably, we applied the delay patch below to the
kernel and ran the C reproducer as root inside an x86_64 QEMU guest. The
crash log we observed, the delay patch and the reproducer are all included
below.

The following kernel config options are required to reproduce the issue:
    CONFIG_SW_SYNC=y
    CONFIG_SYNC_FILE=y
    CONFIG_DMA_SHARED_BUFFER=y
    CONFIG_DEBUG_FS=y
    CONFIG_KASAN=y

We hope this report is useful. Please let us know if any further
information would help.

Reported-by: Eulgyu Kim <eulgyukim@snu.ac.kr>
Reported-by: Jaeyoung Chung <jjy600901@snu.ac.kr>

Kernel delay patch:
==================================================================
diff --git a/drivers/dma-buf/sw_sync.c b/drivers/dma-buf/sw_sync.c
index 8df20b0218a9..d30ce9d915ba 100644
--- a/drivers/dma-buf/sw_sync.c
+++ b/drivers/dma-buf/sw_sync.c
@@ -8,6 +8,7 @@
 #include <linux/file.h>
 #include <linux/fs.h>
 #include <linux/uaccess.h>
+#include <linux/delay.h>
 #include <linux/panic.h>
 #include <linux/slab.h>
 #include <linux/sync_file.h>
@@ -215,6 +216,10 @@ static void sync_timeline_signal(struct sync_timeline *obj, unsigned int inc)
 
 	spin_lock_irq(&obj->lock);
 
+	if (strncmp(current->comm, "syzrepro1", 9) == 0) {
+		mdelay(50);
+	}
+
 	obj->value += inc;
 
 	list_for_each_entry_safe(pt, next, &obj->pt_list, link) {
==================================================================

C reproducer:
==================================================================
#define _GNU_SOURCE
#include <errno.h>
#include <fcntl.h>
#include <pthread.h>
#include <sched.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/ioctl.h>
#include <sys/mount.h>
#include <sys/prctl.h>
#include <sys/stat.h>
#include <time.h>
#include <unistd.h>

#define SYSCHK(x) ({ long __r = (long)(x); if (__r == -1L) { perror(#x); exit(1); } __r; })

#define SW_SYNC_IOC_CREATE_FENCE 0xc0285700u
#define SW_SYNC_IOC_INC 0x40045701u
#define SWSYNC "/sys/kernel/debug/sync/sw_sync"
#define BIAS_US 2000

struct fence_data {
	uint32_t value;
	char name[32];
	int32_t fence;
};

static volatile int g_round, g_stop, g_tl_fd = -1, g_fence_fd = -1;
static volatile int g_armed, g_done0, g_done1;

static void spin_us(long us)
{
	struct timespec a, b;

	clock_gettime(CLOCK_MONOTONIC, &a);
	do {
		clock_gettime(CLOCK_MONOTONIC, &b);
		__asm__ __volatile__("pause" ::: "memory");
	} while ((b.tv_sec - a.tv_sec) * 1000000L + (b.tv_nsec - a.tv_nsec) / 1000L < us);
}

static void pin_cpu(int cpu)
{
	cpu_set_t set;

	CPU_ZERO(&set);
	CPU_SET(cpu, &set);
	sched_setaffinity(0, sizeof(set), &set);
}

static int wait_round(int *last)
{
	while (g_round == *last && !g_stop)
		sched_yield();
	if (g_stop)
		return 0;
	*last = g_round;
	return 1;
}

/* T1: advances the timeline, signalling the pt */
static void *thr_inc(void *a)
{
	unsigned int v = 1;
	int last = 0;

	(void)a;
	prctl(PR_SET_NAME, "syzrepro1", 0, 0, 0);
	pin_cpu(0);
	while (wait_round(&last)) {
		g_armed = 1;
		__sync_synchronize();
		ioctl(g_tl_fd, SW_SYNC_IOC_INC, &v);
		__sync_synchronize();
		g_done1 = 1;
	}
	return NULL;
}

/* T0: closes the fence mid-signal, dropping the pt's last reference */
static void *thr_close(void *a)
{
	int last = 0;

	(void)a;
	prctl(PR_SET_NAME, "syzrepro0", 0, 0, 0);
	pin_cpu(1);
	while (wait_round(&last)) {
		while (!g_armed && !g_stop)
			__asm__ __volatile__("pause" ::: "memory");
		if (g_stop)
			break;
		spin_us(BIAS_US);
		close(g_fence_fd);
		__sync_synchronize();
		g_done0 = 1;
	}
	return NULL;
}

static int open_sw_sync(void)
{
	int fd = open(SWSYNC, O_RDWR);

	if (fd >= 0 || errno != ENOENT)
		return fd;
	mkdir("/sys/kernel/debug", 0755);
	mount("debugfs", "/sys/kernel/debug", "debugfs", 0, NULL);
	return open(SWSYNC, O_RDWR);
}

int main(void)
{
	pthread_t t0, t1;
	long i;

	close(SYSCHK(open_sw_sync()));
	pthread_create(&t1, NULL, thr_inc, NULL);
	pthread_create(&t0, NULL, thr_close, NULL);

	for (i = 0; i < 200 && !g_stop; i++) {
		struct fence_data d = { .value = 1, .name = "syzrepro_pt", .fence = -1 };
		int tl = SYSCHK(open_sw_sync()), w;

		SYSCHK(ioctl(tl, SW_SYNC_IOC_CREATE_FENCE, &d));
		g_tl_fd = tl;
		g_fence_fd = d.fence;
		g_armed = g_done0 = g_done1 = 0;
		__sync_synchronize();
		g_round = i + 1;

		for (w = 0; w < 5000 && !(g_done0 && g_done1); w++) {
			struct timespec ts = { 0, 1000000 };

			nanosleep(&ts, NULL);
		}
		close(tl);
	}

	g_stop = 1;
	__sync_synchronize();
	g_round++;
	pthread_join(t1, NULL);
	pthread_join(t0, NULL);
	return 0;
}
==================================================================

Crash log:
==================================================================
refcount_t: addition on 0; use-after-free.
WARNING: lib/refcount.c:25 at refcount_warn_saturate+0x76/0xd0 lib/refcount.c:25, CPU#0: syzrepro1/402
Modules linked in:
CPU: 0 UID: 0 PID: 402 Comm: syzrepro1 Tainted: G             L      7.2.0-dirty #2 PREEMPT 
Tainted: [L]=SOFTLOCKUP
Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.13.0-1ubuntu1.1 04/01/2014
RIP: 0010:refcount_warn_saturate+0x76/0xd0 lib/refcount.c:25
Code: 3d ff e4 bb 04 67 48 0f b9 3a eb 4d 85 db 74 2f 83 fb 01 75 38 48 8d 3d f8 e4 bb 04 67 48 0f b9 3a eb 36 48 8d 3d fa e4 bb 04 <67> 48 0f b9 3a eb 28 48 8d 3d fc e4 bb 04 67 48 0f b9 3a eb 1a 48
RSP: 0018:ffff88810cd47d68 EFLAGS: 00010046
RAX: 0000000000000000 RBX: 0000000000000002 RCX: dffffc0000000000
RDX: 0000000000000001 RSI: 0000000000000004 RDI: ffffffff9be2c840
RBP: ffff888102a5dc40 R08: ffff888102a5d73b R09: 1ffff1102054bae7
R10: dffffc0000000000 R11: ffffed102054bae8 R12: dffffc0000000000
R13: ffff888102a5d740 R14: ffff888102a5d738 R15: ffff888102a5d738
FS:  00007ae687b8f6c0(0000) GS:ffff88817d75f000(0000) knlGS:0000000000000000
CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: 0000578dd65f7e58 CR3: 000000010b72c000 CR4: 00000000000006f0
Call Trace:
 <TASK>
 __refcount_add include/linux/refcount.h:-1 [inline]
 __refcount_inc include/linux/refcount.h:366 [inline]
 refcount_inc include/linux/refcount.h:383 [inline]
 kref_get include/linux/kref.h:45 [inline]
 dma_fence_get include/linux/dma-fence.h:317 [inline]
 sync_timeline_signal+0x383/0x550 drivers/dma-buf/sw_sync.c:229
 sw_sync_ioctl_inc drivers/dma-buf/sw_sync.c:410 [inline]
 sw_sync_ioctl+0x140/0x980 drivers/dma-buf/sw_sync.c:475
 vfs_ioctl fs/ioctl.c:51 [inline]
 __do_sys_ioctl fs/ioctl.c:597 [inline]
 __se_sys_ioctl+0xb6/0x100 fs/ioctl.c:583
 do_syscall_x64 arch/x86/entry/syscall_64.c:63 [inline]
 do_syscall_64+0xf7/0x370 arch/x86/entry/syscall_64.c:94
 entry_SYSCALL_64_after_hwframe+0x76/0x7e
RIP: 0033:0x7ae687c90d6b
Code: 00 48 89 44 24 18 31 c0 48 8d 44 24 60 c7 04 24 10 00 00 00 48 89 44 24 08 48 8d 44 24 20 48 89 44 24 10 b8 10 00 00 00 0f 05 <89> c2 3d 00 f0 ff ff 77 1c 48 8b 44 24 18 64 48 2b 04 25 28 00 00
RSP: 002b:00007ae687b8edd0 EFLAGS: 00000246 ORIG_RAX: 0000000000000010
RAX: ffffffffffffffda RBX: 00007ae687b8ee3c RCX: 00007ae687c90d6b
RDX: 00007ae687b8ee38 RSI: 0000000040045701 RDI: 0000000000000003
RBP: 0000000000000000 R08: 0000000000000000 R09: 00007ffcdb19abc7
R10: 0000000000000000 R11: 0000000000000246 R12: ffffffffffffff80
R13: 0000000000000000 R14: 00007ffcdb19aad0 R15: 00007ae68738f000
 </TASK>
----------------
Code disassembly (best guess):
   0:	3d ff e4 bb 04       	cmp    $0x4bbe4ff,%eax
   5:	67 48 0f b9 3a       	ud1    (%edx),%rdi
   a:	eb 4d                	jmp    0x59
   c:	85 db                	test   %ebx,%ebx
   e:	74 2f                	je     0x3f
  10:	83 fb 01             	cmp    $0x1,%ebx
  13:	75 38                	jne    0x4d
  15:	48 8d 3d f8 e4 bb 04 	lea    0x4bbe4f8(%rip),%rdi        # 0x4bbe514
  1c:	67 48 0f b9 3a       	ud1    (%edx),%rdi
  21:	eb 36                	jmp    0x59
  23:	48 8d 3d fa e4 bb 04 	lea    0x4bbe4fa(%rip),%rdi        # 0x4bbe524
* 2a:	67 48 0f b9 3a       	ud1    (%edx),%rdi <-- trapping instruction
  2f:	eb 28                	jmp    0x59
  31:	48 8d 3d fc e4 bb 04 	lea    0x4bbe4fc(%rip),%rdi        # 0x4bbe534
  38:	67 48 0f b9 3a       	ud1    (%edx),%rdi
  3d:	eb 1a                	jmp    0x59
  3f:	48                   	rex.W
==================================================================



^ permalink raw reply related	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2026-08-26  8:34 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-08-24 15:56 [BUG] WARNING: refcount bug in sync_timeline_signal Jaeyoung Chung
2026-08-26  8:34 ` Christian König

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox