在新的用户名称空间中运行“ ping”时,获取“不允许的操作”

时间:2018-09-21 04:20:18

标签: c linux permissions linux-capabilities linux-namespaces

我创建一个新的流程和新的用户命名空间,如下所示:

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

那么,我该如何解决这个问题?

谢谢。

0 个答案:

没有答案