blob: cbc4d9599d791989e0d8ab9833a7aae514237f65 [file] [log] [blame]
plars865695b2001-08-27 22:15:12 +00001/*
2 *
3 * Copyright (c) International Business Machines Corp., 2001
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 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 */
19
20/*
21 * NAME
22 * modify_ldt01.c
23 *
24 * DESCRIPTION
25 * Testcase to check the error conditions for modify_ldt(2)
26 *
27 * CALLS
28 * modify_ldt()
29 *
30 * ALGORITHM
31 * block1:
32 * Invoke modify_ldt() with a func value which is neither
33 * 0 or 1. Verify that ENOSYS is set.
34 * block2:
35 * Invoke mprotect() with ptr == NULL. Verify that EINVAL
36 * is set.
37 * block3:
38 * Create an LDT segment.
39 * Try to read from an invalid pointer.
40 * Verify that EFAULT is set.
41 *
42 * USAGE
43 * modify_ldt01
44 *
45 * HISTORY
46 * 07/2001 Ported by Wayne Boyer
47 *
48 * RESTRICTIONS
49 * None
50 */
51
subrata_modakae5eb2c2008-11-18 09:00:57 +000052#include "config.h"
plars865695b2001-08-27 22:15:12 +000053#include "test.h"
54#include "usctest.h"
55
subrata_modakae5eb2c2008-11-18 09:00:57 +000056TCID_DEFINE(modify_ldt01);
plars865695b2001-08-27 22:15:12 +000057int TST_TOTAL = 1;
58extern int Tst_count;
plars865695b2001-08-27 22:15:12 +000059
subrata_modakae5eb2c2008-11-18 09:00:57 +000060#if defined(__i386__) && defined(HAVE_MODIFY_LDT)
61
62#ifdef HAVE_ASM_LDT_H
63#include <asm/ldt.h>
64#endif
subrata_modak56207ce2009-03-23 13:35:39 +000065extern int modify_ldt(int, void *, unsigned long);
subrata_modakae5eb2c2008-11-18 09:00:57 +000066
67#include <asm/unistd.h>
68#include <errno.h>
69
70/* Newer ldt.h files use user_desc, instead of modify_ldt_ldt_s */
71#ifdef HAVE_STRUCT_USER_DESC
72typedef struct user_desc modify_ldt_s;
73#elif HAVE_STRUCT_MODIFY_LDT_LDT_S
subrata_modak4bb656a2009-02-26 12:02:09 +000074typedef struct modify_ldt_ldt_s modify_ldt_s;
subrata_modakae5eb2c2008-11-18 09:00:57 +000075#else
subrata_modak56207ce2009-03-23 13:35:39 +000076typedef struct modify_ldt_ldt_t {
77 unsigned int entry_number;
78 unsigned long int base_addr;
79 unsigned int limit;
80 unsigned int seg_32bit:1;
81 unsigned int contents:2;
82 unsigned int read_exec_only:1;
83 unsigned int limit_in_pages:1;
84 unsigned int seg_not_present:1;
85 unsigned int useable:1;
86 unsigned int empty:25;
subrata_modakae5eb2c2008-11-18 09:00:57 +000087} modify_ldt_s;
88#endif
robbiew0d0826a2004-06-11 19:29:13 +000089
90int create_segment(void *, size_t);
subrata_modakae5eb2c2008-11-18 09:00:57 +000091void cleanup(void);
92void setup(void);
robbiew0d0826a2004-06-11 19:29:13 +000093
subrata_modakae5eb2c2008-11-18 09:00:57 +000094#define FAILED 1
95
plars7408fc92002-06-12 17:37:25 +000096int main(int ac, char **av)
plars865695b2001-08-27 22:15:12 +000097{
subrata_modak56207ce2009-03-23 13:35:39 +000098 int lc; /* loop counter */
99 char *msg; /* message returned from parse_opts */
plars865695b2001-08-27 22:15:12 +0000100
101 void *ptr;
102 int retval, func;
103
subrata_modakae5eb2c2008-11-18 09:00:57 +0000104 int flag;
105 int seg[4];
106
subrata_modak56207ce2009-03-23 13:35:39 +0000107 /* parse standard options */
Garrett Cooper45e285d2010-11-22 12:19:25 -0800108 if ((msg = parse_opts(ac, av, NULL, NULL)) != NULL) {
Garrett Cooper60fa8012010-11-22 13:50:58 -0800109 tst_brkm(TBROK, NULL, "OPTION PARSING ERROR - %s", msg);
subrata_modak56207ce2009-03-23 13:35:39 +0000110 /*NOTREACHED*/}
plars865695b2001-08-27 22:15:12 +0000111
subrata_modak56207ce2009-03-23 13:35:39 +0000112 setup(); /* global setup */
plars865695b2001-08-27 22:15:12 +0000113
114 /* The following loop checks looping state if -i option given */
115 for (lc = 0; TEST_LOOPING(lc); lc++) {
116
subrata_modak56207ce2009-03-23 13:35:39 +0000117 /* reset Tst_count in case we are looping */
118 Tst_count = 0;
plars865695b2001-08-27 22:15:12 +0000119
robbiew860b47b2003-03-26 23:13:58 +0000120//block1:
plars865695b2001-08-27 22:15:12 +0000121 /*
122 * Check for ENOSYS.
123 */
124 tst_resm(TINFO, "Enter block 1");
125 flag = 0;
subrata_modak56207ce2009-03-23 13:35:39 +0000126 ptr = (void *)malloc(10);
plarsa6b81d92001-10-24 15:56:42 +0000127 func = 100;
plars865695b2001-08-27 22:15:12 +0000128 retval = modify_ldt(func, ptr, sizeof(ptr));
129 if (retval < 0) {
130 if (errno != ENOSYS) {
131 tst_resm(TFAIL, "modify_ldt() set invalid "
subrata_modak56207ce2009-03-23 13:35:39 +0000132 "errno, expected ENOSYS, got: %d",
plars865695b2001-08-27 22:15:12 +0000133 errno);
134 flag = FAILED;
135 }
136 } else {
137 tst_resm(TFAIL, "modify_ldt error: "
138 "unexpected return value %d", retval);
139 flag = FAILED;
140 }
141
142 if (flag) {
143 tst_resm(TINFO, "block 1 FAILED");
144 } else {
145 tst_resm(TINFO, "block 1 PASSED");
146 }
147 tst_resm(TINFO, "Exit block 1");
plarsa6b81d92001-10-24 15:56:42 +0000148 free(ptr);
plars865695b2001-08-27 22:15:12 +0000149
robbiew860b47b2003-03-26 23:13:58 +0000150//block2:
plars865695b2001-08-27 22:15:12 +0000151 /*
152 * Check for EINVAL
153 */
154 tst_resm(TINFO, "Enter block 2");
155 flag = 0;
156
157 ptr = 0;
158
robbiew929d7022001-09-12 18:38:29 +0000159 retval = modify_ldt(1, ptr, sizeof(ptr));
plars865695b2001-08-27 22:15:12 +0000160 if (retval < 0) {
161 if (errno != EINVAL) {
162 tst_resm(TFAIL, "modify_ldt() set invalid "
subrata_modak56207ce2009-03-23 13:35:39 +0000163 "errno, expected EINVAL, got: %d",
plars865695b2001-08-27 22:15:12 +0000164 errno);
165 flag = FAILED;
166 }
167 } else {
168 tst_resm(TFAIL, "modify_ldt error: "
169 "unexpected return value %d", retval);
170 flag = FAILED;
171 }
172
173 if (flag) {
174 tst_resm(TINFO, "block 2 FAILED");
175 } else {
176 tst_resm(TINFO, "block 2 PASSED");
177 }
178 tst_resm(TINFO, "Exit block 2");
179
robbiew860b47b2003-03-26 23:13:58 +0000180//block3:
plars865695b2001-08-27 22:15:12 +0000181
182 /*
183 * Create a new LDT segment.
184 */
185 if (create_segment(seg, sizeof(seg)) == -1) {
186 tst_brkm(TINFO, cleanup, "Creation of segment failed");
subrata_modak56207ce2009-03-23 13:35:39 +0000187 /*NOTREACHED*/}
plars865695b2001-08-27 22:15:12 +0000188
189 /*
190 * Check for EFAULT
191 */
192 ptr = sbrk(0);
193
194 retval = modify_ldt(0, ptr + 0xFFF, sizeof(ptr));
195 if (retval < 0) {
196 if (errno != EFAULT) {
197 tst_resm(TFAIL, "modify_ldt() set invalid "
subrata_modak56207ce2009-03-23 13:35:39 +0000198 "errno, expected EFAULT, got: %d",
plars865695b2001-08-27 22:15:12 +0000199 errno);
200 flag = FAILED;
201 }
202 } else {
203 tst_resm(TFAIL, "modify_ldt error: "
204 "unexpected return value %d", retval);
205 flag = FAILED;
206 }
207
208 if (flag) {
209 tst_resm(TINFO, "block 3 FAILED");
210 } else {
211 tst_resm(TINFO, "block 3 PASSED");
212 }
213 tst_resm(TINFO, "Exit block 3");
214
subrata_modak56207ce2009-03-23 13:35:39 +0000215 }
216 cleanup();
subrata_modak43337a32009-02-26 11:43:51 +0000217 return 0;
plars865695b2001-08-27 22:15:12 +0000218}
219
subrata_modakae5eb2c2008-11-18 09:00:57 +0000220/*
subrata_modak4bb656a2009-02-26 12:02:09 +0000221 * create_segment() -
subrata_modakae5eb2c2008-11-18 09:00:57 +0000222 */
subrata_modak56207ce2009-03-23 13:35:39 +0000223int create_segment(void *seg, size_t size)
plars7408fc92002-06-12 17:37:25 +0000224{
subrata_modakae5eb2c2008-11-18 09:00:57 +0000225 modify_ldt_s entry;
plars7408fc92002-06-12 17:37:25 +0000226
subrata_modakae5eb2c2008-11-18 09:00:57 +0000227 entry.entry_number = 0;
228 entry.base_addr = (unsigned long)seg;
229 entry.limit = size;
230 entry.seg_32bit = 1;
231 entry.contents = 0;
232 entry.read_exec_only = 0;
233 entry.limit_in_pages = 0;
234 entry.seg_not_present = 0;
235
236 return modify_ldt(1, &entry, sizeof(entry));
237}
plars7408fc92002-06-12 17:37:25 +0000238
plars865695b2001-08-27 22:15:12 +0000239/*
240 * setup() - performs all ONE TIME setup for this test
241 */
subrata_modak56207ce2009-03-23 13:35:39 +0000242void setup(void)
plars865695b2001-08-27 22:15:12 +0000243{
244 /* capture signals */
245 tst_sig(FORK, DEF_HANDLER, cleanup);
246
247 /* Pause if that option was specified */
248 TEST_PAUSE;
249}
250
251/*
252 * cleanup() - performs all the ONE TIME cleanup for this test at completion
253 * or premature exit.
254 */
subrata_modak56207ce2009-03-23 13:35:39 +0000255void cleanup(void)
plars865695b2001-08-27 22:15:12 +0000256{
257 /*
258 * print timing status if that option was specified.
259 * print errno log if that option was specified
260 */
261 TEST_CLEANUP;
262
263 /* exit with return code appropriate for results */
264 tst_exit();
265}
266
subrata_modakae5eb2c2008-11-18 09:00:57 +0000267#elif HAVE_MODIFY_LDT
268int main()
plars865695b2001-08-27 22:15:12 +0000269{
subrata_modak56207ce2009-03-23 13:35:39 +0000270 tst_resm(TCONF,
271 "modify_ldt is available but not tested on the platform than __i386__");
subrata_modakae5eb2c2008-11-18 09:00:57 +0000272 return 0;
plars865695b2001-08-27 22:15:12 +0000273}
subrata_modakae5eb2c2008-11-18 09:00:57 +0000274
275#else
276int main()
277{
278 tst_resm(TINFO, "modify_ldt01 test only for ix86");
279 return 0;
280}
281
282#endif /* defined(__i386__) */