there seems to be some interest in this, so i thought i would post my notes, made more presentable.
here i detail ways to use ssh to restrict access to the filesystem as well as X, mitigating the 'security nightmare' that is X11, not to mention preventing possible leaking of local data. this uses more proven code so may be better than eg virtualization for some things. comments/questions/corrections/etc welcome. i'm sure i missed something. this subject of isolating untrusted programs has been coming up recently, though mostly in regards to web browsers (firefox, xombrero). now i don't use firefox (or any 'modern browser'), but other X programs i have tested work fine (xpdf mplayer xloadimage djview4 feh). there are some that don't seem to work that i haven't tracked down the exact cause yet (qiv zathura; something to do with glib). this works well with w3m+feh for me though. if someone is ambitious enough to try firefox, for a start, they should read faq 10.16 which has a basic method of working out dependences, though i've expanded on that here. also Johnathon Thornburg's work here saved me some time, and gets into the security issues: http://marc.info/?l=openbsd-misc&m=141616701418506&w=1 still, i'm not sure you can do this for firefox, but this may get you started. if not, your best bet may be J. Thornburg's method here: https://marc.info/?l=openbsd-misc&m=141867559504962&w=2 which you should read anyway. much of the rest of the information is spread around various man pages (eg sshd_config(5)) also note Xephyr is required for some programs using 'ssh -X' eg xpdf 0. intro for simplicity, i will be setting up a single jail for multiple programs. you could isolate each program with it's own user and jail. one issue though would be that many dependencies would be duplicated. on the other hand you could then use ssh's ForceCommand. for future reference, i will assume there is a user: /etc/passwd: _inmate:*:1111:1111:public jail account:/home/cell:/bin/sh /etc/group: _chaingang:*:1111: 1. setting up ssh to chroot: you need to add an entry like the following to /etc/ssh/sshd_config: Match User _inmate ChrootDirectory /home/jail AuthorizedKeysFile /home/jail.authorized_keys X11Forwarding yes AllowTcpForwarding no # PermitTTY no # ForceCommand xpdf /tmp/*pdf you may have to tweak this a bit depending on your use. if you are using X11 programs you will need "X11Forwarding yes" if you are using a terminal (eg a console web browser) you may need "PermitTTY yes". (some X programs also require a terminal for some functions eg mplayer). if you are using a single command, you will want to use ForceCommand. remember also that the authorized_keys file must be owned by _inmate, but in the above example i keep it outside of the jail so the user doesn't have access. N.B. remember that when the user's directory is processed, the home directory in /etc/passwd will be appended to the above ChrootDirectory. in our example, the ChrootDirectory is /home/jail and the user _inmate's home directory in /etc/passwd is /home/cell, which ssh will be combine into /home/jail/home/cell. example using ForceCommand: Match User _inmate ChrootDirectory /home/jail AuthorizedKeysFile /home/jail.authorized_keys X11Forwarding no AllowTcpForwarding no PermitTTY yes ForceCommand w3m -B 2. setting up basic chroot filesystem there are some files you need in the chroot in order for various programs to function, at a minimum you need shared library support and the user's homedir: essential user files /home/jail/home/cell/ /home/jail.authorized_keys (must be owned by user ie _inmate) NOTE: all following files are relative to chroot directory ($_chroot), in this case /home/jail. for the most part you can 'cp -p file $_chroot/file'. to handle shared libs (required): /sbin/ldconfig /usr/libexec/ld.so /var/run/ after these files are installed, you will need to run ldconfig $ chroot $_chroot ldconfig /usr/{,X11R6,local}/lib which will create /var/run/ld.so.hints. basic directories that are needed: /bin /sbin /etc /usr/{,X11R6,local}/lib /tmp and since we are going to be installing packages, create: /var/db/pkg/ to run X you will need a minimum: /etc/fonts/ /usr/X11R6/lib/X11/fonts/ /usr/X11R6/bin/xauth you will also need the shared libraries xauth depends on: $ ldd /usr/X11R6/bin/xauth /usr/X11R6/bin/xauth: Start End Type Open Ref GrpRef Name 1669e000 366a3000 exe 1 0 0 /usr/X11R6/bin/xauth 09606000 2960a000 rlib 0 2 0 /usr/X11R6/lib/libXau.so.10.0 0b3fd000 2b401000 rlib 0 1 0 /usr/X11R6/lib/libXext.so.13.0 0e418000 2e41c000 rlib 0 1 0 /usr/X11R6/lib/libXmuu.so.6.0 0092e000 209ad000 rlib 0 3 0 /usr/X11R6/lib/libX11.so.16.0 0b40b000 2b43b000 rlib 0 1 0 /usr/lib/libc.so.77.3 02b35000 22b3b000 rlib 0 3 0 /usr/X11R6/lib/libxcb.so.3.1 02cbb000 22cbf000 rlib 0 1 0 /usr/X11R6/lib/libpthread-stubs.so.2.0 0f995000 2f99a000 rlib 0 1 0 /usr/X11R6/lib/libXdmcp.so.11.0 055bc000 055bc000 rtld 0 1 0 /usr/libexec/ld.so so all entries of type 'rlib' above need to be copied to the proper place under /home/jail, eg: for _lib in $(ldd /usr/X11R6/bin/xauth | grep ' rlib ' | awk '{printf $7" "}') do [ -f $_chroot/$_lib ] || cp -p $_lib $_chroot/$_lib done you need a shell (required by X): /bin/sh (this is needed for xauth to function. ssh calls popen() which calls execle() with /bin/sh in order to run it. i haven't found out how to do without a shell yet) for dns you will need: /etc/resolv.conf and maybe: /etc/hosts (i have local definitions in hosts) if you want a terminal: /dev/tty /usr/share/misc/terminfo.db (for a session sshd_config(5) recommends: /dev/{null,zero,tty,stdin,stdout,stderr,arandom} (also, ssh complains without access to /dev/ttypX files, although nothing significant seems to happen) there may be some things that use time: $ cp -R /etc/localtime $_chroot/etc/ if you add programs like ls(1) that need user/group names, you need /etc/pwd.db /etc/group (note: without pwd.db 'ls' lodges complaints in /var/log/message) i also have a /home/jail/tmp/ dir same as /tmp/. files for the commands i run are copied or linked here. they should be owned by non-_inmate, but they need read permission to be useful. 3. adding packages/dependencies: adding a package is a bit difficult, especially with dependencies. it is complicated and tedious. (i wrote a script for this which i include at the end for convenience). one method i worked out is basically: $ (cd /usr/ports/textproc/xpdf && make print-run-depends) which gives: This port requires package(s) "jpeg-9a libiconv-1.14p1 ghostscript-fonts-8.11p2 png-1.6.14 openmotif-2.3.4p0" to run. this will give the proper order needed to install them. problems: there are some problems you might run into here. a version of mplayer i was testing with required libgnutls (via ldd mplayer) but gnutls was not included as a dependency (for a reason, it wasn't one. if gnutls was already installed it got pulled in. this particular case only lasted a while.) there are other methods to getting the dependences, which are in my script. 4. running programs you should alread have X running, which will be on port 6000 (DISPLAY=:0) first you want a copy of Xephyr running (some programs will not function using 'ssh -X' without Xephyr). $ Xephyr :1 & Xephyr will be listening on DISPLAY=:1 (port 6001) now you want to use ssh to login to the jailed user _inmate, creating a secure X11 tunnel to the Xephyr instance: $ env DISPLAY=:1 ssh -X _inmate@localhost xpdf /tmp/file.pdf ssh reads in DISPLAY to know where the local end of the tunnel is (the X server). if you do not set it as above, it will be set to the current server as specified in DISPLAY (probably :0) and will bypass Xephyr (:1). this will set up an X11 tunnel, probably on DISPLAY=:10 (port 6010), which is what all programs running in the jail will use (DISPLAY will be set by ssh automatically) you can also set ForceCommand to run just that program: Match User _inmate ChrootDirectory /home/jail AuthorizedKeysFile /home/jail.authorized_keys X11Forwarding yes AllowTcpForwarding no # PermitTTY no ForceCommand xpdf /tmp/*pdf which you can run using: $ env DISPLAY=:1 ssh -X _inmate@localhost since the programs i use are for existing files, i need to copy or link them into the jail. i use a script which looks something like this: #!/bin/sh _jailroot=/home/jail [ ${#1} -eq 0 ] && { echo "nothing to do"; return 0; } if [[ "$(df -k "$1")" = "$(df -k $_jailroot/tmp)" ]];then ln "$1" $_jailroot/tmp else cp "$1" $_jailroot/tmp fi env DISPLAY=:1 ssh -X _inmate@localhost xpdf /tmp/"$1" rm $_jailroot/tmp/"$1" appendix 1. some package quirks some packages require some special handling. these are a few things i ran across, but there are certainly others. this should give you an idea of some problems you may run across. for gdk-pixbuf, you need to manually run: $ sudo chroot sh -c "gdk-pixbuf-query-loaders >/usr/local/lib/gdk-pixbuf-2.0/2.10.0/loaders.cache" or the equivalent for that version. the problems with pango seem to me to indicate a bigger problem. inside the jail, pango complains and requires: $ pango-querymodules > '/etc/pango/pango.modules' i have the exact package installed outside the jail, and it functions fine without 'pango.modules', which doesn't seem to get installed normally. to get it to work in the jail you need to: $ sudo chroot sh -c "pango-querymodules >/etc/pango/pango.modules" appendix 2. scripts. i am sending these in a different mail, so that this one is not too long.