Bash의 소스에 왜 실행 비트가 필요하지 않습니까?


57

Bash를 사용 source하면 실행 비트 설정없이 스크립트를 실행할 수 있습니다. 이것은 문서화되고 예상되는 동작이지만 실행 비트 사용에 대한 것이 아닙니까?

나는 그것이 source서브 쉘을 생성하지 않는다는 것을 알고있다 .


2
chmod8 진수로 권한 (x를 포함하여)을 설정할 수 있다는 사실은 그 시대에 대한 힌트를줍니다. 그것은 신속하고 더러운로 시작하면 나는 놀라지 않을 것이다 그녀 - 쾅가 발명되기 전에 일에서, 표시를 "이것은 당신이 실행할 수있는 바이너리 파일입니다",하지만 난 그에게 증거가 없다
infixed

9
다시 SUID가 작동하면 다른 범주의 사용자에 대한 다른 수준의 보호가 더 중요해집니다. 원한다면 SUID 프로그램을 읽으십시오. 당신은 단순히 읽기를 통해 그것을 실행하면 단, SUID의 힘은 그것과 함께 오는되지 않습니다
infixed

@infixed Linux 프로그램 로더는 실행 비트가 설정되어 있지 않으면 shebang을 보지도 않습니다 . (내 자신의 경적을 조금 들으려면 여기를 참조 하십시오 .)
Kyle Strand

+ xr도 가질 수 있지만 실행 프로세스에 코드를 삽입하여 바이너리를 읽을 수 있기 때문에 약간 이상합니다.
Niklas B.

내가의 라인을 따라 뭔가 상상했다 "당신은 단순히 읽기를 통해 그것을 실행하는 경우 SUID의 힘은이와 함께 오는되지 않습니다"에 의해 @KyleStrandcp /sbin/suidexecutable /tmp/mycopy; /tmp/mycopy
infixed

답변:


36

Bash는 통역사입니다. 입력을 받아들이고 원하는 것을 수행합니다. 실행 비트에주의 할 필요는 없습니다. 실제로 Bash는 이식성이 뛰어나며 실행 가능한 비트 개념이없는 운영 체제 및 파일 시스템에서 실행할 수 있습니다.

실행 비트에 관심이있는 것은 운영 체제 커널입니다. exec예를 들어, Linux 커널은 파일 시스템이 noexec옵션으로 마운트되지 않았 는지 확인하고 프로그램 파일의 실행 가능 비트를 확인하고 보안 모듈 (SELinux 또는 AppArmor 등)에 의해 부과 된 모든 요구 사항을 시행합니다.

실행 가능한 비트는 다소 임의의 종류의 제어입니다. 예를 들어, Linux x86-64 시스템에서는 명시 적으로 /lib/x86_64-linux-gnu/ld-linux-x86-64.so.2인터프리터로 호출 하여 커널의 실행 가능 비트 확인을 무시할 수 있습니다 .

cp /bin/ls /tmp/
chmod -x /tmp/ls
/lib/x86_64-linux-gnu/ld-linux-x86-64.so.2 /tmp/ls

이것은 ld.so인터프리터를 제외하고 Bash에서 Bash 소스 코드를 소싱하는 것과 다소 유사하며, 실행되는 코드는 ELF 형식의 기계 코드입니다.


3
로더를 "실제로 실행 가능한 바이너리"인 "바이트 코드"의 "인터프리터"로 사용합니다. 고마워
Kyle Strand

@KyleStrand 여러 수준의 간접 저장 (저장된 프로그램과로드 된 프로세스와 메모리 매핑 방법, 다양한 감독자, VM 등)의 차이가있을 수 있지만 원칙적 으로 기계 코드는 CPU에 의해 직접 실행될 수 있습니다 (마이크로 코드, 기타) 따라서 기계어 코드는 해석되지 않습니다. 하드웨어는이를 그대로 이해합니다. 모국어이므로 통역사가 필요하지 않습니다.
jfs 2016 년

2
@JFSebastian 네, 우리는 그것이 네이티브 코드라는 것을 알고 있습니다. 따라서 "통역사"는 따옴표 안에 있습니다. 작업은 ld.so동적 연결을 수행하는 것입니다.
200_success 2016 년

@JFSebastian 200_ 성공의 말. 또한, 이것이 "실제 실행 가능 바이너리"의 의미이며, "바이트 코드"도 따옴표로 묶습니다 (AFAIK "바이트 코드"는 일반적으로 실제 컴파일 된 네이티브 실행 가능 바이너리 코드를 참조하는 데 사용되지 않기 때문에). 또한 좋은 사용자 이름입니다.
Kyle Strand

@JFSebastian 저는 현대적인 x86 유사 CPU가 실제로 내부적으로 RISC라고 생각합니다. 구식 CISC 명령어 세트는 기본적으로 해당 RISC 명령어의 마이크로 코드 실행을 구동합니다. 여기서 하나의 CISC 명령어는 많은 RISC 명령어가 실행될 수 있습니다. 어떤 의미에서, CPU가 RISC 기계 코드를 "통역"으로하는 것은 기술적 인 관점에서 완전히 정확하지 않다면 적어도 유효한 정신 모델입니다. AES-NI 는 아마도 가장 극단적 인 예 중 하나 일 것입니다. AES 라운드 당 하나의 CISC 명령!
CVn

57

source또는 동등하지만 표준 도트. 는 스크립트를 실행하지 않지만 스크립트 파일에서 명령을 읽은 다음 현재 쉘 환경에서 한 줄씩 실행합니다.

쉘 은 파일의 내용을 읽을 수있는 읽기 권한 만 있으면되기 때문에 실행 비트 사용에 반대되는 것은 없습니다 .

실행 비트는 스크립트 를 실행할 때만 필요합니다 . 여기서 쉘은 fork()새로운 프로세스 execve()를 생성 한 다음 함수를 사용하여 스크립트에서 새로운 프로세스 이미지를 생성하는데, 이는 정기적으로 실행 가능한 파일이어야합니다.


5
@alexis : 정말 따라 갈지 모르겠습니다. 그렇게 bash < script하면 본질적으로와 동일한 결과를 얻을 수 있습니다 source script. 실행 비트 검사는 어떤 보호 기능을 제공합니까?
눈에 띄는 컴파일러

27
@alexis, 해석하는 스크립트의 권한을 확인하는 것은 통역사가 아닙니다. 아무것도 이하지 않는다 -하지 파이썬이 아니라 루비가 아닌 자바 가상 머신, 다른하지 임의 껍질. 실행 비트는 execv인터프리터가 실행할지 여부가 아니라 OS * syscalls 제품군을 실행 파일과 함께 사용할 수 있는지 여부를 제어합니다 . 규칙을 위반하여 사람들을 혼동하고 파일이 아닌 소스에서 스트리밍 된 코드를 평가하는 기능을 어기는 이유는 무엇입니까?
Charles Duffy

14
@alexis, ... 또한, 실행 가능하지 않은 쉘 라이브러리를 갖는 귀중한 의미가 있습니다. "저는 명령이 아니라 라이브러리입니다-소스, 실행하지 마십시오". 그렇지 않으면 소스로만 사용되는 코드의 오용을 감지하고 해결하기 위해 코드를 작성해야하지만 + x 권한이 없어서 사용자가 라이브러리를 오용하지 않도록 할 수 있습니다.
Charles Duffy

6
@alexis "저자에 의한 결정"포함되지 않은 다른 모든 가능한 코드는 결정이라는 의미에서만. 쉘은 읽을 파일을 열어서 명령을 읽습니다. 읽기 권한을 확인하지는 않을 것입니다. 파일을 열려고 시도하면 실패합니다. 마찬가지로 파일을 읽는 것과 관련이 없기 때문에 쓰기 또는 실행 권한을 확인하지 않습니다.
랜디 올리 슨

2
@alexis 이것은 실제로는 예를 들어 python의 virtualenv와 함께 사용되며,이를 활성화하는 스크립트는 소스 화되고 실행 bin/activate되지 않으므로 실행 가능한 비트가 없습니다. 스크립트는 완전히 라이브러리 또는 다른 것들 일 수 있습니다. 나는 .sh가 신호일지도 모른다고 생각하지만 최소한의 ./bin/activate. bin/activate
풋건을

20

비 setuid 및 비 setguid 파일의 실행 비트 (나머지와 달리)는 보안 메커니즘이 아닙니다. 읽을 수있는 것, 간접적으로 실행할 수있는 것, 그리고 리눅스는 실행할 수는 있지만 직접 읽을 수없는 것을 간접적으로 읽을 수있게합니다 (비 세트 (g) uid x-bit라는 개념에 구멍을 뚫기에 충분해야합니다) 보안 조치).

비트가 설정되어 있으면 시스템이 직접 나를 위해 실행하도록하십시오. 그렇지 않으면 간접적으로 수행해야합니다 ( bash the_script;또는 읽기 권한 없음 실행 파일의 메모리 이미지를 얻으려면 일부 해킹 ).

소스가 아닌 소스를 실행하려는 경우 편의를 위해이를 설정할 수 있습니다.

그러나 많은 공유 라이브러리 구현 자들이 여러분의 생각을 공유하고 결과적으로 많은 시스템은 쉘 기본적으로 동등하지 않은 공유 라이브러리가 사용 가능하도록 실행 가능으로 표시되도록 요구합니다. 공유 라이브러리가 실행 가능한 이유를 참조하십시오 . .


3
@ Motte001 원하는 경우 첨부 파일을 실행할 수 있습니다. 편리합니다.
PSkocik 2016 년

2
실행 파일 비트는 보안을위한 것이 아닙니다. 파일을 소유 한 경우 자유롭게 chmod사용할 수 있습니다. 프로그램에서 데이터를 정렬하기위한 것이므로 OP의 질문은 합리적입니다.
Alexis

1
@ Motte001 이것은 GUI 파일 브라우저 / 메일 응용 프로그램의 보안 기능 중 하나입니다. 이름이 ".sh"로 끝나는 파일을 두 번 클릭하는 것이 터미널 (Windows 스타일)에서 실행되거나 반대로 "다운로드 한 첨부 파일"디렉토리에서 파일을 클릭하면 내장 된 샌드 박스 미리보기 앱이 호출됩니다. x비트는 읽기 / 무엇을해야하는지의 힌트를 쓸 수 있습니다 단지 여분의 장소입니다.
IMSoP

3
실행 비트가 필요한 이유 중 하나 는 setuid 프로그램, 특히 루트 소유의 프로그램을 실행하는 것입니다. 확실히 스스로 실행할 수는 있지만 필요한 권한을 갖도록 OS를 실행해야합니다. 다른 경우에는 정말 편리합니다.
Waleed Khan

2
"리눅스는 / proc를 통해 실행할 수있는 모든 것을 읽을 수있게 해줄 것이다" -음, 내 주식 데비안 커널은 그렇지 않습니다 : /tmp$ cp /bin/cat ./cat ; chmod a-rw ./cat ; ./cat & cp /proc/$!/exe /tmp/cat2->cp: cannot stat ‘/proc/16260/exe’: Permission denied
ilkkachu

9

그건 좋은 질문이야! 유닉스는 실행 가능한 비트를 사용하여 프로그램과 데이터를 구별합니다. 소스 스크립트는 새로운 프로세스로 실행하기 위해 OS로 전달되지 않기 때문에 OS는 실행 비트가 필요하지 않습니다. 그러나 쉘은 소스 스크립트를 프로그램으로 취급하고 소스 $PATH파일을 찾습니다 . 따라서 쉘 자체는 소스 파일에 대한 실행 권한이 필요할 수 있습니다. 그러나 그렇지 않았습니다.

질문은 오래 전에 나왔을 것입니다. Bourne 쉘의 설계는 Bell Labs의 수십 명의 사람들 사이에서 "오래된 수정, 대화, 토론"의 결과 였으며, SR Bourne과 다른 사람들이 수년 동안 많은 설계 결정을 논의했습니다. 불행히도, 내 훑어보기에서 소스 기능에 대한 토론을 찾지 못했습니다 (방어에서는 그것을 구글하기가 어렵습니다). 내가 찾은 것은 "." Bourne이 직접 셸을 처음 소개 할 때는 command 명령이 나타나지 않지만보다 성숙한 버전 7 버전에 있습니다.

결석 한 권위자, 여기 내 자신의 해석이 있습니다.

  1. .명령은 일명 source, (같은 효과 텍스트 포함에 #include실행중인 스크립트 또는 대화 형 세션의 소스 코드에 C 프리 프로세서에서). 따라서 포함 된 파일은 "실행"되지 않을 수 있습니다.

  2. 유닉스 철학은 항상 프로그래머에게 자신을 걸기에 충분한 로프를 제공하는 것이 었습니다. 너무 많은 손을 잡고 임의의 제한이 방해가됩니다. 최근에는 일부 배포판에서 rm -r /요청한 작업을 거부했습니다. (이 명령은 컴퓨터의 모든 것을 삭제rm 하도록 지시 합니다. 루트로 시도하지 마십시오! 또는 더 나아진 것은 아닙니다.) 따라서 Bourne at al. 방금 파일을 소스하려고 할 때 수행중인 작업을 알고 있다고 가정했습니다. 또한 불필요한 작업을 피할 수 있으며 그 당시에는주기가 크게 중요했습니다.


그러나 하나는해야 확실히 하지 @cat 말한 않습니다.
TOOGAM

@TOOGAM이 플래그 지정 및 삭제되지 않은 것에 대해 놀랐지 만 / s에 넣었습니다!
고양이

거기에서 나는 @cat이 무엇을 썼는지 알지 못하지만 그 대답을 훨씬 더 어린이에게 증명했습니다. (그러나, 그것은 이미 상황에서 충분히 분명했습니다.)
Alexis

4

OS와 관련하여 쉘 스크립트를 포함하는 파일은 데이터 일뿐입니다. 이러한 데이터 파일 이름을 source명령에 전달하거나 명령 행에서 bash 쉘 호출에 전달하면 모든 OS에 데이터가 포함 된 파일 이름과 일치하는 문자열이 표시됩니다.

이 경우 실행 비트는 어떻게 관련이 있습니까?


3

쉘 명령 파일이 실행 파일로 유용하지는 않지만 소싱 할 때만 유용 할 수 있으므로 구별이 중요합니다. 이 파일의 경우 실행 비트를 끌 수 있으며 소스 명령에 명시 적으로 명시되어 있지 않으면 액세스 할 수 없습니다. 그러한 이유는 그것이 실행되는 쉘에 부작용이 있기 때문입니다. 구체적인 예를 들어, 경로를보고 수정하는 fix_path라는 스크립트가 있습니다.


1

누군가가 추가 연구 및 / 또는 설명에 관심이있는 경우 : 얼마 전에 구현 된 거의 POSIX 호환 쉘에서 'exec_program ()'및 'builtin_source ()'함수의 내부 작업은 매우 모범적입니다. 이 기능들에서 당신은 그 차이점이 무엇인지 정확히 알 수 있습니다.

https://github.com/rsenn/shish/blob/master/src/builtin/builtin_source.c

https://github.com/rsenn/shish/blob/master/src/exec/exec_program.c

기본적으로 소싱은 쉘이 내부 스크립트를 구문 분석하는 내부 파일 디스크립터를 일시적으로 경로 재지 정하는 것으로 볼 수 있습니다 (대화식 모드의 터미널). 그래서 같은 다른 경로 재 지정과 매우 유사 <input_file.txt하고 >>append_to_something.list이 그냥 파일을 열고 닫을 필요합니다.

따라서 execve()실행 비트는 필수 인 시스템 호출에 의해 실행이 처리됩니다 .

ELF / a.out 바이너리 실행을 허용하지만 "/lib/ld-dynamic-linker.so"실행과 바이너리 프로그램 (exec 비트 제외)을 첫 번째 인수로 사용하여 일부 시스템을 본 적이 있습니다. 나는 그것이 일부 DEC Alpha 또는 VAX 시스템에 있다고 생각합니다 (SCO Unix 일 수 있었습니까?)


-2

다른 관점 :

소스 스크립트는 기본적으로 쉘 내장 및 프로그램 호출로 구성됩니다. 쉘 내장 ( source그들 과 함께 )은 쉘의 일부이며 쉘은 먼저 실행 가능해야합니다. 호출 된 모든 프로그램 (ELF, shebang이있는 다른 스크립트)에는 실행 비트가 설정되어 있어야합니다. 그렇지 않으면 실행되지 않습니다.

따라서 실행 비트가 없으면 아무것도 실행되지 않기 때문에 실행 비트 사용에 반대되지 않습니다. 소스 스크립트는 전체적으로 유효성 검사가 수행되지 않습니다. 모든 부분에 대해 개별적으로 수행되지만 그렇지 않습니다.


쉘 빌드 인은 쉘 스크립트에서 제공되지 않습니다. 일반적으로 이들은 셸 실행 파일의 일부입니다. ksh93, zsh 및 몇 가지 다른 셸에서 셸 확장이 될 수 있습니다.
fpmurphy

@ fpmurphy1이 문장이 "shell builtins (...)는 쉘의 일부"입니까?
Kamil Maciorowski 2016 년
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.