• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) International Business Machines  Corp., 2004
3  * Copyright (c) Linux Test Project, 2004-2017
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  * DESCRIPTION
18  *	hugeshmctl03 - check for EACCES, and EPERM errors
19  *
20  * ALGORITHM
21  *	create a large shared memory segment with root only read & write
22  *	permissions fork a child process
23  *	if child
24  *	  set the ID of the child process to that of "ltpuser1"
25  *	  call do_child()
26  *	  loop if that option was specified
27  *	    call shmctl() using three different invalid cases
28  *	    check the errno value
29  *	      issue a PASS message if we get EACCES or EPERM
30  *	    otherwise, the tests fails
31  *	      issue a FAIL message
32  *	  call cleanup
33  *	if parent
34  *	  wait for child to exit
35  *	  remove the large shared memory segment
36  *
37  * HISTORY
38  *	03/2001 - Written by Wayne Boyer
39  *	04/2004 - Updated by Robbie Williamson
40  *
41  * RESTRICTIONS
42  *	test must be run as root
43  */
44 
45 #include <sys/types.h>
46 #include <sys/wait.h>
47 #include <limits.h>
48 #include "hugetlb.h"
49 
50 static size_t shm_size;
51 static int shm_id_1 = -1;
52 static struct shmid_ds buf;
53 static uid_t ltp_uid;
54 static char *ltp_user = "nobody";
55 
56 static long hugepages = 128;
57 
58 static struct tst_option options[] = {
59 	{"s:", &nr_opt, "-s   num  Set the number of the been allocated hugepages"},
60 	{NULL, NULL, NULL}
61 };
62 
63 struct tcase {
64 	int *shmid;
65 	int cmd;
66 	struct shmid_ds *sbuf;
67 	int error;
68 } tcases[] = {
69 	/* EACCES - child has no read permission for segment */
70 	{&shm_id_1, IPC_STAT, &buf, EACCES},
71 	/* EPERM - IPC_SET - child doesn't have permission to change segment */
72 	{&shm_id_1, IPC_SET, &buf, EPERM},
73 	/* EPERM - IPC_RMID - child can not remove the segment */
74 	{&shm_id_1, IPC_RMID, &buf, EPERM},
75 };
76 
77 static void do_child(void);
78 
test_hugeshmctl(void)79 static void test_hugeshmctl(void)
80 {
81 	pid_t pid;
82 	int status;
83 
84 	switch (pid = SAFE_FORK()) {
85 	case 0:
86 		/* set the user ID of the child to the non root user */
87 		SAFE_SETUID(ltp_uid);
88 		do_child();
89 		exit(0);
90 	default:
91 		SAFE_WAITPID(pid, &status, 0);
92 	}
93 }
94 
do_child(void)95 static void do_child(void)
96 {
97 	unsigned int i;
98 
99 	for (i = 0; i < ARRAY_SIZE(tcases); i++) {
100 		TEST(shmctl(*(tcases[i].shmid), tcases[i].cmd, tcases[i].sbuf));
101 		if (TST_RET != -1) {
102 			tst_res(TFAIL, "shmctl succeeded "
103 					"unexpectedly");
104 			continue;
105 		}
106 		if (TST_ERR == tcases[i].error)
107 			tst_res(TPASS | TTERRNO, "shmctl failed "
108 					"as expected");
109 		else
110 			tst_res(TFAIL | TTERRNO, "shmctl failed "
111 					"unexpectedly - expect errno = "
112 					"%d, got", tcases[i].error);
113 	}
114 }
115 
setup(void)116 void setup(void)
117 {
118 	long hpage_size;
119 
120 	save_nr_hugepages();
121 	if (nr_opt)
122 		hugepages = SAFE_STRTOL(nr_opt, 0, LONG_MAX);
123 
124 	set_sys_tune("nr_hugepages", hugepages, 1);
125 	hpage_size = SAFE_READ_MEMINFO("Hugepagesize:") * 1024;
126 
127 	shm_size = hpage_size * hugepages / 2;
128 	update_shm_size(&shm_size);
129 	shmkey = getipckey();
130 	shm_id_1 = shmget(shmkey, shm_size,
131 			  SHM_HUGETLB | IPC_CREAT | IPC_EXCL | SHM_RW);
132 	if (shm_id_1 == -1)
133 		tst_brk(TBROK | TERRNO, "shmget");
134 
135 	/* get the userid for a non root user */
136 	ltp_uid = getuserid(ltp_user);
137 }
138 
cleanup(void)139 void cleanup(void)
140 {
141 	rm_shm(shm_id_1);
142 	restore_nr_hugepages();
143 }
144 
145 static struct tst_test test = {
146 	.needs_root = 1,
147 	.forks_child = 1,
148 	.needs_tmpdir = 1,
149 	.options = options,
150 	.setup = setup,
151 	.cleanup = cleanup,
152 	.test_all = test_hugeshmctl,
153 };
154