All of lore.kernel.org
 help / color / mirror / Atom feed
* [LTP] shmctl03.c is broken for 32bit compat mode
@ 2025-08-08 13:53 Dan Carpenter
  2025-08-10  3:46 ` Li Wang via ltp
  0 siblings, 1 reply; 5+ messages in thread
From: Dan Carpenter @ 2025-08-08 13:53 UTC (permalink / raw)
  To: ltp; +Cc: Theodore Grey

In 32bit compat mode the shmctl03.c test will always fail:

shmctl03.c:33: TFAIL: /proc/sys/kernel/shmmax != 2147483647 got 4294967295
shmctl03.c:34: TPASS: /proc/sys/kernel/shmmni = 4096
shmctl03.c:35: TFAIL: /proc/sys/kernel/shmall != 4278190079 got 4294967295

The test basically does this:
// === === ===
#define _GNU_SOURCE
#include <sys/shm.h>
#include <stdio.h>

int main(void)
{
	struct shminfo info;

	shmctl(0, IPC_INFO, (struct shmid_ds *)&info);

	printf("shmmax = %lu\n", info.shmmax);
	printf("shmmni = %lu\n", info.shmmni);
	printf("shmall = %lu\n", info.shmall);

	return 0;
}
// === === ===

It compares that output with what we read from the file.  You can run
"gcc -m32 test.c && ./a.out" to see the issue.

In the first line shmmax is not the value that we read from the file
because it was capped at INT_MAX by the kernel in commit af7c693f1460
("Cap shmmax at INT_MAX in compat shminfo").
https://elixir.bootlin.com/linux/v6.16/source/ipc/shm.c#L1347

With the last line we're trying to store a u64 value into a u32.  We're
going to lose something so it's not going to be accurate.  The difference
is how scanf() truncates it.  If you have 32bit longs then it will give
you the first u32 but if you assign a u64 to a u32 like the rest of the
code does then you'll get the last 32 bits.

What's the right way to go about fixing this?

regards,
dan carpenter

-- 
Mailing list info: https://lists.linux.it/listinfo/ltp

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

* Re: [LTP] shmctl03.c is broken for 32bit compat mode
  2025-08-08 13:53 [LTP] shmctl03.c is broken for 32bit compat mode Dan Carpenter
@ 2025-08-10  3:46 ` Li Wang via ltp
  2025-08-11  8:03   ` Dan Carpenter
  0 siblings, 1 reply; 5+ messages in thread
From: Li Wang via ltp @ 2025-08-10  3:46 UTC (permalink / raw)
  To: Dan Carpenter; +Cc: Theodore Grey, ltp

Hi Dan,

On Fri, Aug 8, 2025 at 9:53 PM Dan Carpenter <dan.carpenter@linaro.org>
wrote:

> In 32bit compat mode the shmctl03.c test will always fail:
>
> shmctl03.c:33: TFAIL: /proc/sys/kernel/shmmax != 2147483647 got 4294967295
> shmctl03.c:34: TPASS: /proc/sys/kernel/shmmni = 4096
> shmctl03.c:35: TFAIL: /proc/sys/kernel/shmall != 4278190079 got 4294967295
>
> The test basically does this:
> // === === ===
> #define _GNU_SOURCE
> #include <sys/shm.h>
> #include <stdio.h>
>
> int main(void)
> {
>         struct shminfo info;
>
>         shmctl(0, IPC_INFO, (struct shmid_ds *)&info);
>
>         printf("shmmax = %lu\n", info.shmmax);
>         printf("shmmni = %lu\n", info.shmmni);
>         printf("shmall = %lu\n", info.shmall);
>
>         return 0;
> }
> // === === ===
>
> It compares that output with what we read from the file.  You can run
> "gcc -m32 test.c && ./a.out" to see the issue.
>
> In the first line shmmax is not the value that we read from the file
> because it was capped at INT_MAX by the kernel in commit af7c693f1460
> ("Cap shmmax at INT_MAX in compat shminfo").
> https://elixir.bootlin.com/linux/v6.16/source/ipc/shm.c#L1347
>
> With the last line we're trying to store a u64 value into a u32.  We're
> going to lose something so it's not going to be accurate.  The difference
> is how scanf() truncates it.  If you have 32bit longs then it will give
> you the first u32 but if you assign a u64 to a u32 like the rest of the
> code does then you'll get the last 32 bits.
>
> What's the right way to go about fixing this?
>

Maybe we can simply split the comparison part into two:

  #ifdef TST_ABI64: go with the original way.

  #ifdef TST_ABI32:
      'shmmax' expects INT_MAX from shmctl(0, IPC_INFO, ...), even if '
/proc/sys/kernel/shmmax' is higher.
      'shmall' compares the lower 32 bits of the value (expect_shmall =
shmall & 0xFFFFFFFF;)


-- 
Regards,
Li Wang

-- 
Mailing list info: https://lists.linux.it/listinfo/ltp

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

* Re: [LTP] shmctl03.c is broken for 32bit compat mode
  2025-08-10  3:46 ` Li Wang via ltp
@ 2025-08-11  8:03   ` Dan Carpenter
  2025-08-11  9:35     ` Cyril Hrubis
  2025-08-12  8:40     ` Li Wang via ltp
  0 siblings, 2 replies; 5+ messages in thread
From: Dan Carpenter @ 2025-08-11  8:03 UTC (permalink / raw)
  To: Li Wang; +Cc: Theodore Grey, ltp

On Sun, Aug 10, 2025 at 11:46:32AM +0800, Li Wang wrote:
> Hi Dan,
> 
> On Fri, Aug 8, 2025 at 9:53 PM Dan Carpenter <dan.carpenter@linaro.org>
> wrote:
> 
> > In 32bit compat mode the shmctl03.c test will always fail:
> >
> > shmctl03.c:33: TFAIL: /proc/sys/kernel/shmmax != 2147483647 got 4294967295
> > shmctl03.c:34: TPASS: /proc/sys/kernel/shmmni = 4096
> > shmctl03.c:35: TFAIL: /proc/sys/kernel/shmall != 4278190079 got 4294967295
> >
> > The test basically does this:
> > // === === ===
> > #define _GNU_SOURCE
> > #include <sys/shm.h>
> > #include <stdio.h>
> >
> > int main(void)
> > {
> >         struct shminfo info;
> >
> >         shmctl(0, IPC_INFO, (struct shmid_ds *)&info);
> >
> >         printf("shmmax = %lu\n", info.shmmax);
> >         printf("shmmni = %lu\n", info.shmmni);
> >         printf("shmall = %lu\n", info.shmall);
> >
> >         return 0;
> > }
> > // === === ===
> >
> > It compares that output with what we read from the file.  You can run
> > "gcc -m32 test.c && ./a.out" to see the issue.
> >
> > In the first line shmmax is not the value that we read from the file
> > because it was capped at INT_MAX by the kernel in commit af7c693f1460
> > ("Cap shmmax at INT_MAX in compat shminfo").
> > https://elixir.bootlin.com/linux/v6.16/source/ipc/shm.c#L1347
> >
> > With the last line we're trying to store a u64 value into a u32.  We're
> > going to lose something so it's not going to be accurate.  The difference
> > is how scanf() truncates it.  If you have 32bit longs then it will give
> > you the first u32 but if you assign a u64 to a u32 like the rest of the
> > code does then you'll get the last 32 bits.
> >
> > What's the right way to go about fixing this?
> >
> 
> Maybe we can simply split the comparison part into two:
> 
>   #ifdef TST_ABI64: go with the original way.
> 
>   #ifdef TST_ABI32:

Will this affect real 32bit systems?  The problem is only when we're
emulating a 32bit system on a 64bit system using the COMPAT code.

>       'shmmax' expects INT_MAX from shmctl(0, IPC_INFO, ...), even if '
> /proc/sys/kernel/shmmax' is higher.
>       'shmall' compares the lower 32 bits of the value (expect_shmall =
> shmall & 0xFFFFFFFF;)
> 

To be honest, the correct thing with regards to shmall is to cap it at
INT_MAX in the kernel as well.  I didn't want to suggest this because it
was Friday afternoon.  Reporting whatever is in the low 32bits is sort
of random.  But that would make it even more tricky to handle in LTP.

regards,
dan carpenter


-- 
Mailing list info: https://lists.linux.it/listinfo/ltp

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

* Re: [LTP] shmctl03.c is broken for 32bit compat mode
  2025-08-11  8:03   ` Dan Carpenter
@ 2025-08-11  9:35     ` Cyril Hrubis
  2025-08-12  8:40     ` Li Wang via ltp
  1 sibling, 0 replies; 5+ messages in thread
From: Cyril Hrubis @ 2025-08-11  9:35 UTC (permalink / raw)
  To: Dan Carpenter; +Cc: ltp, Theodore Grey

Hi!
> To be honest, the correct thing with regards to shmall is to cap it at
> INT_MAX in the kernel as well.  I didn't want to suggest this because it
> was Friday afternoon.  Reporting whatever is in the low 32bits is sort
> of random.  But that would make it even more tricky to handle in LTP.

We have tst_is_compat_mode() helper that returns true if we are running
in 32bit compatibility mode. So I suppose that we need a flag for the
TST_ASSERT_ULONG() that would tell it to do a saturated comparsion:

diff --git a/testcases/kernel/syscalls/ipc/shmctl/shmctl03.c b/testcases/kernel/syscalls/ipc/shmctl/shmctl03.c
index a3291c37f..5e33b3a2c 100644
--- a/testcases/kernel/syscalls/ipc/shmctl/shmctl03.c
+++ b/testcases/kernel/syscalls/ipc/shmctl/shmctl03.c
@@ -16,6 +16,7 @@
 static void verify_ipcinfo(void)
 {
        struct shminfo info;
+       int flag = 0;

        TEST(shmctl(0, IPC_INFO, (struct shmid_ds *)&info));

@@ -30,9 +31,12 @@ static void verify_ipcinfo(void)
        else
                tst_res(TPASS, "shmmin = 1");

-       TST_ASSERT_ULONG("/proc/sys/kernel/shmmax", info.shmmax);
-       TST_ASSERT_ULONG("/proc/sys/kernel/shmmni", info.shmmni);
-       TST_ASSERT_ULONG("/proc/sys/kernel/shmall", info.shmall);
+       if (tst_is_compat_mode())
+               flag = TST_ASSERT_ULONG_SATURATED;
+
+       TST_ASSERT_ULONG("/proc/sys/kernel/shmmax", info.shmmax, flag);
+       TST_ASSERT_ULONG("/proc/sys/kernel/shmmni", info.shmmni, flag);
+       TST_ASSERT_ULONG("/proc/sys/kernel/shmall", info.shmall, flag);
 }

And the TST_ASSERT_ULONG() would read the syfs file as unsigned long
long and if the saturated flag is present cap it at ULONG_MAX.

-- 
Cyril Hrubis
chrubis@suse.cz

-- 
Mailing list info: https://lists.linux.it/listinfo/ltp

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

* Re: [LTP] shmctl03.c is broken for 32bit compat mode
  2025-08-11  8:03   ` Dan Carpenter
  2025-08-11  9:35     ` Cyril Hrubis
@ 2025-08-12  8:40     ` Li Wang via ltp
  1 sibling, 0 replies; 5+ messages in thread
From: Li Wang via ltp @ 2025-08-12  8:40 UTC (permalink / raw)
  To: Dan Carpenter; +Cc: Theodore Grey, ltp

On Mon, Aug 11, 2025 at 4:04 PM Dan Carpenter <dan.carpenter@linaro.org>
wrote:

> On Sun, Aug 10, 2025 at 11:46:32AM +0800, Li Wang wrote:
> > Hi Dan,
> >
> > On Fri, Aug 8, 2025 at 9:53 PM Dan Carpenter <dan.carpenter@linaro.org>
> > wrote:
> >
> > > In 32bit compat mode the shmctl03.c test will always fail:
> > >
> > > shmctl03.c:33: TFAIL: /proc/sys/kernel/shmmax != 2147483647 got
> 4294967295
> > > shmctl03.c:34: TPASS: /proc/sys/kernel/shmmni = 4096
> > > shmctl03.c:35: TFAIL: /proc/sys/kernel/shmall != 4278190079 got
> 4294967295
> > >
> > > The test basically does this:
> > > // === === ===
> > > #define _GNU_SOURCE
> > > #include <sys/shm.h>
> > > #include <stdio.h>
> > >
> > > int main(void)
> > > {
> > >         struct shminfo info;
> > >
> > >         shmctl(0, IPC_INFO, (struct shmid_ds *)&info);
> > >
> > >         printf("shmmax = %lu\n", info.shmmax);
> > >         printf("shmmni = %lu\n", info.shmmni);
> > >         printf("shmall = %lu\n", info.shmall);
> > >
> > >         return 0;
> > > }
> > > // === === ===
> > >
> > > It compares that output with what we read from the file.  You can run
> > > "gcc -m32 test.c && ./a.out" to see the issue.
> > >
> > > In the first line shmmax is not the value that we read from the file
> > > because it was capped at INT_MAX by the kernel in commit af7c693f1460
> > > ("Cap shmmax at INT_MAX in compat shminfo").
> > > https://elixir.bootlin.com/linux/v6.16/source/ipc/shm.c#L1347
> > >
> > > With the last line we're trying to store a u64 value into a u32.  We're
> > > going to lose something so it's not going to be accurate.  The
> difference
> > > is how scanf() truncates it.  If you have 32bit longs then it will give
> > > you the first u32 but if you assign a u64 to a u32 like the rest of the
> > > code does then you'll get the last 32 bits.
> > >
> > > What's the right way to go about fixing this?
> > >
> >
> > Maybe we can simply split the comparison part into two:
> >
> >   #ifdef TST_ABI64: go with the original way.
> >
> >   #ifdef TST_ABI32:
>
> Will this affect real 32bit systems?  The problem is only when we're
> emulating a 32bit system on a 64bit system using the COMPAT code.
>

Yes, you're right.

Looking into the kernel and test related code, that seems the test will pass
as long as that /proc/sys/kernel/{shmmax,shmmni,shmall} equals with the
info.{shmmax,shmmni,shmall}.

On a modern native 32bit platform, it will still choose the IPC_64 branch
and the
kernel copies shminfo64 fields directly. So test should pass as well.
https://elixir.bootlin.com/linux/v6.16/source/ipc/shm.c#L906



>
> >       'shmmax' expects INT_MAX from shmctl(0, IPC_INFO, ...), even if '
> > /proc/sys/kernel/shmmax' is higher.
> >       'shmall' compares the lower 32 bits of the value (expect_shmall =
> > shmall & 0xFFFFFFFF;)
> >
>
> To be honest, the correct thing with regards to shmall is to cap it at
> INT_MAX in the kernel as well.  I didn't want to suggest this because it
> was Friday afternoon.  Reporting whatever is in the low 32bits is sort
> of random.  But that would make it even more tricky to handle in LTP.
>

Okay, you can try Cyril's suggestion, which sounds more reliable.

-- 
Regards,
Li Wang

-- 
Mailing list info: https://lists.linux.it/listinfo/ltp

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

end of thread, other threads:[~2025-08-12  8:40 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-08-08 13:53 [LTP] shmctl03.c is broken for 32bit compat mode Dan Carpenter
2025-08-10  3:46 ` Li Wang via ltp
2025-08-11  8:03   ` Dan Carpenter
2025-08-11  9:35     ` Cyril Hrubis
2025-08-12  8:40     ` Li Wang via ltp

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.