On Sat, Jul 05, 2014 at 01:34:15PM -0700, Guy Harris wrote: > > On Jul 5, 2014, at 1:15 PM, Loganaden Velvindron <lo...@elandsys.com> wrote: > > > FreeBSD has designed capsicum which is a sandboxing mechanism. > > > > Please find below a patch against FreeBSD 10 Release: > > So this will compile on all versions of FreeBSD, correct? > > If not, please update the configure script to test for the relevant APIs, and > enable the new code only on systems with those APIs.
Thank you for your feeeback. Updated diff. Feedback welcomed. diff --git a/configure.in b/configure.in index c88f470..8488653 100644 --- a/configure.in +++ b/configure.in @@ -177,6 +177,16 @@ else AC_MSG_RESULT(no) fi +AC_ARG_WITH(sandbox-capsicum, [ --with-sandbox-capsicum ]) +AC_MSG_CHECKING([whether to sandbox using capsicum]) +if test ! -z "$with_sandbox-capsicum" && test "$with_sandbox-capsicum" != "no" ; then + AC_CHECK_FUNCS(cap_enter cap_rights_init cap_rights_limit cap_ioctls_limit openat, + AC_DEFINE(HAVE_CAPSICUM, 1, [capsicum support available])) + AC_MSG_RESULT(yes) +else + AC_MSG_RESULT(no) +fi + # # We must check this before checking whether to enable IPv6, because, # on some platforms (such as SunOS 5.x), the test program requires diff --git a/tcpdump.c b/tcpdump.c index 7db319a..40b930d 100644 --- a/tcpdump.c +++ b/tcpdump.c @@ -72,6 +72,13 @@ extern int SIZE_BUF; #include <stdlib.h> #include <string.h> #include <limits.h> +#ifdef HAVE_CAPSICUM +#include <sys/capability.h> +#include <sys/ioccom.h> +#include <net/bpf.h> +#include <fcntl.h> +#include <libgen.h> +#endif /* HAVE_CAPSICUM */ #ifndef WIN32 #include <sys/wait.h> #include <sys/resource.h> @@ -441,6 +448,9 @@ struct dump_info { char *CurrentFileName; pcap_t *pd; pcap_dumper_t *p; +#ifdef HAVE_CAPSICUM + int dirfd; +#endif }; #ifdef HAVE_PCAP_SET_TSTAMP_TYPE @@ -910,6 +920,11 @@ main(int argc, char **argv) #endif int status; FILE *VFile; +#ifdef HAVE_CAPSICUM + cap_rights_t rights; + int cansandbox; +#endif /* HAVE_CAPSICUM */ + #ifdef WIN32 if(wsockinit() != 0) return 1; #endif /* WIN32 */ @@ -1423,6 +1438,13 @@ main(int argc, char **argv) if (pd == NULL) error("%s", ebuf); +#ifdef HAVE_CAPSICUM + cap_rights_init(&rights, CAP_READ); + if (cap_rights_limit(fileno(pcap_file(pd)), &rights) < 0 && + errno != ENOSYS) { + error("unable to limit pcap descriptor"); + } +#endif dlt = pcap_datalink(pd); dlt_name = pcap_datalink_val_to_name(dlt); if (dlt_name == NULL) { @@ -1687,6 +1709,21 @@ main(int argc, char **argv) if (pcap_setfilter(pd, &fcode) < 0) error("%s", pcap_geterr(pd)); +#ifdef HAVE_CAPSICUM + if (RFileName == NULL && VFileName == NULL) { + static const unsigned long cmds[] = { BIOCGSTATS }; + + cap_rights_init(&rights, CAP_IOCTL, CAP_READ); + if (cap_rights_limit(pcap_fileno(pd), &rights) < 0 && + errno != ENOSYS) { + error("unable to limit pcap descriptor"); + } + if (cap_ioctls_limit(pcap_fileno(pd), cmds, + sizeof(cmds) / sizeof(cmds[0])) < 0 && errno != ENOSYS) { + error("unable to limit ioctls on pcap descriptor"); + } + } +#endif if (WFileName) { pcap_dumper_t *p; /* Do not exceed the default PATH_MAX for files. */ @@ -1708,9 +1745,32 @@ main(int argc, char **argv) #endif if (p == NULL) error("%s", pcap_geterr(pd)); +#ifdef HAVE_CAPSICUM + cap_rights_init(&rights, CAP_SEEK, CAP_WRITE); + if (cap_rights_limit(fileno(pcap_dump_file(p)), &rights) < 0 && + errno != ENOSYS) { + error("unable to limit dump descriptor"); + } +#endif if (Cflag != 0 || Gflag != 0) { - callback = dump_packet_and_trunc; +#ifdef HAVE_CAPSICUM + dumpinfo.WFileName = strdup(basename(WFileName)); + dumpinfo.dirfd = open(dirname(WFileName), + O_DIRECTORY | O_RDONLY); + if (dumpinfo.dirfd < 0) { + error("unable to open directory %s", + dirname(WFileName)); + } + cap_rights_init(&rights, CAP_CREATE, CAP_FCNTL, + CAP_FTRUNCATE, CAP_LOOKUP, CAP_SEEK, CAP_WRITE); + if (cap_rights_limit(dumpinfo.dirfd, &rights) < 0 && + errno != ENOSYS) { + error("unable to limit directory rights"); + } +#else /* !HAVE_CAPSICUM */ dumpinfo.WFileName = WFileName; +#endif + callback = dump_packet_and_trunc; dumpinfo.pd = pd; dumpinfo.p = p; pcap_userdata = (u_char *)&dumpinfo; @@ -1780,6 +1840,15 @@ main(int argc, char **argv) (void)fflush(stderr); } #endif /* WIN32 */ + +#ifdef HAVE_CAPSICUM + cansandbox = (nflag && VFileName == NULL && zflag == NULL); + if (cansandbox && cap_enter() < 0 && errno != ENOSYS) + error("unable to enter the capability mode"); + if (cap_sandboxed()) + fprintf(stderr, "capability mode sandbox enabled\n"); +#endif /* HAVE_CAPSICUM */ + do { status = pcap_loop(pd, cnt, callback, pcap_userdata); if (WFileName == NULL) { @@ -1827,6 +1896,13 @@ main(int argc, char **argv) pd = pcap_open_offline(RFileName, ebuf); if (pd == NULL) error("%s", ebuf); +#ifdef HAVE_CAPSICUM + cap_rights_init(&rights, CAP_READ); + if (cap_rights_limit(fileno(pcap_file(pd)), + &rights) < 0 && errno != ENOSYS) { + error("unable to limit pcap descriptor"); + } +#endif new_dlt = pcap_datalink(pd); if (WFileName && new_dlt != dlt) error("%s: new dlt does not match original", RFileName); @@ -1995,6 +2071,9 @@ static void dump_packet_and_trunc(u_char *user, const struct pcap_pkthdr *h, const u_char *sp) { struct dump_info *dump_info; +#ifdef HAVE_CAPSICUM + cap_rights_t rights; +#endif ++packets_captured; @@ -2023,6 +2102,11 @@ dump_packet_and_trunc(u_char *user, const struct pcap_pkthdr *h, const u_char *s /* If the time is greater than the specified window, rotate */ if (t - Gflag_time >= Gflag) { +#ifdef HAVE_CAPSICUM + FILE *fp; + int fd; +#endif + /* Update the Gflag_time */ Gflag_time = t; /* Update Gflag_count */ @@ -2076,13 +2160,36 @@ dump_packet_and_trunc(u_char *user, const struct pcap_pkthdr *h, const u_char *s capng_update(CAPNG_ADD, CAPNG_EFFECTIVE, CAP_DAC_OVERRIDE); capng_apply(CAPNG_EFFECTIVE); #endif /* HAVE_CAP_NG_H */ +#ifdef HAVE_CAPSICUM + fd = openat(dump_info->dirfd, + dump_info->CurrentFileName, + O_CREAT | O_WRONLY | O_TRUNC, 0644); + if (fd < 0) { + error("unable to open file %s", + dump_info->CurrentFileName); + } + fp = fdopen(fd, "w"); + if (fp == NULL) { + error("unable to fdopen file %s", + dump_info->CurrentFileName); + } + dump_info->p = pcap_dump_fopen(dump_info->pd, fp); +#else /* !HAVE_CAPSICUM */ dump_info->p = pcap_dump_open(dump_info->pd, dump_info->CurrentFileName); +#endif #ifdef HAVE_CAP_NG_H capng_update(CAPNG_DROP, CAPNG_EFFECTIVE, CAP_DAC_OVERRIDE); capng_apply(CAPNG_EFFECTIVE); #endif /* HAVE_CAP_NG_H */ if (dump_info->p == NULL) error("%s", pcap_geterr(pd)); +#ifdef HAVE_CAPSICUM + cap_rights_init(&rights, CAP_SEEK, CAP_WRITE); + if (cap_rights_limit(fileno(pcap_dump_file(dump_info->p)), + &rights) < 0 && errno != ENOSYS) { + error("unable to limit dump descriptor"); + } +#endif } } @@ -2092,6 +2199,11 @@ dump_packet_and_trunc(u_char *user, const struct pcap_pkthdr *h, const u_char *s * file could put it over Cflag. */ if (Cflag != 0 && pcap_dump_ftell(dump_info->p) > Cflag) { +#ifdef HAVE_CAPSICUM + FILE *fp; + int fd; +#endif + /* * Close the current file and open a new one. */ @@ -2114,9 +2226,31 @@ dump_packet_and_trunc(u_char *user, const struct pcap_pkthdr *h, const u_char *s if (dump_info->CurrentFileName == NULL) error("dump_packet_and_trunc: malloc"); MakeFilename(dump_info->CurrentFileName, dump_info->WFileName, Cflag_count, WflagChars); +#ifdef HAVE_CAPSICUM + fd = openat(dump_info->dirfd, dump_info->CurrentFileName, + O_CREAT | O_WRONLY | O_TRUNC, 0644); + if (fd < 0) { + error("unable to open file %s", + dump_info->CurrentFileName); + } + fp = fdopen(fd, "w"); + if (fp == NULL) { + error("unable to fdopen file %s", + dump_info->CurrentFileName); + } + dump_info->p = pcap_dump_fopen(dump_info->pd, fp); +#else /* !HAVE_CAPSICUM */ dump_info->p = pcap_dump_open(dump_info->pd, dump_info->CurrentFileName); +#endif if (dump_info->p == NULL) error("%s", pcap_geterr(pd)); +#ifdef HAVE_CAPSICUM + cap_rights_init(&rights, CAP_SEEK, CAP_WRITE); + if (cap_rights_limit(fileno(pcap_dump_file(dump_info->p)), + &rights) < 0 && errno != ENOSYS) { + error("unable to limit dump descriptor"); + } +#endif } pcap_dump((u_char *)dump_info->p, h, sp); _______________________________________________ tcpdump-workers mailing list tcpdump-workers@lists.tcpdump.org https://lists.sandelman.ca/mailman/listinfo/tcpdump-workers