是否可以为流程伪造特定路径?


9

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

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

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

同样,我不是服务器的root用户,所以chrootmount -o rbind并且chmod不是有效的选项。如果可能的话,我不想修改ADB的来源,但是如果没有其他解决方案,我一定会做的。

PS对于特定的ADB案例,我可以求助于adb nodaemon serverwith nohup和输出重定向,但是一般问题仍然很重要。


2
是。您可以将您的进程放在专用的挂载名称空间中,然后在上挂载其他文件/tmp/adb.log,甚至/tmp完全挂载其自己的专用文件。做man unshareman namespacesman nsenter
mikeserv

1
@mikeserv太好了,这似乎正是我所需要的,谢谢!如果您将自己的评论重新格式化为答案,则可以将其设置为接受。
gluk47 2015年

还是有一些LD_PRELOAD技巧,尽管那会更加复杂。
2015年

@thrig是的,我虽然是关于LD_PRELOAD的,但坦率地说,硬编码/home/$USER/tmp/adb.log和重建adb 会更容易:)
gluk47 2015年

Answers:


5

这是一个非常简单的示例,该示例使用util-linuxunshare将一个进程放入一个私有挂载名称空间,并为其提供其父级当前具有的同一文件系统的不同视图:

{   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
}

there                            #root shell
hey                              #root shell suspended
hey                              #root shell restored
there                            #rounded

您可以使用unshare最新Linux系统上的实用程序为进程提供其文件系统的私有视图,尽管在整个3.x内核系列中,mount名称空间工具本身已经相当成熟。您可以使用以下命令输入各种预先存在的名称空间nsenter同一包中的实用程序,还可以使用查找更多信息man


只是一个问题:是我还是一个完美的解决方案,但仅适用于root用户?
gluk47 2015年

@ gluk47-不一定是。您可以使用unshare各种名称空间-包括用户名称空间。因此,您的用户可以运行一个具有根访问权限的命名空间,并且在该命名空间内,root用户可能搞砸的任何操作均不会影响父命名空间。换句话说,安装名称空间可以嵌入用户名称空间内。您确实需要阅读这些man页面。它变得更深。这恰恰是如何dockersytemd-nspawn工作。
mikeserv

我已经从Internet上阅读了这些手册页和示例)似乎只是我需要阅读更多,只是感谢您指出这项技术,我不知何故对此一无所知。
gluk47

@ gluk47-不要为了忠诚而接受答案。尽管人们对此感激不已,但这种东西违背了这个地方的目的。接受您使用的答案。如果,一个是没有这一项,请不要接受这个答案。顺便说一句,仅仅因为一个进程是作为root 启动的,并不意味着它必须保持 root进程。有runuser可以与一起使用的实用程序unshare,并且如果您仍然愿意编写已编译的程序,则没有理由您不能使用unshare()syscall来做同样的事情,甚至不能仅system()使用suid二进制文件来做。
mikeserv

如果它没有用,我肯定不接受答案。我发现答案都是相关且有用的,因此,情绪是检查以下答案之一的唯一与众不同的原因:)
gluk47 2015年

11

LD_PRELOAD不太困难,您不需要是root。插入自己的C例程,而不是真正的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);
}

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。


好吧,的确,您的解决方案是我设法成为非root用户的唯一解决方案。我没有处理取消共享(Operation not permitted)。我希望这open足以处理,但是最后,添加unlink到该处理程序并不困难。
gluk47 2015年

w 我无法检查两个答案,真可惜。我答应了mikeserv来检查他的解决方案作为答案,这确实是一个可行的方法。
gluk47 2015年

2
没关系。我也了解了unshare,所以我们所有人都受益!
meuh

一段时间后,再次感谢您提供LD_PRELOAD示例。自从尝试了您的代码以来,我在各种甚至没有想到的情况下都使用LD_PRELOAD。我的生活变得更好了:)
gluk47 '16

2
@ gluk47这就是Gnu / Linux的奇妙之处:您无需停止探索!有很多好东西可以发现和分享。
meuh's
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.