blob: ea091e6c3cc41faf83f6b8e4d8e506bba3f3ba9e [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
Wanlong Gao4548c6c2012-10-19 18:03:36 +080017 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
plars865695b2001-08-27 22:15:12 +000018 */
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"
plars865695b2001-08-27 22:15:12 +000054
subrata_modakae5eb2c2008-11-18 09:00:57 +000055TCID_DEFINE(modify_ldt01);
plars865695b2001-08-27 22:15:12 +000056int TST_TOTAL = 1;
plars865695b2001-08-27 22:15:12 +000057
subrata_modakae5eb2c2008-11-18 09:00:57 +000058#if defined(__i386__) && defined(HAVE_MODIFY_LDT)
59
60#ifdef HAVE_ASM_LDT_H
61#include <asm/ldt.h>
62#endif
subrata_modak56207ce2009-03-23 13:35:39 +000063extern int modify_ldt(int, void *, unsigned long);
subrata_modakae5eb2c2008-11-18 09:00:57 +000064
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
70typedef struct user_desc modify_ldt_s;
71#elif HAVE_STRUCT_MODIFY_LDT_LDT_S
subrata_modak4bb656a2009-02-26 12:02:09 +000072typedef struct modify_ldt_ldt_s modify_ldt_s;
subrata_modakae5eb2c2008-11-18 09:00:57 +000073#else
subrata_modak56207ce2009-03-23 13:35:39 +000074typedef 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;
subrata_modakae5eb2c2008-11-18 09:00:57 +000085} modify_ldt_s;
86#endif
robbiew0d0826a2004-06-11 19:29:13 +000087
88int create_segment(void *, size_t);
subrata_modakae5eb2c2008-11-18 09:00:57 +000089void cleanup(void);
90void setup(void);
robbiew0d0826a2004-06-11 19:29:13 +000091
subrata_modakae5eb2c2008-11-18 09:00:57 +000092#define FAILED 1
93
plars7408fc92002-06-12 17:37:25 +000094int main(int ac, char **av)
plars865695b2001-08-27 22:15:12 +000095{
Cyril Hrubis89af32a2012-10-24 16:39:11 +020096 int lc;
Cyril Hrubis0b9589f2014-05-27 17:40:33 +020097 const char *msg;
plars865695b2001-08-27 22:15:12 +000098
99 void *ptr;
100 int retval, func;
101
subrata_modakae5eb2c2008-11-18 09:00:57 +0000102 int flag;
103 int seg[4];
104
Garrett Cooper45e285d2010-11-22 12:19:25 -0800105 if ((msg = parse_opts(ac, av, NULL, NULL)) != NULL) {
Garrett Cooper60fa8012010-11-22 13:50:58 -0800106 tst_brkm(TBROK, NULL, "OPTION PARSING ERROR - %s", msg);
Wanlong Gao354ebb42012-12-07 10:10:04 +0800107 }
plars865695b2001-08-27 22:15:12 +0000108
subrata_modak56207ce2009-03-23 13:35:39 +0000109 setup(); /* global setup */
plars865695b2001-08-27 22:15:12 +0000110
111 /* The following loop checks looping state if -i option given */
112 for (lc = 0; TEST_LOOPING(lc); lc++) {
113
Caspar Zhangd59a6592013-03-07 14:59:12 +0800114 /* reset tst_count in case we are looping */
115 tst_count = 0;
plars865695b2001-08-27 22:15:12 +0000116
robbiew860b47b2003-03-26 23:13:58 +0000117//block1:
plars865695b2001-08-27 22:15:12 +0000118 /*
119 * Check for ENOSYS.
120 */
121 tst_resm(TINFO, "Enter block 1");
122 flag = 0;
Cyril Hrubisd218f342014-09-23 13:14:56 +0200123 ptr = malloc(10);
plarsa6b81d92001-10-24 15:56:42 +0000124 func = 100;
plars865695b2001-08-27 22:15:12 +0000125 retval = modify_ldt(func, ptr, sizeof(ptr));
126 if (retval < 0) {
127 if (errno != ENOSYS) {
128 tst_resm(TFAIL, "modify_ldt() set invalid "
subrata_modak56207ce2009-03-23 13:35:39 +0000129 "errno, expected ENOSYS, got: %d",
plars865695b2001-08-27 22:15:12 +0000130 errno);
131 flag = FAILED;
132 }
133 } else {
134 tst_resm(TFAIL, "modify_ldt error: "
135 "unexpected return value %d", retval);
136 flag = FAILED;
137 }
138
139 if (flag) {
140 tst_resm(TINFO, "block 1 FAILED");
141 } else {
142 tst_resm(TINFO, "block 1 PASSED");
143 }
144 tst_resm(TINFO, "Exit block 1");
plarsa6b81d92001-10-24 15:56:42 +0000145 free(ptr);
plars865695b2001-08-27 22:15:12 +0000146
robbiew860b47b2003-03-26 23:13:58 +0000147//block2:
plars865695b2001-08-27 22:15:12 +0000148 /*
149 * Check for EINVAL
150 */
151 tst_resm(TINFO, "Enter block 2");
152 flag = 0;
153
154 ptr = 0;
155
robbiew929d7022001-09-12 18:38:29 +0000156 retval = modify_ldt(1, ptr, sizeof(ptr));
plars865695b2001-08-27 22:15:12 +0000157 if (retval < 0) {
158 if (errno != EINVAL) {
159 tst_resm(TFAIL, "modify_ldt() set invalid "
subrata_modak56207ce2009-03-23 13:35:39 +0000160 "errno, expected EINVAL, got: %d",
plars865695b2001-08-27 22:15:12 +0000161 errno);
162 flag = FAILED;
163 }
164 } else {
165 tst_resm(TFAIL, "modify_ldt error: "
166 "unexpected return value %d", retval);
167 flag = FAILED;
168 }
169
170 if (flag) {
171 tst_resm(TINFO, "block 2 FAILED");
172 } else {
173 tst_resm(TINFO, "block 2 PASSED");
174 }
175 tst_resm(TINFO, "Exit block 2");
176
robbiew860b47b2003-03-26 23:13:58 +0000177//block3:
plars865695b2001-08-27 22:15:12 +0000178
179 /*
180 * Create a new LDT segment.
181 */
182 if (create_segment(seg, sizeof(seg)) == -1) {
183 tst_brkm(TINFO, cleanup, "Creation of segment failed");
Wanlong Gao354ebb42012-12-07 10:10:04 +0800184 }
plars865695b2001-08-27 22:15:12 +0000185
186 /*
187 * Check for EFAULT
188 */
189 ptr = sbrk(0);
190
191 retval = modify_ldt(0, ptr + 0xFFF, sizeof(ptr));
192 if (retval < 0) {
193 if (errno != EFAULT) {
194 tst_resm(TFAIL, "modify_ldt() set invalid "
subrata_modak56207ce2009-03-23 13:35:39 +0000195 "errno, expected EFAULT, got: %d",
plars865695b2001-08-27 22:15:12 +0000196 errno);
197 flag = FAILED;
198 }
199 } else {
200 tst_resm(TFAIL, "modify_ldt error: "
201 "unexpected return value %d", retval);
202 flag = FAILED;
203 }
204
205 if (flag) {
206 tst_resm(TINFO, "block 3 FAILED");
207 } else {
208 tst_resm(TINFO, "block 3 PASSED");
209 }
210 tst_resm(TINFO, "Exit block 3");
211
subrata_modak56207ce2009-03-23 13:35:39 +0000212 }
213 cleanup();
Garrett Cooper1e6f5a62010-12-19 09:58:10 -0800214 tst_exit();
Garrett Cooper2c282152010-12-16 00:55:50 -0800215
plars865695b2001-08-27 22:15:12 +0000216}
217
subrata_modakae5eb2c2008-11-18 09:00:57 +0000218/*
subrata_modak4bb656a2009-02-26 12:02:09 +0000219 * create_segment() -
subrata_modakae5eb2c2008-11-18 09:00:57 +0000220 */
subrata_modak56207ce2009-03-23 13:35:39 +0000221int create_segment(void *seg, size_t size)
plars7408fc92002-06-12 17:37:25 +0000222{
subrata_modakae5eb2c2008-11-18 09:00:57 +0000223 modify_ldt_s entry;
plars7408fc92002-06-12 17:37:25 +0000224
subrata_modakae5eb2c2008-11-18 09:00:57 +0000225 entry.entry_number = 0;
226 entry.base_addr = (unsigned long)seg;
227 entry.limit = size;
228 entry.seg_32bit = 1;
229 entry.contents = 0;
230 entry.read_exec_only = 0;
231 entry.limit_in_pages = 0;
232 entry.seg_not_present = 0;
233
234 return modify_ldt(1, &entry, sizeof(entry));
235}
plars7408fc92002-06-12 17:37:25 +0000236
plars865695b2001-08-27 22:15:12 +0000237/*
238 * setup() - performs all ONE TIME setup for this test
239 */
subrata_modak56207ce2009-03-23 13:35:39 +0000240void setup(void)
plars865695b2001-08-27 22:15:12 +0000241{
Garrett Cooper2c282152010-12-16 00:55:50 -0800242
plars865695b2001-08-27 22:15:12 +0000243 tst_sig(FORK, DEF_HANDLER, cleanup);
244
plars865695b2001-08-27 22:15:12 +0000245 TEST_PAUSE;
246}
247
248/*
249 * cleanup() - performs all the ONE TIME cleanup for this test at completion
250 * or premature exit.
251 */
subrata_modak56207ce2009-03-23 13:35:39 +0000252void cleanup(void)
plars865695b2001-08-27 22:15:12 +0000253{
plars865695b2001-08-27 22:15:12 +0000254
plars865695b2001-08-27 22:15:12 +0000255}
256
subrata_modakae5eb2c2008-11-18 09:00:57 +0000257#elif HAVE_MODIFY_LDT
Mike Frysingerc57fba52014-04-09 18:56:30 -0400258int main(void)
plars865695b2001-08-27 22:15:12 +0000259{
Cyril Hrubis526fdf82014-12-04 14:35:01 +0100260 tst_brkm(TCONF,
261 NULL,
subrata_modak56207ce2009-03-23 13:35:39 +0000262 "modify_ldt is available but not tested on the platform than __i386__");
plars865695b2001-08-27 22:15:12 +0000263}
subrata_modakae5eb2c2008-11-18 09:00:57 +0000264
265#else
Mike Frysingerc57fba52014-04-09 18:56:30 -0400266int main(void)
subrata_modakae5eb2c2008-11-18 09:00:57 +0000267{
268 tst_resm(TINFO, "modify_ldt01 test only for ix86");
Garrett Cooper2c282152010-12-16 00:55:50 -0800269 tst_exit();
subrata_modakae5eb2c2008-11-18 09:00:57 +0000270}
271
Chris Dearmanec6edca2012-10-17 19:54:01 -0700272#endif /* defined(__i386__) */