[LTP] [PATCH v1] Test madvise with advise value 'MADV_WIPEONFORK'
kewal
kewal@zilogic.com
Wed Jul 11 17:59:52 CEST 2018
* madvise10.c :- Present the child process with zero-filled memory in
this range after a fork(2).
Test-Case 1 : madvise with 'MADV_WIPEONFORK'
Test-Case 2 : madvise with 'MADV_WIPEONFORK' as size 'ZERO'
* madvise11.c:- The MADV_WIPEONFORK operation can be applied only to
private anonymous pages.
Test-Case 1 : mmap with 'MAP_SHARED | MAP_ANONYMOUS'
Test-Case 2 : mmap with 'MAP_PRIVATE'
* madvise12.c:- Within the child created by fork(2), the MADV_WIPEONFORK
setting remains in place on the specified address range.
Test-Case 1: 'MADV_WIPEONFORK' on Grand child
* madvise13.c:- MADV_KEEPONFORK Undo the effect of an earlier MADV_WIPEONFORK
Test-Case 1 : Undo 'MADV_WIPEONFORK' by 'MADV_KEEPONFORK'
Signed-off-by: Subash Ganesan <subash@zilogic.com>
Signed-off-by: Kewal Ukunde <kewal@zilogic.com>
---
runtest/syscalls | 4 +
testcases/kernel/syscalls/madvise/madvise10.c | 179 ++++++++++++++++++++++++++
testcases/kernel/syscalls/madvise/madvise11.c | 132 +++++++++++++++++++
testcases/kernel/syscalls/madvise/madvise12.c | 171 ++++++++++++++++++++++++
testcases/kernel/syscalls/madvise/madvise13.c | 162 +++++++++++++++++++++++
5 files changed, 648 insertions(+)
create mode 100644 testcases/kernel/syscalls/madvise/madvise10.c
create mode 100644 testcases/kernel/syscalls/madvise/madvise11.c
create mode 100644 testcases/kernel/syscalls/madvise/madvise12.c
create mode 100644 testcases/kernel/syscalls/madvise/madvise13.c
diff --git a/runtest/syscalls b/runtest/syscalls
index a9afecf57..a95c47c3a 100644
--- a/runtest/syscalls
+++ b/runtest/syscalls
@@ -773,6 +773,10 @@ madvise06 madvise06
madvise07 madvise07
madvise08 madvise08
madvise09 madvise09
+madvise10 madvise10
+madvise11 madvise11
+madvise12 madvise12
+madvise13 madvise13
newuname01 newuname01
diff --git a/testcases/kernel/syscalls/madvise/madvise10.c b/testcases/kernel/syscalls/madvise/madvise10.c
new file mode 100644
index 000000000..1cf3097b0
--- /dev/null
+++ b/testcases/kernel/syscalls/madvise/madvise10.c
@@ -0,0 +1,179 @@
+// SPDX-License-Identifier: GPL-2.0 or later
+/*
+ * Copyright (c) Zilogic Systems Pvt. Ltd., 2007
+ * Email : code@zilogic.com
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ */
+
+/*
+ * test cases for madvise(2) system call, advise value as "MADV_WIPEONFORK".
+ *
+ * DESCRIPTION :
+ * Present the child process with zero-filled memory in this
+ * range after a fork(2).
+ * The MADV_WIPEONFORK operation can be applied only to
+ * private anonymous pages.
+ *
+ * Test-Case 1 : madvise with "MADV_WIPEONFORK"
+ * flow : Map memory area as private anonymous page.
+ * Mark memory area as wipe-on-fork.
+ * On fork, child process memory should be zeroed.
+ *
+ * Test-Case 2 : madvise with "MADV_WIPEONFORK" as size "ZERO"
+ * flow : Map memory area as private anonymous page.
+ * Mark memory area as wipe-on-fork, with length zero.
+ * On fork, child process memory should be accessible.
+ **/
+
+#include <stdio.h>
+#include <signal.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <sys/mman.h>
+#include <error.h>
+#include <string.h>
+#include <errno.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <stdlib.h>
+
+#include "lapi/mmap.h"
+#include "tst_test.h"
+#include "tst_safe_macros.h"
+
+#define TEST_FILE "test_file.txt"
+#define MAP_SIZE (4 * 1024)
+
+static int test_file_fd;
+
+static const struct test_case {
+ int size;
+ int advise;
+ char *advise_name;
+ int expect;
+} tcases[] = {
+ {.size = MAP_SIZE,
+ .advise = MADV_WIPEONFORK,
+ .advise_name = "MADV_WIPEONFORK",
+ .expect = 0},
+
+ {.size = 0,
+ .advise = MADV_WIPEONFORK,
+ .advise_name = "MADV_WIPEONFORK",
+ .expect = 1}
+};
+
+static void assert_equal(int status, const struct test_case *tc)
+{
+ if (status == tc->expect)
+ tst_res(TPASS, "In child data %d : madvise(%s)",
+ tc->expect, tc->advise_name);
+ else
+ tst_res(TFAIL, "In child data %d : madvise(%s)",
+ tc->expect, tc->advise_name);
+}
+
+static void safe_wait_status(int *status)
+{
+ SAFE_WAIT(status);
+
+ if (!WIFEXITED(*status)) {
+ if (WTERMSIG(*status) == SIGSEGV)
+ tst_res(TFAIL, "Invalid access : SIGSEGV");
+ else
+ tst_res(TFAIL, "Abnormal termination");
+ } else {
+ *status = WEXITSTATUS(*status);
+ }
+}
+
+static void spawn_child(char *map_addr)
+{
+ pid_t pid;
+
+ pid = SAFE_FORK();
+
+ if (!pid)
+ exit(*map_addr);
+}
+
+static int set_advice(char *map_addr, const struct test_case *tc)
+{
+ TEST(madvise(map_addr, tc->size, tc->advise));
+
+ if (TEST_RETURN == -1) {
+ tst_res(TINFO, "failed :madvise(%p, %d, %s)",
+ map_addr, tc->size, tc->advise_name);
+ return 1;
+ }
+
+ tst_res(TINFO, "success :madvise(%p, %d, %s)",
+ map_addr, tc->size, tc->advise_name);
+
+ return 0;
+}
+
+static void mem_map(char **map_addr)
+{
+ *map_addr = SAFE_MMAP(NULL, MAP_SIZE,
+ PROT_READ | PROT_WRITE,
+ MAP_PRIVATE | MAP_ANON,
+ test_file_fd, 0);
+
+ tst_res(TINFO, "mmap(NULL, %d, PROT_READ | PROT_WRITE, %s, %d, 0)",
+ MAP_SIZE, "MAP_PRIVATE | MAP_ANON", test_file_fd);
+}
+
+static void test_madvise(unsigned int test_nr)
+{
+ const struct test_case *tc = &tcases[test_nr];
+ char *map_addr;
+ int status;
+
+ mem_map(&map_addr);
+ memset(map_addr, 1, MAP_SIZE);
+
+ if (set_advice(map_addr, tc)) {
+ tst_res(TFAIL, "madvise failed");
+ } else {
+ spawn_child(map_addr);
+ safe_wait_status(&status);
+ assert_equal(status, tc);
+ }
+
+ SAFE_MUNMAP(map_addr, MAP_SIZE);
+}
+
+static void cleanup(void)
+{
+ SAFE_CLOSE(test_file_fd);
+ SAFE_UNLINK(TEST_FILE);
+}
+
+static void setup(void)
+{
+ test_file_fd = SAFE_OPEN(TEST_FILE, O_RDWR | O_CREAT, 0777);
+}
+
+static struct tst_test test = {
+ .tcnt = ARRAY_SIZE(tcases),
+ .needs_root = 1,
+ .forks_child = 1,
+ .needs_tmpdir = 1,
+ .test = test_madvise,
+ .setup = setup,
+ .cleanup = cleanup,
+ .min_kver = "4.14",
+};
diff --git a/testcases/kernel/syscalls/madvise/madvise11.c b/testcases/kernel/syscalls/madvise/madvise11.c
new file mode 100644
index 000000000..aee277dbd
--- /dev/null
+++ b/testcases/kernel/syscalls/madvise/madvise11.c
@@ -0,0 +1,132 @@
+// SPDX-License-Identifier: GPL-2.0 or later
+/*
+ * Copyright (c) Zilogic Systems Pvt. Ltd., 2007
+ * Email : code@zilogic.com
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ */
+
+/*
+ * test cases for madvise(2) system call, advise value as "MADV_WIPEONFORK".
+ *
+ * DESCRIPTION :
+ * Present the child process with zero-filled memory in this
+ * range after a fork(2).
+ * The MADV_WIPEONFORK operation can be applied only to
+ * private anonymous pages.
+ *
+ * Test-Case 1 : mmap with "MAP_SHARED | MAP_ANONYMOUS"
+ * flow : Map memory area as shared anonymous page.
+ * Mark memory area as wipe-on-fork, should fail.
+ *
+ * Test-Case 2 : mmap with "MAP_PRIVATE"
+ * flow : Map memory area as private file-backed.
+ * Mark memory area as wipe-on-fork, should fail.
+ **/
+
+#include <stdio.h>
+#include <signal.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <sys/mman.h>
+#include <error.h>
+#include <string.h>
+#include <errno.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <stdlib.h>
+
+#include "lapi/mmap.h"
+#include "tst_test.h"
+#include "tst_safe_macros.h"
+
+#define TEST_FILE "test_file.txt"
+#define MAP_SIZE (4 * 1024)
+#define ADVISE "MADV_WIPEONFORK"
+
+static int test_file_fd;
+
+static const struct test_case {
+ int flag;
+ char *flag_name;
+} tcases[] = {
+ {.flag = MAP_SHARED | MAP_ANON,
+ .flag_name = "MAP_SHARED | MAP_ANON"},
+
+ {.flag = MAP_PRIVATE,
+ .flag_name = "MAP_PRIVATE"}
+};
+
+static int set_advice(char *map_addr)
+{
+ TEST(madvise(map_addr, MAP_SIZE, MADV_WIPEONFORK));
+
+ if (TEST_RETURN == -1) {
+ tst_res(TINFO, "failed :madvise(%p, MAP_SIZE, %s)",
+ map_addr, ADVISE);
+ return 1;
+ }
+
+ tst_res(TINFO, "success :madvise(%p, MAP_SIZE, %s)",
+ map_addr, ADVISE);
+
+ return 0;
+}
+
+static void mem_map(char **map_addr, const struct test_case *tc)
+{
+ *map_addr = SAFE_MMAP(NULL, MAP_SIZE,
+ PROT_READ | PROT_WRITE,
+ tc->flag,
+ test_file_fd, 0);
+
+ tst_res(TINFO, "mmap(NULL, %d, PROT_READ | PROT_WRITE, %s, %d, 0)",
+ MAP_SIZE, tc->flag_name, test_file_fd);
+}
+
+static void test_madvise(unsigned int test_nr)
+{
+ const struct test_case *tc = &tcases[test_nr];
+ char *map_addr;
+
+ mem_map(&map_addr, tc);
+
+ if (set_advice(map_addr))
+ tst_res(TPASS, "madvise failed");
+ else
+ tst_res(TFAIL, "madvise success");
+
+ SAFE_MUNMAP(map_addr, MAP_SIZE);
+}
+
+static void cleanup(void)
+{
+ SAFE_CLOSE(test_file_fd);
+ SAFE_UNLINK(TEST_FILE);
+}
+
+static void setup(void)
+{
+ test_file_fd = SAFE_OPEN(TEST_FILE, O_RDWR | O_CREAT, 0777);
+}
+
+static struct tst_test test = {
+ .tcnt = ARRAY_SIZE(tcases),
+ .needs_root = 1,
+ .forks_child = 1,
+ .test = test_madvise,
+ .setup = setup,
+ .cleanup = cleanup,
+ .min_kver = "4.14",
+};
+
diff --git a/testcases/kernel/syscalls/madvise/madvise12.c b/testcases/kernel/syscalls/madvise/madvise12.c
new file mode 100644
index 000000000..7e6283d13
--- /dev/null
+++ b/testcases/kernel/syscalls/madvise/madvise12.c
@@ -0,0 +1,171 @@
+// SPDX-License-Identifier: GPL-2.0 or later
+/*
+ * Copyright (c) Zilogic Systems Pvt. Ltd., 2007
+ * Email : code@zilogic.com
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ */
+
+/*
+ * test cases for madvise(2) system call, advise value as "MADV_WIPEONFORK".
+ *
+ * DESCRIPTION :
+ * Present the child process with zero-filled memory in this
+ * range after a fork(2).
+ * The MADV_WIPEONFORK operation can be applied only to
+ * private anonymous pages.
+ * Within the child created by fork(2), the MADV_WIPEONFORK
+ * setting remains in place on the specified map_address range.
+ *
+ * Test-Case 1 : "MADV_WIPEONFORK" on Grand child
+ * flow : Map memory area as private anonymous.
+ * Mark memory areas as wipe-on-fork.
+ * On fork, child process memory should be zeroed.
+ * In child, fork to create grand-child,
+ * memory should be zeroed.
+ **/
+
+#include <stdio.h>
+#include <signal.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <sys/mman.h>
+#include <error.h>
+#include <string.h>
+#include <errno.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <stdlib.h>
+
+#include "lapi/mmap.h"
+#include "tst_test.h"
+#include "tst_safe_macros.h"
+
+#define TEST_FILE "test_file.txt"
+#define MAP_SIZE (4 * 1024)
+#define EXP_VAL 0
+
+static int test_file_fd;
+
+static void assert_equal(int status)
+{
+ if (status == EXP_VAL)
+ tst_res(TPASS, "In child data %d : madvise(%s)",
+ EXP_VAL, "MADV_WIPEONFORK");
+ else
+ tst_res(TFAIL, "In child data %d : madvise(%s)",
+ EXP_VAL, "MADV_WIPEONFORK");
+}
+
+static void safe_wait_status(int *status)
+{
+ SAFE_WAIT(status);
+
+ if (!WIFEXITED(*status)) {
+ if (WTERMSIG(*status) == SIGSEGV)
+ tst_res(TFAIL, "Invalid access : SIGSEGV");
+ else
+ tst_res(TFAIL, "Abnormal termination");
+ }
+}
+
+static void spawn_grand_child(char *map_addr)
+{
+ pid_t pid;
+
+ pid = SAFE_FORK();
+
+ if (!pid)
+ exit(*map_addr);
+}
+
+static void spawn_child(char *map_addr)
+{
+ pid_t pid;
+ int status;
+
+ pid = SAFE_FORK();
+
+ if (!pid) {
+ spawn_grand_child(map_addr);
+ safe_wait_status(&status);
+ exit(status);
+ }
+}
+
+static int set_advice(char *map_addr)
+{
+ TEST(madvise(map_addr, MAP_SIZE, MADV_WIPEONFORK));
+
+ if (TEST_RETURN == -1) {
+ tst_res(TINFO, "failed :madvise(%p, %d, %s)",
+ map_addr, MAP_SIZE, "MADV_WIPEONFORK");
+ return 1;
+ }
+
+ tst_res(TINFO, "success :madvise(%p, %d, %s)",
+ map_addr, MAP_SIZE, "MADV_WIPEONFORK");
+
+ return 0;
+}
+
+static void mem_map(char **map_addr)
+{
+ *map_addr = SAFE_MMAP(NULL, MAP_SIZE,
+ PROT_READ | PROT_WRITE,
+ MAP_PRIVATE | MAP_ANON,
+ test_file_fd, 0);
+
+ tst_res(TINFO, "mmap(NULL, %d, PROT_READ | PROT_WRITE, %s, %d, 0)",
+ MAP_SIZE, "MAP_PRIVATE | MAP_ANON", test_file_fd);
+}
+
+static void test_madvise(void)
+{
+ int status;
+ char *map_addr;
+
+ mem_map(&map_addr);
+ memset(map_addr, 1, MAP_SIZE);
+
+ if (set_advice(map_addr)) {
+ tst_res(TFAIL, "madvise failed");
+ } else {
+ spawn_child(map_addr);
+ safe_wait_status(&status);
+ assert_equal(status);
+ }
+
+ SAFE_MUNMAP(map_addr, MAP_SIZE);
+}
+
+static void cleanup(void)
+{
+ SAFE_CLOSE(test_file_fd);
+ SAFE_UNLINK(TEST_FILE);
+}
+
+static void setup(void)
+{
+ test_file_fd = SAFE_OPEN(TEST_FILE, O_RDWR | O_CREAT, 0777);
+}
+
+static struct tst_test test = {
+ .needs_root = 1,
+ .forks_child = 1,
+ .needs_tmpdir = 1,
+ .test_all = test_madvise,
+ .setup = setup,
+ .cleanup = cleanup,
+ .min_kver = "4.14",
+};
diff --git a/testcases/kernel/syscalls/madvise/madvise13.c b/testcases/kernel/syscalls/madvise/madvise13.c
new file mode 100644
index 000000000..cc4433380
--- /dev/null
+++ b/testcases/kernel/syscalls/madvise/madvise13.c
@@ -0,0 +1,162 @@
+// SPDX-License-Identifier: GPL-2.0 or later
+/*
+ * Copyright (c) Zilogic Systems Pvt. Ltd., 2007
+ * Email : code@zilogic.com
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ */
+
+/*
+ * test cases for madvise(2) system call, advise value as "MADV_WIPEONFORK".
+ *
+ * DESCRIPTION :
+ * Present the child process with zero-filled memory in this
+ * range after a fork(2).
+ * The MADV_KEEPONFORK operation undo the effect of MADV_WIPEONFORK.
+ *
+ * Test-Case 1 : Undo "MADV_WIPEONFORK" by "MADV_KEEPONFORK"
+ * flow : Map memory area as private anonymous page.
+ * Mark memory area as wipe-on-fork.
+ * Mark memory area as keep-on-fork.
+ * On fork, child process memory should be retained.
+ **/
+
+#include <stdio.h>
+#include <signal.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <sys/mman.h>
+#include <error.h>
+#include <string.h>
+#include <errno.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <stdlib.h>
+
+#include "lapi/mmap.h"
+#include "tst_test.h"
+#include "tst_safe_macros.h"
+
+#define EXP_VAL 1
+#define TEST_FILE "test_file.txt"
+#define MAP_SIZE (4 * 1024)
+
+static char *map_addr;
+static int test_file_fd;
+
+static void assert_equal(int status)
+{
+ if (status == EXP_VAL)
+ tst_res(TPASS, "In child data %d : madvise(%s)",
+ EXP_VAL, "MADV_KEEPONFORK");
+ else
+ tst_res(TFAIL, "In child data %d : madvise(%s)",
+ EXP_VAL, "MADV_KEEPONFORK");
+}
+
+static void safe_wait_status(int *status)
+{
+ SAFE_WAIT(status);
+
+ if (!WIFEXITED(*status)) {
+ if (WTERMSIG(*status) == SIGSEGV)
+ tst_res(TFAIL, "Invalid access : SIGSEGV");
+ else
+ tst_res(TFAIL, "Abnormal termination");
+ } else {
+ *status = WEXITSTATUS(*status);
+ }
+}
+
+static void spawn_child(char *map_addr)
+{
+ pid_t pid;
+
+ pid = SAFE_FORK();
+
+ if (!pid)
+ exit(*map_addr);
+}
+
+static int set_advice(int size, int advise, char *adv_name)
+{
+ TEST(madvise(map_addr, size, advise));
+
+ if (TEST_RETURN == -1) {
+ tst_res(TINFO, "failed :madvise(%p, %d, %s)",
+ map_addr, size, adv_name);
+ return 1;
+ }
+
+ tst_res(TINFO, "success :madvise(%p, %d, %s)",
+ map_addr, size, adv_name);
+
+ return 0;
+}
+
+static void test_madvise(void)
+{
+ int status;
+
+ if (set_advice(MAP_SIZE, MADV_WIPEONFORK,
+ "MADV_WIPEONFORK")) {
+ tst_res(TFAIL, "madvise failed");
+ return;
+ }
+
+ if (set_advice(MAP_SIZE, MADV_KEEPONFORK,
+ "MADV_KEEPONFORK")) {
+ tst_res(TFAIL, "madvise failed");
+ return;
+ }
+
+ spawn_child(map_addr);
+ safe_wait_status(&status);
+ assert_equal(status);
+}
+
+static void cleanup(void)
+{
+ SAFE_MUNMAP(map_addr, MAP_SIZE);
+ SAFE_CLOSE(test_file_fd);
+ SAFE_UNLINK(TEST_FILE);
+}
+
+static void mem_map(char **map_addr)
+{
+ *map_addr = SAFE_MMAP(NULL, MAP_SIZE,
+ PROT_READ | PROT_WRITE,
+ MAP_PRIVATE | MAP_ANON,
+ test_file_fd, 0);
+
+ tst_res(TINFO, "mmap(NULL, %d, PROT_READ | PROT_WRITE, %s, %d, 0)",
+ MAP_SIZE, "MAP_PRIVATE | MAP_ANON", test_file_fd);
+}
+
+static void setup(void)
+{
+ mem_map(&map_addr);
+ memset(map_addr, 1, MAP_SIZE);
+ test_file_fd = SAFE_OPEN(TEST_FILE, O_RDWR | O_CREAT, 0777);
+}
+
+static struct tst_test test = {
+ .needs_root = 1,
+ .forks_child = 1,
+ .needs_tmpdir = 1,
+ .test_all = test_madvise,
+ .setup = setup,
+ .cleanup = cleanup,
+ .min_kver = "4.14",
+};
--
2.11.0
More information about the ltp
mailing list