@@ -169,19 +169,95 @@ abi_ulong loader_build_argptr(int envc, int argc, abi_ulong sp,
return sp;
}
+static int is_there(const char *candidate)
+{
+ struct stat fin;
+
+ /* XXX work around access(2) false positives for superuser */
+ if (access(candidate, X_OK) == 0 && stat(candidate, &fin) == 0 &&
+ S_ISREG(fin.st_mode) && (getuid() != 0 ||
+ (fin.st_mode & (S_IXUSR | S_IXGRP | S_IXOTH)) != 0)) {
+ return 1;
+ }
+
+ return 0;
+}
+
+static int find_in_path(char *path, const char *filename, char *retpath,
+ size_t rpsize)
+{
+ const char *d;
+ int found;
+
+ if (strchr(filename, '/') != NULL) {
+ if (is_there(filename)) {
+ if (!realpath(filename, retpath)) {
+ return -1;
+ }
+ return 0;
+ } else {
+ return -1;
+ }
+ }
+
+ found = 0;
+ while ((d = strsep(&path, ":")) != NULL) {
+ if (*d == '\0') {
+ d = ".";
+ }
+ if (snprintf(retpath, rpsize, "%s/%s", d, filename) >= (int)rpsize) {
+ continue;
+ }
+ if (is_there((const char *)retpath)) {
+ found = 1;
+ break;
+ }
+ }
+ return found;
+}
+
int loader_exec(const char * filename, char ** argv, char ** envp,
struct target_pt_regs *regs, struct image_info *infop,
struct bsd_binprm *bprm)
{
- int retval;
- int i;
+ char *p, *path = NULL, fullpath[PATH_MAX];
+ const char *execname = NULL;
+ int retval, i;
- bprm->p = TARGET_PAGE_SIZE*MAX_ARG_PAGES-sizeof(unsigned int);
+ bprm->p = TARGET_PAGE_SIZE * MAX_ARG_PAGES; /* -sizeof(unsigned int); */
for (i=0 ; i<MAX_ARG_PAGES ; i++) /* clear page-table */
bprm->page[i] = NULL;
- retval = open(filename, O_RDONLY);
+
+ /* Find target executable in path, if not already an absolute path. */
+ p = getenv("PATH");
+ if (p != NULL) {
+ path = g_strdup(p);
+ if (path == NULL) {
+ fprintf(stderr, "Out of memory\n");
+ return -1;
+ }
+ execname = realpath(filename, NULL);
+ if (execname == NULL) {
+ execname = filename;
+ }
+ if (!find_in_path(path, execname, fullpath, sizeof(fullpath))) {
+ retval = open(fullpath, O_RDONLY);
+ bprm->fullpath = g_strdup(fullpath);
+ } else {
+ retval = open(execname, O_RDONLY);
+ bprm->fullpath = NULL;
+ }
+ if (execname) {
+ free((void *)execname);
+ }
+ free(path);
+ } else {
+ retval = open(filename, O_RDONLY);
+ bprm->fullpath = NULL;
+ }
if (retval < 0)
return retval;
+
bprm->fd = retval;
bprm->filename = (char *)filename;
bprm->argc = count(argv);
@@ -128,7 +128,8 @@ struct bsd_binprm {
int argc, envc;
char **argv;
char **envp;
- char *filename; /* Name of binary */
+ char *filename; /* (Given) Name of binary */
+ char *fullpath; /* Full path of binary */
int (*core_dump)(int, const CPUArchState *);
};
If the target executable's path is not absolute then this code will search the PATH to find it. Save the fullpath to put on to the stack for the runtime linker. Signed-off-by: Stacey Son <sson@FreeBSD.org> --- bsd-user/bsdload.c | 84 +++++++++++++++++++++++++++++++++++++++++++++++++-- bsd-user/qemu.h | 3 +- 2 files changed, 82 insertions(+), 5 deletions(-)