Resolve absolute symlinks relative to the prefix

This requires a change in libelfloader to ensure the interpreter is resolved according to the Linux root and not the prefix.
This commit is contained in:
Ariel Abreu 2021-06-12 09:03:07 -04:00
parent 1c83210faa
commit 3761b3d7f1
No known key found for this signature in database
GPG Key ID: BB20848279B910AC
6 changed files with 69 additions and 13 deletions

View File

@ -0,0 +1 @@
../../../../../../../../../../../src/kernel/emulation/linux/ext/for-libelfloader.h

View File

@ -266,6 +266,7 @@ set(emulation_sources
ext/file_handle.c
ext/fanotify.c
ext/for-xtrace.c
ext/for-libelfloader.c
bsdthread/bsdthread_register.c
bsdthread/bsdthread_create.c
bsdthread/bsdthread_ctl.c

View File

@ -0,0 +1,43 @@
#include "for-libelfloader.h"
#include "../base.h"
#include "../errno.h"
#include "../bsdthread/cancelable.h"
#include "../bsdthread/per_thread_wd.h"
#include "../fcntl/open.h"
VISIBLE
long _open_for_libelfloader(const char* path, int flags, unsigned int mode) {
int linux_flags;
int wd;
int ret;
CANCELATION_POINT();
linux_flags = oflags_bsd_to_linux(flags);
wd = oflags_bsd_to_linux(flags);
if (sizeof(void*) == 4) {
linux_flags |= LINUX_O_LARGEFILE;
}
ret = LINUX_SYSCALL(__NR_openat, wd, path, linux_flags, mode);
if (ret < 0)
ret = errno_linux_to_bsd(ret);
return ret;
};
VISIBLE
long _access_for_libelfloader(const char* path, int mode) {
int ret;
int wd;
wd = get_perthread_wd();
ret = LINUX_SYSCALL(__NR_faccessat, wd, path, mode, 0);
if (ret < 0)
ret = errno_linux_to_bsd(ret);
return ret;
};

View File

@ -0,0 +1,14 @@
#ifndef _DARLING_EMULATION_FOR_LIBELFLOADER_H_
#define _DARLING_EMULATION_FOR_LIBELFLOADER_H_
#include <darling/emulation/base.h>
// these are non-vchrooted calls for libelfloader
VISIBLE
long _open_for_libelfloader(const char* path, int flags, unsigned int mode);
VISIBLE
long _access_for_libelfloader(const char* path, int mode);
#endif // _DARLING_EMULATION_FOR_LIBELFLOADER_H_

View File

@ -423,6 +423,12 @@ done_getdents:
ctxt->follow = true;
ctxt->symlink_depth++;
// resolve absolute symlinks within the prefix
if (link[0] == '/') {
ctxt->current_root = prefix_path;
ctxt->current_root_len = prefix_path_len;
}
rv = vchroot_run(link, ctxt);
ctxt->symlink_depth--;

View File

@ -28,6 +28,7 @@
#include <setjmp.h>
#include <sys/random.h>
#include <elf.h>
#include <darling/emulation/ext/for-libelfloader.h>
#include "auxvec.h"
#include "loader.h"
#include "native/elfcalls.h"
@ -235,7 +236,8 @@ void load(const char* path, struct loader_context* lc, bool isInterp)
ElfW(Ehdr) elfHdr;
void* phdrs = NULL;
int fd = open(path, O_RDONLY);
// the interpreter path should be relative to the Linux root, not the Darling prefix
int fd = isInterp ? _open_for_libelfloader(path, O_RDONLY, 0) : open(path, O_RDONLY);
uintptr_t slide, base;
if (fd == -1)
@ -389,18 +391,7 @@ void load(const char* path, struct loader_context* lc, bool isInterp)
interp[phdr->p_filesz] = '\0';
// Load interpreter
if (access(interp, F_OK) != 0)
{
char* prefixed = (char*) malloc(phdr->p_filesz + sizeof(SYSTEM_ROOT));
strcpy(prefixed, SYSTEM_ROOT);
strcat(prefixed, interp);
free(interp);
interp = prefixed;
}
if (access(interp, F_OK) != 0)
if (_access_for_libelfloader(interp, F_OK) != 0)
{
fprintf(stderr, "Cannot load interpreter at %s\n", interp);
free(interp);