]> The Tcpdump Group git mirrors - tcpdump/blobdiff - tcpdump.c
add CAP_EVENT for the libpcap device
[tcpdump] / tcpdump.c
index acf62c8a7846e8571cf96346db300bb606b20f5b..e26fbafdd7013dde2b494cbd815d644eb6ccd570 100644 (file)
--- a/tcpdump.c
+++ b/tcpdump.c
@@ -188,7 +188,7 @@ static RETSIGTYPE child_cleanup(int);
 static void print_version(void);
 static void print_usage(void);
 static void show_tstamp_types_and_exit(pcap_t *, const char *device) __attribute__((noreturn));
-static void show_dlts_and_exit(const char *device) __attribute__((noreturn));
+static void show_dlts_and_exit(pcap_t *, const char *device) __attribute__((noreturn));
 #ifdef HAVE_PCAP_FINDALLDEVS
 static void show_devices_and_exit (void) __attribute__((noreturn));
 #endif
@@ -373,15 +373,15 @@ show_tstamp_types_and_exit(pcap_t *pc, const char *device)
 #endif
 
 static void
-show_dlts_and_exit(const char *device)
+show_dlts_and_exit(pcap_t *pc, const char *device)
 {
        int n_dlts, i;
        int *dlts = 0;
        const char *dlt_name;
 
-       n_dlts = pcap_list_datalinks(pd, &dlts);
+       n_dlts = pcap_list_datalinks(pc, &dlts);
        if (n_dlts < 0)
-               error("%s", pcap_geterr(pd));
+               error("%s", pcap_geterr(pc));
        else if (n_dlts == 0 || !dlts)
                error("No data link types.");
 
@@ -458,7 +458,7 @@ show_devices_and_exit (void)
  * OS X tcpdump uses -g to force non--v output for IP to be on one
  * line, making it more "g"repable;
  *
- * OS X tcpdump uses -k tospecify that packet comments in pcap-ng files
+ * OS X tcpdump uses -k to specify that packet comments in pcap-ng files
  * should be printed;
  *
  * OpenBSD tcpdump uses -o to indicate that OS fingerprinting should be done
@@ -643,12 +643,13 @@ droproot(const char *username, const char *chroot_dir)
                exit_tcpdump(1);
        }
 #ifdef HAVE_LIBCAP_NG
-       /* We don't need CAP_SETUID and CAP_SETGID any more. */
+       /* We don't need CAP_SETUID, CAP_SETGID and CAP_SYS_CHROOT any more. */
        capng_updatev(
                CAPNG_DROP,
                CAPNG_EFFECTIVE | CAPNG_PERMITTED,
                CAP_SETUID,
                CAP_SETGID,
+               CAP_SYS_CHROOT,
                -1);
        capng_apply(CAPNG_SELECT_BOTH);
 #endif /* HAVE_LIBCAP_NG */
@@ -1729,7 +1730,7 @@ main(int argc, char **argv)
                        }
 #endif /* !defined(HAVE_PCAP_CREATE) && defined(_WIN32) */
                if (Lflag)
-                       show_dlts_and_exit(device);
+                       show_dlts_and_exit(pd, device);
                if (yflag_dlt >= 0) {
 #ifdef HAVE_PCAP_SET_DATALINK
                        if (pcap_set_datalink(pd, yflag_dlt) < 0)
@@ -1825,6 +1826,13 @@ main(int argc, char **argv)
                                CAP_SETGID,
                                -1);
                }
+               if (chroot_dir) {
+                       capng_update(
+                               CAPNG_ADD,
+                               CAPNG_PERMITTED | CAPNG_EFFECTIVE,
+                               CAP_SYS_CHROOT
+                               );
+               }
 
                if (WFileName) {
                        capng_update(
@@ -1847,7 +1855,12 @@ main(int argc, char **argv)
        if (RFileName == NULL && VFileName == NULL) {
                static const unsigned long cmds[] = { BIOCGSTATS, BIOCROTZBUF };
 
-               cap_rights_init(&rights, CAP_IOCTL, CAP_READ);
+               /*
+                * The various libpcap devices use a combination of
+                * read (bpf), ioctl (bpf, netmap), poll (netmap)
+                * so we add the relevant access rights.
+                */
+               cap_rights_init(&rights, CAP_IOCTL, CAP_READ, CAP_EVENT);
                if (cap_rights_limit(pcap_fileno(pd), &rights) < 0 &&
                    errno != ENOSYS) {
                        error("unable to limit pcap descriptor");
@@ -2322,6 +2335,7 @@ dump_packet_and_trunc(u_char *user, const struct pcap_pkthdr *h, const u_char *s
                        if (Cflag == 0 && Wflag > 0 && Gflag_count >= Wflag) {
                                (void)fprintf(stderr, "Maximum file limit reached: %d\n",
                                    Wflag);
+                               info(1);
                                exit_tcpdump(0);
                                /* NOTREACHED */
                        }