fchownat02.c revision 605fa3362fd7cef0baa2131be32cf44661783d3e
1/* 2 * Copyright (c) 2014 Fujitsu Ltd. 3 * Author: Zeng Linggang <zenglg.jy@cn.fujitsu.com> 4 * 5 * This program is free software; you can redistribute it and/or modify it 6 * under the terms of version 2 of the GNU General Public License as 7 * published by the Free Software Foundation. 8 * 9 * This program is distributed in the hope that it would be useful, but 10 * WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 12 * 13 * You should have received a copy of the GNU General Public License along 14 * with this program. 15 */ 16/* 17 * Test Description: 18 * Verify that, 19 * The flag of fchownat() is AT_SYMLINK_NOFOLLOW and the pathname would 20 * not be dereferenced if the pathname is a symbolic link. 21 */ 22 23#define _GNU_SOURCE 24 25#include <sys/types.h> 26#include <sys/stat.h> 27#include <fcntl.h> 28#include <unistd.h> 29#include <error.h> 30#include <stdlib.h> 31#include <errno.h> 32#include <string.h> 33#include <signal.h> 34#include "test.h" 35#include "usctest.h" 36#include "safe_macros.h" 37#include "fchownat.h" 38#include "lapi/fcntl.h" 39 40#define TESTFILE "testfile" 41#define TESTFILE_LINK "testfile_link" 42 43char *TCID = "fchownat02"; 44int TST_TOTAL = 1; 45 46static int dirfd; 47static uid_t set_uid = 1000; 48static gid_t set_gid = 1000; 49static void setup(void); 50static void cleanup(void); 51static void test_verify(void); 52static void fchownat_verify(void); 53 54int main(int ac, char **av) 55{ 56 int lc; 57 const char *msg; 58 int i; 59 60 msg = parse_opts(ac, av, NULL, NULL); 61 if (msg != NULL) 62 tst_brkm(TBROK, NULL, "OPTION PARSING ERROR - %s", msg); 63 64 setup(); 65 66 for (lc = 0; TEST_LOOPING(lc); lc++) { 67 tst_count = 0; 68 for (i = 0; i < TST_TOTAL; i++) 69 fchownat_verify(); 70 } 71 72 cleanup(); 73 tst_exit(); 74} 75 76static void setup(void) 77{ 78 struct stat c_buf, l_buf; 79 80 if ((tst_kvercmp(2, 6, 16)) < 0) 81 tst_brkm(TCONF, NULL, "This test needs kernel 2.6.16 or newer"); 82 83 tst_require_root(NULL); 84 85 tst_sig(NOFORK, DEF_HANDLER, cleanup); 86 87 TEST_PAUSE; 88 89 tst_tmpdir(); 90 91 dirfd = SAFE_OPEN(cleanup, "./", O_DIRECTORY); 92 93 SAFE_TOUCH(cleanup, TESTFILE, 0600, NULL); 94 95 SAFE_SYMLINK(cleanup, TESTFILE, TESTFILE_LINK); 96 97 SAFE_STAT(cleanup, TESTFILE_LINK, &c_buf); 98 99 SAFE_LSTAT(cleanup, TESTFILE_LINK, &l_buf); 100 101 if (l_buf.st_uid == set_uid || l_buf.st_gid == set_gid) { 102 tst_brkm(TBROK | TERRNO, cleanup, 103 "link_uid(%d) == set_uid(%d) or link_gid(%d) == " 104 "set_gid(%d)", l_buf.st_uid, set_uid, l_buf.st_gid, 105 set_gid); 106 } 107} 108 109static void fchownat_verify(void) 110{ 111 TEST(fchownat(dirfd, TESTFILE_LINK, set_uid, set_gid, 112 AT_SYMLINK_NOFOLLOW)); 113 114 if (TEST_RETURN != 0) { 115 tst_resm(TFAIL | TTERRNO, "fchownat() failed, errno=%d : %s", 116 TEST_ERRNO, strerror(TEST_ERRNO)); 117 } else { 118 test_verify(); 119 } 120} 121 122static void test_verify(void) 123{ 124 struct stat c_buf, l_buf; 125 126 SAFE_STAT(cleanup, TESTFILE_LINK, &c_buf); 127 128 SAFE_LSTAT(cleanup, TESTFILE_LINK, &l_buf); 129 130 if (c_buf.st_uid != set_uid && l_buf.st_uid == set_uid && 131 c_buf.st_gid != set_gid && l_buf.st_gid == set_gid) { 132 tst_resm(TPASS, "fchownat() test AT_SYMLINK_NOFOLLOW success"); 133 } else { 134 tst_resm(TFAIL, 135 "fchownat() test AT_SYMLINK_NOFOLLOW fail with uid=%d " 136 "link_uid=%d set_uid=%d | gid=%d link_gid=%d " 137 "set_gid=%d", c_buf.st_uid, l_buf.st_uid, set_uid, 138 c_buf.st_gid, l_buf.st_gid, set_gid); 139 } 140} 141 142static void cleanup(void) 143{ 144 tst_rmdir(); 145} 146