mirror of
https://github.com/checkpoint-restore/criu
synced 2025-08-31 06:15:24 +00:00
zdtm: Cleanup file_fown test case (v2)
- add test for flags recovery - drop sockets, not needed - simplify test for owners and signumber v2: remove polling (by avagin@) Signed-off-by: Cyrill Gorcunov <gorcunov@openvz.org> Signed-off-by: Andrey Vagin <avagin@openvz.org> Signed-off-by: Pavel Emelyanov <xemul@parallels.com>
This commit is contained in:
committed by
Pavel Emelyanov
parent
0eb0391ce0
commit
b6b9e8dc6d
@@ -20,96 +20,128 @@
|
|||||||
#define F_GETSIG 11 /* for sockets. */
|
#define F_GETSIG 11 /* for sockets. */
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
const char *test_doc = "Check for signal delivery for file owners";
|
const char *test_doc = "Check for signal delivery on file owners";
|
||||||
const char *test_author = "Cyrill Gorcunov <gorcunov@openvz.org>";
|
const char *test_author = "Cyrill Gorcunov <gorcunov@openvz.org>";
|
||||||
|
|
||||||
static int received_io;
|
struct params {
|
||||||
|
int sigio;
|
||||||
#define MAP(map, i) (((int *)map)[i])
|
int pipe_flags[2];
|
||||||
#define MAP_SYNC(map) MAP(map, 0)
|
int pipe_pid[2];
|
||||||
#define MAP_PID_PIPE0(map) MAP(map, 1)
|
int pipe_sig[2];
|
||||||
#define MAP_PID_PIPE1(map) MAP(map, 2)
|
} *shared;
|
||||||
#define MAP_PID_SOK(map) MAP(map, 3)
|
|
||||||
|
|
||||||
#define SK_DATA "packet"
|
|
||||||
|
|
||||||
static void signal_handler_io(int status)
|
static void signal_handler_io(int status)
|
||||||
{
|
{
|
||||||
received_io++;
|
shared->sigio++;
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(int argc, char ** argv)
|
static void fill_pipe_params(struct params *p, int *pipes)
|
||||||
{
|
{
|
||||||
pid_t pid, ppid;
|
p->pipe_flags[0] = fcntl(pipes[0], F_GETFL);
|
||||||
struct sigaction saio;
|
p->pipe_flags[1] = fcntl(pipes[1], F_GETFL);
|
||||||
int status;
|
|
||||||
int pipes[2];
|
|
||||||
void *map;
|
|
||||||
uid_t ruid;
|
|
||||||
uid_t euid;
|
|
||||||
uid_t suid;
|
|
||||||
|
|
||||||
int ssk_pair[2];
|
/*
|
||||||
char buf[64];
|
* The kernel's O_LARGEFILE set automatically
|
||||||
|
* on open() in x86-64, so unmask it explicitly
|
||||||
|
* we restore pipes via open call while the former
|
||||||
|
* pipes are created with pipe() and have no O_LARGEFILE
|
||||||
|
* set.
|
||||||
|
*/
|
||||||
|
p->pipe_flags[0] &= ~00100000;
|
||||||
|
p->pipe_flags[1] &= ~00100000;
|
||||||
|
|
||||||
|
test_msg("pipe_flags0 %08o\n", p->pipe_flags[0]);
|
||||||
|
test_msg("pipe_flags1 %08o\n", p->pipe_flags[1]);
|
||||||
|
|
||||||
|
p->pipe_pid[0] = fcntl(pipes[0], F_GETOWN);
|
||||||
|
p->pipe_pid[1] = fcntl(pipes[1], F_GETOWN);
|
||||||
|
|
||||||
|
p->pipe_sig[0] = fcntl(pipes[0], F_GETSIG);
|
||||||
|
p->pipe_sig[1] = fcntl(pipes[1], F_GETSIG);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int cmp_pipe_params(struct params *p1, struct params *p2)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < 2; i++) {
|
||||||
|
if (p1->pipe_flags[i] != p2->pipe_flags[i]) {
|
||||||
|
fail("pipe flags failed [%d] expected %08o got %08o\n",
|
||||||
|
i, p1->pipe_flags[i], p2->pipe_flags[i]);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (p1->pipe_pid[i] != p2->pipe_pid[i]) {
|
||||||
|
fail("pipe pid failed [%d] expected %d got %d\n",
|
||||||
|
i, p1->pipe_pid[i], p2->pipe_pid[i]);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (p1->pipe_sig[i] != p2->pipe_sig[i]) {
|
||||||
|
fail("pipe sig failed [%d] expected %d got %d\n",
|
||||||
|
i, p1->pipe_sig[i], p2->pipe_sig[i]);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
struct sigaction saio = { };
|
||||||
|
struct params obtained = { };
|
||||||
|
uid_t ruid, euid, suid;
|
||||||
|
int status, pipes[2];
|
||||||
|
pid_t pid;
|
||||||
|
|
||||||
test_init(argc, argv);
|
test_init(argc, argv);
|
||||||
|
|
||||||
if (getresuid(&ruid, &euid, &suid)) {
|
shared = (void *)mmap(NULL, 4096, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS, -1, 0);
|
||||||
fail("getresuid failed");
|
if ((void *)shared == MAP_FAILED) {
|
||||||
|
fail("mmap failed");
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
map = mmap(NULL, 1024, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS, -1, 0);
|
if (getresuid(&ruid, &euid, &suid)) {
|
||||||
if (map == MAP_FAILED) {
|
fail("getresuid failed\n");
|
||||||
fail("Can't map");
|
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pipe(pipes)) {
|
if (pipe(pipes)) {
|
||||||
err("Can't create pipes: %m\n");
|
err("Can't create pipe: %m\n");
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (socketpair(AF_UNIX, SOCK_STREAM, 0, ssk_pair) == -1) {
|
saio.sa_handler = (sig_t)signal_handler_io;
|
||||||
fail("socketpair\n");
|
saio.sa_flags = SA_RESTART;
|
||||||
|
if (sigaction(SIGIO, &saio, 0)) {
|
||||||
|
fail("sigaction failed\n");
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
memset(&saio, 0, sizeof(saio));
|
|
||||||
saio.sa_handler = (sig_t)signal_handler_io;
|
|
||||||
saio.sa_flags = SA_RESTART;
|
|
||||||
sigaction(SIGIO, &saio, 0);
|
|
||||||
|
|
||||||
if (setresuid(-1, 1, -1)) {
|
if (setresuid(-1, 1, -1)) {
|
||||||
fail("setresuid failed");
|
fail("setresuid failed\n");
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
fcntl(pipes[0], F_SETOWN, getpid());
|
if (fcntl(pipes[0], F_SETOWN, getpid()) ||
|
||||||
fcntl(pipes[1], F_SETOWN, getpid());
|
fcntl(pipes[1], F_SETOWN, getpid()) ||
|
||||||
|
fcntl(pipes[0], F_SETSIG, SIGIO) ||
|
||||||
|
fcntl(pipes[1], F_SETSIG, SIGIO) ||
|
||||||
|
fcntl(pipes[0], F_SETFL, fcntl(pipes[0], F_GETFL) | O_ASYNC) ||
|
||||||
|
fcntl(pipes[1], F_SETFL, fcntl(pipes[1], F_GETFL) | O_ASYNC)) {
|
||||||
|
fail("fcntl failed\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
test_msg("main owner pipes[0]: %d\n", fcntl(pipes[0], F_GETOWN));
|
asm volatile ("" :::);
|
||||||
|
|
||||||
fcntl(pipes[0], F_SETSIG, SIGIO);
|
fill_pipe_params(shared, pipes);
|
||||||
fcntl(pipes[1], F_SETSIG, SIGIO);
|
|
||||||
|
|
||||||
fcntl(pipes[0], F_SETFL, fcntl(pipes[0], F_GETFL) | O_NONBLOCK | O_ASYNC);
|
|
||||||
fcntl(pipes[1], F_SETFL, fcntl(pipes[1], F_GETFL) | O_NONBLOCK | O_ASYNC);
|
|
||||||
|
|
||||||
fcntl(ssk_pair[0], F_SETOWN, getpid());
|
|
||||||
fcntl(ssk_pair[0], F_SETSIG, SIGIO);
|
|
||||||
fcntl(ssk_pair[0], F_SETFL, fcntl(ssk_pair[0], F_GETFL) | O_NONBLOCK | O_ASYNC);
|
|
||||||
test_msg("main owner ssk_pair[0]: %d\n", fcntl(ssk_pair[0], F_GETOWN));
|
|
||||||
|
|
||||||
if (setresuid(-1, euid, -1)) {
|
if (setresuid(-1, euid, -1)) {
|
||||||
fail("setresuid failed");
|
fail("setresuid failed\n");
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
ppid = getpid();
|
|
||||||
|
|
||||||
MAP_SYNC(map) = 0;
|
|
||||||
|
|
||||||
pid = test_fork();
|
pid = test_fork();
|
||||||
if (pid < 0) {
|
if (pid < 0) {
|
||||||
err("can't fork %m");
|
err("can't fork %m");
|
||||||
@@ -117,50 +149,44 @@ int main(int argc, char ** argv)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (pid == 0) {
|
if (pid == 0) {
|
||||||
int v = 1;
|
struct params p = { };
|
||||||
MAP_SYNC(map) = 1;
|
|
||||||
|
|
||||||
while (MAP_SYNC(map) != 3)
|
test_waitsig();
|
||||||
sleep(1);
|
|
||||||
|
|
||||||
fcntl(pipes[1], F_SETOWN, getpid());
|
fcntl(pipes[1], F_SETOWN, getpid());
|
||||||
|
fill_pipe_params(&p, pipes);
|
||||||
|
|
||||||
write(pipes[1], &v, sizeof(v));
|
if (write(pipes[1], &p, sizeof(p)) != sizeof(p)) {
|
||||||
read(pipes[0], &v, sizeof(v));
|
fail("write failed\n");
|
||||||
|
|
||||||
write(ssk_pair[0], SK_DATA, sizeof(SK_DATA));
|
|
||||||
read(ssk_pair[1], &buf, sizeof(buf));
|
|
||||||
if (strcmp(buf, SK_DATA)) {
|
|
||||||
fail("data corrupted\n");
|
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
test_msg("stream : '%s'\n", buf);
|
|
||||||
|
|
||||||
MAP_PID_PIPE0(map) = fcntl(pipes[0], F_GETOWN);
|
|
||||||
MAP_PID_PIPE1(map) = fcntl(pipes[1], F_GETOWN);
|
|
||||||
MAP_PID_SOK(map) = fcntl(ssk_pair[0], F_GETOWN);
|
|
||||||
|
|
||||||
exit(0);
|
exit(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
while (MAP_SYNC(map) != 1)
|
|
||||||
sleep(1);
|
|
||||||
|
|
||||||
test_daemon();
|
test_daemon();
|
||||||
test_waitsig();
|
test_waitsig();
|
||||||
|
kill(pid, SIGTERM);
|
||||||
|
|
||||||
MAP_SYNC(map) = 3;
|
if (waitpid(pid, &status, P_ALL) == -1) {
|
||||||
|
fail("waitpid failed\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
waitpid(pid, &status, P_ALL);
|
if (read(pipes[0], &obtained, sizeof(obtained)) != sizeof(obtained)) {
|
||||||
|
fail("read failed\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
if (received_io < 1 ||
|
if (shared->sigio < 1) {
|
||||||
MAP_PID_PIPE0(map) != ppid ||
|
fail("shared->sigio = %d (> 0 expected)\n", shared->sigio);
|
||||||
MAP_PID_PIPE1(map) != pid ||
|
exit(1);
|
||||||
MAP_PID_SOK(map) != ppid) {
|
}
|
||||||
fail("received_io = %d ppid: %d MAP_PID_PIPE0(map): %d "
|
|
||||||
"MAP_PID_PIPE1(map): %d MAP_PID_SOK(map): %d\n",
|
shared->pipe_pid[1] = pid;
|
||||||
received_io, ppid, MAP_PID_PIPE0(map),
|
|
||||||
MAP_PID_PIPE1(map), MAP_PID_SOK(map));
|
if (cmp_pipe_params(shared, &obtained)) {
|
||||||
|
fail("params comparison failed\n");
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user