2
0
mirror of https://github.com/checkpoint-restore/criu synced 2025-08-31 14:25:49 +00:00

zdtm: Check CapAmb is restored correctly after C/R

This test sets CapAmb according to CapPrm and CapInh and check CapAmb
after C/R.

Signed-off-by: Liu Chao <liuchao173@huawei.com>
This commit is contained in:
Liu Chao
2025-01-03 03:33:27 +00:00
committed by Andrei Vagin
parent 6991ea1ff9
commit d4d3937017
3 changed files with 170 additions and 0 deletions

View File

@@ -8,6 +8,7 @@ TST_NOFILE := \
sleeping00 \
pid00 \
caps00 \
caps01 \
wait00 \
zombie00 \
zombie01 \

168
test/zdtm/static/caps01.c Normal file
View File

@@ -0,0 +1,168 @@
#include <errno.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/prctl.h>
#include <linux/capability.h>
#include "zdtmtst.h"
const char *test_doc = "Check that CapAmb are preserved";
const char *test_author = "Liu Chao <liuchao173@huawei.com>";
struct cap_hdr {
unsigned int version;
int pid;
};
struct cap_data {
unsigned int eff;
unsigned int prm;
unsigned int inh;
};
#define _LINUX_CAPABILITY_VERSION_3 0x20080522
#define _LINUX_CAPABILITY_U32S_3 2
#define CAP_DAC_OVERRIDE 1
#define PR_CAP_AMBIENT 47
#define PR_CAP_AMBIENT_IS_SET 1
#define PR_CAP_AMBIENT_RAISE 2
#define PR_CAP_AMBIENT_LOWER 3
int capget(struct cap_hdr *hdrp, struct cap_data *datap);
int capset(struct cap_hdr *hdrp, const struct cap_data *datap);
static int cap_last_cap = 63;
int main(int argc, char **argv)
{
task_waiter_t t;
int pid, result_pipe[2];
unsigned int amb[_LINUX_CAPABILITY_U32S_3];
unsigned int amb_2[_LINUX_CAPABILITY_U32S_3];
char res = 'x';
FILE *f;
test_init(argc, argv);
task_waiter_init(&t);
f = fopen("/proc/sys/kernel/cap_last_cap", "r");
if (f) {
if (fscanf(f, "%d", &cap_last_cap) != 1) {
pr_perror("Unable to read cal_last_cap");
fclose(f);
return 1;
}
fclose(f);
} else
test_msg("/proc/sys/kernel/cap_last_cap is not available\n");
if (pipe(result_pipe)) {
pr_perror("Can't create pipe");
return 1;
}
pid = test_fork();
if (pid == 0) {
int b, i, ret;
struct cap_hdr hdr;
struct cap_data data[_LINUX_CAPABILITY_U32S_3];
hdr.version = _LINUX_CAPABILITY_VERSION_3;
hdr.pid = 0;
if (capget(&hdr, data) < 0) {
pr_perror("capget");
return -1;
}
hdr.version = _LINUX_CAPABILITY_VERSION_3;
hdr.pid = 0;
data[0].eff &= ~((1 << CAP_CHOWN) | (1 << CAP_DAC_OVERRIDE));
data[0].prm &= ~(1 << CAP_DAC_OVERRIDE);
data[0].inh = data[0].prm;
data[1].inh = data[1].prm;
if (capset(&hdr, data) < 0) {
pr_perror("capset");
return -1;
}
for (b = 0; b < _LINUX_CAPABILITY_U32S_3; b++) {
amb[b] = data[b].prm;
for (i = 0; i < 32; i++) {
if (b * 32 + i > cap_last_cap)
break;
if ((amb[b] & (1 << i)) > 0)
ret = prctl(PR_CAP_AMBIENT, PR_CAP_AMBIENT_RAISE, i + b * 32, 0, 0);
else
ret = prctl(PR_CAP_AMBIENT, PR_CAP_AMBIENT_LOWER, i + b * 32, 0, 0);
if (ret) {
pr_perror("Unable to set ambient capability %d to %d: %d", i + b * 32, amb[b] & (1 << i), ret);
return -1;
}
}
}
task_waiter_complete_current(&t);
task_waiter_wait4(&t, getppid());
for (b = 0; b < _LINUX_CAPABILITY_U32S_3; b++) {
amb_2[b] = 0;
for (i = 0; i < 32; i++) {
if (b * 32 + i > cap_last_cap)
break;
ret = prctl(PR_CAP_AMBIENT, PR_CAP_AMBIENT_IS_SET, i + b * 32, 0, 0);
if (ret < 0) {
pr_perror("Unable to read ambient capability %d: %d", i + b * 32, ret);
goto bad;
}
amb_2[b] |= (ret << i);
}
}
for (b = 0; b < _LINUX_CAPABILITY_U32S_3; b++) {
if (amb[b] != amb_2[b]) {
res = '1';
goto bad;
}
}
res = '0';
bad:
write(result_pipe[1], &res, 1);
if (res != '0') {
write(result_pipe[1], amb, sizeof(amb));
write(result_pipe[1], amb_2, sizeof(amb_2));
}
close(result_pipe[0]);
close(result_pipe[1]);
_exit(0);
}
task_waiter_wait4(&t, pid);
test_daemon();
test_waitsig();
task_waiter_complete_current(&t);
read(result_pipe[0], &res, 1);
if (res == '0')
pass();
else {
read(result_pipe[0], amb, sizeof(amb));
read(result_pipe[0], amb_2, sizeof(amb_2));
test_msg("amb[]=%08x, %08x\n", amb[0], amb[1]);
test_msg("amb[]=%08x, %08x\n", amb_2[0], amb_2[1]);
fail("Fail: %c", res);
}
close(result_pipe[0]);
close(result_pipe[1]);
return 0;
}

View File

@@ -0,0 +1 @@
{'flags': 'suid'}