Re: [BUG] taskstats: REGISTER_CPUMASK silently truncates the last byte of the cpumask string
From: Andrew Morton
Date: Thu Jul 23 2026 - 19:17:18 EST
On Thu, 23 Jul 2026 22:11:43 +0100 Bradley Morgan <include@xxxxxxxxx> wrote:
>...
>
> Hi Andrew, let me be honest, I CBA to do a new thread, here's my suggestion
Seems this fooled Sashiko, so no AI review for you!
> From: Bradley Morgan <include@xxxxxxxxx>
> Date: Thu, 23 Jul 2026 21:09:22 +0000
> Subject: [PATCH] taskstats: fix cpumask parsing cutting off the last character
>
> parse() hands nla_strscpy() len as dstsize, and nla_strscpy() copies
> at most dstsize - 1 bytes. When the attr payload comes in without a
> trailing NUL, srclen == len >= dstsize and the last character of the
> cpumask string gets cut off. Register "0-15" and you are silently
> listening on "0-1", exit data for the rest never shows up.
>
> The bug only bites when the sender doesnt NUL terminate the payload;
> senders that include the NUL were always fine (srclen gets decremented
> for the trailing NUL, so srclen < dstsize). Thats probably why this
> survived 20 years. And the policy is NLA_STRING, not NLA_NUL_STRING,
> so a payload without the trailing NUL is legit input here.
>
> Skip the kmalloc/nla_strscpy dance entirely and use nla_strdup(),
> which already allocates srclen + 1 and terminates. The nla_len()
> bounds checks stay as they were.
>
> ...
>
> --- a/kernel/taskstats.c
> +++ b/kernel/taskstats.c
> @@ -371,10 +371,9 @@ static int parse(struct nlattr *na, struct cpumask *mask)
> return -E2BIG;
> if (len < 1)
> return -EINVAL;
> - data = kmalloc(len, GFP_KERNEL);
> + data = nla_strdup(na, GFP_KERNEL);
> if (!data)
> return -ENOMEM;
> - nla_strscpy(data, na, len);
> ret = cpulist_parse(data, mask);
> kfree(data);
> return ret;
Nice, thanks, There's a nla_strdup(), who knew?
(nla_strdup() could use kstrdup(), btw?)