Skip to content

Commit d18d798

Browse files
committed
printk: kunit: Fix __counted_by() in struct prbtest_rbdata
__counted_by() has to point to a variable which defines the size of the related array. The code must never access the array beyond this limit. struct prbtest_rbdata currently stores the length of the string. And the code access the array beyond the limit when writing or reading the trailing '\0'. Store the size of the string, including the trailing '\0' if we wanted to keep __counted_by(). Consistently use "_size" suffix when the trailing '\0' is counted. Note that MAX_RBDATA_TEXT_SIZE was originally used to limit the text length. When touching the code, make sure that @text_size produced by get_random_u32_inclusive() stays within the limits. Reported-by: Dan Carpenter <dan.carpenter@linaro.org> Closes: https://lore.kernel.org/r/eaea66b9-266a-46e7-980d-33f40ad4b215@sabinyo.mountain Suggested-by: Thomas Weißschuh <thomas.weissschuh@linutronix.de> Reviewed-by: John Ogness <john.ogness@linutronix.de> Reviewed-by: Thomas Weißschuh <thomas.weissschuh@linutronix.de> Link: https://patch.msgid.link/20250702095157.110916-4-pmladek@suse.com Signed-off-by: Petr Mladek <pmladek@suse.com>
1 parent 254e8fb commit d18d798

1 file changed

Lines changed: 27 additions & 20 deletions

File tree

kernel/printk/printk_ringbuffer_kunit_test.c

Lines changed: 27 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -52,13 +52,12 @@ module_param(runtime_ms, ulong, 0400);
5252

5353
/* test data structure */
5454
struct prbtest_rbdata {
55-
unsigned int len;
56-
char text[] __counted_by(len);
55+
unsigned int size;
56+
char text[] __counted_by(size);
5757
};
5858

59-
#define MAX_RBDATA_TEXT_SIZE 0x7f
60-
/* +1 for terminator. */
61-
#define MAX_PRB_RECORD_SIZE (sizeof(struct prbtest_rbdata) + MAX_RBDATA_TEXT_SIZE + 1)
59+
#define MAX_RBDATA_TEXT_SIZE 0x80
60+
#define MAX_PRB_RECORD_SIZE (sizeof(struct prbtest_rbdata) + MAX_RBDATA_TEXT_SIZE)
6261

6362
struct prbtest_data {
6463
struct kunit *test;
@@ -74,25 +73,29 @@ struct prbtest_thread_data {
7473

7574
static void prbtest_fail_record(struct kunit *test, const struct prbtest_rbdata *dat, u64 seq)
7675
{
77-
KUNIT_FAIL(test, "BAD RECORD: seq=%llu len=%u text=%.*s\n",
78-
seq, dat->len,
79-
dat->len <= MAX_RBDATA_TEXT_SIZE ? dat->len : -1,
80-
dat->len <= MAX_RBDATA_TEXT_SIZE ? dat->text : "<invalid>");
76+
unsigned int len;
77+
78+
len = dat->size - 1;
79+
80+
KUNIT_FAIL(test, "BAD RECORD: seq=%llu size=%u text=%.*s\n",
81+
seq, dat->size,
82+
len < MAX_RBDATA_TEXT_SIZE ? len : -1,
83+
len < MAX_RBDATA_TEXT_SIZE ? dat->text : "<invalid>");
8184
}
8285

8386
static bool prbtest_check_data(const struct prbtest_rbdata *dat)
8487
{
8588
unsigned int len;
8689

87-
/* Sane length? */
88-
if (dat->len < 1 || dat->len > MAX_RBDATA_TEXT_SIZE)
90+
/* Sane size? At least one character + trailing '\0' */
91+
if (dat->size < 2 || dat->size > MAX_RBDATA_TEXT_SIZE)
8992
return false;
9093

91-
if (dat->text[dat->len] != '\0')
94+
len = dat->size - 1;
95+
if (dat->text[len] != '\0')
9296
return false;
9397

9498
/* String repeats with the same character? */
95-
len = dat->len;
9699
while (len--) {
97100
if (dat->text[len] != dat->text[0])
98101
return false;
@@ -114,10 +117,14 @@ static int prbtest_writer(void *data)
114117
kunit_info(tr->test_data->test, "start thread %03lu (writer)\n", tr->num);
115118

116119
for (;;) {
117-
/* ensure at least 1 character */
118-
text_size = get_random_u32_inclusive(1, MAX_RBDATA_TEXT_SIZE);
119-
/* +1 for terminator. */
120-
record_size = sizeof(struct prbtest_rbdata) + text_size + 1;
120+
/* ensure at least 1 character + trailing '\0' */
121+
text_size = get_random_u32_inclusive(2, MAX_RBDATA_TEXT_SIZE);
122+
if (WARN_ON_ONCE(text_size < 2))
123+
text_size = 2;
124+
if (WARN_ON_ONCE(text_size > MAX_RBDATA_TEXT_SIZE))
125+
text_size = MAX_RBDATA_TEXT_SIZE;
126+
127+
record_size = sizeof(struct prbtest_rbdata) + text_size;
121128
WARN_ON_ONCE(record_size > MAX_PRB_RECORD_SIZE);
122129

123130
/* specify the text sizes for reservation */
@@ -140,9 +147,9 @@ static int prbtest_writer(void *data)
140147
r.info->text_len = record_size;
141148

142149
dat = (struct prbtest_rbdata *)r.text_buf;
143-
dat->len = text_size;
144-
memset(dat->text, text_id, text_size);
145-
dat->text[text_size] = 0;
150+
dat->size = text_size;
151+
memset(dat->text, text_id, text_size - 1);
152+
dat->text[text_size - 1] = '\0';
146153

147154
prb_commit(&e);
148155

0 commit comments

Comments
 (0)