^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * It tests the mlock/mlock2() when they are invoked
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) * on randomly memory region.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) #include <unistd.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) #include <sys/resource.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) #include <sys/capability.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #include <sys/mman.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <fcntl.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <string.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <sys/ipc.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <sys/shm.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <time.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include "mlock2.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #define CHUNK_UNIT (128 * 1024)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #define MLOCK_RLIMIT_SIZE (CHUNK_UNIT * 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #define MLOCK_WITHIN_LIMIT_SIZE CHUNK_UNIT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #define MLOCK_OUTOF_LIMIT_SIZE (CHUNK_UNIT * 3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #define TEST_LOOP 100
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #define PAGE_ALIGN(size, ps) (((size) + ((ps) - 1)) & ~((ps) - 1))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) int set_cap_limits(rlim_t max)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) struct rlimit new;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) cap_t cap = cap_init();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) new.rlim_cur = max;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) new.rlim_max = max;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) if (setrlimit(RLIMIT_MEMLOCK, &new)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) perror("setrlimit() returns error\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) /* drop capabilities including CAP_IPC_LOCK */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) if (cap_set_proc(cap)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) perror("cap_set_proc() returns error\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) return -2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) int get_proc_locked_vm_size(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) FILE *f;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) int ret = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) char line[1024] = {0};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) unsigned long lock_size = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) f = fopen("/proc/self/status", "r");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) if (!f) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) perror("fopen");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) while (fgets(line, 1024, f)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) if (strstr(line, "VmLck")) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) ret = sscanf(line, "VmLck:\t%8lu kB", &lock_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) if (ret <= 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) printf("sscanf() on VmLck error: %s: %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) line, ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) fclose(f);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) fclose(f);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) return (int)(lock_size << 10);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) perror("cann't parse VmLck in /proc/self/status\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) fclose(f);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) * Get the MMUPageSize of the memory region including input
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) * address from proc file.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) * return value: on error case, 0 will be returned.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) * Otherwise the page size(in bytes) is returned.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) int get_proc_page_size(unsigned long addr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) FILE *smaps;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) char *line;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) unsigned long mmupage_size = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) size_t size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) smaps = seek_to_smaps_entry(addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) if (!smaps) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) printf("Unable to parse /proc/self/smaps\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) while (getline(&line, &size, smaps) > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) if (!strstr(line, "MMUPageSize")) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) free(line);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) line = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) size = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) /* found the MMUPageSize of this section */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) if (sscanf(line, "MMUPageSize: %8lu kB",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) &mmupage_size) < 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) printf("Unable to parse smaps entry for Size:%s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) line);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) free(line);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) if (smaps)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) fclose(smaps);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) return mmupage_size << 10;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) * Test mlock/mlock2() on provided memory chunk.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) * It expects the mlock/mlock2() to be successful (within rlimit)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) * With allocated memory chunk [p, p + alloc_size), this
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) * test will choose start/len randomly to perform mlock/mlock2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) * [start, start + len] memory range. The range is within range
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) * of the allocated chunk.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) * The memory region size alloc_size is within the rlimit.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) * So we always expect a success of mlock/mlock2.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) * VmLck is assumed to be 0 before this test.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) * return value: 0 - success
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) * else: failure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) int test_mlock_within_limit(char *p, int alloc_size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) int locked_vm_size = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) struct rlimit cur;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) int page_size = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) getrlimit(RLIMIT_MEMLOCK, &cur);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) if (cur.rlim_cur < alloc_size) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) printf("alloc_size[%d] < %u rlimit,lead to mlock failure\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) alloc_size, (unsigned int)cur.rlim_cur);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) srand(time(NULL));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) for (i = 0; i < TEST_LOOP; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) * - choose mlock/mlock2 randomly
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) * - choose lock_size randomly but lock_size < alloc_size
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) * - choose start_offset randomly but p+start_offset+lock_size
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) * < p+alloc_size
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) int is_mlock = !!(rand() % 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) int lock_size = rand() % alloc_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) int start_offset = rand() % (alloc_size - lock_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) if (is_mlock)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) ret = mlock(p + start_offset, lock_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) ret = mlock2_(p + start_offset, lock_size,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) MLOCK_ONFAULT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) printf("%s() failure at |%p(%d)| mlock:|%p(%d)|\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) is_mlock ? "mlock" : "mlock2",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) p, alloc_size,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) p + start_offset, lock_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) * Check VmLck left by the tests.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) locked_vm_size = get_proc_locked_vm_size();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) page_size = get_proc_page_size((unsigned long)p);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) if (page_size == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) printf("cannot get proc MMUPageSize\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) if (locked_vm_size > PAGE_ALIGN(alloc_size, page_size) + page_size) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) printf("test_mlock_within_limit() left VmLck:%d on %d chunk\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) locked_vm_size, alloc_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) * We expect the mlock/mlock2() to be fail (outof limitation)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) * With allocated memory chunk [p, p + alloc_size), this
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) * test will randomly choose start/len and perform mlock/mlock2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) * on [start, start+len] range.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) * The memory region size alloc_size is above the rlimit.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) * And the len to be locked is higher than rlimit.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) * So we always expect a failure of mlock/mlock2.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) * No locked page number should be increased as a side effect.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) * return value: 0 - success
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) * else: failure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) int test_mlock_outof_limit(char *p, int alloc_size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) int locked_vm_size = 0, old_locked_vm_size = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) struct rlimit cur;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) getrlimit(RLIMIT_MEMLOCK, &cur);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) if (cur.rlim_cur >= alloc_size) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) printf("alloc_size[%d] >%u rlimit, violates test condition\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) alloc_size, (unsigned int)cur.rlim_cur);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) old_locked_vm_size = get_proc_locked_vm_size();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) srand(time(NULL));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) for (i = 0; i < TEST_LOOP; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) int is_mlock = !!(rand() % 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) int lock_size = (rand() % (alloc_size - cur.rlim_cur))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) + cur.rlim_cur;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) int start_offset = rand() % (alloc_size - lock_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) if (is_mlock)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) ret = mlock(p + start_offset, lock_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) ret = mlock2_(p + start_offset, lock_size,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) MLOCK_ONFAULT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) if (ret == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) printf("%s() succeeds? on %p(%d) mlock%p(%d)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) is_mlock ? "mlock" : "mlock2",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) p, alloc_size,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) p + start_offset, lock_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) locked_vm_size = get_proc_locked_vm_size();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) if (locked_vm_size != old_locked_vm_size) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) printf("tests leads to new mlocked page: old[%d], new[%d]\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) old_locked_vm_size,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) locked_vm_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) int main(int argc, char **argv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) char *p = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) if (set_cap_limits(MLOCK_RLIMIT_SIZE))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) p = malloc(MLOCK_WITHIN_LIMIT_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) if (p == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) perror("malloc() failure\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) ret = test_mlock_within_limit(p, MLOCK_WITHIN_LIMIT_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) munlock(p, MLOCK_WITHIN_LIMIT_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) free(p);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) p = malloc(MLOCK_OUTOF_LIMIT_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) if (p == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) perror("malloc() failure\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) ret = test_mlock_outof_limit(p, MLOCK_OUTOF_LIMIT_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) munlock(p, MLOCK_OUTOF_LIMIT_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) free(p);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) }