“Cannot execute /bin/bash : Permission denied” - 해결하다.

리눅스월드 편집부 / By Ben Okopnik

 

     

    이 기사를 쓰기 얼마 전에 지난 몇 주 동안 나를 괴롭혔던 문제를 해결했다. 이 문제는 리눅스 가제트에 종종 언급되었던 문제였으므로 나는 다른 독자들과 이 문제를 공유하고 싶었다.

    이 글은 또한 일반적인 소프트웨어 문제 해결에서 좋은 안내자가 될 수 있다. 그러나 login 문제는 여러 부분에서 나올 수 있으므로 내 경우의 해결책이 여러분에게도 통한다고 볼 수는 없다. 몇 주 전에 나는 내 피시에 MUA(Mail User Agent)를 설치하려고 결정했다. 내가 전화나 전기선에서 멀리 떨어진 정박된 돛단배에 산다는 것을 고려하면 이상한 결정이라고 볼지도 모르나 나름대로 이유가 있다.

    나는 예전에 육상에서 이 작업을 했었다. 나는 몇 가지 테스트를 해 보고 싶었다. MTA (Mail Transfer Agent)는 MUA를 선행한다. 즉 메일은 배달해 줄 어떤 것을 필요로 한다. 그렇지 않으면 메일을 쓰는 의미가 없다.  그래서 MTA/MUA 조합이 필요하다. 나는 데비안 전체를 내 하드 드라이브의 파티션에 갖고 있으므로 아무런 어려움이 없다. 이렇게 해 놓으면 설치도 쉽고 패키지 찾는 것도 힘들지 않다.

    나는 su 를 별로 좋아하지 않는다. 적어도 주요 작업에서는 이 명령은 본래 사용자의 환경변수를 유지하므로 때로는 아주 흥미로운 경우들을 보여 주었다. 간단한 허가 변경이나 /etc 파일 수정 외의 경우는 몰라도 패키지를 설치하거나 제거하는 것과 같은 중요한 작업에는 (나는 아직 어느 MTA 를 설치할지는 결정 않았다)나는 root 로 로그인 한다.

    Midnight Commander는 디렉토리 변경에서부터 내용 보기 데비안이나 레드햇 패키지 설치 작업들을 아주 쉽게 해준다. `sendmail’이건 너무 크고 복잡하다. 보다 간단한게 필요하다. `exim’?... `exmh’?... `mh’?... `nmh’? 모두 설치/해제를 반복.. 그러나 필요한 라이브러리는 예외다. 나는 라이브러리를 설치한 경우는 그대로 둔다. 새 시스템에 몇 번 이렇게 하면 이제는 "필요한 라이브러리가 없습니다"라는 불평을 듣지 않는다. 단 어떤 배포본에서 상당수의 라이브러리는 어느 한 가지만을 선택해야 한다.(즉 그들은 서로 충돌한다) 나는 “libs” 디렉토리를 통째로 설치하고는 그런 문제에 대해서는 잊어 버린다.

    하지만 아직도 MTA 선택 문제가 있다. 아! `smail’이 있군. 설치도 쉽고 구성도 간단하다. 됐다. MUA는 선택이 쉽다. 나는 mutt의 융통성이 맘에 든다. 이제 끝났군.(섣부른 판단이었다) 그런데 이제 나는 root 외의 사용자로는 로그인이 안된다. 내가 받은 메시지는 이렇다.
     

    Cannot execute /bin/bash: Permission denied

 

    이 무슨 날벼락인가?
     

     `Was this some occult illusion?
     Some maniacal intrusion?
     These were choices Solomon
     Himself had never faced before...’


    (이 부분은 어느 고전에서 인용한 것 같다. 번역 생략)

    나는 /etc/password를 건드리지 않았다는 것을 알고 있다. 또 /etc 도 마찬가지다. 그러나 나는 이들 패키지에 대해서는 비록 그들이 안전하다고는 하지만 내가 root 권한으로 작업할 때 어떻게 했는지는 확실히 모른다. 그래서 몇 가지 사항을 면밀히 체크했다. 패스워드 파일에 `ben’ 계정은 들어 있었다. /etc/group 도 마찬가지였다. 틀린 패스워드를 넣으면 `Cannot execute’ 대신 `Login incorrect’ 란 메시지가 정상적으로 출력된다.

    다른 방법으로 점검. 새로운 계정을 만들었다. (“joe”) 패스워드도 넣고서 이 계정으로 로그인을 시도했다. 역시 같은 에러 메시지가 나온다. 로그인 과정에서 알 수 없는 이유로 무언가가 잘못되었다. (Goodbye, “joe”...)

    나는 이 단계에서 불안한 생각이 들어 재빨리 다른 버츄얼 터미널을 열어 root로 로그인을 시도했다. 아무런 문제가 없다. 적어도 나는 다시 부팅 해도 시스템에 접근이 가능하다는 생각이 들었다. 나는 백업과 재설치가 싫었다.

    /bin 디렉토리를 열었다. 파일 허가는 어떤가? 모든게 755 (-rwxr-xr-x)이다. `login’, `mount’, `umount’, `ping’ and `su’는 모두 SETUID (-rwsr-xr-x)이다. 문제가 없다. /etc의 허가모드는 어떤가? 그들도 모두 괜찮다. 대부분 644 (-rw-r--r--)이다. 가끔씩 root외의 모두에게 감추어진 파일들이 몇 개가 600 (-rw-------)이다. 조금 어리석은 방법을 썼다. `login’과 `bash’ 가 깨지지 않았나 보려고 원래의 패키지에서 나온 새 것으로 덮어 씌웠다. 역시 달라지지 않는다.

    잠깐만! /home는 어떤가? 그 디렉토리의 허가 모드가 잘못되면 사용자는 로그인이 안된다. 그것도 문제없다. 6775 (drwxrwsr-s)이다.

    .bashrc 와 .bash_profile 도 이상없다. 허가모드도 문제 없다. 내친 김에 모든/밑의 디렉토리를 조사했지만 /root만 빼고 제 3자가 읽을 수 있다. 즉 문제가 없다.  /var에는 누가 로그인 했는지, 언제 록아웃 했는지 등을 기록하는 몇 개의 파일이 있다. 이들이 잘못 되도 예측할 수 없는 이상한 현상이 나올 수 있다.

     

비상 확인 방법을 써 보았다.

     

    cat >/var/log/wtmp
    cat >/var/run/utmp


    이렇게 하면 내용을 없애고 0바이트의 파일로 만든다.
    [ cat 없이 명령을 주었다. 그러나 “>”을 쉘프롬프트로 오인하지 않도록 앞에 cat룰 넣었다. ]
    나는 모든 VT에서 로그아웃했다. (`utmp’ 와 `wtmp’ 가 데이터를 받도록) 결과는 정상이었다.

    /dev/ttyX 와 /dev/vcsX 의 허가모드는? (터미널과 콘솔) 그들도 모두 정상적으로 보인다. 이제 별로 희망이 없다.

    잠깐! 시스템적인 접근방법을 써보면? 어느 방향으로 진행하기 전에 무슨 일이 일어나는지를 생각해 보자.  기억을 살리기 위해 System Administrator’s Guide (SAG) 를 들추어 보았다. 여기 로그인 과정이 있다.

     

“System Administrator’s Guide”로부터  (Lars Wirzenius 씀)

    맨처음 init는 터미널 또는 콘솔 연결을 위한 getty 프로그램이 있는지를 확인한다. Getty는 터미널을 감시하고 사용자가 로그인할 준비가 돼 있는지를 알려주길 기다린다. (이는 보통 사용자가 어떤 키를 누르는 것을 의미한다) 사용자를 감지하면 getty는 환영메시지를 출력하고(/etc/issue 에 들어 있는) 계정명 입력을 요구한다. 그리고서는 login 프로그램을 실행한다. Login 프로그램은 계정명을 파라메터로 받고는 패스워드 프롬프트를 내 보낸다. 이 둘이 일치하면 login은 그 사용자에게 지정된 쉘을 시작한다.

    일치하지 않으면 실행을 중단하고 프로세스를 종료한다. (사용자에게는 다시 계정과 패스워드 입력 기회를 줄 것이다) init는 프로세스가 종료한 것을 알고 그 터미널에 대한 새로운 getty를 시작한다.

                                 시작(Start)     

                              init: fork + exec  
                               “/sbin/getty”   

                             getty: 사용자 대기

                          getty: 계정명 읽어 들임
                               exec “/bin/login”

                          login: 패스워드 읽어들임

        Login: exit             일치하는가?

                                       Yes

                           login: exec(“/bin/sh”)

                           sh: 명령 읽기 및 실행

                                  sh: exit

         Figure 8.1: 터미널 로그인 과정: init, getty, login, shell의 상호 작용.

    유일한 새로운 프로세스는 init에 의해 창조된 것이다.(fork 시스템콜을 사용한다); getty 와 login 은 그 프로세스에서 수행되고 있는 프로그램을 대체한다. ( exec 시스템콜을 사용한다.)

    이 과정을 추적해 보아도 우리는 마지막 부분 즉 ‘exec(“/bin/sh”) 까지 모든게 정상인 것으로 보인다. 잘못된 부분은 연결을 해주는 부분이나 부수 부문이다. 문제는 이제 시스템콜로 귀착된다. 그런데 이 부분은 어떻게 접근해야 하는지 나는 알 수가 없다.

    그러나 이미 내가 필요로 하는 모든 정보는 거기에 있었다. 단지 나는 그것을 어떻게 적용하는지를 몰랐다. 나중에 이것은 명백해 질 것이다.

    다음 10일 동안 로그인 할 때마다 나는 몇 가지 새로운 것을 시도해 보았다. 어떤 것은 전혀 상관이 없어 적용되지 않는 것 같았다. 어떤 그럴 듯한 생각도 그 망할 메시지가 다시 나올 때는 실망뿐이었다. 아무 것도 소용이 없었다.

    나는 getty도 바꾸어 보았고 /bin/bash 외에 다른 여러 쉘도 시험했다. ‘ben’으로 su도 시도했다. 그리고 로그를 조사했다. (그런데 ben이 성공적으로 로그인한 것으로 기록된다. 그러면 login은 문제가 없다. 실패는 login이 프로세스를 bash로 넘길 때 발생하는 것이다. - 이것을 깨달았다.)

    인터넷에서 이 부분에 대한 몇 가지 참고문을 찾아냈다. - 거의 모두 일어, 스웨덴어, 독일어 였다 - 나는 뒤의 둘은 추측으로 맞추었는데 그 중 하나는 ‘/’에 대한 허가를 체크하는 것이었다. 좋은 생각이나 내겐 해당되지 않았다. 나는 이 문제를 The Answer Guy 에게 보냈으나 그는 윈도우 2000 문제에 깊이 빠져 있었다. 이제는 내 스스로 해결하는 길 뿐이다.

    아! - `strace’! `strace’를 기억했다. `strace’는 프로그램 실행 과정을 추적해서 단계 별로 알려주는 환상적인 프로그램이다. 어디 한번 시험해 보자.

    프로그램을 실행하려면 로그인해야 하므로 나는 현재의 터미널에서 아래처럼 실행했다.
     

    strace -s 10000 -vfo login.ben login ben

 

    의미는 아래와 같다.

    `login ben’에 대해 strace를 실행하라. ; 10000 캐릭터까지의 모든 라인을 출력하라(나는 어느 메시지도 놓치고 싶지 않았다. 아무리 길지라도); 출력은 최대한 자세히 하라; 어떠한 forked 프로세스도 추적하라; 결과를 `login.ben’” 파일에 기록하라.
     

    strace -s 10000 -vfo login.root login root

 

    -이제 나는 두 파일을 비교할 수 있다. ‘root’의 출력은 ‘ben’보다 두 배는 길었다. -
    그래야 맞다. 왜냐하면 성공적인 로그인은 “~/.bash*” 파일 내의 모든 사항을 실행하니까.

    `strace login’은 매우 좋은 정보를 알려준다. 내가 만약 System Administrator’s Guide 를 읽지 않았다면 이 프로그램이 정확한 정보를 알려 주었을 것이다.
    - 훨씬 더 상세히. 이는 `login’이 읽어 들인 모든 라이브러리를 보여주고 참고 한 모든 파일
       들도 그리고 `group’과 `password’비교 과정까지 .. 단지 실패 원인만 보여 주지 않았다.
     

    (300+ lines elided)
    execve(“/bin/bash”, [“-bash”], [“TERM=linux”, “HZ=100”, “HOME=/home/ben”,
         “SHELL=/bin/bash”, “PATH=/bin:/usr/bin”, “USER=ben”, “LOGNAME=ben”,
         “MAIL=/var/spool/mail/ben”, “LANG=C”, “HUSHLOGIN=FALSE”])=-1 EACCES
         (Permission denied)            
    write(2, “Cannot execute /bin/bash: Permission denied\n”, 44) = 44

 

    어쨌든 대단하다. `login’이 허공에 두 다리를 뻗고 눕기 전에 시도한 마지막 과정은 /etc/password, /etc/login.defs 등에서 가져온 변수로서 bash를 `execve’하는 것이었다.

    그 모두는 이상이 없다. - 결국은 “stderr” (출력 장치 2)에 44개의 그 보기 싫은 글자를 남기는 것이다.
    그러나 나는 ‘login’이  Name Service Switch 구성 파일 (/etc/nsswitch.conf)에서 필요한 몇 개의 라이브러리를 /lib에서 불러 오는 것을 알았다. 그 중에 어느 하나가 깨졌을 수도 있지 않을까? 시스템콜 추론과 비교할 때 맞는 것 같다. 왜냐하면 라이브러리에서 시스템콜이 나오니까. NSS (see `man nsswitch’)에 대한 로칼 로그인을 다루는 라이브러리를 보자.
     

    dpkg -S libnss_compat-2.0.7.so


    전능하신 데비안 패키지 관리자님이시여 위 프로그램이 어디서 오시나이까?
    (“Tell me, O Mighty Debian Package Manager, whence cometh said program?”),

    그러자 데비안 신께서는 현명하게도 아래처럼 답하셨다.
    (and the Debian Oracle, in his wisdom, replied - )
     

    libc6: /lib/libnss_compat-2.0.7.so


    흠, 바로 리눅스 핵심 라이브러리이군.. 모든 /lib/libnss* 파일을 대치해 본다. 별 무소득이다. 다른 방도를 보자.
    이 과정은 내게 어떤 힌트를 주었다. 어떤 것이 “rotten in the state of Denmark”(?) - 아무래도 /lib의 파일들의 허가모드를 검사해야겠다.
    문제는 내가 그들이 어떻게 설정되어 있어야 하는지를 모른다는 것이었다. 여러분도 알다시피 libs의 대부분의 파일은 “root.root 644” 로 설정되어 있다.(owner root, group root, user - read/write, group - read-only, others - read-only)그러나 몇 개는 “root.root 755”여야한다. 즉 관련된 모두에게 실행모드가 부여 되야 한다. 바로 설치한 리눅스를 보지 않고는 어느 것이 맞는지 알 수 없다.

    잠깐만! 내가 LG에 보냈던 2센트 팁에서 언급했듯이 데비안 베이스 설치 파일( 7 파일, 약 15메가)을 비상시 용으로 도스 파티션에 넣어 놓았다. - 이것이 내가 필요로 하는 것을 갖고 있겠지!

    거기에 있었다. Midnight Commander는 “Virtual File System”을 사용해서 압축파일이 디렉토리인것처럼 탐색하는 것을 허용한다. “base2_1.tgz#utar/lib” (the VFS syntax used by MC)를 보았을 때 맨 앞의 라이브러리 중 하나인 - ld-2.0.7.so - 가 755 였다. 이제 ‘ben’은 새 터미널의 주인이 되었다.

    나는 다른 라이브러리들도 모두 검사했으나 `ld-2.0.7.so’ 가 허가 모드가 변경된 유일한 파일이었다. 남은 유일한 의문은 왜 허가모드가 변경 되었느냐 이다.  하지만 이는 영원히 풀리지 않을 것 같다.

    항상 그렇듯이 리눅스가 가르치는 교훈은 어렵다. 그러나 공평하다. 문제를 해결하는 길은 항상 있다. 시스템을 재설치하는 것은 종종 가장 쉬운 방법이다. 그러나 이것은 OS의 내부에 관한 부분을 당신에게 알려주지 않는다. 그리고 문제를 추적해 내는 것도 알려주지 않는다. 내 경우도 재설치는 쉬웠다. 데이터를 백업하고 데비안 기본을 까는데 10분이면 족하다. 나는 그 방법은 흥미가 없었다. 내 마음 속에 있는 생각은 만약 이것이 고객의 사이트에서 발생했다면 어떻게 할 것인가 이다. 올바른 해결책을 알아야 했다.

    끈기와 집념으로 나는 해냈다. 나는 단지 연습으로 이런 어려운 문제를 가지고 일주일에 한번씩 머리를 쥐어 짜라고 하지는 않는다.

    그러나 나는 여러분이 HOWTO 나 다른 문서에서 얻은 지식으로 체계적인 접근을 시도하기를 권한다.

    Happy Linuxing to all,
    Ben Okopnik

    Copyright (c) 2000, Ben Okopnik
    Published in Issue 52 of Linux Gazette, April 2000




▲ top

home으로...