Message ID | 20240724210515.473004-4-hjl.tools@gmail.com |
---|---|
State | New |
Headers | show |
Series | linux: Update the mremap C implementation [BZ #31968] | expand |
On 24/07/24 18:05, H.J. Lu wrote: > Add tests for MREMAP_MAYMOVE and MREMAP_FIXED. On Linux, also test > MREMAP_DONTUNMAP. > > Signed-off-by: H.J. Lu <hjl.tools@gmail.com> LGTM, thanks. Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org> > --- > misc/Makefile | 2 + > misc/tst-mremap1.c | 46 +++++++++++++++ > misc/tst-mremap2.c | 54 ++++++++++++++++++ > sysdeps/generic/mremap-failure.h | 25 ++++++++ > sysdeps/unix/sysv/linux/Makefile | 1 + > sysdeps/unix/sysv/linux/mremap-failure.h | 30 ++++++++++ > sysdeps/unix/sysv/linux/tst-linux-mremap1.c | 63 +++++++++++++++++++++ > 7 files changed, 221 insertions(+) > create mode 100644 misc/tst-mremap1.c > create mode 100644 misc/tst-mremap2.c > create mode 100644 sysdeps/generic/mremap-failure.h > create mode 100644 sysdeps/unix/sysv/linux/mremap-failure.h > create mode 100644 sysdeps/unix/sysv/linux/tst-linux-mremap1.c > > diff --git a/misc/Makefile b/misc/Makefile > index 5d17c562fe..7b7f8351bf 100644 > --- a/misc/Makefile > +++ b/misc/Makefile > @@ -257,6 +257,8 @@ tests := \ > tst-mntent-blank-passno \ > tst-mntent-escape \ > tst-mntent2 \ > + tst-mremap1 \ > + tst-mremap2 \ > tst-preadvwritev \ > tst-preadvwritev2 \ > tst-preadvwritev64 \ > diff --git a/misc/tst-mremap1.c b/misc/tst-mremap1.c > new file mode 100644 > index 0000000000..0469991a6c > --- /dev/null > +++ b/misc/tst-mremap1.c > @@ -0,0 +1,46 @@ > +/* Test mremap with MREMAP_MAYMOVE. > + Copyright (C) 2024 Free Software Foundation, Inc. > + This file is part of the GNU C Library. > + > + The GNU C Library is free software; you can redistribute it and/or > + modify it under the terms of the GNU Lesser General Public > + License as published by the Free Software Foundation; either > + version 2.1 of the License, or (at your option) any later version. > + > + The GNU C Library is distributed in the hope that it will be useful, > + but WITHOUT ANY WARRANTY; without even the implied warranty of > + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU > + Lesser General Public License for more details. > + > + You should have received a copy of the GNU Lesser General Public > + License along with the GNU C Library; if not, see > + <https://www.gnu.org/licenses/>. */ > + > +#include <errno.h> > +#include <sys/mman.h> > +#include <support/xstdlib.h> > +#include <support/xunistd.h> > +#include <support/check.h> > +#include <support/test-driver.h> > + > +static int > +do_test (void) > +{ > + size_t old_size = getpagesize (); > + char *old_addr = xmmap (NULL, old_size, PROT_READ | PROT_WRITE, > + MAP_PRIVATE | MAP_ANONYMOUS, -1); > + old_addr[0] = 1; > + old_addr[old_size - 1] = 2; > + > + /* Test MREMAP_MAYMOVE. */ > + size_t new_size = old_size + old_size; > + char *new_addr = mremap (old_addr, old_size, new_size, MREMAP_MAYMOVE); > + TEST_VERIFY_EXIT (new_addr != MAP_FAILED); > + new_addr[0] = 1; > + new_addr[new_size - 1] = 2; > + xmunmap (new_addr, new_size); > + > + return 0; > +} > + > +#include <support/test-driver.c> > diff --git a/misc/tst-mremap2.c b/misc/tst-mremap2.c > new file mode 100644 > index 0000000000..45be7f0369 > --- /dev/null > +++ b/misc/tst-mremap2.c > @@ -0,0 +1,54 @@ > +/* Test mremap with MREMAP_FIXED. > + Copyright (C) 2024 Free Software Foundation, Inc. > + This file is part of the GNU C Library. > + > + The GNU C Library is free software; you can redistribute it and/or > + modify it under the terms of the GNU Lesser General Public > + License as published by the Free Software Foundation; either > + version 2.1 of the License, or (at your option) any later version. > + > + The GNU C Library is distributed in the hope that it will be useful, > + but WITHOUT ANY WARRANTY; without even the implied warranty of > + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU > + Lesser General Public License for more details. > + > + You should have received a copy of the GNU Lesser General Public > + License along with the GNU C Library; if not, see > + <https://www.gnu.org/licenses/>. */ > + > +#include <errno.h> > +#include <sys/mman.h> > +#include <support/xstdlib.h> > +#include <support/xunistd.h> > +#include <support/test-driver.h> > +#include <mremap-failure.h> > + > +static int > +do_test (void) > +{ > + size_t old_size = getpagesize (); > + size_t new_size = old_size + old_size; > + char *old_addr = xmmap (NULL, old_size, PROT_READ | PROT_WRITE, > + MAP_PRIVATE | MAP_ANONYMOUS, -1); > + old_addr[0] = 1; > + old_addr[old_size - 1] = 2; > + > + char *fixed_addr = xmmap (NULL, new_size, PROT_READ | PROT_WRITE, > + MAP_PRIVATE | MAP_ANONYMOUS, -1); > + fixed_addr[0] = 1; > + fixed_addr[new_size - 1] = 2; > + > + /* Test MREMAP_FIXED. */ > + char *new_addr = mremap (old_addr, old_size, new_size, > + MREMAP_FIXED | MREMAP_MAYMOVE, > + fixed_addr); > + if (new_addr == MAP_FAILED) > + return mremap_failure_exit (errno); > + new_addr[0] = 1; > + new_addr[new_size - 1] = 2; > + xmunmap (new_addr, new_size); > + > + return 0; > +} > + > +#include <support/test-driver.c> > diff --git a/sysdeps/generic/mremap-failure.h b/sysdeps/generic/mremap-failure.h > new file mode 100644 > index 0000000000..bc0d476368 > --- /dev/null > +++ b/sysdeps/generic/mremap-failure.h > @@ -0,0 +1,25 @@ > +/* mremap failure handling. Generic version. > + Copyright (C) 2024 Free Software Foundation, Inc. > + This file is part of the GNU C Library. > + > + The GNU C Library is free software; you can redistribute it and/or > + modify it under the terms of the GNU Lesser General Public > + License as published by the Free Software Foundation; either > + version 2.1 of the License, or (at your option) any later version. > + > + The GNU C Library is distributed in the hope that it will be useful, > + but WITHOUT ANY WARRANTY; without even the implied warranty of > + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU > + Lesser General Public License for more details. > + > + You should have received a copy of the GNU Lesser General Public > + License along with the GNU C Library; if not, see > + <https://www.gnu.org/licenses/>. */ > + > +/* Return exit value on mremap failure with errno ERR. */ > + > +static int > +mremap_failure_exit (int err) > +{ > + return EXIT_FAILURE; > +} > diff --git a/sysdeps/unix/sysv/linux/Makefile b/sysdeps/unix/sysv/linux/Makefile > index 097b5a26fc..59998c7af4 100644 > --- a/sysdeps/unix/sysv/linux/Makefile > +++ b/sysdeps/unix/sysv/linux/Makefile > @@ -206,6 +206,7 @@ tests += \ > tst-getauxval \ > tst-gettid \ > tst-gettid-kill \ > + tst-linux-mremap1 \ > tst-memfd_create \ > tst-misalign-clone \ > tst-mlock2 \ > diff --git a/sysdeps/unix/sysv/linux/mremap-failure.h b/sysdeps/unix/sysv/linux/mremap-failure.h > new file mode 100644 > index 0000000000..c99ab30ca9 > --- /dev/null > +++ b/sysdeps/unix/sysv/linux/mremap-failure.h > @@ -0,0 +1,30 @@ > +/* mremap failure handling. Linux version. > + Copyright (C) 2024 Free Software Foundation, Inc. > + This file is part of the GNU C Library. > + > + The GNU C Library is free software; you can redistribute it and/or > + modify it under the terms of the GNU Lesser General Public > + License as published by the Free Software Foundation; either > + version 2.1 of the License, or (at your option) any later version. > + > + The GNU C Library is distributed in the hope that it will be useful, > + but WITHOUT ANY WARRANTY; without even the implied warranty of > + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU > + Lesser General Public License for more details. > + > + You should have received a copy of the GNU Lesser General Public > + License along with the GNU C Library; if not, see > + <https://www.gnu.org/licenses/>. */ > + > +#include <support/check.h> > + > +/* Return exit value on mremap failure with errno ERR. */ > + > +static int > +mremap_failure_exit (int err) > +{ > + if (err != EINVAL) > + return EXIT_FAILURE; > + > + return EXIT_UNSUPPORTED; > +} > diff --git a/sysdeps/unix/sysv/linux/tst-linux-mremap1.c b/sysdeps/unix/sysv/linux/tst-linux-mremap1.c > new file mode 100644 > index 0000000000..408e8af2ab > --- /dev/null > +++ b/sysdeps/unix/sysv/linux/tst-linux-mremap1.c > @@ -0,0 +1,63 @@ > +/* Test mremap with MREMAP_DONTUNMAP. > + Copyright (C) 2024 Free Software Foundation, Inc. > + This file is part of the GNU C Library. > + > + The GNU C Library is free software; you can redistribute it and/or > + modify it under the terms of the GNU Lesser General Public > + License as published by the Free Software Foundation; either > + version 2.1 of the License, or (at your option) any later version. > + > + The GNU C Library is distributed in the hope that it will be useful, > + but WITHOUT ANY WARRANTY; without even the implied warranty of > + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU > + Lesser General Public License for more details. > + > + You should have received a copy of the GNU Lesser General Public > + License along with the GNU C Library; if not, see > + <https://www.gnu.org/licenses/>. */ > + > +#include <errno.h> > +#include <sys/mman.h> > +#include <support/xstdlib.h> > +#include <support/xunistd.h> > +#include <support/check.h> > +#include <support/test-driver.h> > +#include <mremap-failure.h> > + > +static int > +do_test (void) > +{ > + size_t old_size = getpagesize (); > + size_t new_size = old_size; > + char *old_addr = xmmap (NULL, old_size, PROT_READ | PROT_WRITE, > + MAP_PRIVATE | MAP_ANONYMOUS, -1); > + old_addr[0] = 1; > + old_addr[old_size - 1] = 2; > + > + /* Create an available 64-page mmap region. */ > + size_t fixed_size = old_size * 64; > + char *fixed_addr = xmmap (NULL, fixed_size, PROT_READ | PROT_WRITE, > + MAP_PRIVATE | MAP_ANONYMOUS, -1); > + xmunmap (fixed_addr, fixed_size); > + > + /* Add 3 * pagesize. */ > + fixed_size += 3 * old_size; > + > + /* Test MREMAP_DONTUNMAP. It should return FIXED_ADDR created above. */ > + char *new_addr = mremap (old_addr, old_size, new_size, > + MREMAP_DONTUNMAP | MREMAP_MAYMOVE, > + fixed_addr); > + if (new_addr == MAP_FAILED) > + return mremap_failure_exit (errno); > + TEST_VERIFY_EXIT (fixed_addr == new_addr); > + old_addr[0] = 3; > + old_addr[old_size - 1] = 4; > + new_addr[0] = 1; > + new_addr[new_size - 1] = 2; > + xmunmap (new_addr, new_size); > + xmunmap (old_addr, old_size); > + > + return 0; > +} > + > +#include <support/test-driver.c>
diff --git a/misc/Makefile b/misc/Makefile index 5d17c562fe..7b7f8351bf 100644 --- a/misc/Makefile +++ b/misc/Makefile @@ -257,6 +257,8 @@ tests := \ tst-mntent-blank-passno \ tst-mntent-escape \ tst-mntent2 \ + tst-mremap1 \ + tst-mremap2 \ tst-preadvwritev \ tst-preadvwritev2 \ tst-preadvwritev64 \ diff --git a/misc/tst-mremap1.c b/misc/tst-mremap1.c new file mode 100644 index 0000000000..0469991a6c --- /dev/null +++ b/misc/tst-mremap1.c @@ -0,0 +1,46 @@ +/* Test mremap with MREMAP_MAYMOVE. + Copyright (C) 2024 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <https://www.gnu.org/licenses/>. */ + +#include <errno.h> +#include <sys/mman.h> +#include <support/xstdlib.h> +#include <support/xunistd.h> +#include <support/check.h> +#include <support/test-driver.h> + +static int +do_test (void) +{ + size_t old_size = getpagesize (); + char *old_addr = xmmap (NULL, old_size, PROT_READ | PROT_WRITE, + MAP_PRIVATE | MAP_ANONYMOUS, -1); + old_addr[0] = 1; + old_addr[old_size - 1] = 2; + + /* Test MREMAP_MAYMOVE. */ + size_t new_size = old_size + old_size; + char *new_addr = mremap (old_addr, old_size, new_size, MREMAP_MAYMOVE); + TEST_VERIFY_EXIT (new_addr != MAP_FAILED); + new_addr[0] = 1; + new_addr[new_size - 1] = 2; + xmunmap (new_addr, new_size); + + return 0; +} + +#include <support/test-driver.c> diff --git a/misc/tst-mremap2.c b/misc/tst-mremap2.c new file mode 100644 index 0000000000..45be7f0369 --- /dev/null +++ b/misc/tst-mremap2.c @@ -0,0 +1,54 @@ +/* Test mremap with MREMAP_FIXED. + Copyright (C) 2024 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <https://www.gnu.org/licenses/>. */ + +#include <errno.h> +#include <sys/mman.h> +#include <support/xstdlib.h> +#include <support/xunistd.h> +#include <support/test-driver.h> +#include <mremap-failure.h> + +static int +do_test (void) +{ + size_t old_size = getpagesize (); + size_t new_size = old_size + old_size; + char *old_addr = xmmap (NULL, old_size, PROT_READ | PROT_WRITE, + MAP_PRIVATE | MAP_ANONYMOUS, -1); + old_addr[0] = 1; + old_addr[old_size - 1] = 2; + + char *fixed_addr = xmmap (NULL, new_size, PROT_READ | PROT_WRITE, + MAP_PRIVATE | MAP_ANONYMOUS, -1); + fixed_addr[0] = 1; + fixed_addr[new_size - 1] = 2; + + /* Test MREMAP_FIXED. */ + char *new_addr = mremap (old_addr, old_size, new_size, + MREMAP_FIXED | MREMAP_MAYMOVE, + fixed_addr); + if (new_addr == MAP_FAILED) + return mremap_failure_exit (errno); + new_addr[0] = 1; + new_addr[new_size - 1] = 2; + xmunmap (new_addr, new_size); + + return 0; +} + +#include <support/test-driver.c> diff --git a/sysdeps/generic/mremap-failure.h b/sysdeps/generic/mremap-failure.h new file mode 100644 index 0000000000..bc0d476368 --- /dev/null +++ b/sysdeps/generic/mremap-failure.h @@ -0,0 +1,25 @@ +/* mremap failure handling. Generic version. + Copyright (C) 2024 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <https://www.gnu.org/licenses/>. */ + +/* Return exit value on mremap failure with errno ERR. */ + +static int +mremap_failure_exit (int err) +{ + return EXIT_FAILURE; +} diff --git a/sysdeps/unix/sysv/linux/Makefile b/sysdeps/unix/sysv/linux/Makefile index 097b5a26fc..59998c7af4 100644 --- a/sysdeps/unix/sysv/linux/Makefile +++ b/sysdeps/unix/sysv/linux/Makefile @@ -206,6 +206,7 @@ tests += \ tst-getauxval \ tst-gettid \ tst-gettid-kill \ + tst-linux-mremap1 \ tst-memfd_create \ tst-misalign-clone \ tst-mlock2 \ diff --git a/sysdeps/unix/sysv/linux/mremap-failure.h b/sysdeps/unix/sysv/linux/mremap-failure.h new file mode 100644 index 0000000000..c99ab30ca9 --- /dev/null +++ b/sysdeps/unix/sysv/linux/mremap-failure.h @@ -0,0 +1,30 @@ +/* mremap failure handling. Linux version. + Copyright (C) 2024 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <https://www.gnu.org/licenses/>. */ + +#include <support/check.h> + +/* Return exit value on mremap failure with errno ERR. */ + +static int +mremap_failure_exit (int err) +{ + if (err != EINVAL) + return EXIT_FAILURE; + + return EXIT_UNSUPPORTED; +} diff --git a/sysdeps/unix/sysv/linux/tst-linux-mremap1.c b/sysdeps/unix/sysv/linux/tst-linux-mremap1.c new file mode 100644 index 0000000000..408e8af2ab --- /dev/null +++ b/sysdeps/unix/sysv/linux/tst-linux-mremap1.c @@ -0,0 +1,63 @@ +/* Test mremap with MREMAP_DONTUNMAP. + Copyright (C) 2024 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <https://www.gnu.org/licenses/>. */ + +#include <errno.h> +#include <sys/mman.h> +#include <support/xstdlib.h> +#include <support/xunistd.h> +#include <support/check.h> +#include <support/test-driver.h> +#include <mremap-failure.h> + +static int +do_test (void) +{ + size_t old_size = getpagesize (); + size_t new_size = old_size; + char *old_addr = xmmap (NULL, old_size, PROT_READ | PROT_WRITE, + MAP_PRIVATE | MAP_ANONYMOUS, -1); + old_addr[0] = 1; + old_addr[old_size - 1] = 2; + + /* Create an available 64-page mmap region. */ + size_t fixed_size = old_size * 64; + char *fixed_addr = xmmap (NULL, fixed_size, PROT_READ | PROT_WRITE, + MAP_PRIVATE | MAP_ANONYMOUS, -1); + xmunmap (fixed_addr, fixed_size); + + /* Add 3 * pagesize. */ + fixed_size += 3 * old_size; + + /* Test MREMAP_DONTUNMAP. It should return FIXED_ADDR created above. */ + char *new_addr = mremap (old_addr, old_size, new_size, + MREMAP_DONTUNMAP | MREMAP_MAYMOVE, + fixed_addr); + if (new_addr == MAP_FAILED) + return mremap_failure_exit (errno); + TEST_VERIFY_EXIT (fixed_addr == new_addr); + old_addr[0] = 3; + old_addr[old_size - 1] = 4; + new_addr[0] = 1; + new_addr[new_size - 1] = 2; + xmunmap (new_addr, new_size); + xmunmap (old_addr, old_size); + + return 0; +} + +#include <support/test-driver.c>
Add tests for MREMAP_MAYMOVE and MREMAP_FIXED. On Linux, also test MREMAP_DONTUNMAP. Signed-off-by: H.J. Lu <hjl.tools@gmail.com> --- misc/Makefile | 2 + misc/tst-mremap1.c | 46 +++++++++++++++ misc/tst-mremap2.c | 54 ++++++++++++++++++ sysdeps/generic/mremap-failure.h | 25 ++++++++ sysdeps/unix/sysv/linux/Makefile | 1 + sysdeps/unix/sysv/linux/mremap-failure.h | 30 ++++++++++ sysdeps/unix/sysv/linux/tst-linux-mremap1.c | 63 +++++++++++++++++++++ 7 files changed, 221 insertions(+) create mode 100644 misc/tst-mremap1.c create mode 100644 misc/tst-mremap2.c create mode 100644 sysdeps/generic/mremap-failure.h create mode 100644 sysdeps/unix/sysv/linux/mremap-failure.h create mode 100644 sysdeps/unix/sysv/linux/tst-linux-mremap1.c