-
Notifications
You must be signed in to change notification settings - Fork 31
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add binfmt loader for ELF. This is the default loader used on execve(). Signed-off-by: Michalis Pappas <[email protected]>
- Loading branch information
1 parent
866d13b
commit bf8b46c
Showing
2 changed files
with
94 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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); |