From: Seebs on
On 2010-04-15 12:36:56 -0500, blacklight said:

> Even calling a
> system() on "/exe", "./exe" or "exe" gives no results. So, how do I invoke an
> executable file in a chroot() environment?

The most likely explanation would be that your chroot environment doesn't have
all the libraries and support files the programs need to run. It's possible
that a statically-linked binary would work on your system (I seem to recall
that being one of the workarounds), otherwise, you need to get enough of the
infrastructure of the system in place that executables run. Usually that means
a fair bit of /lib or /usr/lib, /etc, and probably /bin.

Generally, chroot(2) is most useful for simplifying execution paths within
a program that will use it directly. The case of setting up an entire virtual
filesystem and spawning new programs is a lot harder to get right. Note
also that plain chroot(2) offers essentially no security if you don't know how
to use it; you have to be root to use it, and if you don't immediately drop
those privileges, well, root can get out of a chroot directory very easily.

-s
--
Copyright 2010, all wrongs reversed. Peter Seebach / usenet-nospam(a)seebs.net
http://www.seebs.net/log/ <-- lawsuits, religion, and funny pictures
http://en.wikipedia.org/wiki/Fair_Game_(Scientology) <-- get educated!

From: blacklight on
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Well I've also tried by using pipe()+fork()+exec() routing to get around the
issue, but it doesn't work this way too.

Again, this is the tree where I'm going to chroot:

+ /p
|--> /p/popen
|--> /p/test

The source code of test in this case is very simple, a simple and stupid
printf, so it relies on no external library. This is the new code of popen.c:


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

int
main ( int argc, char *argv[] )
{
if (chroot(".") < 0)
return EXIT_FAILURE;

execl ("/test", "test", NULL);
return EXIT_SUCCESS;
}

Again, it doesn't work like this (if I just remove the chroot call and I exec
"test" in the ordinary way, through the absolute path "/p/test" as first
parameter of execl, everything works fine). I've also tried using a pipe:


#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>

typedef int pipe_t[2];

int
main ( int argc, char *argv[] )
{
pipe_t pp;
char ch;

if (chroot(".") < 0)
return EXIT_FAILURE;

if (pipe(pp) < 0)
return EXIT_FAILURE;

if (!fork()) {
close(pp[0]);
close(1);
dup(pp[1]);

execl ("/test", "test", NULL);
close(pp[1]);
exit(0);
} else {
close(pp[1]);

while (read(pp[0], &ch, 1) > 0)
write (1, &ch, 1);
write (1, "\n", 1);

close(pp[0]);
wait ((int*) 0);
}

return EXIT_SUCCESS;
}

This behaviour is really weird and I can find no explanation for that.
Anyway, I cannot avoid the chroot() jail. I'm working to improve a tiny
webserver coded by a friend in order to let it work with CGI apps/scripts, and
it strongly relies on chroot() system call.

(Oh, and of course I execute this program as root, lol).

William Ahern <william(a)wilbur.25thandclement.com> wrote:
> blacklight <blacklight(a)wintermute.blacklight.org> wrote:
>> I'm experiencing a weird behaviour in executing programs in a chroot()
>> environment. This is the situation.
> <snip>
>> while (fread(&ch, 1, 1, pipe) > 0)
>> printf ("%c", ch);
>> printf ("\n");
>>
>> pclose(pipe);
>> return EXIT_SUCCESS;
>> }
>>
>> popen() does not fail, but just no character is read.
>
> popen() will only fail if it cannot create a pipe or fork (or perhaps
> allocate memory). So popen() will work even if the executable doesn't even
> exist, because that won't be determined until the exec() is attempted. If
> the exec() fails, then what? That somehow must be communicated to the
> process that called popen(), but there's no defined way to do that. pclose()
> won't give you the exit value of the process. And you can't generally
> distinguish a successful fork+exec which happens to write nothing to stdout
> from a failed exec after the fork. Basically, popen() isn't very useful for
> debugging your issue; it can't signal the cause of the probable culprit.
>
> There's another more specific issue, which is probably the source of your
> troubles. popen() and system() use the command as a parameter to /bin/sh,
> which is what they will actually exec() directly (i.e. `/bin/sh -c
> "[command]"'). Unless /bin/sh exists in the new root, you can't expect to
> use either popen() or system(), no matter what you're ultimately trying to
> execute. If there's no /bin/sh, then you need to create your own popen-like
> routine using pipe()+fork()+exec(). The code to do this is quite short but
> conceptually very dense, so one so should be very familiar with the Unix
> process model before attempting it.
>
> Note that system() does return the exit value, and I bet you'll see a
> difference if you compare the value from the chroot'd call and the
> non-chroot'd call.
>
>> Of course if I do not use chroot() and i just call popen ("./exe", "r") I
>> have no problem. I also have tried popen-ing "./exe" and "exe", both
>> without any results. Even calling a system() on "/exe", "./exe" or "exe"
>> gives no results. So, how do I invoke an executable file in a chroot()
>> environment?
>
> The procedure is exactly the same. There are no other side-effects of the
> chroot() itself. The problem is likely the absence of /bin/sh, however,
> which is a collateral issue.

- --
- -----BEGIN GEEK CODE BLOCK-----
Version: 3.1
GAT d? a? C++++ U++++ P++++ L+++++ E--- W+++ !w PS+++ PE-- Y++ PGP++ X++
R+ tv-- b+>+++ DI++ G++ e+++ h* r++ z**
- ------END GEEK CODE BLOCK------

- -ONLY- email me using my PGP key
# http://pgp.mit.edu:11371/pks/lookup?op=get&search=0xE8468AFB46DBC195

Admin of
# http://0x00.ath.cx
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.9 (GNU/Linux)

iEUEARECAAYFAkvIPe8ACgkQ6EaK+0bbwZVbQACY3RwWmaNo6jH23674Wwk0MDPJ
oQCePA3XQlq13hREUyDgN7I7DAGA9tI=
=BrVq
-----END PGP SIGNATURE-----
From: Rainer Weikusat on
blacklight <blacklight(a)wintermute.blacklight.org> writes:
> Again, this is the tree where I'm going to chroot:
>
> + /p
> |--> /p/popen
> |--> /p/test
>
> The source code of test in this case is very simple, a simple and stupid
> printf, so it relies on no external library. This is the new code of popen.c:
>
>
> #include <stdio.h>
> #include <stdlib.h>
> #include <unistd.h>
>
> int
> main ( int argc, char *argv[] )
> {
> if (chroot(".") < 0)
> return EXIT_FAILURE;
>
> execl ("/test", "test", NULL);
> return EXIT_SUCCESS;
> }
>
> Again, it doesn't work like this (if I just remove the chroot call and I exec
> "test" in the ordinary way, through the absolute path "/p/test" as first
> parameter of execl, everything works fine).

You either need to add a couple libraries to your chroot or ensure
that programs you might want to execute are statically linked.
From: Mark Hobley on
blacklight <blacklight(a)wintermute.blacklight.org> wrote:

> This behaviour is really weird and I can find no explanation for that.
> Anyway, I cannot avoid the chroot() jail. I'm working to improve a tiny
> webserver coded by a friend in order to let it work with CGI apps/scripts, and
> it strongly relies on chroot() system call.

You might want to look at thttpd then. That is a tiny webserver with CGI and
chroot capabilities, so is probably a similar to the one you are working on.

Mark.

--
Mark Hobley
Linux User: #370818 http://markhobley.yi.org/

From: Casper H.S. Dik on
Rainer Weikusat <rweikusat(a)mssgmbh.com> writes:

>blacklight <blacklight(a)wintermute.blacklight.org> writes:
>> Again, this is the tree where I'm going to chroot:
>>
>> + /p
>> |--> /p/popen
>> |--> /p/test
>>
>> The source code of test in this case is very simple, a simple and stupid
>> printf, so it relies on no external library. This is the new code of popen.c:
>>
>>
>> #include <stdio.h>
>> #include <stdlib.h>
>> #include <unistd.h>
>>
>> int
>> main ( int argc, char *argv[] )
>> {
>> if (chroot(".") < 0)
>> return EXIT_FAILURE;
>>
>> execl ("/test", "test", NULL);
>> return EXIT_SUCCESS;
>> }
>>
>> Again, it doesn't work like this (if I just remove the chroot call and I exec
>> "test" in the ordinary way, through the absolute path "/p/test" as first
>> parameter of execl, everything works fine).

>You either need to add a couple libraries to your chroot or ensure
>that programs you might want to execute are statically linked.

You can also easily test this using:

chroot /p /test

Casper
--
Expressed in this posting are my opinions. They are in no way related
to opinions held by my employer, Sun Microsystems.
Statements on Sun products included here are not gospel and may
be fiction rather than truth.