dockerd makes runc invoke dockerd using /proc/$pid/exe. This commit makes it work when both of dockerd and runc are emulated by qemu linux-user. In that case, we (the qemu interpreting runc) need to invoke the real executable (dockerd), where /proc/$pid/exe in question is the qemu command interpreting dockerd.
Signed-off-by: YAMAMOTO Takashi <yamam...@midokura.com> --- linux-user/syscall.c | 59 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 59 insertions(+) diff --git a/linux-user/syscall.c b/linux-user/syscall.c index 86b12cc8b4..6f9161dbe4 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -7988,10 +7988,69 @@ static int open_self_auxv(void *cpu_env, int fd) static const char *get_exe_path(int pid, char *buf, size_t bufsize) { + ssize_t ssz; + int fd; + if (pid == getpid()) { return exec_path; } + /* dockerd makes runc invoke dockerd using "/proc/${dockerd_pid}/exe". */ + snprintf(buf, bufsize, "/proc/%d/cmdline", pid); + fd = open(buf, O_RDONLY); + if (fd == -1) { + return NULL; + } + ssz = read(fd, buf, bufsize); + if (ssz != -1) { + const char *argv0; + const char *argv1; + const char *cp; + const char *ep; + const char *slash; + + cp = buf; + ep = cp + ssz; + + argv0 = cp; + while (*cp != 0) { + cp++; + if (cp >= ep) { + goto fail; + } + } + + cp++; + if (cp >= ep) { + goto fail; + } + + argv1 = cp; + while (*cp != 0) { + cp++; + if (cp >= ep) { + goto fail; + } + } + + /* + * XXX a bit too loose detection of qemu. + * maybe we can compare /proc/$pid/exe with ours. + */ + slash = strrchr(argv0, '/'); + if (slash != NULL) { + argv0 = slash + 1; /* basename */ + } + if (strncmp(argv0, "qemu-", sizeof("qemu-") - 1)) { + goto fail; + } + + close(fd); + return argv1; + } +fail: + close(fd); + return NULL; } -- 2.21.1 (Apple Git-122.3)