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