Is it possible to fake a specific path for a process?

I’m trying to run ADB on a linux server with multiple users where I am not root (to play with my android emulator). The adb daemon writes its logs to the file /tmp/adb.log which unfortunately seems to be hard-coded into ADB and this situation is not going to change.

So, adb is failing to run, giving the obvious error: cannot open '/tmp/adb.log': Permission denied. This file is created by another user and /tmp has sticky bit on. If I start adb with adb nodaemon server making it write to stdout, no errors occur (I also set up its port to a unique value to avoid conflicts).

My question is: is there some way to make ADB write to another file than /tmp/adb.log? More generally, is there a way to create a sort of a process-specific symlink? I want to redirect all file accesses to /tmp/adb.log to, saying, a file ~/tmp/adb.log.

Again, I am not root on the server, so chroot, mount -o rbind and chmod are not valid options. If possible, I’d like not to modify ADB sources, but surely if there are no other solutions, I’ll do that.

P.S. For the specific ADB case I can resort to running adb nodaemon server with nohup and output redirection, but the general question is still relevant.

Answers:

Thank you for visiting the Q&A section on Magenaut. Please note that all the answers may not help you solve the issue immediately. So please treat them as advisements. If you found the post helpful (or not), leave a comment & I’ll get back to you as soon as possible.

Method 1

LD_PRELOAD isn’t too difficult, and you don’t need to be root.
Interpose your own C routine which is called instead of the real open() in the C library. Your routine checks if the file to open is “/tmp/adb.log” and calls the real open with a different filename. Here’s your 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, "%sn", error);
            exit(1);
        }
    }
    if (strcmp(pathname,OLDNAME)==0) pathname = NEWNAME;
    fprintf(stderr, "opening: %sn", pathname);
    return real_open(pathname, flags, mode);
}

Compile it with gcc -Wall -O2 -fpic -shared -ldl -o shim_open.so shim_open.c and test it by putting something in /tmp/myadb.log and running
LD_PRELOAD=/.../shim_open.so cat /tmp/adb.log. Then try the LD_PRELOAD on adb.

Method 2

Here is a very simple example of using util-linux‘s unshare to put a process in a private mount namespace and give it a different view of the same filesystem its parent currently has:

{   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

You can give a process a private view of its filesystem with the unshare utility on up-to-date linux systems, though the mount namespace facility itself has been fairly mature for the entire 3.x kernel series. You can enter pre-existing namespaces of all kinds with nsenter utility from the same package, and you can find out more with man.


All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0

0 0 votes
Article Rating
Subscribe
Notify of
guest

0 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
0
Would love your thoughts, please comment.x
()
x