1f08c3bdfSopenharmony_ci// SPDX-License-Identifier: GPL-2.0 2f08c3bdfSopenharmony_ci/* 3f08c3bdfSopenharmony_ci * Copyright (c) 2021 SUSE LLC 4f08c3bdfSopenharmony_ci */ 5f08c3bdfSopenharmony_ci/*\ 6f08c3bdfSopenharmony_ci * [Description] 7f08c3bdfSopenharmony_ci * 8f08c3bdfSopenharmony_ci * - First check close_range works on a valid range. 9f08c3bdfSopenharmony_ci * - Then check close_range does not accept invalid paramters. 10f08c3bdfSopenharmony_ci * - Then check it accepts a large lower fd. 11f08c3bdfSopenharmony_ci * - Finally check CLOEXEC works 12f08c3bdfSopenharmony_ci * 13f08c3bdfSopenharmony_ci */ 14f08c3bdfSopenharmony_ci 15f08c3bdfSopenharmony_ci#include <stdlib.h> 16f08c3bdfSopenharmony_ci 17f08c3bdfSopenharmony_ci#include "tst_test.h" 18f08c3bdfSopenharmony_ci#include "tst_clone.h" 19f08c3bdfSopenharmony_ci#include "lapi/fcntl.h" 20f08c3bdfSopenharmony_ci#include "lapi/close_range.h" 21f08c3bdfSopenharmony_ci#include "lapi/sched.h" 22f08c3bdfSopenharmony_ci 23f08c3bdfSopenharmony_cistatic int try_close_range(int fd, int flags) 24f08c3bdfSopenharmony_ci{ 25f08c3bdfSopenharmony_ci int res; 26f08c3bdfSopenharmony_ci 27f08c3bdfSopenharmony_ci TEST(close_range(fd, fd, flags)); 28f08c3bdfSopenharmony_ci 29f08c3bdfSopenharmony_ci if (TST_RET == -1 && TST_ERR == EINVAL) 30f08c3bdfSopenharmony_ci res = TCONF; 31f08c3bdfSopenharmony_ci else if (TST_RET == -1) 32f08c3bdfSopenharmony_ci res = TFAIL; 33f08c3bdfSopenharmony_ci else 34f08c3bdfSopenharmony_ci res = TPASS; 35f08c3bdfSopenharmony_ci 36f08c3bdfSopenharmony_ci return res; 37f08c3bdfSopenharmony_ci} 38f08c3bdfSopenharmony_ci 39f08c3bdfSopenharmony_cistatic void run(unsigned int n) 40f08c3bdfSopenharmony_ci{ 41f08c3bdfSopenharmony_ci const struct tst_clone_args args = { 42f08c3bdfSopenharmony_ci .flags = CLONE_FILES, 43f08c3bdfSopenharmony_ci .exit_signal = SIGCHLD, 44f08c3bdfSopenharmony_ci }; 45f08c3bdfSopenharmony_ci int fd = -1, res; 46f08c3bdfSopenharmony_ci 47f08c3bdfSopenharmony_ci switch (n) { 48f08c3bdfSopenharmony_ci case 0: 49f08c3bdfSopenharmony_ci fd = SAFE_OPEN("/", O_PATH); 50f08c3bdfSopenharmony_ci SAFE_DUP2(fd, 100); 51f08c3bdfSopenharmony_ci 52f08c3bdfSopenharmony_ci TST_EXP_PASS(close_range(fd, 100, 0), 53f08c3bdfSopenharmony_ci "close_range(%d, 100, 0)", fd); 54f08c3bdfSopenharmony_ci TST_EXP_FAIL(fcntl(fd, F_GETFD), EBADF, 55f08c3bdfSopenharmony_ci "fcntl(%d, F_GETFD)", fd); 56f08c3bdfSopenharmony_ci TST_EXP_FAIL(fcntl(100, F_GETFD), EBADF); 57f08c3bdfSopenharmony_ci break; 58f08c3bdfSopenharmony_ci case 1: 59f08c3bdfSopenharmony_ci TST_EXP_FAIL(close_range(4, 3, 0), EINVAL); 60f08c3bdfSopenharmony_ci break; 61f08c3bdfSopenharmony_ci case 2: 62f08c3bdfSopenharmony_ci TST_EXP_FAIL(close_range(3, ~0U, ~0U), EINVAL); 63f08c3bdfSopenharmony_ci break; 64f08c3bdfSopenharmony_ci case 3: 65f08c3bdfSopenharmony_ci TST_EXP_PASS(close_range(~0U, ~0U, 0)); 66f08c3bdfSopenharmony_ci break; 67f08c3bdfSopenharmony_ci case 4: 68f08c3bdfSopenharmony_ci fd = SAFE_OPEN("/", O_PATH); 69f08c3bdfSopenharmony_ci 70f08c3bdfSopenharmony_ci res = try_close_range(fd, CLOSE_RANGE_CLOEXEC); 71f08c3bdfSopenharmony_ci tst_res(res | TTERRNO, 72f08c3bdfSopenharmony_ci "close_range(%d, %d, CLOSE_RANGE_CLOEXEC)", fd, fd); 73f08c3bdfSopenharmony_ci 74f08c3bdfSopenharmony_ci if (res != TPASS) 75f08c3bdfSopenharmony_ci break; 76f08c3bdfSopenharmony_ci 77f08c3bdfSopenharmony_ci TST_EXP_FD_SILENT(fcntl(fd, F_GETFD), "fcntl(%d, F_GETFD)", fd); 78f08c3bdfSopenharmony_ci if (TST_RET & FD_CLOEXEC) 79f08c3bdfSopenharmony_ci tst_res(TPASS, "FD_CLOEXEC was set on %d", fd); 80f08c3bdfSopenharmony_ci else 81f08c3bdfSopenharmony_ci tst_res(TFAIL, "FD_CLOEXEC not set on %d", fd); 82f08c3bdfSopenharmony_ci break; 83f08c3bdfSopenharmony_ci case 5: 84f08c3bdfSopenharmony_ci fd = SAFE_OPEN("/", O_PATH); 85f08c3bdfSopenharmony_ci 86f08c3bdfSopenharmony_ci if (!SAFE_CLONE(&args)) { 87f08c3bdfSopenharmony_ci res = try_close_range(fd, CLOSE_RANGE_UNSHARE); 88f08c3bdfSopenharmony_ci tst_res(res | TTERRNO, 89f08c3bdfSopenharmony_ci "close_range(%d, %d, CLOSE_RANGE_UNSHARE)", 90f08c3bdfSopenharmony_ci fd, fd); 91f08c3bdfSopenharmony_ci 92f08c3bdfSopenharmony_ci if (res != TPASS) 93f08c3bdfSopenharmony_ci exit(0); 94f08c3bdfSopenharmony_ci 95f08c3bdfSopenharmony_ci TST_EXP_FAIL(fcntl(fd, F_GETFD), EBADF, 96f08c3bdfSopenharmony_ci "fcntl(%d, F_GETFD)", fd); 97f08c3bdfSopenharmony_ci exit(0); 98f08c3bdfSopenharmony_ci } 99f08c3bdfSopenharmony_ci 100f08c3bdfSopenharmony_ci tst_reap_children(); 101f08c3bdfSopenharmony_ci 102f08c3bdfSopenharmony_ci TST_EXP_PASS(fcntl(fd, F_GETFD), "%d is open", fd); 103f08c3bdfSopenharmony_ci } 104f08c3bdfSopenharmony_ci 105f08c3bdfSopenharmony_ci if (fd > -1) 106f08c3bdfSopenharmony_ci TST_EXP_PASS_SILENT(close_range(fd, fd, 0), 107f08c3bdfSopenharmony_ci "close_range(%d, %d, 0)", fd, fd); 108f08c3bdfSopenharmony_ci} 109f08c3bdfSopenharmony_ci 110f08c3bdfSopenharmony_cistatic struct tst_test test = { 111f08c3bdfSopenharmony_ci .tcnt = 6, 112f08c3bdfSopenharmony_ci .forks_child = 1, 113f08c3bdfSopenharmony_ci .test = run, 114f08c3bdfSopenharmony_ci .setup = close_range_supported_by_kernel, 115f08c3bdfSopenharmony_ci}; 116