Overview
Comment: | use `#pragma optimize` blast shield to prevent optimization segfaults on GCC |
---|---|
Downloads: | Tarball | ZIP archive | SQL archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA3-256: |
193c0650417b567d55cda11be7e15f72 |
User & Date: | lexi on 2019-07-25 23:28:30 |
Other Links: | manifest | tags |
Context
2019-07-25
| ||
23:29 | remove debug code oops check-in: 6db4e12bdd user: lexi tags: trunk | |
23:28 | use `#pragma optimize` blast shield to prevent optimization segfaults on GCC check-in: 193c065041 user: lexi tags: trunk | |
11:08 | fix typo check-in: 10946f3ca5 user: lexi tags: trunk | |
Changes
Modified nkvd.c from [1b97491783] to [ef67c2aa68].
4 4 * $ cc -fPIC -pie nkvd.c -Wl,-E -onkvd -ldl 5 5 * [-D_NO_GNU [-D_LIBC=…]] [-D_CONF_HOME=…] 6 6 * $ export LD_PRELOAD=nkvd.so <dissident> 7 7 * 8 8 * ! NOTE: for unknown reasons, nkvd currently only works 9 9 * when built without optimizations. it's probably that 10 10 * wrecker Trotsky's fault. i'm working on it. 11 + * - partial solution on GCC: using #pragma to disable 12 + * optimization around the sensitive code. unclear if 13 + * this bug affects other compilers. 14 + * - bizarre complication: the bug can only be reproduced 15 + * if the -O flag itself is present; turning on the 16 + * same individual optimization flags that -O<x> is 17 + * supposed to represent does not trigger the problem. 18 + * - conclusion: compiler devils. 11 19 * 12 20 * ! WARNING: test this program thoroughly before you start 13 21 * exporting it from your shellrcs; if things get fucked, 14 22 * you may not be able to execute any binaries with the 15 23 * variable set, and will need to log in as root or boot 16 24 * off a rescue disk to fix the problem. LD_PRELOAD is 17 25 * not a toy. you have been warned. ................................................................................ 102 110 * 103 111 * TODO: exempt xdg dirs beginning with ~/. from proscription 104 112 * in nkvd_interdict_all=1 mode 105 113 */ 106 114 107 115 #include <stdarg.h> 108 116 #include <unistd.h> 109 -#include <sys/stat.h> 110 117 #include <sys/types.h> 111 118 #include <fcntl.h> 112 119 #include <limits.h> 113 120 #include <stdlib.h> 114 121 #include <pwd.h> 115 122 #ifdef _NO_GNU 116 123 /* the POSIX version of basename is a goddamn mess and ................................................................................ 119 126 # define SYMSRC hnd 120 127 #else 121 128 /* glibc's basename() is imported from <string.h> via 122 129 * the following directive. i have no idea how this 123 130 * magic works unless they're abusing asm declarations */ 124 131 # define _GNU_SOURCE /* for basename() */ 125 132 # define __USE_GNU /* for RTLD_NEXT */ 126 -# define SYMSRC RTLD_NEXT 133 +# ifdef _USE_RTLD_NEXT 134 +# define SYMSRC RTLD_NEXT 135 +# else 136 +# define SYMSRC hnd 137 +# endif 127 138 #endif 128 139 #include <string.h> 129 140 #include <dlfcn.h> 141 +#include <stdio.h> 130 142 131 143 #ifndef _LIBC 132 -# define _LIBC "libc.so" 144 +# define _LIBC "libc.so.6" 133 145 #endif 134 146 135 147 #ifndef _CONF_HOME 136 148 # define _CONF_HOME ".config" 137 149 #endif 138 150 139 151 ................................................................................ 280 292 # endif 281 293 return (mode == whitelist); 282 294 # ifdef _NO_GNU 283 295 } 284 296 # endif 285 297 } 286 298 287 -#define STAT_PARAMS const char* volatile path, struct stat* statbuf 288 -#define XSTAT_PARAMS int ver, const char* volatile path, struct stat* statbuf 299 +#pragma GCC push_options 300 +#pragma GCC optimize ("O0") 301 + 302 +#define STAT_PARAMS const char* volatile path, struct stat* volatile statbuf 303 +#define XSTAT_PARAMS int volatile ver, const char* volatile path, struct stat* volatile statbuf 289 304 #define decl_stat_ptr(nm) static int (*libc_##nm) (STAT_PARAMS) 290 305 #define decl_xstat_ptr(nm) static int (*libc_##nm) (XSTAT_PARAMS) 291 306 292 307 static int (*libc_open) (const char*,int,...); 293 308 static int (*libc_unlink)(const char*); 294 309 295 310 decl_stat_ptr(stat); ................................................................................ 300 315 #ifndef _NO_GNU 301 316 decl_xstat_ptr(xstat); 302 317 decl_xstat_ptr(xstat64); 303 318 decl_xstat_ptr(lxstat); 304 319 decl_xstat_ptr(lxstat64); 305 320 #endif 306 321 307 -int nkvd_stat(int (*fn)(STAT_PARAMS), STAT_PARAMS) { 322 +int nkvd_stat(int (*volatile fn)(STAT_PARAMS), STAT_PARAMS) { 323 + printf(bold("nkvd") " stat: %p\n", fn); 308 324 if (intercept) { 309 325 size_t plen = strlen(path); 310 326 char gulag[redir_len + plen]; 311 327 if (interrogate(path, plen, gulag)) { 312 328 return (*fn)(gulag,statbuf); 313 329 } 314 330 } 315 331 return (*fn)(path,statbuf); 316 332 } 317 333 318 -int nkvd_xstat(int (*fn)(XSTAT_PARAMS), XSTAT_PARAMS) { 334 +int nkvd_xstat(int (*volatile fn)(XSTAT_PARAMS), XSTAT_PARAMS) { 335 + printf(bold("nkvd") " xstat: %p\n", fn); 319 336 if (intercept) { 320 337 size_t plen = strlen(path); 321 338 char gulag[redir_len + plen]; 322 339 if (interrogate(path, plen, gulag)) { 323 340 return (*fn)(ver,gulag,statbuf); 324 341 } 325 342 } ................................................................................ 336 353 337 354 #ifndef _NO_GNU 338 355 def_xstat_fn(__xstat,xstat); 339 356 def_xstat_fn(__xstat64,xstat64); 340 357 def_xstat_fn(__lxstat,lxstat); 341 358 def_xstat_fn(__lxstat64,lxstat64); 342 359 #endif 360 + 361 +#pragma GCC pop_options 343 362 344 363 int unlink(const char* volatile path) { 345 364 if (intercept) { 346 365 size_t plen = strlen(path); 347 366 char gulag[redir_len + plen]; 348 367 if (interrogate(path, plen, gulag)) { 349 368 return (*libc_unlink)(gulag); ................................................................................ 369 388 return (*libc_open)(path, flags, m); 370 389 } 371 390 372 391 int nkvd_init(int argc, const char** argv) { 373 392 wiretap_argc = argc; 374 393 wiretap_argv = argv; 375 394 376 -# ifdef _NO_GNU 377 - /* RTLD_NEXT is unfortunately a glibc extension, so in 378 - * the _NO_GNU case we need to load open() via other 379 - * means. */ 395 +# ifndef _USE_RTLD_NEXT 396 + /* RTLD_NEXT is buggy as hell so we avoid it by default */ 380 397 void* SYMSRC = dlopen(_LIBC,RTLD_LAZY); 381 398 if (SYMSRC == NULL) 382 - fail(-2,"compiled in non-glibc mode and cannot load " 399 + fail(-2,"compiled in non-RTLD_NEXT mode and cannot load " 383 400 "libc from " bold(_LIBC) "; please recompile " 384 - " and specify your libc with -D_LIBC= on the" 401 + " and specify your libc with -D_LIBC= on the " 385 402 "compile command line."); 386 403 # endif 387 404 388 405 # define load_fn(fn,pfx) libc_##fn = dlsym(SYMSRC, #pfx #fn) 389 406 load_fn(open,); load_fn(unlink,); 390 407 load_fn(stat,); load_fn(lstat,); 391 408 load_fn(stat64,); load_fn(lstat64,);