mirror of
https://github.com/tbsdtv/linux_media.git
synced 2025-07-23 12:43:29 +02:00
Merge branch 'for-next' of git://git.kernel.org/pub/scm/linux/kernel/git/gerg/m68knommu
Pull m68nommu updates from Greg Ungerer: "A series of cleanups for the FLAT format binary loader, binfmt_flat, from Christoph. The end goal is to support no-MMU on RISC-V, and the last patch enables that" * 'for-next' of git://git.kernel.org/pub/scm/linux/kernel/git/gerg/m68knommu: riscv: add binfmt_flat support binfmt_flat: don't offset the data start binfmt_flat: move the MAX_SHARED_LIBS definition to binfmt_flat.c binfmt_flat: remove the persistent argument from flat_get_addr_from_rp binfmt_flat: provide an asm-generic/flat.h binfmt_flat: make support for old format binaries optional binfmt_flat: add a ARCH_HAS_BINFMT_FLAT option binfmt_flat: add endianess annotations binfmt_flat: use fixed size type for the on-disk format binfmt_flat: consolidate two version of flat_v2_reloc_t binfmt_flat: remove the unused OLD_FLAT_FLAG_RAM definition binfmt_flat: remove the uapi <linux/flat.h> header binfmt_flat: replace flat_argvp_envp_on_stack with a Kconfig variable binfmt_flat: remove flat_old_ram_flag binfmt_flat: provide a default version of flat_get_relocate_addr binfmt_flat: remove flat_set_persistent binfmt_flat: remove flat_reloc_valid
This commit is contained in:
@@ -42,6 +42,11 @@
|
||||
#include <asm/unaligned.h>
|
||||
#include <asm/cacheflush.h>
|
||||
#include <asm/page.h>
|
||||
#include <asm/flat.h>
|
||||
|
||||
#ifndef flat_get_relocate_addr
|
||||
#define flat_get_relocate_addr(rel) (rel)
|
||||
#endif
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
@@ -63,6 +68,12 @@
|
||||
#define RELOC_FAILED 0xff00ff01 /* Relocation incorrect somewhere */
|
||||
#define UNLOADED_LIB 0x7ff000ff /* Placeholder for unused library */
|
||||
|
||||
#ifdef CONFIG_BINFMT_SHARED_FLAT
|
||||
#define MAX_SHARED_LIBS (4)
|
||||
#else
|
||||
#define MAX_SHARED_LIBS (1)
|
||||
#endif
|
||||
|
||||
struct lib_info {
|
||||
struct {
|
||||
unsigned long start_code; /* Start of text segment */
|
||||
@@ -120,14 +131,15 @@ static int create_flat_tables(struct linux_binprm *bprm, unsigned long arg_start
|
||||
|
||||
sp -= bprm->envc + 1;
|
||||
sp -= bprm->argc + 1;
|
||||
sp -= flat_argvp_envp_on_stack() ? 2 : 0;
|
||||
if (IS_ENABLED(CONFIG_BINFMT_FLAT_ARGVP_ENVP_ON_STACK))
|
||||
sp -= 2; /* argvp + envp */
|
||||
sp -= 1; /* &argc */
|
||||
|
||||
current->mm->start_stack = (unsigned long)sp & -FLAT_STACK_ALIGN;
|
||||
sp = (unsigned long __user *)current->mm->start_stack;
|
||||
|
||||
__put_user(bprm->argc, sp++);
|
||||
if (flat_argvp_envp_on_stack()) {
|
||||
if (IS_ENABLED(CONFIG_BINFMT_FLAT_ARGVP_ENVP_ON_STACK)) {
|
||||
unsigned long argv, envp;
|
||||
argv = (unsigned long)(sp + 2);
|
||||
envp = (unsigned long)(sp + 2 + bprm->argc + 1);
|
||||
@@ -345,7 +357,7 @@ calc_reloc(unsigned long r, struct lib_info *p, int curid, int internalp)
|
||||
start_code = p->lib_list[id].start_code;
|
||||
text_len = p->lib_list[id].text_len;
|
||||
|
||||
if (!flat_reloc_valid(r, start_brk - start_data + text_len)) {
|
||||
if (r > start_brk - start_data + text_len) {
|
||||
pr_err("reloc outside program 0x%lx (0 - 0x%lx/0x%lx)",
|
||||
r, start_brk-start_data+text_len, text_len);
|
||||
goto failed;
|
||||
@@ -368,6 +380,7 @@ failed:
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_BINFMT_FLAT_OLD
|
||||
static void old_reloc(unsigned long rl)
|
||||
{
|
||||
static const char *segment[] = { "TEXT", "DATA", "BSS", "*UNKNOWN*" };
|
||||
@@ -405,6 +418,7 @@ static void old_reloc(unsigned long rl)
|
||||
|
||||
pr_debug("Relocation became %lx\n", val);
|
||||
}
|
||||
#endif /* CONFIG_BINFMT_FLAT_OLD */
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
@@ -415,7 +429,8 @@ static int load_flat_file(struct linux_binprm *bprm,
|
||||
unsigned long textpos, datapos, realdatastart;
|
||||
u32 text_len, data_len, bss_len, stack_len, full_data, flags;
|
||||
unsigned long len, memp, memp_size, extra, rlim;
|
||||
u32 __user *reloc, *rp;
|
||||
__be32 __user *reloc;
|
||||
u32 __user *rp;
|
||||
struct inode *inode;
|
||||
int i, rev, relocs;
|
||||
loff_t fpos;
|
||||
@@ -454,6 +469,7 @@ static int load_flat_file(struct linux_binprm *bprm,
|
||||
if (flags & FLAT_FLAG_KTRACE)
|
||||
pr_info("Loading file: %s\n", bprm->filename);
|
||||
|
||||
#ifdef CONFIG_BINFMT_FLAT_OLD
|
||||
if (rev != FLAT_VERSION && rev != OLD_FLAT_VERSION) {
|
||||
pr_err("bad flat file version 0x%x (supported 0x%lx and 0x%lx)\n",
|
||||
rev, FLAT_VERSION, OLD_FLAT_VERSION);
|
||||
@@ -469,6 +485,23 @@ static int load_flat_file(struct linux_binprm *bprm,
|
||||
goto err;
|
||||
}
|
||||
|
||||
/*
|
||||
* fix up the flags for the older format, there were all kinds
|
||||
* of endian hacks, this only works for the simple cases
|
||||
*/
|
||||
if (rev == OLD_FLAT_VERSION &&
|
||||
(flags || IS_ENABLED(CONFIG_BINFMT_FLAT_OLD_ALWAYS_RAM)))
|
||||
flags = FLAT_FLAG_RAM;
|
||||
|
||||
#else /* CONFIG_BINFMT_FLAT_OLD */
|
||||
if (rev != FLAT_VERSION) {
|
||||
pr_err("bad flat file version 0x%x (supported 0x%lx)\n",
|
||||
rev, FLAT_VERSION);
|
||||
ret = -ENOEXEC;
|
||||
goto err;
|
||||
}
|
||||
#endif /* !CONFIG_BINFMT_FLAT_OLD */
|
||||
|
||||
/*
|
||||
* Make sure the header params are sane.
|
||||
* 28 bits (256 MB) is way more than reasonable in this case.
|
||||
@@ -480,13 +513,6 @@ static int load_flat_file(struct linux_binprm *bprm,
|
||||
goto err;
|
||||
}
|
||||
|
||||
/*
|
||||
* fix up the flags for the older format, there were all kinds
|
||||
* of endian hacks, this only works for the simple cases
|
||||
*/
|
||||
if (rev == OLD_FLAT_VERSION && flat_old_ram_flag(flags))
|
||||
flags = FLAT_FLAG_RAM;
|
||||
|
||||
#ifndef CONFIG_BINFMT_ZFLAT
|
||||
if (flags & (FLAT_FLAG_GZIP|FLAT_FLAG_GZDATA)) {
|
||||
pr_err("Support for ZFLAT executables is not enabled.\n");
|
||||
@@ -547,7 +573,7 @@ static int load_flat_file(struct linux_binprm *bprm,
|
||||
goto err;
|
||||
}
|
||||
|
||||
len = data_len + extra + MAX_SHARED_LIBS * sizeof(unsigned long);
|
||||
len = data_len + extra;
|
||||
len = PAGE_ALIGN(len);
|
||||
realdatastart = vm_mmap(NULL, 0, len,
|
||||
PROT_READ|PROT_WRITE|PROT_EXEC, MAP_PRIVATE, 0);
|
||||
@@ -561,9 +587,7 @@ static int load_flat_file(struct linux_binprm *bprm,
|
||||
vm_munmap(textpos, text_len);
|
||||
goto err;
|
||||
}
|
||||
datapos = ALIGN(realdatastart +
|
||||
MAX_SHARED_LIBS * sizeof(unsigned long),
|
||||
FLAT_DATA_ALIGN);
|
||||
datapos = ALIGN(realdatastart, FLAT_DATA_ALIGN);
|
||||
|
||||
pr_debug("Allocated data+bss+stack (%u bytes): %lx\n",
|
||||
data_len + bss_len + stack_len, datapos);
|
||||
@@ -587,13 +611,13 @@ static int load_flat_file(struct linux_binprm *bprm,
|
||||
goto err;
|
||||
}
|
||||
|
||||
reloc = (u32 __user *)
|
||||
reloc = (__be32 __user *)
|
||||
(datapos + (ntohl(hdr->reloc_start) - text_len));
|
||||
memp = realdatastart;
|
||||
memp_size = len;
|
||||
} else {
|
||||
|
||||
len = text_len + data_len + extra + MAX_SHARED_LIBS * sizeof(u32);
|
||||
len = text_len + data_len + extra;
|
||||
len = PAGE_ALIGN(len);
|
||||
textpos = vm_mmap(NULL, 0, len,
|
||||
PROT_READ | PROT_EXEC | PROT_WRITE, MAP_PRIVATE, 0);
|
||||
@@ -608,11 +632,9 @@ static int load_flat_file(struct linux_binprm *bprm,
|
||||
}
|
||||
|
||||
realdatastart = textpos + ntohl(hdr->data_start);
|
||||
datapos = ALIGN(realdatastart +
|
||||
MAX_SHARED_LIBS * sizeof(u32),
|
||||
FLAT_DATA_ALIGN);
|
||||
datapos = ALIGN(realdatastart, FLAT_DATA_ALIGN);
|
||||
|
||||
reloc = (u32 __user *)
|
||||
reloc = (__be32 __user *)
|
||||
(datapos + (ntohl(hdr->reloc_start) - text_len));
|
||||
memp = textpos;
|
||||
memp_size = len;
|
||||
@@ -627,8 +649,9 @@ static int load_flat_file(struct linux_binprm *bprm,
|
||||
(text_len + full_data
|
||||
- sizeof(struct flat_hdr)),
|
||||
0);
|
||||
memmove((void *) datapos, (void *) realdatastart,
|
||||
full_data);
|
||||
if (datapos != realdatastart)
|
||||
memmove((void *)datapos, (void *)realdatastart,
|
||||
full_data);
|
||||
#else
|
||||
/*
|
||||
* This is used on MMU systems mainly for testing.
|
||||
@@ -684,8 +707,7 @@ static int load_flat_file(struct linux_binprm *bprm,
|
||||
if (IS_ERR_VALUE(result)) {
|
||||
ret = result;
|
||||
pr_err("Unable to read code+data+bss, errno %d\n", ret);
|
||||
vm_munmap(textpos, text_len + data_len + extra +
|
||||
MAX_SHARED_LIBS * sizeof(u32));
|
||||
vm_munmap(textpos, text_len + data_len + extra);
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
@@ -775,20 +797,18 @@ static int load_flat_file(struct linux_binprm *bprm,
|
||||
* __start to address 4 so that is okay).
|
||||
*/
|
||||
if (rev > OLD_FLAT_VERSION) {
|
||||
u32 __maybe_unused persistent = 0;
|
||||
for (i = 0; i < relocs; i++) {
|
||||
u32 addr, relval;
|
||||
__be32 tmp;
|
||||
|
||||
/*
|
||||
* Get the address of the pointer to be
|
||||
* relocated (of course, the address has to be
|
||||
* relocated first).
|
||||
*/
|
||||
if (get_user(relval, reloc + i))
|
||||
if (get_user(tmp, reloc + i))
|
||||
return -EFAULT;
|
||||
relval = ntohl(relval);
|
||||
if (flat_set_persistent(relval, &persistent))
|
||||
continue;
|
||||
relval = ntohl(tmp);
|
||||
addr = flat_get_relocate_addr(relval);
|
||||
rp = (u32 __user *)calc_reloc(addr, libinfo, id, 1);
|
||||
if (rp == (u32 __user *)RELOC_FAILED) {
|
||||
@@ -797,8 +817,7 @@ static int load_flat_file(struct linux_binprm *bprm,
|
||||
}
|
||||
|
||||
/* Get the pointer's value. */
|
||||
ret = flat_get_addr_from_rp(rp, relval, flags,
|
||||
&addr, &persistent);
|
||||
ret = flat_get_addr_from_rp(rp, relval, flags, &addr);
|
||||
if (unlikely(ret))
|
||||
goto err;
|
||||
|
||||
@@ -807,8 +826,13 @@ static int load_flat_file(struct linux_binprm *bprm,
|
||||
* Do the relocation. PIC relocs in the data section are
|
||||
* already in target order
|
||||
*/
|
||||
if ((flags & FLAT_FLAG_GOTPIC) == 0)
|
||||
addr = ntohl(addr);
|
||||
if ((flags & FLAT_FLAG_GOTPIC) == 0) {
|
||||
/*
|
||||
* Meh, the same value can have a different
|
||||
* byte order based on a flag..
|
||||
*/
|
||||
addr = ntohl((__force __be32)addr);
|
||||
}
|
||||
addr = calc_reloc(addr, libinfo, id, 0);
|
||||
if (addr == RELOC_FAILED) {
|
||||
ret = -ENOEXEC;
|
||||
@@ -821,14 +845,15 @@ static int load_flat_file(struct linux_binprm *bprm,
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
#ifdef CONFIG_BINFMT_FLAT_OLD
|
||||
} else {
|
||||
for (i = 0; i < relocs; i++) {
|
||||
u32 relval;
|
||||
__be32 relval;
|
||||
if (get_user(relval, reloc + i))
|
||||
return -EFAULT;
|
||||
relval = ntohl(relval);
|
||||
old_reloc(relval);
|
||||
old_reloc(ntohl(relval));
|
||||
}
|
||||
#endif /* CONFIG_BINFMT_FLAT_OLD */
|
||||
}
|
||||
|
||||
flush_icache_range(start_code, end_code);
|
||||
|
Reference in New Issue
Block a user