Chroot 후 상위 폴더의 프로그램 실행(=자바)

안녕하세요.

c프로그램에서 fork 후 child에서 execl로 자바 프로그램을 돌려야 하는데…

execl 전에 chroot를 현재폴더로 지정해 줍니다.

그후 execl로 자바 프로그램 실행하려 하면, /usr/lib/jvm/… 에 있는 자바의 실행파일을 읽지 못하는데, 어떻게 해야할까요?

chroot 후 심볼릭링크로 원래의 루트위치에 있는 "java"를 옮겨와도 접근이 안되더라구요.

대충 찾아보니 chroot후 상위폴더의 프로그램이 필요할 경우, chroot 폴더 내로 미리 옮겨오는 방법이 있던데, 자바의 경우 jvm 폴더 자체를 옮겨오기엔 부담이 너무 큽니다.

chroot를 안쓰자니 다른 안전장치를 구현해야 하는 방법뿐인데…

chroot와 자바 jvm… 해결방법이 없을까요?

아마 패스 부분 한번 확인 해보세요!
환경변수만 잡혀있으면 문제 없이 실행될겁니다.

[quote="toori67":3mm3lju8]아마 패스 부분 한번 확인 해보세요!
환경변수만 잡혀있으면 문제 없이 실행될겁니다.[/quote:3mm3lju8]

chroot 부분을 없앨경우 execl(자바프로그램) 은 문제없이 실행이 됩니다.

java 패스 자체는 제대로 잡혀 있는데,

chroot후 바뀐 루트를 위해 패스를 다시 설정해야 한다는 말씀이신가요?ㅠㅠ

자바에서 virtual filesystem이란게 있는데, 해당사항이 있는지 모르겠네요.

일단 chroot가 필요하다면, 먼저 해당 위치를 마운트해 놓는 방법이 있습니다.
옮겨놓는 것이 아니라, 링크 비슷한 개념으로 디렉토리를 마운트하는 것이죠.

mkdir -p newroot/jvm
mkdir -p newroot/home/$USER
sudo mount -o bind,ro /usr/lib/jvm/java-7-openjdk-amd64 newroot/jvm
sudo mount -o bind,rw /home/$USER newroot/home/$USER
sudo chroot newroot /jvm/jre/bin/java -jar SOMEJAR.jar

만일 루트시스템 전체에 액세스를 원한다면, unionfs를 사용해 볼 수 있습니다.
sudo mkdir -p /var/chroot_base/{rw,new_root}
sudo unionfs-fuse -o cow,rw,uid=$(id -u),gid=$(id -g),allow_other,use_ino,suid,dev,nonempty "/var/chroot_base/rw=RW:/=RO" /var/chroot_base/new_root
echo "export JAVA_HOME=/usr/lib/jvm/java-7-openjdk-amd64; export PATH=$HOME/bin:/usr/local/bin:/usr/bin:/usr/local/sbin:/usr/sbin;java -jar SOMEJAR.jar" | sudo chroot /var/chroot_base/new_root /bin/bash

이렇게 하면 / 디렉토리 전체에 읽기쓰기가 가능해집니다.
단 실제 / 디렉토리는 쓰기만 가능하고, 변경된 내용에 대해서는 /var/chroot_base/rw에 저장됩니다.
unionfs는 여러 장치들을 하나로 묶어 마운트하는 것입니다.
이 때 속성을 주어, 각 장치 별 접근 권한을 설정하고, 우선 순위를 정하게 됩니다.
cow라는 것은 copy-on-write의 약자로, 변경하면 원래 소스를 복사한 후, 사본을 변경하게 됩니다.

[quote="unexpectab":m6lz2kec][quote="toori67":m6lz2kec]아마 패스 부분 한번 확인 해보세요!
환경변수만 잡혀있으면 문제 없이 실행될겁니다.[/quote:m6lz2kec]

chroot 부분을 없앨경우 execl(자바프로그램) 은 문제없이 실행이 됩니다.

java 패스 자체는 제대로 잡혀 있는데,

chroot후 바뀐 루트를 위해 패스를 다시 설정해야 한다는 말씀이신가요?ㅠㅠ[/quote:m6lz2kec]

chroot 에 대해서 잘못생각하고 있어서 실수를 했네요…

  1. http://www.bpfh.net/simes/computing/chroot-break.html 여기 중간에 c code 를 보시면 chroot(..) 이런식으로 cursor(?)를 루트 디렉토리까지 올린 다음 필요한 프로그램을 exec 하게 되어 있는데 이걸 이용해서 맨 위로 커서를 올려서 실행하고 난 뒤에 다시 떨어트리는 방법 또는
  2. http://stackoverflow.com/a/16503389/2373466 여기 처럼 custom chrooter 를 작성하는 방법
  3. hard-link 를 이용하는 방법

이렇게 세개가 있네요!

부팅과정과 chroot에 대해서 설명을 해보겠습니다.

먼저 root는 최상위 디렉토리를 말합니다.
우리가 보통 알기로 / 파티션이 루트디렉토리라고 알고 있지만, 이것은 정확한 것은 아닙니다.

먼저 커널이 로드되는 시점에서 루트디렉토리가 정의되지만, 이시점에서 /에는 아무것도 없습니다.
initrd=(hd0,0)/initrd.gz등의 부트설정에 의해 램디스크 이미지가 로드되면서,
램디스크이미지를 루트디렉토리로 마운트합니다.
그리고 init스크립트가 실행되어 initramfs 스크립트가 진행되죠.
그리고, initramfs스크립트의 단계는
init-top
init-premount
local-top
local-premount
마운트
local-bottom
init-bottom
이런 단계로 진행될것이고, 이 단계들 내부에서
부팅시 옵션인 root=/dev/sda7 이나 root=UUID=xxxxxxxxx 혹은 root=LABEL=lllll
의 구문을 분석하여, 해당 장치로 chroot하고, init를 실행할 것입니다.
이 단계에서 하드디스크로의 부팅이 되는 것이죠.

라이브모드로 부팅하면, initrd로 램디스크부팅후,
라이브이미지를 마운트하고, 이 이미지로 chroot하게 될 것입니다.
단 이 경우, aufs나 unionfs 등으로 라이브이미지를 읽기전용으로,
램디스크를 읽기쓰기모드로 공유하여 하나의 디렉토리로 마운트한 후,
해당 디렉토리로 chroot 할 것입니다.

/ 는 실제 디렉토리나 장치라기 보다는 순수하게 마운트 지점의 최상위를 말하는 것입니다.
언제든 이 마운트 지점의 최상위 디렉토리를 바꾸는 것이 chroot와 pivot_root, fakeroot 등 이죠.

mkdir t
sudo mount /dev/sda1 t
sudo chroot t /bin/bash
이런 일련의 명령은 /dev/sda1을 t 디렉토리에 마운트 후,
t 디렉토리를 최상위 디렉토리로 잡고, 그 밑의 /bin/bash를 실행하게 됩니다.
즉, chroot 이전의 /bin/bash가 아니라는 것입니다.

홈 디렉토리로 chroot 할 경우, 홈 디렉토리가 /가 되고, /디렉토리의 상위디렉토리는 없으므로,
홈 디렉토리의 상위 디렉토리에 접근이 불가능해집니다.
또한, 경로도 해당 디렉토리를 기준으로 존재하여야 합니다.
/bin/ls대신 $HOME/bin/ls를 참조하게 되는 것입니다.
따라서, 모든 실행 및 접근 경로를 /기준으로 흉내내야 합니다.
이것을 jail이라고 합니다.

따라서, 일반적인 chroot 패턴은,
mkdir t
sudo mount /dev/sda1 t
sudo mount -o bind /proc t/proc
sudo mount -o bind /sys t/sys
sudo mount -o bind /dev t/dev
sudo mount -o bind /dev/pts t/dev/pts
sudo chroot t /bin/bash
sudo umount /dev/pts /dev /sys /proc
sudo umount t
이런 형태가 되는데, /proc,/sys,/dev/,/dev/pts 등은 커널이 자동으로 장치를 탐색하여,
그와 관련 정보들을 담아 마운트해 놓은 곳으로,
현재 마운트되어 있는 상기 마운트지점을 단순히 차용하면 되기에, bind옵션으로 마운트하는 것입니다.
이런 작업을 안하면, 터미널 및 장치정보, 파일시스템정보 등에 접근할 수 없어,
문제가 발생할 수 있습니다.

이 경우는 /dev/sda1이 루트파일시스템이라는 가정하에,
중요 디렉토리들 만 jail로 만든 것이지만,
홈 디렉토리로 chroot하게 되면, /usr/bin /bin /lib /usr/lib /var /etc 등등… 거의 모든 디렉토리를 jail로 구성해야
문제없이 동작하게 됩니다.
그렇기 때문에, 이런 경우는 unionfs등으로 /파티션을 읽기전용으로, 다른 디렉토리를 읽기 쓰기 모드로 공유 마운트하여,
copy-on-write모드로, /파티션에 없거나, 변경된 사항을 따로 저장하게 하는 방법이 좋습니다.

schroot를 설치하여, 배포판 자체를 데비안 부트스트랩으로 설치하여 사용하실 수 도 있습니다.
예를 들어 64비트 배포판에서, 32비트 환경을 온전히 실행하고자 할 때,
32비트 배포만의 최소버젼을 설치하여 그 안으로 chroot하여 실행하는 것이죠.

[quote="toori67":xgowgecl][quote="unexpectab":xgowgecl][quote="toori67":xgowgecl]아마 패스 부분 한번 확인 해보세요!
환경변수만 잡혀있으면 문제 없이 실행될겁니다.[/quote:xgowgecl]

chroot 부분을 없앨경우 execl(자바프로그램) 은 문제없이 실행이 됩니다.

java 패스 자체는 제대로 잡혀 있는데,

chroot후 바뀐 루트를 위해 패스를 다시 설정해야 한다는 말씀이신가요?ㅠㅠ[/quote:xgowgecl]

chroot 에 대해서 잘못생각하고 있어서 실수를 했네요…

  1. http://www.bpfh.net/simes/computing/chroot-break.html 여기 중간에 c code 를 보시면 chroot(..) 이런식으로 cursor(?)를 루트 디렉토리까지 올린 다음 필요한 프로그램을 exec 하게 되어 있는데 이걸 이용해서 맨 위로 커서를 올려서 실행하고 난 뒤에 다시 떨어트리는 방법 또는
  2. http://stackoverflow.com/a/16503389/2373466 여기 처럼 custom chrooter 를 작성하는 방법
  3. hard-link 를 이용하는 방법

이렇게 세개가 있네요![/quote:xgowgecl]

1,2번은 안될것 같습니다…
execl 하는 자바 프로그램이 실제 루트에 접근 가능할것 같아서…

3번은 한번 시도해봤는데 여러 파일들을 하드링크로 해줘야 하는것 같은데

정확히 어떤 파일을 하드링크로 해야할지 모르겠네요…ㅠㅠ;

이글 올리기 전에 /usr/lib/jvm/…/java 하드링크 해봤을땐 안됬었습니다.

mount -o bind /usr/lib/jvm 바뀐루트
위 처럼 jvm이랑 proc, usr이었나 서너개를 마운트해주고 마운트된 위치의 java를 execl로 실행했더니 우선 돌아는 갑니다.

여기서 궁금한게, execl로 자바프로그램 콜하는 c프로그램이 루트권한에서 돌아가기때문에, 자바 프로그램도 루트권한을 갖게됩니다.

그럴경우 마운트된 디렉토리들을 자바프로그램이 삭제나 변경도 할 수 있기때문에, 보안상 마운트된 디렉토리들을 읽기 외에 삭제, 이동, 바꾸기 등등 불가능하게 하고 싶은데,

마운트 옵션에 r 옵션만 두면 읽기전용으로 마운트되기 때문에, 루트권한을 갖고있더라고 수정, 변경, 삭제등등 못하게 되나요?

mount -o bind,r /usr/lib/jvm

위처럼 하면 루트권한의 프로그램일지라도 마운트된 디렉토리 내의 파일들 수정, 변경, 삭제가 불가능한건지 궁금합니다.

[quote="unexpectab":3ouf2tt4]mount -o bind /usr/lib/jvm 바뀐루트
위 처럼 jvm이랑 proc, usr이었나 서너개를 마운트해주고 마운트된 위치의 java를 execl로 실행했더니 우선 돌아는 갑니다.

여기서 궁금한게, execl로 자바프로그램 콜하는 c프로그램이 루트권한에서 돌아가기때문에, 자바 프로그램도 루트권한을 갖게됩니다.

그럴경우 마운트된 디렉토리들을 자바프로그램이 삭제나 변경도 할 수 있기때문에, 보안상 마운트된 디렉토리들을 읽기 외에 삭제, 이동, 바꾸기 등등 불가능하게 하고 싶은데,

마운트 옵션에 r 옵션만 두면 읽기전용으로 마운트되기 때문에, 루트권한을 갖고있더라고 수정, 변경, 삭제등등 못하게 되나요?

mount -o bind,r /usr/lib/jvm

위처럼 하면 루트권한의 프로그램일지라도 마운트된 디렉토리 내의 파일들 수정, 변경, 삭제가 불가능한건지 궁금합니다.[/quote:3ouf2tt4]

r이아니고 ro(readonly)입니다.
이것은 접근 권한하고 는 좀 다르게, 장치 접근 옵션입니다.
즉, 에러가 생겨, 루트파티션이 읽기전용으로 마운트되었다면, 관리자도 변경이 불가합니다.
단 mount -o remount,rw 옵션으로 다시 마운트하면 변경가능합니다.

엄격히 사용자권한으로 chroot하고 싶으시면,
dchroot를 설치해서 사용해보세요.
이것은 사용자권한으로 chroot합니다.

이에 반해 schroot는 -u 사용자 옵션으로, 사용자를 원하는대로 바꿀 수 있습니다.

dchroot와 schroot는 데비안 부트스트랩으로 기본프로그램들을 설치하고,
그 안으로 chroot합니다.
또한 단발성 명령을 chroot환경하에서 실행할 수 있습니다.