imgact_elf.c (22d4b0fb418e0896f158ce3994ff117a708d7a7c) imgact_elf.c (8c64af4f750d8c5fdc217c194d0d3ab5651617c3)
1/*-
2 * Copyright (c) 1995-1996 S�ren Schmidt
3 * Copyright (c) 1996 Peter Wemm
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:

--- 12 unchanged lines hidden (view full) ---

21 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 *
1/*-
2 * Copyright (c) 1995-1996 S�ren Schmidt
3 * Copyright (c) 1996 Peter Wemm
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:

--- 12 unchanged lines hidden (view full) ---

21 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 *
29 * $Id: imgact_elf.c,v 1.29 1998/07/29 18:39:35 dfr Exp $
29 * $Id: imgact_elf.c,v 1.30 1998/09/14 05:36:49 jdp Exp $
30 */
31
32#include "opt_rlimit.h"
33
34#include <sys/param.h>
30 */
31
32#include "opt_rlimit.h"
33
34#include <sys/param.h>
35#include <sys/systm.h>
35#include <sys/acct.h>
36#include <sys/exec.h>
36#include <sys/exec.h>
37#include <sys/mman.h>
37#include <sys/fcntl.h>
38#include <sys/imgact.h>
39#include <sys/imgact_elf.h>
40#include <sys/kernel.h>
38#include <sys/imgact.h>
39#include <sys/imgact_elf.h>
40#include <sys/kernel.h>
41#include <sys/sysent.h>
42#include <sys/malloc.h>
41#include <sys/malloc.h>
42#include <sys/mman.h>
43#include <sys/namei.h>
43#include <sys/namei.h>
44#include <sys/pioctl.h>
44#include <sys/proc.h>
45#include <sys/proc.h>
45#include <sys/syscall.h>
46#include <sys/procfs.h>
47#include <sys/resourcevar.h>
46#include <sys/signalvar.h>
48#include <sys/signalvar.h>
49#include <sys/stat.h>
50#include <sys/syscall.h>
47#include <sys/sysctl.h>
51#include <sys/sysctl.h>
52#include <sys/sysent.h>
53#include <sys/systm.h>
48#include <sys/vnode.h>
49
50#include <vm/vm.h>
51#include <vm/vm_kern.h>
52#include <vm/vm_param.h>
53#include <vm/pmap.h>
54#include <sys/lock.h>
55#include <vm/vm_map.h>

--- 17 unchanged lines hidden (view full) ---

73#define Elf_Phdr Elf64_Phdr
74#define Elf_Auxargs Elf64_Auxargs
75#define Elf_Brandinfo Elf64_Brandinfo
76
77#endif
78
79
80static int elf_check_header __P((const Elf_Ehdr *hdr, int type));
54#include <sys/vnode.h>
55
56#include <vm/vm.h>
57#include <vm/vm_kern.h>
58#include <vm/vm_param.h>
59#include <vm/pmap.h>
60#include <sys/lock.h>
61#include <vm/vm_map.h>

--- 17 unchanged lines hidden (view full) ---

79#define Elf_Phdr Elf64_Phdr
80#define Elf_Auxargs Elf64_Auxargs
81#define Elf_Brandinfo Elf64_Brandinfo
82
83#endif
84
85
86static int elf_check_header __P((const Elf_Ehdr *hdr, int type));
81static int elf_load_section __P((struct vmspace *vmspace, struct vnode *vp, vm_offset_t offset, caddr_t vmaddr, size_t memsz, size_t filsz, vm_prot_t prot));
82static int elf_load_file __P((struct proc *p, char *file, u_long *addr, u_long *entry));
83static int elf_freebsd_fixup __P((long **stack_base, struct image_params *imgp));
87static int elf_freebsd_fixup __P((long **stack_base,
88 struct image_params *imgp));
89static int elf_load_file __P((struct proc *p, char *file, u_long *addr,
90 u_long *entry));
91static int elf_load_section __P((struct vmspace *vmspace, struct vnode *vp,
92 vm_offset_t offset, caddr_t vmaddr, size_t memsz, size_t filsz,
93 vm_prot_t prot));
84static int exec_elf_imgact __P((struct image_params *imgp));
85
86static int elf_trace = 0;
87SYSCTL_INT(_debug, OID_AUTO, elf_trace, CTLFLAG_RW, &elf_trace, 0, "");
88#define UPRINTF if (elf_trace) uprintf
89
90static struct sysentvec elf_freebsd_sysvec = {
91 SYS_MAXSYSCALL,

--- 542 unchanged lines hidden (view full) ---

634
635 /* don't allow modifying the file while we run it */
636 imgp->vp->v_flag |= VTEXT;
637
638fail:
639 return error;
640}
641
94static int exec_elf_imgact __P((struct image_params *imgp));
95
96static int elf_trace = 0;
97SYSCTL_INT(_debug, OID_AUTO, elf_trace, CTLFLAG_RW, &elf_trace, 0, "");
98#define UPRINTF if (elf_trace) uprintf
99
100static struct sysentvec elf_freebsd_sysvec = {
101 SYS_MAXSYSCALL,

--- 542 unchanged lines hidden (view full) ---

644
645 /* don't allow modifying the file while we run it */
646 imgp->vp->v_flag |= VTEXT;
647
648fail:
649 return error;
650}
651
642int
643elf_coredump (p)
644 register struct proc *p;
645{
646 /* Not implemented yet. */
647 return EFAULT;
648}
649
650static int
651elf_freebsd_fixup(long **stack_base, struct image_params *imgp)
652{
653 Elf_Auxargs *args = (Elf_Auxargs *)imgp->auxargs;
654 long *pos;
655
656 pos = *stack_base + (imgp->argc + imgp->envc + 2);
657

--- 16 unchanged lines hidden (view full) ---

674 imgp->auxargs = NULL;
675
676 (*stack_base)--;
677 **stack_base = (long)imgp->argc;
678 return 0;
679}
680
681/*
652static int
653elf_freebsd_fixup(long **stack_base, struct image_params *imgp)
654{
655 Elf_Auxargs *args = (Elf_Auxargs *)imgp->auxargs;
656 long *pos;
657
658 pos = *stack_base + (imgp->argc + imgp->envc + 2);
659

--- 16 unchanged lines hidden (view full) ---

676 imgp->auxargs = NULL;
677
678 (*stack_base)--;
679 **stack_base = (long)imgp->argc;
680 return 0;
681}
682
683/*
684 * Code for generating ELF core dumps.
685 */
686
687static int elf_corehdr __P((struct proc *, struct vnode *, struct ucred *));
688static size_t elf_hdrsize(void);
689static void elf_puthdr(void *, size_t *, const prstatus_t *,
690 const prfpregset_t *, const prpsinfo_t *, const void *, size_t,
691 const void *, size_t);
692static void elf_putnote(void *, size_t *, const char *, int, const void *,
693 size_t);
694
695extern int osreldate;
696
697int
698elf_coredump(p)
699 register struct proc *p;
700{
701 register struct vnode *vp;
702 register struct ucred *cred = p->p_cred->pc_ucred;
703 register struct vmspace *vm = p->p_vmspace;
704 struct nameidata nd;
705 struct vattr vattr;
706 int error, error1;
707 char *name; /* name of corefile */
708 size_t hdrsize;
709
710 STOPEVENT(p, S_CORE, 0);
711
712 if (sugid_coredump == 0 && p->p_flag & P_SUGID)
713 return (EFAULT);
714 hdrsize = elf_hdrsize();
715 if (hdrsize + ctob(vm->vm_dsize + vm->vm_ssize) >=
716 p->p_rlimit[RLIMIT_CORE].rlim_cur)
717 return (EFAULT);
718 name = expand_name(p->p_comm, p->p_ucred->cr_uid, p->p_pid);
719 if (name == NULL)
720 return (EFAULT); /* XXX -- not the best error */
721
722 NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, name, p);
723 error = vn_open(&nd, O_CREAT | FWRITE, S_IRUSR | S_IWUSR);
724 free(name, M_TEMP);
725 if (error)
726 return (error);
727 vp = nd.ni_vp;
728
729 /* Don't dump to non-regular files or files with links. */
730 if (vp->v_type != VREG ||
731 VOP_GETATTR(vp, &vattr, cred, p) || vattr.va_nlink != 1) {
732 error = EFAULT;
733 goto out;
734 }
735 VATTR_NULL(&vattr);
736 vattr.va_size = 0;
737 VOP_LEASE(vp, p, cred, LEASE_WRITE);
738 VOP_SETATTR(vp, &vattr, cred, p);
739 p->p_acflag |= ACORE;
740 error = elf_corehdr(p, vp, cred);
741 if (error == 0)
742 error = vn_rdwr(UIO_WRITE, vp, vm->vm_daddr,
743 (int)ctob(vm->vm_dsize), (off_t)hdrsize, UIO_USERSPACE,
744 IO_NODELOCKED|IO_UNIT, cred, (int *) NULL, p);
745 if (error == 0)
746 error = vn_rdwr(UIO_WRITE, vp,
747 (caddr_t) trunc_page(USRSTACK - ctob(vm->vm_ssize)),
748 round_page(ctob(vm->vm_ssize)),
749 (off_t)hdrsize + ctob(vm->vm_dsize), UIO_USERSPACE,
750 IO_NODELOCKED|IO_UNIT, cred, (int *) NULL, p);
751out:
752 VOP_UNLOCK(vp, 0, p);
753 error1 = vn_close(vp, FWRITE, cred, p);
754 if (error == 0)
755 error = error1;
756 return (error);
757}
758
759static int
760elf_corehdr(p, vp, cred)
761 struct proc *p;
762 struct vnode *vp;
763 struct ucred *cred;
764{
765 struct vmspace *vm = p->p_vmspace;
766 size_t off;
767 size_t hdrsize;
768 prstatus_t status;
769 prfpregset_t fpregset;
770 prpsinfo_t psinfo;
771 void *hdr;
772 int error;
773
774 /* Gather the information for the header. */
775 bzero(&status, sizeof status);
776 status.pr_version = PRSTATUS_VERSION;
777 status.pr_statussz = sizeof(prstatus_t);
778 status.pr_gregsetsz = sizeof(gregset_t);
779 status.pr_fpregsetsz = sizeof(fpregset_t);
780 status.pr_osreldate = osreldate;
781 status.pr_cursig = p->p_sigacts->ps_sig;
782 status.pr_pid = p->p_pid;
783 fill_regs(p, &status.pr_reg);
784
785 fill_fpregs(p, &fpregset);
786
787 bzero(&psinfo, sizeof psinfo);
788 psinfo.pr_version = PRPSINFO_VERSION;
789 psinfo.pr_psinfosz = sizeof(prpsinfo_t);
790 strncpy(psinfo.pr_fname, p->p_comm, MAXCOMLEN);
791 psinfo.pr_psargs[0] = '\0'; /* XXX - args not implemented yet */
792
793 /* Allocate memory for building the header. */
794 hdrsize = elf_hdrsize();
795 hdr = malloc(hdrsize, M_TEMP, M_WAITOK);
796 if (hdr == NULL)
797 return EINVAL;
798 bzero(hdr, hdrsize);
799
800 /* Fill in the header. */
801 off = 0;
802 elf_puthdr(hdr, &off, &status, &fpregset, &psinfo,
803 vm->vm_daddr, ctob(vm->vm_dsize),
804 (void *)trunc_page(USRSTACK - ctob(vm->vm_ssize)),
805 ctob(vm->vm_ssize));
806
807 /* Write it to the core file. */
808 error = vn_rdwr(UIO_WRITE, vp, hdr, hdrsize, (off_t)0,
809 UIO_SYSSPACE, IO_NODELOCKED|IO_UNIT, cred, NULL, p);
810
811 free(hdr, M_TEMP);
812 return error;
813}
814
815static size_t
816elf_hdrsize(void)
817{
818 size_t off;
819
820 off = 0;
821 elf_puthdr(NULL, &off, NULL, NULL, NULL, NULL, 0, NULL, 0);
822 return off;
823}
824
825static void
826elf_puthdr(void *dst, size_t *off, const prstatus_t *status,
827 const prfpregset_t *fpregset, const prpsinfo_t *psinfo,
828 const void *data, size_t datasz, const void *stack, size_t stacksz)
829{
830 size_t ehoff;
831 size_t phoff;
832 size_t noteoff;
833 size_t notesz;
834 size_t dataoff;
835 size_t stackoff;
836 int numsegs = 3;
837
838 ehoff = *off;
839 *off += sizeof(Elf_Ehdr);
840
841 phoff = *off;
842 *off += numsegs * sizeof(Elf_Phdr);
843
844 noteoff = *off;
845 elf_putnote(dst, off, "FreeBSD", NT_PRSTATUS, status,
846 sizeof *status);
847 elf_putnote(dst, off, "FreeBSD", NT_FPREGSET, fpregset,
848 sizeof *fpregset);
849 elf_putnote(dst, off, "FreeBSD", NT_PRPSINFO, psinfo,
850 sizeof *psinfo);
851 notesz = *off - noteoff;
852
853 /* Align up to a page boundary for the data segment. */
854 *off = round_page(*off);
855
856 if (dst != NULL) {
857 Elf_Ehdr *ehdr;
858 Elf_Phdr *phdr;
859
860 /*
861 * Fill in the ELF header.
862 */
863 ehdr = (Elf_Ehdr *)((char *)dst + ehoff);
864 ehdr->e_ident[EI_MAG0] = ELFMAG0;
865 ehdr->e_ident[EI_MAG1] = ELFMAG1;
866 ehdr->e_ident[EI_MAG2] = ELFMAG2;
867 ehdr->e_ident[EI_MAG3] = ELFMAG3;
868 ehdr->e_ident[EI_CLASS] = ELF_CLASS;
869 ehdr->e_ident[EI_DATA] = ELF_DATA;
870 ehdr->e_ident[EI_VERSION] = EV_CURRENT;
871 ehdr->e_ident[EI_PAD] = 0;
872 strncpy(ehdr->e_ident + EI_BRAND, "FreeBSD",
873 EI_NIDENT - EI_BRAND);
874 ehdr->e_type = ET_CORE;
875 ehdr->e_machine = ELF_ARCH;
876 ehdr->e_version = EV_CURRENT;
877 ehdr->e_entry = 0;
878 ehdr->e_phoff = phoff;
879 ehdr->e_flags = 0;
880 ehdr->e_ehsize = sizeof(Elf_Ehdr);
881 ehdr->e_phentsize = sizeof(Elf_Phdr);
882 ehdr->e_phnum = numsegs;
883 ehdr->e_shentsize = sizeof(Elf_Shdr);
884 ehdr->e_shnum = 0;
885 ehdr->e_shstrndx = SHN_UNDEF;
886
887 /*
888 * Fill in the program header entries.
889 */
890 phdr = (Elf_Phdr *)((char *)dst + phoff);
891
892 /* The note segement. */
893 phdr->p_type = PT_NOTE;
894 phdr->p_offset = noteoff;
895 phdr->p_vaddr = 0;
896 phdr->p_paddr = 0;
897 phdr->p_filesz = notesz;
898 phdr->p_memsz = 0;
899 phdr->p_flags = 0;
900 phdr->p_align = 0;
901 phdr++;
902
903 /* The data segment. */
904 phdr->p_type = PT_LOAD;
905 phdr->p_offset = *off;
906 phdr->p_vaddr = (Elf_Addr)data;
907 phdr->p_paddr = 0;
908 phdr->p_filesz = phdr->p_memsz = datasz;
909 phdr->p_align = PAGE_SIZE;
910 phdr->p_flags = PF_R | PF_W | PF_X;
911 phdr++;
912
913 /* The stack segment. */
914 phdr->p_type = PT_LOAD;
915 phdr->p_offset = *off + datasz;
916 phdr->p_vaddr = (Elf_Addr)stack;
917 phdr->p_paddr = 0;
918 phdr->p_filesz = phdr->p_memsz = stacksz;
919 phdr->p_align = PAGE_SIZE;
920 phdr->p_flags = PF_R | PF_W | PF_X;
921 phdr++;
922 }
923}
924
925static void
926elf_putnote(void *dst, size_t *off, const char *name, int type,
927 const void *desc, size_t descsz)
928{
929 Elf_Note note;
930
931 note.n_namesz = strlen(name) + 1;
932 note.n_descsz = descsz;
933 note.n_type = type;
934 if (dst != NULL)
935 bcopy(&note, (char *)dst + *off, sizeof note);
936 *off += sizeof note;
937 if (dst != NULL)
938 bcopy(name, (char *)dst + *off, note.n_namesz);
939 *off += roundup2(note.n_namesz, sizeof(Elf_Size));
940 if (dst != NULL)
941 bcopy(desc, (char *)dst + *off, note.n_descsz);
942 *off += roundup2(note.n_descsz, sizeof(Elf_Size));
943}
944
945/*
682 * Tell kern_execve.c about it, with a little help from the linker.
683 * Since `const' objects end up in the text segment, TEXT_SET is the
684 * correct directive to use.
685 */
686static const struct execsw elf_execsw = {exec_elf_imgact, "ELF"};
687TEXT_SET(execsw_set, elf_execsw);
688
946 * Tell kern_execve.c about it, with a little help from the linker.
947 * Since `const' objects end up in the text segment, TEXT_SET is the
948 * correct directive to use.
949 */
950static const struct execsw elf_execsw = {exec_elf_imgact, "ELF"};
951TEXT_SET(execsw_set, elf_execsw);
952