access05.c revision 354ebb48db8e66a853a58379a4808d5dcd1ceac3
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 * Test Name: access05
22 *
23 * Test Description:
24 *  Verify that,
25 *   1. access() fails with -1 return value and sets errno to EACCES
26 *      if the permission bits of the file mode do not permit the
27 *	 requested (Read/Write/Execute) access.
28 *   2. access() fails with -1 return value and sets errno to EINVAL
29 *	if the specified access mode argument is invalid.
30 *   3. access() fails with -1 return value and sets errno to EFAULT
31 *	if the pathname points outside allocate address space for the
32 *	process.
33 *   4. access() fails with -1 return value and sets errno to ENOENT
34 *	if the specified file doesn't exist (or pathname is NULL).
35 *   5. access() fails with -1 return value and sets errno to ENAMETOOLONG
36 *      if the pathname size is > PATH_MAX characters.
37 *
38 * Expected Result:
39 *  access() should fail with return value -1 and set expected errno.
40 *
41 * Algorithm:
42 *  Setup:
43 *   Setup signal handling.
44 *   Create temporary directory.
45 *   Pause for SIGUSR1 if option specified.
46 *
47 *  Test:
48 *   Loop if the proper options are given.
49 *   Execute system call
50 *   Check return code, if system call failed (return=-1)
51 *	if errno set == expected errno
52 *		Issue sys call fails with expected return value and errno.
53 *	Otherwise,
54 *		Issue sys call fails with unexpected errno.
55 *   Otherwise,
56 *	Issue sys call returns unexpected value.
57 *
58 *  Cleanup:
59 *   Print errno log and/or timing stats if options given
60 *   Delete the temporary directory(s)/file(s) created.
61 *
62 * Usage:  <for command-line>
63 *  access05 [-c n] [-e] [-i n] [-I x] [-P x] [-t]
64 *     where,  -c n : Run n copies concurrently.
65 *             -e   : Turn on errno logging.
66 *	       -i n : Execute test n times.
67 *	       -I x : Execute test for x seconds.
68 *	       -P x : Pause for x seconds between iterations.
69 *	       -t   : Turn on syscall timing.
70 *
71 * HISTORY
72 *	07/2001 Ported by Wayne Boyer
73 *
74 * RESTRICTIONS:
75 *  This test should be run by 'non-super-user' only.
76 *
77 */
78
79#include <stdio.h>
80#include <errno.h>
81#include <unistd.h>
82#include <fcntl.h>
83#include <string.h>
84#include <signal.h>
85#include <sys/types.h>
86#include <sys/stat.h>
87#include <sys/mman.h>
88#include <pwd.h>
89
90#include "test.h"
91#include "usctest.h"
92
93#define INV_OK		-1
94#define TEST_FILE1	"test_file1"
95#define TEST_FILE2	"test_file2"
96#define TEST_FILE3	"test_file3"
97#define TEST_FILE4	"test_file4"
98
99#define FILE_MODE	(S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH)
100
101void setup1();			/* setup() to test access() for EACCES */
102void setup2();			/* setup() to test access() for EACCES */
103void setup3();			/* setup() to test access() for EACCES */
104void setup4();			/* setup() to test access() for EINVAL */
105void longpath_setup();		/* setup function to test access() for ENAMETOOLONG */
106
107#if !defined(UCLINUX)
108char high_address_node[64];
109#endif
110
111char Longpathname[PATH_MAX + 2];
112
113struct test_case_t {		/* test case structure */
114	char *pathname;
115	int a_mode;
116	int exp_errno;
117	void (*setupfunc) (void);
118} test_cases[] = {
119	{
120	TEST_FILE1, R_OK, EACCES, setup1}, {
121	TEST_FILE2, W_OK, EACCES, setup2}, {
122	TEST_FILE3, X_OK, EACCES, setup3}, {
123	TEST_FILE4, INV_OK, EINVAL, setup4},
124#if !defined(UCLINUX)
125	{
126	(char *)-1, R_OK, EFAULT, NULL}, {
127	high_address_node, R_OK, EFAULT, NULL},
128#endif
129	{
130	"", W_OK, ENOENT, NULL}, {
131Longpathname, R_OK, ENAMETOOLONG, longpath_setup},};
132
133char *TCID = "access05";	/* Test program identifier.    */
134int TST_TOTAL = sizeof(test_cases) / sizeof(*test_cases);
135int exp_enos[] = { EACCES, EFAULT, EINVAL, ENOENT, ENAMETOOLONG, 0 };
136
137char nobody_uid[] = "nobody";
138struct passwd *ltpuser;
139
140void setup();			/* Main setup function of test */
141void cleanup();			/* cleanup function for the test */
142
143char *bad_addr = 0;
144
145int main(int ac, char **av)
146{
147	int lc;
148	char *msg;
149	char *file_name;	/* name of the testfile */
150	int access_mode;	/* specified access mode for testfile */
151	int i;
152
153	if ((msg = parse_opts(ac, av, NULL, NULL)) != NULL)
154		tst_brkm(TBROK, NULL, "OPTION PARSING ERROR - %s", msg);
155
156	setup();
157
158	TEST_EXP_ENOS(exp_enos);
159
160	for (lc = 0; TEST_LOOPING(lc); lc++) {
161
162		Tst_count = 0;
163
164		for (i = 0; i < TST_TOTAL; i++) {
165			file_name = test_cases[i].pathname;
166			access_mode = test_cases[i].a_mode;
167
168#if !defined(UCLINUX)
169			if (file_name == high_address_node)
170				file_name = get_high_address();
171#endif
172
173			/*
174			 * Call access(2) to test different test conditions.
175			 * verify that it fails with -1 return value and
176			 * sets appropriate errno.
177			 */
178			TEST(access(file_name, access_mode));
179
180			if (TEST_RETURN != -1) {
181				tst_resm(TFAIL,
182					 "access(%s, %#o) succeeded unexpectedly",
183					 file_name, access_mode);
184				continue;
185			}
186
187			if (TEST_ERRNO == test_cases[i].exp_errno)
188				tst_resm(TPASS | TTERRNO,
189					 "access failed as expected");
190			else
191				tst_resm(TFAIL | TTERRNO,
192					 "access failed unexpectedly; expected: "
193					 "%d - %s",
194					 test_cases[i].exp_errno,
195					 strerror(test_cases[i].exp_errno));
196		}
197	}
198
199	cleanup();
200
201	tst_exit();
202
203}
204
205void setup()
206{
207	int i;
208
209	tst_sig(NOFORK, DEF_HANDLER, cleanup);
210
211	tst_require_root(NULL);
212
213	ltpuser = getpwnam(nobody_uid);
214	if (ltpuser == NULL)
215		tst_brkm(TBROK | TERRNO, NULL, "getpwnam failed");
216	if (setuid(ltpuser->pw_uid) == -1)
217		tst_brkm(TBROK | TERRNO, NULL, "setuid failed");
218
219	TEST_PAUSE;
220
221#if !defined(UCLINUX)
222	bad_addr = mmap(0, 1, PROT_NONE,
223			MAP_PRIVATE_EXCEPT_UCLINUX | MAP_ANONYMOUS, 0, 0);
224	if (bad_addr == MAP_FAILED)
225		tst_brkm(TBROK | TERRNO, NULL, "mmap failed");
226	test_cases[5].pathname = bad_addr;
227#endif
228
229	tst_tmpdir();
230
231	for (i = 0; i < TST_TOTAL; i++)
232		if (test_cases[i].setupfunc != NULL)
233			test_cases[i].setupfunc();
234}
235
236void setup_file(const char *file, mode_t perms)
237{
238	int fd;			/* file handle for testfile */
239
240	if ((fd = open(file, O_RDWR | O_CREAT, FILE_MODE)) == -1)
241		tst_brkm(TBROK | TERRNO, cleanup,
242			 "open(%s, O_RDWR|O_CREAT, %#o) failed",
243			 file, FILE_MODE);
244
245	if (fchmod(fd, perms) < 0)
246		tst_brkm(TBROK | TERRNO, cleanup, "chmod(%s, %#o) failed",
247			 file, perms);
248	if (close(fd) == -1)
249		tst_brkm(TBROK | TERRNO, cleanup, "close(%s) failed", file);
250}
251
252/*
253 * setup1() - Setup function to test access() for return value -1
254 *	      and errno EACCES when read access denied for specified
255 *	      testfile.
256 *
257 *   Creat/open a testfile and close it.
258 *   Deny read access permissions on testfile.
259 *   This function returns 0.
260 */
261void setup1()
262{
263	setup_file(TEST_FILE1, 0333);
264}
265
266/*
267 * setup2() - Setup function to test access() for return value -1 and
268 *	      errno EACCES when write access denied on testfile.
269 *
270 *   Creat/open a testfile and close it.
271 *   Deny write access permissions on testfile.
272 *   This function returns 0.
273 */
274void setup2()
275{
276	setup_file(TEST_FILE2, 0555);
277}
278
279/*
280 * setup3() - Setup function to test access() for return value -1 and
281 *	      errno EACCES when execute access denied on testfile.
282 *
283 *   Creat/open a testfile and close it.
284 *   Deny search access permissions on testfile.
285 *   This function returns 0.
286 */
287void setup3()
288{
289	setup_file(TEST_FILE3, 0666);
290}
291
292/*
293 * setup4() - Setup function to test access() for return value -1
294 *	      and errno EINVAL when specified access mode argument is
295 *	      invalid.
296 *
297 *   Creat/open a testfile and close it.
298 *   This function returns 0.
299 */
300void setup4()
301{
302	setup_file(TEST_FILE4, FILE_MODE);
303}
304
305/*
306 * longpath_setup() - setup to create a node with a name length exceeding
307 *		      the MAX. length of PATH_MAX.
308 */
309void longpath_setup()
310{
311	int i;
312
313	for (i = 0; i <= (PATH_MAX + 1); i++)
314		Longpathname[i] = 'a';
315}
316
317/*
318 * cleanup() - performs all ONE TIME cleanup for this test at
319 *             completion or premature exit.
320 *
321 *  Remove the test directory and testfile created in the setup.
322 */
323void cleanup()
324{
325	/*
326	 * print timing stats if that option was specified.
327	 * print errno log if that option was specified.
328	 */
329	TEST_CLEANUP;
330
331	/*
332	 * Delete the test directory/file and temporary directory
333	 * created in the setup.
334	 */
335	tst_rmdir();
336
337}
338