* SMACK 원리

[SMACK] 스맥체크의 7가지 단계


* SMACK Manifest

[SMACK] 스맥 레이블을 긋기 위한 manifest의 모든 것 - 파일편

[SMACK] 스맥 레이블을 긋기 위한 manifest의 모든 것 - DBUS편


* SMACK 기능

[SMACK] 스맥에서 onlycap으로 root 권한 축소하기


* SMACK 사용하기

[SMACK] 쉘의 /proc/self/attr/current로 스맥권한 조종하기


* SMACK & Privilege

[SMACK] 타이젠 Privilege의 모든 것



SMACK을 사용하는 시스템에 있는 파일들은,

언제 스맥 레이블이 그어질까요?

파일이 설치되는 시점입니다.


- 사용자가 직접 파일을 생성/다운로드/카피/이동하는 경우

사용자가 직접 파일을 생성/다운로드/카피/이동하면,

사용프로세스 혹은 이동디렉토리의 스맥권한이 파일에 새겨집니다.


- 패키지를 풀어 그 안의 파일들을 설치하는 경우

패키지를 풀어 파일을 설치하면,

패키지를 만드는 시점에 지정한 방식으로 스맥레이블이 그어지겠지요.


이 포스팅에서는 패키지를 생성하는 시점에 "파일/디렉토리"에 스맥 레이블을 긋는 방법을 공유하도록 하겠습니다.



패키징하는 시점에 이미 존재하는 파일에는,

패키지마다 하나씩 존재하는 manifest 파일로 스맥 권한을 부여할 수 있습니다.

manifest 파일은 [패키지이름].manifest로 이름을 지어주게 됩니다.

어차피 패키지 내에 하나만 있으므로 패키지이름으로 지어주어도 되지요.


manifest 파일은 xml을 사용합니다.

최상위 태그는 <manifest></manifest>로 시작하지요.


<manifest>
    ...
</manifest>

manifest에는 패키지에서 사용할 스맥레이블을 정의할 수 있습니다.

여기서 정의한 레이블은 레이블을 정의한 방식에 따라,

한 패키지에서만 독점적으로 사용하거나,

다수의 패키지에서 사용할 수 있습니다.


<define> <domain name="YOUR_SMACK_LABEL" /> </define>

위의 예처럼 <domain> 태그로 스맥레이블을 정의할 수 있습니다.

레이블은 255자 이하로 지을 수 있습니다.

"A-Z", "a-z", "0-9", "_", "-", "."의 문자만 사용해야 합니다.

도메인 이름은 위에 명시된 문자들을 조합하여 고유하게 만들어야합니다.

그렇기 때문에 패키지이름으로 짓기도 하지요.


<define> <domain name="YOUR_SMACK_LABEL" policy="shared" /> </define>

위처럼 policy를 shared로 지정하여 다른 패키지에서도 스맥레이블을 사용할 수 있게 설정할 수 있습니다.

policy가 없으면 default는 private로 설정되게 됩니다.

오직 정의한 패키지에서만 사용할 수 있는 스맥레이블이 되는 셈이지요.

만약 private로 정의한 스맥 레이블과 동일한 스맥 레이블을 가진 패키지가 설치된다면,

나중에 설치되는 패키지는 설치할 수 없게 됩니다.

따라서 스맥레이블을 고유한 이름을 지정하는 것이 중요합니다.


<define> <domain name="YOUR_SMACK_LABEL" policy="restricted" plist="package1,package2" /> </define>

policy가 restricted로 설정되어 있으면,

스맥레이블을 정의하는 시점에 이 스맥을 사용할 수 있는 패키지를 선택할 수 있습니다.

다른 패키지와 스맥 레이블을 공유하지만 제한적으로 공유하게 됩니다.

plist, 곧 패키지 리스트에 명시된 패키지 이름만 여기서 정의하는 스맥레이블을 사용할 수 있습니다.


<define> <domain name="YOUR_SMACK_LABEL policy="shared" /> <request> <smack request="OTHER_SMACK_LABEL_1" type="w" /> <smack request="OTHER_SMACK_LABEL_2" type="rwxat" /> </request> </define>

직접 정의한 스맥레이블 외에 다른 패키지에 선언한 스맥레이블을 사용해야할 수도 있습니다.

다른 패키지에서 관리하는 파일에 접근하는 경우에 흔히 사용합니다.

그럴 경우, <define> 내에서 <request></request> 태그를 사용합니다.

그리고 사용하고자 하는 스맥레이블을 적고,

type으로 해당하는 스맥레이블에 원하는 권한을 적어둡니다.

위의 예에서는, YOUR_SMACK_LABEL이 Subject로, OTHER_SMACK_LABEL_1이 Object로 동작하겠지요.


<define> <domain name="YOUR_SMACK_LABEL" policy="shared" /> <permit> <smack permit="OTHER_SMACK_LABEL" type="rwx" /> </premit> </define>

permit을 정의할 수도 있습니다.

YOUR_SMACK_LABEL을 사용할때,

OTHER_SMACK_LABEL에 대한 rwx 권한도 함께 주는 것이지요.

개발자가 명시적으로 OTHER_SMACK_LABEL에 대한 권한을 요청하지 않아도 사용할 수 있게 됩니다.

다른 스맥 권한도 함께 부여하는 것이기에 사용에 주의를 기울여야합니다.


<request> <domain name="OTHER_SMACK_LABEL" /> </request>

자신이 정의한 스맥레이블을 사용하지 않고,

다른 패키지에서 정의한 스맥레이블을 기본으로 사용할 수도 있습니다.

위의 <request>는 <define>과 동일한 레벨의 <request> 태그로,

<define> 태그없이도 사용할 수 있습니다.

<define> 내에서 사용하는 <request>도 있었는데 두 개의 의미가 다릅니다.

<define> 내에서 선언한 것은,

<define>에서 정의한 도메인이 <request>에서 선언한 스맥레이블을 사용하도록 요청한 것입니다.

<define> 외에서 선언한 것은,

패키지에서 설치하는 모든 파일들을 <request>에서 설정한 스맥레이블로 지정하라는 의미이죠.

따라서 두 개의 request를 동시에 사용할 수 있습니다.

(이런 식의 작명은 별로 좋아보이지 않습니다.)


<manifest> <define> <domain name="YOUR_SMACK_LABEL" policy="restricted" plist="package1,package2" /> <request> <smack request="OTHER_SMACK_LABEL_1" type="rw" /> <smack request="OTHER_SMACK_LABEL_2" type="rx" /> </request> </define> <request> <domain name="OTHER_SMACK_LABEL_3" /> </request> </manifest>

위의 manifest를 살펴보면,

새로운 도메인 "YOUR_SMACK_LABEL"을 만들고 나서,

실제로 자신의 파일에는 "OTHER_SMACK_LABEL_3"를 사용하였습니다.

보통은 자신이 define하고 그걸 다시 request로 사용하게 됩니다.


<manifest> <request> <domain name="OTHER_SMACK_LABEL" /> </request> </manifest>

자신이 아예 define하지 않는 경우도 있습니다.

다른 패키지에서 define한 스맥레이블을 자신의 파일에 적용할 수 있습니다.


<manifest> <define> <domain name="YOUR_SMACK_LABEL" policy="shared" /> <provide> <label name="YOUR_SMACK_LABEL::COMPONENT_1" /> <label name="YOUR_SMACK_LABEL::COMPONENT_2" /> <label name="YOUR_SMACK_LABEL::COMPONENT_3" /> </provide> <permit> <smack permit="OTHER_SMACK_LABEL" to="YOUR_SMACK_LABEL::COMPONENT_1" type="rwxat" /> </permit> </define> </manifest>

위처럼 한 도메인 내에서 다수의 서브 스맥레이블을 만들 수도 있습니다.

서브도메인은 "::" 두개의 콜론으로 나눠야합니다.

위의 예에서는 <domain> 태그와 같은 레벨의 <provide> 태그를 만들고,

그 안에 세 개의 서브도메인을 만들었습니다.

서브도메인에서 정의한 스맥레이블은 모두 "::"로 도메인과 서브도메인 이름을 구분하고 있습니다.

추가로 permit을 지정하여 YOUR_SMACK_LABEL::COMPONENT_1에만,

OTHER_SMACK_LABEL을 permit 해주고 있네요.

"to"를 빼면 모든 provide된 서브도메인에 스맥레이블을 permit할 수 있습니다.


<assign> <filesystem path="/YOUR/DIRECTORY_1" label="YOUR_SMACK_LABEL::COMPONENT_1" /> <filesystem path="/YOUR/DIRECTORY_2" label="YOUR_SMACK_LABEL::COMPONENT_2" /> <filesystem path="/YOUR/DIRECTORY_3" label="YOUR_SMACK_LABEL::COMPONENT_3" /> </assign>

특정 파일에 별도의 스맥레이블을 지정할 수 있습니다.

그러려면 <assign> 태그를 사용하여야 합니다.

<filesystem> 밑에 path에 스맥레이블을 지정하고자 하는 디렉토리나 파일을 적어 놓습니다.

label에는 지정하고자 하는 스맥레이블을 적으면 됩니다.

위의 예에서는 그 전에 <provide> 태그로 설정한 스맥레이블을 지정하였습니다.


<assign> <filesystem path="/usr/local/command" label="YOUR_SMACK_LABEL::COMPONENT_1" exec_label="none" /> </assign>

실행파일에는 exec_label을 추가로 부여할 수 있습니다.

파일이 갖는 스맥레이블은 label 필드에 기입하지만,

exec_label 필드에는 프로세스가 갖는 스맥레이블을 기입합니다.


하지만, exec_label이 caller와 같은 스맥레이블을 지녀야하는 경우도 있습니다.

caller의 스맥레이블이 OTHER_SMACK_LABEL이고,

caller가 실행한 프로세스도 OTHER_SMACK_LABEL로 지정되어,

caller의 자원 중 OTHER_SMACK_LABEL로 지정된 자원에 자유롭게 접근하는 경우이지요.

그럴 때는, exec_label에 위처럼 none을 지정해주면 됩니다.


<assign> <filesystem path="/YOUR/DIRECTORY" label="YOUR_SMACK_LABEL::COMPONENT_2" type="transmutable" /> </assign>

디렉토리에 transmutable 타입을 설정할 수 있습니다.

transmutable은 디렉토리 내에서 생성하는 파일의 스맥레이블을,

파일을 생성한 프로세스의 스맥레이블이 아닌,

파일이 생성되는 디렉토리에 설정된 스맥레이블로 지정하는 경우에 사용합니다.

이 말을 뒤집어서 하면, 파일은 파일을 생성한 프로세스의 스맥레이블을 따른다는 것이지요.

transmutable은 특정 디렉토리를 다수의 프로세스에서 접근하여 사용하는 경우에 유용합니다.


<assign> <filesystem path="/YOUR/DIRECTORY/*" label="YOUR_SMACK_LABEL::COMPONENT_3" /> </assign>

디렉토리 내의 모든 파일과 디렉토리에 recursive하게 스맥레이블을 줄 수 있습니다.

디렉토리와 "*"를 사용하면 됩니다.


dbus의 interface나 method에도 스맥레이블을 부여할 수 있습니다.

이 부분은 다음에 다시 설명하도록 하겠습니다.

<무한도전>부터 보고... :)


끝_


* SMACK에 대한 이야기를 쌓아본다

http://storycompiler.tistory.com/51


* Reference

https://wiki.tizen.org/wiki/Security/Application_installation_and_Manifest


  1. 2016.08.09 16:26

    비밀댓글입니다

스맥에 대해 하나씩 정리를 해보고자 마음을 먹었습니다만,

정리해야할 내용이 너무 많아서 고민하고 있습니다.


기본적인 원리는 간단할지 모르겠으나,

원리와 원리의 적용(현실화)에는 무척이나 깊은 간극이 있습니다.


비교적 간단한 원리부터 설명하여,

틈 나는 대로 하나씩 포스팅하겠습니다.



위의 그림은 펭귄...일겁니다.

이상한 모양의 삼각형 펭귄.

SMACK의 공식 로고입니다.

SMACK에 대한 신뢰를 한 순간에 무너뜨릴 만큼 허접한 로고입니다.


SMACK은 프로세스와 파일에 Label을 긋는 것에서 시작됩니다.

SMACK이 적용된 플랫폼의 모든 파일에는 SMACK Label이 그어지게 되죠.

Label은 흔히 그 파일을 설치한 패키지 이름이나 파일의 성격에 따라 작명합니다.


한 패키지에 다수의 파일이 있으면,

같은 패키지 이름으로 모든 파일에 같은 Label을 그어줄 수도 있고,

파일의 성격에 따라 서로 다른 Label을 지을 수도 있습니다.


이처럼 사용자가 지정하는 Label 외에 스맥이 사전에 정의한 Label도 있습니다.

아래 명시되어 있는 5가지 문자가 사전에 정의된 Label입니다.


Pronounced "floor", a single underscore character.

^  Pronounced "hat", a single circumflex character.

*  Pronounced "star", a single asterisk character.

?  Pronounced "huh", a single question mark character.

@  Pronounced "web", a single at sign character.


상위 3개(_, ^, *)는 자주 사용하지만,

아래 2개(?, @)는 사용해본 적이 없습니다.

'?' Label은 실제로 사용하는지 의문입니다.

'@' Label은 앱에서 인터넷을 특정 IP 주소를 누구나 사용하도록 열어줄때 사용합니다.

이 Label 또한 자주 사용하진 않으므로 생략하겠습니다.


상위 3개는 커널 소스에서도 그대로 사용됩니다.

커널 소스를 그대로 볼 필요는 없고,

아래 7가지 단계로 되어있다고 여기시면 됩니다.


  1. Any access requested by a task labeled "*" is denied.

2. A read or execute access requested by a task labeled "^"

   is permitted.

3. A read or execute access requested on an object labeled "_"

   is permitted.

4. Any access requested on an object labeled "*" is permitted.

5. Any access requested by a task on an object with the same

   label is permitted.

6. Any access requested that is explicitly defined in the loaded

   rule set is permitted.

7. Any other access is denied.


우선 프로세스가 "*" 실행권한인지 체크합니다(1).

프로세스가 "*" 권한이라면, 어떤 파일에도 접근할 수 없습니다.

바로 Access denied 에러를 리턴하게 되겠지요.

실행파일이지만 다른 파일에는 접근하게 하고 싶지 않을때 설정하면 됩니다.


프로세스가 "^" 실행권한이 있으면(2),

파일에 어떤 label이 그어져 있건,

읽고 실행할 수 있습니다.

쓰기 권한은 없습니다.

굉장히 막강한 권한입니다.

'^'는 제한적인 프로세스에 사용해야합니다.


파일에 "_" Label이 새겨져 있으면(3),

프로세스가 읽고 실행할 수 있는 파일입니다.

라이브러리에 "_" Label을 새겨놓으면 됩니다.

어느 프로세스나 접근할 수 있게 판을 깔아놓는 셈이지요.


파일에 "*" Label이 새겨져 있으면(4),

어느 프로세스이든 접근하여 읽고 쓰고 실행할 수 있습니다.

스맥이 적용되지 않은 시스템에 있는 파일과 같은 상태인 셈입니다.

오직 리눅스 권한만이 영향을 미칠 수 있습니다.

누구나 읽고 쓰고 실행할 수 있는 파일/디렉토리에 지정하면 됩니다.


프로세스와 파일의 Label이 같다면(5),

읽고 쓰고 실행할 수 있습니다.

같은 패키지인 경우가 이에 해당합니다.

자기가 설치한 파일을 관리하는 것이죠.


룰이 적혀있는 set에 명시적으로 프로세스와 파일을 관계가 적혀있는 경우(6),

이 경우에 룰에 적혀있는 범위 내에서의 접근할 수 있습니다.

룰 set에 읽기만 언급되어 있다면,

프로세스는 파일에 대해 읽기만 가능할테지요.


그 외의 경우는 접근할 수 없습니다(7).


이상의 7단계를 차례대로 거쳐서,

프로세스의 파일에 대한 접근이 확정됩니다.


여기서 오직 '*' 기호만 프로세스와 파일에 적용할 수 있습니다.

기호는 같지만 의미는 완전히 다릅니다.

'*'가 프로세스와 쓰일때는 프로세스가 어떤 파일에도 접근할 수 없게 됩니다.

하지만, '*'가 파일에 쓰인다면 어떤 프로세스나 읽고 쓰고 실행할 수 있게 되지요.

좀 더 분명한 역할정의를 위해,

서로 다른 기호를 썼으면 좋았을거란 생각이 듭니다.


'*' 기호와는 다르게 '^'는 프로세스에서만 사용하고,

'_'는 파일에서만 사용합니다.

만약 '^'를 파일에, '_'를 프로세스에 사용하면 의도치 않은 동작을 할 수 있습니다.


끝_


* SMACK에 대한 이야기를 쌓아본다

http://storycompiler.tistory.com/51


* References

http://www.webcitation.org/6AqzohCXq

+ Recent posts