그 첫번째... 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(?)}정보를 써 넣는다.
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
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.
*/
가 들어있는 함수 놈이 있다.
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 등이 포함되어 있다.
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
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
public static int forkAndSpecialize(int uid, int gid, int[] gids,
답글삭제int debugFlags, int[][] rlimits, String seInfo, String niceName) {
요렇게 2개 더 들어간다.
룰... 룰로 들어 간다.
답글삭제정책은 리눅스 subject, object 그리고 what to do 를 알아야 제대로 정할 수 있다.
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 };
요렇게 되는 것.