blob: ed4f240f1da3fa22b4199ef5630a8ca93b561304 [file] [log] [blame]
plars865695b2001-08-27 22:15:12 +00001/*
2 *
3 * Copyright (c) International Business Machines Corp., 2001
Cyril Hrubisae02b422014-05-05 17:57:54 +02004 * 07/2001 Ported by Wayne Boyer
plars865695b2001-08-27 22:15:12 +00005 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
14 * the GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
Cyril Hrubisae02b422014-05-05 17:57:54 +020017 * along with this program; if not, write to the Free Software Foundation,
18 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
plars865695b2001-08-27 22:15:12 +000019 */
plars865695b2001-08-27 22:15:12 +000020/*
plars865695b2001-08-27 22:15:12 +000021 * Test Description :
22 * Verify that,
23 * 1) readlink(2) returns -1 and sets errno to EACCES if search/write
24 * permission is denied in the directory where the symbolic link
25 * resides.
26 * 2) readlink(2) returns -1 and sets errno to EINVAL if the buffer size
27 * is not positive.
28 * 3) readlink(2) returns -1 and sets errno to EINVAL if the specified
29 * file is not a symbolic link file.
subrata_modak4bb656a2009-02-26 12:02:09 +000030 * 4) readlink(2) returns -1 and sets errno to ENAMETOOLONG if the
plars865695b2001-08-27 22:15:12 +000031 * pathname component of symbolic link is too long (ie, > PATH_MAX).
32 * 5) readlink(2) returns -1 and sets errno to ENOENT if the component of
33 * symbolic link points to an empty string.
Xing Gu74931692014-03-31 18:26:25 +080034 * 6) readlink(2) returns -1 and sets errno to ENOTDIR if a component of
35 * the path prefix is not a directory.
36 * 7) readlink(2) returns -1 and sets errno to ELOOP if too many symbolic
37 * links were encountered in translating the pathname.
plars865695b2001-08-27 22:15:12 +000038 */
39
40#include <stdio.h>
41#include <sys/types.h>
42#include <sys/fcntl.h>
43#include <errno.h>
44#include <string.h>
45#include <signal.h>
46#include <sys/stat.h>
robbiew20e8ec62001-09-10 21:15:02 +000047#include <pwd.h>
plars865695b2001-08-27 22:15:12 +000048
49#include "test.h"
Cyril Hrubisae02b422014-05-05 17:57:54 +020050#include "safe_macros.h"
plars865695b2001-08-27 22:15:12 +000051
Cyril Hrubisae02b422014-05-05 17:57:54 +020052#define MODE_RWX (S_IRWXU | S_IRWXG | S_IRWXO)
53#define FILE_MODE (S_IRUSR | S_IRGRP | S_IROTH)
54#define DIR_TEMP "testdir_1"
55#define TEST_FILE1 "testdir_1/tfile_1"
plars865695b2001-08-27 22:15:12 +000056#define SYM_FILE1 "testdir_1/sfile_1"
Cyril Hrubisae02b422014-05-05 17:57:54 +020057#define TEST_FILE2 "tfile_2"
plars865695b2001-08-27 22:15:12 +000058#define SYM_FILE2 "sfile_2"
Xing Gu74931692014-03-31 18:26:25 +080059#define TEST_FILE3 "tfile_3"
60#define SYM_FILE3 "tfile_3/sfile_3"
61#define ELOOPFILE "/test_eloop"
plars865695b2001-08-27 22:15:12 +000062#define MAX_SIZE 256
63
Cyril Hrubisae02b422014-05-05 17:57:54 +020064static char longpathname[PATH_MAX + 2];
Xing Gu74931692014-03-31 18:26:25 +080065static char elooppathname[sizeof(ELOOPFILE) * 43] = ".";
plars865695b2001-08-27 22:15:12 +000066
Cyril Hrubisae02b422014-05-05 17:57:54 +020067static struct test_case_t {
plars865695b2001-08-27 22:15:12 +000068 char *link;
Cyril Hrubisae02b422014-05-05 17:57:54 +020069 size_t buf_size;
plars865695b2001-08-27 22:15:12 +000070 int exp_errno;
Cyril Hrubisae02b422014-05-05 17:57:54 +020071} test_cases[] = {
72 {SYM_FILE1, 1, EACCES},
subrata_modak56207ce2009-03-23 13:35:39 +000073 /* Don't test with bufsize -1, since this cause a fortify-check-fail when
74 using glibc and -D_FORITY_SOURCE=2
subrata_modak98559462008-11-18 10:18:41 +000075
subrata_modak56207ce2009-03-23 13:35:39 +000076 Discussion: http://lkml.org/lkml/2008/10/23/229
77 Conclusion: Only test with 0 as non-positive bufsize.
78
Cyril Hrubisae02b422014-05-05 17:57:54 +020079 { SYM_FILE2, -1, EINVAL, NULL },
subrata_modak56207ce2009-03-23 13:35:39 +000080 */
Cyril Hrubisae02b422014-05-05 17:57:54 +020081 {SYM_FILE2, 0, EINVAL},
82 {TEST_FILE2, 1, EINVAL},
83 {longpathname, 1, ENAMETOOLONG},
84 {"", 1, ENOENT},
Xing Gu74931692014-03-31 18:26:25 +080085 {SYM_FILE3, 1, ENOTDIR},
86 {elooppathname, 1, ELOOP},
plars865695b2001-08-27 22:15:12 +000087};
88
Cyril Hrubisae02b422014-05-05 17:57:54 +020089static void setup(void);
90static void readlink_verify(struct test_case_t *);
91static void cleanup(void);
92
93char *TCID = "readlink03";
94int TST_TOTAL = ARRAY_SIZE(test_cases);
plars865695b2001-08-27 22:15:12 +000095
subrata_modak56207ce2009-03-23 13:35:39 +000096int main(int ac, char **av)
plars865695b2001-08-27 22:15:12 +000097{
Cyril Hrubisae02b422014-05-05 17:57:54 +020098 int i, lc;
Cyril Hrubis0b9589f2014-05-27 17:40:33 +020099 const char *msg;
plars865695b2001-08-27 22:15:12 +0000100
Cyril Hrubisae02b422014-05-05 17:57:54 +0200101 msg = parse_opts(ac, av, NULL, NULL);
102 if (msg != NULL)
Garrett Cooper60fa8012010-11-22 13:50:58 -0800103 tst_brkm(TBROK, NULL, "OPTION PARSING ERROR - %s", msg);
plars865695b2001-08-27 22:15:12 +0000104
plars865695b2001-08-27 22:15:12 +0000105 setup();
106
plars865695b2001-08-27 22:15:12 +0000107 for (lc = 0; TEST_LOOPING(lc); lc++) {
Caspar Zhangd59a6592013-03-07 14:59:12 +0800108 tst_count = 0;
subrata_modakbdbaec52009-02-26 12:14:51 +0000109
Cyril Hrubisae02b422014-05-05 17:57:54 +0200110 for (i = 0; i < TST_TOTAL; i++)
111 readlink_verify(&test_cases[i]);
Garrett Cooper2c282152010-12-16 00:55:50 -0800112 }
113
plars865695b2001-08-27 22:15:12 +0000114 cleanup();
Garrett Cooper1e6f5a62010-12-19 09:58:10 -0800115 tst_exit();
Garrett Cooper2c282152010-12-16 00:55:50 -0800116}
plars865695b2001-08-27 22:15:12 +0000117
Mike Frysingerc57fba52014-04-09 18:56:30 -0400118void setup(void)
plars865695b2001-08-27 22:15:12 +0000119{
Cyril Hrubisae02b422014-05-05 17:57:54 +0200120 struct passwd *ltpuser;
Xing Gu74931692014-03-31 18:26:25 +0800121 int i;
plars865695b2001-08-27 22:15:12 +0000122
Cyril Hrubisae02b422014-05-05 17:57:54 +0200123 tst_require_root(NULL);
plars865695b2001-08-27 22:15:12 +0000124
plars865695b2001-08-27 22:15:12 +0000125 tst_sig(NOFORK, DEF_HANDLER, cleanup);
126
Cyril Hrubisae02b422014-05-05 17:57:54 +0200127 ltpuser = SAFE_GETPWNAM(cleanup, "nobody");
128 SAFE_SETEUID(cleanup, ltpuser->pw_uid);
129
plars865695b2001-08-27 22:15:12 +0000130 TEST_PAUSE;
131
plars865695b2001-08-27 22:15:12 +0000132 tst_tmpdir();
133
Cyril Hrubisae02b422014-05-05 17:57:54 +0200134 SAFE_MKDIR(cleanup, DIR_TEMP, MODE_RWX);
135 SAFE_TOUCH(cleanup, TEST_FILE1, 0666, NULL);
136 SAFE_SYMLINK(cleanup, TEST_FILE1, SYM_FILE1);
137 SAFE_CHMOD(cleanup, DIR_TEMP, FILE_MODE);
138
139 SAFE_TOUCH(cleanup, TEST_FILE2, 0666, NULL);
140 SAFE_SYMLINK(cleanup, TEST_FILE2, SYM_FILE2);
141
142 memset(longpathname, 'a', PATH_MAX + 1);
Xing Gu74931692014-03-31 18:26:25 +0800143
144 SAFE_TOUCH(cleanup, TEST_FILE3, 0666, NULL);
145
146 /*
147 * NOTE: the ELOOP test is written based on that the consecutive
148 * symlinks limit in kernel is hardwired to 40.
149 */
150 SAFE_MKDIR(cleanup, "test_eloop", MODE_RWX);
151 SAFE_SYMLINK(cleanup, "../test_eloop", "test_eloop/test_eloop");
152 for (i = 0; i < 43; i++)
153 strcat(elooppathname, ELOOPFILE);
plars865695b2001-08-27 22:15:12 +0000154}
155
Cyril Hrubisae02b422014-05-05 17:57:54 +0200156void readlink_verify(struct test_case_t *tc)
plars865695b2001-08-27 22:15:12 +0000157{
Cyril Hrubisae02b422014-05-05 17:57:54 +0200158 char buffer[MAX_SIZE];
159
160 if (tc->buf_size == 1)
161 tc->buf_size = sizeof(buffer);
162
163 TEST(readlink(tc->link, buffer, tc->buf_size));
164
165 if (TEST_RETURN != -1) {
166 tst_resm(TFAIL, "readlink() returned %ld, "
167 "expected -1, errno:%d", TEST_RETURN,
168 tc->exp_errno);
169 return;
170 }
171
Cyril Hrubisae02b422014-05-05 17:57:54 +0200172 if (TEST_ERRNO == tc->exp_errno) {
173 tst_resm(TPASS | TTERRNO, "readlink() failed as expected");
174 } else {
175 tst_resm(TFAIL | TTERRNO,
176 "readlink() failed unexpectedly; expected: %d - %s",
177 tc->exp_errno, strerror(tc->exp_errno));
178 if (tc->exp_errno == ENOENT && TEST_ERRNO == EINVAL) {
179 tst_resm(TWARN | TTERRNO,
180 "It may be a Kernel Bug, see the patch:"
181 "http://git.kernel.org/linus/1fa1e7f6");
182 }
183 }
plars865695b2001-08-27 22:15:12 +0000184}
185
Mike Frysingerc57fba52014-04-09 18:56:30 -0400186void cleanup(void)
plars865695b2001-08-27 22:15:12 +0000187{
Cyril Hrubisae02b422014-05-05 17:57:54 +0200188 if (seteuid(0) == -1)
189 tst_resm(TWARN | TERRNO, "seteuid(0) failed");
190
plars865695b2001-08-27 22:15:12 +0000191 tst_rmdir();
Nageswara R Sastry0cc75142011-09-12 17:17:27 +0530192}