The first shell script, mkjail.sh, makes a tarball containing core shared libraries and the jail's etc/passwd file. The second shell script, initjail.sh, unpacks that tarball into the jail, and adds crucial /dev entries, a /proc filesystem, /etc files, core programs like sh, and non-toolchain shared libraries, and appends a given file to the jail's /etc/passwd file.
The two-step process is exactly what you need when testing cross-toolchains; you run the first script on the development system, and the second script on the target system. However, you should run them both on the target system initially and verify that the jail works before testing them with your newly compiled and probably buggy toolchain's shared libraries.
$ sh mkjail.sh / /etc/passwd $ su # zcat jail.tar.gz | sh initjail.sh myjail
$ su # /usr/sbin/chroot `pwd`/myjail /bin/sh(Note: the argument to chroot must be an absolute path, else exec fails. This appears to be a bug in Linux.) If you can't run a shell inside the jail, try running something easier, e.g. /bin/true (the simplest program there is):
$ su # /usr/sbin/chroot `pwd`/myjail /bin/trueOnce you get that working, go back to trying the shell. The most common cause of programs not running in the jail is missing shared libraries; to fix that, just copy the missing libraries from the system into the corresponding place in the jail. (Note that shared libraries consist of one or two files, and zero or more symbolic links; take care to not follow symbolic links when copying. In the provided scripts, I use the -d option to /bin/cp to avoid dereferencing links.)
Only users who have the root password can set up jails, partly because setting up a jail requires mounting /proc inside the jail. Users with the root password can set up jails on behalf of lesser users (though you might want to take away their ability to run setuid root programs if you do that, else they might be able to get out of the jail...)
$ cc chrootshell.c -o chrootshell $ su # install -o root -m 4755 chrootshell /sbin/chrootshellYou probably need to add the line
/sbin/chrootshellto /etc/shells, else login may refuse to run it.
fred2:x:1000:1000:Fred Smith's Jail:/home/fred/jail:/sbin/chrootshell
fred2:x:1000:1000:Fred Smith In Jail:/home/fred2:/bin/sh
$ telnet localhost username: fred2 password: xxxx $ lsWhen you do an ls, you should see just the files in that user's home directory inside the jail.
If telnet just closes the connection after login, first you need to figure out whether the problem is before or after chrootshell starts. Begin by listing the target system's logfiles, e.g.
$ su # cd /var/log # ls -ltrand examine the most recently change log files for telnet or pam permission problems. If you see any, it means you haven't even gotten to chrootshell yet.
If it looks like chrootshell is started, but then aborts, you can turn on more helpful logging by uncommenting the line
/* #define DEBUG_PRINTS */and recompiling and reinstalling chrootshell. This will cause verbose error messages to be sent directly to the file /var/log/chrootshell.log. The error messages tell you what line chrootshell.c is failing in, which should tell you enough to solve the problem.
Incidentally, rcp and rsh are the reason I used a C program for chrootshell rather than a shell script. A shell script version of chrootshell seems to fail to handle some of the remote commands
To do this on a Red Hat or Debian Linux workstation, install the rsh-server and rsh-client packages. You can also do this by downloading, building, and installing ftp://ftp.gnu.org/gnu/inetutils/inetutils-1.4.2.tar.gz. (Don't use version 1.4.1; the rshd in that version did not set up the remote environment properly.) For an embedded target, the only parts of inetutils you really need to build and install are rcp, rshd, and rlogind. (Yes, you need rcp even if you just want to run the server side.) sent by the gcc regression test due to quoting problems.
Once the binaries are installed on the target, you need to configure the system to run them.
rshd is run via inetd or xinetd or the like.
If your target system uses inetd, here's an example line to add to /etc/inetd.conf:
shell stream tcp nowait.1000 root /bin/rshdThe ".1000" tells inetd to expect 1000 sessions per minute, which should be sufficient to handle the gcc regression tests. (If you leave this off, inetd will stop spawning rshd after about the 40th session in a one-minute period.)
If your target system uses xinetd, you probably need to set the "cps" field of /etc/xinetd.d/rsh to a large value such as "200 5" for xinet to handle the expected traffic. I haven't tested this, but here's what I think /etc/xinetd.d/rsh should look like:
service login { socket_type = stream wait = no cps = 200 5 user = root server = /usr/sbin/in.rlogind disable = no }
rlogind is normally run standalone by giving the -d option. For instance, add this line to the target system's startup scripts:
/bin/rlogind -dIf you want to allow remote access by root (which is highly insecure, but useful in limited situations, as you'll see below), add the -o option.
If your system is using PAM, you may need to add entries in /etc/pam.d for rsh and rlogin. (If you installed the rsh-servers package, it probably added these entries for you.)
You probably need to add entries either to the systemwide /etc/hosts.equiv file (see 'man hosts.equiv') or the per-user .rhosts file (see 'man rhosts').
$ rsh target lsIf this doesn't work, look at the most recently modified files in the target's /var/log directory for interesting error messages. If that doesn't explain the problem, try running tcpdump and looking at the packets being sent and received. If that doesn't explain the problem, you can run rshd under strace to see what files it's opening -- maybe it's not looking where you expected for security info. (This requires modifying /etc/inetd.conf to invoke strace -o /tmp/strace.log /bin/rshd instead of just /bin/rshd.) When all else fails, you could build rsh from source and step through it in the debugger.
Once that's working, verify that you can spawn 200 commands in quick succession, e.g.
x=0; while test $x -lt 200; do rsh 11.3.4.1 ls; x=$(($x+1)); echo $x; doneand once that works, really overstress the system by verifying you can spawn 200 overlapping commands, e.g.
x=0; while test $x -lt 200; do rsh -n 11.3.1.1 ls & true ; x=$(($x+1)); echo $x; doneIf you get the error
poll: protocol failure in circuit setuparound the 40th iteration, then you may need to edit /etc/inetd.conf and add .1000 to the end of the 'nowait' keyword (or edit /etc/xinit.d/rsh and add the cps parameter...) as described above.
rcp /etc/hosts target:
$ TARGET=11.3.4.1 $ rcp $JAILUSER@$TARGET:/jail/etc/passwd jail_etc_passwd $ sh mkjail.sh result/sh4-unknown-linux-gnu/gcc-3.3-glibc-2.2.5/sh4-unknown-linux-gnu jail_etc_passwd $ rcp initjail.sh root@$TARGET: $ cat jail.tar.gz | rsh -l root $TARGET /bin/sh initjail.sh /jailThen test the jail to make sure it still works, e.g.
$ rsh -l jailuser target ls $ rcp /etc/hosts jailuser@target:/tmp
Copyright 2003, Ixia Communications. Released under the GPL.
Last revision 26 August 2003 by dkegel@ixiacom.com