fchownat02.c revision d1e794d62b1bf619df8390535e4c2a58899b1145
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 "safe_macros.h" 36#include "fchownat.h" 37#include "lapi/fcntl.h" 38 39#define TESTFILE "testfile" 40#define TESTFILE_LINK "testfile_link" 41 42char *TCID = "fchownat02"; 43int TST_TOTAL = 1; 44 45static int dir_fd; 46static uid_t set_uid = 1000; 47static gid_t set_gid = 1000; 48static void setup(void); 49static void cleanup(void); 50static void test_verify(void); 51static void fchownat_verify(void); 52 53int main(int ac, char **av) 54{ 55 int lc; 56 int i; 57 58 tst_parse_opts(ac, av, NULL, NULL); 59 60 setup(); 61 62 for (lc = 0; TEST_LOOPING(lc); lc++) { 63 tst_count = 0; 64 for (i = 0; i < TST_TOTAL; i++) 65 fchownat_verify(); 66 } 67 68 cleanup(); 69 tst_exit(); 70} 71 72static void setup(void) 73{ 74 struct stat c_buf, l_buf; 75 76 if ((tst_kvercmp(2, 6, 16)) < 0) 77 tst_brkm(TCONF, NULL, "This test needs kernel 2.6.16 or newer"); 78 79 tst_require_root(); 80 81 tst_sig(NOFORK, DEF_HANDLER, cleanup); 82 83 TEST_PAUSE; 84 85 tst_tmpdir(); 86 87 dir_fd = SAFE_OPEN(cleanup, "./", O_DIRECTORY); 88 89 SAFE_TOUCH(cleanup, TESTFILE, 0600, NULL); 90 91 SAFE_SYMLINK(cleanup, TESTFILE, TESTFILE_LINK); 92 93 SAFE_STAT(cleanup, TESTFILE_LINK, &c_buf); 94 95 SAFE_LSTAT(cleanup, TESTFILE_LINK, &l_buf); 96 97 if (l_buf.st_uid == set_uid || l_buf.st_gid == set_gid) { 98 tst_brkm(TBROK | TERRNO, cleanup, 99 "link_uid(%d) == set_uid(%d) or link_gid(%d) == " 100 "set_gid(%d)", l_buf.st_uid, set_uid, l_buf.st_gid, 101 set_gid); 102 } 103} 104 105static void fchownat_verify(void) 106{ 107 TEST(fchownat(dir_fd, TESTFILE_LINK, set_uid, set_gid, 108 AT_SYMLINK_NOFOLLOW)); 109 110 if (TEST_RETURN != 0) { 111 tst_resm(TFAIL | TTERRNO, "fchownat() failed, errno=%d : %s", 112 TEST_ERRNO, strerror(TEST_ERRNO)); 113 } else { 114 test_verify(); 115 } 116} 117 118static void test_verify(void) 119{ 120 struct stat c_buf, l_buf; 121 122 SAFE_STAT(cleanup, TESTFILE_LINK, &c_buf); 123 124 SAFE_LSTAT(cleanup, TESTFILE_LINK, &l_buf); 125 126 if (c_buf.st_uid != set_uid && l_buf.st_uid == set_uid && 127 c_buf.st_gid != set_gid && l_buf.st_gid == set_gid) { 128 tst_resm(TPASS, "fchownat() test AT_SYMLINK_NOFOLLOW success"); 129 } else { 130 tst_resm(TFAIL, 131 "fchownat() test AT_SYMLINK_NOFOLLOW fail with uid=%d " 132 "link_uid=%d set_uid=%d | gid=%d link_gid=%d " 133 "set_gid=%d", c_buf.st_uid, l_buf.st_uid, set_uid, 134 c_buf.st_gid, l_buf.st_gid, set_gid); 135 } 136} 137 138static void cleanup(void) 139{ 140 tst_rmdir(); 141} 142