1 /*
2 * Copyright (c) 2013 Wanlong Gao <gaowanlong@cn.fujitsu.com>
3 * Copyright (c) 2018 Linux Test Project
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 * DESCRIPTION
22 * Check for the following errors:
23 * 1. EEXIST
24 * 2. EISDIR
25 * 3. ENOTDIR
26 * 4. ENAMETOOLONG
27 * 5. EACCES
28 * 6. EFAULT
29 *
30 * ALGORITHM
31 * 1. Open a file with O_CREAT and O_EXCL, when the file already
32 * exists. Check the errno for EEXIST
33 *
34 * 2. Pass a directory as the pathname and request a write access,
35 * check for errno for EISDIR
36 *
37 * 3. Specify O_DIRECTORY as a parameter to open and pass a file as the
38 * pathname, check errno for ENOTDIR
39 *
40 * 4. Attempt to open() a filename which is more than VFS_MAXNAMLEN, and
41 * check for errno to be ENAMETOOLONG.
42 *
43 * 5. Attempt to open a (0600) file owned by different user in WRONLY mode,
44 * open(2) should fail with EACCES.
45 *
46 * 6. Attempt to pass an invalid pathname with an address pointing outside
47 * the accessible address space of the process, as the argument to open(),
48 * and expect to get EFAULT.
49 */
50
51 #define _GNU_SOURCE /* for O_DIRECTORY */
52 #include <sys/types.h>
53 #include <sys/stat.h>
54 #include <stdio.h>
55 #include <errno.h>
56 #include <sys/mman.h>
57 #include <fcntl.h>
58 #include <signal.h>
59 #include <pwd.h>
60 #include "tst_test.h"
61 #include "tst_get_bad_addr.h"
62
63 static char *existing_fname = "open08_testfile";
64 static char *toolong_fname = "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstmnopqrstuvwxyzabcdefghijklmnopqrstmnopqrstuvwxyzabcdefghijklmnopqrstmnopqrstuvwxyzabcdefghijklmnopqrstmnopqrstuvwxyzabcdefghijklmnopqrstmnopqrstuvwxyzabcdefghijklmnopqrstmnopqrstuvwxyz";
65 static char *dir_fname = "/tmp";
66 static char *user2_fname = "user2_0600";
67 static char *unmapped_fname;
68
69 struct test_case_t;
70
71 static struct test_case_t {
72 char **fname;
73 int flags;
74 int error;
75 } tcases[] = {
76 {&existing_fname, O_CREAT | O_EXCL, EEXIST},
77 {&dir_fname, O_RDWR, EISDIR},
78 {&existing_fname, O_DIRECTORY, ENOTDIR},
79 {&toolong_fname, O_RDWR, ENAMETOOLONG},
80 {&user2_fname, O_WRONLY, EACCES},
81 {&unmapped_fname, O_CREAT, EFAULT}
82 };
83
verify_open(unsigned int i)84 void verify_open(unsigned int i)
85 {
86 TEST(open(*tcases[i].fname, tcases[i].flags,
87 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH));
88
89 if (TST_RET != -1) {
90 tst_res(TFAIL, "call succeeded unexpectedly");
91 return;
92 }
93
94 if (TST_ERR == tcases[i].error) {
95 tst_res(TPASS, "expected failure - "
96 "errno = %d : %s", TST_ERR,
97 strerror(TST_ERR));
98 } else {
99 tst_res(TFAIL, "unexpected error - %d : %s - "
100 "expected %d", TST_ERR,
101 strerror(TST_ERR), tcases[i].error);
102 }
103 }
104
setup(void)105 static void setup(void)
106 {
107 int fildes;
108 char nobody_uid[] = "nobody";
109 struct passwd *ltpuser;
110
111 umask(0);
112
113 SAFE_CREAT(user2_fname, 0600);
114
115 /* Switch to nobody user for correct error code collection */
116 ltpuser = getpwnam(nobody_uid);
117 SAFE_SETGID(ltpuser->pw_gid);
118 SAFE_SETUID(ltpuser->pw_uid);
119
120 fildes = SAFE_CREAT(existing_fname, 0600);
121 close(fildes);
122
123 unmapped_fname = tst_get_bad_addr(NULL);
124 }
125
126 static struct tst_test test = {
127 .tcnt = ARRAY_SIZE(tcases),
128 .needs_tmpdir = 1,
129 .needs_root = 1,
130 .setup = setup,
131 .test = verify_open,
132 };
133