본문 바로가기

IT

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

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