mirror of
https://github.com/AuxXxilium/linux_dsm_epyc7002.git
synced 2024-11-24 05:40:55 +07:00
new helper: read_code()
switch binfmts that use ->read() to that (and to kernel_read() in several cases in binfmt_flat - sure, it's nommu, but still, doing ->read() into kmalloc'ed buffer...) Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
This commit is contained in:
parent
3af0761307
commit
3dc20cb282
@ -323,11 +323,8 @@ static int load_aout_binary(struct linux_binprm *bprm)
|
|||||||
|
|
||||||
if (N_MAGIC(ex) == OMAGIC) {
|
if (N_MAGIC(ex) == OMAGIC) {
|
||||||
unsigned long text_addr, map_size;
|
unsigned long text_addr, map_size;
|
||||||
loff_t pos;
|
|
||||||
|
|
||||||
text_addr = N_TXTADDR(ex);
|
text_addr = N_TXTADDR(ex);
|
||||||
|
|
||||||
pos = 32;
|
|
||||||
map_size = ex.a_text+ex.a_data;
|
map_size = ex.a_text+ex.a_data;
|
||||||
|
|
||||||
error = vm_brk(text_addr & PAGE_MASK, map_size);
|
error = vm_brk(text_addr & PAGE_MASK, map_size);
|
||||||
@ -337,15 +334,12 @@ static int load_aout_binary(struct linux_binprm *bprm)
|
|||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
error = bprm->file->f_op->read(bprm->file,
|
error = read_code(bprm->file, text_addr, 32,
|
||||||
(char __user *)text_addr,
|
ex.a_text + ex.a_data);
|
||||||
ex.a_text+ex.a_data, &pos);
|
|
||||||
if ((signed long)error < 0) {
|
if ((signed long)error < 0) {
|
||||||
send_sig(SIGKILL, current, 0);
|
send_sig(SIGKILL, current, 0);
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
flush_icache_range(text_addr, text_addr+ex.a_text+ex.a_data);
|
|
||||||
} else {
|
} else {
|
||||||
#ifdef WARN_OLD
|
#ifdef WARN_OLD
|
||||||
static unsigned long error_time, error_time2;
|
static unsigned long error_time, error_time2;
|
||||||
@ -367,14 +361,8 @@ static int load_aout_binary(struct linux_binprm *bprm)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (!bprm->file->f_op->mmap || (fd_offset & ~PAGE_MASK) != 0) {
|
if (!bprm->file->f_op->mmap || (fd_offset & ~PAGE_MASK) != 0) {
|
||||||
loff_t pos = fd_offset;
|
|
||||||
|
|
||||||
vm_brk(N_TXTADDR(ex), ex.a_text+ex.a_data);
|
vm_brk(N_TXTADDR(ex), ex.a_text+ex.a_data);
|
||||||
bprm->file->f_op->read(bprm->file,
|
read_code(bprm->file, N_TXTADDR(ex), fd_offset,
|
||||||
(char __user *)N_TXTADDR(ex),
|
|
||||||
ex.a_text+ex.a_data, &pos);
|
|
||||||
flush_icache_range((unsigned long) N_TXTADDR(ex),
|
|
||||||
(unsigned long) N_TXTADDR(ex) +
|
|
||||||
ex.a_text+ex.a_data);
|
ex.a_text+ex.a_data);
|
||||||
goto beyond_if;
|
goto beyond_if;
|
||||||
}
|
}
|
||||||
@ -452,8 +440,6 @@ static int load_aout_library(struct file *file)
|
|||||||
start_addr = ex.a_entry & 0xfffff000;
|
start_addr = ex.a_entry & 0xfffff000;
|
||||||
|
|
||||||
if ((N_TXTOFF(ex) & ~PAGE_MASK) != 0) {
|
if ((N_TXTOFF(ex) & ~PAGE_MASK) != 0) {
|
||||||
loff_t pos = N_TXTOFF(ex);
|
|
||||||
|
|
||||||
#ifdef WARN_OLD
|
#ifdef WARN_OLD
|
||||||
static unsigned long error_time;
|
static unsigned long error_time;
|
||||||
if (time_after(jiffies, error_time + 5*HZ)) {
|
if (time_after(jiffies, error_time + 5*HZ)) {
|
||||||
@ -466,12 +452,8 @@ static int load_aout_library(struct file *file)
|
|||||||
#endif
|
#endif
|
||||||
vm_brk(start_addr, ex.a_text + ex.a_data + ex.a_bss);
|
vm_brk(start_addr, ex.a_text + ex.a_data + ex.a_bss);
|
||||||
|
|
||||||
file->f_op->read(file, (char __user *)start_addr,
|
read_code(file, start_addr, N_TXTOFF(ex),
|
||||||
ex.a_text + ex.a_data, &pos);
|
ex.a_text + ex.a_data);
|
||||||
flush_icache_range((unsigned long) start_addr,
|
|
||||||
(unsigned long) start_addr + ex.a_text +
|
|
||||||
ex.a_data);
|
|
||||||
|
|
||||||
retval = 0;
|
retval = 0;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
@ -287,15 +287,12 @@ static int load_aout_binary(struct linux_binprm * bprm)
|
|||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
error = bprm->file->f_op->read(bprm->file,
|
error = read_code(bprm->file, text_addr, pos,
|
||||||
(char __user *)text_addr,
|
ex.a_text+ex.a_data);
|
||||||
ex.a_text+ex.a_data, &pos);
|
|
||||||
if ((signed long)error < 0) {
|
if ((signed long)error < 0) {
|
||||||
send_sig(SIGKILL, current, 0);
|
send_sig(SIGKILL, current, 0);
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
flush_icache_range(text_addr, text_addr+ex.a_text+ex.a_data);
|
|
||||||
} else {
|
} else {
|
||||||
if ((ex.a_text & 0xfff || ex.a_data & 0xfff) &&
|
if ((ex.a_text & 0xfff || ex.a_data & 0xfff) &&
|
||||||
(N_MAGIC(ex) != NMAGIC) && printk_ratelimit())
|
(N_MAGIC(ex) != NMAGIC) && printk_ratelimit())
|
||||||
@ -311,14 +308,9 @@ static int load_aout_binary(struct linux_binprm * bprm)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!bprm->file->f_op->mmap||((fd_offset & ~PAGE_MASK) != 0)) {
|
if (!bprm->file->f_op->mmap||((fd_offset & ~PAGE_MASK) != 0)) {
|
||||||
loff_t pos = fd_offset;
|
|
||||||
vm_brk(N_TXTADDR(ex), ex.a_text+ex.a_data);
|
vm_brk(N_TXTADDR(ex), ex.a_text+ex.a_data);
|
||||||
bprm->file->f_op->read(bprm->file,
|
read_code(bprm->file, N_TXTADDR(ex), fd_offset,
|
||||||
(char __user *)N_TXTADDR(ex),
|
ex.a_text + ex.a_data);
|
||||||
ex.a_text+ex.a_data, &pos);
|
|
||||||
flush_icache_range((unsigned long) N_TXTADDR(ex),
|
|
||||||
(unsigned long) N_TXTADDR(ex) +
|
|
||||||
ex.a_text+ex.a_data);
|
|
||||||
goto beyond_if;
|
goto beyond_if;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -397,8 +389,6 @@ static int load_aout_library(struct file *file)
|
|||||||
start_addr = ex.a_entry & 0xfffff000;
|
start_addr = ex.a_entry & 0xfffff000;
|
||||||
|
|
||||||
if ((N_TXTOFF(ex) & ~PAGE_MASK) != 0) {
|
if ((N_TXTOFF(ex) & ~PAGE_MASK) != 0) {
|
||||||
loff_t pos = N_TXTOFF(ex);
|
|
||||||
|
|
||||||
if (printk_ratelimit())
|
if (printk_ratelimit())
|
||||||
{
|
{
|
||||||
printk(KERN_WARNING
|
printk(KERN_WARNING
|
||||||
@ -407,11 +397,8 @@ static int load_aout_library(struct file *file)
|
|||||||
}
|
}
|
||||||
vm_brk(start_addr, ex.a_text + ex.a_data + ex.a_bss);
|
vm_brk(start_addr, ex.a_text + ex.a_data + ex.a_bss);
|
||||||
|
|
||||||
file->f_op->read(file, (char __user *)start_addr,
|
read_code(file, start_addr, N_TXTOFF(ex),
|
||||||
ex.a_text + ex.a_data, &pos);
|
ex.a_text + ex.a_data);
|
||||||
flush_icache_range((unsigned long) start_addr,
|
|
||||||
(unsigned long) start_addr + ex.a_text + ex.a_data);
|
|
||||||
|
|
||||||
retval = 0;
|
retval = 0;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
@ -926,7 +926,6 @@ static int elf_fdpic_map_file_constdisp_on_uclinux(
|
|||||||
struct elf32_fdpic_loadseg *seg;
|
struct elf32_fdpic_loadseg *seg;
|
||||||
struct elf32_phdr *phdr;
|
struct elf32_phdr *phdr;
|
||||||
unsigned long load_addr, base = ULONG_MAX, top = 0, maddr = 0, mflags;
|
unsigned long load_addr, base = ULONG_MAX, top = 0, maddr = 0, mflags;
|
||||||
loff_t fpos;
|
|
||||||
int loop, ret;
|
int loop, ret;
|
||||||
|
|
||||||
load_addr = params->load_addr;
|
load_addr = params->load_addr;
|
||||||
@ -964,14 +963,12 @@ static int elf_fdpic_map_file_constdisp_on_uclinux(
|
|||||||
if (params->phdrs[loop].p_type != PT_LOAD)
|
if (params->phdrs[loop].p_type != PT_LOAD)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
fpos = phdr->p_offset;
|
|
||||||
|
|
||||||
seg->addr = maddr + (phdr->p_vaddr - base);
|
seg->addr = maddr + (phdr->p_vaddr - base);
|
||||||
seg->p_vaddr = phdr->p_vaddr;
|
seg->p_vaddr = phdr->p_vaddr;
|
||||||
seg->p_memsz = phdr->p_memsz;
|
seg->p_memsz = phdr->p_memsz;
|
||||||
|
|
||||||
ret = file->f_op->read(file, (void *) seg->addr,
|
ret = read_code(file, seg->addr, phdr->p_offset,
|
||||||
phdr->p_filesz, &fpos);
|
phdr->p_filesz);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
|
@ -207,11 +207,12 @@ static int decompress_exec(
|
|||||||
|
|
||||||
/* Read in first chunk of data and parse gzip header. */
|
/* Read in first chunk of data and parse gzip header. */
|
||||||
fpos = offset;
|
fpos = offset;
|
||||||
ret = bprm->file->f_op->read(bprm->file, buf, LBUFSIZE, &fpos);
|
ret = kernel_read(bprm->file, offset, buf, LBUFSIZE);
|
||||||
|
|
||||||
strm.next_in = buf;
|
strm.next_in = buf;
|
||||||
strm.avail_in = ret;
|
strm.avail_in = ret;
|
||||||
strm.total_in = 0;
|
strm.total_in = 0;
|
||||||
|
fpos += ret;
|
||||||
|
|
||||||
retval = -ENOEXEC;
|
retval = -ENOEXEC;
|
||||||
|
|
||||||
@ -277,7 +278,7 @@ static int decompress_exec(
|
|||||||
}
|
}
|
||||||
|
|
||||||
while ((ret = zlib_inflate(&strm, Z_NO_FLUSH)) == Z_OK) {
|
while ((ret = zlib_inflate(&strm, Z_NO_FLUSH)) == Z_OK) {
|
||||||
ret = bprm->file->f_op->read(bprm->file, buf, LBUFSIZE, &fpos);
|
ret = kernel_read(bprm->file, fpos, buf, LBUFSIZE);
|
||||||
if (ret <= 0)
|
if (ret <= 0)
|
||||||
break;
|
break;
|
||||||
len -= ret;
|
len -= ret;
|
||||||
@ -285,6 +286,7 @@ static int decompress_exec(
|
|||||||
strm.next_in = buf;
|
strm.next_in = buf;
|
||||||
strm.avail_in = ret;
|
strm.avail_in = ret;
|
||||||
strm.total_in = 0;
|
strm.total_in = 0;
|
||||||
|
fpos += ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
@ -428,6 +430,7 @@ static int load_flat_file(struct linux_binprm * bprm,
|
|||||||
unsigned long textpos = 0, datapos = 0, result;
|
unsigned long textpos = 0, datapos = 0, result;
|
||||||
unsigned long realdatastart = 0;
|
unsigned long realdatastart = 0;
|
||||||
unsigned long text_len, data_len, bss_len, stack_len, flags;
|
unsigned long text_len, data_len, bss_len, stack_len, flags;
|
||||||
|
unsigned long full_data;
|
||||||
unsigned long len, memp = 0;
|
unsigned long len, memp = 0;
|
||||||
unsigned long memp_size, extra, rlim;
|
unsigned long memp_size, extra, rlim;
|
||||||
unsigned long *reloc = 0, *rp;
|
unsigned long *reloc = 0, *rp;
|
||||||
@ -451,6 +454,7 @@ static int load_flat_file(struct linux_binprm * bprm,
|
|||||||
relocs = ntohl(hdr->reloc_count);
|
relocs = ntohl(hdr->reloc_count);
|
||||||
flags = ntohl(hdr->flags);
|
flags = ntohl(hdr->flags);
|
||||||
rev = ntohl(hdr->rev);
|
rev = ntohl(hdr->rev);
|
||||||
|
full_data = data_len + relocs * sizeof(unsigned long);
|
||||||
|
|
||||||
if (strncmp(hdr->magic, "bFLT", 4)) {
|
if (strncmp(hdr->magic, "bFLT", 4)) {
|
||||||
/*
|
/*
|
||||||
@ -577,12 +581,12 @@ static int load_flat_file(struct linux_binprm * bprm,
|
|||||||
#ifdef CONFIG_BINFMT_ZFLAT
|
#ifdef CONFIG_BINFMT_ZFLAT
|
||||||
if (flags & FLAT_FLAG_GZDATA) {
|
if (flags & FLAT_FLAG_GZDATA) {
|
||||||
result = decompress_exec(bprm, fpos, (char *) datapos,
|
result = decompress_exec(bprm, fpos, (char *) datapos,
|
||||||
data_len + (relocs * sizeof(unsigned long)), 0);
|
full_data, 0);
|
||||||
} else
|
} else
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
result = bprm->file->f_op->read(bprm->file, (char *) datapos,
|
result = read_code(bprm->file, datapos, fpos,
|
||||||
data_len + (relocs * sizeof(unsigned long)), &fpos);
|
full_data);
|
||||||
}
|
}
|
||||||
if (IS_ERR_VALUE(result)) {
|
if (IS_ERR_VALUE(result)) {
|
||||||
printk("Unable to read data+bss, errno %d\n", (int)-result);
|
printk("Unable to read data+bss, errno %d\n", (int)-result);
|
||||||
@ -627,30 +631,25 @@ static int load_flat_file(struct linux_binprm * bprm,
|
|||||||
if (flags & FLAT_FLAG_GZIP) {
|
if (flags & FLAT_FLAG_GZIP) {
|
||||||
result = decompress_exec(bprm, sizeof (struct flat_hdr),
|
result = decompress_exec(bprm, sizeof (struct flat_hdr),
|
||||||
(((char *) textpos) + sizeof (struct flat_hdr)),
|
(((char *) textpos) + sizeof (struct flat_hdr)),
|
||||||
(text_len + data_len + (relocs * sizeof(unsigned long))
|
(text_len + full_data
|
||||||
- sizeof (struct flat_hdr)),
|
- sizeof (struct flat_hdr)),
|
||||||
0);
|
0);
|
||||||
memmove((void *) datapos, (void *) realdatastart,
|
memmove((void *) datapos, (void *) realdatastart,
|
||||||
data_len + (relocs * sizeof(unsigned long)));
|
full_data);
|
||||||
} else if (flags & FLAT_FLAG_GZDATA) {
|
} else if (flags & FLAT_FLAG_GZDATA) {
|
||||||
fpos = 0;
|
result = read_code(bprm->file, textpos, 0, text_len);
|
||||||
result = bprm->file->f_op->read(bprm->file,
|
|
||||||
(char *) textpos, text_len, &fpos);
|
|
||||||
if (!IS_ERR_VALUE(result))
|
if (!IS_ERR_VALUE(result))
|
||||||
result = decompress_exec(bprm, text_len, (char *) datapos,
|
result = decompress_exec(bprm, text_len, (char *) datapos,
|
||||||
data_len + (relocs * sizeof(unsigned long)), 0);
|
full_data, 0);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
fpos = 0;
|
result = read_code(bprm->file, textpos, 0, text_len);
|
||||||
result = bprm->file->f_op->read(bprm->file,
|
if (!IS_ERR_VALUE(result))
|
||||||
(char *) textpos, text_len, &fpos);
|
result = read_code(bprm->file, datapos,
|
||||||
if (!IS_ERR_VALUE(result)) {
|
ntohl(hdr->data_start),
|
||||||
fpos = ntohl(hdr->data_start);
|
full_data);
|
||||||
result = bprm->file->f_op->read(bprm->file, (char *) datapos,
|
|
||||||
data_len + (relocs * sizeof(unsigned long)), &fpos);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (IS_ERR_VALUE(result)) {
|
if (IS_ERR_VALUE(result)) {
|
||||||
printk("Unable to read code+data+bss, errno %d\n",(int)-result);
|
printk("Unable to read code+data+bss, errno %d\n",(int)-result);
|
||||||
|
@ -802,6 +802,15 @@ int kernel_read(struct file *file, loff_t offset,
|
|||||||
|
|
||||||
EXPORT_SYMBOL(kernel_read);
|
EXPORT_SYMBOL(kernel_read);
|
||||||
|
|
||||||
|
ssize_t read_code(struct file *file, unsigned long addr, loff_t pos, size_t len)
|
||||||
|
{
|
||||||
|
ssize_t res = file->f_op->read(file, (void __user *)addr, len, &pos);
|
||||||
|
if (res > 0)
|
||||||
|
flush_icache_range(addr, addr + len);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(read_code);
|
||||||
|
|
||||||
static int exec_mmap(struct mm_struct *mm)
|
static int exec_mmap(struct mm_struct *mm)
|
||||||
{
|
{
|
||||||
struct task_struct *tsk;
|
struct task_struct *tsk;
|
||||||
|
@ -118,5 +118,6 @@ extern int prepare_bprm_creds(struct linux_binprm *bprm);
|
|||||||
extern void install_exec_creds(struct linux_binprm *bprm);
|
extern void install_exec_creds(struct linux_binprm *bprm);
|
||||||
extern void set_binfmt(struct linux_binfmt *new);
|
extern void set_binfmt(struct linux_binfmt *new);
|
||||||
extern void free_bprm(struct linux_binprm *);
|
extern void free_bprm(struct linux_binprm *);
|
||||||
|
extern ssize_t read_code(struct file *, unsigned long, loff_t, size_t);
|
||||||
|
|
||||||
#endif /* _LINUX_BINFMTS_H */
|
#endif /* _LINUX_BINFMTS_H */
|
||||||
|
Loading…
Reference in New Issue
Block a user