On Wed, 25 Feb 2004, Jefferson Ogata wrote:
> > This doesn't try to automatically create directories or whatever, but
> > relies on the compile time option (e.g. /var/empty) but is IMHO better
> > in some sense.
>
> > - if (initgroups(pw->pw_name, 0) != 0 || setgid(pw->pw_gid) != 0 ||
> > + if (chroot_dir) {
> > + if (chroot(chroot_dir) != 0 || chdir (".") != 0) {
>
> No, you have to chdir to "/". Or better, do (chdir(chroot_dir) != 0 ||
> chroot(".") != 0).
Oops -- sorry for the typo! Obviously, that should be chdir("/") :)
I was looking this after my another patch, to chroot/droproot ntp, and
didn't copy it appropriately.
> There's one issue that occurred to me with chroot: on some
> platforms/configurations there may be a need for access to certain files outside
> the jail. If any get*byname() calls are being used, there may be a need for
> access to /etc/resolv.conf, /etc/protocols, etc. On IRIX, it's worse since all
> the get*by*() calls end up relying on access to /ns. So if -n isn't in force,
> chrooting might break some lookups. So that also argues for a commandline
> argument at least to switch it off.
I would not enable tcpdump at compile time on such systems, so I don't
think this is a particularly nasty problem.
--
Pekka Savola "You each name yourselves king, yet the
Netcore Oy kingdom bleeds."
Systems. Networks. Security. -- George R.R. Martin: A Clash of Kings
diff -ur -x configure tcpdump-2004.02.24/acconfig.h tcpdump-2004.02.23.new/acconfig.h
--- tcpdump-2004.02.24/acconfig.h Thu Jan 22 11:51:30 2004
+++ tcpdump-2004.02.23.new/acconfig.h Wed Feb 25 09:04:41 2004
@@ -129,3 +129,6 @@
/* define if should drop privileges by default */
#undef WITH_USER
+
+/* define if should chroot when dropping privileges */
+#undef WITH_CHROOT
diff -ur -x configure tcpdump-2004.02.24/configure.in
tcpdump-2004.02.23.new/configure.in
--- tcpdump-2004.02.24/configure.in Sat Jan 31 07:26:51 2004
+++ tcpdump-2004.02.23.new/configure.in Wed Feb 25 09:23:03 2004
@@ -111,6 +111,15 @@
AC_MSG_RESULT(no)
fi
+AC_ARG_WITH(chroot, [ --with-chroot=DIRECTORY when dropping privileges, chroot to
DIRECTORY])
+AC_MSG_CHECKING([whether to chroot])
+if test ! -z "$with_chroot" ; then
+ AC_DEFINE_UNQUOTED(WITH_CHROOT, "$withval")
+ AC_MSG_RESULT(to \"$withval\")
+else
+ AC_MSG_RESULT(no)
+fi
+
AC_MSG_CHECKING([whether to enable ipv6])
AC_ARG_ENABLE(ipv6,
[ --enable-ipv6 enable ipv6 (with ipv4) support
diff -ur -x configure tcpdump-2004.02.24/tcpdump.c tcpdump-2004.02.23.new/tcpdump.c
--- tcpdump-2004.02.24/tcpdump.c Tue Feb 24 10:12:18 2004
+++ tcpdump-2004.02.23.new/tcpdump.c Wed Feb 25 09:56:25 2004
@@ -129,7 +129,7 @@
static void print_packet(u_char *, const struct pcap_pkthdr *, const u_char *);
static void dump_packet_and_trunc(u_char *, const struct pcap_pkthdr *, const u_char
*);
static void dump_packet(u_char *, const struct pcap_pkthdr *, const u_char *);
-static void droproot(const char *);
+static void droproot(const char *, const char *);
#ifdef SIGINFO
RETSIGTYPE requestinfo(int);
@@ -324,15 +324,26 @@
#define U_FLAG
#endif
-/* Drop root privileges */
+/* Drop root privileges and chroot if necessary */
static void
-droproot(const char *username)
+droproot(const char *username, const char *chroot_dir)
{
struct passwd *pw = NULL;
+ if (chroot_dir && !username) {
+ fprintf(stderr, "Chroot without dropping root is insecure\n");
+ exit(1);
+ }
+
pw = getpwnam(username);
if (pw) {
- if (initgroups(pw->pw_name, 0) != 0 || setgid(pw->pw_gid) != 0 ||
+ if (chroot_dir) {
+ if (chroot(chroot_dir) != 0 || chdir ("/") != 0) {
+ fprintf(stderr, "Couldn't chroot/chdir to '%.64s'\n",
chroot_dir);
+ exit(1);
+ }
+ }
+ if (initgroups(pw->pw_name, pw->pw_gid) != 0 || setgid(pw->pw_gid) !=
0 ||
setuid(pw->pw_uid) != 0) {
fprintf(stderr, "Couldn't change to '%.32s' uid=%d gid=%d\n",
username,
pw->pw_uid, pw->pw_gid);
@@ -386,6 +397,7 @@
u_char *pcap_userdata;
char ebuf[PCAP_ERRBUF_SIZE];
char *username = NULL;
+ char *chroot_dir = NULL;
#ifdef HAVE_PCAP_FINDALLDEVS
pcap_if_t *devpointer;
int devnum;
@@ -704,6 +716,15 @@
if (tflag > 0)
thiszone = gmt2local(0);
+#ifdef WITH_CHROOT
+ /* if run as root, prepare for chrooting */
+ if (getuid() == 0 || geteuid() == 0) {
+ /* future extensibility for cmd-line arguments */
+ if (!chroot_dir)
+ chroot_dir = WITH_CHROOT;
+ }
+#endif
+
#ifdef WITH_USER
/* if run as root, prepare for dropping root privileges */
if (getuid() == 0 || geteuid() == 0) {
@@ -885,9 +906,8 @@
* We cannot do this earlier, because we want to be able to open
* the file (if done) for writing before giving up permissions.
*/
- if (username) {
- droproot(username);
- }
+ if (username || chroot_dir)
+ droproot(username, chroot_dir);
#endif /* WIN32 */
#ifdef SIGINFO
(void)setsignal(SIGINFO, requestinfo);