criu/test/zdtm/transition/Makefile
Andrei Vagin 3f37798594
zdtm: add rseq parasite collision avoidance test
Add a transition test to verify that CRIU correctly avoids active rseq
critical sections when selecting an address for parasite code injection
and execution during checkpointing.

If CRIU were to inject parasite blobs or execute parasite syscalls
inside an active restartable sequence critical section, kernel
preemption hooks (`rseq_handle_notify_resume`) would trigger sequence
aborts or fixups, clobbering userspace memory or breaking parasite
execution.

- Emulates a spinning worker loop (`while (futex_get(f) == 0)`) inside
  an active rseq critical section so the thread is consistently inside
  `[start_ip, start_ip + post_commit_offset)` when CRIU initiates
  checkpointing.
- Dynamically sets and clears `__rseq_abi.rseq_cs` inside the assembly
  block (`start_ip`), adhering to the rseq protocol where critical
  section descriptors must only be active during critical section
  execution.
- Configures `abort_ip` to return (`ret`) out of the assembly function
  back to `test_waitsig_rseq()`, where a wrapper loop re-invokes the
  function if C/R is still in progress or an interruption occurs.

Signed-off-by: Andrei Vagin <avagin@google.com>
Reviewed-by: Alexander Mikhalitsyn <aleksandr.mikhalitsyn@futurfusion.io>
2026-07-20 11:23:01 +02:00

99 lines
1.7 KiB
Makefile

LIBDIR := ../lib
LIB := $(LIBDIR)/libzdtmtst.a
LDLIBS += $(LIB)
CPPFLAGS += -I$(LIBDIR)
TST_NOFILE = \
ipc \
ptrace \
epoll \
fork \
fork2 \
thread-bomb \
maps007 \
maps008 \
pipe_loop00 \
pipe_shared00 \
socket_loop00 \
netlink00 \
file_aio \
socket-tcp \
socket-tcp6 \
shmem \
lazy-thp \
pid_reuse \
pidfd_store_sk \
rseq01 \
rseq02 \
rseq03 \
stack \
TST_FILE = \
file_read \
unix_sock \
fifo_dyn \
fifo_loop \
TST = $(TST_NOFILE) $(TST_FILE)
SRC = $(TST:%=%.c)
OBJ = $(SRC:%.c=%.o)
DEP = $(SRC:%.c=%.d)
PID = $(TST:%=%.pid)
OUT = $(TST:%=%.out)
include ../Makefile.inc
all: $(TST)
install: all
.PHONY: all install
$(TST_NOFILE:%=%.pid): %.pid: %
$(<D)/$(<F) --pidfile=$@ --outfile=$<.out
$(TST_FILE:%=%.pid): %.pid: %
$(<D)/$(<F) --pidfile=$@ --outfile=$<.out --filename=$<.test
%.out: %.pid %
-kill -TERM `cat $<`
start: $(PID)
%.is_running: %.pid
kill -0 `cat $<`
check_start: $(PID:%.pid=%.is_running)
stop:
-kill -TERM `awk '{print}' *.pid`
WAIT_TIME=10
wait_stop:
-for i in `seq 1 $(WAIT_TIME)`; do \
kill -0 `awk '{print}' *.pid 2>/dev/null` 2>/dev/null || break; \
sleep 1; \
done
$(TST): | $(LIB)
file_aio: LDLIBS += -lrt -pthread
socket-tcp: CFLAGS += -D STREAM
socket-tcp6: CFLAGS += -D ZDTM_IPV6 -D STREAM
ptrace.o: CFLAGS += -pthread
ptrace: LDFLAGS += -pthread
fork2: CFLAGS += -D FORK2
thread-bomb.o: CFLAGS += -pthread
thread-bomb: LDFLAGS += -pthread
rseq01: LDLIBS += -pthread
rseq02: CFLAGS += -D NORESTART
rseq02: LDLIBS += -pthread
%: %.sh
cp $< $@
chmod +x $@
$(LIB): force
$(Q) $(MAKE) -C $(LIBDIR)
.PHONY: force start check_start stop wait_stop