Re: include/linux/thread_info.h:259:25: error: call to '__bad_copy_to' declared with attribute error: copy destination size is too small
From: Arnd Bergmann
Date: Fri Feb 14 2025 - 06:24:40 EST
On Fri, Feb 14, 2025, at 09:44, Philip Li wrote:
> On Mon, Feb 10, 2025 at 02:39:46PM -0600, Elizabeth Figura wrote:
>> On Friday, 7 February 2025 06:11:47 CST kernel test robot wrote:
>> > In file included from include/linux/spinlock.h:60,
>> > from include/linux/wait.h:9,
>> > from include/linux/wait_bit.h:8,
>> > from include/linux/fs.h:6,
>> > from drivers/misc/ntsync.c:11:
>> > In function 'check_copy_size',
>> > inlined from 'copy_from_user' at include/linux/uaccess.h:207:7,
>> > inlined from 'setup_wait' at drivers/misc/ntsync.c:888:6:
>> > >> include/linux/thread_info.h:259:25: error: call to '__bad_copy_to' declared with attribute error: copy destination size is too small
>> > 259 | __bad_copy_to();
>> > | ^~~~~~~~~~~~~~~
>>
>> This was caught before and mentioned in [1]. The suggestion there of changing "args->count" to "count" doesn't help.
>>
>> Somehow gcc 12 thinks that the array_size(count, sizeof(*fds)) parameter is constant, although it's finnicky and depends on exactly where __builtin_constant_p() is evaluated.
>>
>> The bug goes away with gcc 13. Is this worth trying to work around? I don't have any ideas for how to do so.
>
> Thanks for the info, at bot side, we will ignore this error to
> avoid further reporting on old gcc.
gcc-12 isn't really "old", we support gcc-5 through gcc-14 at the moment.
Maybe the change below would address it? (Not sure I handled the
"+1" right here, but something like that should make it obvious
to the compiler what the check is).
Arnd
diff --git a/drivers/misc/ntsync.c b/drivers/misc/ntsync.c
index 055395cde42b..ae13aae9194b 100644
--- a/drivers/misc/ntsync.c
+++ b/drivers/misc/ntsync.c
@@ -873,6 +873,7 @@ static int setup_wait(struct ntsync_device *dev,
{
int fds[NTSYNC_MAX_WAIT_COUNT + 1];
const __u32 count = args->count;
+ size_t size = count * sizeof(fds[0]);
struct ntsync_q *q;
__u32 total_count;
__u32 i, j;
@@ -880,15 +881,14 @@ static int setup_wait(struct ntsync_device *dev,
if (args->pad || (args->flags & ~NTSYNC_WAIT_REALTIME))
return -EINVAL;
- if (args->count > NTSYNC_MAX_WAIT_COUNT)
+ if (size >= sizeof(fds))
return -EINVAL;
total_count = count;
if (args->alert)
total_count++;
- if (copy_from_user(fds, u64_to_user_ptr(args->objs),
- array_size(count, sizeof(*fds))))
+ if (copy_from_user(fds, u64_to_user_ptr(args->objs), size))
return -EFAULT;
if (args->alert)
fds[count] = args->alert;