1f08c3bdfSopenharmony_ci/* 2f08c3bdfSopenharmony_ci * Copyright (c) International Business Machines Corp., 2000 3f08c3bdfSopenharmony_ci * Copyright (c) 2010 Cyril Hrubis chrubis@suse.cz 4f08c3bdfSopenharmony_ci * 5f08c3bdfSopenharmony_ci * This program is free software; you can redistribute it and/or modify 6f08c3bdfSopenharmony_ci * it under the terms of the GNU General Public License as published by 7f08c3bdfSopenharmony_ci * the Free Software Foundation; either version 2 of the License, or 8f08c3bdfSopenharmony_ci * (at your option) any later version. 9f08c3bdfSopenharmony_ci * 10f08c3bdfSopenharmony_ci * This program is distributed in the hope that it will be useful, 11f08c3bdfSopenharmony_ci * but WITHOUT ANY WARRANTY; without even the implied warranty of 12f08c3bdfSopenharmony_ci * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See 13f08c3bdfSopenharmony_ci * the GNU General Public License for more details. 14f08c3bdfSopenharmony_ci * 15f08c3bdfSopenharmony_ci * You should have received a copy of the GNU General Public License 16f08c3bdfSopenharmony_ci * along with this program; if not, write to the Free Software 17f08c3bdfSopenharmony_ci * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 18f08c3bdfSopenharmony_ci */ 19f08c3bdfSopenharmony_ci 20f08c3bdfSopenharmony_ci/* 21f08c3bdfSopenharmony_ci * FILE(s) : fs_perms.c simpletest.sh textx.o Makefile README 22f08c3bdfSopenharmony_ci * DESCRIPTION : Regression test for Linux filesystem permissions. 23f08c3bdfSopenharmony_ci * AUTHOR : Jeff Martin (martinjn@us.ibm.com) 24f08c3bdfSopenharmony_ci * HISTORY : 25f08c3bdfSopenharmony_ci * (04/12/01)v.99 First attempt at using C for fs-regression test. Only tests read and write bits. 26f08c3bdfSopenharmony_ci * (04/19/01)v1.0 Added test for execute bit. 27f08c3bdfSopenharmony_ci * (05/23/01)v1.1 Added command line parameter to specify test file. 28f08c3bdfSopenharmony_ci * (07/12/01)v1.2 Removed conf file and went to command line parameters. 29f08c3bdfSopenharmony_ci * (10/19/04) Rewritten to fit ltp test interface. 30f08c3bdfSopenharmony_ci * Also now we try to run two different files, one is executed by execl, 31f08c3bdfSopenharmony_ci * has shebang and should end up executed by kernel, other one is empty 32f08c3bdfSopenharmony_ci * is executed by execlp and should end up executed by libc. 33f08c3bdfSopenharmony_ci */ 34f08c3bdfSopenharmony_ci 35f08c3bdfSopenharmony_ci#include <stdio.h> 36f08c3bdfSopenharmony_ci#include <string.h> 37f08c3bdfSopenharmony_ci#include <ctype.h> 38f08c3bdfSopenharmony_ci#include <sys/stat.h> 39f08c3bdfSopenharmony_ci#include <sys/types.h> 40f08c3bdfSopenharmony_ci#include <stdlib.h> 41f08c3bdfSopenharmony_ci#include <unistd.h> 42f08c3bdfSopenharmony_ci#include <sys/wait.h> 43f08c3bdfSopenharmony_ci#include <linux/limits.h> 44f08c3bdfSopenharmony_ci 45f08c3bdfSopenharmony_ci#include "test.h" 46f08c3bdfSopenharmony_ci 47f08c3bdfSopenharmony_ci#define TEST_FILE_NAME1 "./test.file1" 48f08c3bdfSopenharmony_ci#define TEST_FILE_NAME2 "./test.file2" 49f08c3bdfSopenharmony_ci 50f08c3bdfSopenharmony_cichar *TCID = "fs_perms"; 51f08c3bdfSopenharmony_ciint TST_TOTAL = 1; 52f08c3bdfSopenharmony_ci 53f08c3bdfSopenharmony_cistatic void cleanup(void) 54f08c3bdfSopenharmony_ci{ 55f08c3bdfSopenharmony_ci seteuid(0); 56f08c3bdfSopenharmony_ci setegid(0); 57f08c3bdfSopenharmony_ci 58f08c3bdfSopenharmony_ci tst_rmdir(); 59f08c3bdfSopenharmony_ci 60f08c3bdfSopenharmony_ci} 61f08c3bdfSopenharmony_ci 62f08c3bdfSopenharmony_ci/* 63f08c3bdfSopenharmony_ci * Create file and set permissions, user id, group id. 64f08c3bdfSopenharmony_ci * 65f08c3bdfSopenharmony_ci * If flag is non zero, the file contains #!/PATH/sh shebang otherwise it's 66f08c3bdfSopenharmony_ci * empty. 67f08c3bdfSopenharmony_ci */ 68f08c3bdfSopenharmony_cistatic void testsetup(const char *file_name, int flag, mode_t mode, 69f08c3bdfSopenharmony_ci int user_id, int group_id) 70f08c3bdfSopenharmony_ci{ 71f08c3bdfSopenharmony_ci FILE *file; 72f08c3bdfSopenharmony_ci 73f08c3bdfSopenharmony_ci file = fopen(file_name, "w"); 74f08c3bdfSopenharmony_ci 75f08c3bdfSopenharmony_ci if (file == NULL) 76f08c3bdfSopenharmony_ci tst_brkm(TBROK | TERRNO, cleanup, 77f08c3bdfSopenharmony_ci "Could not create test file %s.", file_name); 78f08c3bdfSopenharmony_ci 79f08c3bdfSopenharmony_ci /* create file with shebang */ 80f08c3bdfSopenharmony_ci if (flag) { 81f08c3bdfSopenharmony_ci char buf[PATH_MAX]; 82f08c3bdfSopenharmony_ci 83f08c3bdfSopenharmony_ci if (tst_get_path("sh", buf, PATH_MAX)) 84f08c3bdfSopenharmony_ci tst_brkm(TBROK, cleanup, 85f08c3bdfSopenharmony_ci "Could not find path to sh in $PATH."); 86f08c3bdfSopenharmony_ci 87f08c3bdfSopenharmony_ci if (fprintf(file, "#!%s\n", buf) < 0) 88f08c3bdfSopenharmony_ci tst_brkm(TBROK, cleanup, "Calling fprintf failed."); 89f08c3bdfSopenharmony_ci } 90f08c3bdfSopenharmony_ci 91f08c3bdfSopenharmony_ci if (fclose(file)) 92f08c3bdfSopenharmony_ci tst_brkm(TBROK | TERRNO, cleanup, "Calling fclose failed."); 93f08c3bdfSopenharmony_ci 94f08c3bdfSopenharmony_ci if (chmod(file_name, mode)) 95f08c3bdfSopenharmony_ci tst_brkm(TBROK | TERRNO, cleanup, 96f08c3bdfSopenharmony_ci "Could not chmod test file %s.", file_name); 97f08c3bdfSopenharmony_ci 98f08c3bdfSopenharmony_ci if (chown(file_name, user_id, group_id)) 99f08c3bdfSopenharmony_ci tst_brkm(TBROK | TERRNO, cleanup, 100f08c3bdfSopenharmony_ci "Could not chown test file %s.", file_name); 101f08c3bdfSopenharmony_ci} 102f08c3bdfSopenharmony_ci 103f08c3bdfSopenharmony_ci/* 104f08c3bdfSopenharmony_ci * Test permissions. 105f08c3bdfSopenharmony_ci */ 106f08c3bdfSopenharmony_cistatic int testfperm(const char *file_name, int flag, int user_id, 107f08c3bdfSopenharmony_ci int group_id, char *fperm) 108f08c3bdfSopenharmony_ci{ 109f08c3bdfSopenharmony_ci FILE *file; 110f08c3bdfSopenharmony_ci int status; 111f08c3bdfSopenharmony_ci 112f08c3bdfSopenharmony_ci switch (fork()) { 113f08c3bdfSopenharmony_ci case 0: 114f08c3bdfSopenharmony_ci if (setgid(group_id)) 115f08c3bdfSopenharmony_ci tst_brkm(TBROK | TERRNO, cleanup, 116f08c3bdfSopenharmony_ci "Could not setgid to %d.", group_id); 117f08c3bdfSopenharmony_ci 118f08c3bdfSopenharmony_ci if (setuid(user_id)) 119f08c3bdfSopenharmony_ci tst_brkm(TBROK | TERRNO, cleanup, 120f08c3bdfSopenharmony_ci "Could not setuid to %d.", user_id); 121f08c3bdfSopenharmony_ci 122f08c3bdfSopenharmony_ci switch (tolower(fperm[0])) { 123f08c3bdfSopenharmony_ci case 'x': 124f08c3bdfSopenharmony_ci 125f08c3bdfSopenharmony_ci /* 126f08c3bdfSopenharmony_ci * execlp runs file with sh in case kernel has 127f08c3bdfSopenharmony_ci * no binmft handler for it, execl does not. 128f08c3bdfSopenharmony_ci */ 129f08c3bdfSopenharmony_ci if (flag) 130f08c3bdfSopenharmony_ci execl(file_name, file_name, NULL); 131f08c3bdfSopenharmony_ci else 132f08c3bdfSopenharmony_ci execlp(file_name, "test", NULL); 133f08c3bdfSopenharmony_ci 134f08c3bdfSopenharmony_ci exit(1); 135f08c3bdfSopenharmony_ci break; 136f08c3bdfSopenharmony_ci default: 137f08c3bdfSopenharmony_ci if ((file = fopen(file_name, fperm)) != NULL) { 138f08c3bdfSopenharmony_ci fclose(file); 139f08c3bdfSopenharmony_ci exit(0); 140f08c3bdfSopenharmony_ci } 141f08c3bdfSopenharmony_ci exit(1); 142f08c3bdfSopenharmony_ci break; 143f08c3bdfSopenharmony_ci } 144f08c3bdfSopenharmony_ci break; 145f08c3bdfSopenharmony_ci case -1: 146f08c3bdfSopenharmony_ci tst_brkm(TBROK | TERRNO, cleanup, "fork failed"); 147f08c3bdfSopenharmony_ci break; 148f08c3bdfSopenharmony_ci default: 149f08c3bdfSopenharmony_ci break; 150f08c3bdfSopenharmony_ci } 151f08c3bdfSopenharmony_ci 152f08c3bdfSopenharmony_ci wait(&status); 153f08c3bdfSopenharmony_ci 154f08c3bdfSopenharmony_ci return WEXITSTATUS(status); 155f08c3bdfSopenharmony_ci} 156f08c3bdfSopenharmony_ci 157f08c3bdfSopenharmony_cistatic void print_usage(const char *bname) 158f08c3bdfSopenharmony_ci{ 159f08c3bdfSopenharmony_ci char *usage = "<file mode> <file UID> <file GID> " 160f08c3bdfSopenharmony_ci "<tester UID> <tester GID> <permission " 161f08c3bdfSopenharmony_ci "to test r|w|x> <expected result 0|1>"; 162f08c3bdfSopenharmony_ci 163f08c3bdfSopenharmony_ci printf("Usage: %s %s\n", bname, usage); 164f08c3bdfSopenharmony_ci} 165f08c3bdfSopenharmony_ci 166f08c3bdfSopenharmony_cistatic long str_to_l(const char *str, const char *name, int base) 167f08c3bdfSopenharmony_ci{ 168f08c3bdfSopenharmony_ci char *end; 169f08c3bdfSopenharmony_ci long i = strtol(str, &end, base); 170f08c3bdfSopenharmony_ci 171f08c3bdfSopenharmony_ci if (*end != '\0') 172f08c3bdfSopenharmony_ci tst_brkm(TBROK, NULL, "Invalid parameter '%s' passed. (%s)", 173f08c3bdfSopenharmony_ci name, str); 174f08c3bdfSopenharmony_ci 175f08c3bdfSopenharmony_ci return i; 176f08c3bdfSopenharmony_ci} 177f08c3bdfSopenharmony_ci 178f08c3bdfSopenharmony_ciint main(int argc, char *argv[]) 179f08c3bdfSopenharmony_ci{ 180f08c3bdfSopenharmony_ci char *fperm; 181f08c3bdfSopenharmony_ci gid_t fgroup_id, group_id; 182f08c3bdfSopenharmony_ci uid_t fuser_id, user_id; 183f08c3bdfSopenharmony_ci mode_t fmode; 184f08c3bdfSopenharmony_ci int exp_res; 185f08c3bdfSopenharmony_ci int res1, res2 = 1; 186f08c3bdfSopenharmony_ci 187f08c3bdfSopenharmony_ci tst_require_root(); 188f08c3bdfSopenharmony_ci 189f08c3bdfSopenharmony_ci if (argc != 8) { 190f08c3bdfSopenharmony_ci print_usage(argv[0]); 191f08c3bdfSopenharmony_ci tst_exit(); 192f08c3bdfSopenharmony_ci } 193f08c3bdfSopenharmony_ci 194f08c3bdfSopenharmony_ci if (strlen(argv[6]) > 1) { 195f08c3bdfSopenharmony_ci print_usage(argv[0]); 196f08c3bdfSopenharmony_ci tst_exit(); 197f08c3bdfSopenharmony_ci } 198f08c3bdfSopenharmony_ci 199f08c3bdfSopenharmony_ci fmode = str_to_l(argv[1], "file mode", 8); 200f08c3bdfSopenharmony_ci fuser_id = str_to_l(argv[2], "file uid", 10); 201f08c3bdfSopenharmony_ci fgroup_id = str_to_l(argv[3], "file gid", 10); 202f08c3bdfSopenharmony_ci user_id = str_to_l(argv[4], "tester uid", 10); 203f08c3bdfSopenharmony_ci group_id = str_to_l(argv[5], "tester gid", 10); 204f08c3bdfSopenharmony_ci fperm = argv[6]; 205f08c3bdfSopenharmony_ci exp_res = str_to_l(argv[7], "expected result", 10); 206f08c3bdfSopenharmony_ci 207f08c3bdfSopenharmony_ci tst_tmpdir(); 208f08c3bdfSopenharmony_ci testsetup(TEST_FILE_NAME1, 0, fmode, fuser_id, fgroup_id); 209f08c3bdfSopenharmony_ci 210f08c3bdfSopenharmony_ci /* more tests for 'x' flag */ 211f08c3bdfSopenharmony_ci if (tolower(fperm[0]) == 'x') { 212f08c3bdfSopenharmony_ci testsetup(TEST_FILE_NAME2, 1, fmode, fuser_id, fgroup_id); 213f08c3bdfSopenharmony_ci res2 = testfperm(TEST_FILE_NAME2, 1, user_id, group_id, fperm); 214f08c3bdfSopenharmony_ci 215f08c3bdfSopenharmony_ci if (res2 == exp_res) 216f08c3bdfSopenharmony_ci res2 = 1; 217f08c3bdfSopenharmony_ci else 218f08c3bdfSopenharmony_ci res2 = 0; 219f08c3bdfSopenharmony_ci } 220f08c3bdfSopenharmony_ci 221f08c3bdfSopenharmony_ci res1 = testfperm(TEST_FILE_NAME1, 0, user_id, group_id, fperm); 222f08c3bdfSopenharmony_ci 223f08c3bdfSopenharmony_ci tst_resm((exp_res == res1) && res2 ? TPASS : TFAIL, 224f08c3bdfSopenharmony_ci "%c a %03o file owned by (%d/%d) as user/group (%d/%d)", 225f08c3bdfSopenharmony_ci fperm[0], fmode, fuser_id, fgroup_id, user_id, group_id); 226f08c3bdfSopenharmony_ci tst_rmdir(); 227f08c3bdfSopenharmony_ci tst_exit(); 228f08c3bdfSopenharmony_ci} 229