Message ID | 20240226153754.24998-3-andrea.cervesato@suse.de |
---|---|
State | Superseded |
Headers | show |
Series | SysV IPC bug reproducer | expand |
Hi! > +static void change_access(void *addr, int size, int prot) > +{ > + switch (prot) { > + case PROT_NONE: > + tst_res(TINFO, "Disable memory access. addr: %p - size: %d", > + addr, size); > + break; > + case PROT_WRITE: > + tst_res(TINFO, "Enable write memory access. addr: %p - size: %d", > + addr, size); > + break; > + default: > + tst_res(TINFO, "Change memory access. addr: %p - size: %d", > + addr, size); > + break; > + } > + > + SAFE_MPROTECT(addr, size, prot); > +} Hmm, it's kind of ugly how we wrap the macro here like that... What about we instead add debugging messages to all the SAFE_MACROS()? Given that we added TDEBUG flag recently we can do soemthing as: tst_res_(TDEBUG, file, lineno, "mprotect(%p, %d, %s)", addr, size, prot_to_str(prot)); To the SAFE_MPROTECT() and get the verbose output for free with verbose flag passed to the test. We can do that with all SAFE_MACROS() then we do not have to print most of the messages in this test... > + > +static void run(void) > +{ > + struct shmid_ds shmid_ds; > + void *sh_mem; > + > + segment_id = SAFE_SHMGET( > + key_id, > + segment_size, > + IPC_CREAT | IPC_EXCL | 0600); > + > + sh_mem = SAFE_SHMAT(segment_id, NULL, 0); > + > + tst_res(TINFO, "Attached at %p. key: %d - size: %lu", > + sh_mem, segment_id, segment_size); > + > + SAFE_SHMCTL(segment_id, IPC_STAT, &shmid_ds); > + > + tst_res(TINFO, "Number of attaches: %lu", shmid_ds.shm_nattch); > + > + change_access(sh_mem + page_size, page_size, PROT_NONE); > + change_access(sh_mem, 2 * page_size, PROT_WRITE); > + > + SAFE_SHMCTL(segment_id, IPC_STAT, &shmid_ds); > + > + tst_res(TINFO, "Number of attaches: %lu", shmid_ds.shm_nattch); > + tst_res(TINFO, "Delete attached memory"); > + > + SAFE_SHMDT(sh_mem); > + SAFE_SHMCTL(segment_id, IPC_STAT, &shmid_ds); > + > + tst_res(TINFO, "Number of attaches: %lu", shmid_ds.shm_nattch); > + > + SAFE_SHMCTL(segment_id, IPC_RMID, NULL); > + segment_id = -1; > + > + if (shmid_ds.shm_nattch) > + tst_res(TFAIL, "The system is affected by the SysV IPC bug"); > + else > + tst_res(TPASS, "Test passed"); These messages are not really that useful, we can as well do: TST_EXP_EQ_LU(shmid_ds.shm_nattach, 0); That will provide better message than "PASS: Test passed" > +} > + > +static void setup(void) > +{ > + key_id = GETIPCKEY(); > + page_size = getpagesize(); > + > + tst_res(TINFO, "Key id: %d", key_id); > + tst_res(TINFO, "Page size: %d", page_size); > + > + segment_size = 3 * page_size; > +} > + > +static void cleanup(void) > +{ > + if (segment_id != -1) > + SAFE_SHMCTL(segment_id, IPC_RMID, NULL); > +} > + > +static struct tst_test test = { > + .test_all = run, > + .setup = setup, > + .cleanup = cleanup, > +}; > -- > 2.35.3 > > > -- > Mailing list info: https://lists.linux.it/listinfo/ltp
Hi! On 2/26/24 17:06, Cyril Hrubis wrote: > Hi! >> +static void change_access(void *addr, int size, int prot) >> +{ >> + switch (prot) { >> + case PROT_NONE: >> + tst_res(TINFO, "Disable memory access. addr: %p - size: %d", >> + addr, size); >> + break; >> + case PROT_WRITE: >> + tst_res(TINFO, "Enable write memory access. addr: %p - size: %d", >> + addr, size); >> + break; >> + default: >> + tst_res(TINFO, "Change memory access. addr: %p - size: %d", >> + addr, size); >> + break; >> + } >> + >> + SAFE_MPROTECT(addr, size, prot); >> +} > Hmm, it's kind of ugly how we wrap the macro here like that... > > What about we instead add debugging messages to all the SAFE_MACROS()? > > Given that we added TDEBUG flag recently we can do soemthing as: > > tst_res_(TDEBUG, file, lineno, "mprotect(%p, %d, %s)", > addr, size, prot_to_str(prot)); > > To the SAFE_MPROTECT() and get the verbose output for free with verbose > flag passed to the test. > > We can do that with all SAFE_MACROS() then we do not have to print most > of the messages in this test... Is this comment related with the previous patch of the set? >> + >> +static void run(void) >> +{ >> + struct shmid_ds shmid_ds; >> + void *sh_mem; >> + >> + segment_id = SAFE_SHMGET( >> + key_id, >> + segment_size, >> + IPC_CREAT | IPC_EXCL | 0600); >> + >> + sh_mem = SAFE_SHMAT(segment_id, NULL, 0); >> + >> + tst_res(TINFO, "Attached at %p. key: %d - size: %lu", >> + sh_mem, segment_id, segment_size); >> + >> + SAFE_SHMCTL(segment_id, IPC_STAT, &shmid_ds); >> + >> + tst_res(TINFO, "Number of attaches: %lu", shmid_ds.shm_nattch); >> + >> + change_access(sh_mem + page_size, page_size, PROT_NONE); >> + change_access(sh_mem, 2 * page_size, PROT_WRITE); >> + >> + SAFE_SHMCTL(segment_id, IPC_STAT, &shmid_ds); >> + >> + tst_res(TINFO, "Number of attaches: %lu", shmid_ds.shm_nattch); >> + tst_res(TINFO, "Delete attached memory"); >> + >> + SAFE_SHMDT(sh_mem); >> + SAFE_SHMCTL(segment_id, IPC_STAT, &shmid_ds); >> + >> + tst_res(TINFO, "Number of attaches: %lu", shmid_ds.shm_nattch); >> + >> + SAFE_SHMCTL(segment_id, IPC_RMID, NULL); >> + segment_id = -1; >> + >> + if (shmid_ds.shm_nattch) >> + tst_res(TFAIL, "The system is affected by the SysV IPC bug"); >> + else >> + tst_res(TPASS, "Test passed"); > These messages are not really that useful, we can as well do: > > TST_EXP_EQ_LU(shmid_ds.shm_nattach, 0); > > That will provide better message than "PASS: Test passed" > >> +} >> + >> +static void setup(void) >> +{ >> + key_id = GETIPCKEY(); >> + page_size = getpagesize(); >> + >> + tst_res(TINFO, "Key id: %d", key_id); >> + tst_res(TINFO, "Page size: %d", page_size); >> + >> + segment_size = 3 * page_size; >> +} >> + >> +static void cleanup(void) >> +{ >> + if (segment_id != -1) >> + SAFE_SHMCTL(segment_id, IPC_RMID, NULL); >> +} >> + >> +static struct tst_test test = { >> + .test_all = run, >> + .setup = setup, >> + .cleanup = cleanup, >> +}; >> -- >> 2.35.3 >> >> >> -- >> Mailing list info: https://lists.linux.it/listinfo/ltp Andrea
Hi! > > Hmm, it's kind of ugly how we wrap the macro here like that... > > > > What about we instead add debugging messages to all the SAFE_MACROS()? > > > > Given that we added TDEBUG flag recently we can do soemthing as: > > > > tst_res_(TDEBUG, file, lineno, "mprotect(%p, %d, %s)", > > addr, size, prot_to_str(prot)); > > > > To the SAFE_MPROTECT() and get the verbose output for free with verbose > > flag passed to the test. > > > > We can do that with all SAFE_MACROS() then we do not have to print most > > of the messages in this test... > Is this comment related with the previous patch of the set? Not at all, I'm just complaining that we are adding debuging print to the test itself when it would be much cleaner to put it into the test library instead.
> Hi! > > > Hmm, it's kind of ugly how we wrap the macro here like that... > > > What about we instead add debugging messages to all the SAFE_MACROS()? > > > Given that we added TDEBUG flag recently we can do soemthing as: > > > tst_res_(TDEBUG, file, lineno, "mprotect(%p, %d, %s)", > > > addr, size, prot_to_str(prot)); > > > To the SAFE_MPROTECT() and get the verbose output for free with verbose > > > flag passed to the test. > > > We can do that with all SAFE_MACROS() then we do not have to print most > > > of the messages in this test... > > Is this comment related with the previous patch of the set? > Not at all, I'm just complaining that we are adding debuging print to > the test itself when it would be much cleaner to put it into the test > library instead. +1, setting patchset as changes requested, please send v3. Kind regards, Petr
diff --git a/runtest/syscalls b/runtest/syscalls index 7794f1465..cc0144379 100644 --- a/runtest/syscalls +++ b/runtest/syscalls @@ -1445,6 +1445,7 @@ setxattr03 setxattr03 shmat01 shmat01 shmat02 shmat02 shmat03 shmat03 +shmat04 shmat04 shmctl01 shmctl01 shmctl02 shmctl02 diff --git a/runtest/syscalls-ipc b/runtest/syscalls-ipc index df41140a7..9860394de 100644 --- a/runtest/syscalls-ipc +++ b/runtest/syscalls-ipc @@ -49,6 +49,7 @@ semop03 semop03 shmat01 shmat01 shmat02 shmat02 +shmat04 shmat04 shmctl01 shmctl01 shmctl02 shmctl02 diff --git a/testcases/kernel/syscalls/ipc/shmat/.gitignore b/testcases/kernel/syscalls/ipc/shmat/.gitignore index 2b972f8f2..5600b2742 100644 --- a/testcases/kernel/syscalls/ipc/shmat/.gitignore +++ b/testcases/kernel/syscalls/ipc/shmat/.gitignore @@ -1,3 +1,4 @@ /shmat01 /shmat02 /shmat03 +/shmat04 diff --git a/testcases/kernel/syscalls/ipc/shmat/shmat04.c b/testcases/kernel/syscalls/ipc/shmat/shmat04.c new file mode 100644 index 000000000..63daaa73e --- /dev/null +++ b/testcases/kernel/syscalls/ipc/shmat/shmat04.c @@ -0,0 +1,115 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright (C) 2024 SUSE LLC + * Author: Michal Hocko <mhocko@suse.com> + * LTP port: Andrea Cervesato <andrea.cervesato@suse.com> + */ + +/*\ + * [Description] + * + * When debugging issues with a workload using SysV shmem, Michal Hocko has + * come up with a reproducer that shows how a series of mprotect() + * operations can result in an elevated shm_nattch and thus leak of the + * resource. + * + * The problem is caused by wrong assumptions in vma_merge() commit + * 714965ca8252 ("mm/mmap: start distinguishing if vma can be removed in + * mergeability test"). The shmem vmas have a vma_ops->close callback + * that decrements shm_nattch, and we remove the vma without calling it. + * + * Patch: https://lore.kernel.org/all/20240222215930.14637-2-vbabka@suse.cz/ + */ + +#include "tst_test.h" +#include "tst_safe_sysv_ipc.h" +#include "libnewipc.h" + +static int segment_id = -1; +static int key_id; +static int page_size; +static size_t segment_size; + +static void change_access(void *addr, int size, int prot) +{ + switch (prot) { + case PROT_NONE: + tst_res(TINFO, "Disable memory access. addr: %p - size: %d", + addr, size); + break; + case PROT_WRITE: + tst_res(TINFO, "Enable write memory access. addr: %p - size: %d", + addr, size); + break; + default: + tst_res(TINFO, "Change memory access. addr: %p - size: %d", + addr, size); + break; + } + + SAFE_MPROTECT(addr, size, prot); +} + +static void run(void) +{ + struct shmid_ds shmid_ds; + void *sh_mem; + + segment_id = SAFE_SHMGET( + key_id, + segment_size, + IPC_CREAT | IPC_EXCL | 0600); + + sh_mem = SAFE_SHMAT(segment_id, NULL, 0); + + tst_res(TINFO, "Attached at %p. key: %d - size: %lu", + sh_mem, segment_id, segment_size); + + SAFE_SHMCTL(segment_id, IPC_STAT, &shmid_ds); + + tst_res(TINFO, "Number of attaches: %lu", shmid_ds.shm_nattch); + + change_access(sh_mem + page_size, page_size, PROT_NONE); + change_access(sh_mem, 2 * page_size, PROT_WRITE); + + SAFE_SHMCTL(segment_id, IPC_STAT, &shmid_ds); + + tst_res(TINFO, "Number of attaches: %lu", shmid_ds.shm_nattch); + tst_res(TINFO, "Delete attached memory"); + + SAFE_SHMDT(sh_mem); + SAFE_SHMCTL(segment_id, IPC_STAT, &shmid_ds); + + tst_res(TINFO, "Number of attaches: %lu", shmid_ds.shm_nattch); + + SAFE_SHMCTL(segment_id, IPC_RMID, NULL); + segment_id = -1; + + if (shmid_ds.shm_nattch) + tst_res(TFAIL, "The system is affected by the SysV IPC bug"); + else + tst_res(TPASS, "Test passed"); +} + +static void setup(void) +{ + key_id = GETIPCKEY(); + page_size = getpagesize(); + + tst_res(TINFO, "Key id: %d", key_id); + tst_res(TINFO, "Page size: %d", page_size); + + segment_size = 3 * page_size; +} + +static void cleanup(void) +{ + if (segment_id != -1) + SAFE_SHMCTL(segment_id, IPC_RMID, NULL); +} + +static struct tst_test test = { + .test_all = run, + .setup = setup, + .cleanup = cleanup, +};