1 /* 2 * Copyright (c) 2017 Fujitsu Ltd. 3 * Author: Xiao Yang <yangx.jy@cn.fujitsu.com> 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 the 13 * 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, see <http://www.gnu.org/licenses/>.* 17 */ 18 19 /* 20 * This is a regression test for the race between getting an existing 21 * xattr and setting/removing a large xattr. This bug leads to that 22 * getxattr() fails to get an existing xattr and returns ENOATTR in xfs 23 * filesystem. 24 * 25 * Thie bug has been fixed in: 26 * 27 * commit 5a93790d4e2df73e30c965ec6e49be82fc3ccfce 28 * Author: Brian Foster <bfoster@redhat.com> 29 * Date: Wed Jan 25 07:53:43 2017 -0800 30 * 31 * xfs: remove racy hasattr check from attr ops 32 */ 33 34 #include "config.h" 35 #include <errno.h> 36 #include <sys/types.h> 37 #include <string.h> 38 #include <stdlib.h> 39 #include <signal.h> 40 41 #ifdef HAVE_SYS_XATTR_H 42 # include <sys/xattr.h> 43 #endif 44 45 #include "tst_test.h" 46 47 #ifdef HAVE_SYS_XATTR_H 48 49 #define MNTPOINT "mntpoint" 50 #define TEST_FILE MNTPOINT "/file" 51 #define TRUSTED_BIG "trusted.big" 52 #define TRUSTED_SMALL "trusted.small" 53 54 static volatile int end; 55 static char big_value[512]; 56 static char small_value[32]; 57 58 static void sigproc(int sig) 59 { 60 end = sig; 61 } 62 63 static void loop_getxattr(void) 64 { 65 int res; 66 67 while (!end) { 68 res = getxattr(TEST_FILE, TRUSTED_SMALL, NULL, 0); 69 if (res == -1) { 70 if (errno == ENODATA) { 71 tst_res(TFAIL, "getxattr() failed to get an " 72 "existing attribute"); 73 } else { 74 tst_res(TFAIL | TERRNO, 75 "getxattr() failed without ENOATTR"); 76 } 77 78 exit(0); 79 } 80 } 81 82 tst_res(TPASS, "getxattr() succeeded to get an existing attribute"); 83 exit(0); 84 } 85 86 static void verify_getxattr(void) 87 { 88 pid_t pid; 89 int n; 90 91 end = 0; 92 93 pid = SAFE_FORK(); 94 if (!pid) 95 loop_getxattr(); 96 97 for (n = 0; n < 99; n++) { 98 SAFE_SETXATTR(TEST_FILE, TRUSTED_BIG, big_value, 99 sizeof(big_value), XATTR_CREATE); 100 SAFE_REMOVEXATTR(TEST_FILE, TRUSTED_BIG); 101 } 102 103 kill(pid, SIGUSR1); 104 tst_reap_children(); 105 } 106 107 static void setup(void) 108 { 109 SAFE_SIGNAL(SIGUSR1, sigproc); 110 111 SAFE_TOUCH(TEST_FILE, 0644, NULL); 112 113 memset(big_value, 'a', sizeof(big_value)); 114 memset(small_value, 'a', sizeof(small_value)); 115 116 SAFE_SETXATTR(TEST_FILE, TRUSTED_SMALL, small_value, 117 sizeof(small_value), XATTR_CREATE); 118 } 119 120 static struct tst_test test = { 121 .needs_tmpdir = 1, 122 .needs_root = 1, 123 .mount_device = 1, 124 .dev_fs_type = "xfs", 125 .mntpoint = MNTPOINT, 126 .forks_child = 1, 127 .test_all = verify_getxattr, 128 .setup = setup 129 }; 130 131 #else /* HAVE_SYS_XATTR_H */ 132 TST_TEST_TCONF("<sys/xattr.h> does not exist."); 133 #endif 134