따라서 사용자가 nproc
한도를 초과했습니다. 따라서 SSH도 불가능하고 su
대상 사용자로 로그인도 불가능합니다. 그러나 사용자가 액세스할 수 있는 셸은 없습니다. 루트 권한 없이 이 문제를 해결하는 방법은 무엇입니까?
감사해요
답변1
nproc과 "ulimit" 라벨이 보이면 이 ulimit 메커니즘에 대해 2가지 포인트를 추가하겠습니다.
귀하가 겪고 있는 상황을 정확하게 피하기 위해 시스템 관리자가 소프트 제한을 하드 제한보다 약간 낮게 설정하기를 바랍니다. 이렇게 하면 su
다른 계정에서 실행하기 위한 소프트 값을 추가하고 이를 사용하여 종료할 수 있습니다.
또한 ulimit는 grep -r pam_limits.so /etc/pam.d/
PAM( )에 의해 설정되므로 이 PAM 모듈을 사용하지 않는 인증 방법/프로그램이 있는 경우 이 ulimit를 피하고 종료를 생성할 수 있습니다.
CAP_KILL
문제가 발생하기 전에 조치를 취해야 하는 이 두 가지 솔루션 외에도 올바른 액세스 권한(동일한 사용자, 루트, setuid 또는 기능) 없이 기존 프로그램에 신호를 보내는 것은 실제로 불가능합니다.
답변2
다른 사용자의 자격 증명이 있고 대상 사용자의 자격 증명을 사용하여 어떤 방식으로든 파일 시스템을 변경할 수 있는 경우 다음 프로그램을 컴파일하고 s 비트를 설정한 후 다른 사용자의 자격 증명을 사용하여 실행할 수 있습니다.
참고: seteuid
대상 사용자의 uid
.
프로그램의 첫 번째 인수는 대상 사용자의 인수입니다 uid
.
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <signal.h>
#include <errno.h>
int main(int argc, char**argv) {
if(seteuid(atoi(argv[1])) != 0) {
printf("seteuid failed... %d", errno);
}
if(kill(-1, SIGTERM) != 0) {
printf("kill failed...%d", errno);
}
return 0;
}
답변3
아시다시피, nproc
이 수준에 도달하면 커널은 해당 사용자의 자격 증명을 사용하여 다른 프로세스를 실행하는 것을 허용하지 않습니다. 즉, SSH를 통한 원격 세션도 없고, 프로그램도 없으며 su
, sudo
계정에 대한 setuid도 없습니다.
이렇게 하면 루트 또는 사용자만 사용할 수 있습니다(아직 작동 중인 대화형 세션이 있는 경우). 루트를 제외했으므로 사용자가 여전히 셸을 실행하고 있기를 바랍니다. 그렇다면 문제가 되는 프로세스 중 일부를 종료하기에 충분한 기능이 셸에 내장되어 있어야 합니다. 을 반복하려면 쉘 내장 함수를 사용해야 합니다 /proc
.
예를 들어 모든 셸을 종료하려면 bash
다음과 같이 하면 됩니다. Bash 셸 내장 명령만 사용하면 됩니다.
pushd /proc && for pid in *; do
test "$pid" = "self" && continue # skip /proc/self
test -d "$pid" || continue # skip if not a directory
test -O "$pid" || continue # skip if we don't own it
read cmd < "${pid}/cmdline"
case "$cmd" in
*bash*) kill -9 $pid ;; # or whatever you want to do to it
esac
done && popd
여기에는 몇 가지 제한 사항이 있으므로 완전하지는 않지만 대부분의 경우 유용합니다.
만약 있다면많은처리가 실행될 때
*
루프 상단의 확장으로 인해 문자열이 초과될 수 있습니다.최대 명령 길이. 이러한 상황이 발생하면 , , 또는 유사한 항목을 사용하여1*
여러2*
번{1..3}*
실행하여 와일드카드 확장을 줄일 수 있습니다./proc/${pid}/cmdline
실제 명령이 하나의 항목인 NULL로 구분된 목록을 포함합니다. Bash 내장 기능만 사용하여 이와 같은 문자열을 깔끔하게 구문 분석하는 방법을 모르겠습니다. 문자열은 일반적으로 NULL로 끝나기 때문에read
명령 이름일 수도 있고 아닐 수도 있는 첫 번째 항목만 가져옵니다. 또 다른 방법은/proc/${pid}/stat
or 를 반복하는 것입니다/proc/${pid}/status
.