View Issue Details
ID | Project | Category | View Status | Date Submitted | Last Update |
---|---|---|---|---|---|
0001514 | unreal | documentation | public | 2004-01-30 22:57 | 2004-02-11 03:53 |
Reporter | thilo | Assigned To | |||
Priority | normal | Severity | feature | Reproducibility | N/A |
Status | resolved | Resolution | fixed | ||
Summary | 0001514: Chrooting should be better documented | ||||
Description | CHROOTing the ircd is a really very nice feature of unreal. Firstly, it builds up a barrier against hackers, secondly one can use ports below 1024, like 194 for the officially IANA assigned IRC port and 994 for IANA assigned irc-ssl port. Actually, there is not much work to be done once the ircd was started up... the only problem there is with chroot is when trying to run the ircd with SSL support. SSL Connections are not possible without a little trick: create the directory dev/ in the main ircd directory and hardlink /dev/urandom and /dev/tty into there. The directory must be accessible for the ircd user of course. Took me a few strace sessions to find out, maybe you can spare less experienced users this bug hunt. | ||||
Tags | No tags attached. | ||||
3rd party modules | |||||
|
Hmm, I'll look into that, but another thing. What version of Unreal is this? I ask because we've made some changes since b19 (related to remote includes and the module system) that could potentially affect the chroot stuff, so I was wondering if that is working for you or not... |
|
sorry, can't confirm anything, I am using the plain beta19 version. |
|
Ok, well then I guess we'll just have to hope it works for now ;) |
|
I'm thinking maybe I'll make it auto do this (would you mind testing it if I get around to it?) Basically there is a function called mknod() [which does the same thing as the mknod command] which should allow me to auto create these files. I'd just need someone to test it out when I finish it. I think this would be a better solution than having to force the user to hard link... |
|
thilo: @"secondly one can use ports below 1024": I hope you don't mean running the whole thing as root... Running the whole ircd as root is a very bad idea. Even if it's chrooted, in fact running a chrooted daemon as root does not help much at all... every security person will tell you that ;). codemastr: problem is mknod() can only be done by root [otherwise you could simply create a few devices with write permissions and hack the box] :p And hardlinks will (obviously) in many cases fail due to crossing of filesystems, and symbolic links to somewhere outside the chroot environment won't work... so you would still end up with root having to create the entry unless you are lucky ;). fun. Still, thanks for letting us know this SSL+chroot-specific problem! :) |
|
Best solution may be to start unreal from a suid helper app. The helper should only make the apropriate /dev entries and libraries needed. Then start unreal chrooted as the correct user. |
|
come on syzop .. you should know me better than that now :P OF COURSE! I did not overlook the SETUID defines in config.h .... generally, you need root access to be able to execute the chroot() call anyways. Cnils: libraries are preloaded before the chroot call is actually issued, thus, all libraries are loaded without the necessity of the libraries being present in the chroot environment. I do not know the OpenSSL library. But what struck me as possibility to avoid the problem, is open()ing the files _before_ the chroot() call is issued .. that is not as easy of course if the open() call is within the OpenSSL library itself. In the case of chrooting, the ircd must be started as root anyways, and it only later on changes its effective user id. Why would we need any helper app at all? You could just check whether SSL is included, then check for the presence of these devices, mknod() them if necessary, and be done with. edited on: 01-31-04 12:21 |
|
Heh, we even had "exploits" for people running suid with CMDLINE_CONFIG enabled... so I'm not surprised of anything anymore ;). Oh mknod() at _runtime_ hmm, right... just stat() the original entry and mknod() the new one... that would be good indeed... Btw, are you sure you need /dev/tty? seems unlogical :P. Ah well, that's for code to find out ;). I'll have fun with less interresting bugs... |
|
I am pretty sure. Both turned up in the strace output, and both were needed in order for SSL to work. I tested it. |
|
oh btw, something I also noticed is that it tries to read /etc/resolv.conf after being chrooted, thus DNS might not be working: [20:22:13] -maintest.test.net- Nameserver list has 1 server(s): [20:22:13] -maintest.test.net- 0. 0.0.0.0 [..] the fun is, 0.0.0.0 works just like 127.0.0.1 (loopback), so if you have a local nameserver running it will work... but it's still a bug ;). thilo : I can confirm that /dev/urandom is (obviously) required, but /dev/tty is not... if you remove the dev/tty thing in the chroot, does it refuse to run then or do you experience problems? |
|
src/ircd.c:1492: if ((fd = open("/dev/null", O_WRONLY)) < 0) src/random.c:204: fd = open("/dev/urandom", O_RDONLY); src/s_bsd.c:635: if ((fd = open("/dev/tty", O_RDWR)) >= 0) |
|
i thought, the dns server was set in the configuration file? (although i don't like it ...) on tty: nope, i see now it's not required for SSL to work, nevertheless turned up in the strace output. codemaster showed you the reason why. thilo@Thilo $ strings /usr/lib/libcrypto.so | grep dev ENGINE_load_cryptodev /dev/ubskey /dev/urandom /dev/random /dev/srandom /dev/egd-pool secure device signature /dev/tty |
|
src/ircd.c:1492: if ((fd = open("/dev/null", O_WRONLY)) < 0) seems only to be (somtimes) used if compiled in debugmode, but I would still recommend to have a /dev/null device yes... I won't be surprised if any other lib depends on it, and it's a good idea anyway ;). src/random.c:204: fd = open("/dev/urandom", O_RDONLY); right.. highly recommended to have. And in in case of SSL required to make it work :). src/s_bsd.c:635: if ((fd = open("/dev/tty", O_RDWR)) >= 0) hmm #ifdef TIOCNOTTY if ((fd = open("/dev/tty", O_RDWR)) >= 0) { (void)ioctl(fd, TIOCNOTTY, (char *)NULL); (void)close(fd); } #endif hmmm.. "TIOCNOTTY Detach the current process from its controlling terminal. If the process is the session leader, then SIGHUP and SIGCONT signals are sent to the foreground process group and all processes in the current session lose their controlling tty. " not sure if that is very useful, since we already fork() and stuff? ;) Perhaps this was for src/ircd -F& or something weird... I don't know.. all I know is that it worked perfectly without a /dev/tty entry here, but if you think it's required for some OS's... :p. It's just that one should always try to use a minimum amount of /dev entries (the more you add, the more you help a hacker) ;) |
|
##### It's just that one should always try to use a minimum amount of /dev entries (the more you add, the more you help a hacker) ;) ##### Yes, that's right of course. |
|
Are you sure /etc/resolv.conf screws things up? From what I see, ircd_res_init() is called before chroot(). So that means it should work. Also, about all those /dev entries in ssl, that shouldn't be a problem. the /dev/urandom, /dev/srandom, /dev/random are an "or" thing. Meaning it tries to find one of those three. The /dev/egd-pool shouldn't be a problem since Unreal already allows you to specify the path to an egd socket, so you can (and probably should) run your own. And /dev/ubskey, I have no idea what that is :) |
|
Ok can you try this, apply http://www.codemastr.com/chroot.diff then recompile, then remove the dev dir you created in the Unreal dir, then start Unreal. It should create the dev dir and the necessary devices. |
|
small uh-oh: 1. there is no EEXISTS ... it's called "EEXIST" ... 2. Permissions! Kickchat:/home/ircd/ircd-testing# ls -l dev/ total 0 -rw------- 1 root root 0 Jan 31 21:53 null -rw------- 1 root root 0 Jan 31 21:53 tty -r-------- 1 root root 0 Jan 31 21:53 urandom |
|
Ah .. forgot. ##### Are you sure /etc/resolv.conf screws things up ##### like I said, I thought the nameserver was set in the unrealircd.conf rather than resolv.conf? ##### And /dev/ubskey, I have no idea what that is :) ##### Maybe some usb memory stick with a key on it? =) I guess mode_t should be: S_IRUSR | S_IWUSR | S_IWGRP | S_IRGRP | S_IROTH for /dev/null and /dev/tty and S_IRUSR | S_IRGRP | S_IROTH for /dev/random .... and finally, yet another issue: The ircd.pid file is created before the chroot takes place, resulting in the ircd.pid to be unreadable in my setup by the default ircd user. (i prefer more restrictive umasks ...) edited on: 01-31-04 22:06 |
|
like I said, I thought the nameserver was set in the unrealircd.conf rather than resolv.conf? Trust me... I'm a unreal coder you know ;p. |
|
yeah, i see it in the source code, but then what is the purpose of the set::dns::nameserver directive? |
|
the purpose of it is to get annoying questions |
|
I apologize annoying the great ircd coders for asking such stupid questions... especially since the changelog claims to not anymore use the resolv.conf as reference while prior posts suggested the opposite .. edited on: 02-01-04 00:11 |
|
no problem! |
|
Ok I made some changes, I corrected the EEXISTS thing (I must be blind cause I could swear that's what the man page said!) and I changed the permissions, stupid me, I hardcoded those permissions... now it will just use whatever permissions the original file had. So if /dev/null was 777, then dev/null will be 777, that seems like the best way to go. Would you be able to apply the new patch (same URL) and make sure it works now? Again you'll have to remove the dev/ directory so that Unreal will recreate the files (this time with the correct permissions). |
|
The dev-creating part works now. The mknod / stat etc functions though do not return errno codes ... they only return 0 or -1 ... you must look in the errno variable for the error code. |
|
Ok can you reinstall the patch yet again, this time it should work perfectly (at least I hope) :P It stinks not being able to test it myself... *** Edit: I also made this patch correct the problem with permissions on ircd.pid due to setu/gid. It should use the correct user/group now. Could you try deleting ircd.pid first though (since the ircd won't be able to overwrite the file since it is owned by root) then start Unreal. It should use the correct stuff now. edited on: 02-01-04 18:45 |
|
ircd@Kickchat:~/Unreal$ patch -p0 < chroot.diff patching file src/ircd.c Hunk #1 succeeded at 840 (offset -8 lines). Hunk #2 succeeded at 1249 (offset -19 lines). Hunk #3 FAILED at 1281. 1 out of 3 hunks FAILED -- saving rejects to file src/ircd.c.rej ircd@Kickchat:~/Unreal$ cat src/ircd.c.rej *************** *** 1244,1249 **** } } #endif Debug((DEBUG_NOTICE, "Server ready...")); SetupEvents(); #ifdef THROTTLING --- 1281,1287 ---- } } #endif + write_pidfile(); Debug((DEBUG_NOTICE, "Server ready...")); SetupEvents(); #ifdef THROTTLING ircd@Kickchat:~/Unreal$ That was the result when trying to patch both with the original ircd.c file from beta19 and with the latest CVS version. |
|
Strange that the current CVS would give you that error seeing as how the patch was made against the current CVS. In any case, I've committed the patch to the CVS server so if you just cvs update it should install that fine. However I believe I've identified yet another setuid problem in the current CVS (doesn't affect b19) which I'll have to look at. |
|
well, the device making and all works correctly now. but the pid file is not being created at startup. the write_pidfile function now only appears in some define for that weird OS ULTRIX in s_conf.c and there even is only executed when the ircd receives a SIGHUP. Oh .. and to make the splitting of hair perfect: Too restrictive umasks will probably also hinder the creation of files with correct permissions. Kickchat:/home/ircd/Unreal# umask 0027 so the original chmod of the device files is: Kickchat:/home/ircd/Unreal# ls -l /dev/null /dev/tty /dev/urandom crw-rw-rw- 1 root root 1, 3 Jul 21 2002 /dev/null crw-rw-rw- 2 root tty 5, 0 Jan 31 19:39 /dev/tty cr--r--r-- 2 root root 1, 9 Feb 3 06:56 /dev/urandom Kickchat:/home/ircd/Unreal# ls -l dev total 0 crw-r----- 1 root ircd 1, 3 Feb 3 22:20 null crw-r----- 1 root ircd 5, 0 Feb 3 22:20 tty cr--r----- 1 root ircd 1, 9 Feb 3 22:20 urandom and that's what it turned out to be. If I hadn't set the sticky gid bit for the parent directories, the group of these files would probably also have been root, thus unusable again for the ircd. If you wish I can sit myself behind the source code, code it, test it and send you a diff if I'm done. It's probably only a simple chmod() to take care of it. edited on: 02-03-04 22:29 |
|
Fixed resolver issue (always being localhost) in .2072 |
|
If you'd like to work on it be my guest, but as for write_pidfile I have no idea what you are talking about there. Yeah it is in an #ifdef in s_conf.c, however it's also used in src/ircd.c which is what I changed (I moved it to be after the setuid code). So you totally lost me with that whole thing... In current CVS, src/ircd.c line 1303 is a call to write_pidfile(). Maybe something got screwed up with the patching? As for the umask stuff... does that actually result in a problem? I mean does stuff fail if only the owner bits are set? (though I would have thought since mknod() has a param to specify the mode_t that it would have overwritten this). I would assume for this purpose the group/other flags are irrelevant. But of course, I suppose we could always work around this too. Before creating the devices we do: mode_t old = umask(0777); create the devices umask(old); Or something along those lines... It's fun how much it is to program when people make things secure :) Also I noticed another problem (only affects CVS) that I have to deal with. The new tmp/ directory. Files created there at startup in a setuid environment will be root:root. However after the setuid we can no longer overwrite them since we're not root anymore. I think the solution to this is to at startup whenever we create a file in tmp/, we then call chown() to use the specified uid/gid. That should work since if we are root, then we can read the files even if they are a different uid/gid, then once we switch to that uid/gid everything will be fine. |
|
yes you're right. I haven't downloaded the CVS version from the developer branch, but got to some other branch where the changes were not incorporated yet? anyways. I have made a diff against the ircd.c from the Unreal3.2-beta19 package. It's available at http://thilo.kickchat.com/chroot.diff i have tested it and it works now. To the thing with the tmp files: maybe you could just set the effective user id to another user than root, and change it back when done? that would be another possibility too, and spare you doing any chowns. |
|
I'll have a look at the chown() stuff :). thilo: no we cannot do that since we might need to bind to a <1024 port which is not allowed if the effective userid is not 0.. and since with for example remote includes we need to create the files BEFORE we might have all listen lines it's not an option to seteuid() later or something... There's of course setfsuid() but that's Linux specific... so let's just stick with chown() [on a sidenote I usually don't comment technical user suggestions but it might be informative to codemastr, although I doubt he would have overlooked this] |
|
file permissions stuff should be fixed in current CVS [.2074]. On a sidenote, curl (or rather ares) has a problem too... it doesn't read the nameserver info on init, no... it rather thinks it would be wise to reread it on every download... yeah right. So it will always fail, unless you create a etc/resolv.conf inside your chroot. |
|
I added your umask stuff in .2090. To our knowledge there only exists one problem with regards to chroot. The problem results from using libcurl for remote includes. The library will attempt to parse /etc/resolv.conf and fail since it is after a chroot. The library author's have been notified of this however and a solution is planned for the next version of libcurl. |
Date Modified | Username | Field | Change |
---|---|---|---|
2004-01-30 22:57 | thilo | New Issue | |
2004-01-30 23:37 |
|
Note Added: 0004803 | |
2004-01-31 00:19 | thilo | Note Added: 0004804 | |
2004-01-31 01:12 |
|
Note Added: 0004805 | |
2004-01-31 01:45 |
|
Note Added: 0004806 | |
2004-01-31 05:32 | syzop | Note Added: 0004807 | |
2004-01-31 11:30 | Cnils | Note Added: 0004809 | |
2004-01-31 12:12 | thilo | Note Added: 0004810 | |
2004-01-31 12:21 | thilo | Note Edited: 0004810 | |
2004-01-31 14:54 | syzop | Note Added: 0004811 | |
2004-01-31 15:05 | thilo | Note Added: 0004812 | |
2004-01-31 19:30 | syzop | Note Added: 0004816 | |
2004-01-31 19:48 |
|
Note Added: 0004817 | |
2004-01-31 20:03 | thilo | Note Added: 0004818 | |
2004-01-31 20:04 | syzop | Note Added: 0004819 | |
2004-01-31 20:22 | thilo | Note Added: 0004820 | |
2004-01-31 20:32 |
|
Note Added: 0004821 | |
2004-01-31 21:06 |
|
Note Added: 0004822 | |
2004-01-31 21:55 | thilo | Note Added: 0004823 | |
2004-01-31 22:04 | thilo | Note Added: 0004824 | |
2004-01-31 22:06 | thilo | Note Edited: 0004824 | |
2004-01-31 22:20 | syzop | Note Added: 0004826 | |
2004-01-31 22:52 | thilo | Note Added: 0004827 | |
2004-01-31 23:17 | syzop | Note Added: 0004828 | |
2004-02-01 00:10 | thilo | Note Added: 0004829 | |
2004-02-01 00:11 | thilo | Note Edited: 0004829 | |
2004-02-01 00:18 | syzop | Note Added: 0004830 | |
2004-02-01 05:32 |
|
Note Added: 0004836 | |
2004-02-01 11:33 | thilo | Note Added: 0004839 | |
2004-02-01 18:36 |
|
Note Added: 0004845 | |
2004-02-01 18:45 |
|
Note Edited: 0004845 | |
2004-02-03 18:12 | thilo | Note Added: 0004857 | |
2004-02-03 19:11 |
|
Note Added: 0004859 | |
2004-02-03 22:22 | thilo | Note Added: 0004863 | |
2004-02-03 22:26 | thilo | Note Edited: 0004863 | |
2004-02-03 22:29 | thilo | Note Edited: 0004863 | |
2004-02-03 22:45 | syzop | Note Added: 0004864 | |
2004-02-04 02:10 |
|
Note Added: 0004865 | |
2004-02-04 13:05 | thilo | Note Added: 0004867 | |
2004-02-04 21:13 | syzop | Note Added: 0004868 | |
2004-02-04 23:17 | syzop | Note Added: 0004876 | |
2004-02-11 03:53 |
|
Status | new => resolved |
2004-02-11 03:53 |
|
Resolution | open => fixed |
2004-02-11 03:53 |
|
Assigned To | => codemastr |
2004-02-11 03:53 |
|
Note Added: 0004968 |