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