• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 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 
52 #include "config.h"
53 #include "test.h"
54 
55 TCID_DEFINE(modify_ldt01);
56 int TST_TOTAL = 1;
57 
58 #if defined(__i386__) && defined(HAVE_MODIFY_LDT)
59 
60 #ifdef HAVE_ASM_LDT_H
61 #include <asm/ldt.h>
62 #endif
63 extern int modify_ldt(int, void *, unsigned long);
64 
65 #include <asm/unistd.h>
66 #include <errno.h>
67 
68 /* Newer ldt.h files use user_desc, instead of modify_ldt_ldt_s */
69 #ifdef HAVE_STRUCT_USER_DESC
70 typedef struct user_desc modify_ldt_s;
71 #elif  HAVE_STRUCT_MODIFY_LDT_LDT_S
72 typedef struct modify_ldt_ldt_s modify_ldt_s;
73 #else
74 typedef struct modify_ldt_ldt_t {
75 	unsigned int entry_number;
76 	unsigned long int base_addr;
77 	unsigned int limit;
78 	unsigned int seg_32bit:1;
79 	unsigned int contents:2;
80 	unsigned int read_exec_only:1;
81 	unsigned int limit_in_pages:1;
82 	unsigned int seg_not_present:1;
83 	unsigned int useable:1;
84 	unsigned int empty:25;
85 } modify_ldt_s;
86 #endif
87 
88 int create_segment(void *, size_t);
89 void cleanup(void);
90 void setup(void);
91 
92 #define FAILED 1
93 
main(int ac,char ** av)94 int main(int ac, char **av)
95 {
96 	int lc;
97 
98 	void *ptr;
99 	int retval, func;
100 
101 	int flag;
102 	int seg[4];
103 
104 	tst_parse_opts(ac, av, NULL, NULL);
105 
106 	setup();		/* global setup */
107 
108 	/* The following loop checks looping state if -i option given */
109 	for (lc = 0; TEST_LOOPING(lc); lc++) {
110 
111 		/* reset tst_count in case we are looping */
112 		tst_count = 0;
113 
114 //block1:
115 		/*
116 		 * Check for ENOSYS.
117 		 */
118 		tst_resm(TINFO, "Enter block 1");
119 		flag = 0;
120 		ptr = malloc(10);
121 		func = 100;
122 		retval = modify_ldt(func, ptr, sizeof(ptr));
123 		if (retval < 0) {
124 			if (errno != ENOSYS) {
125 				tst_resm(TFAIL, "modify_ldt() set invalid "
126 					 "errno, expected ENOSYS, got: %d",
127 					 errno);
128 				flag = FAILED;
129 			}
130 		} else {
131 			tst_resm(TFAIL, "modify_ldt error: "
132 				 "unexpected return value %d", retval);
133 			flag = FAILED;
134 		}
135 
136 		if (flag) {
137 			tst_resm(TINFO, "block 1 FAILED");
138 		} else {
139 			tst_resm(TINFO, "block 1 PASSED");
140 		}
141 		tst_resm(TINFO, "Exit block 1");
142 		free(ptr);
143 
144 //block2:
145 		/*
146 		 * Check for EINVAL
147 		 */
148 		tst_resm(TINFO, "Enter block 2");
149 		flag = 0;
150 
151 		ptr = 0;
152 
153 		retval = modify_ldt(1, ptr, sizeof(ptr));
154 		if (retval < 0) {
155 			if (errno != EINVAL) {
156 				tst_resm(TFAIL, "modify_ldt() set invalid "
157 					 "errno, expected EINVAL, got: %d",
158 					 errno);
159 				flag = FAILED;
160 			}
161 		} else {
162 			tst_resm(TFAIL, "modify_ldt error: "
163 				 "unexpected return value %d", retval);
164 			flag = FAILED;
165 		}
166 
167 		if (flag) {
168 			tst_resm(TINFO, "block 2 FAILED");
169 		} else {
170 			tst_resm(TINFO, "block 2 PASSED");
171 		}
172 		tst_resm(TINFO, "Exit block 2");
173 
174 //block3:
175 
176 		/*
177 		 * Create a new LDT segment.
178 		 */
179 		if (create_segment(seg, sizeof(seg)) == -1) {
180 			tst_brkm(TINFO, cleanup, "Creation of segment failed");
181 		}
182 
183 		/*
184 		 * Check for EFAULT
185 		 */
186 		ptr = sbrk(0);
187 
188 		retval = modify_ldt(0, ptr + 0xFFF, sizeof(ptr));
189 		if (retval < 0) {
190 			if (errno != EFAULT) {
191 				tst_resm(TFAIL, "modify_ldt() set invalid "
192 					 "errno, expected EFAULT, got: %d",
193 					 errno);
194 				flag = FAILED;
195 			}
196 		} else {
197 			tst_resm(TFAIL, "modify_ldt error: "
198 				 "unexpected return value %d", retval);
199 			flag = FAILED;
200 		}
201 
202 		if (flag) {
203 			tst_resm(TINFO, "block 3 FAILED");
204 		} else {
205 			tst_resm(TINFO, "block 3 PASSED");
206 		}
207 		tst_resm(TINFO, "Exit block 3");
208 
209 	}
210 	cleanup();
211 	tst_exit();
212 
213 }
214 
215 /*
216  * create_segment() -
217  */
create_segment(void * seg,size_t size)218 int create_segment(void *seg, size_t size)
219 {
220 	modify_ldt_s entry;
221 
222 	entry.entry_number = 0;
223 	entry.base_addr = (unsigned long)seg;
224 	entry.limit = size;
225 	entry.seg_32bit = 1;
226 	entry.contents = 0;
227 	entry.read_exec_only = 0;
228 	entry.limit_in_pages = 0;
229 	entry.seg_not_present = 0;
230 
231 	return modify_ldt(1, &entry, sizeof(entry));
232 }
233 
234 /*
235  * setup() - performs all ONE TIME setup for this test
236  */
setup(void)237 void setup(void)
238 {
239 
240 	tst_sig(FORK, DEF_HANDLER, cleanup);
241 
242 	TEST_PAUSE;
243 }
244 
245 /*
246  * cleanup() - performs all the ONE TIME cleanup for this test at completion
247  * or premature exit.
248  */
cleanup(void)249 void cleanup(void)
250 {
251 
252 }
253 
254 #elif HAVE_MODIFY_LDT
main(void)255 int main(void)
256 {
257 	tst_brkm(TCONF,
258 		 NULL,
259 		 "modify_ldt is available but not tested on the platform than __i386__");
260 }
261 
262 #else
main(void)263 int main(void)
264 {
265 	tst_resm(TINFO, "modify_ldt01 test only for ix86");
266 	tst_exit();
267 }
268 
269 #endif /* defined(__i386__) */
270