Skip to content

Commit

Permalink
exec: Make exec path for starting UKL application
Browse files Browse the repository at this point in the history
The UKL application still relies on much of the setup done to start a
standard user space process, so we still need to use much of that path.
There are several areas that the UKL application doesn't need or want so we
bypass them in the case of UKL. These are: ELF loading, because it is part
of the kernel image; and segments register value initialization.  We need
to record a starting location for the application heap, this normally is
the end of the ELF binary, once loaded. We choose an arbitrary low address
because there is no binary to load. We also hardcode the entry point for
the application to ukl__start which is the entry point for glibc plus the
'ukl_' prefix.

Suggested-by: Thomas Unger <tommyu@bu.edu>
Signed-off-by: Ali Raza <aliraza@bu.edu>

Cc: Daniel Bristot de Oliveira <bristot@kernel.org>
Cc: Richard W.M. Jones <rjones@redhat.com>
  • Loading branch information
razaaliraza committed Sep 27, 2022
1 parent c03051e commit c3b3d60
Show file tree
Hide file tree
Showing 4 changed files with 90 additions and 29 deletions.
9 changes: 6 additions & 3 deletions arch/x86/include/asm/elf.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
* ELF register definitions..
*/
#include <linux/thread_info.h>
#include <linux/sched.h>

#include <asm/ptrace.h>
#include <asm/user.h>
Expand Down Expand Up @@ -164,9 +165,11 @@ static inline void elf_common_init(struct thread_struct *t,
regs->si = regs->di = regs->bp = 0;
regs->r8 = regs->r9 = regs->r10 = regs->r11 = 0;
regs->r12 = regs->r13 = regs->r14 = regs->r15 = 0;
t->fsbase = t->gsbase = 0;
t->fsindex = t->gsindex = 0;
t->ds = t->es = ds;
if (!is_ukl_thread()) {
t->fsbase = t->gsbase = 0;
t->fsindex = t->gsindex = 0;
t->ds = t->es = ds;
}
}

#define ELF_PLAT_INIT(_r, load_addr) \
Expand Down
27 changes: 16 additions & 11 deletions arch/x86/kernel/process_64.c
Original file line number Diff line number Diff line change
Expand Up @@ -530,21 +530,26 @@ start_thread_common(struct pt_regs *regs, unsigned long new_ip,
{
WARN_ON_ONCE(regs != current_pt_regs());

if (static_cpu_has(X86_BUG_NULL_SEG)) {
/* Loading zero below won't clear the base. */
loadsegment(fs, __USER_DS);
load_gs_index(__USER_DS);
}
if (!is_ukl_thread()) {
if (static_cpu_has(X86_BUG_NULL_SEG)) {
/* Loading zero below won't clear the base. */
loadsegment(fs, __USER_DS);
load_gs_index(__USER_DS);
}

loadsegment(fs, 0);
loadsegment(es, _ds);
loadsegment(ds, _ds);
load_gs_index(0);
loadsegment(fs, 0);
loadsegment(es, _ds);
loadsegment(ds, _ds);
load_gs_index(0);

regs->cs = _cs;
regs->ss = _ss;
} else {
regs->cs = __KERNEL_CS;
regs->ss = __KERNEL_DS;
}
regs->ip = new_ip;
regs->sp = new_sp;
regs->cs = _cs;
regs->ss = _ss;
regs->flags = X86_EFLAGS_IF;
}

Expand Down
28 changes: 28 additions & 0 deletions fs/binfmt_elf.c
Original file line number Diff line number Diff line change
Expand Up @@ -845,6 +845,10 @@ static int load_elf_binary(struct linux_binprm *bprm)
struct pt_regs *regs;

retval = -ENOEXEC;

if (is_ukl_thread())
goto UKL_SKIP_READING_ELF;

/* First of all, some simple consistency checks */
if (memcmp(elf_ex->e_ident, ELFMAG, SELFMAG) != 0)
goto out;
Expand Down Expand Up @@ -998,6 +1002,7 @@ static int load_elf_binary(struct linux_binprm *bprm)
if (retval)
goto out_free_dentry;

UKL_SKIP_READING_ELF:
/* Flush all traces of the currently running executable */
retval = begin_new_exec(bprm);
if (retval)
Expand Down Expand Up @@ -1029,6 +1034,17 @@ static int load_elf_binary(struct linux_binprm *bprm)
start_data = 0;
end_data = 0;

if (is_ukl_thread()) {
/*
* load_bias needs to ensure that we push the heap start
* past the end of the executable, but in this case, it is
* already mapped with the kernel text. So we select an
* address that is "high enough"
*/
load_bias = 0x405000;
goto UKL_SKIP_LOADING_ELF;
}

/* Now we do a little grungy work by mmapping the ELF image into
the correct location in memory. */
for(i = 0, elf_ppnt = elf_phdata;
Expand Down Expand Up @@ -1224,6 +1240,7 @@ static int load_elf_binary(struct linux_binprm *bprm)
}
}

UKL_SKIP_LOADING_ELF:
e_entry = elf_ex->e_entry + load_bias;
phdr_addr += load_bias;
elf_bss += load_bias;
Expand All @@ -1246,6 +1263,16 @@ static int load_elf_binary(struct linux_binprm *bprm)
goto out_free_dentry;
}

if (is_ukl_thread()) {
/*
* We know that this symbol exists and that it is the entry
* point for the linked application.
*/
extern void ukl__start(void);
elf_entry = (unsigned long) ukl__start;
goto UKL_SKIP_FINDING_ELF_ENTRY;
}

if (interpreter) {
elf_entry = load_elf_interp(interp_elf_ex,
interpreter,
Expand Down Expand Up @@ -1283,6 +1310,7 @@ static int load_elf_binary(struct linux_binprm *bprm)

set_binfmt(&elf_format);

UKL_SKIP_FINDING_ELF_ENTRY:
#ifdef ARCH_HAS_SETUP_ADDITIONAL_PAGES
retval = ARCH_SETUP_ADDITIONAL_PAGES(bprm, elf_ex, !!interpreter);
if (retval < 0)
Expand Down
55 changes: 40 additions & 15 deletions fs/exec.c
Original file line number Diff line number Diff line change
Expand Up @@ -1246,9 +1246,11 @@ int begin_new_exec(struct linux_binprm * bprm)
int retval;

/* Once we are committed compute the creds */
retval = bprm_creds_from_file(bprm);
if (retval)
return retval;
if (!is_ukl_thread()) {
retval = bprm_creds_from_file(bprm);
if (retval)
return retval;
}

/*
* Ensure all future errors are fatal.
Expand Down Expand Up @@ -1282,9 +1284,11 @@ int begin_new_exec(struct linux_binprm * bprm)
goto out;

/* If the binary is not readable then enforce mm->dumpable=0 */
would_dump(bprm, bprm->file);
if (bprm->have_execfd)
would_dump(bprm, bprm->executable);
if (!is_ukl_thread()) {
would_dump(bprm, bprm->file);
if (bprm->have_execfd)
would_dump(bprm, bprm->executable);
}

/*
* Release all of the old mmap stuff
Expand Down Expand Up @@ -1509,6 +1513,11 @@ static struct linux_binprm *alloc_bprm(int fd, struct filename *filename)
if (!bprm)
goto out;

if (is_ukl_thread()) {
bprm->filename = "UKL";
goto out_ukl;
}

if (fd == AT_FDCWD || filename->name[0] == '/') {
bprm->filename = filename->name;
} else {
Expand All @@ -1522,6 +1531,8 @@ static struct linux_binprm *alloc_bprm(int fd, struct filename *filename)

bprm->filename = bprm->fdpath;
}

out_ukl:
bprm->interp = bprm->filename;

retval = bprm_mm_init(bprm);
Expand Down Expand Up @@ -1708,6 +1719,15 @@ static int search_binary_handler(struct linux_binprm *bprm)
struct linux_binfmt *fmt;
int retval;

if (is_ukl_thread()) {
list_for_each_entry(fmt, &formats, lh) {
retval = fmt->load_binary(bprm);
if (retval == 0)
return retval;
}
goto out_ukl;
}

retval = prepare_binprm(bprm);
if (retval < 0)
return retval;
Expand All @@ -1717,7 +1737,7 @@ static int search_binary_handler(struct linux_binprm *bprm)
return retval;

retval = -ENOENT;
retry:
retry:
read_lock(&binfmt_lock);
list_for_each_entry(fmt, &formats, lh) {
if (!try_module_get(fmt->module))
Expand Down Expand Up @@ -1745,6 +1765,7 @@ static int search_binary_handler(struct linux_binprm *bprm)
goto retry;
}

out_ukl:
return retval;
}

Expand Down Expand Up @@ -1799,7 +1820,7 @@ static int exec_binprm(struct linux_binprm *bprm)
static int bprm_execve(struct linux_binprm *bprm,
int fd, struct filename *filename, int flags)
{
struct file *file;
struct file *file = NULL;
int retval;

retval = prepare_bprm_creds(bprm);
Expand All @@ -1809,10 +1830,12 @@ static int bprm_execve(struct linux_binprm *bprm,
check_unsafe_exec(bprm);
current->in_execve = 1;

file = do_open_execat(fd, filename, flags);
retval = PTR_ERR(file);
if (IS_ERR(file))
goto out_unmark;
if (!is_ukl_thread()) {
file = do_open_execat(fd, filename, flags);
retval = PTR_ERR(file);
if (IS_ERR(file))
goto out_unmark;
}

sched_exec();

Expand All @@ -1830,9 +1853,11 @@ static int bprm_execve(struct linux_binprm *bprm,
bprm->interp_flags |= BINPRM_FLAGS_PATH_INACCESSIBLE;

/* Set the unchanging part of bprm->cred */
retval = security_bprm_creds_for_exec(bprm);
if (retval)
goto out;
if (!is_ukl_thread()) {
retval = security_bprm_creds_for_exec(bprm);
if (retval)
goto out;
}

retval = exec_binprm(bprm);
if (retval < 0)
Expand Down

0 comments on commit c3b3d60

Please sign in to comment.