Skip to content

Commit

Permalink
Add ELF binfmt loader
Browse files Browse the repository at this point in the history
Add binfmt loader for ELF. This is the default loader used on
execve().

Signed-off-by: Michalis Pappas <[email protected]>
  • Loading branch information
michpappas committed Jul 24, 2024
1 parent 866d13b commit bf8b46c
Show file tree
Hide file tree
Showing 2 changed files with 94 additions and 0 deletions.
1 change: 1 addition & 0 deletions Makefile.uk
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ APPELFLOADER_CFLAGS-$(CONFIG_APPELFLOADER_DEBUG) += -DUK_DEBUG
APPELFLOADER_SRCS-y += $(APPELFLOADER_BASE)/main.c
APPELFLOADER_SRCS-y += $(APPELFLOADER_BASE)/elf_load.c
APPELFLOADER_SRCS-y += $(APPELFLOADER_BASE)/elf_ctx.c
APPELFLOADER_SRCS-y += $(APPELFLOADER_BASE)/elf_binfmt.c

APPELFLOADER_SRCS-$(CONFIG_APPELFLOADER_BRK) += $(APPELFLOADER_BASE)/syscalls/brk.c
UK_PROVIDED_SYSCALLS-$(CONFIG_APPELFLOADER_BRK) += brk-1
Expand Down
93 changes: 93 additions & 0 deletions elf_binfmt.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
/* SPDX-License-Identifier: BSD-3-Clause */
/* Copyright (c) 2023, Unikraft GmbH and The Unikraft Authors.
* Licensed under the BSD-3-Clause License (the "License").
* You may not use this file except in compliance with the License.
*/

#include <uk/assert.h>
#include <uk/arch/ctx.h>
#include <uk/binfmt.h>
#include <uk/essentials.h>
#include <uk/errptr.h>
#include <uk/init.h>

#if CONFIG_LIBUKSWRAND
#include <uk/swrand.h>
#endif /* CONFIG_LIBUKSWRAND */

#include "elf_prog.h"

static int uk_binfmt_load_elf(struct uk_binfmt_loader_args *args)
{
struct elf_prog *prog;
__u64 rand[2];
int rc;

UK_ASSERT(args);
UK_ASSERT(args->alloc);

prog = elf_load_vfs(args->alloc, args->pathname, args->progname);
if (PTRISERR(prog) || !prog) {
if (PTR2ERR(prog) == -ENOEXEC)
return UK_BINFMT_NOT_HANDLED;
return PTR2ERR(prog);
}

/* Save to private data in case we are requested to unload */
args->user = (void *)prog;

uk_pr_debug("%s: ELF loaded to 0x%lx-0x%lx (%lx B)\n", args->progname,
(__u64)prog->vabase, (__u64)prog->vabase + prog->valen,
prog->valen);
uk_pr_debug("%s: Entry at %p\n", args->progname, (void *)prog->entry);

#if CONFIG_LIBUKSWRAND
uk_swrand_fill_buffer(rand, sizeof(rand));
#else /* !CONFIG_LIBUKSWRAND */
/* Without random numbers, use a hardcoded seed */
uk_pr_warn("%s: Using hard-coded random seed\n", args->progname);
rand[0] = 0xB0B0;
rand[1] = 0xF00D;
#endif /* !CONFIG_LIBUKSWRAND */

rc = elf_arg_env_count(&args->argc, args->argv,
&args->envc, args->envp,
args->stack_size);
if (unlikely(rc < 0)) {
elf_unload(prog);
return rc;
}

elf_ctx_init(&args->ctx, prog, args->progname,
args->argc, args->argv,
args->envc, args->envp, rand);

return UK_BINFMT_HANDLED;
}

static int uk_binfmt_unload_elf(struct uk_binfmt_loader_args *args)
{
UK_ASSERT(args);
UK_ASSERT(args->user);

elf_unload((struct elf_prog *)args->user);

return UK_BINFMT_HANDLED;
}

static struct uk_binfmt_loader elf_loader = {
.name = "ELF loader",
.type = UK_BINFMT_LOADER_TYPE_EXEC,
.ops = {
.load = uk_binfmt_load_elf,
.unload = uk_binfmt_unload_elf
}
};

static int uk_binfmt_elf_loader_init(struct uk_init_ctx *init_ctx __unused)
{
uk_binfmt_register(&elf_loader);
return 0;
}

uk_late_initcall(uk_binfmt_elf_loader_init, 0);

0 comments on commit bf8b46c

Please sign in to comment.