Ami
Ami

Reputation: 363

can I do nested calls for system functions loaded by LD_PRELOAD

Hi I am trying to override sscanf() which gets called from localtime(), But its not calling sscanf() of my library loaded rather its calling sscanf() of glibc.

Is there something I am missing?

Files content mentioned below:

//preload_localtime.c
#include <stdarg.h>
#include <stdio.h>
#include <time.h>
#include <dlfcn.h>


__attribute__((force_align_arg_pointer)) int sscanf(const char *str, const char *format, ...)
{
  int ret;
  va_list ap;
  printf("test\n");
  va_start(ap, format);
  ret = vsscanf(str, format, ap);
  va_end(ap);
  return ret;
}

__attribute__((force_align_arg_pointer)) int __isoc99_sscanf(const char *str, const char *format, ...)
{
  int ret;
  va_list ap;
  printf("test\n");
  va_start(ap, format);
  ret = vsscanf(str, format, ap);
  va_end(ap);
  return ret;
}
__attribute__((force_align_arg_pointer)) struct tm *
localtime(const time_t *timep)
{
    static struct tm *(*real_localtime)(const time_t *) = (void*)0;

    printf("my_local\n");
   if (!real_localtime)
        real_localtime = dlsym(RTLD_NEXT, "localtime");
    return real_localtime(timep);
}


//foo.c
#include <stdio.h>
#include <time.h>
int main(void)
{
        int i;
        //sscanf("42", "%d", &i);
        //printf("%d\n", i);

time_t rawtime;
  struct tm * timeinfo;

  time (&rawtime);
 timeinfo = localtime (&rawtime);
printf ("Current local time and date: %s", asctime(timeinfo));
        return 0;
}

Steps I am doing:

# gcc -fPIC -shared preload_localtime.c -o preload_localtime.so -ldl -D_GNU_SOURCE=1
#export LD_PRELOAD=$PWD/preload_localtime.so
gcc foo.c -o foo

output I am getting:

# ./foo
my_local
Current local time and date: Wed Mar 10 18:20:47 2021

What is expected output: It should print test as well, from printf("test\n"); of sscanf() overriden. Since localtime() internally has call to sscanf() and I have overridden and instructed to use sscanf() as well.

IS there any way to override another system call like in this example sscanf() which is internally gets called from localtime().

Call hierarchy as below:

localtime()->__tz_convert() ->__tzfile_compute() -->__tzset_parse_tz() -->parse_offset() -->sscanf()

Upvotes: 2

Views: 215

Answers (1)

Efi Weiss
Efi Weiss

Reputation: 650

LD_PRELOAD works by being the first symbol of the same name found by the dynamic linker - so if a symbol usage can be resolved in compile time, the dynamic linking won't affect it because localtime and sscanf exist in the same binary the call may very well be a static one - the call can be resolved in compile time and the dynamic linker isn't involved in this call chain.

Upvotes: 2

Related Questions