是否可以伪造进程的特定路径?

glu*_*k47 10 linux filenames adb

我正在尝试在我不是 root 的多个用户的 linux 服务器上运行 ADB(与我的 android 模拟器一起玩)。adb 守护进程将其日志写入文件/tmp/adb.log,不幸的是,该文件似乎已硬编码到 ADB 中,并且这种情况不会改变

因此, adb 无法运行,给出了明显的错误:cannot open '/tmp/adb.log': Permission denied. 这个文件是由另一个用户创建的,并且/tmp有粘性位。如果我启动 adb 并adb nodaemon server使其写入 stdout,则不会发生错误(我还将其端口设置为唯一值以避免冲突)。

我的问题是:有什么方法可以让 ADB 写入另一个文件而不是/tmp/adb.log? 更一般地说,有没有办法创建一种特定于进程的符号链接?我想将所有文件访问重定向/tmp/adb.log到一个文件~/tmp/adb.log

再次,我不是根服务器上,因此chrootmount -o rbindchmod不能有效的选项。如果可能,我不想修改 ADB 源,但如果没有其他解决方案,我肯定会这样做。

PS对于具体ADB情况下,我可以诉诸运行adb nodaemon servernohup输出重定向,但总的问题仍然是相关的。

meu*_*euh 12

LD_PRELOAD 并不太难,而且您不需要是 root。插入您自己的 C 例程,它被调用而不是open()在 C 库中调用。您的例程检查要打开的文件是否为“/tmp/adb.log”并使用不同的文件名调用真正的打开。这是你的 shim_open.c:

/*
 * capture calls to a routine and replace with your code
 * gcc -Wall -O2 -fpic -shared -ldl -o shim_open.so shim_open.c
 * LD_PRELOAD=/.../shim_open.so cat /tmp/adb.log
 */
#define _FCNTL_H 1 /* hack for open() prototype */
#define _GNU_SOURCE /* needed to get RTLD_NEXT defined in dlfcn.h */
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <dlfcn.h>
#define OLDNAME "/tmp/adb.log"
#define NEWNAME "/tmp/myadb.log"

int open(const char *pathname, int flags, mode_t mode){
    static int (*real_open)(const char *pathname, int flags, mode_t mode) = NULL;

    if (!real_open) {
        real_open = dlsym(RTLD_NEXT, "open");
        char *error = dlerror();
        if (error != NULL) {
            fprintf(stderr, "%s\n", error);
            exit(1);
        }
    }
    if (strcmp(pathname,OLDNAME)==0) pathname = NEWNAME;
    fprintf(stderr, "opening: %s\n", pathname);
    return real_open(pathname, flags, mode);
}
Run Code Online (Sandbox Code Playgroud)

编译它gcc -Wall -O2 -fpic -shared -ldl -o shim_open.so shim_open.c并通过将一些东西放入/tmp/myadb.log并运行来 测试它LD_PRELOAD=/.../shim_open.so cat /tmp/adb.log。然后在 adb 上尝试 LD_PRELOAD。

  • 没关系。我也了解了`unshare`,所以我们都有收获! (2认同)
  • @gluk47 这就是 Gnu/Linux 的美妙之处:你永远不需要停止探索!有很多好东西可以发现和分享。 (2认同)

mik*_*erv 6

这是一个非常简单的示例,使用util-linux'sunshare将进程放在私有挂载命名空间中,并为其父级当前拥有的同一文件系统提供不同的视图:

{   cd /tmp                      #usually a safe place for this stuff
    echo hey   >file             #some
    echo there >file2            #evidence
    sudo unshare -m sh -c '      #unshare requires root by default
         mount -B file2 file     #bind mount there over hey
         cat file                #show it
         kill -TSTP "$$"         #suspend root shell and switch back to parent
         umount file             #unbind there
         cat file'               #show it
    cat file                     #root shell just suspended
    fg                           #bring it back
    cat file2                    #round it off
}
Run Code Online (Sandbox Code Playgroud)
there                            #root shell
hey                              #root shell suspended
hey                              #root shell restored
there                            #rounded
Run Code Online (Sandbox Code Playgroud)

您可以使用unshare最新 linux 系统上的实用程序为进程提供其文件系统的私有视图,尽管挂载命名空间工具本身对于整个 3.x 内核系列已经相当成熟。您可以使用nsenter同一个包中的实用程序输入各种预先存在的命名空间,您可以使用man.