Since I don't get any answer, I guess I have not been convincing
enough. Here is the deal:

 a) It is obvious that there's an inconsistency: 'error' is almost
    always set before goto bad.
 b) Beyond the fact that it is obvious: if you have a look at this
    function, you will see that there are cases where the return
    value shouldn't be ENOEXEC, at l.546 & l.697
    - l.546
     ELFNAME(read_from) calls vn_rdwr(), which then calls VOP_{READ/
     WRITE}; the man page of VOP_{READ/WRITE} cleary points out that
      "Upon success, zero is returned; otherwise, an appropriate error
       code is returned."
     Thus, it could return something else than ENOEXEC.
    - l.697
     If you take a binary with a PT_OPENBSD_RANDOMIZE section which
     value is above 1024, you will see that exec() returns ENOEXEC
     whereas it is expected to return ENOMEM.

Does it sound more... glamourous?


Le 26/08/2013 15:39, Maxime Villard a écrit :
> Hi,
> after playing with some ELF binaries, I figured out that error
> codes received in errno do not always match with what is expected
> in the kernel.
> 
> Actually, this function should return (error) instead of (ENOEXEC):
> 
> 
> Index: exec_elf.c
> ===================================================================
> RCS file: /cvs/src/sys/kern/exec_elf.c,v
> retrieving revision 1.93
> diff -u -p -r1.93 exec_elf.c
> --- exec_elf.c        4 Jul 2013 17:37:05 -0000       1.93
> +++ exec_elf.c        26 Aug 2013 15:26:06 -0000
> @@ -552,8 +552,10 @@ ELFNAME2(exec,makecmds)(struct proc *p,
>   
>       for (i = 0, pp = ph; i < eh->e_phnum; i++, pp++) {
>               if (pp->p_type == PT_INTERP && !interp) {
> -                     if (pp->p_filesz >= MAXPATHLEN)
> +                     if (pp->p_filesz >= MAXPATHLEN) {
> +                             error = ENOEXEC;
>                               goto bad;
> +                     }
>                       interp = pool_get(&namei_pool, PR_WAITOK);
>                       if ((error = ELFNAME(read_from)(p, epp->ep_vp,
>                           pp->p_offset, interp, pp->p_filesz)) != 0) {
> @@ -567,8 +569,10 @@ ELFNAME2(exec,makecmds)(struct proc *p,
>   
>       if (eh->e_type == ET_DYN) {
>               /* need an interpreter and load sections for PIE */
> -             if (interp == NULL || base_ph == NULL)
> +             if (interp == NULL || base_ph == NULL) {
> +                     error = ENOEXEC;
>                       goto bad;
> +             }
>               /* randomize exe_base for PIE */
>               exe_base = uvm_map_pie(base_ph->p_align);
>       }
> @@ -589,9 +593,9 @@ ELFNAME2(exec,makecmds)(struct proc *p,
>        * *interp with a changed path (/emul/xxx/<path>), and also
>        * set the ep_emul field in the exec package structure.
>        */
> -     error = ENOEXEC;
>       if (eh->e_ident[EI_OSABI] != ELFOSABI_OPENBSD &&
>           ELFNAME(os_pt_note)(p, epp, epp->ep_hdr, "OpenBSD", 8, 4) != 0) {
> +             error = ENOEXEC;
>               for (i = 0; ELFNAME(probes)[i].func != NULL && error; i++)
>                       error = (*ELFNAME(probes)[i].func)(p, epp, interp, 
> &pos);
>               if (error)
> @@ -760,7 +764,7 @@ bad:
>               pool_put(&namei_pool, interp);
>       free(ph, M_TEMP);
>       kill_vmcmds(&epp->ep_vmcmds);
> -     return (ENOEXEC);
> +     return (error);
>   }
>   
>   /*
> 
> 
> Ok/Comments?
> 
> 

Reply via email to