1f08c3bdfSopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later
2f08c3bdfSopenharmony_ci/*
3f08c3bdfSopenharmony_ci * Copyright (c) International Business Machines Corp., 2002
4f08c3bdfSopenharmony_ci *
5f08c3bdfSopenharmony_ci * 06/2002 Written by Paul Larson
6f08c3bdfSopenharmony_ci */
7f08c3bdfSopenharmony_ci
8f08c3bdfSopenharmony_ci/*\
9f08c3bdfSopenharmony_ci * [Description]
10f08c3bdfSopenharmony_ci *
11f08c3bdfSopenharmony_ci * Test for ENOMEM, EPERM errors.
12f08c3bdfSopenharmony_ci *
13f08c3bdfSopenharmony_ci * 1) mlock(2) fails with ENOMEM if some of the specified address range
14f08c3bdfSopenharmony_ci *    does not correspond to mapped pages in the address space of
15f08c3bdfSopenharmony_ci *    the process.
16f08c3bdfSopenharmony_ci *
17f08c3bdfSopenharmony_ci * 2) mlock(2) fails with ENOMEM if the caller had a non-zero RLIMIT_MEMLOCK
18f08c3bdfSopenharmony_ci *    soft resource limit, but tried to lock more memory than the limit
19f08c3bdfSopenharmony_ci *    permitted.  This limit is not enforced if the process is
20f08c3bdfSopenharmony_ci *    privileged (CAP_IPC_LOCK).
21f08c3bdfSopenharmony_ci *
22f08c3bdfSopenharmony_ci * 3) mlock(2) fails with EPERM if the caller was not privileged (CAP_IPC_LOCK)
23f08c3bdfSopenharmony_ci *    and its RLIMIT_MEMLOCK soft resource limit was 0.
24f08c3bdfSopenharmony_ci */
25f08c3bdfSopenharmony_ci
26f08c3bdfSopenharmony_ci#include <unistd.h>
27f08c3bdfSopenharmony_ci#include <sys/mman.h>
28f08c3bdfSopenharmony_ci#include <sys/types.h>
29f08c3bdfSopenharmony_ci#include <pwd.h>
30f08c3bdfSopenharmony_ci#include "tst_test.h"
31f08c3bdfSopenharmony_ci
32f08c3bdfSopenharmony_cistatic size_t len;
33f08c3bdfSopenharmony_cistatic struct rlimit original;
34f08c3bdfSopenharmony_cistatic struct passwd *ltpuser;
35f08c3bdfSopenharmony_ci
36f08c3bdfSopenharmony_cistatic void test_enomem1(void)
37f08c3bdfSopenharmony_ci{
38f08c3bdfSopenharmony_ci	void *addr;
39f08c3bdfSopenharmony_ci
40f08c3bdfSopenharmony_ci	addr = SAFE_MMAP(NULL, len, PROT_READ,
41f08c3bdfSopenharmony_ci			 MAP_PRIVATE | MAP_ANONYMOUS, 0, 0);
42f08c3bdfSopenharmony_ci	SAFE_MUNMAP(addr, len);
43f08c3bdfSopenharmony_ci	TST_EXP_FAIL(mlock(addr, len), ENOMEM, "mlock(%p, %lu)", addr, len);
44f08c3bdfSopenharmony_ci}
45f08c3bdfSopenharmony_ci
46f08c3bdfSopenharmony_cistatic void test_enomem2(void)
47f08c3bdfSopenharmony_ci{
48f08c3bdfSopenharmony_ci	void *addr;
49f08c3bdfSopenharmony_ci	struct rlimit rl;
50f08c3bdfSopenharmony_ci
51f08c3bdfSopenharmony_ci	rl.rlim_max = len - 1;
52f08c3bdfSopenharmony_ci	rl.rlim_cur = len - 1;
53f08c3bdfSopenharmony_ci	SAFE_SETRLIMIT(RLIMIT_MEMLOCK, &rl);
54f08c3bdfSopenharmony_ci	addr = SAFE_MMAP(NULL, len, PROT_READ,
55f08c3bdfSopenharmony_ci			 MAP_PRIVATE | MAP_ANONYMOUS, 0, 0);
56f08c3bdfSopenharmony_ci	SAFE_SETEUID(ltpuser->pw_uid);
57f08c3bdfSopenharmony_ci	TST_EXP_FAIL(mlock(addr, len), ENOMEM, "mlock(%p, %lu)", addr, len);
58f08c3bdfSopenharmony_ci	SAFE_SETEUID(0);
59f08c3bdfSopenharmony_ci	SAFE_MUNMAP(addr, len);
60f08c3bdfSopenharmony_ci	SAFE_SETRLIMIT(RLIMIT_MEMLOCK, &original);
61f08c3bdfSopenharmony_ci}
62f08c3bdfSopenharmony_ci
63f08c3bdfSopenharmony_cistatic void test_eperm(void)
64f08c3bdfSopenharmony_ci{
65f08c3bdfSopenharmony_ci	void *addr;
66f08c3bdfSopenharmony_ci	struct rlimit rl;
67f08c3bdfSopenharmony_ci
68f08c3bdfSopenharmony_ci	rl.rlim_max = 0;
69f08c3bdfSopenharmony_ci	rl.rlim_cur = 0;
70f08c3bdfSopenharmony_ci	SAFE_SETRLIMIT(RLIMIT_MEMLOCK, &rl);
71f08c3bdfSopenharmony_ci	addr = SAFE_MMAP(NULL, len, PROT_READ,
72f08c3bdfSopenharmony_ci			 MAP_PRIVATE | MAP_ANONYMOUS, 0, 0);
73f08c3bdfSopenharmony_ci	SAFE_SETEUID(ltpuser->pw_uid);
74f08c3bdfSopenharmony_ci	TST_EXP_FAIL(mlock(addr, len), EPERM, "mlock(%p, %lu)", addr, len);
75f08c3bdfSopenharmony_ci	SAFE_SETEUID(0);
76f08c3bdfSopenharmony_ci	SAFE_MUNMAP(addr, len);
77f08c3bdfSopenharmony_ci	SAFE_SETRLIMIT(RLIMIT_MEMLOCK, &original);
78f08c3bdfSopenharmony_ci}
79f08c3bdfSopenharmony_ci
80f08c3bdfSopenharmony_cistatic void run(void)
81f08c3bdfSopenharmony_ci{
82f08c3bdfSopenharmony_ci	test_enomem1();
83f08c3bdfSopenharmony_ci	test_enomem2();
84f08c3bdfSopenharmony_ci	test_eperm();
85f08c3bdfSopenharmony_ci}
86f08c3bdfSopenharmony_ci
87f08c3bdfSopenharmony_cistatic void setup(void)
88f08c3bdfSopenharmony_ci{
89f08c3bdfSopenharmony_ci	ltpuser = SAFE_GETPWNAM("nobody");
90f08c3bdfSopenharmony_ci	len = getpagesize();
91f08c3bdfSopenharmony_ci	SAFE_GETRLIMIT(RLIMIT_MEMLOCK, &original);
92f08c3bdfSopenharmony_ci}
93f08c3bdfSopenharmony_ci
94f08c3bdfSopenharmony_cistatic struct tst_test test = {
95f08c3bdfSopenharmony_ci	.needs_root = 1,
96f08c3bdfSopenharmony_ci	.setup = setup,
97f08c3bdfSopenharmony_ci	.test_all = run,
98f08c3bdfSopenharmony_ci};
99