util  Diff

Differences From Artifact [1b97491783]:

To Artifact [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,);