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