Skip to content

Commit c857e10

Browse files
committed
upload the test case in the criu crtool to test the kernel change in the QEMU
Signed-off-by: dong sunchao <dongsunchao@gmail.com>
1 parent 9f16a1c commit c857e10

File tree

4 files changed

+197
-0
lines changed

4 files changed

+197
-0
lines changed

criu/cr-dump.c

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
#include <sys/vfs.h>
1515
#include <sys/time.h>
1616
#include <sys/wait.h>
17+
#include <sys/ioctl.h>
1718

1819
#include <sched.h>
1920
#include <sys/resource.h>
@@ -89,6 +90,29 @@
8990
#include "timer.h"
9091
#include "sigact.h"
9192

93+
/* ================= GSOC HACK ================= */
94+
/* this need to be tested in the full env
95+
* I have reuse this code in the crtool.c main() to test in the QEMU
96+
*/
97+
struct mq_peek_msg_hdr {
98+
uint32_t msg_len;
99+
uint32_t msg_prio;
100+
uint8_t payload[0];
101+
};
102+
103+
struct mq_bulk_peek_args {
104+
uint32_t start_idx;
105+
uint32_t max_count;
106+
uint64_t buf_ptr;
107+
uint64_t buf_size;
108+
uint32_t out_count;
109+
uint32_t next_idx;
110+
uint64_t reserved[2];
111+
};
112+
113+
#define MQ_IOC_BULK_PEEK _IOWR('M', 1, struct mq_bulk_peek_args)
114+
/* ============================================= */
115+
92116
/*
93117
* Architectures can overwrite this function to restore register sets that
94118
* are not covered by ptrace_set/get_regs().
@@ -2141,12 +2165,43 @@ int cr_dump_tasks(pid_t pid)
21412165
int ret;
21422166
int exit_code = -1;
21432167

2168+
int mq_fd = open("/dev/mqueue/test_queue", O_RDONLY);
2169+
size_t offset = 0;
2170+
21442171
kerndat_warn_about_madv_guards();
21452172

21462173
pr_info("========================================\n");
21472174
pr_info("Dumping processes (pid: %d comm: %s)\n", pid, __task_comm_info(pid));
21482175
pr_info("========================================\n");
21492176

2177+
/* ================= GSOC HACK TEST ================= */
2178+
pr_info(">>> [GSoC PoC] Attempting to peek POSIX mqueue directly from CRIU...\n");
2179+
2180+
if (mq_fd >= 0) {
2181+
char peek_buf[4096];
2182+
struct mq_bulk_peek_args args = {0};
2183+
args.max_count = 10;
2184+
args.buf_ptr = (uint64_t)(uintptr_t)peek_buf;
2185+
args.buf_size = sizeof(peek_buf);
2186+
2187+
if (ioctl(mq_fd, MQ_IOC_BULK_PEEK, &args) == 0) {
2188+
pr_info(">>> QEMU TEST [GSoC PoC] SUCCESS! CRIU peeked %u messages!\n", args.out_count);
2189+
2190+
for (uint32_t i = 0; i < args.out_count; i++) {
2191+
struct mq_peek_msg_hdr *hdr = (struct mq_peek_msg_hdr *)(peek_buf + offset);
2192+
pr_info(">>> QEMU TEST [GSoC PoC] Msg %u | Prio: %u | Payload: '%s'\n",
2193+
i, hdr->msg_prio, hdr->payload);
2194+
offset += sizeof(struct mq_peek_msg_hdr) + hdr->msg_len;
2195+
}
2196+
} else {
2197+
pr_err(">>> QEMU TEST [GSoC PoC] ioctl failed!\n");
2198+
}
2199+
close(mq_fd);
2200+
} else {
2201+
pr_info(">>> QEMU TEST [GSoC PoC] Could not open /dev/mqueue/test_queue (maybe victim is not running?)\n");
2202+
}
2203+
/* ================================================== */
2204+
21502205
/*
21512206
* We will fetch all file descriptors for each task, their number can
21522207
* be bigger than a default file limit, so we need to raise it to the

criu/crtools.c

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,9 @@
1111

1212
#include <sys/types.h>
1313
#include <sys/stat.h>
14+
#include <sys/ioctl.h>
15+
16+
#include <linux/ioctl.h>
1417

1518
#include <sys/socket.h>
1619
#include <netinet/in.h>
@@ -47,6 +50,24 @@
4750
#include "setproctitle.h"
4851
#include "sysctl.h"
4952

53+
struct mq_peek_msg_hdr {
54+
uint32_t msg_len;
55+
uint32_t msg_prio;
56+
uint8_t payload[0];
57+
};
58+
59+
struct mq_bulk_peek_args {
60+
uint32_t start_idx;
61+
uint32_t max_count;
62+
uint64_t buf_ptr;
63+
uint64_t buf_size;
64+
uint32_t out_count;
65+
uint32_t next_idx;
66+
uint64_t reserved[2];
67+
};
68+
69+
#define MQ_IOC_BULK_PEEK _IOWR('M', 1, struct mq_bulk_peek_args)
70+
5071
void flush_early_log_to_stderr(void) __attribute__((destructor));
5172

5273
void flush_early_log_to_stderr(void)
@@ -134,6 +155,39 @@ int main(int argc, char *argv[], char *envp[])
134155
int state = PARSING_GLOBAL_CONF;
135156
char *cmd;
136157

158+
/* ================= GSOC HACK TEST ================= */
159+
160+
size_t offset = 0;
161+
char peek_buf[4096];
162+
struct mq_bulk_peek_args args = {0};
163+
int mq_fd = open("/dev/mqueue/test_queue", O_RDONLY);
164+
165+
printf(">>> [GSoC PoC] Attempting to peek POSIX mqueue directly from CRIU main()...\n");
166+
167+
if (mq_fd >= 0) {
168+
169+
args.max_count = 10;
170+
args.buf_ptr = (uint64_t)(unsigned long)peek_buf;
171+
args.buf_size = sizeof(peek_buf);
172+
173+
if (ioctl(mq_fd, MQ_IOC_BULK_PEEK, &args) == 0) {
174+
printf(">>> [GSoC PoC] SUCCESS! CRIU peeked %u messages!\n", args.out_count);
175+
176+
for (uint32_t i = 0; i < args.out_count; i++) {
177+
struct mq_peek_msg_hdr *hdr = (struct mq_peek_msg_hdr *)(peek_buf + offset);
178+
printf(">>> [GSoC PoC] Msg %u | Prio: %u | Payload: '%s'\n",
179+
i, hdr->msg_prio, hdr->payload);
180+
offset += sizeof(struct mq_peek_msg_hdr) + hdr->msg_len;
181+
}
182+
} else {
183+
printf(">>> [GSoC PoC] ioctl failed!\n");
184+
}
185+
close(mq_fd);
186+
} else {
187+
printf(">>> [GSoC PoC] Could not open mqueue! (Did you run victim in chroot?)\n");
188+
}
189+
/* ================================================== */
190+
137191
BUILD_BUG_ON(CTL_32 != SYSCTL_TYPE__CTL_32);
138192
BUILD_BUG_ON(__CTL_STR != SYSCTL_TYPE__CTL_STR);
139193
/* We use it for fd overlap handling in clone_service_fd() */

test/zdtm/static/Makefile

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -288,6 +288,7 @@ TST_NOFILE := \
288288
change_mnt_context \
289289
fd_offset \
290290
massive_groups \
291+
mqueue_peek \
291292
# jobctl00 \
292293
293294
PKG_CONFIG ?= pkg-config
@@ -739,6 +740,8 @@ uprobes: LDLIBS += $(call pkg-libs, libtracefs libelf)
739740

740741
massive_groups: LDLIBS += -lrt -pthread
741742

743+
mqueue_peek: LDLIBS += -lrt -pthread
744+
742745
$(LIB): force
743746
$(Q) $(MAKE) -C $(LIBDIR)
744747

test/zdtm/static/mqueue_peek.c

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
#include <errno.h>
2+
#include <fcntl.h>
3+
#include <mqueue.h>
4+
#include <stdio.h>
5+
#include <stdlib.h>
6+
#include <string.h>
7+
#include <sys/stat.h>
8+
9+
#include "zdtmtst.h"
10+
11+
/*
12+
* This test is just a tempory test to verify that mqueue messages and priorities are retained across C/R.
13+
* It sends 3 messages with different priorities, waits for C/R, then receives them back in priority order to verify correct behavior.
14+
*/
15+
16+
const char *test_doc = "Test that POSIX mqueue retains messages and priorities across C/R.";
17+
const char *test_author = "SunChao Dong";
18+
19+
int main(int argc, char **argv){
20+
mqd_t mq;
21+
struct mq_attr attr;
22+
23+
char *msg2 = "Hello CRIU, priority 2!";
24+
char *msg1 = "Message with priority 1";
25+
char *msg0 = "Message with priority 0";
26+
27+
char buf[1024];
28+
unsigned int prio;
29+
ssize_t bytes_read;
30+
31+
test_init(argc, argv);
32+
33+
attr.mq_flags = 0;
34+
attr.mq_maxmsg = 10;
35+
attr.mq_msgsize = 1024;
36+
attr.mq_curmsgs = 0;
37+
38+
mq_unlink("/test_queue_zdtm");
39+
40+
mq = mq_open("/test_queue_zdtm", O_CREAT | O_RDWR, 0644, &attr);
41+
if (mq == (mqd_t)-1) {
42+
pr_perror("mq_open failed");
43+
return 1;
44+
}
45+
test_msg("Successfully opened /test_queue_zdtm\n");
46+
47+
if (mq_send(mq, msg1, strlen(msg1) + 1, 1) ||
48+
mq_send(mq, msg2, strlen(msg2) + 1, 2) ||
49+
mq_send(mq, msg0, strlen(msg0) + 1, 0)) {
50+
pr_perror("mq_send failed");
51+
return 1;
52+
}
53+
test_msg("Sent 3 messages with different priorities (1, 2, 0)\n");
54+
55+
test_daemon();
56+
test_msg("Waiting for checkpoint/restore...\n");
57+
test_waitsig();
58+
59+
test_msg("Restored! Verifying mqueue state via standard mq_receive...\n");
60+
61+
bytes_read = mq_receive(mq, buf, sizeof(buf), &prio);
62+
if (bytes_read < 0 || prio != 2 || strcmp(buf, msg2) != 0) {
63+
fail("Msg 1 verification failed! expected prio: 2, got prio: %u", prio);
64+
return 1;
65+
}
66+
67+
bytes_read = mq_receive(mq, buf, sizeof(buf), &prio);
68+
if (bytes_read < 0 || prio != 1 || strcmp(buf, msg1) != 0) {
69+
fail("Msg 2 verification failed! expected prio: 1, got prio: %u", prio);
70+
return 1;
71+
}
72+
73+
bytes_read = mq_receive(mq, buf, sizeof(buf), &prio);
74+
if (bytes_read < 0 || prio != 0 || strcmp(buf, msg0) != 0) {
75+
fail("Msg 3 verification failed! expected prio: 0, got prio: %u", prio);
76+
return 1;
77+
}
78+
79+
test_msg("All messages received correctly in exact priority order!\n");
80+
81+
mq_close(mq);
82+
mq_unlink("/test_queue_zdtm");
83+
pass();
84+
return 0;
85+
}

0 commit comments

Comments
 (0)