не удается открыть (/proc / $ pid / ns /{namespace_files})

#c #file-read #linux-namespaces

#c #файл-прочитан #linux-пространства имен

Вопрос:

Мне нужно присоединить процесс к новому пространству имен, поэтому я извлекаю fd пространства имен процесса, чтобы он мог вызывать setns для этих fd.

Но проблема в том, что все возвращаемые fd являются -1s.

Я сделал это:

 cout<<mnt<<"n"; // prints /proc/4563/ns/mnt
int mnt_fd =  open(mnt, O_RDONLY | O_CLOEXEC);      
cout<<mnt_fd<<" n"; // prints -1


cout<<net<<"n"; // prints /proc/4563/ns/net
int net_fd =  open(net, O_RDONLY | O_CLOEXEC);          
cout<<net_fd<<" n"; //prints -1

cout<<pid<<"n"; // prints /proc/4563/ns/pid
int pid_fd =  open(pid, O_RDONLY | O_CLOEXEC);
cout<<pid_fd<<" n"; // prints -1
  

pid , mnt , net являются объявленными путями.
Как я могу это решить?

EDIT1: при печати stderror говорится, что он печатает permission denied при выполнении sudo chmod 755 во всей файловой системе proc operation not permitted

ПРАВКА2: я допустил ошибку, не скомпилировав и не запустив исполняемый файл с помощью sudo. На этот раз он может открыть fds, и все возвращенные fds положительные. Аналогично вышеописанному, я также открыл другие fd пространства имен, такие как usr_fd, чтобы присоединиться к пользовательскому пространству имен, ipc_fd для присоединения к пространству имен ipc и uts_fd для присоединения к пространству имен uts целевого процесса, но при выполнении setns on userfd выдается ошибка Invalid argument . Ниже приведен код, который я написал для объединения пространств имен.

 pid_t cpid = fork();
    if(cpid == 0){
       if (setns(pid_fd, 0) == -1)        /* Join pid namespace */
           cout<<"joining pid "<<strerror(errno);
       if (setns(uts_fd, 0) == -1)        /* Join uts namespace */
           cout<<"joining uts "<<strerror(errno);
       if (setns(ipc_fd, 0) == -1)        /* Join pic namespace */
           cout<<"joining ipc "<<strerror(errno);
       if (setns(usr_fd, 0) == -1)        /* Join usr namespace */
           cout<<"joining usr "<<strerror(errno);
       if (setns(net_fd, 0) == -1)        /* Join net namespace */
           cout<<"joining net "<<strerror(errno);
       if (setns(mnt_fd, 0) == -1)        /* Join mnt namespace */
           cout<<"joining mnt "<<strerror(errno);

        char *argv[] = { "sudo ./mycode",NULL };
        execve(argv[0], argv, NULL);                                                                                        
    }
  

Я хотел, чтобы дочерний процесс выполнил программу getcode в этом пространстве имен, но он этого не делает? Если это неправильный способ сделать это, то как дочерний элемент может запустить программу в этом пространстве имен?

mycode.cpp

 int main() {
  
  printf("I am child process %d of parent %dn", getpid(), getppid());
  while (true) {
  }
  
  return 0;
}
  

ПРАВКА3: однако замена строки ниже:

 char *argv[] = { "sudo ./mycode",NULL };
execve(argv[0], argv, NULL); 
  

с помощью этого

     char *argv[] = {"ps", NULL};  
    execvp(argv[0], amp;argv[0]); 
  

работает.

Комментарии:

1. У вас есть необходимые разрешения для открытия путей? Что произойдет, если вы сделаете это ls /proc/4563/ns/mnt в командной строке?

2. что говорит errno?

3. @G.M. Написано, что в разрешении отказано

4. @user253751 да, ошибка также указывает, что в разрешении отказано, что я могу теперь сделать?

5. изменение разрешения также не помогает. при выполнении sudo chmod 755 во всей файловой системе proc сообщается, что операция не разрешена

Ответ №1:

Короче говоря, вам нужна CAP_SYS_PTRACE возможность доступа к ссылкам на пространства имен (и нескольким другим вещам) внутри файловой системы /proc процесса, включая связанные с пространством имен подразделы, поступающие из файловой системы пространства имен nsfs внутри procfs. ………. Здесь CAP_DAC_READ_SEARCH и CAP_DAC_OVERRIDE являются только частью игры. В зависимости от вашего конкретного развертывания они могут потребоваться при запуске не как UID0 с ограниченными возможностями.

Запуск от имени root обычно предоставляет вам все возможности, включая CAP_SYS_PTRACE . Процессу, отличному от UID0, можно предоставить доступ, предоставив ему ограниченные, разрешенные и не в последнюю очередь эффективные CAP_SYS_PTRACE возможности.

Один из способов сделать это — установить возможности файла («POSIX») с помощью setcap CLI tool. Как обычно, с большой мощностью приходит большая ответственность, поэтому убедитесь, что ваш двоичный файл должным образом укреплен, чтобы его нельзя было использовать в качестве трамплина для получения запрещенного доступа к системе.