【问题标题】:can I do nested calls for system functions loaded by LD_PRELOAD我可以对 LD_PRELOAD 加载的系统函数进行嵌套调用吗
【发布时间】:2022-01-24 06:59:58
【问题描述】:

您好,我正在尝试覆盖从localtime() 调用的sscanf(), 但它没有调用我加载的库的sscanf(),而是调用glibc的sscanf()。

我有什么遗漏吗?

文件内容如下:

//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;
}

我正在做的步骤:

# 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

我得到的输出:

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

预期输出: 它也应该打印test,从printf("test\n"); 的sscanf() 覆盖。 由于localtime() 在内部调用了sscanf(),并且我已经覆盖并指示使用sscanf()。

是否有任何方法可以覆盖另一个系统调用,例如本例中的 sscanf(),它在内部从 localtime() 调用。

调用层次如下:

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

【问题讨论】:

  • 你确定 localtime() 调用 sscanf() 吗?在我的 glibc 中,它调用了一个内部 __tz_convert()。
  • @RachidK。是的,它的调用跟踪如下: ``` #0 0x00007ffff6e7740e in __GI__IO_vfscanf () from /lib64/libc.so.6 #1 0x00007ffff6e8b401 in vsscanf () from /lib64/libc.so.6 #2 0x00007ffff6e859d8 in sscanf () from /lib64/libc.so.6 #3 0x00007ffff6ed0bce in parse_offset () from /lib64/libc.so.6 #4 0x00007ffff6ed115a in __tzset_parse_tz () from /lib64/libc.so.6 #5 0x00007ffff6ed2c50 in __tzfile_compute () from / lib64/libc.so.6 #6 0x00007ffff6ed16f9 in __tz_convert () from /lib64/libc.so.6 #7 localtime() ```
  • __tz_convert ->__tzfile_compute -->__tzset_parse_tz -->parse_offset -->sscanf

标签: c linux scanf localtime ld-preload


【解决方案1】:

LD_PRELOAD 通过成为动态链接器找到的第一个同名符号来工作 - 因此,如果可以在编译时解决符号使用,则动态链接不会影响它 因为localtime 和sscanf 存在于同一个二进制文件中,所以调用很可能是静态调用 - 调用可以在编译时解析,并且动态链接器不参与此调用链。

【讨论】:

  • 是的,你是对的,否则这意味着 glibc 需要 glibc 才能工作。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-01-18
  • 1970-01-01
  • 1970-01-01
  • 2012-03-09
  • 1970-01-01
  • 2019-08-06
  • 1970-01-01
相关资源
最近更新 更多