Home | History | Annotate | Download | only in access
      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 Description:
     22  *  Verify that access() succeeds to check the existence or read/write/execute
     23  *  permissions on a file if the mode argument passed was F_OK/R_OK/W_OK/X_OK.
     24  *
     25  *  Also verify that, access() succeeds to test the accessibility of the file
     26  *  referred to by symbolic link if the pathname points to a symbolic link.
     27  *
     28  *  As well as verify that, these test files can be
     29  *  stat/read/written/executed indeed as root and nobody respectively.
     30  *
     31  *	07/2001 Ported by Wayne Boyera
     32  *	06/2016 Modified by Guangwen Feng <fenggw-fnst (at) cn.fujitsu.com>
     33  */
     34 
     35 #include <sys/types.h>
     36 #include <unistd.h>
     37 #include <errno.h>
     38 #include <pwd.h>
     39 #include <stdio.h>
     40 #include <stdlib.h>
     41 #include <paths.h>
     42 #include "tst_test.h"
     43 
     44 #define FNAME_F	"file_f"
     45 #define FNAME_R	"file_r"
     46 #define FNAME_W	"file_w"
     47 #define FNAME_X	"file_x"
     48 #define SNAME_F	"symlink_f"
     49 #define SNAME_R	"symlink_r"
     50 #define SNAME_W	"symlink_w"
     51 #define SNAME_X	"symlink_x"
     52 
     53 static uid_t uid;
     54 
     55 static struct tcase {
     56 	const char *pathname;
     57 	int mode;
     58 	char *name;
     59 	const char *targetname;
     60 } tcases[] = {
     61 	{FNAME_F, F_OK, "F_OK", FNAME_F},
     62 	{FNAME_R, R_OK, "R_OK", FNAME_R},
     63 	{FNAME_W, W_OK, "W_OK", FNAME_W},
     64 	{FNAME_X, X_OK, "X_OK", FNAME_X},
     65 	{SNAME_F, F_OK, "F_OK", FNAME_F},
     66 	{SNAME_R, R_OK, "R_OK", FNAME_R},
     67 	{SNAME_W, W_OK, "W_OK", FNAME_W},
     68 	{SNAME_X, X_OK, "X_OK", FNAME_X}
     69 };
     70 
     71 static void access_test(struct tcase *tc, const char *user)
     72 {
     73 	struct stat stat_buf;
     74 	char command[64];
     75 
     76 	TEST(access(tc->pathname, tc->mode));
     77 
     78 	if (TEST_RETURN == -1) {
     79 		tst_res(TFAIL | TTERRNO, "access(%s, %s) as %s failed",
     80 			tc->pathname, tc->name, user);
     81 		return;
     82 	}
     83 
     84 	switch (tc->mode) {
     85 	case F_OK:
     86 		/*
     87 		 * The specified file(or pointed to by symbolic link)
     88 		 * exists, attempt to get its status, if successful,
     89 		 * access() behaviour is correct.
     90 		 */
     91 		TEST(stat(tc->targetname, &stat_buf));
     92 
     93 		if (TEST_RETURN == -1) {
     94 			tst_res(TFAIL | TTERRNO, "stat(%s) as %s failed",
     95 				tc->targetname, user);
     96 			return;
     97 		}
     98 
     99 		break;
    100 	case R_OK:
    101 		/*
    102 		 * The specified file(or pointed to by symbolic link)
    103 		 * has read access, attempt to open the file with O_RDONLY,
    104 		 * if we get a valid fd, access() behaviour is correct.
    105 		 */
    106 		TEST(open(tc->targetname, O_RDONLY));
    107 
    108 		if (TEST_RETURN == -1) {
    109 			tst_res(TFAIL | TTERRNO,
    110 				"open %s with O_RDONLY as %s failed",
    111 				tc->targetname, user);
    112 			return;
    113 		}
    114 
    115 		SAFE_CLOSE(TEST_RETURN);
    116 
    117 		break;
    118 	case W_OK:
    119 		/*
    120 		 * The specified file(or pointed to by symbolic link)
    121 		 * has write access, attempt to open the file with O_WRONLY,
    122 		 * if we get a valid fd, access() behaviour is correct.
    123 		 */
    124 		TEST(open(tc->targetname, O_WRONLY));
    125 
    126 		if (TEST_RETURN == -1) {
    127 			tst_res(TFAIL | TTERRNO,
    128 				"open %s with O_WRONLY as %s failed",
    129 				tc->targetname, user);
    130 			return;
    131 		}
    132 
    133 		SAFE_CLOSE(TEST_RETURN);
    134 
    135 		break;
    136 	case X_OK:
    137 		/*
    138 		 * The specified file(or pointed to by symbolic link)
    139 		 * has execute access, attempt to execute the executable
    140 		 * file, if successful, access() behaviour is correct.
    141 		 */
    142 		sprintf(command, "./%s", tc->targetname);
    143 
    144 		TEST(system(command));
    145 
    146 		if (TEST_RETURN != 0) {
    147 			tst_res(TFAIL | TTERRNO, "execute %s as %s failed",
    148 				tc->targetname, user);
    149 			return;
    150 		}
    151 
    152 		break;
    153 	default:
    154 		break;
    155 	}
    156 
    157 	tst_res(TPASS, "access(%s, %s) as %s behaviour is correct.",
    158 		tc->pathname, tc->name, user);
    159 }
    160 
    161 static void verify_access(unsigned int n)
    162 {
    163 	struct tcase *tc = &tcases[n];
    164 	pid_t pid;
    165 
    166 	/* test as root */
    167 	access_test(tc, "root");
    168 
    169 	/* test as nobody */
    170 	pid = SAFE_FORK();
    171 	if (pid) {
    172 		SAFE_WAITPID(pid, NULL, 0);
    173 	} else {
    174 		SAFE_SETUID(uid);
    175 		access_test(tc, "nobody");
    176 	}
    177 }
    178 
    179 static void setup(void)
    180 {
    181 	struct passwd *pw;
    182 
    183 	pw = SAFE_GETPWNAM("nobody");
    184 
    185 	uid = pw->pw_uid;
    186 
    187 	SAFE_TOUCH(FNAME_F, 0000, NULL);
    188 	SAFE_TOUCH(FNAME_R, 0444, NULL);
    189 	SAFE_TOUCH(FNAME_W, 0222, NULL);
    190 	SAFE_TOUCH(FNAME_X, 0555, NULL);
    191 	SAFE_FILE_PRINTF(FNAME_X, "#!%s\n", _PATH_BSHELL);
    192 
    193 	SAFE_SYMLINK(FNAME_F, SNAME_F);
    194 	SAFE_SYMLINK(FNAME_R, SNAME_R);
    195 	SAFE_SYMLINK(FNAME_W, SNAME_W);
    196 	SAFE_SYMLINK(FNAME_X, SNAME_X);
    197 }
    198 
    199 static struct tst_test test = {
    200 	.tcnt = ARRAY_SIZE(tcases),
    201 	.needs_tmpdir = 1,
    202 	.needs_root = 1,
    203 	.forks_child = 1,
    204 	.setup = setup,
    205 	.test = verify_access,
    206 };
    207