tcpdump mailing list archives

Re: chroot and setuid [Re: OpenBSD work on Tcpdump privilege separation]


From: Hannes Gredler <hannes () juniper net>
Date: Wed, 25 Feb 2004 15:20:24 +0100

checked in; - /hannes

On Wed, Feb 25, 2004 at 12:03:30PM +0200, Pekka Savola wrote:
| 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);

-
This is the TCPDUMP workers list. It is archived at
http://www.tcpdump.org/lists/workers/index.html
To unsubscribe use mailto:tcpdump-workers-request () tcpdump org?body=unsubscribe


Current thread: