2013년 1월 24일 목요일

selinux 004 둘러보기

core init을 살펴보자.

수정파일 부터

android/system/core/init/

Android.mk
builtins.c
devices.c / h
init.c / h
init_parser.c
keywords.h
property_service.c
util.c / h

우선 Android.mk를 보면 libselinux 피처를 넣는다.
얜(libselinux) 실재로 수행되는 녀석들 집합이라 뭘하던 들어간다.



context 관련 함수 처리 부분이 들어가 있는데

int selabel_lookup(struct selabel_handle *rec, security_context_t *con,
                   const char *key, int type)
{
        struct selabel_lookup_rec *lr;
    
        lr = selabel_lookup_common(rec, 1, key, type);
        if (!lr)
                return -1;
        
        *con = strdup(lr->ctx_raw);
        return *con ? 0 : -1;
}   
가 자주 보인다. 물론 이런 본체는 libselinux에 있다.

struct selabel_handle {
        /* arguments that were passed to selabel_open */
        unsigned int backend;
        int validating;

        /* labeling operations */
        struct selabel_lookup_rec *(*func_lookup) (struct selabel_handle *h,
                                                   const char *key, int type);
        void (*func_close) (struct selabel_handle *h);
        void (*func_stats) (struct selabel_handle *h);

        /* supports backend-specific state information */
        void *data;

        /* substitution support */
        struct selabel_sub *subs;
};

에서 

struct selabel_sub {
        char *src;
        int slen;  
        char *dst;
        struct selabel_sub *next; 
};          

요 녀석이 context에 뭔가 하는 녀석으로 보인다. oneway linked list 형태가 보여 뭔가 찜찜하지만, grep으로 찾아 보기엔 시간이 걸리고 분석 내용이 많으니 가설만 세우고 넘어가자. 

util.c에 보면 restorecon 본체도 보인다.

int restorecon(const char *pathname)
{
#ifdef HAVE_SELINUX
    char *secontext = NULL;
    struct stat sb;
    int i;

    if (is_selinux_enabled() <= 0 || !sehandle)
        return 0;

    if (lstat(pathname, &sb) < 0)
        return -errno;
    if (selabel_lookup(sehandle, &secontext, pathname, sb.st_mode) < 0)
        return -errno;
    if (lsetfilecon(pathname, secontext) < 0) {
        freecon(secontext);
        return -errno;
    }
    freecon(secontext);
#endif
    return 0;
}

흐름상, 레이블 찾아보고 file context를 적용한다. 제대로 안되면 context 해제하면서 -1을  던진다.

init.c를 보면

#ifdef HAVE_SELINUX
static const struct selinux_opt seopts_prop[] = {
        { SELABEL_OPT_PATH, "/data/system/property_contexts" },
        { SELABEL_OPT_PATH, "/property_contexts" },
        { 0, NULL }
};

저런 폴더가 사용되고

void selinux_init_all_handles(void)
{
    sehandle = selinux_android_file_context_handle();
    sehandle_prop = selinux_android_prop_context_handle();
}

핸들은 2종류고

int selinux_reload_policy(void)
{
    if (!selinux_enabled) {
        return -1;
    }

    INFO("SELinux: Attempting to reload policy files\n");

    if (selinux_android_reload_policy() == -1) {
        return -1;
    }

    if (sehandle)
        selabel_close(sehandle);

    if (sehandle_prop)
        selabel_close(sehandle_prop);

    selinux_init_all_handles();
    return 0;
}

reload 한다는건 핸들 2종류는 init한다는 것.


keywords.c에는

restorecon, setcon, setenforce, setsebool이 추가되었다.

요렇게 코어 부분 업뎃~


댓글 7개:

  1. SEAndroid policy를 만드는 일은 2가지가 필요하다. 하나는 관련해서 permissive mode에서 로그를 뽑는 일.

    다른 하나는 안드로이드 시스템 서비스나 앱 등에 어떤 보안을 제공할 것인지에 대한 일이다.

    SEAndroid 자체만으로 루티을 막는 기능이 있으나 진정한 의미의 보안을 위해서는 시스템의 각 데몬, 앱들이 원하는 시큐리티를 먼저 정의를 해야 그에 대한 보안 기능을 제공할 수 있다.

    답글삭제
  2. Type Enforcement file(.te)들은 사실 policy.conf로 합쳐지고 하나의 바이너리 파일인 sepolicy로 만들어 진다. 이 말인 즉. te 파일을 단일 파일로 만들어도 된다는 이야기 이다. 그러나 개발자 가독성 측면에서 분리를 하는데, 분리를 하던 합치던 개발자 마음이다. 각각의 모듈 담당자들이 security concern을 주었을 때 작업하는 사람은 여러명이 되어도 좋지만 관련해서 ok 혹은 no를 하는 사람은 안드로이드 시스템에 대해서 정통해 있는 사람이 하는게 맞다고 생각된다. 물론, 커널 / 프레임웍단 모두. 리눅스 커널 버전도 끊임업이 올라가고 그걸 가져다 쓰는 안드로이드 시스템도 끊임없이 변화한다. 모든 것을 캣치할 수는 없어도 어떤 식으로 변화되고 있는지 알 수 있는 기술적 힘이 있어야 SEAndroid 팀을 이끌 수 있다.

    답글삭제
    답글
    1. ㅡㅡ; 사실 리눅스 커널과 안드로이드 프레임웍에 정통해 있고, C, C++, JAVA프로그래밍은 해야 뭘 말할게 있지...

      삭제
    2. 안드로이드 커널이 시작되면서 부트로더는 리눅스 커널과 init 프로세스를 시작한다.

      init은 리눅스 데몬들을 띄워주는데

      usbd, adbd, debuggerd, rild 가 중요한 친구들이다.

      usbd는 말그대로 usb 커넥션을 위한 친구고, adbd는 Adnroid Debug Bridge의 약자
      usb가 되어야 adbd를 편하게 쓸 수 있다. adb tcpip xxx, adb connect xxxx 명령어를
      사용하면 wifi를 이용하여 접속할 수도 있다.

      rild는 릴쪽 데몬이다. 모뎀과 통신을 담당한다. 안드로이드 처음 시작할 때 맡았던
      job이 rild쪽이었는데 소스 찾기 정말 거지 같은 쪽이다.(난이도가 있다는 뜻) 큐에
      겁나 넣어주고 어데서 쇽쇽 데려가기 때문에 중간에 막 소스 끊겨 있고 그랬던 것 같다.
      모뎀쪽 바이너리는 또 다르니까 양쪽 스펙 안 맞으면 간단한 거도 안되었고
      믓튼, 위에서는 쉽게 보고 인력을 개떡같이 붙여서 고생했던 기억이 난다.
      프로젝트 딜레이도 겁나 되는거지 그럼 ㅡㅡ;
      위에서는 밑에 애들 잘 못한다고 하면 그만이고.

      그래서 무식한 사람은 올라가면 안된다. 무식한 사람 안 만들려면
      오래도록 그 일을 한 사람들을 아껴줘야 한다. 이야기가 새는군.
      (놈이라고 하고 싶지만 딸도 생기고 말을 유순하게 하고 살아야지.)

      debugd랑 adbd 차이점을 알고 싶으면 소스 ㄱㄱ
      android /system /core /debuggerd 같은 곳에 adbd

      삭제
  3. 안드로이드 시스템은 init 프로세스에서 시작된다고 보면 되는데, http://modian.tistory.com/12 에 보면 잘 정리디어 있다. 그러나 개발자면 소스레벨에서 보는게 더 도움이 될 것 같다.android/system/core/rootdir/init.rc에 모든 내용이 있다.

    답글삭제
  4. http://grepcode.com/project/repository.grepcode.com/java/ext/com.google.android/android/
    에서는 안드로이드 소스 탐색이 버전별로 가능하다.
    커널 소스를 보려면 git를 이용해서 받아야 한다.

    안드로이드의 공개된 소스 트리를 보고 싶으면
    git ls-remote -h http://android.googlesource.com/platform/manifest.git

    받고 싶으면
    curl http://android.git.kernel.org/repo > ./repo
    리포{리파지토리(저장소)} 스크립트를 받고
    repo init -u https://android.googlesource.com/platform/manifest -b android-4.2.1_r1
    repo sync
    요렇게.

    커널소스는
    git clone https://android.googlesource.com/kernel/common.git .


    git branch -a
    1.repo init -u https://android.googlesource.com/platform/manifest -b android-4.1.2_r1

    요렇게

    https://groups.google.com/forum/?fromgroups#!topic/android-building/7Mg52A9eP4s

    여기에 잘 정리되어 있다.

    답글삭제
  5. 삼성 커널은 요걸로... git clone https://android.googlesource.com/kernel/samsung.git

    답글삭제

국정원의 댓글 공작을 지탄합니다.

UPBIT is a South Korean company, and people died of suicide cause of coin investment.

 UPBIT is a South Korean company, and people died of suicide cause of coin. The company helps the people who control the market price manipu...