1 /*
2  * Copyright (c) 2017 FUJITSU LIMITED. All rights reserved.
3  * Author: Xiao Yang <yangx.jy@cn.fujitsu.com>
4  *
5  * This program is free software;  you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY;  without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
13  * the GNU General Public License for more details.
14  */
15 
16 /*
17  * Test for EFAULT when rlim points outside the accessible address space.
18  */
19 
20 #define _GNU_SOURCE
21 #include <errno.h>
22 #include <sys/resource.h>
23 #include <sys/time.h>
24 #include <sys/wait.h>
25 #include <stdlib.h>
26 
27 #include "tst_test.h"
28 
29 static void verify_setrlimit(void)
30 {
31 	int status;
32 	pid_t pid;
33 
34 	pid = SAFE_FORK();
35 	if (!pid) {
36 		TEST(setrlimit(RLIMIT_NOFILE, (void *) -1));
37 		if (TEST_RETURN != -1) {
38 			tst_res(TFAIL, "setrlimit()  succeeded unexpectedly");
39 			exit(0);
40 		}
41 
42 		/* Usually, setrlimit() should return EFAULT */
43 		if (TEST_ERRNO == EFAULT) {
44 			tst_res(TPASS | TTERRNO,
45 				"setrlimit() failed as expected");
46 		} else {
47 			tst_res(TFAIL | TTERRNO,
48 				"setrlimit() should fail with EFAULT, got");
49 		}
50 
51 		exit(0);
52 	}
53 
54 	SAFE_WAITPID(pid, &status, 0);
55 
56 	/* If glibc has to convert between 32bit and 64bit struct rlimit
57 	 * in some cases, it is possible to get SegFault.
58 	 */
59 	if (WIFSIGNALED(status) && WTERMSIG(status) == SIGSEGV) {
60 		tst_res(TPASS, "setrlimit() caused SIGSEGV");
61 		return;
62 	}
63 
64 	if (WIFEXITED(status) && WEXITSTATUS(status) == 0)
65 		return;
66 
67 	tst_res(TBROK, "child %s", tst_strstatus(status));
68 }
69 
70 static struct tst_test test = {
71 	.test_all = verify_setrlimit,
72 	.forks_child = 1,
73 };
74