2013년 1월 23일 수요일

selinux 001 둘러보기

구글에서 공개된 현재 최신 버전인 안드로이드(android 4.2.1_r1)에서 SELINUX 부분만 떼서 분석을 해 보려고 한다.

그 첫번째... extras 패치 내용... (이K님 감사합니다.)

extras는 말 그대로 엑스트라들을 모아놓은 폴더이다.

어디 넣기 애매한 것들...

android/system/extras/ext4_utils를 보면

ext4 파일 시스템을 만들어 주는 유틸리티가 있다.

int wipe_block_device(int fd, s64 len)
{
        u64 range[2];
        int ret;

        range[0] = 0;
        range[1] = len;
        ret = ioctl(fd, BLKSECDISCARD, &range);
        if (ret < 0) {
                range[0] = 0;
                range[1] = len;
                ret = ioctl(fd, BLKDISCARD, &range);
                if (ret < 0) {
                        warn("Discard failed\n");
                        return 1;
                } else {
                        warn("Wipe via secure discard failed, used discard instead\
n");
                        return 0;
                }
        }

        return 0;
}

파일 시스템 wipe out 해주는 부분도 여기 있다.
시스템 레벨에 있어서 그런지 icotl 명령어가 있다.
여기다가 먼 코딩을 해 놓으면 wipe out 할 때 시스템 명령어를 써서 뭔짓을 할 수 있겠군.

암튼, 대충 이런 용도로 쓰는 이곳에 SELINUX를 어떻게 포팅하였는지 알아보자.


소스를 보면

ifeq ($(HAVE_SELINUX), true)
LOCAL_C_INCLUDES += external/libselinux/include
LOCAL_SHARED_LIBRARIES += libselinux
LOCAL_CFLAGS += -DHAVE_SELINUX
endif # HAVE_SELINUX

이런 친구들이 잔뜩있다.

보면

다 같은 구문

include $(CLEAR_VARS)는 android/build/core/clear_vars.mk를 인클루드 해서
VARIABLES를 다 지운다. 새출발을 위한 준비.

HAVE_SELINUX가 있는지 다 체킹해서 있으면 selinux library를 넣어준다.

얜 Buildconfigration file에 지정되어 있으면 같이 빌드가 되는 것이겄지.


content.c를 보면

int inode_set_selinux(u32 inode_num, const char *secon)
{
        struct ext4_inode *inode = get_inode(inode_num);
        u32 *hdr;
        struct ext4_xattr_entry *entry;
        size_t name_len = strlen(XATTR_SELINUX_SUFFIX);
        size_t value_len;
        size_t size, min_offs;
        char *val;

        if (!secon)
                return 0;

        if (!inode)
                return -1;

        hdr = (u32 *) (inode + 1);
        *hdr = cpu_to_le32(EXT4_XATTR_MAGIC);
        entry = (struct ext4_xattr_entry *) (hdr+1);
        memset(entry, 0, EXT4_XATTR_LEN(name_len));
        entry->e_name_index = EXT4_XATTR_INDEX_SECURITY;
        entry->e_name_len = name_len;
        memcpy(entry->e_name, XATTR_SELINUX_SUFFIX, name_len);
        value_len = strlen(secon)+1;
        entry->e_value_size = cpu_to_le32(value_len);
        min_offs = (char *)inode + info.inode_size - (char*) entry;
        size = EXT4_XATTR_SIZE(value_len);
        val = (char *)entry + min_offs - size;
        entry->e_value_offs = cpu_to_le16(min_offs - size);
        memset(val + size - EXT4_XATTR_PAD, 0, EXT4_XATTR_PAD);
        memcpy(val, secon, value_len);
        inode->i_extra_isize = cpu_to_le16(sizeof(struct ext4_inode) - EXT4_GOOD_OL
D_INODE_SIZE);

        return 0;
}

요렇게 되어 있다.

https://ext4.wiki.kernel.org/index.php/Ext4_Disk_Layout
보면


Extended attributes (xattrs) are typically stored in a separate data block on the disk and referenced from inodes via inode.i_file_acl*. The first use of extended attributes seems to have been for storing file ACLs and other security data (selinux)

 selinux를 xattr 영역에 넣는거다.

같은 폴더의

make_ext4fs.c를 보면

ret = inode_set_selinux(entry_inode, dentries[i].secon);
if (ret)
error("failed to set SELinux context on %s\n", dentries[i].path);

해당 함수를 쓰는 부분이 나온다.

int make_ext4fs(const char *filename, s64 len,
                const char *mountpoint, struct selabel_handle *sehnd)
함수 인자로도 들어가 있다.

여기까지만 봐도 ext4 파일 시스템을 만들 때 selinux를 위한 정보가 들어가는 것을 알 수 있다.

if (directory)
root_inode_num = build_directory_structure(directory, mountpoint, 0, android, sehnd);
else
디렉토리 구조 만들때에도...


struct ext4_xattr_entry {
    __u8 e_name_len;
    __u8 e_name_index;
    __le16 e_value_offs;
    __le32 e_value_block;
    __le32 e_value_size;
    __le32 e_hash;
    char e_name[0];
};
라는 xattr.h가 추가되었다.

위키보면

Offset Type Name Description
0x0 __u8 e_name_len Length of name.
0x1 __u8 e_name_index Attribute name index.
0x2 __le16 e_value_offs Location of this attribute's value on the disk block where it is stored. Multiple attributes can share the same value.
0x4 __le32 e_value_block The disk block where the value is stored. Zero indicates the value is in the same block as this entry.
0x8 __le32 e_value_size Length of attribute value.
0xC __le32 e_hash Hash value of name and value.
0x10 char e_name[e_name_len] Attribute name. Does not include trailing NULL. 

더 자세한건 소스레벨 공부~ ext4 파일 시스템도 알아야 겠지만 리눅스쪽 공부는 더이상 하기 싫다. PE 파일 배웠던 거나 완전히 내것으로 만들고 싶은데..


extras 에 selinux 관련 파일

android/system/extras/ext4_utils/

Android.mk
contents.c
contents.h
make_ext4fs.c
make_ext4fs.h
make_ext4fs_main.c
mkuserimg.sh
xattr.h


결론 seandoird는 ext4 파일시스템에 xattr에다가 secon{security context(?)}정보를 써 넣는다.

댓글 8개:

  1. selinux 라이브러리를
    import android.os.SELinux;


    임포트 할 수 있으면

    if (!SELinux.isSELinuxEnabled()) {

    로 SEAndroid 상태를 알 수 있다.

    SELINUX에서는 sestatus 명령어로 확인 가능하다.


    root@cooler-desktop:~# sestatus
    SELinux status: enabled
    SELinuxfs mount: /selinux
    Current mode: permissive
    Mode from config file: permissive
    Policy version: 24
    Policy from config file: ubuntu

    답글삭제
  2. android libcore dalvik에 보면


    /**
    * Forks a new VM instance. The current VM must have been started
    * with the -Xzygote flag. NOTE: new instance keeps all
    * root capabilities. The new process is expected to call capset()
    .
    *
    * @param uid the UNIX uid that the new process should setuid() to after
    * fork()ing and and before spawning any threads.
    * @param gid the UNIX gid that the new process should setgid() to after
    * fork()ing and and before spawning any threads.
    * @param gids null-ok; a list of UNIX gids that the new process should
    * setgroups() to after fork and before spawning any threads.
    * @param debugFlags bit flags that enable debugging features.
    * @param rlimits null-ok an array of rlimit tuples, with the second
    * dimension having a length of 3 and representing
    * (resource, rlim_cur, rlim_max). These are set via the posix
    * setrlimit(2) call.
    * @param seInfo null-ok a string specifying SEAndroid information for
    * the new process.
    * @param niceName null-ok a string specifying the process name.
    *
    * @return 0 if this is the child, pid of the child
    * if this is the parent, or -1 on error.
    */
    가 들어있는 함수 놈이 있다.

    답글삭제
    답글
    1. www.kandroid.org _
      안드로이드 런타임은, 안드로이드에서 사용되는 Dalvik 가상 머신과 Core 라이브러리들로 구성된다.
      Dalvik 가상머신은 안드로이드에서 자체적으로 만든 것으로 clean-room(청정영역)을 제공하는 가상 머신이다.
      이것은 이것은, 애플리케이션의 호환성(Portability)과 실행 일관성(runtime consistency)을 제공하며, 최적화된 파일 포맷
      (.dex)과 Dalvik 바이트 코드를 실행한다. 더불어 빌드 시점에서 Java .class / .jar 파일들은 .dex 파일로 변환된다.
      Dalvik 가상머신은 임베디드 환경을 위해 디자인 되었다. Dalvik은 디바이스 별로 다양한 가상머신 프로세스들을 지
      원하며, 높은 수준으로 CPU에 최적화된 바이트코드 인터프리터에 기반하며, 실행시 메모리를 매우 효율적으로 사용
      한다.
      Cora 라이브러리들은 강력하지만, 단순하고 익숙한 개발 플랫폼을 제공하는 Java 언어를 위한 Core API들을 포함
      하고 있다. 여기에는 Data structure, Utility, File Access, Network Access, Graphic 등이 포함되어 있다.

      삭제
  3. forkAndSpecialize
    public static int forkAndSpecialize(int uid,
    int gid,
    int[] gids,
    int debugFlags,
    int[][] rlimits)Forks a new VM instance. The current VM must have been started with the -Xzygote flag. NOTE: new instance keeps all root capabilities. The new process is expected to call capset().

    Parameters:
    uid - the UNIX uid that the new process should setuid() to after fork()ing and and before spawning any threads.
    gid - the UNIX gid that the new process should setgid() to after fork()ing and and before spawning any threads.
    gids - null-ok; a list of UNIX gids that the new process should setgroups() to after fork and before spawning any threads.
    debugFlags - bit flags that enable debugging features.
    rlimits - null-ok an array of rlimit tuples, with the second dimension having a length of 3 and representing (resource, rlim_cur, rlim_max). These are set via the posix setrlimit(2) call.
    Returns:
    0 if this is the child, pid of the child if this is the parent, or -1 on error.

    --------------------------------------------------------------------------------
    http://www.androidjavadoc.com/1.1_r1_src/dalvik/system/Zygote.html

    답글삭제
  4. 1. 자바프로세스가 Zygote에 의해 포크됨
    2. ZygoteInit.main()메서드가 ActivityThread.main()을 호출한다.
    ActivityThread.main()은 Looper.prepareMainLooper() 를 호출 한후 메인 메시지를 초기화 한다.
    3. ActivityThread는 ActivityThread의 인스턴스가 생성된 후 AplicationThread를
    생성시킨 다음 system_server 프로세스의 IBinder 객체를 이용해서
    ActivityManagerService서비스와 상호작용을하며 IPC콜을 기다린다.
    4. 애플리케이션에서 실행되어야할 액티비티가 있다면 ActivityManagerService가
    RPC 호출을 통해 애플리케이션 프로세스의 ApplicationThread.scheduleLaunchActivity()를
    실행 시킨다.
    5. ApplicationThread는 APplication과 ApplicationContext객체를 생성시키고
    Instrumentation을 통해서 액티비티 자바 객체를 생성한 후 액티비티의 onCreate()를 호출함


    http://blog.daum.net/urlover/17049847

    답글삭제
  5. public static int forkAndSpecialize(int uid, int gid, int[] gids,
    int debugFlags, int[][] rlimits, String seInfo, String niceName) {

    요렇게 2개 더 들어간다.

    답글삭제
  6. 룰... 룰로 들어 간다.

    정책은 리눅스 subject, object 그리고 what to do 를 알아야 제대로 정할 수 있다.

    답글삭제
  7. Permission
    Description

    append
    Append to file contents (that is, opened with O_APPEND flag).

    create
    Create new file.

    entrypoint*
    File can be used as the entry point of the new domain via a domain transition.

    execmod*
    Make executable a file mapping that has been modified (implied by a copy-on-write).

    execute
    Execute; corresponds to x access in standard Linux.

    execute_no_trans*
    Execute file in the caller's domain (that is, without a domain transition).

    getattr
    Get attributes for file, such as access mode (for example, stat, some ioctls).

    ioctl
    ioctl(2) system call requests not addressed by other permissions.

    link
    Create hard link to file.

    lock
    Set and unset file locks.

    mounton
    Use as mount point.

    quotaon
    Allow file to be used as a quota database.

    read
    Read file contents; corresponds to r access in standard Linux.

    relabelfrom
    Change the security context from the existing type.

    relabelto
    Change the security context to the new type.

    rename
    Rename a hard link.

    setattr
    Change attributes for file such as access mode (for example, chmod, some ioctls).

    swapon
    Deprecated; was used to allow file to be used for paging/swapping space.

    unlink
    Remove hard link (delete).

    write
    Write file contents; corresponds to w access in standard Linux.



    SELinux by Example 내용이다. 파일 오브젝트 클레스의 퍼미션이 그리 많지 않다. 뒤에 * 붙는건 먼 뜻인지...
    *란 것은 뒤의 퍼미션들을 모두 포함한다는 뜻이다.

    하기 커널 로그를 보자.
    type=1400 audit(1360394478.404:8): avc: denied { read } for pid=846 comm="PackageManager" name="com.google.android.googlequicksearchbox-1" dev="mmcblk0p28" ino=389806 scontext=u:r:system:s0 tcontext=u:object_r:app_files:s0 tclass=dir

    이런 에러가 났다면
    allow 해주고 scontext가 소스니까
    system 타입을 적어 준다.
    타켓은 app_files 이니 적어 주고
    타켓 클레스엔 dir에 read 권한을 주어 한다는 뜻.

    allow system app_files:dir { read };
    요렇게 되는 것.


    답글삭제

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

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...