diff mbox series

[4/4] syscalls/mlock202: Add new testcase

Message ID 1534844339-8655-4-git-send-email-yangx.jy@cn.fujitsu.com
State Superseded
Headers show
Series [1/4] lapi/syscalls: Add syscall numbers for mlock2 | expand

Commit Message

Xiao Yang Aug. 21, 2018, 9:38 a.m. UTC
Check various errnos for mlock2(2) since kernel v2.6.9.

Signed-off-by: Xiao Yang <yangx.jy@cn.fujitsu.com>
---
 runtest/ltplite                             |   1 +
 runtest/stress.part3                        |   1 +
 runtest/syscalls                            |   1 +
 testcases/kernel/syscalls/mlock2/.gitignore |   1 +
 testcases/kernel/syscalls/mlock2/mlock202.c | 110 ++++++++++++++++++++++++++++
 5 files changed, 114 insertions(+)
 create mode 100644 testcases/kernel/syscalls/mlock2/mlock202.c

Comments

Jan Stancek Aug. 29, 2018, 12:44 p.m. UTC | #1
----- Original Message -----
> Check various errnos for mlock2(2) since kernel v2.6.9.

mlock2() is available since Linux 4.4.

> +static struct tcase {
> +	char **taddr;
> +	int flag;
> +	unsigned long *max_size;
> +	/* 1: nobody expected  0: root expected */
> +	int exp_user;

I'd drop the "expected" prefix here, this isn't something syscall provides as "output".

> +	int exp_err;
> +} tcases[] = {
> +	{&addr, -1, NULL, 0, EINVAL},
> +	{&addr, 0, &max_sz1, 1, ENOMEM},
> +	{&addr, 0, &max_sz2, 1, EPERM},
> +	{&unmapped_addr, 0, NULL, 0, ENOMEM},
> +};
> +
..
> +static void setup(void)
> +{
> +	pgsz = getpagesize();
> +	nobody = SAFE_GETPWNAM("nobody");
> +
> +	addr = SAFE_MMAP(NULL, pgsz, PROT_WRITE,
> +			 MAP_PRIVATE | MAP_ANONYMOUS, 0, 0);
> +	unmapped_addr = SAFE_MMAP(NULL, pgsz, PROT_READ,
> +				  MAP_PRIVATE | MAP_ANONYMOUS, 0, 0);
> +	SAFE_MUNMAP(unmapped_addr, pgsz);

I suggest larger map here (couple M) and pick address in middle.
Single page can easily be mapped by glibc for some buffer.

> +
> +	max_sz1 = pgsz - 1;
> +}
> +

Regards,
Jan
Xiao Yang Aug. 30, 2018, 7:41 a.m. UTC | #2
On 2018/08/29 20:44, Jan Stancek wrote:
> ----- Original Message -----
>> Check various errnos for mlock2(2) since kernel v2.6.9.
> mlock2() is available since Linux 4.4.
>
>> +static struct tcase {
>> +	char **taddr;
>> +	int flag;
>> +	unsigned long *max_size;
>> +	/* 1: nobody expected  0: root expected */
>> +	int exp_user;
> I'd drop the "expected" prefix here, this isn't something syscall provides as "output".
Hi Jan,

OK, I will drop it.
>> +	int exp_err;
>> +} tcases[] = {
>> +	{&addr, -1, NULL, 0, EINVAL},
>> +	{&addr, 0,&max_sz1, 1, ENOMEM},
>> +	{&addr, 0,&max_sz2, 1, EPERM},
>> +	{&unmapped_addr, 0, NULL, 0, ENOMEM},
>> +};
>> +
> ..
>> +static void setup(void)
>> +{
>> +	pgsz = getpagesize();
>> +	nobody = SAFE_GETPWNAM("nobody");
>> +
>> +	addr = SAFE_MMAP(NULL, pgsz, PROT_WRITE,
>> +			 MAP_PRIVATE | MAP_ANONYMOUS, 0, 0);
>> +	unmapped_addr = SAFE_MMAP(NULL, pgsz, PROT_READ,
>> +				  MAP_PRIVATE | MAP_ANONYMOUS, 0, 0);
>> +	SAFE_MUNMAP(unmapped_addr, pgsz);
> I suggest larger map here (couple M) and pick address in middle.
> Single page can easily be mapped by glibc for some buffer.
OK, i will map a larger one and pick address in middle.

Thanks,
Xiao Yang
>> +
>> +	max_sz1 = pgsz - 1;
>> +}
>> +
> Regards,
> Jan
>
>
>
diff mbox series

Patch

diff --git a/runtest/ltplite b/runtest/ltplite
index 270c649..7ebe632 100644
--- a/runtest/ltplite
+++ b/runtest/ltplite
@@ -444,6 +444,7 @@  mlock01 mlock01
 mlock02 mlock02
 
 mlock201 mlock201
+mlock202 mlock202
 
 qmm01 mmap001 -m 1
 mmap01 mmap01
diff --git a/runtest/stress.part3 b/runtest/stress.part3
index 6850572..0804172 100644
--- a/runtest/stress.part3
+++ b/runtest/stress.part3
@@ -370,6 +370,7 @@  mlock01 mlock01
 mlock02 mlock02
 
 mlock201 mlock201
+mlock202 mlock202
 
 qmm01 mmap001 -m 1
 mmap01 mmap01
diff --git a/runtest/syscalls b/runtest/syscalls
index 5d84d48..2615254 100644
--- a/runtest/syscalls
+++ b/runtest/syscalls
@@ -634,6 +634,7 @@  mlock03 mlock03 -i 20
 mlock04 mlock04
 
 mlock201 mlock201
+mlock202 mlock202
 
 qmm01 mmap001 -m 1
 mmap01 mmap01
diff --git a/testcases/kernel/syscalls/mlock2/.gitignore b/testcases/kernel/syscalls/mlock2/.gitignore
index 431eff8..8daf0f9 100644
--- a/testcases/kernel/syscalls/mlock2/.gitignore
+++ b/testcases/kernel/syscalls/mlock2/.gitignore
@@ -1 +1,2 @@ 
 /mlock201
+/mlock202
diff --git a/testcases/kernel/syscalls/mlock2/mlock202.c b/testcases/kernel/syscalls/mlock2/mlock202.c
new file mode 100644
index 0000000..61dd29d
--- /dev/null
+++ b/testcases/kernel/syscalls/mlock2/mlock202.c
@@ -0,0 +1,110 @@ 
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (c) 2018 FUJITSU LIMITED. All rights reserved.
+ * Author: Xiao Yang <yangx.jy@cn.fujitsu.com>
+ */
+/*
+ * Description:
+ * Check various errnos for mlock2(2) since kernel v2.6.9:
+ * 1) mlock(2) fails and returns EINVAL if unknown flag is specified.
+ * 2) mlock(2) fails and returns ENOMEM if the caller is not
+ *    privileged(CAP_IPC_LOCK) and tries to lock more memory than the
+ *    RLIMIT_MEMLOCK limit.
+ * 3) mlock(2) fails and returns EPERM if the caller is not
+ *    privileged(CAP_IPC_LOCK) and its RLIMIT_MEMLOCK limit is 0.
+ * 4) mlock(2) fails and returns ENOMEM if some of the specified address
+ *    range does not correspond to mapped pages in the address space
+ *    of the caller.
+ */
+#include <errno.h>
+#include <unistd.h>
+#include <sys/mman.h>
+#include <sys/time.h>
+#include <sys/resource.h>
+#include <pwd.h>
+
+#include "tst_test.h"
+#include "lapi/syscalls.h"
+
+static unsigned long pgsz;
+static unsigned long max_sz1, max_sz2;
+static char *addr, *unmapped_addr;
+static struct passwd *nobody;
+
+static struct tcase {
+	char **taddr;
+	int flag;
+	unsigned long *max_size;
+	/* 1: nobody expected  0: root expected */
+	int exp_user;
+	int exp_err;
+} tcases[] = {
+	{&addr, -1, NULL, 0, EINVAL},
+	{&addr, 0, &max_sz1, 1, ENOMEM},
+	{&addr, 0, &max_sz2, 1, EPERM},
+	{&unmapped_addr, 0, NULL, 0, ENOMEM},
+};
+
+static void verify_mlock2(unsigned int n)
+{
+	struct tcase *tc = &tcases[n];
+	struct rlimit orig_limit, new_limit;
+
+	if (tc->exp_user) {
+		SAFE_GETRLIMIT(RLIMIT_MEMLOCK, &orig_limit);
+		new_limit.rlim_cur = *tc->max_size;
+		new_limit.rlim_max = *tc->max_size;
+		SAFE_SETRLIMIT(RLIMIT_MEMLOCK, &new_limit);
+		SAFE_SETEUID(nobody->pw_uid);
+	}
+
+	TEST(tst_syscall(__NR_mlock2, *tc->taddr, pgsz, tc->flag));
+	if (TST_RET != -1) {
+		tst_res(TFAIL, "mlock2() succeeded");
+		SAFE_MUNLOCK(*tc->taddr, pgsz);
+		goto end;
+	}
+
+	if (TST_ERR != tc->exp_err) {
+		tst_res(TFAIL | TTERRNO,
+			"mlock2() failed unexpectedly, expected %s",
+			tst_strerrno(tc->exp_err));
+	} else {
+		tst_res(TPASS | TTERRNO, "mlock2() failed as expected");
+	}
+
+end:
+	if (tc->exp_user) {
+		SAFE_SETEUID(0);
+		SAFE_SETRLIMIT(RLIMIT_MEMLOCK, &orig_limit);
+	}
+}
+
+static void setup(void)
+{
+	pgsz = getpagesize();
+	nobody = SAFE_GETPWNAM("nobody");
+
+	addr = SAFE_MMAP(NULL, pgsz, PROT_WRITE,
+			 MAP_PRIVATE | MAP_ANONYMOUS, 0, 0);
+	unmapped_addr = SAFE_MMAP(NULL, pgsz, PROT_READ,
+				  MAP_PRIVATE | MAP_ANONYMOUS, 0, 0);
+	SAFE_MUNMAP(unmapped_addr, pgsz);
+
+	max_sz1 = pgsz - 1;
+}
+
+static void cleanup(void)
+{
+	if (addr)
+		SAFE_MUNMAP(addr, pgsz);
+}
+
+static struct tst_test test = {
+	.tcnt = ARRAY_SIZE(tcases),
+	.test = verify_mlock2,
+	.setup = setup,
+	.cleanup = cleanup,
+	.needs_root = 1,
+	.min_kver = "2.6.9",
+};