mailing list of musl libc
 help / color / mirror / code / Atom feed
* [musl] execvp() behaviour with unrecognized file header
@ 2020-02-12 13:54 Alexander Scherbatiy
  2020-02-12 14:13 ` A. Wilcox
  2020-02-13 20:11 ` Markus Wichmann
  0 siblings, 2 replies; 8+ messages in thread
From: Alexander Scherbatiy @ 2020-02-12 13:54 UTC (permalink / raw)
  To: musl

Hello,

execvp() works differently on Linux Alpine and Ubuntu if it is called 
with a file which does not contain a proper shebang line. The file is 
executed on Ubuntu. It results to  ENOEXEC error on Linux Alpine.

man execvp on Ubuntu has description: "If the header of a file isn't 
recognized (the attempted execve(2) failed with the error ENOEXEC), 
these functions will execute the shell (/bin/sh) with the path of the 
file as its first argument."

Does execvp() from musl behaves differently by purpose in this case?


The sample code:

---- execvp_sample.c  ----

#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <unistd.h>

int main(int argc, char* argv[]) {

     char *file = argv[1];
     char *execvp_argv[1] = {NULL};
     execvp(file, execvp_argv);
     exit(errno);
}
--------------------------------------

gcc -o execvp_sample execvp_sample.c

---- script_1.sh ---

#!/bin/bash
echo Hello, World!

----------------------

Ubuntu: > ./execvp_sample ./script_1.sh

Hello, World!

---- script_2.sh ---

#!/bin/ash

echo Hello, World!

----------------------

Alpine Linux: > ./execvp_sample ./script_2.sh

Hello, World!

---- script_3.sh ---

echo Hello, World!

----------------------

Ubuntu: > ./execvp_sample ./script_3.sh

Hello, World!

Alpine Linux: > ./execvp_sample ./script_3.sh

error code: ENOEXEC


Thanks,

Alexander.


^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [musl] execvp() behaviour with unrecognized file header
  2020-02-12 13:54 [musl] execvp() behaviour with unrecognized file header Alexander Scherbatiy
@ 2020-02-12 14:13 ` A. Wilcox
  2020-02-12 14:27   ` Rich Felker
  2020-02-13 20:11 ` Markus Wichmann
  1 sibling, 1 reply; 8+ messages in thread
From: A. Wilcox @ 2020-02-12 14:13 UTC (permalink / raw)
  To: musl


[-- Attachment #1.1: Type: text/plain, Size: 974 bytes --]

On 12/02/2020 07:54, Alexander Scherbatiy wrote:
> Hello,
> 
> execvp() works differently on Linux Alpine and Ubuntu if it is called
> with a file which does not contain a proper shebang line. The file is
> executed on Ubuntu. It results to  ENOEXEC error on Linux Alpine.
> 
> man execvp on Ubuntu has description: "If the header of a file isn't
> recognized (the attempted execve(2) failed with the error ENOEXEC),
> these functions will execute the shell (/bin/sh) with the path of the
> file as its first argument."
> 
> Does execvp() from musl behaves differently by purpose in this case?


This has been discussed before on this list:

https://www.openwall.com/lists/musl/2018/03/09/1

Since this is non-conformant to POSIX, Adélie integrated quinq's patch:
https://code.foxkit.us/adelie/musl/commit/16cbbea8e97d08e0fc6e9ccda0cf8b6e87ed6b82

Best,
--arw

-- 
A. Wilcox (awilfox)
Project Lead, Adélie Linux
https://www.adelielinux.org


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [musl] execvp() behaviour with unrecognized file header
  2020-02-12 14:13 ` A. Wilcox
@ 2020-02-12 14:27   ` Rich Felker
  2020-02-12 20:01     ` A. Wilcox
  2020-02-13 10:02     ` Micha Nelissen
  0 siblings, 2 replies; 8+ messages in thread
From: Rich Felker @ 2020-02-12 14:27 UTC (permalink / raw)
  To: musl

On Wed, Feb 12, 2020 at 08:13:12AM -0600, A. Wilcox wrote:
> On 12/02/2020 07:54, Alexander Scherbatiy wrote:
> > Hello,
> > 
> > execvp() works differently on Linux Alpine and Ubuntu if it is called
> > with a file which does not contain a proper shebang line. The file is
> > executed on Ubuntu. It results to  ENOEXEC error on Linux Alpine.
> > 
> > man execvp on Ubuntu has description: "If the header of a file isn't
> > recognized (the attempted execve(2) failed with the error ENOEXEC),
> > these functions will execute the shell (/bin/sh) with the path of the
> > file as its first argument."
> > 
> > Does execvp() from musl behaves differently by purpose in this case?
> 
> 
> This has been discussed before on this list:
> 
> https://www.openwall.com/lists/musl/2018/03/09/1
> 
> Since this is non-conformant to POSIX, Adélie integrated quinq's patch:
> https://code.foxkit.us/adelie/musl/commit/16cbbea8e97d08e0fc6e9ccda0cf8b6e87ed6b82

Note that this patch has multiple problems which is why it's not
upstream: unbounded vla, inconsistency of not supporting the shell
behavior in execvpe (nonstandard extension, but should behave
analogously), and redundant code in execlp (execvp, which it's
calling, is already doing the fallback). I'm not sure what the right
fix is. These functions are supposed to be safe to use from a vforked
child, so allocation is kinda out of the question, at least not
without some heavy machinery to prevent a leak in the parent's address
space. I'd welcome ideas for a real fix.

Rich

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [musl] execvp() behaviour with unrecognized file header
  2020-02-12 14:27   ` Rich Felker
@ 2020-02-12 20:01     ` A. Wilcox
  2020-02-13 10:02     ` Micha Nelissen
  1 sibling, 0 replies; 8+ messages in thread
From: A. Wilcox @ 2020-02-12 20:01 UTC (permalink / raw)
  To: musl


[-- Attachment #1.1: Type: text/plain, Size: 1026 bytes --]

On 12/02/2020 08:27, Rich Felker wrote:
> Note that this patch has multiple problems which is why it's not
> upstream: unbounded vla, inconsistency of not supporting the shell
> behavior in execvpe (nonstandard extension, but should behave
> analogously), and redundant code in execlp (execvp, which it's
> calling, is already doing the fallback). I'm not sure what the right
> fix is. These functions are supposed to be safe to use from a vforked
> child, so allocation is kinda out of the question, at least not
> without some heavy machinery to prevent a leak in the parent's address
> space. I'd welcome ideas for a real fix.
> 
> Rich
> 


Indeed, the patch is not ideal.  It was simply the fastest way to ensure
conformance with this behaviour, which was important for reasons that
are lost to the sands of time.  (I no longer have any recollection of
which package was demanding this behaviour.)

Best,
--arw

-- 
A. Wilcox (awilfox)
Project Lead, Adélie Linux
https://www.adelielinux.org


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [musl] execvp() behaviour with unrecognized file header
  2020-02-12 14:27   ` Rich Felker
  2020-02-12 20:01     ` A. Wilcox
@ 2020-02-13 10:02     ` Micha Nelissen
  2020-02-13 18:29       ` Rich Felker
  1 sibling, 1 reply; 8+ messages in thread
From: Micha Nelissen @ 2020-02-13 10:02 UTC (permalink / raw)
  To: musl, Rich Felker

On 12-02-2020 15:27, Rich Felker wrote:
>> Since this is non-conformant to POSIX, Adélie integrated quinq's patch:
>> https://code.foxkit.us/adelie/musl/commit/16cbbea8e97d08e0fc6e9ccda0cf8b6e87ed6b82
>
> Note that this patch has multiple problems which is why it's not

For execlp, what about 'return execvp("/bin/sh", &file);' in case of
ENOEXEC? Too ugly? Assumes right-to-left push order with top-down stack
(or left-to-right in case of bottom-up stack).

Doesn't work for execvp itself though.

Gr, Micha

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [musl] execvp() behaviour with unrecognized file header
  2020-02-13 10:02     ` Micha Nelissen
@ 2020-02-13 18:29       ` Rich Felker
  0 siblings, 0 replies; 8+ messages in thread
From: Rich Felker @ 2020-02-13 18:29 UTC (permalink / raw)
  To: musl

On Thu, Feb 13, 2020 at 11:02:08AM +0100, Micha Nelissen wrote:
> On 12-02-2020 15:27, Rich Felker wrote:
> >> Since this is non-conformant to POSIX, Adélie integrated quinq's patch:
> >> https://code.foxkit.us/adelie/musl/commit/16cbbea8e97d08e0fc6e9ccda0cf8b6e87ed6b82
> >
> > Note that this patch has multiple problems which is why it's not
> 
> For execlp, what about 'return execvp("/bin/sh", &file);' in case of
> ENOEXEC? Too ugly? Assumes right-to-left push order with top-down stack
> (or left-to-right in case of bottom-up stack).

This doesn't work -- even if you ignore UB and assume some simplistic
"high level asm" model of C.

There is a clean solution for execlp, just expanding the VLA by a
couple slots (VLA can be assumed reasonable size since the same number
of args were passed in to execlp and since the number is a fixed
compile-time constant the programmer has decided to use rather than
potentially variable) and prepending to the VLA if needed...

> Doesn't work for execvp itself though.

...but regardless execvp needs a solution too, and execlp can just
piggyback on whatever execvp does, so there's really no reason to be
writing a specialized version of this functionality for execlp.

Rich

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [musl] execvp() behaviour with unrecognized file header
  2020-02-12 13:54 [musl] execvp() behaviour with unrecognized file header Alexander Scherbatiy
  2020-02-12 14:13 ` A. Wilcox
@ 2020-02-13 20:11 ` Markus Wichmann
  2020-02-13 23:21   ` Rich Felker
  1 sibling, 1 reply; 8+ messages in thread
From: Markus Wichmann @ 2020-02-13 20:11 UTC (permalink / raw)
  To: musl

Hi all,

so I had a look around at other implementations, since I thought the
problem might be a solved one, and here's what I found:

newlib does not support this behavior at all.

bionic uses a VLA for the new argv[]. I didn't even know C++ had VLAs,
so at least I learned something from this.

glibc also uses a VLA.

klibc also does not support this behavior.

uclibc-ng is an interesting one. On architectures with MMU they allocate
the necessary space with alloca(), but without an MMU, they will use
mmap() directly to try and minimize the memory leak, as a comment
directly before the code responsible tells us.

So yeah, the competition appears to either not bother or just use VLAs.
I guess it is not a huge problem in practice?

Ciao,
Markus

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [musl] execvp() behaviour with unrecognized file header
  2020-02-13 20:11 ` Markus Wichmann
@ 2020-02-13 23:21   ` Rich Felker
  0 siblings, 0 replies; 8+ messages in thread
From: Rich Felker @ 2020-02-13 23:21 UTC (permalink / raw)
  To: musl

On Thu, Feb 13, 2020 at 09:11:03PM +0100, Markus Wichmann wrote:
> Hi all,
> 
> so I had a look around at other implementations, since I thought the
> problem might be a solved one, and here's what I found:
> 
> newlib does not support this behavior at all.
> 
> bionic uses a VLA for the new argv[]. I didn't even know C++ had VLAs,
> so at least I learned something from this.
> 
> glibc also uses a VLA.
> 
> klibc also does not support this behavior.
> 
> uclibc-ng is an interesting one. On architectures with MMU they allocate
> the necessary space with alloca(), but without an MMU, they will use
> mmap() directly to try and minimize the memory leak, as a comment
> directly before the code responsible tells us.

This makes no sense. alloca does not cause any memory leak; it just
blows away the stack if the stack isn't sufficiently large. On the
other hand mmap is a memory leak without some dirty tricks to get rid
of the leak. You could either use synchronization, taking advantage of
shared memory with parent, to allocate a single mmap that's reused
(and possibly resized) every time there's a vfork child calling
execvp, but otherwise left around (bounded usage so not a "leak"), or
you could stick a hook in the parent side of vfork that checks for a
thread-local mmap execvp buffer pointer and unmaps it before return in
the parent if it's found.

> So yeah, the competition appears to either not bother or just use VLAs.
> I guess it is not a huge problem in practice?

Using VLAs is worse than not supportint it at all -- it's an
exploitable vuln.

Rich

^ permalink raw reply	[flat|nested] 8+ messages in thread

end of thread, other threads:[~2020-02-13 23:21 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-02-12 13:54 [musl] execvp() behaviour with unrecognized file header Alexander Scherbatiy
2020-02-12 14:13 ` A. Wilcox
2020-02-12 14:27   ` Rich Felker
2020-02-12 20:01     ` A. Wilcox
2020-02-13 10:02     ` Micha Nelissen
2020-02-13 18:29       ` Rich Felker
2020-02-13 20:11 ` Markus Wichmann
2020-02-13 23:21   ` Rich Felker

Code repositories for project(s) associated with this public inbox

	https://git.vuxu.org/mirror/musl/

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).