Por que um processo de um binário com permissão de execução somente permanece oculto em “ps” ao usar hidepid = 2, se o usuário não for root?

4

Estou usando o hidepid = 2 para montar / proc, para que os usuários não possam ver nada além de seus próprios processos. Um binário específico que eu quero usar foi restrito às permissões rwx-x-x, portanto, somente seu proprietário (root) pode lê-lo, mas outros usuários podem executá-lo. Um usuário normal pode executá-lo sem problemas, mas não pode ver o processo com "ps". Se o binário tiver suas permissões alteradas para que o usuário possa lê-lo, o processo aparecerá em "ps" novamente.

Um exemplo reproduzível:

sudo mount -o remount,hidepid=2 /proc
sudo cp $(which yes) /tmp
sudo chmod 0711 /tmp/yes
/tmp/yes >/dev/null &
ps aux | grep yes # The process is hidden
sudo ps aux | grep yes # The process can be seen by root
kill %1
sudo chmod og+r /tmp/yes
/tmp/yes >/dev/null &
ps aux | grep yes # The process appears in the list

Por que isso está acontecendo? Obviamente, tem alguma relação com as permissões do arquivo, mas não deveria ter: se o processo pertence a um usuário, o usuário deve ser capaz de vê-lo mesmo que o binário seja restrito.

Meu palpite é que, como o link "exe" dentro de / proc / PID aponta para o binário sendo executado, o kernel proíbe todo o acesso ao diretório além do próprio binário. Mas eu gostaria de saber se isso é verdade ou apenas uma consequência de alguma outra coisa acontecendo.

Obrigado antecipadamente!

    
por rsuarez 24.09.2015 / 14:48

1 resposta

4

A resposta é (ou pelo menos começa ) em fs/proc/base.c (inalterado do kernel 3.12 para 4.2 pelo menos)

742 static int proc_pid_permission(struct inode *inode, int mask)
743 {
744         struct pid_namespace *pid = inode->i_sb->s_fs_info;
745         struct task_struct *task;
746         bool has_perms;
747 
748         task = get_proc_task(inode);
749         if (!task)
750                 return -ESRCH;
751         has_perms = has_pid_permissions(pid, task, 1);
752         put_task_struct(task);
753 
754         if (!has_perms) {
755                 if (pid->hide_pid == 2) {
756                         /*
757                          * Let's make getdents(), stat(), and open()
758                          * consistent with each other.  If a process
759                          * may not stat() a file, it shouldn't be    seen
760                          * in procfs at all.
761                          */
762                         return -ENOENT;
763                 }
764 
765                 return -EPERM;
766         }
767         return generic_permission(inode, mask);
768 }

O código acima é o ponto de partida para determinar se uma entrada /proc/PID específica pode ser vista como existente ou não. Quando hide_pid é definido como 2, ele retorna -ENOENT se você não tiver a permissão necessária. As permissões são verificadas por meio de:

has_pid_permissions() →   ptrace_may_access() →   __ptrace_may_access()

__ptrace_may_access() nega acesso porque o processo não é "dumpable", pois foi criado a partir de uma imagem executável ilegível, conforme determinado durante a criação do processo:

setup_new_exec() →   would_dump()

1118 void would_dump(struct linux_binprm *bprm, struct file *file)
1119 {
1120         if (inode_permission(file_inode(file), MAY_READ) < 0)
1121                 bprm->interp_flags |= BINPRM_FLAGS_ENFORCE_NONDUMP;
1122 }
    
por 01.10.2015 / 14:46