[CRIU] [PATCH 2/5] fown: test -- Add file_fown_dead
Cyrill Gorcunov
gorcunov at gmail.com
Fri Dec 7 15:29:45 MSK 2018
Just setup owner to a pid which immediately exit
and file left with dead pid assigned.
Signed-off-by: Cyrill Gorcunov <gorcunov at gmail.com>
---
test/zdtm/static/Makefile | 1 +
test/zdtm/static/file_fown_dead.c | 192 +++++++++++++++++++++++++++
test/zdtm/static/file_fown_dead.desc | 1 +
3 files changed, 194 insertions(+)
create mode 100644 test/zdtm/static/file_fown_dead.c
create mode 100644 test/zdtm/static/file_fown_dead.desc
diff --git a/test/zdtm/static/Makefile b/test/zdtm/static/Makefile
index 7b8d663778b6..ab20c61b3574 100644
--- a/test/zdtm/static/Makefile
+++ b/test/zdtm/static/Makefile
@@ -119,6 +119,7 @@ TST_NOFILE := \
groups \
pdeath_sig \
file_fown \
+ file_fown_dead \
proc-self \
eventfs00 \
epoll \
diff --git a/test/zdtm/static/file_fown_dead.c b/test/zdtm/static/file_fown_dead.c
new file mode 100644
index 000000000000..3a99bc729f51
--- /dev/null
+++ b/test/zdtm/static/file_fown_dead.c
@@ -0,0 +1,192 @@
+#include <unistd.h>
+
+#include <errno.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <signal.h>
+#include <string.h>
+#include <utime.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <sys/mman.h>
+#include <sys/socket.h>
+
+#include "zdtmtst.h"
+
+#ifndef F_SETSIG
+#define F_SETSIG 10 /* for sockets. */
+#define F_GETSIG 11 /* for sockets. */
+#endif
+
+const char *test_doc = "Check for restore with dead file owners";
+const char *test_author = "Cyrill Gorcunov <gorcunov at openvz.org>";
+
+struct params {
+ int sigio;
+ int pipe_flags[2];
+ int pipe_pid[2];
+ int pipe_sig[2];
+} *shared;
+
+static void signal_handler_io(int status)
+{
+ shared->sigio++;
+}
+
+static void fill_pipe_params(struct params *p, int *pipes)
+{
+ p->pipe_flags[0] = fcntl(pipes[0], F_GETFL);
+ p->pipe_flags[1] = fcntl(pipes[1], F_GETFL);
+
+ 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);
+
+ shared = (void *)mmap(NULL, 4096, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS, -1, 0);
+ if ((void *)shared == MAP_FAILED) {
+ fail("mmap failed");
+ exit(1);
+ }
+
+ if (getresuid(&ruid, &euid, &suid)) {
+ fail("getresuid failed\n");
+ exit(1);
+ }
+
+ if (pipe(pipes)) {
+ pr_perror("Can't create pipe");
+ exit(1);
+ }
+
+ saio.sa_handler = (sig_t)signal_handler_io;
+ saio.sa_flags = SA_RESTART;
+ if (sigaction(SIGIO, &saio, 0)) {
+ fail("sigaction failed\n");
+ exit(1);
+ }
+
+ if (!getuid() && setresuid(-1, 1, -1)) {
+ fail("setresuid failed\n");
+ exit(1);
+ }
+
+ if (fcntl(pipes[0], 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);
+ }
+
+ fill_pipe_params(shared, pipes);
+
+ if (setresuid(-1, euid, -1)) {
+ fail("setresuid failed\n");
+ exit(1);
+ }
+
+ pid = test_fork();
+ if (pid < 0) {
+ pr_perror("can't fork");
+ exit(1);
+ } else if (pid == 0) {
+ struct params p = { };
+
+ fcntl(pipes[1], F_SETOWN, getpid());
+ fill_pipe_params(&p, pipes);
+
+ if (write(pipes[1], &p, sizeof(p)) != sizeof(p)) {
+ fail("write failed\n");
+ exit(1);
+ }
+
+ exit(0);
+ }
+
+ if (waitpid(pid, &status, P_ALL) == -1) {
+ fail("waitpid %d failed\n", pid);
+ exit(1);
+ }
+
+ test_daemon();
+ test_waitsig();
+
+ if (read(pipes[0], &obtained, sizeof(obtained)) != sizeof(obtained)) {
+ fail("read failed\n");
+ exit(1);
+ }
+
+ if (shared->sigio < 1) {
+ fail("shared->sigio = %d (> 0 expected)\n", shared->sigio);
+ exit(1);
+ }
+
+ shared->pipe_pid[1] = pid;
+
+ if (cmp_pipe_params(shared, &obtained)) {
+ fail("params comparison failed\n");
+ exit(1);
+ }
+
+ /*
+ * The F_SETOWN above operates on child which
+ * is already exited so in criu we should skip
+ * setting PID back and in result there must
+ * be a zero.
+ */
+ obtained.pipe_pid[1] = 0;
+
+ fill_pipe_params(shared, pipes);
+
+ if (cmp_pipe_params(shared, &obtained)) {
+ fail("params comparison failed\n");
+ exit(1);
+ }
+
+ pass();
+ return 0;
+}
diff --git a/test/zdtm/static/file_fown_dead.desc b/test/zdtm/static/file_fown_dead.desc
new file mode 100644
index 000000000000..63df42aa670a
--- /dev/null
+++ b/test/zdtm/static/file_fown_dead.desc
@@ -0,0 +1 @@
+{'flavor': 'h'}
--
2.17.2
More information about the CRIU
mailing list