Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/checkpoint-restore/criu.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAdrian Reber <areber@redhat.com>2020-07-24 19:18:31 +0300
committerAndrei Vagin <avagin@gmail.com>2022-10-25 17:26:42 +0300
commit0add1b6cdbedaaac93d48ea323beceb7328b69b2 (patch)
treef56dca90b010f57939288a33a4a76aa60b729fdc
parent1db95afd02c754beea33c6071b4070e3c35cf77b (diff)
non-root: extend zdtm.py to be able to run tests as non-root
These are the minimal changes to make zdtm.py successfully run the env00 and pthread test case as non-root using the '--rootless' zdtm option. Co-authored-by: Younes Manton <ymanton@ca.ibm.com> Signed-off-by: Adrian Reber <areber@redhat.com> Signed-off-by: Younes Manton <ymanton@ca.ibm.com>
-rwxr-xr-xtest/zdtm.py56
-rw-r--r--test/zdtm/lib/test.c49
-rw-r--r--test/zdtm_ct.c60
3 files changed, 104 insertions, 61 deletions
diff --git a/test/zdtm.py b/test/zdtm.py
index aefcb36a4..a311610c3 100755
--- a/test/zdtm.py
+++ b/test/zdtm.py
@@ -41,6 +41,8 @@ STREAMED_IMG_FILE_NAME = "img.criu"
prev_line = None
uuid = uuid.uuid4()
+NON_ROOT_UID = 65534
+
def alarm(*args):
print("==== ALARM ====")
@@ -392,10 +394,11 @@ class test_fail_expected_exc(Exception):
class zdtm_test:
- def __init__(self, name, desc, flavor, freezer):
+ def __init__(self, name, desc, flavor, freezer, rootless):
self.__name = name
self.__desc = desc
self.__freezer = None
+ self.__rootless = rootless
self.__make_action('cleanout')
self.__pid = 0
self.__flavor = flavor
@@ -439,6 +442,8 @@ class zdtm_test:
wait_pid_die(int(self.__pid), self.__name, self.__timeout)
def __add_wperms(self):
+ if os.getuid() != 0:
+ return
# Add write perms for .out and .pid files
for b in self._bins:
p = os.path.dirname(b)
@@ -457,6 +462,9 @@ class zdtm_test:
env['ZDTM_NOTIFY_FDIN'] = "100"
env['ZDTM_NOTIFY_FDOUT'] = "101"
+ if self.__rootless:
+ env['ZDTM_ROOTLESS'] = "1"
+
if not test_flag(self.__desc, 'suid'):
# Numbers should match those in criu
env['ZDTM_UID'] = "18943"
@@ -618,11 +626,15 @@ class zdtm_test:
["make", "zdtm_ct"], env=dict(os.environ, MAKEFLAGS=""))
if not os.access("zdtm/lib/libzdtmtst.a", os.F_OK):
subprocess.check_call(["make", "-C", "zdtm/"])
+ if opts['rootless']:
+ return
subprocess.check_call(
["flock", "zdtm_mount_cgroups.lock", "./zdtm_mount_cgroups", str(uuid)])
@staticmethod
def cleanup():
+ if opts['rootless']:
+ return
subprocess.check_call(
["flock", "zdtm_mount_cgroups.lock", "./zdtm_umount_cgroups", str(uuid)])
@@ -640,7 +652,9 @@ def load_module_from_file(name, path):
class inhfd_test:
- def __init__(self, name, desc, flavor, freezer):
+ def __init__(self, name, desc, flavor, freezer, rootless):
+ if rootless:
+ raise test_fail_exc("This kind of test does not currently support rootless mode")
self.__name = os.path.basename(name)
print("Load %s" % name)
self.__fdtyp = load_module_from_file(self.__name, name)
@@ -801,8 +815,8 @@ class inhfd_test:
class groups_test(zdtm_test):
- def __init__(self, name, desc, flavor, freezer):
- zdtm_test.__init__(self, 'zdtm/lib/groups', desc, flavor, freezer)
+ def __init__(self, name, desc, flavor, freezer, rootless):
+ zdtm_test.__init__(self, 'zdtm/lib/groups', desc, flavor, freezer, rootless)
if flavor.ns:
self.__real_name = name
with open(name) as fd:
@@ -1039,6 +1053,7 @@ class criu:
self.__dedup = bool(opts['dedup'])
self.__mdedup = bool(opts['noauto_dedup'])
self.__user = bool(opts['user'])
+ self.__rootless = bool(opts['rootless'])
self.__leave_stopped = bool(opts['stop'])
self.__stream = bool(opts['stream'])
self.__show_stats = bool(opts['show_stats'])
@@ -1138,6 +1153,9 @@ class criu:
print("Run criu " + action)
+ if self.__rootless:
+ s_args += ["--unprivileged"]
+
strace = []
if self.__sat:
fname = os.path.join(self.__ddir(), action + '.strace')
@@ -1156,7 +1174,10 @@ class criu:
if action == "restore":
preexec = None
else:
- preexec = self.__user and self.set_user_id or None
+ if os.getuid():
+ preexec = None
+ else:
+ preexec = self.__user and self.set_user_id or None
__ddir = self.__ddir()
@@ -1476,10 +1497,11 @@ class criu:
except Exception:
return False
- return criu_cli.run(
- "check",
- ["--no-default-config", "--verbosity=0", "--feature", feature],
- opts['criu_bin']) == 0
+ args = ["--no-default-config", "-verbosity=0", "--feature", feature]
+ if opts['rootless']:
+ args += ["--unprivileged"]
+
+ return criu_cli.run("check", args, opts['criu_bin']) == 0
@staticmethod
def available():
@@ -1900,7 +1922,7 @@ def do_run_test(tname, tdesc, flavs, opts):
if opts['dry_run']:
continue
flav = flavors[f](opts)
- t = tclass(tname, tdesc, flav, fcg)
+ t = tclass(tname, tdesc, flav, fcg, opts['rootless'])
cr_api = criu(opts)
try:
@@ -2051,7 +2073,8 @@ class Launcher:
'sat', 'script', 'rpc', 'criu_config', 'lazy_pages', 'join_ns',
'dedup', 'sbs', 'freezecg', 'user', 'dry_run', 'noauto_dedup',
'remote_lazy_pages', 'show_stats', 'lazy_migrate', 'stream',
- 'tls', 'criu_bin', 'crit_bin', 'pre_dump_mode', 'mntns_compat_mode')
+ 'tls', 'criu_bin', 'crit_bin', 'pre_dump_mode', 'mntns_compat_mode',
+ 'rootless')
arg = repr((name, desc, flavor, {d: self.__opts[d] for d in nd}))
if self.__use_log:
@@ -2061,6 +2084,9 @@ class Launcher:
logf = None
log = None
+ if opts['rootless'] and os.getuid() == 0:
+ os.setgid(NON_ROOT_UID)
+ os.setuid(NON_ROOT_UID)
sub = subprocess.Popen(["./zdtm_ct", "zdtm.py"],
env=dict(os.environ, CR_CT_TEST_INFO=arg),
stdout=log,
@@ -2600,6 +2626,10 @@ def set_nr_hugepages(nr):
with open("/proc/sys/vm/nr_hugepages", "w") as f:
f.write("{}\n".format(nr))
return orig_hugepages
+ except PermissionError as err:
+ # EACCES is expected when running as non-root, otherwise re-raise the exception.
+ if err.errno != errno.EACCES or os.getuid() == 0:
+ raise
except OSError as err:
if err.errno != errno.EOPNOTSUPP:
raise
@@ -2673,6 +2703,10 @@ def get_cli_args():
rp.add_argument("--freezecg", help="Use freeze cgroup (path:state)")
rp.add_argument("--user", help="Run CRIU as regular user",
action='store_true')
+ rp.add_argument(
+ "--rootless",
+ help="Run CRIU rootless (uid!=0) (needs CAP_CHECKPOINT_RESTORE)",
+ action='store_true')
rp.add_argument("--rpc",
help="Run CRIU via RPC rather than CLI",
action='store_true')
diff --git a/test/zdtm/lib/test.c b/test/zdtm/lib/test.c
index 57eb42046..6291ea4a7 100644
--- a/test/zdtm/lib/test.c
+++ b/test/zdtm/lib/test.c
@@ -239,34 +239,37 @@ void test_init(int argc, char **argv)
exit(1);
}
- val = getenv("ZDTM_GROUPS");
- if (val) {
- char *tok = NULL;
- unsigned int size = 0, groups[NGROUPS_MAX];
-
- tok = strtok(val, " ");
- while (tok) {
- size++;
- groups[size - 1] = atoi(tok);
- tok = strtok(NULL, " ");
+ val = getenv("ZDTM_ROOTLESS");
+ if (!val) {
+ val = getenv("ZDTM_GROUPS");
+ if (val) {
+ char *tok = NULL;
+ unsigned int size = 0, groups[NGROUPS_MAX];
+
+ tok = strtok(val, " ");
+ while (tok) {
+ size++;
+ groups[size - 1] = atoi(tok);
+ tok = strtok(NULL, " ");
+ }
+
+ if (setgroups(size, groups)) {
+ fprintf(stderr, "Can't set groups: %m");
+ exit(1);
+ }
}
- if (setgroups(size, groups)) {
- fprintf(stderr, "Can't set groups: %m");
+ val = getenv("ZDTM_GID");
+ if (val && (setgid(atoi(val)) == -1)) {
+ fprintf(stderr, "Can't set gid: %m");
exit(1);
}
- }
- val = getenv("ZDTM_GID");
- if (val && (setgid(atoi(val)) == -1)) {
- fprintf(stderr, "Can't set gid: %m");
- exit(1);
- }
-
- val = getenv("ZDTM_UID");
- if (val && (setuid(atoi(val)) == -1)) {
- fprintf(stderr, "Can't set gid: %m");
- exit(1);
+ val = getenv("ZDTM_UID");
+ if (val && (setuid(atoi(val)) == -1)) {
+ fprintf(stderr, "Can't set gid: %m");
+ exit(1);
+ }
}
if (prctl(PR_SET_DUMPABLE, 1)) {
diff --git a/test/zdtm_ct.c b/test/zdtm_ct.c
index 0e8eeff8a..5e849b904 100644
--- a/test/zdtm_ct.c
+++ b/test/zdtm_ct.c
@@ -93,44 +93,50 @@ static int create_timens(void)
int main(int argc, char **argv)
{
+ uid_t uid;
pid_t pid;
int status;
+ uid = getuid();
+
/*
* pidns is used to avoid conflicts
* mntns is used to mount /proc
* net is used to avoid conflicts of parasite sockets
*/
- if (unshare(CLONE_NEWNS | CLONE_NEWPID | CLONE_NEWNET | CLONE_NEWIPC))
- return 1;
+ if (!uid)
+ if (unshare(CLONE_NEWNS | CLONE_NEWPID | CLONE_NEWNET | CLONE_NEWIPC))
+ return 1;
pid = fork();
if (pid == 0) {
- if (create_timens())
- exit(1);
- if (mount(NULL, "/", NULL, MS_REC | MS_SLAVE, NULL)) {
- fprintf(stderr, "mount(/, S_REC | MS_SLAVE)): %m");
- return 1;
- }
- umount2("/proc", MNT_DETACH);
- umount2("/dev/pts", MNT_DETACH);
- if (mount("zdtm_proc", "/proc", "proc", 0, NULL)) {
- fprintf(stderr, "mount(/proc): %m");
- return 1;
+ if (!uid) {
+ if (create_timens())
+ exit(1);
+ if (mount(NULL, "/", NULL, MS_REC | MS_SLAVE, NULL)) {
+ fprintf(stderr, "mount(/, S_REC | MS_SLAVE)): %m");
+ return 1;
+ }
+ umount2("/proc", MNT_DETACH);
+ umount2("/dev/pts", MNT_DETACH);
+ if (mount("zdtm_proc", "/proc", "proc", 0, NULL)) {
+ fprintf(stderr, "mount(/proc): %m");
+ return 1;
+ }
+ if (mount("zdtm_devpts", "/dev/pts", "devpts", 0, "newinstance,ptmxmode=0666")) {
+ fprintf(stderr, "mount(pts): %m");
+ return 1;
+ }
+ if (mount("zdtm_binfmt", "/proc/sys/fs/binfmt_misc", "binfmt_misc", 0, NULL)) {
+ fprintf(stderr, "mount(binfmt_misc): %m");
+ return 1;
+ }
+ if (mount("/dev/pts/ptmx", "/dev/ptmx", NULL, MS_BIND, NULL)) {
+ fprintf(stderr, "mount(ptmx): %m");
+ return 1;
+ }
+ if (system("ip link set up dev lo"))
+ return 1;
}
- if (mount("zdtm_devpts", "/dev/pts", "devpts", 0, "newinstance,ptmxmode=0666")) {
- fprintf(stderr, "mount(pts): %m");
- return 1;
- }
- if (mount("zdtm_binfmt", "/proc/sys/fs/binfmt_misc", "binfmt_misc", 0, NULL)) {
- fprintf(stderr, "mount(binfmt_misc): %m");
- return 1;
- }
- if (mount("/dev/pts/ptmx", "/dev/ptmx", NULL, MS_BIND, NULL)) {
- fprintf(stderr, "mount(ptmx): %m");
- return 1;
- }
- if (system("ip link set up dev lo"))
- return 1;
execv(argv[1], argv + 1);
fprintf(stderr, "execve: %m");
return 1;