115 lines
2.3 KiB
C
115 lines
2.3 KiB
C
// SPDX-License-Identifier: GPL-2.0
|
|
/*
|
|
* Copyright (c) 2021 SUSE LLC
|
|
*/
|
|
/*\
|
|
* [Description]
|
|
*
|
|
* - First check close_range works on a valid range.
|
|
* - Then check close_range does not accept invalid paramters.
|
|
* - Then check it accepts a large lower fd.
|
|
* - Finally check CLOEXEC works
|
|
*
|
|
*/
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include "tst_test.h"
|
|
#include "tst_clone.h"
|
|
#include "lapi/fcntl.h"
|
|
#include "lapi/close_range.h"
|
|
#include "lapi/clone.h"
|
|
|
|
static int try_close_range(int fd, int flags)
|
|
{
|
|
int res;
|
|
|
|
TEST(close_range(fd, fd, flags));
|
|
|
|
if (TST_RET == -1 && TST_ERR == EINVAL)
|
|
res = TCONF;
|
|
else if (TST_RET == -1)
|
|
res = TFAIL;
|
|
else
|
|
res = TPASS;
|
|
|
|
return res;
|
|
}
|
|
|
|
static void run(unsigned int n)
|
|
{
|
|
const struct tst_clone_args args = {
|
|
.flags = CLONE_FILES,
|
|
.exit_signal = SIGCHLD,
|
|
};
|
|
int fd = -1, res;
|
|
|
|
switch (n) {
|
|
case 0:
|
|
fd = SAFE_OPEN("/", O_PATH);
|
|
SAFE_DUP2(fd, 100);
|
|
|
|
TST_EXP_PASS(close_range(fd, 100, 0),
|
|
"close_range(%d, 100, 0)", fd);
|
|
TST_EXP_FAIL(fcntl(fd, F_GETFD), EBADF,
|
|
"fcntl(%d, F_GETFD)", fd);
|
|
TST_EXP_FAIL(fcntl(100, F_GETFD), EBADF);
|
|
break;
|
|
case 1:
|
|
TST_EXP_FAIL(close_range(4, 3, 0), EINVAL);
|
|
break;
|
|
case 2:
|
|
TST_EXP_FAIL(close_range(3, ~0U, ~0U), EINVAL);
|
|
break;
|
|
case 3:
|
|
TST_EXP_PASS(close_range(~0U, ~0U, 0));
|
|
break;
|
|
case 4:
|
|
fd = SAFE_OPEN("/", O_PATH);
|
|
|
|
res = try_close_range(fd, CLOSE_RANGE_CLOEXEC);
|
|
tst_res(res | TTERRNO,
|
|
"close_range(%d, %d, CLOSE_RANGE_CLOEXEC)", fd, fd);
|
|
|
|
if (res != TPASS)
|
|
break;
|
|
|
|
TST_EXP_FD_SILENT(fcntl(fd, F_GETFD), "fcntl(%d, F_GETFD)", fd);
|
|
if (TST_RET & FD_CLOEXEC)
|
|
tst_res(TPASS, "FD_CLOEXEC was set on %d", fd);
|
|
else
|
|
tst_res(TFAIL, "FD_CLOEXEC not set on %d", fd);
|
|
break;
|
|
case 5:
|
|
fd = SAFE_OPEN("/", O_PATH);
|
|
|
|
if (!SAFE_CLONE(&args)) {
|
|
res = try_close_range(fd, CLOSE_RANGE_UNSHARE);
|
|
tst_res(res | TTERRNO,
|
|
"close_range(%d, %d, CLOSE_RANGE_UNSHARE)",
|
|
fd, fd);
|
|
|
|
if (res != TPASS)
|
|
exit(0);
|
|
|
|
TST_EXP_FAIL(fcntl(fd, F_GETFD), EBADF,
|
|
"fcntl(%d, F_GETFD)", fd);
|
|
exit(0);
|
|
}
|
|
|
|
tst_reap_children();
|
|
|
|
TST_EXP_PASS(fcntl(fd, F_GETFD), "%d is open", fd);
|
|
}
|
|
|
|
if (fd > -1)
|
|
TST_EXP_PASS_SILENT(close_range(fd, fd, 0),
|
|
"close_range(%d, %d, 0)", fd, fd);
|
|
}
|
|
|
|
static struct tst_test test = {
|
|
.tcnt = 6,
|
|
.forks_child = 1,
|
|
.test = run,
|
|
};
|