• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2002, Intel Corporation. All rights reserved.
3  * Copyright (c) 2012, Cyril Hrubis <chrubis@suse.cz>
4  *
5  * This file is licensed under the GPL license.  For the full content
6  * of this license, see the COPYING file at the top level of this
7  * source tree.
8  *
9  * The mmap() function shall fail if:
10  * ML [EAGAIN] The mapping could not be locked in memory,
11  * if required by mlockall(), due to a lack of resources.
12  *
13  * Test Steps:
14  * 1. Call mlockall(), setting MCL_FUTURE;
15  * 2. Call setrlimit(), set rlim_cur of resource RLIMIT_MEMLOCK to a
16  *    certain value.
17  * 3. Change user to non-root user seteuid()
18  * 4. Map a shared memory object, with size larger than the
19  *    rlim_cur value set in step 2
20  * 5. Should get EAGAIN.
21  * 6. Change user to root seteuid()
22  */
23 
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <unistd.h>
27 #include <sys/mman.h>
28 #include <sys/types.h>
29 #include <sys/stat.h>
30 #include <sys/resource.h>
31 #include <fcntl.h>
32 #include <pwd.h>
33 #include <string.h>
34 #include <errno.h>
35 #include "posixtest.h"
36 
37 /* Set the euid of this process to a non-root uid */
set_nonroot(void)38 int set_nonroot(void)
39 {
40 	struct passwd *pw;
41 	setpwent();
42 	/* search for the first user which is non root */
43 	while ((pw = getpwent()) != NULL)
44 		if (strcmp(pw->pw_name, "root"))
45 			break;
46 	endpwent();
47 	if (pw == NULL) {
48 		printf("There is no other user than current and root.\n");
49 		return 1;
50 	}
51 
52 	if (seteuid(pw->pw_uid) != 0) {
53 		if (errno == EPERM) {
54 			printf
55 			    ("You don't have permission to change your UID.\n");
56 			return 1;
57 		}
58 		perror("An error occurs when calling seteuid()");
59 		return 1;
60 	}
61 
62 	printf("Testing with user '%s' (uid: %d)\n",
63 	       pw->pw_name, (int)geteuid());
64 	return 0;
65 }
66 
main(void)67 int main(void)
68 {
69 	char tmpfname[256];
70 
71 	/* size of shared memory object */
72 	size_t shm_size;
73 
74 	void *pa;
75 	size_t len;
76 	int fd;
77 
78 	size_t memlock_size;
79 	struct rlimit rlim = {.rlim_max = RLIM_INFINITY };
80 
81 	/* Lock all memory page to be mapped */
82 	if (mlockall(MCL_FUTURE) == -1) {
83 		printf("Error at mlockall(): %s\n", strerror(errno));
84 		return PTS_UNRESOLVED;
85 	}
86 
87 	/* Set rlim.rlim_cur < len */
88 	len = 1024 * 1024;
89 	memlock_size = len / 2;
90 	rlim.rlim_cur = memlock_size;
91 
92 	/* We don't care of the size of the actual shared memory object */
93 	shm_size = 1024;
94 
95 	if (setrlimit(RLIMIT_MEMLOCK, &rlim) == -1) {
96 		printf("Error at setrlimit(): %s\n", strerror(errno));
97 		return PTS_UNRESOLVED;
98 	}
99 
100 	snprintf(tmpfname, sizeof(tmpfname), "pts_mmap_18_1_%d", getpid());
101 
102 	/* Create shared object */
103 	shm_unlink(tmpfname);
104 	fd = shm_open(tmpfname, O_RDWR | O_CREAT | O_EXCL, S_IRUSR | S_IWUSR);
105 	if (fd == -1) {
106 		printf("Error at shm_open(): %s\n", strerror(errno));
107 		return PTS_UNRESOLVED;
108 	}
109 	shm_unlink(tmpfname);
110 	if (ftruncate(fd, shm_size) == -1) {
111 		printf("Error at ftruncate(): %s\n", strerror(errno));
112 		return PTS_UNRESOLVED;
113 	}
114 
115 	/* This test should be run under standard user permissions */
116 	if (getuid() == 0) {
117 		if (set_nonroot() != 0) {
118 			printf("Cannot run this test as non-root user\n");
119 			return PTS_UNTESTED;
120 		}
121 	}
122 
123 	/*
124 	 * EAGAIN:
125 	 * Lock all the memory by mlockall().
126 	 * Set resource limit setrlimit()
127 	 * Change the user to non-root then only setrmilit is applicable.
128 	 */
129 	pa = mmap(NULL, len, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
130 	if (pa == MAP_FAILED && errno == EAGAIN) {
131 		printf("Got EAGAIN: %s\n", strerror(errno));
132 		printf("Test PASSED\n");
133 		/* Change user to root */
134 		seteuid(0);
135 		close(fd);
136 		munmap(pa, len);
137 		return PTS_PASS;
138 	}
139 
140 	if (pa == MAP_FAILED)
141 		perror("Error at mmap()");
142 	close(fd);
143 	munmap(pa, len);
144 	printf("Test FAILED: Did not get EAGAIN as expected\n");
145 	return PTS_FAIL;
146 }
147