Я создаю новый процесс и новое пространство имен пользователя, например:
clone(run, stack + STACK_SIZE, CLONE_NEWUSER | SIGCHLD, NULL);
и запускаю ping
в новом процессе, но я получил ошибку: операция не разрешена.
Здесьмой код:
#define _GNU_SOURCE
#include <sched.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/capability.h>
#include <sys/wait.h>
#include <unistd.h>
#define STACK_SIZE (1024 * 1024)
#define ROOT_UID 0
#define ROOT_GID 0
static char stack[STACK_SIZE];
static int fd[2];
#define wait do { \
char __ch; \
read(fd[0], &__ch, 1); \
} while (0)
#define awake do { \
char __ch; \
write(fd[1], &__ch, 1); \
} while (0)
static inline void
cap_info() {
cap_t caps = cap_get_proc();
char *txt = cap_to_text(caps, NULL);
printf("cap info:\n%s\n", txt);
cap_free(txt);
cap_free(caps);
}
static inline int set_map(const char *filename, int inside_id, int outsid_id, int len) {
FILE *f = fopen(filename, "w");
if (f == NULL) {
perror("open");
return 1;
}
int r = fprintf(f, "%d %d %d", inside_id, outsid_id, len) < 0 ? 1 : 0;
fclose(f);
return r;
}
static int
set_uid_map(pid_t pid, int inside_id, int outside_id, int len) {
char filename[64];
sprintf(filename, "/proc/%d/uid_map", pid);
return set_map(filename, inside_id, outside_id, len);
}
static int
set_gid_map(pid_t pid, int inside_id, int outside_id, int len) {
char filename[64];
sprintf(filename, "/proc/%d/gid_map", pid);
return set_map(filename, inside_id, outside_id, len);
}
static int
run(void *arg) {
wait;
cap_info();
printf("run `id`:\n");
system("id");
printf("run `ping`:\n");
system("/bin/ping -c 1 www.example.org");
return 0;
}
int main(int argc, char **args) {
if (pipe(fd) != 0) {
perror("pipe");
return 1;
}
pid_t pid = clone(run, stack + STACK_SIZE, CLONE_NEWUSER | SIGCHLD, NULL);
if (pid == -1) {
perror("clone");
return 1;
}
set_uid_map(pid, 0, getuid(), 1);
set_gid_map(pid, 0, getuid(), 1);
awake;
waitpid(pid, NULL, 0);
return 0;
}
и вот результат:
# gcc -lcap code.c -o run && sudo ./run
cap info:
= cap_chown,cap_dac_override,cap_dac_read_search,cap_fowner,cap_fsetid,cap_kill,cap_setgid,cap_setuid,cap_setpcap,cap_linux_immutable,cap_net_bind_service,cap_net_broadcast,cap_net_admin,cap_net_raw,cap_ipc_lock,cap_ipc_owner,cap_sys_module,cap_sys_rawio,cap_sys_chroot,cap_sys_ptrace,cap_sys_pacct,cap_sys_admin,cap_sys_boot,cap_sys_nice,cap_sys_resource,cap_sys_time,cap_sys_tty_config,cap_mknod,cap_lease,cap_audit_write,cap_audit_control,cap_setfcap,cap_mac_override,cap_mac_admin,cap_syslog,cap_wake_alarm,cap_block_suspend,cap_audit_read+ep
run `id`:
uid=0(root) gid=0(root) groups=0(root),65534(nobody)
run `ping`:
ping: socket: Operation not permitted
вот мое окружение:
OS: Archlinux
kernel: 4.17.14-arch1-1-ARCH
Итак, как мне решить эту проблему?
Thx.