1f08c3bdfSopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 2f08c3bdfSopenharmony_ci/* 3f08c3bdfSopenharmony_ci * Copyright (c) Zilogic Systems Pvt. Ltd., 2018 4f08c3bdfSopenharmony_ci * Email : code@zilogic.com 5f08c3bdfSopenharmony_ci */ 6f08c3bdfSopenharmony_ci 7f08c3bdfSopenharmony_ci/* 8f08c3bdfSopenharmony_ci * test cases for madvise(2) system call, advise value as "MADV_WIPEONFORK". 9f08c3bdfSopenharmony_ci * 10f08c3bdfSopenharmony_ci * DESCRIPTION 11f08c3bdfSopenharmony_ci * Present the child process with zero-filled memory in this 12f08c3bdfSopenharmony_ci * range after a fork(2). 13f08c3bdfSopenharmony_ci * The MADV_WIPEONFORK operation can be applied only to 14f08c3bdfSopenharmony_ci * private anonymous pages. 15f08c3bdfSopenharmony_ci * Within the child created by fork(2), the MADV_WIPEONFORK 16f08c3bdfSopenharmony_ci * setting remains in place on the specified map_address range. 17f08c3bdfSopenharmony_ci * The MADV_KEEPONFORK operation undo the effect of MADV_WIPEONFORK. 18f08c3bdfSopenharmony_ci * 19f08c3bdfSopenharmony_ci * Test-Case 1 : madvise with "MADV_WIPEONFORK" 20f08c3bdfSopenharmony_ci * flow : Map memory area as private anonymous page. 21f08c3bdfSopenharmony_ci * Mark memory area as wipe-on-fork. 22f08c3bdfSopenharmony_ci * On fork, child process memory should be zeroed. 23f08c3bdfSopenharmony_ci * 24f08c3bdfSopenharmony_ci * Test-Case 2 : madvise with "MADV_WIPEONFORK" and "ZERO" length 25f08c3bdfSopenharmony_ci * flow : Map memory area as private anonymous page. 26f08c3bdfSopenharmony_ci * Mark memory area as wipe-on-fork, with length zero. 27f08c3bdfSopenharmony_ci * On fork, child process memory should be accessible. 28f08c3bdfSopenharmony_ci * 29f08c3bdfSopenharmony_ci * Test-Case 3 : "MADV_WIPEONFORK" on Grand child 30f08c3bdfSopenharmony_ci * flow : Map memory area as private anonymous. 31f08c3bdfSopenharmony_ci * Mark memory areas as wipe-on-fork. 32f08c3bdfSopenharmony_ci * On fork, child process memory should be zeroed. 33f08c3bdfSopenharmony_ci * In child, fork to create grand-child, 34f08c3bdfSopenharmony_ci * memory should be zeroed. 35f08c3bdfSopenharmony_ci * 36f08c3bdfSopenharmony_ci * Test-Case 4 : Undo "MADV_WIPEONFORK" by "MADV_KEEPONFORK" 37f08c3bdfSopenharmony_ci * flow : Map memory area as private anonymous page. 38f08c3bdfSopenharmony_ci * Mark memory area as wipe-on-fork. 39f08c3bdfSopenharmony_ci * Mark memory area as keep-on-fork. 40f08c3bdfSopenharmony_ci * On fork, child process memory should be retained. 41f08c3bdfSopenharmony_ci **/ 42f08c3bdfSopenharmony_ci 43f08c3bdfSopenharmony_ci#include <stdio.h> 44f08c3bdfSopenharmony_ci#include <errno.h> 45f08c3bdfSopenharmony_ci#include <unistd.h> 46f08c3bdfSopenharmony_ci#include <stdlib.h> 47f08c3bdfSopenharmony_ci 48f08c3bdfSopenharmony_ci#include "lapi/mmap.h" 49f08c3bdfSopenharmony_ci#include "tst_test.h" 50f08c3bdfSopenharmony_ci#include "tst_safe_macros.h" 51f08c3bdfSopenharmony_ci 52f08c3bdfSopenharmony_ci#define MAP_SIZE (16 * 1024) 53f08c3bdfSopenharmony_ci 54f08c3bdfSopenharmony_cistatic char pattern[MAP_SIZE]; 55f08c3bdfSopenharmony_cistatic char zero[MAP_SIZE]; 56f08c3bdfSopenharmony_ci 57f08c3bdfSopenharmony_cistatic const struct test_case { 58f08c3bdfSopenharmony_ci int size; 59f08c3bdfSopenharmony_ci int advise1; 60f08c3bdfSopenharmony_ci int advise2; 61f08c3bdfSopenharmony_ci char *exp; 62f08c3bdfSopenharmony_ci int grand_child; 63f08c3bdfSopenharmony_ci const char *desc; 64f08c3bdfSopenharmony_ci} tcases[] = { 65f08c3bdfSopenharmony_ci {MAP_SIZE, MADV_NORMAL, MADV_WIPEONFORK, zero, 0, 66f08c3bdfSopenharmony_ci "MADV_WIPEONFORK zeroes memory in child"}, 67f08c3bdfSopenharmony_ci {0, MADV_NORMAL, MADV_WIPEONFORK, pattern, 0, 68f08c3bdfSopenharmony_ci "MADV_WIPEONFORK with zero length does nothing"}, 69f08c3bdfSopenharmony_ci {MAP_SIZE, MADV_NORMAL, MADV_WIPEONFORK, zero, 1, 70f08c3bdfSopenharmony_ci "MADV_WIPEONFORK zeroes memory in grand-child"}, 71f08c3bdfSopenharmony_ci {MAP_SIZE, MADV_WIPEONFORK, MADV_KEEPONFORK, pattern, 0, 72f08c3bdfSopenharmony_ci "MADV_KEEPONFORK will undo MADV_WIPEONFORK"}, 73f08c3bdfSopenharmony_ci}; 74f08c3bdfSopenharmony_ci 75f08c3bdfSopenharmony_cistatic void cmp_area(char *addr, const struct test_case *tc) 76f08c3bdfSopenharmony_ci{ 77f08c3bdfSopenharmony_ci int i; 78f08c3bdfSopenharmony_ci 79f08c3bdfSopenharmony_ci for (i = 0; i < tc->size; i++) { 80f08c3bdfSopenharmony_ci if (addr[i] != tc->exp[i]) { 81f08c3bdfSopenharmony_ci tst_res(TFAIL, "In PID %d, addr[%d] = 0x%02x, " 82f08c3bdfSopenharmony_ci "expected[%d] = 0x%02x", getpid(), 83f08c3bdfSopenharmony_ci i, addr[i], i, tc->exp[i]); 84f08c3bdfSopenharmony_ci break; 85f08c3bdfSopenharmony_ci } 86f08c3bdfSopenharmony_ci } 87f08c3bdfSopenharmony_ci 88f08c3bdfSopenharmony_ci tst_res(TPASS, "In PID %d, Matched expected pattern", getpid()); 89f08c3bdfSopenharmony_ci} 90f08c3bdfSopenharmony_ci 91f08c3bdfSopenharmony_cistatic int set_advice(char *addr, int size, int advise) 92f08c3bdfSopenharmony_ci{ 93f08c3bdfSopenharmony_ci TEST(madvise(addr, size, advise)); 94f08c3bdfSopenharmony_ci 95f08c3bdfSopenharmony_ci if (TST_RET == -1) { 96f08c3bdfSopenharmony_ci if (TST_ERR == EINVAL) { 97f08c3bdfSopenharmony_ci tst_res(TCONF, "madvise(%p, %d, 0x%x) is not supported", 98f08c3bdfSopenharmony_ci addr, size, advise); 99f08c3bdfSopenharmony_ci } else { 100f08c3bdfSopenharmony_ci tst_res(TFAIL | TTERRNO, "madvise(%p, %d, 0x%x)", 101f08c3bdfSopenharmony_ci addr, size, advise); 102f08c3bdfSopenharmony_ci } 103f08c3bdfSopenharmony_ci 104f08c3bdfSopenharmony_ci return 1; 105f08c3bdfSopenharmony_ci } 106f08c3bdfSopenharmony_ci 107f08c3bdfSopenharmony_ci tst_res(TPASS, "madvise(%p, %d, 0x%x)", addr, size, advise); 108f08c3bdfSopenharmony_ci return 0; 109f08c3bdfSopenharmony_ci} 110f08c3bdfSopenharmony_ci 111f08c3bdfSopenharmony_cistatic char *mem_map(void) 112f08c3bdfSopenharmony_ci{ 113f08c3bdfSopenharmony_ci char *ptr; 114f08c3bdfSopenharmony_ci 115f08c3bdfSopenharmony_ci ptr = SAFE_MMAP(NULL, MAP_SIZE, 116f08c3bdfSopenharmony_ci PROT_READ | PROT_WRITE, 117f08c3bdfSopenharmony_ci MAP_PRIVATE | MAP_ANONYMOUS, 118f08c3bdfSopenharmony_ci -1, 0); 119f08c3bdfSopenharmony_ci 120f08c3bdfSopenharmony_ci memcpy(ptr, pattern, MAP_SIZE); 121f08c3bdfSopenharmony_ci 122f08c3bdfSopenharmony_ci return ptr; 123f08c3bdfSopenharmony_ci} 124f08c3bdfSopenharmony_ci 125f08c3bdfSopenharmony_cistatic void test_madvise(unsigned int test_nr) 126f08c3bdfSopenharmony_ci{ 127f08c3bdfSopenharmony_ci const struct test_case *tc = &tcases[test_nr]; 128f08c3bdfSopenharmony_ci char *addr; 129f08c3bdfSopenharmony_ci pid_t pid; 130f08c3bdfSopenharmony_ci 131f08c3bdfSopenharmony_ci addr = mem_map(); 132f08c3bdfSopenharmony_ci 133f08c3bdfSopenharmony_ci tst_res(TINFO, "%s", tc->desc); 134f08c3bdfSopenharmony_ci if (set_advice(addr, tc->size, tc->advise1)) 135f08c3bdfSopenharmony_ci goto un_map; 136f08c3bdfSopenharmony_ci 137f08c3bdfSopenharmony_ci if (!set_advice(addr, tc->size, tc->advise2)) { 138f08c3bdfSopenharmony_ci pid = SAFE_FORK(); 139f08c3bdfSopenharmony_ci 140f08c3bdfSopenharmony_ci if (!pid) { 141f08c3bdfSopenharmony_ci if (tc->grand_child) { 142f08c3bdfSopenharmony_ci pid = SAFE_FORK(); 143f08c3bdfSopenharmony_ci 144f08c3bdfSopenharmony_ci if (!pid) { 145f08c3bdfSopenharmony_ci cmp_area(addr, tc); 146f08c3bdfSopenharmony_ci exit(0); 147f08c3bdfSopenharmony_ci } 148f08c3bdfSopenharmony_ci } else { 149f08c3bdfSopenharmony_ci cmp_area(addr, tc); 150f08c3bdfSopenharmony_ci exit(0); 151f08c3bdfSopenharmony_ci } 152f08c3bdfSopenharmony_ci } 153f08c3bdfSopenharmony_ci tst_reap_children(); 154f08c3bdfSopenharmony_ci } 155f08c3bdfSopenharmony_ci 156f08c3bdfSopenharmony_ciun_map: 157f08c3bdfSopenharmony_ci SAFE_MUNMAP(addr, MAP_SIZE); 158f08c3bdfSopenharmony_ci} 159f08c3bdfSopenharmony_ci 160f08c3bdfSopenharmony_cistatic void setup(void) 161f08c3bdfSopenharmony_ci{ 162f08c3bdfSopenharmony_ci unsigned int i; 163f08c3bdfSopenharmony_ci 164f08c3bdfSopenharmony_ci for (i = 0; i < MAP_SIZE; i++) 165f08c3bdfSopenharmony_ci pattern[i] = i % 0x03; 166f08c3bdfSopenharmony_ci} 167f08c3bdfSopenharmony_ci 168f08c3bdfSopenharmony_cistatic struct tst_test test = { 169f08c3bdfSopenharmony_ci .tcnt = ARRAY_SIZE(tcases), 170f08c3bdfSopenharmony_ci .forks_child = 1, 171f08c3bdfSopenharmony_ci .test = test_madvise, 172f08c3bdfSopenharmony_ci .setup = setup, 173f08c3bdfSopenharmony_ci}; 174