diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2013-11-13 07:34:18 +0100 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2013-11-13 07:34:18 +0100 |
commit | 9bc9ccd7db1c9f043f75380b5a5b94912046a60e (patch) | |
tree | dd0a1b3396ae9414f668b0110cc39d11268ad3ed /fs/binfmt_elf_fdpic.c | |
parent | Merge tag 'dlm-3.13' of git://git.kernel.org/pub/scm/linux/kernel/git/teiglan... (diff) | |
parent | ecryptfs: ->f_op is never NULL (diff) | |
download | linux-9bc9ccd7db1c9f043f75380b5a5b94912046a60e.tar.xz linux-9bc9ccd7db1c9f043f75380b5a5b94912046a60e.zip |
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs
Pull vfs updates from Al Viro:
"All kinds of stuff this time around; some more notable parts:
- RCU'd vfsmounts handling
- new primitives for coredump handling
- files_lock is gone
- Bruce's delegations handling series
- exportfs fixes
plus misc stuff all over the place"
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs: (101 commits)
ecryptfs: ->f_op is never NULL
locks: break delegations on any attribute modification
locks: break delegations on link
locks: break delegations on rename
locks: helper functions for delegation breaking
locks: break delegations on unlink
namei: minor vfs_unlink cleanup
locks: implement delegations
locks: introduce new FL_DELEG lock flag
vfs: take i_mutex on renamed file
vfs: rename I_MUTEX_QUOTA now that it's not used for quotas
vfs: don't use PARENT/CHILD lock classes for non-directories
vfs: pull ext4's double-i_mutex-locking into common code
exportfs: fix quadratic behavior in filehandle lookup
exportfs: better variable name
exportfs: move most of reconnect_path to helper function
exportfs: eliminate unused "noprogress" counter
exportfs: stop retrying once we race with rename/remove
exportfs: clear DISCONNECTED on all parents sooner
exportfs: more detailed comment for path_reconnect
...
Diffstat (limited to 'fs/binfmt_elf_fdpic.c')
-rw-r--r-- | fs/binfmt_elf_fdpic.c | 152 |
1 files changed, 47 insertions, 105 deletions
diff --git a/fs/binfmt_elf_fdpic.c b/fs/binfmt_elf_fdpic.c index c166f325a183..fe2a643ee005 100644 --- a/fs/binfmt_elf_fdpic.c +++ b/fs/binfmt_elf_fdpic.c @@ -111,7 +111,7 @@ static int is_elf_fdpic(struct elfhdr *hdr, struct file *file) return 0; if (!elf_check_arch(hdr) || !elf_check_fdpic(hdr)) return 0; - if (!file->f_op || !file->f_op->mmap) + if (!file->f_op->mmap) return 0; return 1; } @@ -1267,35 +1267,17 @@ static int notesize(struct memelfnote *en) /* #define DEBUG */ -#define DUMP_WRITE(addr, nr, foffset) \ - do { if (!dump_write(file, (addr), (nr))) return 0; *foffset += (nr); } while(0) - -static int alignfile(struct file *file, loff_t *foffset) -{ - static const char buf[4] = { 0, }; - DUMP_WRITE(buf, roundup(*foffset, 4) - *foffset, foffset); - return 1; -} - -static int writenote(struct memelfnote *men, struct file *file, - loff_t *foffset) +static int writenote(struct memelfnote *men, struct coredump_params *cprm) { struct elf_note en; en.n_namesz = strlen(men->name) + 1; en.n_descsz = men->datasz; en.n_type = men->type; - DUMP_WRITE(&en, sizeof(en), foffset); - DUMP_WRITE(men->name, en.n_namesz, foffset); - if (!alignfile(file, foffset)) - return 0; - DUMP_WRITE(men->data, men->datasz, foffset); - if (!alignfile(file, foffset)) - return 0; - - return 1; + return dump_emit(cprm, &en, sizeof(en)) && + dump_emit(cprm, men->name, en.n_namesz) && dump_align(cprm, 4) && + dump_emit(cprm, men->data, men->datasz) && dump_align(cprm, 4); } -#undef DUMP_WRITE static inline void fill_elf_fdpic_header(struct elfhdr *elf, int segs) { @@ -1500,66 +1482,40 @@ static void fill_extnum_info(struct elfhdr *elf, struct elf_shdr *shdr4extnum, /* * dump the segments for an MMU process */ -#ifdef CONFIG_MMU -static int elf_fdpic_dump_segments(struct file *file, size_t *size, - unsigned long *limit, unsigned long mm_flags) +static bool elf_fdpic_dump_segments(struct coredump_params *cprm) { struct vm_area_struct *vma; - int err = 0; for (vma = current->mm->mmap; vma; vma = vma->vm_next) { unsigned long addr; - if (!maydump(vma, mm_flags)) + if (!maydump(vma, cprm->mm_flags)) continue; +#ifdef CONFIG_MMU for (addr = vma->vm_start; addr < vma->vm_end; addr += PAGE_SIZE) { + bool res; struct page *page = get_dump_page(addr); if (page) { void *kaddr = kmap(page); - *size += PAGE_SIZE; - if (*size > *limit) - err = -EFBIG; - else if (!dump_write(file, kaddr, PAGE_SIZE)) - err = -EIO; + res = dump_emit(cprm, kaddr, PAGE_SIZE); kunmap(page); page_cache_release(page); - } else if (!dump_seek(file, PAGE_SIZE)) - err = -EFBIG; - if (err) - goto out; + } else { + res = dump_skip(cprm, PAGE_SIZE); + } + if (!res) + return false; } - } -out: - return err; -} -#endif - -/* - * dump the segments for a NOMMU process - */ -#ifndef CONFIG_MMU -static int elf_fdpic_dump_segments(struct file *file, size_t *size, - unsigned long *limit, unsigned long mm_flags) -{ - struct vm_area_struct *vma; - - for (vma = current->mm->mmap; vma; vma = vma->vm_next) { - if (!maydump(vma, mm_flags)) - continue; - - if ((*size += PAGE_SIZE) > *limit) - return -EFBIG; - - if (!dump_write(file, (void *) vma->vm_start, +#else + if (!dump_emit(cprm, (void *) vma->vm_start, vma->vm_end - vma->vm_start)) - return -EIO; + return false; +#endif } - - return 0; + return true; } -#endif static size_t elf_core_vma_data_size(unsigned long mm_flags) { @@ -1585,11 +1541,10 @@ static int elf_fdpic_core_dump(struct coredump_params *cprm) int has_dumped = 0; mm_segment_t fs; int segs; - size_t size = 0; int i; struct vm_area_struct *vma; struct elfhdr *elf = NULL; - loff_t offset = 0, dataoff, foffset; + loff_t offset = 0, dataoff; int numnote; struct memelfnote *notes = NULL; struct elf_prstatus *prstatus = NULL; /* NT_PRSTATUS */ @@ -1606,6 +1561,8 @@ static int elf_fdpic_core_dump(struct coredump_params *cprm) struct elf_shdr *shdr4extnum = NULL; Elf_Half e_phnum; elf_addr_t e_shoff; + struct core_thread *ct; + struct elf_thread_status *tmp; /* * We no longer stop all VM operations. @@ -1641,28 +1598,23 @@ static int elf_fdpic_core_dump(struct coredump_params *cprm) goto cleanup; #endif - if (cprm->siginfo->si_signo) { - struct core_thread *ct; - struct elf_thread_status *tmp; - - for (ct = current->mm->core_state->dumper.next; - ct; ct = ct->next) { - tmp = kzalloc(sizeof(*tmp), GFP_KERNEL); - if (!tmp) - goto cleanup; + for (ct = current->mm->core_state->dumper.next; + ct; ct = ct->next) { + tmp = kzalloc(sizeof(*tmp), GFP_KERNEL); + if (!tmp) + goto cleanup; - tmp->thread = ct->task; - list_add(&tmp->list, &thread_list); - } + tmp->thread = ct->task; + list_add(&tmp->list, &thread_list); + } - list_for_each(t, &thread_list) { - struct elf_thread_status *tmp; - int sz; + list_for_each(t, &thread_list) { + struct elf_thread_status *tmp; + int sz; - tmp = list_entry(t, struct elf_thread_status, list); - sz = elf_dump_thread_status(cprm->siginfo->si_signo, tmp); - thread_status_size += sz; - } + tmp = list_entry(t, struct elf_thread_status, list); + sz = elf_dump_thread_status(cprm->siginfo->si_signo, tmp); + thread_status_size += sz; } /* now collect the dump for the current */ @@ -1720,7 +1672,6 @@ static int elf_fdpic_core_dump(struct coredump_params *cprm) offset += sizeof(*elf); /* Elf header */ offset += segs * sizeof(struct elf_phdr); /* Program headers */ - foffset = offset; /* Write notes phdr entry */ { @@ -1755,13 +1706,10 @@ static int elf_fdpic_core_dump(struct coredump_params *cprm) offset = dataoff; - size += sizeof(*elf); - if (size > cprm->limit || !dump_write(cprm->file, elf, sizeof(*elf))) + if (!dump_emit(cprm, elf, sizeof(*elf))) goto end_coredump; - size += sizeof(*phdr4note); - if (size > cprm->limit - || !dump_write(cprm->file, phdr4note, sizeof(*phdr4note))) + if (!dump_emit(cprm, phdr4note, sizeof(*phdr4note))) goto end_coredump; /* write program headers for segments dump */ @@ -1785,18 +1733,16 @@ static int elf_fdpic_core_dump(struct coredump_params *cprm) phdr.p_flags |= PF_X; phdr.p_align = ELF_EXEC_PAGESIZE; - size += sizeof(phdr); - if (size > cprm->limit - || !dump_write(cprm->file, &phdr, sizeof(phdr))) + if (!dump_emit(cprm, &phdr, sizeof(phdr))) goto end_coredump; } - if (!elf_core_write_extra_phdrs(cprm->file, offset, &size, cprm->limit)) + if (!elf_core_write_extra_phdrs(cprm, offset)) goto end_coredump; /* write out the notes section */ for (i = 0; i < numnote; i++) - if (!writenote(notes + i, cprm->file, &foffset)) + if (!writenote(notes + i, cprm)) goto end_coredump; /* write out the thread status notes section */ @@ -1805,25 +1751,21 @@ static int elf_fdpic_core_dump(struct coredump_params *cprm) list_entry(t, struct elf_thread_status, list); for (i = 0; i < tmp->num_notes; i++) - if (!writenote(&tmp->notes[i], cprm->file, &foffset)) + if (!writenote(&tmp->notes[i], cprm)) goto end_coredump; } - if (!dump_seek(cprm->file, dataoff - foffset)) + if (!dump_skip(cprm, dataoff - cprm->written)) goto end_coredump; - if (elf_fdpic_dump_segments(cprm->file, &size, &cprm->limit, - cprm->mm_flags) < 0) + if (!elf_fdpic_dump_segments(cprm)) goto end_coredump; - if (!elf_core_write_extra_data(cprm->file, &size, cprm->limit)) + if (!elf_core_write_extra_data(cprm)) goto end_coredump; if (e_phnum == PN_XNUM) { - size += sizeof(*shdr4extnum); - if (size > cprm->limit - || !dump_write(cprm->file, shdr4extnum, - sizeof(*shdr4extnum))) + if (!dump_emit(cprm, shdr4extnum, sizeof(*shdr4extnum))) goto end_coredump; } |