From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mail-wm1-f43.google.com (mail-wm1-f43.google.com [209.85.128.43]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 350642DF12E for ; Thu, 19 Mar 2026 16:22:10 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.128.43 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1773937331; cv=none; b=n0NYhqswXiQuuqV7DT+hi5VqsQqZS5o8DJcgNw7fPlve6yeT5mGhLcy0jrSIvq4oN10DJ3hFDhhoA/8QC8MR+D/aXyrtRw80ZkSNverHusAPFtrM0Du9lRUJPZLfoWRfYe2zG1cHrfPvYOVqEhmi7lPI0ZYPsJpNrWyuuHqNltM= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1773937331; c=relaxed/simple; bh=iR0eQvxOhBU9zamCwecHC0DnXI+IzqN8GhB6bKOQG1U=; h=Date:From:To:Cc:Subject:Message-ID:References:MIME-Version: Content-Type:Content-Disposition:In-Reply-To; b=OZZHbdN97smlaZfI9vvMgtnBL9OHYo/Su+tT0dnugREzBXbKO9awkzWf4tVI7S9YhAiS8pbwQHOVs9BS8mLtGV1drSG3aH7bP72lZ5C7TjSHRUm5HcpC9PAGVhJ5YDLGX8JnhI/qNVPqpX/yrEUqzq/CgMZQhjEUv/lsX9062QM= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=suse.com; spf=pass smtp.mailfrom=suse.com; dkim=pass (2048-bit key) header.d=suse.com header.i=@suse.com header.b=V8MIXgV3; arc=none smtp.client-ip=209.85.128.43 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=suse.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=suse.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=suse.com header.i=@suse.com header.b="V8MIXgV3" Received: by mail-wm1-f43.google.com with SMTP id 5b1f17b1804b1-483487335c2so8759695e9.2 for ; Thu, 19 Mar 2026 09:22:09 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=suse.com; s=google; t=1773937328; x=1774542128; darn=vger.kernel.org; h=in-reply-to:content-disposition:mime-version:references:message-id :subject:cc:to:from:date:from:to:cc:subject:date:message-id:reply-to; bh=ofgVV7ZRxJg6Oo03zwn1PqAR/e3UNMkP1d0DQA6j/Uc=; b=V8MIXgV3AyMOsilDOANuKo3sBqIQn6erW+jSpKJW1qoMovONDFQCa0+a07p4l2aA7A 1thwiRMQ573ZZH2uAixbL6GZyftdAnoipJ4avpoczsrW3P20F+CQw8KwTwHG0p54yF1w /Lmx2ZFYM+CaxPMLWIWPDdGKZn1JQqwKmrputD107HqKW0h/PdjLFbqbFTUpwpx5ZRew GgJTn18Z+AKbX1f4tRjpfcEPag9rh8B1NOVjCJCriYg6PwO8BAoARwThyNnyVRrfnO6T GD/cnBhzOeiQbFfrFks5ZDv4vdHbE6HhmXkZTUlyGC3n6BHo81dqFOnfSK/w0Ut8EuR8 DrfQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1773937328; x=1774542128; h=in-reply-to:content-disposition:mime-version:references:message-id :subject:cc:to:from:date:x-gm-gg:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=ofgVV7ZRxJg6Oo03zwn1PqAR/e3UNMkP1d0DQA6j/Uc=; b=MaV/loUIADcTWX02HoGTiFA3uHC3IO6uh16YLrvr2aIKw8z6SdEi6txPX609jBhK4a 9cG/V2PC5Ex2QrqDRDku0WV0hgdaequICCY40Xbuy+Lb4k2biYgRg5XrG3+xK5M+z2OA AiK+KBPcgpBykprvMrh4+jKdMu7P+Jeq0ufZ8lID+7zQmlpIaQZep0/z9iC4l3wfGYye WWso7J47zgZKtSguX6/rjLpgKpOJ2eKGyJdsp433TeaHuKcrhYxRTPU7tQf3vl+dpbuK iDtWD7jmbhPXnL1CF92ONHfGqScnhbGfD5aIQNKaB+RWbJ6MKRSugHOxcmO/qNGdIc+A TBCA== X-Gm-Message-State: AOJu0YxOcIKMVXJfqcTjmv9EYD/6HIfVmzwHV/tyFUxlqqF88/AJsUFd 8R2uE5zb7NRrhJZCXnhFGfTPNZgKgHsasju7eTLgeG7YAFnjrtr8f9brB2WqP/a/Tx4= X-Gm-Gg: ATEYQzwvZZRqr7MIjECdPD67ZWvtt/tKA7IENYdTTZB/fvlsqGGG1uMN0PR2oyq5OVT bwkDKpvp4kagM9YKotZBebycS5bNYWwtXJm+qP0356/HATqvavCCDErt0urJWd/RUSizYcBnFsD I8MWLHK6gfMmMhRWHCa93S+j6OqhohOuLVebs3ZznJwfjNFh9yKhO14Uq1QNgHjKaD0SOykww1e kqrMYLa6cPT7fs+qrKArw96CFHVaHS9A+t4ZTBj2xkOw7/rpf4c3DBCHwplOORidi2qII7wwhRk jBvM+uHCkLYWhyj9T/fjBI2M4QmOFRYKLHIGtr6ZSzvEKXCiIlF1WtfZfMyandi7oTTL+4f2QPP mOqD6JC2rAjToPytyVre76jfmGwV3Gd/ZwaMCSsJTKNjMvUBdMKf/X/qlmbcD930NZW2MBtxybW ZAD569eogujj6zIGQTjU+RZRzJcg== X-Received: by 2002:a05:600c:3e08:b0:485:5812:bb9e with SMTP id 5b1f17b1804b1-486f42018dcmr130545895e9.0.1773937328346; Thu, 19 Mar 2026 09:22:08 -0700 (PDT) Received: from pathway.suse.cz ([176.114.240.130]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-486f8c53324sm85201205e9.15.2026.03.19.09.22.07 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 19 Mar 2026 09:22:08 -0700 (PDT) Date: Thu, 19 Mar 2026 17:22:06 +0100 From: Petr Mladek To: Jianzhou Zhao Cc: linux-kernel@vger.kernel.org, senozhatsky@chromium.org, rostedt@goodmis.org, andriy.shevchenko@linux.intel.com, linux@rasmusvillemoes.dk, akpm@linux-foundation.org Subject: Re: KCSAN: data-race in data_push_tail / symbol_string Message-ID: References: <4a692712.648a.19cdbd3a995.Coremail.luckd0g@163.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <4a692712.648a.19cdbd3a995.Coremail.luckd0g@163.com> Hi Jianzhou, first, thanks a lot for the report. On Wed 2026-03-11 15:36:47, Jianzhou Zhao wrote: > > > Subject: [BUG] printk: KCSAN: data-race in data_push_tail / symbol_string > > Dear Maintainers, > > We are writing to report a KCSAN-detected data-race vulnerability in the Linux kernel. This bug was found by our custom fuzzing tool, RacePilot. The bug occurs during ringbuffer tail advancement where a reader speculatively reads the `blk->id` from a physical address that has concurrently been overwritten by a writer formatting a string. We observed this on the Linux kernel version 6.18.0-08691-g2061f18ad76e-dirty. > > Call Trace & Context > ================================================================== > BUG: KCSAN: data-race in data_push_tail.part.0 / symbol_string > > write to 0xffffffff88f194a8 of 1 bytes by task 38579 on cpu 0: > string_nocheck lib/vsprintf.c:658 [inline] > symbol_string+0x129/0x2c0 lib/vsprintf.c:1020 > pointer+0x24c/0x920 lib/vsprintf.c:2565 > vsnprintf+0x5d0/0xb80 lib/vsprintf.c:2982 > vscnprintf+0x41/0x90 lib/vsprintf.c:3042 > printk_sprint+0x31/0x1c0 kernel/printk/printk.c:2199 > vprintk_store+0x3f6/0x980 kernel/printk/printk.c:2321 > vprintk_emit+0xfd/0x540 kernel/printk/printk.c:2412 > vprintk_default+0x26/0x30 kernel/printk/printk.c:2451 > vprintk+0x1d/0x30 kernel/printk/printk_safe.c:82 > _printk+0x63/0x90 kernel/printk/printk.c:2461 > printk_stack_address arch/x86/kernel/dumpstack.c:70 [inline] > > read to 0xffffffff88f194a8 of 8 bytes by task 38521 on cpu 1: > data_make_reusable kernel/printk/printk_ringbuffer.c:606 [inline] > data_push_tail.part.0+0xe6/0x350 kernel/printk/printk_ringbuffer.c:692 > data_push_tail kernel/printk/printk_ringbuffer.c:656 [inline] > data_alloc+0x157/0x330 kernel/printk/printk_ringbuffer.c:1096 > prb_reserve+0x44d/0x7d0 kernel/printk/printk_ringbuffer.c:1742 > vprintk_store+0x3b4/0x980 kernel/printk/printk.c:2311 > vprintk_emit+0xfd/0x540 kernel/printk/printk.c:2412 > vprintk_default+0x26/0x30 kernel/printk/printk.c:2451 > vprintk+0x1d/0x30 kernel/printk/printk_safe.c:82 > _printk+0x63/0x90 kernel/printk/printk.c:2461 > > value changed: 0x00000000fffff47a -> 0x302f303978302b6c > > Reported by Kernel Concurrency Sanitizer on: > CPU: 1 UID: 0 PID: 38521 Comm: syz.7.1998 Not tainted 6.18.0-08691-g2061f18ad76e-dirty #42 PREEMPT(voluntary) > Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.15.0-1 04/01/2014 > ================================================================== > > Execution Flow & Code Context > On CPU 0, a printing task formats an output string containing a symbol address through `vsprintf.c` which recursively formats data and writes to a buffer natively byte-by-byte: > ```c > // lib/vsprintf.c > static char *string_nocheck(char *buf, char *end, const char *s, > struct printf_spec spec) > { > ... > while (lim--) { > char c = *s++; > ... > if (buf < end) > *buf = c; // <-- Plain Write > ++buf; > ... > } > return widen_string(buf, len, end, spec); > } > ``` > > This destination buffer represents the text block inside the physical `printk_ringbuffer` array, historically mapped out by `data_alloc()`. Concurrently, CPU 1 calls `prb_reserve()` advancing `data_make_reusable()` along the same space to check if it's safe to clear descriptors. The reader uses `blk->id` unannotated to see if a particular logical block was recycled: > ```c > // kernel/printk/printk_ringbuffer.c > static bool data_make_reusable(struct printk_ringbuffer *rb, ...) > { > ... > while (need_more_space(data_ring, lpos_begin, lpos_end)) { > blk = to_block(data_ring, lpos_begin); > > /* > * Load the block ID from the data block. This is a data race > * against a writer that may have newly reserved this data > * area. If the loaded value matches a valid descriptor ID, > ... > */ > id = blk->id; /* LMM(data_make_reusable:A) */ // <-- Plain Lockless Read > ... > ``` > > Root Cause Analysis > A data race occurs because the reader speculatively accesses `blk->id` using a plain memory access (`id = blk->id`). However, because another concurrent task (`CPU 0`) running `vsprintf` has already pushed the logical boundaries on this data array and is linearly formatting strings onto this exact overlapping physical memory region block, `CPU 1` reads data undergoing character writes. This is an intentional heuristic documented by the comment: "This is a data race against a writer that may have newly reserved this data area". Reading garbage here is gracefully handled out-of-band by mapping the `sys_desc` ring ID and concluding it mismatching. However, it still trips compiler sanitizer checks. > Unfortunately, we were unable to generate a reproducer for this bug. > > Potential Impact > This data race is functionally benign. If `data_make_reusable` reads formatted text characters rather than a proper `unsigned long id`, it safely skips it and verifies limits via `blk_lpos` logic. However, tripping the KCSAN sanitizer adds unnecessary debugging noise and may hide actual vulnerabilities under prolonged workloads. > > Proposed Fix > To silence the compiler sanitizer and explicitly annotate to the memory model that this deliberate racing behavior is expected, `data_race()` macro should wrap the read on `blk->id`. > > ```diff > --- a/kernel/printk/printk_ringbuffer.c > +++ b/kernel/printk/printk_ringbuffer.c > @@ -616,7 +616,7 @@ static bool data_make_reusable(struct printk_ringbuffer *rb, > * sure it points back to this data block. If the check fails, > * the data area has been recycled by another writer. > */ > - id = blk->id; /* LMM(data_make_reusable:A) */ > + id = data_race(blk->id); /* LMM(data_make_reusable:A) */ > > d_state = desc_read(desc_ring, id, &desc, NULL, > NULL); /* LMM(data_make_reusable:B) */ > ``` > > We would be highly honored if this could be of any help. The proposed change makes perfect sense. Would you like to send it as a proper patch? Or should I prepare it myself (giving you credits)? The proper patch might be similar to this report. I would just do: + keep only printk-related part of the backtraces + format the other text to keep <= 75 characters long lines + add the tags (Reported-by:, Closes:, Fixes:, Signed-off-by:). Best Regards, Petr