1f08c3bdfSopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later
2f08c3bdfSopenharmony_ci/*
3f08c3bdfSopenharmony_ci * Copyright (c) 2017 FUJITSU LIMITED. All rights reserved.
4f08c3bdfSopenharmony_ci * Author: Xiao Yang <yangx.jy@cn.fujitsu.com>
5f08c3bdfSopenharmony_ci */
6f08c3bdfSopenharmony_ci
7f08c3bdfSopenharmony_ci/*
8f08c3bdfSopenharmony_ci * Test for EFAULT when rlim points outside the accessible address space.
9f08c3bdfSopenharmony_ci */
10f08c3bdfSopenharmony_ci
11f08c3bdfSopenharmony_ci#define _GNU_SOURCE
12f08c3bdfSopenharmony_ci#include <errno.h>
13f08c3bdfSopenharmony_ci#include <sys/resource.h>
14f08c3bdfSopenharmony_ci#include <sys/time.h>
15f08c3bdfSopenharmony_ci#include <sys/wait.h>
16f08c3bdfSopenharmony_ci#include <stdlib.h>
17f08c3bdfSopenharmony_ci
18f08c3bdfSopenharmony_ci#include "tst_test.h"
19f08c3bdfSopenharmony_ci
20f08c3bdfSopenharmony_cistatic void *bad_addr;
21f08c3bdfSopenharmony_ci
22f08c3bdfSopenharmony_cistatic void verify_setrlimit(void)
23f08c3bdfSopenharmony_ci{
24f08c3bdfSopenharmony_ci	int status;
25f08c3bdfSopenharmony_ci	pid_t pid;
26f08c3bdfSopenharmony_ci
27f08c3bdfSopenharmony_ci	pid = SAFE_FORK();
28f08c3bdfSopenharmony_ci	if (!pid) {
29f08c3bdfSopenharmony_ci		TEST(setrlimit(RLIMIT_NOFILE, bad_addr));
30f08c3bdfSopenharmony_ci		if (TST_RET != -1) {
31f08c3bdfSopenharmony_ci			tst_res(TFAIL, "setrlimit()  succeeded unexpectedly");
32f08c3bdfSopenharmony_ci			exit(0);
33f08c3bdfSopenharmony_ci		}
34f08c3bdfSopenharmony_ci
35f08c3bdfSopenharmony_ci		/* Usually, setrlimit() should return EFAULT */
36f08c3bdfSopenharmony_ci		if (TST_ERR == EFAULT) {
37f08c3bdfSopenharmony_ci			tst_res(TPASS | TTERRNO,
38f08c3bdfSopenharmony_ci				"setrlimit() failed as expected");
39f08c3bdfSopenharmony_ci		} else {
40f08c3bdfSopenharmony_ci			tst_res(TFAIL | TTERRNO,
41f08c3bdfSopenharmony_ci				"setrlimit() should fail with EFAULT, got");
42f08c3bdfSopenharmony_ci		}
43f08c3bdfSopenharmony_ci
44f08c3bdfSopenharmony_ci		exit(0);
45f08c3bdfSopenharmony_ci	}
46f08c3bdfSopenharmony_ci
47f08c3bdfSopenharmony_ci	SAFE_WAITPID(pid, &status, 0);
48f08c3bdfSopenharmony_ci
49f08c3bdfSopenharmony_ci	/* If glibc has to convert between 32bit and 64bit struct rlimit
50f08c3bdfSopenharmony_ci	 * in some cases, it is possible to get SegFault.
51f08c3bdfSopenharmony_ci	 */
52f08c3bdfSopenharmony_ci	if (WIFSIGNALED(status) && WTERMSIG(status) == SIGSEGV) {
53f08c3bdfSopenharmony_ci		tst_res(TPASS, "setrlimit() caused SIGSEGV");
54f08c3bdfSopenharmony_ci		return;
55f08c3bdfSopenharmony_ci	}
56f08c3bdfSopenharmony_ci
57f08c3bdfSopenharmony_ci	if (WIFEXITED(status) && WEXITSTATUS(status) == 0)
58f08c3bdfSopenharmony_ci		return;
59f08c3bdfSopenharmony_ci
60f08c3bdfSopenharmony_ci	tst_res(TFAIL, "child %s", tst_strstatus(status));
61f08c3bdfSopenharmony_ci}
62f08c3bdfSopenharmony_ci
63f08c3bdfSopenharmony_cistatic void setup(void)
64f08c3bdfSopenharmony_ci{
65f08c3bdfSopenharmony_ci	bad_addr = tst_get_bad_addr(NULL);
66f08c3bdfSopenharmony_ci}
67f08c3bdfSopenharmony_ci
68f08c3bdfSopenharmony_cistatic struct tst_test test = {
69f08c3bdfSopenharmony_ci	.test_all = verify_setrlimit,
70f08c3bdfSopenharmony_ci	.forks_child = 1,
71f08c3bdfSopenharmony_ci	.setup = setup,
72f08c3bdfSopenharmony_ci};
73