diff -Nru sysdig-0.16.0/debian/changelog sysdig-0.17.0/debian/changelog --- sysdig-0.16.0/debian/changelog 2017-06-27 08:56:38.000000000 +0000 +++ sysdig-0.17.0/debian/changelog 2017-08-08 01:17:05.000000000 +0000 @@ -1,10 +1,9 @@ -sysdig (0.16.0-1ubuntu1) artful; urgency=medium +sysdig (0.17.0-1) unstable; urgency=medium - * Fix parsing of cgroups with empty subsys field (LP: #1700014) - - Upstream commit 2044108ef1f863 to fix cgroups parsing for - 4.12 cgroups subsys field + * New upstream version 0.17.0 + * Update priority to optional for Policy v4.0. - -- Colin Ian King Tue, 27 Jun 2017 09:57:11 +0100 + -- Harlan Lieberman-Berg Mon, 07 Aug 2017 21:17:05 -0400 sysdig (0.16.0-1) unstable; urgency=medium diff -Nru sysdig-0.16.0/debian/control sysdig-0.17.0/debian/control --- sysdig-0.16.0/debian/control 2017-06-27 08:57:11.000000000 +0000 +++ sysdig-0.17.0/debian/control 2017-08-08 01:12:19.000000000 +0000 @@ -1,8 +1,7 @@ Source: sysdig Section: admin -Priority: extra -Maintainer: Ubuntu Developers -XSBC-Original-Maintainer: Evgeni Golov +Priority: optional +Maintainer: Evgeni Golov Uploaders: Harlan Lieberman-Berg Build-Depends: cmake, debhelper (>= 9.20120417~), @@ -16,7 +15,7 @@ pandoc (>= 1.11), zlib1g-dev Build-Depends-Indep: dkms -Standards-Version: 3.9.8 +Standards-Version: 4.0.0 Homepage: http://www.sysdig.org/ Vcs-Git: https://anonscm.debian.org/git/collab-maint/sysdig.git Vcs-Browser: https://anonscm.debian.org/cgit/collab-maint/sysdig.git diff -Nru sysdig-0.16.0/debian/patches/0001-Fix-parsing-of-cgroups-with-empty-subsys.patch sysdig-0.17.0/debian/patches/0001-Fix-parsing-of-cgroups-with-empty-subsys.patch --- sysdig-0.16.0/debian/patches/0001-Fix-parsing-of-cgroups-with-empty-subsys.patch 2017-06-27 08:20:54.000000000 +0000 +++ sysdig-0.17.0/debian/patches/0001-Fix-parsing-of-cgroups-with-empty-subsys.patch 1970-01-01 00:00:00.000000000 +0000 @@ -1,33 +0,0 @@ -From 2044108ef1f863f77735aa05ccd930ed462aa09c Mon Sep 17 00:00:00 2001 -From: Luca Marturana -Date: Mon, 15 May 2017 16:42:49 +0200 -Subject: [PATCH] Fix parsing of cgroups with empty subsys - ---- - userspace/libscap/scap_procs.c | 10 ++++++++++ - 1 file changed, 10 insertions(+) - -diff --git a/userspace/libscap/scap_procs.c b/userspace/libscap/scap_procs.c -index 0f36157b..3c2ef81c 100644 ---- a/userspace/libscap/scap_procs.c -+++ b/userspace/libscap/scap_procs.c -@@ -329,6 +329,16 @@ int32_t scap_proc_fill_cgroups(struct scap_threadinfo* tinfo, const char* procdi - return SCAP_FAILURE; - } - -+ // Hack to detect empty fields, because strtok does not support it -+ // strsep() should be used to fix this but it's not available -+ // on CentOS 6 (has been added from Glibc 2.19) -+ if(subsys_list-token-strlen(token) > 1) -+ { -+ // skip cgroups like this: -+ // 0::/init.scope -+ continue; -+ } -+ - // transient cgroup - if(strncmp(subsys_list, "name=", sizeof("name=") - 1) == 0) - { --- -2.11.0 - diff -Nru sysdig-0.16.0/debian/patches/series sysdig-0.17.0/debian/patches/series --- sysdig-0.16.0/debian/patches/series 2017-06-27 08:21:00.000000000 +0000 +++ sysdig-0.17.0/debian/patches/series 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -0001-Fix-parsing-of-cgroups-with-empty-subsys.patch diff -Nru sysdig-0.16.0/docker/dev/Dockerfile sysdig-0.17.0/docker/dev/Dockerfile --- sysdig-0.16.0/docker/dev/Dockerfile 2017-05-08 09:30:22.000000000 +0000 +++ sysdig-0.17.0/docker/dev/Dockerfile 2017-07-24 16:13:14.000000000 +0000 @@ -24,7 +24,10 @@ gcc \ gcc-5 \ gcc-4.9 \ - libelf1 less && rm -rf /var/lib/apt/lists/* + libelf1 \ + less \ + procps \ + && rm -rf /var/lib/apt/lists/* # Since our base Debian image ships with GCC 5.0 which breaks older kernels, revert the # default to gcc-4.9. Also, since some customers use some very old distributions whose kernel diff -Nru sysdig-0.16.0/docker/local/Dockerfile sysdig-0.17.0/docker/local/Dockerfile --- sysdig-0.16.0/docker/local/Dockerfile 2017-05-08 09:30:22.000000000 +0000 +++ sysdig-0.17.0/docker/local/Dockerfile 2017-07-24 16:13:14.000000000 +0000 @@ -19,6 +19,7 @@ && apt-get install -y --no-install-recommends \ bash-completion \ curl \ + dkms \ gnupg2 \ ca-certificates \ gcc \ @@ -26,7 +27,8 @@ gcc-4.9 \ libelf1 \ less \ - dkms && rm -rf /var/lib/apt/lists/* + procps \ + && rm -rf /var/lib/apt/lists/* # Since our base Debian image ships with GCC 5.0 which breaks older kernels, revert the # default to gcc-4.9. Also, since some customers use some very old distributions whose kernel diff -Nru sysdig-0.16.0/docker/stable/Dockerfile sysdig-0.17.0/docker/stable/Dockerfile --- sysdig-0.16.0/docker/stable/Dockerfile 2017-05-08 09:30:22.000000000 +0000 +++ sysdig-0.17.0/docker/stable/Dockerfile 2017-07-24 16:13:14.000000000 +0000 @@ -24,7 +24,10 @@ gcc \ gcc-5 \ gcc-4.9 \ - libelf1 less && rm -rf /var/lib/apt/lists/* + libelf1 \ + less \ + procps \ + && rm -rf /var/lib/apt/lists/* # Since our base Debian image ships with GCC 5.0 which breaks older kernels, revert the # default to gcc-4.9. Also, since some customers use some very old distributions whose kernel diff -Nru sysdig-0.16.0/driver/event_table.c sysdig-0.17.0/driver/event_table.c --- sysdig-0.16.0/driver/event_table.c 2017-05-08 09:30:22.000000000 +0000 +++ sysdig-0.17.0/driver/event_table.c 2017-07-24 16:13:14.000000000 +0000 @@ -23,7 +23,7 @@ /* PPME_GENERIC_E */{"syscall", EC_OTHER, EF_NONE, 2, {{"ID", PT_SYSCALLID, PF_DEC}, {"nativeID", PT_UINT16, PF_DEC} } }, /* PPME_GENERIC_X */{"syscall", EC_OTHER, EF_NONE, 1, {{"ID", PT_SYSCALLID, PF_DEC} } }, /* PPME_SYSCALL_OPEN_E */{"open", EC_FILE, EF_CREATES_FD | EF_MODIFIES_STATE, 0}, - /* PPME_SYSCALL_OPEN_X */{"open", EC_FILE, EF_CREATES_FD | EF_MODIFIES_STATE, 4, {{"fd", PT_FD, PF_DEC}, {"name", PT_FSPATH, PF_NA}, {"flags", PT_FLAGS32, PF_HEX, file_flags}, {"mode", PT_UINT32, PF_HEX} } }, + /* PPME_SYSCALL_OPEN_X */{"open", EC_FILE, EF_CREATES_FD | EF_MODIFIES_STATE, 4, {{"fd", PT_FD, PF_DEC}, {"name", PT_FSPATH, PF_NA}, {"flags", PT_FLAGS32, PF_HEX, file_flags}, {"mode", PT_UINT32, PF_OCT} } }, /* PPME_SYSCALL_CLOSE_E */{"close", EC_IO_OTHER, EF_DESTROYS_FD | EF_USES_FD | EF_MODIFIES_STATE | EF_DROP_FALCO, 1, {{"fd", PT_FD, PF_DEC} } }, /* PPME_SYSCALL_CLOSE_X */{"close", EC_IO_OTHER, EF_DESTROYS_FD | EF_USES_FD | EF_MODIFIES_STATE | EF_DROP_FALCO, 1, {{"res", PT_ERRNO, PF_DEC} } }, /* PPME_SYSCALL_READ_E */{"read", EC_IO_READ, EF_USES_FD | EF_READS_FROM_FD | EF_DROP_FALCO, 2, {{"fd", PT_FD, PF_DEC}, {"size", PT_UINT32, PF_DEC} } }, @@ -124,7 +124,7 @@ /* PPME_SYSCALL_MKDIR_X */{"mkdir", EC_FILE, EF_NONE, 1, {{"res", PT_ERRNO, PF_DEC} } }, /* PPME_SYSCALL_RMDIR_E */{"rmdir", EC_FILE, EF_NONE, 1, {{"path", PT_FSPATH, PF_NA} } }, /* PPME_SYSCALL_RMDIR_X */{"rmdir", EC_FILE, EF_NONE, 1, {{"res", PT_ERRNO, PF_DEC} } }, - /* PPME_SYSCALL_OPENAT_E */{"openat", EC_FILE, EF_CREATES_FD | EF_MODIFIES_STATE, 4, {{"dirfd", PT_FD, PF_DEC}, {"name", PT_CHARBUF, PF_NA}, {"flags", PT_FLAGS32, PF_HEX, file_flags}, {"mode", PT_UINT32, PF_HEX} } }, + /* PPME_SYSCALL_OPENAT_E */{"openat", EC_FILE, EF_CREATES_FD | EF_MODIFIES_STATE, 4, {{"dirfd", PT_FD, PF_DEC}, {"name", PT_CHARBUF, PF_NA}, {"flags", PT_FLAGS32, PF_HEX, file_flags}, {"mode", PT_UINT32, PF_OCT} } }, /* PPME_SYSCALL_OPENAT_X */{"openat", EC_FILE, EF_CREATES_FD | EF_MODIFIES_STATE, 1, {{"fd", PT_FD, PF_DEC} } }, /* PPME_SYSCALL_LINK_E */{"link", EC_FILE, EF_NONE, 2, {{"oldpath", PT_FSPATH, PF_NA}, {"newpath", PT_FSPATH, PF_NA} } }, /* PPME_SYSCALL_LINK_X */{"link", EC_FILE, EF_NONE, 1, {{"res", PT_ERRNO, PF_DEC} } }, diff -Nru sysdig-0.16.0/driver/flags_table.c sysdig-0.17.0/driver/flags_table.c --- sysdig-0.16.0/driver/flags_table.c 2017-05-08 09:30:22.000000000 +0000 +++ sysdig-0.17.0/driver/flags_table.c 2017-07-24 16:13:14.000000000 +0000 @@ -252,6 +252,9 @@ {"F_SETFD", PPM_FCNTL_F_SETFD}, {"F_GETFD", PPM_FCNTL_F_GETFD}, {"F_DUPFD", PPM_FCNTL_F_DUPFD}, + {"F_OFD_GETLK", PPM_FCNTL_F_OFD_GETLK}, + {"F_OFD_SETLK", PPM_FCNTL_F_OFD_SETLK}, + {"F_OFD_SETLKW", PPM_FCNTL_F_OFD_SETLKW}, {"UNKNOWN", PPM_FCNTL_UNKNOWN}, { }, }; diff -Nru sysdig-0.16.0/driver/main.c sysdig-0.17.0/driver/main.c --- sysdig-0.16.0/driver/main.c 2017-05-08 09:30:22.000000000 +0000 +++ sysdig-0.17.0/driver/main.c 2017-07-24 16:13:14.000000000 +0000 @@ -49,6 +49,11 @@ #include #include #include +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 26)) +#include +#else +#include +#endif #include #include /* For NR_syscalls */ #include @@ -1275,8 +1280,53 @@ } } -static inline int drop_event(struct ppm_consumer_t *consumer, enum ppm_event_type event_type, enum syscall_flags drop_flags, struct timespec *ts) +static inline int drop_event(struct ppm_consumer_t *consumer, + enum ppm_event_type event_type, + enum syscall_flags drop_flags, + struct timespec *ts, + struct pt_regs *regs) { + unsigned long close_arg = 0; + int close_fd = -1; + struct files_struct *files; + struct fdtable *fdt; + bool close_return = false; + + /* + * It's annoying but valid for a program to make a large number of + * close() calls on nonexistent fds. That can cause driver cpu usage + * to spike dramatically, so drop close events if the fd is not valid. + * + * The invalid fd events don't matter to userspace in dropping mode, + * so we do this before the UF_NEVER_DROP check + */ + if (consumer->dropping_mode) { + if (event_type == PPME_SYSCALL_CLOSE_X) { + if (syscall_get_return_value(current, regs) < 0) + close_return = true; + } else if (event_type == PPME_SYSCALL_CLOSE_E) { + syscall_get_arguments(current, regs, 0, 1, &close_arg); + close_fd = (int)close_arg; + + files = current->files; + spin_lock(&files->file_lock); + fdt = files_fdtable(files); + if (close_fd < 0 || close_fd >= fdt->max_fds || +#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 4, 0)) + !FD_ISSET(close_fd, fdt->open_fds) +#else + !fd_is_open(close_fd, fdt) +#endif + ) { + close_return = true; + } + spin_unlock(&files->file_lock); + } + + if (close_return) + return 1; + } + if (drop_flags & UF_NEVER_DROP) { ASSERT((drop_flags & UF_ALWAYS_DROP) == 0); return 0; @@ -1355,7 +1405,8 @@ else if (consumer->need_to_insert_drop_x == 1) record_drop_x(consumer, ts); - if (drop_event(consumer, event_type, drop_flags, ts)) + if (drop_event(consumer, event_type, drop_flags, ts, + event_datap->event_info.syscall_data.regs)) return res; } diff -Nru sysdig-0.16.0/driver/ppm_events_public.h sysdig-0.17.0/driver/ppm_events_public.h --- sysdig-0.16.0/driver/ppm_events_public.h 2017-05-08 09:30:22.000000000 +0000 +++ sysdig-0.17.0/driver/ppm_events_public.h 2017-07-24 16:13:14.000000000 +0000 @@ -86,18 +86,35 @@ #define PPM_O_WRONLY (1 << 1) /* Open for writing only */ #define PPM_O_RDWR (PPM_O_RDONLY | PPM_O_WRONLY) /* Open for reading and writing */ #define PPM_O_CREAT (1 << 2) /* Create a new file if it doesn't exist. */ -#define PPM_O_APPEND (1 << 3) /* If set, the file offset shall be set to the end of the file prior to each write. */ +#define PPM_O_APPEND (1 << 3) /* If set, the file offset shall be set to the end of the file prior to each write. */ #define PPM_O_DSYNC (1 << 4) #define PPM_O_EXCL (1 << 5) #define PPM_O_NONBLOCK (1 << 6) #define PPM_O_SYNC (1 << 7) #define PPM_O_TRUNC (1 << 8) -#define PPM_O_DIRECT (1 << 9) +#define PPM_O_DIRECT (1 << 9) #define PPM_O_DIRECTORY (1 << 10) #define PPM_O_LARGEFILE (1 << 11) #define PPM_O_CLOEXEC (1 << 12) /* + * File modes + */ +#define PPM_S_NONE 0 +#define PPM_S_IXOTH (1 << 0) +#define PPM_S_IWOTH (1 << 1) +#define PPM_S_IROTH (1 << 2) +#define PPM_S_IXGRP (1 << 3) +#define PPM_S_IWGRP (1 << 4) +#define PPM_S_IRGRP (1 << 5) +#define PPM_S_IXUSR (1 << 6) +#define PPM_S_IWUSR (1 << 7) +#define PPM_S_IRUSR (1 << 8) +#define PPM_S_ISVTX (1 << 9) +#define PPM_S_ISGID (1 << 10) +#define PPM_S_ISUID (1 << 11) + +/* * flock() flags */ #define PPM_LOCK_NONE 0 @@ -285,6 +302,9 @@ #define PPM_FCNTL_F_NOTIFY 27 #define PPM_FCNTL_F_SETPIPE_SZ 28 #define PPM_FCNTL_F_GETPIPE_SZ 29 +#define PPM_FCNTL_F_OFD_GETLK 30 +#define PPM_FCNTL_F_OFD_SETLK 31 +#define PPM_FCNTL_F_OFD_SETLKW 32 /* * ptrace requests @@ -1194,10 +1214,11 @@ enum ppm_print_format { PF_NA = 0, PF_DEC = 1, /* decimal */ - PF_HEX = 2, /* hexadecima */ + PF_HEX = 2, /* hexadecimal */ PF_10_PADDED_DEC = 3, /* decimal padded to 10 digits, useful to print the fractional part of a ns timestamp */ PF_ID = 4, PF_DIR = 5, + PF_OCT = 6, /* octal */ }; /*! diff -Nru sysdig-0.16.0/driver/ppm_fillers.c sysdig-0.17.0/driver/ppm_fillers.c --- sysdig-0.16.0/driver/ppm_fillers.c 2017-05-08 09:30:22.000000000 +0000 +++ sysdig-0.17.0/driver/ppm_fillers.c 2017-07-24 16:13:14.000000000 +0000 @@ -524,9 +524,92 @@ return res; } + +static inline u32 open_modes_to_scap(unsigned long modes) +{ + u32 res = 0; + + if (modes & S_IRUSR) + res |= PPM_S_IRUSR; + + if (modes & S_IWUSR) + res |= PPM_S_IWUSR; + + if (modes & S_IXUSR) + res |= PPM_S_IXUSR; + + /* + * PPM_S_IRWXU == S_IRUSR | S_IWUSR | S_IXUSR + */ + + if (modes & S_IRGRP) + res |= PPM_S_IRGRP; + + if (modes & S_IWGRP) + res |= PPM_S_IWGRP; + + if (modes & S_IXGRP) + res |= PPM_S_IXGRP; + + /* + * PPM_S_IRWXG == S_IRGRP | S_IWGRP | S_IXGRP + */ + + if (modes & S_IROTH) + res |= PPM_S_IROTH; + + if (modes & S_IWOTH) + res |= PPM_S_IWOTH; + + if (modes & S_IXOTH) + res |= PPM_S_IXOTH; + + /* + * PPM_S_IRWXO == S_IROTH | S_IWOTH | S_IXOTH + */ + + if (modes & S_ISUID) + res |= PPM_S_ISUID; + + if (modes & S_ISGID) + res |= PPM_S_ISGID; + + if (modes & S_ISVTX) + res |= PPM_S_ISVTX; + + return res; +} + +static inline int open_mode_to_ring(struct event_filler_arguments *args, + unsigned long flags, + unsigned int i) +{ +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0) + unsigned long flags_mask = O_CREAT | O_TMPFILE; +#else + unsigned long flags_mask = O_CREAT; +#endif + int res; + + if (flags & flags_mask) { + unsigned long val; + + /* + * Mode + * Note that we convert them into the ppm portable + * representation before pushing them to the ring + */ + syscall_get_arguments(current, args->regs, i, 1, &val); + res = val_to_ring(args, open_modes_to_scap(val), 0, false, 0); + } else { + res = val_to_ring(args, 0, 0, false, 0); + } + return res; +} + static int f_sys_open_x(struct event_filler_arguments *args) { - unsigned long val; + unsigned long val, flags; int res; int64_t retval; @@ -550,19 +633,15 @@ * Flags * Note that we convert them into the ppm portable representation before pushing them to the ring */ - syscall_get_arguments(current, args->regs, 1, 1, &val); - res = val_to_ring(args, open_flags_to_scap(val), 0, false, 0); + syscall_get_arguments(current, args->regs, 1, 1, &flags); + res = val_to_ring(args, open_flags_to_scap(flags), 0, false, 0); if (unlikely(res != PPM_SUCCESS)) return res; /* - * Mode - * XXX: at this time, mode decoding is not supported. We nonetheless return a value (zero) - * so the format of the event is ready for when we'll export the mode in the future. - * - * syscall_get_arguments(current, args->regs, 2, 1, &val); + * mode */ - res = val_to_ring(args, 0, 0, false, 0); + res = open_mode_to_ring(args, flags, 2); if (unlikely(res != PPM_SUCCESS)) return res; @@ -3029,7 +3108,7 @@ static int f_sys_openat_e(struct event_filler_arguments *args) { - unsigned long val; + unsigned long val, flags; int res; /* @@ -3056,19 +3135,15 @@ * Flags * Note that we convert them into the ppm portable representation before pushing them to the ring */ - syscall_get_arguments(current, args->regs, 2, 1, &val); - res = val_to_ring(args, open_flags_to_scap(val), 0, false, 0); + syscall_get_arguments(current, args->regs, 2, 1, &flags); + res = val_to_ring(args, open_flags_to_scap(flags), 0, false, 0); if (unlikely(res != PPM_SUCCESS)) return res; /* - * Mode - * XXX: at this time, mode decoding is not supported. We nonetheless return a value (zero) - * so the format of the event is ready for when we'll export the mode in the future. - * - * syscall_get_arguments(current, args->regs, 3, 1, &val); + * mode */ - res = val_to_ring(args, 0, 0, false, 0); + res = open_mode_to_ring(args, flags, 3); if (unlikely(res != PPM_SUCCESS)) return res; @@ -3906,6 +3981,18 @@ case F_GETPIPE_SZ: return PPM_FCNTL_F_GETPIPE_SZ; #endif +#ifdef F_OFD_GETLK + case F_OFD_GETLK: + return PPM_FCNTL_F_OFD_GETLK; +#endif +#ifdef F_OFD_SETLK + case F_OFD_SETLK: + return PPM_FCNTL_F_OFD_SETLK; +#endif +#ifdef F_OFD_SETLKW + case F_OFD_SETLKW: + return PPM_FCNTL_F_OFD_SETLKW; +#endif default: ASSERT(false); return PPM_FCNTL_UNKNOWN; diff -Nru sysdig-0.16.0/.gitignore sysdig-0.17.0/.gitignore --- sysdig-0.16.0/.gitignore 2017-05-08 09:30:22.000000000 +0000 +++ sysdig-0.17.0/.gitignore 2017-07-24 16:13:14.000000000 +0000 @@ -11,3 +11,4 @@ build/ driver/Makefile driver/driver_config.h +*.pyc diff -Nru sysdig-0.16.0/test/sysdig_batch_parser.sh sysdig-0.17.0/test/sysdig_batch_parser.sh --- sysdig-0.16.0/test/sysdig_batch_parser.sh 2017-05-08 09:30:22.000000000 +0000 +++ sysdig-0.17.0/test/sysdig_batch_parser.sh 2017-07-24 16:13:14.000000000 +0000 @@ -54,7 +54,7 @@ echo "Corresponding reference file $ref does not exist--skipping" else echo "Processing $f" - TZ=UTC eval ${TIMEOUT_BIN} 60 $SYSDIG -N -r $f $ARGS > $DIRNAME/$(basename $f).output + TZ=UTC eval ${TIMEOUT_BIN} 60 $SYSDIG -r $f $ARGS > $DIRNAME/$(basename $f).output fi done diff -Nru sysdig-0.16.0/.travis.yml sysdig-0.17.0/.travis.yml --- sysdig-0.16.0/.travis.yml 2017-05-08 09:30:22.000000000 +0000 +++ sysdig-0.17.0/.travis.yml 2017-07-24 16:13:14.000000000 +0000 @@ -5,12 +5,15 @@ env: - BUILD_TYPE=Debug - BUILD_TYPE=Release +sudo: required +services: + - docker before_install: - .travis-scripts/${TRAVIS_OS_NAME}/before_install.sh install: - .travis-scripts/${TRAVIS_OS_NAME}/install.sh before_script: - - export KERNELDIR=/lib/modules/$(ls /lib/modules | sort | head -1)/build + - export KERNELDIR=/lib/modules/$(uname -r)/build script: - .travis-scripts/${TRAVIS_OS_NAME}/build.sh notifications: diff -Nru sysdig-0.16.0/userspace/libscap/event_table.c sysdig-0.17.0/userspace/libscap/event_table.c --- sysdig-0.16.0/userspace/libscap/event_table.c 2017-05-08 09:30:22.000000000 +0000 +++ sysdig-0.17.0/userspace/libscap/event_table.c 2017-07-24 16:13:14.000000000 +0000 @@ -23,7 +23,7 @@ /* PPME_GENERIC_E */{"syscall", EC_OTHER, EF_NONE, 2, {{"ID", PT_SYSCALLID, PF_DEC}, {"nativeID", PT_UINT16, PF_DEC} } }, /* PPME_GENERIC_X */{"syscall", EC_OTHER, EF_NONE, 1, {{"ID", PT_SYSCALLID, PF_DEC} } }, /* PPME_SYSCALL_OPEN_E */{"open", EC_FILE, EF_CREATES_FD | EF_MODIFIES_STATE, 0}, - /* PPME_SYSCALL_OPEN_X */{"open", EC_FILE, EF_CREATES_FD | EF_MODIFIES_STATE, 4, {{"fd", PT_FD, PF_DEC}, {"name", PT_FSPATH, PF_NA}, {"flags", PT_FLAGS32, PF_HEX, file_flags}, {"mode", PT_UINT32, PF_HEX} } }, + /* PPME_SYSCALL_OPEN_X */{"open", EC_FILE, EF_CREATES_FD | EF_MODIFIES_STATE, 4, {{"fd", PT_FD, PF_DEC}, {"name", PT_FSPATH, PF_NA}, {"flags", PT_FLAGS32, PF_HEX, file_flags}, {"mode", PT_UINT32, PF_OCT} } }, /* PPME_SYSCALL_CLOSE_E */{"close", EC_IO_OTHER, EF_DESTROYS_FD | EF_USES_FD | EF_MODIFIES_STATE | EF_DROP_FALCO, 1, {{"fd", PT_FD, PF_DEC} } }, /* PPME_SYSCALL_CLOSE_X */{"close", EC_IO_OTHER, EF_DESTROYS_FD | EF_USES_FD | EF_MODIFIES_STATE | EF_DROP_FALCO, 1, {{"res", PT_ERRNO, PF_DEC} } }, /* PPME_SYSCALL_READ_E */{"read", EC_IO_READ, EF_USES_FD | EF_READS_FROM_FD | EF_DROP_FALCO, 2, {{"fd", PT_FD, PF_DEC}, {"size", PT_UINT32, PF_DEC} } }, @@ -124,7 +124,7 @@ /* PPME_SYSCALL_MKDIR_X */{"mkdir", EC_FILE, EF_NONE, 1, {{"res", PT_ERRNO, PF_DEC} } }, /* PPME_SYSCALL_RMDIR_E */{"rmdir", EC_FILE, EF_NONE, 1, {{"path", PT_FSPATH, PF_NA} } }, /* PPME_SYSCALL_RMDIR_X */{"rmdir", EC_FILE, EF_NONE, 1, {{"res", PT_ERRNO, PF_DEC} } }, - /* PPME_SYSCALL_OPENAT_E */{"openat", EC_FILE, EF_CREATES_FD | EF_MODIFIES_STATE, 4, {{"dirfd", PT_FD, PF_DEC}, {"name", PT_CHARBUF, PF_NA}, {"flags", PT_FLAGS32, PF_HEX, file_flags}, {"mode", PT_UINT32, PF_HEX} } }, + /* PPME_SYSCALL_OPENAT_E */{"openat", EC_FILE, EF_CREATES_FD | EF_MODIFIES_STATE, 4, {{"dirfd", PT_FD, PF_DEC}, {"name", PT_CHARBUF, PF_NA}, {"flags", PT_FLAGS32, PF_HEX, file_flags}, {"mode", PT_UINT32, PF_OCT} } }, /* PPME_SYSCALL_OPENAT_X */{"openat", EC_FILE, EF_CREATES_FD | EF_MODIFIES_STATE, 1, {{"fd", PT_FD, PF_DEC} } }, /* PPME_SYSCALL_LINK_E */{"link", EC_FILE, EF_NONE, 2, {{"oldpath", PT_FSPATH, PF_NA}, {"newpath", PT_FSPATH, PF_NA} } }, /* PPME_SYSCALL_LINK_X */{"link", EC_FILE, EF_NONE, 1, {{"res", PT_ERRNO, PF_DEC} } }, diff -Nru sysdig-0.16.0/userspace/libscap/flags_table.c sysdig-0.17.0/userspace/libscap/flags_table.c --- sysdig-0.16.0/userspace/libscap/flags_table.c 2017-05-08 09:30:22.000000000 +0000 +++ sysdig-0.17.0/userspace/libscap/flags_table.c 2017-07-24 16:13:14.000000000 +0000 @@ -253,6 +253,9 @@ {"F_SETFD", PPM_FCNTL_F_SETFD}, {"F_GETFD", PPM_FCNTL_F_GETFD}, {"F_DUPFD", PPM_FCNTL_F_DUPFD}, + {"F_OFD_GETLK", PPM_FCNTL_F_OFD_GETLK}, + {"F_OFD_SETLK", PPM_FCNTL_F_OFD_SETLK}, + {"F_OFD_SETLKW", PPM_FCNTL_F_OFD_SETLKW}, {"UNKNOWN", PPM_FCNTL_UNKNOWN}, {0, 0}, }; diff -Nru sysdig-0.16.0/userspace/libscap/scap.c sysdig-0.17.0/userspace/libscap/scap.c --- sysdig-0.16.0/userspace/libscap/scap.c 2017-05-08 09:30:22.000000000 +0000 +++ sysdig-0.17.0/userspace/libscap/scap.c 2017-07-24 16:13:14.000000000 +0000 @@ -59,7 +59,7 @@ static uint32_t get_max_consumers() { uint32_t max; - FILE *pfile = fopen("/sys/module/sysdig_probe/parameters/max_consumers", "r"); + FILE *pfile = fopen("/sys/module/" PROBE_DEVICE_NAME "_probe/parameters/max_consumers", "r"); if(pfile != NULL) { int w = fscanf(pfile, "%"PRIu32, &max); @@ -203,7 +203,7 @@ else if(errno == EBUSY) { uint32_t curr_max_consumers = get_max_consumers(); - snprintf(error, SCAP_LASTERR_SIZE, "Too many sysdig instances attached to device %s. Current value for /sys/module/sysdig_probe/parameters/max_consumers is '%"PRIu32"'.", filename, curr_max_consumers); + snprintf(error, SCAP_LASTERR_SIZE, "Too many sysdig instances attached to device %s. Current value for /sys/module/" PROBE_DEVICE_NAME "_probe/parameters/max_consumers is '%"PRIu32"'.", filename, curr_max_consumers); } else { @@ -214,6 +214,13 @@ return NULL; } + // Set close-on-exec for the fd + if (fcntl(handle->m_devs[j].m_fd, F_SETFD, FD_CLOEXEC) == -1) { + snprintf(error, SCAP_LASTERR_SIZE, "Can not set close-on-exec flag for fd for device %s (%s)", filename, strerror(errno)); + scap_close(handle); + return NULL; + } + // // Map the ring buffer // @@ -288,7 +295,7 @@ } #endif // HAS_CAPTURE -scap_t* scap_open_offline_int(const char* fname, +scap_t* scap_open_offline_int(gzFile gzfile, char *error, proc_entry_callback proc_callback, void* proc_callback_context, @@ -334,16 +341,7 @@ return NULL; } - // - // Open the file - // - handle->m_file = gzopen(fname, "rb"); - if(handle->m_file == NULL) - { - snprintf(error, SCAP_LASTERR_SIZE, "can't open file %s", fname); - scap_close(handle); - return NULL; - } + handle->m_file = gzfile; // // If this is a merged file, we might have to move the read offset to the next section @@ -358,7 +356,7 @@ // if(scap_read_init(handle, handle->m_file) != SCAP_SUCCESS) { - snprintf(error, SCAP_LASTERR_SIZE, "%s", scap_getlasterr(handle)); + snprintf(error, SCAP_LASTERR_SIZE, "Could not initialize reader: %s", scap_getlasterr(handle)); scap_close(handle); return NULL; } @@ -387,7 +385,26 @@ scap_t* scap_open_offline(const char* fname, char *error) { - return scap_open_offline_int(fname, error, NULL, NULL, true, 0); + gzFile gzfile = gzopen(fname, "rb"); + if(gzfile == NULL) + { + snprintf(error, SCAP_LASTERR_SIZE, "can't open file %s", fname); + return NULL; + } + + return scap_open_offline_int(gzfile, error, NULL, NULL, true, 0); +} + +scap_t* scap_open_offline_fd(int fd, char *error) +{ + gzFile gzfile = gzdopen(fd, "rb"); + if(gzfile == NULL) + { + snprintf(error, SCAP_LASTERR_SIZE, "can't open fd %d", fd); + return NULL; + } + + return scap_open_offline_int(gzfile, error, NULL, NULL, true, 0); } scap_t* scap_open_live(char *error) @@ -494,9 +511,35 @@ switch(args.mode) { case SCAP_MODE_CAPTURE: - return scap_open_offline_int(args.fname, error, + { + gzFile gzfile; + + if(args.fd != 0) + { + gzfile = gzdopen(args.fd, "rb"); + } + else + { + gzfile = gzopen(args.fname, "rb"); + } + + if(gzfile == NULL) + { + if(args.fd != 0) + { + snprintf(error, SCAP_LASTERR_SIZE, "can't open fd %d", args.fd); + } + else + { + snprintf(error, SCAP_LASTERR_SIZE, "can't open file %s", args.fname); + } + return NULL; + } + + return scap_open_offline_int(gzfile, error, args.proc_callback, args.proc_callback_context, args.import_users, args.start_offset); + } case SCAP_MODE_LIVE: return scap_open_live_int(error, args.proc_callback, args.proc_callback_context, @@ -523,24 +566,24 @@ ASSERT(handle->m_file == NULL); - // - // Destroy all the device descriptors - // - for(j = 0; j < handle->m_ndevs; j++) + if(handle->m_devs != NULL) { - if(handle->m_devs[j].m_buffer != MAP_FAILED) + // + // Destroy all the device descriptors + // + for(j = 0; j < handle->m_ndevs; j++) { - munmap(handle->m_devs[j].m_bufinfo, sizeof(struct ppm_ring_buffer_info)); - munmap(handle->m_devs[j].m_buffer, RING_BUF_SIZE * 2); - close(handle->m_devs[j].m_fd); + if(handle->m_devs[j].m_buffer != MAP_FAILED) + { + munmap(handle->m_devs[j].m_bufinfo, sizeof(struct ppm_ring_buffer_info)); + munmap(handle->m_devs[j].m_buffer, RING_BUF_SIZE * 2); + close(handle->m_devs[j].m_fd); + } } - } - // - // Free the memory - // - if(handle->m_devs != NULL) - { + // + // Free the memory + // free(handle->m_devs); } #endif // HAS_CAPTURE @@ -907,11 +950,13 @@ stats->n_evts = 0; stats->n_drops = 0; + stats->n_drops_buffer = 0; stats->n_preemptions = 0; for(j = 0; j < handle->m_ndevs; j++) { stats->n_evts += handle->m_devs[j].m_bufinfo->n_evts; + stats->n_drops_buffer += handle->m_devs[j].m_bufinfo->n_drops_buffer; stats->n_drops += handle->m_devs[j].m_bufinfo->n_drops_buffer + handle->m_devs[j].m_bufinfo->n_drops_pf; stats->n_preemptions += handle->m_devs[j].m_bufinfo->n_preemptions; diff -Nru sysdig-0.16.0/userspace/libscap/scap.def sysdig-0.17.0/userspace/libscap/scap.def --- sysdig-0.16.0/userspace/libscap/scap.def 2017-05-08 09:30:22.000000000 +0000 +++ sysdig-0.17.0/userspace/libscap/scap.def 2017-07-24 16:13:14.000000000 +0000 @@ -3,6 +3,7 @@ EXPORTS scap_open_live scap_open_offline + scap_open_offline_fd scap_open scap_close scap_get_os_platform @@ -12,10 +13,13 @@ scap_event_getlen scap_event_get_ts scap_dump_open + scap_dump_open_fd scap_dump_close scap_dump_get_offset scap_dump_flush + scap_dump_ftell scap_dump + scap_event_reset_count scap_event_get_num scap_get_proc_table scap_event_getinfo diff -Nru sysdig-0.16.0/userspace/libscap/scap_event.c sysdig-0.17.0/userspace/libscap/scap_event.c --- sysdig-0.16.0/userspace/libscap/scap_event.c 2017-05-08 09:30:22.000000000 +0000 +++ sysdig-0.17.0/userspace/libscap/scap_event.c 2017-07-24 16:13:14.000000000 +0000 @@ -60,6 +60,11 @@ return handle->m_evtcnt; } +void scap_event_reset_count(scap_t* handle) +{ + handle->m_evtcnt = 0; +} + uint64_t scap_event_get_ts(scap_evt* e) { return e->ts; diff -Nru sysdig-0.16.0/userspace/libscap/scap_fds.c sysdig-0.17.0/userspace/libscap/scap_fds.c --- sysdig-0.16.0/userspace/libscap/scap_fds.c 2017-05-08 09:30:22.000000000 +0000 +++ sysdig-0.17.0/userspace/libscap/scap_fds.c 2017-07-24 16:13:14.000000000 +0000 @@ -23,6 +23,7 @@ #include "scap-int.h" #include #include +#include #include "uthash.h" #ifdef _WIN32 #include @@ -144,12 +145,16 @@ case SCAP_FD_UNIX_SOCK: snprintf(str, stlen, "%"PRIi64" %"PRIu64" %"PRIX64"-> %"PRIX64" %s", fdi->fd,fdi->ino, fdi->info.unix_socket_info.source,fdi->info.unix_socket_info.destination, fdi->info.unix_socket_info.fname); break; + case SCAP_FD_FILE_V2: case SCAP_FD_FILE: case SCAP_FD_DIRECTORY: break; case SCAP_FD_UNSUPPORTED: snprintf(str, stlen, ""); break; + case SCAP_FD_NETLINK: + snprintf(str, stlen, ""); + break; default: ASSERT(false); return SCAP_FAILURE; @@ -197,6 +202,10 @@ sizeof(uint64_t) + // unix destination (uint32_t)strnlen(fdi->info.unix_socket_info.fname, SCAP_MAX_PATH_SIZE) + 2; break; + case SCAP_FD_FILE_V2: + res += sizeof(uint32_t) + // open_flags + (uint32_t)strnlen(fdi->info.regularinfo.fname, SCAP_MAX_PATH_SIZE) + 2; + break; case SCAP_FD_FIFO: case SCAP_FD_FILE: case SCAP_FD_DIRECTORY: @@ -206,6 +215,7 @@ case SCAP_FD_EVENTPOLL: case SCAP_FD_INOTIFY: case SCAP_FD_TIMERFD: + case SCAP_FD_NETLINK: res += (uint32_t)strnlen(fdi->info.fname, SCAP_MAX_PATH_SIZE) + 2; // 2 is the length field before the string break; default: @@ -289,6 +299,20 @@ return SCAP_FAILURE; } break; + case SCAP_FD_FILE_V2: + if(scap_dump_write(d, &(fdi->info.regularinfo.open_flags), sizeof(uint32_t)) != sizeof(uint32_t)) + { + snprintf(handle->m_lasterr, SCAP_LASTERR_SIZE, "error writing to file (fi1)"); + return SCAP_FAILURE; + } + stlen = (uint16_t)strnlen(fdi->info.regularinfo.fname, SCAP_MAX_PATH_SIZE); + if(scap_dump_write(d, &stlen, sizeof(uint16_t)) != sizeof(uint16_t) || + (stlen > 0 && scap_dump_write(d, fdi->info.regularinfo.fname, stlen) != stlen)) + { + snprintf(handle->m_lasterr, SCAP_LASTERR_SIZE, "error writing to file (fi1)"); + return SCAP_FAILURE; + } + break; case SCAP_FD_FIFO: case SCAP_FD_FILE: case SCAP_FD_DIRECTORY: @@ -298,6 +322,7 @@ case SCAP_FD_EVENTPOLL: case SCAP_FD_INOTIFY: case SCAP_FD_TIMERFD: + case SCAP_FD_NETLINK: stlen = (uint16_t)strnlen(fdi->info.fname, SCAP_MAX_PATH_SIZE); if(scap_dump_write(d, &stlen, sizeof(uint16_t)) != sizeof(uint16_t) || (stlen > 0 && scap_dump_write(d, fdi->info.fname, stlen) != stlen)) @@ -306,7 +331,12 @@ return SCAP_FAILURE; } break; + case SCAP_FD_UNKNOWN: + // Ignore UNKNOWN fds without failing + ASSERT(false); + break; default: + snprintf(handle->m_lasterr, SCAP_LASTERR_SIZE, "Unknown fdi type %d", fdi->type); ASSERT(false); return SCAP_FAILURE; } @@ -432,6 +462,16 @@ (*nbytes) += (sizeof(uint64_t) + sizeof(uint64_t)); res = scap_fd_read_fname_from_disk(handle, fdi->info.unix_socket_info.fname, nbytes, f); break; + case SCAP_FD_FILE_V2: + if(gzread(f, &(fdi->info.regularinfo.open_flags), sizeof(uint32_t)) != sizeof(uint32_t)) + { + snprintf(handle->m_lasterr, SCAP_LASTERR_SIZE, "error reading the fd info from file (fi1)"); + return SCAP_FAILURE; + } + + (*nbytes) += sizeof(uint32_t); + res = scap_fd_read_fname_from_disk(handle, fdi->info.regularinfo.fname, nbytes, f); + break; case SCAP_FD_FIFO: case SCAP_FD_FILE: case SCAP_FD_DIRECTORY: @@ -441,8 +481,12 @@ case SCAP_FD_EVENTPOLL: case SCAP_FD_INOTIFY: case SCAP_FD_TIMERFD: + case SCAP_FD_NETLINK: res = scap_fd_read_fname_from_disk(handle, fdi->info.fname,nbytes,f); break; + case SCAP_FD_UNKNOWN: + ASSERT(false); + break; default: snprintf(handle->m_lasterr, SCAP_LASTERR_SIZE, "error reading the fd info from file, wrong fd type %u", (uint32_t)fdi->type); return SCAP_FAILURE; @@ -569,12 +613,12 @@ int32_t scap_fd_handle_pipe(scap_t *handle, char *fname, scap_threadinfo *tinfo, scap_fdinfo *fdi, char *error) { - char link_name[1024]; + char link_name[SCAP_MAX_PATH_SIZE]; ssize_t r; uint64_t ino; struct stat sb; - r = readlink(fname, link_name, 1024); + r = readlink(fname, link_name, SCAP_MAX_PATH_SIZE); if (r <= 0) { return SCAP_FAILURE; @@ -596,12 +640,138 @@ return scap_add_fd_to_proc_table(handle, tinfo, fdi); } -int32_t scap_fd_handle_regular_file(scap_t *handle, char *fname, scap_threadinfo *tinfo, scap_fdinfo *fdi, char *error) +static inline uint32_t open_flags_to_scap(unsigned long flags) +{ + uint32_t res = 0; + + switch (flags & (O_RDONLY | O_WRONLY | O_RDWR)) { + case O_WRONLY: + res |= PPM_O_WRONLY; + break; + case O_RDWR: + res |= PPM_O_RDWR; + break; + default: + res |= PPM_O_RDONLY; + break; + } + + if (flags & O_CREAT) + res |= PPM_O_CREAT; + + if (flags & O_APPEND) + res |= PPM_O_APPEND; + +#ifdef O_DSYNC + if (flags & O_DSYNC) + res |= PPM_O_DSYNC; +#endif + + if (flags & O_EXCL) + res |= PPM_O_EXCL; + + if (flags & O_NONBLOCK) + res |= PPM_O_NONBLOCK; + + if (flags & O_SYNC) + res |= PPM_O_SYNC; + + if (flags & O_TRUNC) + res |= PPM_O_TRUNC; + +#ifdef O_DIRECT + if (flags & O_DIRECT) + res |= PPM_O_DIRECT; +#endif + + if (flags & O_DIRECTORY) + res |= PPM_O_DIRECTORY; + +#ifdef O_LARGEFILE + if (flags & O_LARGEFILE) + res |= PPM_O_LARGEFILE; +#endif + +#ifdef O_CLOEXEC + if (flags & O_CLOEXEC) + res |= PPM_O_CLOEXEC; +#endif + + return res; +} + +void scap_fd_flags_file(scap_t *handle, scap_fdinfo *fdi, const char *procdir) +{ + int is_first_line = true; + const char *delimiters = " \t"; + char fd_dir_name[SCAP_MAX_PATH_SIZE]; + char line[SCAP_MAX_PATH_SIZE]; + FILE *finfo; + + snprintf(fd_dir_name, SCAP_MAX_PATH_SIZE, "%sfdinfo/%ld", procdir, fdi->fd); + finfo = fopen(fd_dir_name, "r"); + if(finfo == NULL) + { + return; + } + + while(fgets(line, sizeof(line), finfo) != NULL) + { + // We are just interested in the flags. + // + // The format of the file is: + // pos: XXXX + // flags: YYYYYYYY + // mnt_id: ZZZ + + char *scratch; + char *token; + + if(is_first_line) + { + is_first_line = false; + continue; + } + + token = strtok_r(line, delimiters, &scratch); + if(token == NULL) + { + ASSERT(false); + continue; + } + + token = strtok_r(NULL, delimiters, &scratch); + if(token == NULL) + { + ASSERT(false); + continue; + } + + uint32_t open_flags; + unsigned long flags = strtoul(token, NULL, 8); + + if(errno == ERANGE) + { + open_flags = PPM_O_NONE; + } + else + { + open_flags = open_flags_to_scap(flags); + } + + fdi->info.regularinfo.open_flags = open_flags; + break; + } + + fclose(finfo); +} + +int32_t scap_fd_handle_regular_file(scap_t *handle, char *fname, scap_threadinfo *tinfo, scap_fdinfo *fdi, const char *procdir, char *error) { - char link_name[1024]; + char link_name[SCAP_MAX_PATH_SIZE]; ssize_t r; - r = readlink(fname, link_name, 1024); + r = readlink(fname, link_name, SCAP_MAX_PATH_SIZE); if (r <= 0) { return SCAP_SUCCESS; @@ -637,10 +807,17 @@ if(SCAP_FD_UNSUPPORTED == fdi->type) { // still not able to classify -// printf("unsupported %s -> %s\n",fname,link_name); + // printf("unsupported %s -> %s\n",fname,link_name); } fdi->info.fname[0] = '\0'; - } else { + } + else if(fdi->type == SCAP_FD_FILE_V2) + { + scap_fd_flags_file(handle, fdi, procdir); + strncpy(fdi->info.regularinfo.fname, link_name, SCAP_MAX_PATH_SIZE); + } + else + { strncpy(fdi->info.fname, link_name, SCAP_MAX_PATH_SIZE); } @@ -649,7 +826,7 @@ int32_t scap_fd_handle_socket(scap_t *handle, char *fname, scap_threadinfo *tinfo, scap_fdinfo *fdi, char* procdir, uint64_t net_ns, struct scap_ns_socket_list **sockets_by_ns, char *error) { - char link_name[1024]; + char link_name[SCAP_MAX_PATH_SIZE]; ssize_t r; scap_fdinfo *tfdi; uint64_t ino; @@ -684,7 +861,7 @@ } } - r = readlink(fname, link_name, 1024); + r = readlink(fname, link_name, SCAP_MAX_PATH_SIZE); if(r <= 0) { return SCAP_SUCCESS; @@ -722,7 +899,7 @@ int32_t scap_fd_read_unix_sockets_from_proc_fs(scap_t *handle, const char* filename, scap_fdinfo **sockets) { FILE *f; - char line[1024]; + char line[SCAP_MAX_PATH_SIZE]; int first_line = false; char *delimiters = " \t"; char *token; @@ -736,6 +913,8 @@ } while(NULL != fgets(line, sizeof(line), f)) { + char *scratch; + // skip the first line ... contains field names if(!first_line) { @@ -750,7 +929,7 @@ // parse the fields // // 1. Num - token = strtok(line, delimiters); + token = strtok_r(line, delimiters, &scratch); if(token == NULL) { ASSERT(false); @@ -762,7 +941,7 @@ fdinfo->info.unix_socket_info.destination = 0; // 2. RefCount - token = strtok(NULL, delimiters); + token = strtok_r(NULL, delimiters, &scratch); if(token == NULL) { ASSERT(false); @@ -771,7 +950,7 @@ } // 3. Protocol - token = strtok(NULL, delimiters); + token = strtok_r(NULL, delimiters, &scratch); if(token == NULL) { ASSERT(false); @@ -780,7 +959,7 @@ } // 4. Flags - token = strtok(NULL, delimiters); + token = strtok_r(NULL, delimiters, &scratch); if(token == NULL) { ASSERT(false); @@ -789,7 +968,7 @@ } // 5. Type - token = strtok(NULL, delimiters); + token = strtok_r(NULL, delimiters, &scratch); if(token == NULL) { ASSERT(false); @@ -798,7 +977,7 @@ } // 6. St - token = strtok(NULL, delimiters); + token = strtok_r(NULL, delimiters, &scratch); if(token == NULL) { ASSERT(false); @@ -807,7 +986,7 @@ } // 7. Inode - token = strtok(NULL, delimiters); + token = strtok_r(NULL, delimiters, &scratch); if(token == NULL) { ASSERT(false); @@ -818,7 +997,7 @@ sscanf(token, "%"PRIu64, &(fdinfo->ino)); // 8. Path - token = strtok(NULL, delimiters); + token = strtok_r(NULL, delimiters, &scratch); if(NULL != token) { strncpy(fdinfo->info.unix_socket_info.fname, token, SCAP_MAX_PATH_SIZE); @@ -839,6 +1018,145 @@ return uth_status; } +//sk Eth Pid Groups Rmem Wmem Dump Locks Drops Inode +//ffff88011abfb000 0 0 00000000 0 0 0 2 0 13 + +int32_t scap_fd_read_netlink_sockets_from_proc_fs(scap_t *handle, const char* filename, scap_fdinfo **sockets) +{ + FILE *f; + char line[SCAP_MAX_PATH_SIZE]; + int first_line = false; + char *delimiters = " \t"; + char *token; + int32_t uth_status = SCAP_SUCCESS; + + f = fopen(filename, "r"); + if(NULL == f) + { + ASSERT(false); + return SCAP_FAILURE; + } + while(NULL != fgets(line, sizeof(line), f)) + { + char *scratch; + + // skip the first line ... contains field names + if(!first_line) + { + first_line = true; + continue; + } + scap_fdinfo *fdinfo = malloc(sizeof(scap_fdinfo)); + memset(fdinfo, 0, sizeof(scap_fdinfo)); + fdinfo->type = SCAP_FD_UNIX_SOCK; + + + // + // parse the fields + // + // 1. Num + token = strtok_r(line, delimiters, &scratch); + if(token == NULL) + { + ASSERT(false); + free(fdinfo); + continue; + } + + // 2. Eth + token = strtok_r(NULL, delimiters, &scratch); + if(token == NULL) + { + ASSERT(false); + free(fdinfo); + continue; + } + + // 3. Pid + token = strtok_r(NULL, delimiters, &scratch); + if(token == NULL) + { + ASSERT(false); + free(fdinfo); + continue; + } + + // 4. Groups + token = strtok_r(NULL, delimiters, &scratch); + if(token == NULL) + { + ASSERT(false); + free(fdinfo); + continue; + } + + // 5. Rmem + token = strtok_r(NULL, delimiters, &scratch); + if(token == NULL) + { + ASSERT(false); + free(fdinfo); + continue; + } + + // 6. Wmem + token = strtok_r(NULL, delimiters, &scratch); + if(token == NULL) + { + ASSERT(false); + free(fdinfo); + continue; + } + + // 7. Dump + token = strtok_r(NULL, delimiters, &scratch); + if(token == NULL) + { + ASSERT(false); + free(fdinfo); + continue; + } + + // 8. Locks + token = strtok_r(NULL, delimiters, &scratch); + if(token == NULL) + { + ASSERT(false); + free(fdinfo); + continue; + } + + // 9. Drops + token = strtok_r(NULL, delimiters, &scratch); + if(token == NULL) + { + ASSERT(false); + free(fdinfo); + continue; + } + + // 10. Inode + token = strtok_r(NULL, delimiters, &scratch); + if(token == NULL) + { + ASSERT(false); + free(fdinfo); + continue; + } + + sscanf(token, "%"PRIu64, &(fdinfo->ino)); + + HASH_ADD_INT64((*sockets), ino, fdinfo); + if(uth_status != SCAP_SUCCESS) + { + snprintf(handle->m_lasterr, SCAP_LASTERR_SIZE, "netlink socket allocation error"); + return SCAP_FAILURE; + } + } + fclose(f); + return uth_status; +} + int32_t scap_fd_read_ipv4_sockets_from_proc_fs(scap_t *handle, const char *dir, int l4proto, scap_fdinfo **sockets) { FILE *f; @@ -1279,6 +1597,13 @@ return SCAP_FAILURE; } + snprintf(filename, sizeof(filename), "%snetlink", netroot); + if(scap_fd_read_netlink_sockets_from_proc_fs(handle, filename, &sockets->sockets) == SCAP_FAILURE) + { + scap_fd_free_table(handle, &sockets->sockets); + return SCAP_FAILURE; + } + snprintf(filename, sizeof(filename), "%stcp6", netroot); /* We assume if there is /proc/net/tcp6 that ipv6 is avaiable */ if(access(filename, R_OK) == 0) @@ -1367,9 +1692,9 @@ DIR *dir_p; struct dirent *dir_entry_p; int32_t res = SCAP_SUCCESS; - char fd_dir_name[1024]; - char f_name[1024]; - char link_name[1024]; + char fd_dir_name[SCAP_MAX_PATH_SIZE]; + char f_name[SCAP_MAX_PATH_SIZE]; + char link_name[SCAP_MAX_PATH_SIZE]; struct stat sb; uint64_t fd; scap_fdinfo *fdi = NULL; @@ -1377,7 +1702,7 @@ ssize_t r; uint16_t fd_added = 0; - snprintf(fd_dir_name, 1024, "%sfd", procdir); + snprintf(fd_dir_name, SCAP_MAX_PATH_SIZE, "%sfd", procdir); dir_p = opendir(fd_dir_name); if(dir_p == NULL) { @@ -1407,7 +1732,7 @@ (handle->m_fd_lookup_limit == 0 || fd_added < handle->m_fd_lookup_limit)) { fdi = NULL; - snprintf(f_name, 1024, "%s/%s", fd_dir_name, dir_entry_p->d_name); + snprintf(f_name, SCAP_MAX_PATH_SIZE, "%s/%s", fd_dir_name, dir_entry_p->d_name); if(-1 == stat(f_name, &sb) || 1 != sscanf(dir_entry_p->d_name, "%"PRIu64, &fd)) { @@ -1428,20 +1753,20 @@ if(SCAP_FAILURE == res) { break; - } + } res = scap_fd_handle_pipe(handle, f_name, tinfo, fdi, error); break; case S_IFREG: case S_IFBLK: case S_IFCHR: case S_IFLNK: - res = scap_fd_allocate_fdinfo(handle, &fdi, fd, SCAP_FD_FILE); + res = scap_fd_allocate_fdinfo(handle, &fdi, fd, SCAP_FD_FILE_V2); if(SCAP_FAILURE == res) { break; } fdi->ino = sb.st_ino; - res = scap_fd_handle_regular_file(handle, f_name, tinfo, fdi, error); + res = scap_fd_handle_regular_file(handle, f_name, tinfo, fdi, procdir, error); break; case S_IFDIR: res = scap_fd_allocate_fdinfo(handle, &fdi, fd, SCAP_FD_DIRECTORY); @@ -1450,7 +1775,7 @@ break; } fdi->ino = sb.st_ino; - res = scap_fd_handle_regular_file(handle, f_name, tinfo, fdi, error); + res = scap_fd_handle_regular_file(handle, f_name, tinfo, fdi, procdir, error); break; case S_IFSOCK: res = scap_fd_allocate_fdinfo(handle, &fdi, fd, SCAP_FD_UNKNOWN); @@ -1475,7 +1800,7 @@ break; } fdi->ino = sb.st_ino; - res = scap_fd_handle_regular_file(handle, f_name, tinfo, fdi, error); + res = scap_fd_handle_regular_file(handle, f_name, tinfo, fdi, procdir, error); break; } diff -Nru sysdig-0.16.0/userspace/libscap/scap.h sysdig-0.17.0/userspace/libscap/scap.h --- sysdig-0.16.0/userspace/libscap/scap.h 2017-05-08 09:30:22.000000000 +0000 +++ sysdig-0.17.0/userspace/libscap/scap.h 2017-07-24 16:13:14.000000000 +0000 @@ -83,6 +83,7 @@ { uint64_t n_evts; ///< Total number of events that were received by the driver. uint64_t n_drops; ///< Number of dropped events. + uint64_t n_drops_buffer; ///< Number of dropped events caused by full buffer. uint64_t n_preemptions; ///< Number of preemptions. }scap_stats; @@ -122,7 +123,9 @@ SCAP_FD_SIGNALFD = 11, SCAP_FD_EVENTPOLL = 12, SCAP_FD_INOTIFY = 13, - SCAP_FD_TIMERFD = 14 + SCAP_FD_TIMERFD = 14, + SCAP_FD_NETLINK = 15, + SCAP_FD_FILE_V2 = 16 }scap_fd_type; /*! @@ -182,6 +185,11 @@ uint64_t destination; ///< Destination socket endpoint char fname[SCAP_MAX_PATH_SIZE]; ///< Name associated to this unix socket } unix_socket_info; ///< Information specific to unix sockets + struct + { + uint32_t open_flags; ///< Flags associated with the file + char fname[SCAP_MAX_PATH_SIZE]; ///< Name associated to this file + } regularinfo; ///< Information specific to regular files char fname[SCAP_MAX_PATH_SIZE]; ///< The name for file system FDs }info; UT_hash_handle hh; ///< makes this structure hashable @@ -243,6 +251,7 @@ typedef struct scap_open_args { scap_mode_t mode; + int fd; // If non-zero, will be used instead of fname. const char* fname; ///< The name of the file to open. NULL for live captures. proc_entry_callback proc_callback; ///< Callback to be invoked for each thread/fd that is extracted from /proc, or NULL if no callback is needed. void* proc_callback_context; ///< Opaque pointer that will be included in the calls to proc_callback. Ignored if proc_callback is NULL. @@ -497,6 +506,17 @@ scap_t* scap_open_offline(const char* fname, char *error); /*! + \brief Start an event capture from an already opened file descriptor. + + \param fd The fd to use. + \param error Pointer to a buffer that will contain the error string in case the + function fails. The buffer must have size SCAP_LASTERR_SIZE. + + \return The capture instance handle in case of success. NULL in case of failure. +*/ +scap_t* scap_open_offline_fd(int fd, char *error); + +/*! \brief Advanced function to start a capture. \param args a \ref scap_open_args structure containing the open paraneters. @@ -576,6 +596,13 @@ uint64_t scap_event_get_num(scap_t* handle); /*! + \brief Reset the event count to 0. + + \param handle Handle to the capture instance. +*/ +void scap_event_reset_count(scap_t* handle); + +/*! \brief Return the meta-information describing the given event \param e pointer to an event returned by \ref scap_next. @@ -612,6 +639,16 @@ scap_dumper_t* scap_dump_open(scap_t *handle, const char *fname, compression_mode compress); /*! + \brief Open a tracefile for writing, using the provided fd. + + \param handle Handle to the capture instance. + \param fd A file descriptor to which the dumper will write + + \return Dump handle that can be used to identify this specific dump instance. +*/ +scap_dumper_t* scap_dump_open_fd(scap_t *handle, int fd, compression_mode compress, bool skip_proc_scan); + +/*! \brief Close a tracefile. \param d The dump handle, returned by \ref scap_dump_open @@ -627,6 +664,15 @@ int64_t scap_dump_get_offset(scap_dumper_t *d); /*! + \brief Return the position for the next write to a tracefile. + This uses gztell, while scap_dump_get_offset uses gzoffset. + + \param d The dump handle, returned by \ref scap_dump_open + \return The next write position. +*/ +int64_t scap_dump_ftell(scap_dumper_t *d); + +/*! \brief Flush all pending output into the file. \param d The dump handle, returned by \ref scap_dump_open @@ -890,6 +936,10 @@ scap_dumper_t *scap_memory_dump_open(scap_t *handle, uint8_t* targetbuf, uint64_t targetbufsize); int32_t compr(uint8_t* dest, uint64_t* destlen, const uint8_t* source, uint64_t sourcelen, int level); uint8_t* scap_get_memorydumper_curpos(scap_dumper_t *d); +int32_t scap_write_proc_fds(scap_t *handle, struct scap_threadinfo *tinfo, scap_dumper_t *d); +int32_t scap_write_proclist_header(scap_t *handle, scap_dumper_t *d, uint32_t totlen); +int32_t scap_write_proclist_trailer(scap_t *handle, scap_dumper_t *d, uint32_t totlen); +int32_t scap_write_proclist_entry(scap_t *handle, scap_dumper_t *d, struct scap_threadinfo *tinfo); #ifdef __cplusplus } diff -Nru sysdig-0.16.0/userspace/libscap/scap-int.h sysdig-0.17.0/userspace/libscap/scap-int.h --- sysdig-0.16.0/userspace/libscap/scap-int.h 2017-05-08 09:30:22.000000000 +0000 +++ sysdig-0.17.0/userspace/libscap/scap-int.h 2017-07-24 16:13:14.000000000 +0000 @@ -225,6 +225,17 @@ return SCAP_FAILURE;\ } +#define CHECK_READ_SIZE_WITH_FREE(alloc_buffer, read_size, expected_size) if(read_size != expected_size) \ + {\ + snprintf(handle->m_lasterr, SCAP_LASTERR_SIZE, "expecting %d bytes, read %d at %s, line %d. Is the file truncated?",\ + (int)expected_size,\ + (int)read_size,\ + __FILE__,\ + __LINE__);\ + free(alloc_buffer);\ + return SCAP_FAILURE;\ + } + // // Useful stuff // diff -Nru sysdig-0.16.0/userspace/libscap/scap_procs.c sysdig-0.17.0/userspace/libscap/scap_procs.c --- sysdig-0.16.0/userspace/libscap/scap_procs.c 2017-05-08 09:30:22.000000000 +0000 +++ sysdig-0.17.0/userspace/libscap/scap_procs.c 2017-07-24 16:13:14.000000000 +0000 @@ -310,9 +310,10 @@ char* token; char* subsys_list; char* cgroup; + char* scratch; // id - token = strtok(line, ":"); + token = strtok_r(line, ":", &scratch); if(token == NULL) { ASSERT(false); @@ -321,7 +322,7 @@ } // subsys - subsys_list = strtok(NULL, ":"); + subsys_list = strtok_r(NULL, ":", &scratch); if(subsys_list == NULL) { ASSERT(false); @@ -329,6 +330,16 @@ return SCAP_FAILURE; } + // Hack to detect empty fields, because strtok does not support it + // strsep() should be used to fix this but it's not available + // on CentOS 6 (has been added from Glibc 2.19) + if(subsys_list-token-strlen(token) > 1) + { + // skip cgroups like this: + // 0::/init.scope + continue; + } + // transient cgroup if(strncmp(subsys_list, "name=", sizeof("name=") - 1) == 0) { @@ -336,7 +347,7 @@ } // cgroup - cgroup = strtok(NULL, ":"); + cgroup = strtok_r(NULL, ":", &scratch); if(cgroup == NULL) { ASSERT(false); @@ -347,7 +358,7 @@ // remove the \n cgroup[strlen(cgroup) - 1] = 0; - while((token = strtok(subsys_list, ",")) != NULL) + while((token = strtok_r(subsys_list, ",", &scratch)) != NULL) { subsys_list = NULL; if(strlen(cgroup) + 1 + strlen(token) + 1 > SCAP_MAX_CGROUPS_SIZE - tinfo->cgroups_len) diff -Nru sysdig-0.16.0/userspace/libscap/scap_savefile.c sysdig-0.17.0/userspace/libscap/scap_savefile.c --- sysdig-0.16.0/userspace/libscap/scap_savefile.c 2017-05-08 09:30:22.000000000 +0000 +++ sysdig-0.17.0/userspace/libscap/scap_savefile.c 2017-07-24 16:13:14.000000000 +0000 @@ -108,7 +108,7 @@ } } -static int32_t scap_write_proc_fds(scap_t *handle, struct scap_threadinfo *tinfo, scap_dumper_t *d) +int32_t scap_write_proc_fds(scap_t *handle, struct scap_threadinfo *tinfo, scap_dumper_t *d) { block_header bh; uint32_t bt; @@ -121,7 +121,8 @@ // HASH_ITER(hh, tinfo->fdlist, fdi, tfdi) { - if(fdi->type != SCAP_FD_UNINITIALIZED) + if(fdi->type != SCAP_FD_UNINITIALIZED && + fdi->type != SCAP_FD_UNKNOWN) { totlen += scap_fd_info_len(fdi); } @@ -211,13 +212,63 @@ // // Write the process list block // -static int32_t scap_write_proclist(scap_t *handle, scap_dumper_t *d) +int32_t scap_write_proclist_header(scap_t *handle, scap_dumper_t *d, uint32_t totlen) +{ + block_header bh; + + // + // Create the block header + // + bh.block_type = PL_BLOCK_TYPE_V6; + bh.block_total_length = scap_normalize_block_len(sizeof(block_header) + totlen + 4); + + if(scap_dump_write(d, &bh, sizeof(bh)) != sizeof(bh)) + { + snprintf(handle->m_lasterr, SCAP_LASTERR_SIZE, "error writing to file (1)"); + return SCAP_FAILURE; + } + + return SCAP_SUCCESS; +} + +// +// Write the process list block +// +int32_t scap_write_proclist_trailer(scap_t *handle, scap_dumper_t *d, uint32_t totlen) { block_header bh; uint32_t bt; - uint32_t totlen = 0; - struct scap_threadinfo *tinfo; - struct scap_threadinfo *ttinfo; + + bh.block_type = PL_BLOCK_TYPE_V6; + bh.block_total_length = scap_normalize_block_len(sizeof(block_header) + totlen + 4); + + // + // Blocks need to be 4-byte padded + // + if(scap_write_padding(d, totlen) != SCAP_SUCCESS) + { + snprintf(handle->m_lasterr, SCAP_LASTERR_SIZE, "error writing to file (3)"); + return SCAP_FAILURE; + } + + // + // Create the trailer + // + bt = bh.block_total_length; + if(scap_dump_write(d, &bt, sizeof(bt)) != sizeof(bt)) + { + snprintf(handle->m_lasterr, SCAP_LASTERR_SIZE, "error writing to file (4)"); + return SCAP_FAILURE; + } + + return SCAP_SUCCESS; +} + +// +// Write the process list block +// +int32_t scap_write_proclist_entry(scap_t *handle, scap_dumper_t *d, struct scap_threadinfo *tinfo) +{ uint16_t commlen; uint16_t exelen; uint16_t argslen; @@ -225,13 +276,68 @@ uint16_t rootlen; // + // Second pass of the table to dump it + // + commlen = (uint16_t)strnlen(tinfo->comm, SCAP_MAX_PATH_SIZE); + exelen = (uint16_t)strnlen(tinfo->exe, SCAP_MAX_PATH_SIZE); + argslen = tinfo->args_len; + cwdlen = (uint16_t)strnlen(tinfo->cwd, SCAP_MAX_PATH_SIZE); + rootlen = (uint16_t)strnlen(tinfo->root, SCAP_MAX_PATH_SIZE); + + if(scap_dump_write(d, &(tinfo->tid), sizeof(uint64_t)) != sizeof(uint64_t) || + scap_dump_write(d, &(tinfo->pid), sizeof(uint64_t)) != sizeof(uint64_t) || + scap_dump_write(d, &(tinfo->ptid), sizeof(uint64_t)) != sizeof(uint64_t) || + scap_dump_write(d, &(tinfo->sid), sizeof(uint64_t)) != sizeof(uint64_t) || + scap_dump_write(d, &commlen, sizeof(uint16_t)) != sizeof(uint16_t) || + scap_dump_write(d, tinfo->comm, commlen) != commlen || + scap_dump_write(d, &exelen, sizeof(uint16_t)) != sizeof(uint16_t) || + scap_dump_write(d, tinfo->exe, exelen) != exelen || + scap_dump_write(d, &argslen, sizeof(uint16_t)) != sizeof(uint16_t) || + scap_dump_write(d, tinfo->args, argslen) != argslen || + scap_dump_write(d, &cwdlen, sizeof(uint16_t)) != sizeof(uint16_t) || + scap_dump_write(d, tinfo->cwd, cwdlen) != cwdlen || + scap_dump_write(d, &(tinfo->fdlimit), sizeof(uint64_t)) != sizeof(uint64_t) || + scap_dump_write(d, &(tinfo->flags), sizeof(uint32_t)) != sizeof(uint32_t) || + scap_dump_write(d, &(tinfo->uid), sizeof(uint32_t)) != sizeof(uint32_t) || + scap_dump_write(d, &(tinfo->gid), sizeof(uint32_t)) != sizeof(uint32_t) || + scap_dump_write(d, &(tinfo->vmsize_kb), sizeof(uint32_t)) != sizeof(uint32_t) || + scap_dump_write(d, &(tinfo->vmrss_kb), sizeof(uint32_t)) != sizeof(uint32_t) || + scap_dump_write(d, &(tinfo->vmswap_kb), sizeof(uint32_t)) != sizeof(uint32_t) || + scap_dump_write(d, &(tinfo->pfmajor), sizeof(uint64_t)) != sizeof(uint64_t) || + scap_dump_write(d, &(tinfo->pfminor), sizeof(uint64_t)) != sizeof(uint64_t) || + scap_dump_write(d, &(tinfo->env_len), sizeof(uint16_t)) != sizeof(uint16_t) || + scap_dump_write(d, tinfo->env, tinfo->env_len) != tinfo->env_len || + scap_dump_write(d, &(tinfo->vtid), sizeof(int64_t)) != sizeof(int64_t) || + scap_dump_write(d, &(tinfo->vpid), sizeof(int64_t)) != sizeof(int64_t) || + scap_dump_write(d, &(tinfo->cgroups_len), sizeof(uint16_t)) != sizeof(uint16_t) || + scap_dump_write(d, tinfo->cgroups, tinfo->cgroups_len) != tinfo->cgroups_len || + scap_dump_write(d, &rootlen, sizeof(uint16_t)) != sizeof(uint16_t) || + scap_dump_write(d, tinfo->root, rootlen) != rootlen) + { + snprintf(handle->m_lasterr, SCAP_LASTERR_SIZE, "error writing to file (2)"); + return SCAP_FAILURE; + } + + return SCAP_SUCCESS; +} + +// +// Write the process list block +// +static int32_t scap_write_proclist(scap_t *handle, scap_dumper_t *d) +{ + uint32_t totlen = 0; + struct scap_threadinfo *tinfo; + struct scap_threadinfo *ttinfo; + + // // First pass pass of the table to calculate the length // HASH_ITER(hh, handle->m_proclist, tinfo, ttinfo) { if(!tinfo->filtered_out) { - totlen += (uint32_t) + uint32_t il= (uint32_t) (sizeof(uint64_t) + // tid sizeof(uint64_t) + // pid sizeof(uint64_t) + // ptid @@ -254,23 +360,18 @@ 2 + tinfo->cgroups_len + sizeof(uint32_t) + 2 + strnlen(tinfo->root, SCAP_MAX_PATH_SIZE)); + + totlen += il; } } - // - // Create the block - // - bh.block_type = PL_BLOCK_TYPE_V6; - bh.block_total_length = scap_normalize_block_len(sizeof(block_header) + totlen + 4); - - if(scap_dump_write(d, &bh, sizeof(bh)) != sizeof(bh)) + if(scap_write_proclist_header(handle, d, totlen) != SCAP_SUCCESS) { - snprintf(handle->m_lasterr, SCAP_LASTERR_SIZE, "error writing to file (1)"); return SCAP_FAILURE; } // - // Second pass pass of the table to dump it + // Second pass of the table to dump it // HASH_ITER(hh, handle->m_proclist, tinfo, ttinfo) { @@ -279,67 +380,13 @@ continue; } - commlen = (uint16_t)strnlen(tinfo->comm, SCAP_MAX_PATH_SIZE); - exelen = (uint16_t)strnlen(tinfo->exe, SCAP_MAX_PATH_SIZE); - argslen = tinfo->args_len; - cwdlen = (uint16_t)strnlen(tinfo->cwd, SCAP_MAX_PATH_SIZE); - rootlen = (uint16_t)strnlen(tinfo->root, SCAP_MAX_PATH_SIZE); - - if(scap_dump_write(d, &(tinfo->tid), sizeof(uint64_t)) != sizeof(uint64_t) || - scap_dump_write(d, &(tinfo->pid), sizeof(uint64_t)) != sizeof(uint64_t) || - scap_dump_write(d, &(tinfo->ptid), sizeof(uint64_t)) != sizeof(uint64_t) || - scap_dump_write(d, &(tinfo->sid), sizeof(uint64_t)) != sizeof(uint64_t) || - scap_dump_write(d, &commlen, sizeof(uint16_t)) != sizeof(uint16_t) || - scap_dump_write(d, tinfo->comm, commlen) != commlen || - scap_dump_write(d, &exelen, sizeof(uint16_t)) != sizeof(uint16_t) || - scap_dump_write(d, tinfo->exe, exelen) != exelen || - scap_dump_write(d, &argslen, sizeof(uint16_t)) != sizeof(uint16_t) || - scap_dump_write(d, tinfo->args, argslen) != argslen || - scap_dump_write(d, &cwdlen, sizeof(uint16_t)) != sizeof(uint16_t) || - scap_dump_write(d, tinfo->cwd, cwdlen) != cwdlen || - scap_dump_write(d, &(tinfo->fdlimit), sizeof(uint64_t)) != sizeof(uint64_t) || - scap_dump_write(d, &(tinfo->flags), sizeof(uint32_t)) != sizeof(uint32_t) || - scap_dump_write(d, &(tinfo->uid), sizeof(uint32_t)) != sizeof(uint32_t) || - scap_dump_write(d, &(tinfo->gid), sizeof(uint32_t)) != sizeof(uint32_t) || - scap_dump_write(d, &(tinfo->vmsize_kb), sizeof(uint32_t)) != sizeof(uint32_t) || - scap_dump_write(d, &(tinfo->vmrss_kb), sizeof(uint32_t)) != sizeof(uint32_t) || - scap_dump_write(d, &(tinfo->vmswap_kb), sizeof(uint32_t)) != sizeof(uint32_t) || - scap_dump_write(d, &(tinfo->pfmajor), sizeof(uint64_t)) != sizeof(uint64_t) || - scap_dump_write(d, &(tinfo->pfminor), sizeof(uint64_t)) != sizeof(uint64_t) || - scap_dump_write(d, &(tinfo->env_len), sizeof(uint16_t)) != sizeof(uint16_t) || - scap_dump_write(d, tinfo->env, tinfo->env_len) != tinfo->env_len || - scap_dump_write(d, &(tinfo->vtid), sizeof(int64_t)) != sizeof(int64_t) || - scap_dump_write(d, &(tinfo->vpid), sizeof(int64_t)) != sizeof(int64_t) || - scap_dump_write(d, &(tinfo->cgroups_len), sizeof(uint16_t)) != sizeof(uint16_t) || - scap_dump_write(d, tinfo->cgroups, tinfo->cgroups_len) != tinfo->cgroups_len || - scap_dump_write(d, &rootlen, sizeof(uint16_t)) != sizeof(uint16_t) || - scap_dump_write(d, tinfo->root, rootlen) != rootlen) + if(scap_write_proclist_entry(handle, d, tinfo) != SCAP_SUCCESS) { - snprintf(handle->m_lasterr, SCAP_LASTERR_SIZE, "error writing to file (2)"); return SCAP_FAILURE; } } - // - // Blocks need to be 4-byte padded - // - if(scap_write_padding(d, totlen) != SCAP_SUCCESS) - { - snprintf(handle->m_lasterr, SCAP_LASTERR_SIZE, "error writing to file (3)"); - return SCAP_FAILURE; - } - - // - // Create the trailer - // - bt = bh.block_total_length; - if(scap_dump_write(d, &bt, sizeof(bt)) != sizeof(bt)) - { - snprintf(handle->m_lasterr, SCAP_LASTERR_SIZE, "error writing to file (4)"); - return SCAP_FAILURE; - } - - return SCAP_SUCCESS; + return scap_write_proclist_trailer(handle, d, totlen); } // @@ -697,6 +744,35 @@ return SCAP_SUCCESS; } +// fname is only used for log messages in scap_setup_dump +static scap_dumper_t *scap_dump_open_gzfile(scap_t *handle, gzFile gzfile, const char *fname, bool skip_proc_scan) +{ + scap_dumper_t* res = (scap_dumper_t*)malloc(sizeof(scap_dumper_t)); + res->m_f = gzfile; + res->m_type = DT_FILE; + res->m_targetbuf = NULL; + res->m_targetbufcurpos = NULL; + res->m_targetbufend = NULL; + + bool tmp_refresh_proc_table_when_saving = handle->refresh_proc_table_when_saving; + if(skip_proc_scan) + { + handle->refresh_proc_table_when_saving = false; + } + + if(scap_setup_dump(handle, res, fname) != SCAP_SUCCESS) + { + res = NULL; + } + + if(skip_proc_scan) + { + handle->refresh_proc_table_when_saving = tmp_refresh_proc_table_when_saving; + } + + return res; +} + // // Open a "savefile" for writing. // @@ -751,19 +827,39 @@ return NULL; } - scap_dumper_t* res = (scap_dumper_t*)malloc(sizeof(scap_dumper_t)); - res->m_f = f; - res->m_type = DT_FILE; - res->m_targetbuf = NULL; - res->m_targetbufcurpos = NULL; - res->m_targetbufend = NULL; + return scap_dump_open_gzfile(handle, f, fname, false); +} - if(scap_setup_dump(handle, res, fname) != SCAP_SUCCESS) +// +// Open a savefile for writing, using the provided fd +scap_dumper_t* scap_dump_open_fd(scap_t *handle, int fd, compression_mode compress, bool skip_proc_scan) +{ + gzFile f = NULL; + const char* mode; + + switch(compress) { - res = NULL; + case SCAP_COMPRESSION_GZIP: + mode = "wb"; + break; + case SCAP_COMPRESSION_NONE: + mode = "wbT"; + break; + default: + ASSERT(false); + snprintf(handle->m_lasterr, SCAP_LASTERR_SIZE, "invalid compression mode"); + return NULL; } - return res; + f = gzdopen(fd, mode); + + if(f == NULL) + { + snprintf(handle->m_lasterr, SCAP_LASTERR_SIZE, "can't open fd %d", fd); + return NULL; + } + + return scap_dump_open_gzfile(handle, f, "", skip_proc_scan); } // @@ -784,12 +880,22 @@ res->m_targetbufcurpos = targetbuf; res->m_targetbufend = targetbuf + targetbufsize; + // + // Disable proc parsing since it would be too heavy when saving to memory. + // Before doing that, backup handle->refresh_proc_table_when_saving so we can + // restore whatever the current seetting is as soon as we're done. + // + bool tmp_refresh_proc_table_when_saving = handle->refresh_proc_table_when_saving; + handle->refresh_proc_table_when_saving = false; + if(scap_setup_dump(handle, res, "") != SCAP_SUCCESS) { free(res); res = NULL; } + handle->refresh_proc_table_when_saving = tmp_refresh_proc_table_when_saving; + return res; } @@ -821,6 +927,18 @@ } } +int64_t scap_dump_ftell(scap_dumper_t *d) +{ + if(d->m_type == DT_FILE) + { + return gztell(d->m_f); + } + else + { + return (int64_t)d->m_targetbufcurpos - (int64_t)d->m_targetbuf; + } +} + void scap_dump_flush(scap_dumper_t *d) { if(d->m_type == DT_FILE) @@ -951,7 +1069,7 @@ tinfo.sid = -1; tinfo.clone_ts = 0; tinfo.tty = 0; - + while(((int32_t)block_length - (int32_t)totreadsize) >= 4) { // @@ -1313,6 +1431,7 @@ if(totreadsize > block_length) { ASSERT(false); + snprintf(handle->m_lasterr, SCAP_LASTERR_SIZE, "scap_read_proclist read more %lu than a block %u", totreadsize, block_length); return SCAP_FAILURE; } padding_len = block_length - totreadsize; @@ -1362,7 +1481,7 @@ } readsize = gzread(f, readbuf, block_length); - CHECK_READ_SIZE(readsize, block_length); + CHECK_READ_SIZE_WITH_FREE(readbuf, readsize, block_length); // // First pass, count the number of addresses @@ -1848,6 +1967,7 @@ if(totreadsize > block_length) { ASSERT(false); + snprintf(handle->m_lasterr, SCAP_LASTERR_SIZE, "scap_read_userlist read more %lu than a block %u", totreadsize, block_length); return SCAP_FAILURE; } padding_len = block_length - totreadsize; @@ -1949,6 +2069,7 @@ if(totreadsize > block_length) { ASSERT(false); + snprintf(handle->m_lasterr, SCAP_LASTERR_SIZE, "scap_read_fdlist read more %lu than a block %u", totreadsize, block_length); return SCAP_FAILURE; } padding_len = block_length - totreadsize; diff -Nru sysdig-0.16.0/userspace/libscap/scap_userlist.c sysdig-0.17.0/userspace/libscap/scap_userlist.c --- sysdig-0.16.0/userspace/libscap/scap_userlist.c 2017-05-08 09:30:22.000000000 +0000 +++ sysdig-0.17.0/userspace/libscap/scap_userlist.c 2017-07-24 16:13:14.000000000 +0000 @@ -82,8 +82,8 @@ if(handle->m_userlist->groups == NULL) { snprintf(handle->m_lasterr, SCAP_LASTERR_SIZE, "grouplist allocation failed(2)"); - free(handle->m_userlist); free(handle->m_userlist->users); + free(handle->m_userlist); return SCAP_FAILURE; } diff -Nru sysdig-0.16.0/userspace/libsinsp/chisel_api.cpp sysdig-0.17.0/userspace/libsinsp/chisel_api.cpp --- sysdig-0.16.0/userspace/libsinsp/chisel_api.cpp 2017-05-08 09:30:22.000000000 +0000 +++ sysdig-0.17.0/userspace/libsinsp/chisel_api.cpp 2017-07-24 16:13:14.000000000 +0000 @@ -109,6 +109,7 @@ lua_pushnumber(ls, *(double*)rawval); return 1; case PT_CHARBUF: + case PT_FSPATH: lua_pushlstring(ls, (char*)rawval, len); return 1; case PT_BYTEBUF: @@ -832,12 +833,12 @@ // lua_pushstring(ls, "env"); - vector* env = &(it->second.m_env); + const auto& env = it->second.get_env(); lua_newtable(ls); - for(j = 0; j < env->size(); j++) + for(j = 0; j < env.size(); j++) { lua_pushinteger(ls, j + 1); - lua_pushstring(ls, env->at(j).c_str()); + lua_pushstring(ls, env.at(j).c_str()); lua_settable(ls, -3); } lua_settable(ls,-3); diff -Nru sysdig-0.16.0/userspace/libsinsp/container.cpp sysdig-0.17.0/userspace/libsinsp/container.cpp --- sysdig-0.16.0/userspace/libsinsp/container.cpp 2017-05-08 09:30:22.000000000 +0000 +++ sysdig-0.17.0/userspace/libsinsp/container.cpp 2017-07-24 16:13:14.000000000 +0000 @@ -231,6 +231,7 @@ bool sinsp_container_manager::resolve_container(sinsp_threadinfo* tinfo, bool query_os_for_missing_info) { + ASSERT(tinfo); bool valid_id = false; sinsp_container_info container_info; @@ -355,27 +356,60 @@ // // systemd rkt // - pos = cgroup.find("machine-rkt\\x2d"); - if(pos != string::npos) + // rkt cgroups + // 1. /system.slice/k8s_d1efb75a-ad42-458e-af65-2b378f42173f.service/system.slice/redis.service + // 2. /machine.slice/machine-rkt\x2dc508ad4c\x2d7fa4\x2d4513\x2d9d53\x2d007628003805.scope/system.slice/redis.service + static const string COREOS_PODID_VAR = "container_uuid="; + static const string SYSTEMD_UUID_ARG = "--uuid="; + static const string SERVICE_SUFFIX = ".service"; + if(cgroup.rfind(SERVICE_SUFFIX) == cgroup.size() - SERVICE_SUFFIX.size()) { - string::size_type service_pos = cgroup.find("/", pos + 1); - if (service_pos == string::npos) - continue; - - string::size_type appname_pos = cgroup.find("/", service_pos + 1); - string::size_type appname_pos2 = cgroup.find(".", appname_pos + 1); - if (appname_pos == string::npos || appname_pos2 == string::npos) - continue; - rkt_appname = cgroup.substr(appname_pos + 1, appname_pos2 - appname_pos - 1); - if (rkt_appname.substr(0, 7) == "systemd" || rkt_appname.substr(0, 8) == "/machine") - continue; - rkt_podid = cgroup.substr(pos + sizeof("machine-rkt\\x2d") - 1, 48); - replace_in_place(rkt_podid, "\\x2d", "-"); - container_info.m_type = CT_RKT; - container_info.m_id = rkt_podid + ":" + rkt_appname; - container_info.m_name = rkt_appname; - valid_id = true; - break; + // check if there is a parent with pod uuid var + sinsp_threadinfo::visitor_func_t visitor = [&rkt_podid](sinsp_threadinfo* ptinfo) + { + for(const auto& env_var : ptinfo->get_env()) + { + auto container_uuid_pos = env_var.find(COREOS_PODID_VAR); + if(container_uuid_pos == 0) + { + rkt_podid = env_var.substr(COREOS_PODID_VAR.size()); + return false; + } + } + for(const auto& arg : ptinfo->m_args) + { + if(arg.find(SYSTEMD_UUID_ARG) != string::npos) + { + rkt_podid = arg.substr(SYSTEMD_UUID_ARG.size()); + return false; + } + } + return true; + }; + tinfo->traverse_parent_state(visitor); + + if(!rkt_podid.empty()) + { + auto last_slash = cgroup.find_last_of("/"); + rkt_appname = cgroup.substr(last_slash + 1, cgroup.size() - last_slash - SERVICE_SUFFIX.size() - 1); + + char image_manifest_path[SCAP_MAX_PATH_SIZE]; + snprintf(image_manifest_path, sizeof(image_manifest_path), "%s/var/lib/rkt/pods/run/%s/appsinfo/%s/manifest", scap_get_host_root(), rkt_podid.c_str(), rkt_appname.c_str()); + + // First lookup if the container exists in our table, otherwise only if we are live check if it has + // an entry in /var/lib/rkt. In capture mode only the former will be used. + // In live mode former will be used only if we already hit that container + if( m_containers.find(rkt_podid + ":" + rkt_appname) != m_containers.end() || + (query_os_for_missing_info && access(image_manifest_path, F_OK) == 0) + ) + { + container_info.m_type = CT_RKT; + container_info.m_id = rkt_podid + ":" + rkt_appname; + container_info.m_name = rkt_appname; + valid_id = true; + break; + } + } } } @@ -385,6 +419,8 @@ { // Try parsing from process root, // Strings used to detect rkt stage1-cores pods + // TODO: detecting stage1-coreos rkt pods in this way is deprecated + // we can remove it in the future static const string COREOS_PREFIX = "/opt/stage2/"; static const string COREOS_APP_SUFFIX = "/rootfs"; static const string COREOS_PODID_VAR = "container_uuid="; @@ -400,7 +436,7 @@ sinsp_threadinfo::visitor_func_t visitor = [&rkt_podid, &container_info, &rkt_appname, &valid_id] (sinsp_threadinfo *ptinfo) { - for(const auto& env_var : ptinfo->m_env) + for(const auto& env_var : ptinfo->get_env()) { auto container_uuid_pos = env_var.find(COREOS_PODID_VAR); if(container_uuid_pos == 0) @@ -494,7 +530,7 @@ ASSERT(false); } - m_containers.insert(std::make_pair(container_info.m_id, container_info)); + add_container(container_info); if(container_to_sinsp_event(container_to_json(container_info), &m_inspector->m_meta_evt)) { m_inspector->m_meta_evt_pending = true; diff -Nru sysdig-0.16.0/userspace/libsinsp/ctext.cpp sysdig-0.17.0/userspace/libsinsp/ctext.cpp --- sysdig-0.16.0/userspace/libsinsp/ctext.cpp 2017-05-08 09:30:22.000000000 +0000 +++ sysdig-0.17.0/userspace/libsinsp/ctext.cpp 2017-07-24 16:13:14.000000000 +0000 @@ -240,13 +240,14 @@ size_t found; string haystack; ctext_search res, *out; - string query = to_search_in->_query; if(!to_search_in) { return -1; } + string query = to_search_in->_query; + if(!new_pos_out) { search_copy(&res, to_search_in); diff -Nru sysdig-0.16.0/userspace/libsinsp/cursestable.cpp sysdig-0.17.0/userspace/libsinsp/cursestable.cpp --- sysdig-0.16.0/userspace/libsinsp/cursestable.cpp 2017-05-08 09:30:22.000000000 +0000 +++ sysdig-0.17.0/userspace/libsinsp/cursestable.cpp 2017-07-24 16:13:14.000000000 +0000 @@ -259,7 +259,7 @@ for(uint32_t j = 0;; j++) { string ss = line.substr(spos, spos + m_parent->m_screenw); -lo("2, %d %s\n", spos, ss.c_str()); +glogf("2, %d %s\n", spos, ss.c_str()); mvwprintw(m_tblwin, m_parent->m_screenh / 2 + off + j, diff -Nru sysdig-0.16.0/userspace/libsinsp/cursesui.cpp sysdig-0.17.0/userspace/libsinsp/cursesui.cpp --- sysdig-0.16.0/userspace/libsinsp/cursesui.cpp 2017-05-08 09:30:22.000000000 +0000 +++ sysdig-0.17.0/userspace/libsinsp/cursesui.cpp 2017-07-24 16:13:14.000000000 +0000 @@ -195,7 +195,7 @@ m_colors[CPU_IRQ] = ColorPair(COLOR_YELLOW,COLOR_BLACK); m_colors[CPU_SOFTIRQ] = ColorPair(COLOR_MAGENTA,COLOR_BLACK); m_colors[SPY_READ] = ColorPair(COLOR_RED,COLOR_BLACK); - m_colors[SPY_WRITE] = ColorPair(COLOR_BLUE,COLOR_BLACK); + m_colors[SPY_WRITE] = ColorPair(COLOR_CYAN,COLOR_BLACK); // // Populate the main menu entries diff -Nru sysdig-0.16.0/userspace/libsinsp/dumper.cpp sysdig-0.17.0/userspace/libsinsp/dumper.cpp --- sysdig-0.16.0/userspace/libsinsp/dumper.cpp 2017-05-08 09:30:22.000000000 +0000 +++ sysdig-0.17.0/userspace/libsinsp/dumper.cpp 2017-07-24 16:13:14.000000000 +0000 @@ -27,6 +27,7 @@ m_dumper = NULL; m_target_memory_buffer = NULL; m_target_memory_buffer_size = 0; + m_nevts = 0; } sinsp_dumper::sinsp_dumper(sinsp* inspector, uint8_t* target_memory_buffer, uint64_t target_memory_buffer_size) @@ -52,11 +53,6 @@ throw sinsp_exception("can't start event dump, inspector not opened yet"); } - if(threads_from_sinsp) - { - m_inspector->m_thread_manager->to_scap(); - } - if(m_target_memory_buffer) { m_dumper = scap_memory_dump_open(m_inspector->m_h, m_target_memory_buffer, m_target_memory_buffer_size); @@ -78,7 +74,45 @@ throw sinsp_exception(scap_getlasterr(m_inspector->m_h)); } + if(threads_from_sinsp) + { + m_inspector->m_thread_manager->dump_threads_to_file(m_dumper); + } + m_inspector->m_container_manager.dump_containers(m_dumper); + + m_nevts = 0; +} + +void sinsp_dumper::fdopen(int fd, bool compress, bool threads_from_sinsp) +{ + if(m_inspector->m_h == NULL) + { + throw sinsp_exception("can't start event dump, inspector not opened yet"); + } + + if(compress) + { + m_dumper = scap_dump_open_fd(m_inspector->m_h, fd, SCAP_COMPRESSION_GZIP, true); + } + else + { + m_dumper = scap_dump_open_fd(m_inspector->m_h, fd, SCAP_COMPRESSION_NONE, true); + } + + if(m_dumper == NULL) + { + throw sinsp_exception(scap_getlasterr(m_inspector->m_h)); + } + + if(threads_from_sinsp) + { + m_inspector->m_thread_manager->dump_threads_to_file(m_dumper); + } + + m_inspector->m_container_manager.dump_containers(m_dumper); + + m_nevts = 0; } void sinsp_dumper::close() @@ -90,6 +124,16 @@ } } +bool sinsp_dumper::is_open() +{ + return (m_dumper != NULL); +} + +bool sinsp_dumper::written_events() +{ + return m_nevts; +} + void sinsp_dumper::dump(sinsp_evt* evt) { if(m_dumper == NULL) @@ -106,6 +150,8 @@ { throw sinsp_exception(scap_getlasterr(m_inspector->m_h)); } + + m_nevts++; } uint64_t sinsp_dumper::written_bytes() @@ -124,6 +170,22 @@ return written_bytes; } +uint64_t sinsp_dumper::next_write_position() +{ + if(m_dumper == NULL) + { + return 0; + } + + int64_t position = scap_dump_ftell(m_dumper); + if(position == -1) + { + throw sinsp_exception("error getting offset"); + } + + return position; +} + void sinsp_dumper::flush() { if(m_dumper == NULL) diff -Nru sysdig-0.16.0/userspace/libsinsp/dumper.h sysdig-0.17.0/userspace/libsinsp/dumper.h --- sysdig-0.16.0/userspace/libsinsp/dumper.h 2017-05-08 09:30:22.000000000 +0000 +++ sysdig-0.17.0/userspace/libsinsp/dumper.h 2017-07-24 16:13:14.000000000 +0000 @@ -69,12 +69,27 @@ bool compress, bool threads_from_sinsp=false); + void fdopen(int fd, + bool compress, + bool threads_from_sinsp=false); + /*! \brief Closes the dump file. */ void close(); /*! + \brief Return whether or not the underling scap file has been + opened. + */ + bool is_open(); + + /*! + \brief Return the number of events dumped so far. + */ + bool written_events(); + + /*! \brief Return the current size of a tracefile. \return The current size of the dump file. @@ -82,6 +97,15 @@ uint64_t written_bytes(); /*! + \brief Return the starting position for the next write into + the file. (Under the covers, this uses gztell while + written_bytes uses gzoffset, which represent different values). + + \return The starting position for the next write. + */ + uint64_t next_write_position(); + + /*! \brief Flush all pending output into the file. */ void flush(); @@ -103,6 +127,7 @@ scap_dumper_t* m_dumper; uint8_t* m_target_memory_buffer; uint64_t m_target_memory_buffer_size; + uint64_t m_nevts; }; /*@}*/ diff -Nru sysdig-0.16.0/userspace/libsinsp/event.cpp sysdig-0.17.0/userspace/libsinsp/event.cpp --- sysdig-0.16.0/userspace/libsinsp/event.cpp 2017-05-08 09:30:22.000000000 +0000 +++ sysdig-0.17.0/userspace/libsinsp/event.cpp 2017-07-24 16:13:14.000000000 +0000 @@ -34,8 +34,12 @@ extern sinsp_evttables g_infotables; -#define SET_NUMERIC_FORMAT(resfmt, fmt, ustr, xstr) do { \ - if(fmt == ppm_print_format::PF_DEC) \ +#define SET_NUMERIC_FORMAT(resfmt, fmt, ostr, ustr, xstr) do { \ + if(fmt == ppm_print_format::PF_OCT) \ + { \ + resfmt = (char*)"%#" ostr; \ + } \ + else if(fmt == ppm_print_format::PF_DEC) \ { \ resfmt = (char*)"%" ustr; \ } \ @@ -1399,7 +1403,7 @@ { case PT_INT8: ASSERT(payload_len == sizeof(int8_t)); - SET_NUMERIC_FORMAT(prfmt, param_fmt, PRId8, PRIX8); + SET_NUMERIC_FORMAT(prfmt, param_fmt, PRIo8, PRId8, PRIX8); snprintf(&m_paramstr_storage[0], m_paramstr_storage.size(), @@ -1407,7 +1411,7 @@ break; case PT_INT16: ASSERT(payload_len == sizeof(int16_t)); - SET_NUMERIC_FORMAT(prfmt, param_fmt, PRId16, PRIX16); + SET_NUMERIC_FORMAT(prfmt, param_fmt, PRIo16, PRId16, PRIX16); snprintf(&m_paramstr_storage[0], m_paramstr_storage.size(), @@ -1415,7 +1419,7 @@ break; case PT_INT32: ASSERT(payload_len == sizeof(int32_t)); - SET_NUMERIC_FORMAT(prfmt, param_fmt, PRId32, PRIX32); + SET_NUMERIC_FORMAT(prfmt, param_fmt, PRIo32, PRId32, PRIX32); snprintf(&m_paramstr_storage[0], m_paramstr_storage.size(), @@ -1423,7 +1427,7 @@ break; case PT_INT64: ASSERT(payload_len == sizeof(int64_t)); - SET_NUMERIC_FORMAT(prfmt, param_fmt, PRId64, PRIX64); + SET_NUMERIC_FORMAT(prfmt, param_fmt, PRIo64, PRId64, PRIX64); snprintf(&m_paramstr_storage[0], m_paramstr_storage.size(), @@ -1467,7 +1471,7 @@ break; case PT_UINT8: ASSERT(payload_len == sizeof(uint8_t)); - SET_NUMERIC_FORMAT(prfmt, param_fmt, PRIu8, PRIX8); + SET_NUMERIC_FORMAT(prfmt, param_fmt, PRIo8, PRId8, PRIX8); snprintf(&m_paramstr_storage[0], m_paramstr_storage.size(), @@ -1475,7 +1479,7 @@ break; case PT_UINT16: ASSERT(payload_len == sizeof(uint16_t)); - SET_NUMERIC_FORMAT(prfmt, param_fmt, PRIu16, PRIX16); + SET_NUMERIC_FORMAT(prfmt, param_fmt, PRIo16, PRId16, PRIX16); snprintf(&m_paramstr_storage[0], m_paramstr_storage.size(), @@ -1483,7 +1487,7 @@ break; case PT_UINT32: ASSERT(payload_len == sizeof(uint32_t)); - SET_NUMERIC_FORMAT(prfmt, param_fmt, PRIu32, PRIX32); + SET_NUMERIC_FORMAT(prfmt, param_fmt, PRIo32, PRId32, PRIX32); snprintf(&m_paramstr_storage[0], m_paramstr_storage.size(), @@ -1519,7 +1523,7 @@ break; case PT_UINT64: ASSERT(payload_len == sizeof(uint64_t)); - SET_NUMERIC_FORMAT(prfmt, param_fmt, PRIu64, PRIX64); + SET_NUMERIC_FORMAT(prfmt, param_fmt, PRIo64, PRId64, PRIX64); snprintf(&m_paramstr_storage[0], m_paramstr_storage.size(), @@ -2356,6 +2360,7 @@ switch(m_fdinfo->m_type) { case SCAP_FD_FILE: + case SCAP_FD_FILE_V2: case SCAP_FD_DIRECTORY: cat->m_subcategory = SC_FILE; break; @@ -2376,6 +2381,7 @@ case SCAP_FD_UNSUPPORTED: case SCAP_FD_EVENTPOLL: case SCAP_FD_TIMERFD: + case SCAP_FD_NETLINK: cat->m_subcategory = SC_OTHER; break; case SCAP_FD_UNKNOWN: diff -Nru sysdig-0.16.0/userspace/libsinsp/event.h sysdig-0.17.0/userspace/libsinsp/event.h --- sysdig-0.16.0/userspace/libsinsp/event.h 2017-05-08 09:30:22.000000000 +0000 +++ sysdig-0.17.0/userspace/libsinsp/event.h 2017-07-24 16:13:14.000000000 +0000 @@ -31,11 +31,11 @@ /////////////////////////////////////////////////////////////////////////////// typedef enum filtercheck_field_flags { - EPF_NONE = 0, - EPF_FILTER_ONLY, ///< this field can only be used as a filter. - EPF_PRINT_ONLY, ///< this field can only be printed. - EPF_REQUIRES_ARGUMENT, ///< this field includes an argument, under the form 'property.argument'. - EPF_TABLE_ONLY, ///< this field is desgned to be used in a table and won't appear in the list created by sysdig's '-l'. + EPF_NONE = 0, + EPF_FILTER_ONLY = 1 << 0, ///< this field can only be used as a filter. + EPF_PRINT_ONLY = 1 << 1, ///< this field can only be printed. + EPF_REQUIRES_ARGUMENT = 1 << 2, ///< this field includes an argument, under the form 'property.argument'. + EPF_TABLE_ONLY = 1 << 3, ///< this field is desgned to be used in a table and won't appear in the list created by sysdig's '-l'. }filtercheck_field_flags; /*! @@ -45,7 +45,7 @@ { ppm_param_type m_type; ///< Field type. filtercheck_field_flags m_flags; ///< Field flags. - ppm_print_format m_print_format; ///< If this is a numeric field, this flag specifies if it should be rendered as decimal or hex. + ppm_print_format m_print_format; ///< If this is a numeric field, this flag specifies if it should be rendered as octal, decimal or hex. char m_name[64]; ///< Field name. char m_description[1024]; ///< Field description. }filtercheck_field_info; @@ -418,7 +418,7 @@ friend class sinsp_container_manager; friend class sinsp_table; friend class sinsp_cursesui; - friend class sisnp_baseliner; + friend class sinsp_baseliner; friend class sinsp_memory_dumper; friend class sinsp_memory_dumper_job; }; diff -Nru sysdig-0.16.0/userspace/libsinsp/fdinfo.cpp sysdig-0.17.0/userspace/libsinsp/fdinfo.cpp --- sysdig-0.16.0/userspace/libsinsp/fdinfo.cpp 2017-05-08 09:30:22.000000000 +0000 +++ sysdig-0.17.0/userspace/libsinsp/fdinfo.cpp 2017-07-24 16:13:14.000000000 +0000 @@ -53,6 +53,7 @@ { switch(m_type) { + case SCAP_FD_FILE_V2: case SCAP_FD_FILE: return CHAR_FD_FILE; case SCAP_FD_IPV4_SOCK: @@ -83,6 +84,8 @@ return CHAR_FD_INOTIFY; case SCAP_FD_TIMERFD: return CHAR_FD_TIMERFD; + case SCAP_FD_NETLINK: + return CHAR_FD_NETLINK; default: // ASSERT(false); return '?'; @@ -93,6 +96,7 @@ { switch(m_type) { + case SCAP_FD_FILE_V2: case SCAP_FD_FILE: return (char*)"file"; case SCAP_FD_DIRECTORY: @@ -117,6 +121,8 @@ return (char*)"inotify"; case SCAP_FD_TIMERFD: return (char*)"timerfd"; + case SCAP_FD_NETLINK: + return (char*)"netlink"; default: return (char*)""; } diff -Nru sysdig-0.16.0/userspace/libsinsp/fdinfo.h sysdig-0.17.0/userspace/libsinsp/fdinfo.h --- sysdig-0.16.0/userspace/libsinsp/fdinfo.h 2017-05-08 09:30:22.000000000 +0000 +++ sysdig-0.17.0/userspace/libsinsp/fdinfo.h 2017-07-24 16:13:14.000000000 +0000 @@ -42,6 +42,7 @@ #define CHAR_FD_EVENTPOLL 'l' #define CHAR_FD_INOTIFY 'i' #define CHAR_FD_TIMERFD 't' +#define CHAR_FD_NETLINK 'n' /** @defgroup state State management * A collection of classes to query process and FD state. @@ -218,7 +219,7 @@ */ bool is_file() { - return m_type == SCAP_FD_FILE; + return m_type == SCAP_FD_FILE || m_type == SCAP_FD_FILE_V2; } /*! @@ -323,6 +324,9 @@ FLAGS_IS_TRACER_FILE = (1 << 7), FLAGS_IS_TRACER_FD = (1 << 8), FLAGS_IS_NOT_TRACER_FD = (1 << 9), + FLAGS_IN_BASELINE_R = (1 << 10), + FLAGS_IN_BASELINE_RW = (1 << 11), + FLAGS_IN_BASELINE_OTHER = (1 << 12), }; void add_filename(const char* fullpath); @@ -367,6 +371,43 @@ return !is_role_client() && !is_role_server(); } + inline void set_inpipeline_r() + { + m_flags |= FLAGS_IN_BASELINE_R; + } + + inline void set_inpipeline_rw() + { + m_flags |= FLAGS_IN_BASELINE_RW; + } + + inline void set_inpipeline_other() + { + m_flags |= FLAGS_IN_BASELINE_OTHER; + } + + inline void reset_inpipeline() + { + m_flags &= ~FLAGS_IN_BASELINE_R; + m_flags &= ~FLAGS_IN_BASELINE_RW; + m_flags &= ~FLAGS_IN_BASELINE_OTHER; + } + + inline bool is_inpipeline_r() + { + return (m_flags & FLAGS_IN_BASELINE_R) == FLAGS_IN_BASELINE_R; + } + + inline bool is_inpipeline_rw() + { + return (m_flags & FLAGS_IN_BASELINE_RW) == FLAGS_IN_BASELINE_RW; + } + + inline bool is_inpipeline_other() + { + return (m_flags & FLAGS_IN_BASELINE_OTHER) == FLAGS_IN_BASELINE_OTHER; + } + T* m_usrstate; uint32_t m_flags; uint64_t m_ino; @@ -384,6 +425,7 @@ friend class sinsp_filter_check_event; friend class lua_cbacks; friend class sinsp_proto_detector; + friend class sinsp_baseliner; }; /*@}*/ diff -Nru sysdig-0.16.0/userspace/libsinsp/filterchecks.cpp sysdig-0.17.0/userspace/libsinsp/filterchecks.cpp --- sysdig-0.16.0/userspace/libsinsp/filterchecks.cpp 2017-05-08 09:30:22.000000000 +0000 +++ sysdig-0.17.0/userspace/libsinsp/filterchecks.cpp 2017-07-24 16:13:14.000000000 +0000 @@ -1340,7 +1340,8 @@ {PT_UINT64, EPF_TABLE_ONLY, PF_DEC, "thread.vmsize.b", "For the process main thread, this is the total virtual memory for the process (in bytes). For the other threads, this field is zero."}, {PT_UINT64, EPF_TABLE_ONLY, PF_DEC, "thread.vmrss.b", "For the process main thread, this is the resident non-swapped memory for the process (in bytes). For the other threads, this field is zero."}, {PT_INT64, EPF_NONE, PF_ID, "proc.sid", "the session id of the process generating the event."}, - {PT_CHARBUF, EPF_NONE, PF_NA, "proc.sname", "the name of the current process's session leader. This is either the process with pid=proc.sid or the eldest ancestor that has the same sid as the current process."} + {PT_CHARBUF, EPF_NONE, PF_NA, "proc.sname", "the name of the current process's session leader. This is either the process with pid=proc.sid or the eldest ancestor that has the same sid as the current process."}, + {PT_INT32, EPF_NONE, PF_ID, "proc.tty", "The controlling terminal of the process. 0 for processes without a terminal."} }; sinsp_filter_check_thread::sinsp_filter_check_thread() @@ -1661,6 +1662,8 @@ return (uint8_t*)m_tstr.c_str(); } } + case TYPE_TTY: + return (uint8_t*)&tinfo->m_tty; case TYPE_NAME: m_tstr = tinfo->get_comm(); *len = m_tstr.size(); @@ -1693,11 +1696,12 @@ m_tstr.clear(); uint32_t j; - uint32_t nargs = (uint32_t)tinfo->m_env.size(); + const auto& env = tinfo->get_env(); + uint32_t nargs = (uint32_t)env.size(); for(j = 0; j < nargs; j++) { - m_tstr += tinfo->m_env[j]; + m_tstr += env[j]; if(j < nargs -1) { m_tstr += ' '; @@ -3658,6 +3662,7 @@ if(fdinfo != NULL) { if(fdinfo->m_type == SCAP_FD_FILE || + fdinfo->m_type == SCAP_FD_FILE_V2 || fdinfo->m_type == SCAP_FD_DIRECTORY) { return extract_error_count(evt, len); @@ -3726,6 +3731,7 @@ if(fdinfo != NULL) { if(!(fdinfo->m_type == SCAP_FD_FILE || + fdinfo->m_type == SCAP_FD_FILE_V2 || fdinfo->m_type == SCAP_FD_DIRECTORY || fdinfo->m_type == SCAP_FD_IPV4_SOCK || fdinfo->m_type == SCAP_FD_IPV6_SOCK || @@ -3814,7 +3820,7 @@ case TYPE_BUFLEN_FILE: if(evt->m_fdinfo && evt->get_category() & EC_IO_BASE) { - if(evt->m_fdinfo->m_type == SCAP_FD_FILE) + if(evt->m_fdinfo->m_type == SCAP_FD_FILE || evt->m_fdinfo->m_type == SCAP_FD_FILE_V2) { return extract_buflen(evt); } @@ -3824,7 +3830,7 @@ case TYPE_BUFLEN_FILE_IN: if(evt->m_fdinfo && evt->get_category() == EC_IO_READ) { - if(evt->m_fdinfo->m_type == SCAP_FD_FILE) + if(evt->m_fdinfo->m_type == SCAP_FD_FILE || evt->m_fdinfo->m_type == SCAP_FD_FILE_V2) { return extract_buflen(evt); } @@ -3834,7 +3840,7 @@ case TYPE_BUFLEN_FILE_OUT: if(evt->m_fdinfo && evt->get_category() == EC_IO_WRITE) { - if(evt->m_fdinfo->m_type == SCAP_FD_FILE) + if(evt->m_fdinfo->m_type == SCAP_FD_FILE || evt->m_fdinfo->m_type == SCAP_FD_FILE_V2) { return extract_buflen(evt); } @@ -5452,7 +5458,7 @@ try { m_argid = sinsp_numparser::parsed32(numstr); - } catch (sinsp_exception e) + } catch (sinsp_exception &e) { if(strstr(e.what(), "is not a valid number") == NULL) { diff -Nru sysdig-0.16.0/userspace/libsinsp/filterchecks.h sysdig-0.17.0/userspace/libsinsp/filterchecks.h --- sysdig-0.16.0/userspace/libsinsp/filterchecks.h 2017-05-08 09:30:22.000000000 +0000 +++ sysdig-0.17.0/userspace/libsinsp/filterchecks.h 2017-07-24 16:13:14.000000000 +0000 @@ -370,6 +370,7 @@ TYPE_THREAD_VMRSS_B = 39, TYPE_SID = 40, TYPE_SNAME = 41, + TYPE_TTY = 42, }; sinsp_filter_check_thread(); diff -Nru sysdig-0.16.0/userspace/libsinsp/filter.cpp sysdig-0.17.0/userspace/libsinsp/filter.cpp --- sysdig-0.16.0/userspace/libsinsp/filter.cpp 2017-05-08 09:30:22.000000000 +0000 +++ sysdig-0.17.0/userspace/libsinsp/filter.cpp 2017-07-24 16:13:14.000000000 +0000 @@ -561,7 +561,8 @@ { return *(int8_t *)rawval; } - else if(finfo->m_print_format == PF_HEX) + else if(finfo->m_print_format == PF_OCT || + finfo->m_print_format == PF_HEX) { return rawval_to_string(rawval, finfo, len); } @@ -577,7 +578,8 @@ { return *(int16_t *)rawval; } - else if(finfo->m_print_format == PF_HEX) + else if(finfo->m_print_format == PF_OCT || + finfo->m_print_format == PF_HEX) { return rawval_to_string(rawval, finfo, len); } @@ -593,7 +595,8 @@ { return *(int32_t *)rawval; } - else if(finfo->m_print_format == PF_HEX) + else if(finfo->m_print_format == PF_OCT || + finfo->m_print_format == PF_HEX) { return rawval_to_string(rawval, finfo, len); } @@ -622,7 +625,8 @@ { return *(uint8_t *)rawval; } - else if(finfo->m_print_format == PF_HEX) + else if(finfo->m_print_format == PF_OCT || + finfo->m_print_format == PF_HEX) { return rawval_to_string(rawval, finfo, len); } @@ -639,7 +643,8 @@ { return *(uint16_t *)rawval; } - else if(finfo->m_print_format == PF_HEX) + else if(finfo->m_print_format == PF_OCT || + finfo->m_print_format == PF_HEX) { return rawval_to_string(rawval, finfo, len); } @@ -655,7 +660,8 @@ { return *(uint32_t *)rawval; } - else if(finfo->m_print_format == PF_HEX) + else if(finfo->m_print_format == PF_OCT || + finfo->m_print_format == PF_HEX) { return rawval_to_string(rawval, finfo, len); } @@ -675,6 +681,7 @@ } else if( finfo->m_print_format == PF_10_PADDED_DEC || + finfo->m_print_format == PF_OCT || finfo->m_print_format == PF_HEX) { return rawval_to_string(rawval, finfo, len); @@ -694,6 +701,7 @@ return Json::Value((bool)(*(uint32_t*)rawval != 0)); case PT_CHARBUF: + case PT_FSPATH: case PT_BYTEBUF: case PT_IPV4ADDR: return rawval_to_string(rawval, finfo, len); @@ -714,8 +722,12 @@ switch(finfo->m_type) { case PT_INT8: - if(finfo->m_print_format == PF_DEC || - finfo->m_print_format == PF_ID) + if(finfo->m_print_format == PF_OCT) + { + prfmt = (char*)"%" PRIo8; + } + else if(finfo->m_print_format == PF_DEC || + finfo->m_print_format == PF_ID) { prfmt = (char*)"%" PRId8; } @@ -734,8 +746,12 @@ prfmt, *(int8_t *)rawval); return m_getpropertystr_storage; case PT_INT16: - if(finfo->m_print_format == PF_DEC || - finfo->m_print_format == PF_ID) + if(finfo->m_print_format == PF_OCT) + { + prfmt = (char*)"%" PRIo16; + } + else if(finfo->m_print_format == PF_DEC || + finfo->m_print_format == PF_ID) { prfmt = (char*)"%" PRId16; } @@ -754,8 +770,12 @@ prfmt, *(int16_t *)rawval); return m_getpropertystr_storage; case PT_INT32: - if(finfo->m_print_format == PF_DEC || - finfo->m_print_format == PF_ID) + if(finfo->m_print_format == PF_OCT) + { + prfmt = (char*)"%" PRIo32; + } + else if(finfo->m_print_format == PF_DEC || + finfo->m_print_format == PF_ID) { prfmt = (char*)"%" PRId32; } @@ -776,8 +796,12 @@ case PT_INT64: case PT_PID: case PT_ERRNO: - if(finfo->m_print_format == PF_DEC || - finfo->m_print_format == PF_ID) + if(finfo->m_print_format == PF_OCT) + { + prfmt = (char*)"%" PRIo64; + } + else if(finfo->m_print_format == PF_DEC || + finfo->m_print_format == PF_ID) { prfmt = (char*)"%" PRId64; } @@ -800,8 +824,12 @@ return m_getpropertystr_storage; case PT_L4PROTO: // This can be resolved in the future case PT_UINT8: - if(finfo->m_print_format == PF_DEC || - finfo->m_print_format == PF_ID) + if(finfo->m_print_format == PF_OCT) + { + prfmt = (char*)"%" PRIo8; + } + else if(finfo->m_print_format == PF_DEC || + finfo->m_print_format == PF_ID) { prfmt = (char*)"%" PRIu8; } @@ -821,8 +849,12 @@ return m_getpropertystr_storage; case PT_PORT: // This can be resolved in the future case PT_UINT16: - if(finfo->m_print_format == PF_DEC || - finfo->m_print_format == PF_ID) + if(finfo->m_print_format == PF_OCT) + { + prfmt = (char*)"%" PRIo16; + } + else if(finfo->m_print_format == PF_DEC || + finfo->m_print_format == PF_ID) { prfmt = (char*)"%" PRIu16; } @@ -841,8 +873,12 @@ prfmt, *(uint16_t *)rawval); return m_getpropertystr_storage; case PT_UINT32: - if(finfo->m_print_format == PF_DEC || - finfo->m_print_format == PF_ID) + if(finfo->m_print_format == PF_OCT) + { + prfmt = (char*)"%" PRIo32; + } + else if(finfo->m_print_format == PF_DEC || + finfo->m_print_format == PF_ID) { prfmt = (char*)"%" PRIu32; } @@ -863,8 +899,12 @@ case PT_UINT64: case PT_RELTIME: case PT_ABSTIME: - if(finfo->m_print_format == PF_DEC || - finfo->m_print_format == PF_ID) + if(finfo->m_print_format == PF_OCT) + { + prfmt = (char*)"%" PRIo64; + } + else if(finfo->m_print_format == PF_DEC || + finfo->m_print_format == PF_ID) { prfmt = (char*)"%" PRIu64; } @@ -887,6 +927,7 @@ prfmt, *(uint64_t *)rawval); return m_getpropertystr_storage; case PT_CHARBUF: + case PT_FSPATH: return (char*)rawval; case PT_BYTEBUF: if(rawval[len] == 0) diff -Nru sysdig-0.16.0/userspace/libsinsp/marathon_component.cpp sysdig-0.17.0/userspace/libsinsp/marathon_component.cpp --- sysdig-0.16.0/userspace/libsinsp/marathon_component.cpp 2017-05-08 09:30:22.000000000 +0000 +++ sysdig-0.17.0/userspace/libsinsp/marathon_component.cpp 2017-07-24 16:13:14.000000000 +0000 @@ -351,12 +351,16 @@ return 0; } -void marathon_group::print() const +void marathon_group::print(int indent) const { + for(int j = 0; j < indent; ++j) + { + std::cout << " "; + } std::cout << get_id() << std::endl; for(auto& group : m_groups) { - group.second->print(); + group.second->print(indent+2); } } diff -Nru sysdig-0.16.0/userspace/libsinsp/marathon_component.h sysdig-0.17.0/userspace/libsinsp/marathon_component.h --- sysdig-0.16.0/userspace/libsinsp/marathon_component.h 2017-05-08 09:30:22.000000000 +0000 +++ sysdig-0.17.0/userspace/libsinsp/marathon_component.h 2017-07-24 16:13:14.000000000 +0000 @@ -109,7 +109,7 @@ bool remove(const std::string& id); - void print() const; + void print(int indent = 0) const; const std::string& get_framework_id() const; void set_framework_id(const std::string& id); diff -Nru sysdig-0.16.0/userspace/libsinsp/parsers.cpp sysdig-0.17.0/userspace/libsinsp/parsers.cpp --- sysdig-0.16.0/userspace/libsinsp/parsers.cpp 2017-05-08 09:30:22.000000000 +0000 +++ sysdig-0.17.0/userspace/libsinsp/parsers.cpp 2017-07-24 16:13:14.000000000 +0000 @@ -201,7 +201,7 @@ // sinsp_fdinfo_t* fdinfo = evt->m_fdinfo; - if(fdinfo == NULL) + if(fdinfo == NULL && evt->m_tinfo != nullptr) { fdinfo = evt->m_tinfo->get_fd(evt->m_tinfo->m_lastevent_fd); evt->m_fdinfo = fdinfo; @@ -275,7 +275,7 @@ store_event(evt); break; case PPME_SYSCALL_WRITE_E: - if(!m_inspector->m_is_dumping) + if(!m_inspector->m_is_dumping && evt->m_tinfo != nullptr) { evt->m_fdinfo = evt->m_tinfo->get_fd(evt->m_tinfo->m_lastevent_fd); if(evt->m_fdinfo) @@ -1832,6 +1832,10 @@ string sdir; ASSERT(evt->m_tinfo); + if(evt->m_tinfo == nullptr) + { + return; + } // // Load the enter event so we can access its arguments @@ -1914,7 +1918,7 @@ } else { - fdi.m_type = SCAP_FD_FILE; + fdi.m_type = SCAP_FD_FILE_V2; } fdi.m_openflags = flags; @@ -2008,10 +2012,13 @@ fdi.m_sockinfo.m_ipv4info.m_fields.m_l4proto = SCAP_L4_ICMP; } } + else if (domain == PPM_AF_NETLINK) + { + fdi.m_type = SCAP_FD_NETLINK; + } else { - if(domain != 16 && // AF_NETLINK, used by processes to talk to the kernel - domain != 10 && // IPv6 + if( domain != 10 && // IPv6 domain != 17) // AF_PACKET, used for packet capture { // @@ -2021,6 +2028,17 @@ } } + if(fdi.m_type == SCAP_FD_UNKNOWN) + { + g_logger.log("Unknown fd fd=" + to_string(fd) + + " domain=" + to_string(domain) + + " type=" + to_string(type) + + " protocol=" + to_string(protocol) + + " pid=" + to_string(evt->m_tinfo->m_pid) + + " comm=" + evt->m_tinfo->m_comm, + sinsp_logger::SEV_DEBUG); + } + #ifndef INCLUDE_UNKNOWN_SOCKET_FDS if(fdi.m_type == SCAP_FD_UNKNOWN) { @@ -2061,6 +2079,11 @@ return; } + if(evt->m_tinfo == nullptr) + { + return; + } + // // Load the enter event so we can access its arguments // @@ -2496,7 +2519,7 @@ // if(retval >= 0) { - if(evt->m_fdinfo == NULL) + if(evt->m_fdinfo == NULL || evt->m_tinfo == nullptr) { return; } @@ -2597,6 +2620,12 @@ return; } + if(evt->m_tinfo == nullptr) + { + // There is nothing we can do here if tinfo is missing + return; + } + parinfo = evt->get_param(1); ASSERT(parinfo->m_len == sizeof(int64_t)); fd1 = *(int64_t *)parinfo->m_val; @@ -3392,7 +3421,7 @@ // // Find the fd name // - if(evt->m_fdinfo == NULL) + if(evt->m_fdinfo == NULL || evt->m_tinfo == nullptr) { return; } @@ -3506,6 +3535,11 @@ sinsp_evt_param *parinfo; int64_t retval; + if(evt->m_tinfo == nullptr) + { + return; + } + // // Extract the return value // @@ -3573,6 +3607,11 @@ retval = *(int64_t *)parinfo->m_val; ASSERT(parinfo->m_len == sizeof(int64_t)); + if(evt->m_tinfo == nullptr) + { + return; + } + // // Check if the syscall was successful // @@ -3637,6 +3676,11 @@ retval = *(int64_t *)parinfo->m_val; ASSERT(parinfo->m_len == sizeof(int64_t)); + if(evt->m_tinfo == nullptr) + { + return; + } + // // Check if the syscall was successful // @@ -3665,6 +3709,11 @@ uint8_t resource; int64_t curval; + if(evt->m_tinfo == nullptr) + { + return; + } + // // Extract the return value // @@ -4212,7 +4261,7 @@ { auto parinfo = evt->get_param(0); auto retval = *(int64_t *)parinfo->m_val; - if(retval == 0) + if(retval == 0 && evt->m_tinfo != nullptr) { const char* resolved_path; auto path = evt->get_param_as_str(1, &resolved_path); diff -Nru sysdig-0.16.0/userspace/libsinsp/parsers.h sysdig-0.17.0/userspace/libsinsp/parsers.h --- sysdig-0.16.0/userspace/libsinsp/parsers.h 2017-05-08 09:30:22.000000000 +0000 +++ sysdig-0.17.0/userspace/libsinsp/parsers.h 2017-07-24 16:13:14.000000000 +0000 @@ -183,6 +183,6 @@ friend class sinsp_analyzer; friend class sinsp_analyzer_fd_listener; friend class sinsp_protodecoder; - friend class sisnp_baseliner; + friend class sinsp_baseliner; friend class sinsp_container_manager; }; diff -Nru sysdig-0.16.0/userspace/libsinsp/sinsp.cpp sysdig-0.17.0/userspace/libsinsp/sinsp.cpp --- sysdig-0.16.0/userspace/libsinsp/sinsp.cpp 2017-05-08 09:30:22.000000000 +0000 +++ sysdig-0.17.0/userspace/libsinsp/sinsp.cpp 2017-07-24 16:13:14.000000000 +0000 @@ -95,6 +95,7 @@ m_max_n_proc_socket_lookups = 0; m_snaplen = DEFAULT_SNAPLEN; m_buffer_format = sinsp_evt::PF_NORMAL; + m_input_fd = 0; m_isdebug_enabled = false; m_isfatfile_enabled = false; m_hostname_and_port_resolution_enabled = false; @@ -327,9 +328,10 @@ } // - // Rewind and consume the exact number of events + // Rewind, reset the event count, and consume the exact number of events // scap_fseek(m_h, off); + scap_event_reset_count(m_h); for(uint32_t j = 0; j < ncnt; j++) { sinsp_evt* tevt; @@ -522,20 +524,10 @@ return errstr; } -void sinsp::open(string filename) +void sinsp::open_int() { char error[SCAP_LASTERR_SIZE] = {0}; - if(filename == "") - { - open(); - return; - } - - m_input_filename = filename; - - g_logger.log("starting offline capture"); - // // Reset the thread manager // @@ -547,7 +539,15 @@ m_mode = SCAP_MODE_CAPTURE; scap_open_args oargs; oargs.mode = SCAP_MODE_CAPTURE; - oargs.fname = filename.c_str(); + if(m_input_fd != 0) + { + oargs.fd = m_input_fd; + } + else + { + oargs.fd = 0; + oargs.fname = m_input_filename.c_str(); + } oargs.proc_callback = NULL; oargs.proc_callback_context = NULL; oargs.import_users = m_import_users; @@ -567,16 +567,48 @@ throw sinsp_exception(error); } - m_filesize = get_file_size(filename, error); - - if(m_filesize < 0) + if(m_input_fd != 0) { - throw sinsp_exception(error); + // We can't get a reliable filesize + m_filesize = 0; + } + else + { + m_filesize = get_file_size(m_input_filename, error); + + if(m_filesize < 0) + { + throw sinsp_exception(error); + } } init(); } +void sinsp::open(string filename) +{ + if(filename == "") + { + open(); + return; + } + + m_input_filename = filename; + + g_logger.log("starting offline capture"); + + open_int(); +} + +void sinsp::fdopen(int fd) +{ + m_input_fd = fd; + + g_logger.log("starting offline capture"); + + open_int(); +} + void sinsp::close() { if(m_h) @@ -881,7 +913,7 @@ // m_file_start_offset = filepos; close(); - open(m_input_filename); + open_int(); // // Set again the backuped settings @@ -899,7 +931,6 @@ sinsp_evt* evt; int32_t res; - // // Check if there are fake cpu events to events // @@ -1695,6 +1726,13 @@ double sinsp::get_read_progress() { + if(m_input_fd != 0) + { + // We can't get a reliable file size, so we can't get + // any reliable progress + return 0; + } + if(m_filesize == -1) { throw sinsp_exception(scap_getlasterr(m_h)); diff -Nru sysdig-0.16.0/userspace/libsinsp/sinsp.h sysdig-0.17.0/userspace/libsinsp/sinsp.h --- sysdig-0.16.0/userspace/libsinsp/sinsp.h 2017-05-08 09:30:22.000000000 +0000 +++ sysdig-0.17.0/userspace/libsinsp/sinsp.h 2017-07-24 16:13:14.000000000 +0000 @@ -253,6 +253,16 @@ */ void open(string filename); + /*! + \brief Start an event capture from a file descriptor. + + \param fd the file descriptor + + @throws a sinsp_exception containing the error string is thrown in case + of failure. + */ + void fdopen(int fd); + void open_nodriver(); /*! @@ -763,6 +773,7 @@ private: #endif + void open_int(); void init(); void import_thread_table(); void import_ifaddr_list(); @@ -834,11 +845,20 @@ void restart_capture_at_filepos(uint64_t filepos); + void fseek(uint64_t filepos) + { + scap_fseek(m_h, filepos); + } + scap_t* m_h; uint32_t m_nevts; int64_t m_filesize; scap_mode_t m_mode; + + // If non-zero, reading from this fd and m_input_filename contains "fd + // ". Otherwise, reading from m_input_filename. + int m_input_fd; string m_input_filename; bool m_isdebug_enabled; bool m_isfatfile_enabled; @@ -1034,7 +1054,7 @@ friend class sinsp_filter_check_k8s; friend class sinsp_filter_check_mesos; friend class sinsp_filter_check_evtin; - friend class sisnp_baseliner; + friend class sinsp_baseliner; friend class sinsp_memory_dumper; friend class sinsp_network_interfaces; diff -Nru sysdig-0.16.0/userspace/libsinsp/sinsp_int.h sysdig-0.17.0/userspace/libsinsp/sinsp_int.h --- sysdig-0.16.0/userspace/libsinsp/sinsp_int.h 2017-05-08 09:30:22.000000000 +0000 +++ sysdig-0.17.0/userspace/libsinsp/sinsp_int.h 2017-07-24 16:13:14.000000000 +0000 @@ -98,7 +98,7 @@ // The logger // extern sinsp_logger g_logger; -#define lo g_logger.format +#define glogf g_logger.format // // Prototype of the callback invoked by the thread table when a thread is diff -Nru sysdig-0.16.0/userspace/libsinsp/socket_collector.h sysdig-0.17.0/userspace/libsinsp/socket_collector.h --- sysdig-0.16.0/userspace/libsinsp/socket_collector.h 2017-05-08 09:30:22.000000000 +0000 +++ sysdig-0.17.0/userspace/libsinsp/socket_collector.h 2017-07-24 16:13:14.000000000 +0000 @@ -60,7 +60,8 @@ handler->enable(); return; } - g_logger.log("Socket collector: attempt to enable non-existing handler: " + handler->get_id()); + g_logger.log("Socket collector: attempt to enable non-existing handler.", + sinsp_logger::SEV_ERROR); } int get_socket(std::shared_ptr handler) const diff -Nru sysdig-0.16.0/userspace/libsinsp/socket_handler.h sysdig-0.17.0/userspace/libsinsp/socket_handler.h --- sysdig-0.16.0/userspace/libsinsp/socket_handler.h 2017-05-08 09:30:22.000000000 +0000 +++ sysdig-0.17.0/userspace/libsinsp/socket_handler.h 2017-07-24 16:13:14.000000000 +0000 @@ -368,11 +368,15 @@ //g_logger.log("Socket handler (" + m_id + ") received=" + std::to_string(rec) + // "\n\n" + data + "\n\n", sinsp_logger::SEV_TRACE); } - if(++counter > 100) + + // To prevent reads from entirely stalling (like in gigantic k8s + // environments), give up after reading 30mb. + ++counter; + if(processed > 30 * 1024 * 1024) { throw sinsp_exception("Socket handler (" + m_id + "): " - "unable to retrieve data from " + m_url.to_string(false) + m_path + - " (" + std::to_string(counter) + " attempts)"); + "read more than 30MB of data from " + m_url.to_string(false) + m_path + + " (" + std::to_string(processed) + " bytes, " + std::to_string(counter) + " reads). Giving up"); } else { usleep(10000); } } while(!m_msg_completed); diff -Nru sysdig-0.16.0/userspace/libsinsp/threadinfo.cpp sysdig-0.17.0/userspace/libsinsp/threadinfo.cpp --- sysdig-0.16.0/userspace/libsinsp/threadinfo.cpp 2017-05-08 09:30:22.000000000 +0000 +++ sysdig-0.17.0/userspace/libsinsp/threadinfo.cpp 2017-07-24 16:13:14.000000000 +0000 @@ -88,6 +88,7 @@ m_lastevent_data = NULL; m_parent_loop_detected = false; m_tty = 0; + m_blprogram = NULL; } sinsp_threadinfo::~sinsp_threadinfo() @@ -296,6 +297,10 @@ newfdi->set_role_server(); } break; + case SCAP_FD_FILE_V2: + newfdi->m_openflags = fdi->info.regularinfo.open_flags; + newfdi->m_name = fdi->info.regularinfo.fname; + break; case SCAP_FD_FIFO: case SCAP_FD_FILE: case SCAP_FD_DIRECTORY: @@ -305,6 +310,7 @@ case SCAP_FD_EVENT: case SCAP_FD_INOTIFY: case SCAP_FD_TIMERFD: + case SCAP_FD_NETLINK: newfdi->m_name = fdi->info.fname; if(newfdi->m_name == USER_EVT_DEVICE_NAME) @@ -359,8 +365,11 @@ m_comm = pi->comm; m_exe = pi->exe; set_args(pi->args, pi->args_len); - set_env(pi->env, pi->env_len); - set_cwd(pi->cwd, (uint32_t)strlen(pi->cwd)); + if(is_main_thread()) + { + set_env(pi->env, pi->env_len); + set_cwd(pi->cwd, (uint32_t)strlen(pi->cwd)); + } m_flags |= pi->flags; m_flags |= PPM_CL_ACTIVE; // Assume that all the threads coming from /proc are real, active threads m_fdtable.clear(); @@ -492,9 +501,31 @@ } } -string sinsp_threadinfo::get_env(const string& name) const +const vector& sinsp_threadinfo::get_env() +{ + if(is_main_thread()) + { + return m_env; + } + else + { + auto mtinfo = get_main_thread(); + if(mtinfo != nullptr) + { + return mtinfo->get_env(); + } + else + { + // it should never happen but provide a safe fallback just in case + ASSERT(false); + return m_env; + } + } +} + +string sinsp_threadinfo::get_env(const string& name) { - for(const auto& env_var : m_env) + for(const auto& env_var : get_env()) { if((env_var.length() > name.length()) && (env_var.substr(0, name.length()) == name)) { @@ -868,19 +899,58 @@ } #endif +inline void scpy(char* dst, const char* src, uint32_t maxlen) +{ + if(maxlen == 0) + { + return; + } + + while(true) + { + if(maxlen == 1) + { + *dst = 0; + return; + } + + if(*src == 0) + { + *dst = 0; + return; + } + + *(dst++) = *(src++); + maxlen--; + } +} + void sinsp_threadinfo::args_to_scap(scap_threadinfo* sctinfo) { uint32_t alen = SCAP_MAX_ARGS_SIZE; uint32_t tlen = 0; char* dst = sctinfo->args; - for(auto a : m_args) + for(auto it = m_args.begin(); it != m_args.end(); ++it) { - uint32_t len = a.size() + 1; + uint32_t len = it->size() + 1; + + scpy(dst + tlen, it->c_str(), alen); - strncpy(dst + tlen, a.c_str(), alen); - tlen += len; - alen -= len; + if(len >= alen) + { + // + // We saturated the args buffer. Null terminate it and return + // + sctinfo->args[SCAP_MAX_ARGS_SIZE - 1] = 0; + sctinfo->args_len = SCAP_MAX_ARGS_SIZE; + return; + } + else + { + tlen += len; + alen -= len; + } } sctinfo->args_len = tlen; @@ -892,13 +962,26 @@ uint32_t tlen = 0; char* dst = sctinfo->env; - for(auto a : m_env) + for(auto it = m_env.begin(); it != m_env.end(); ++it) { - uint32_t len = a.size() + 1; + uint32_t len = it->size() + 1; - strncpy(dst + tlen, a.c_str(), alen); - tlen += len; - alen -= len; + scpy(dst + tlen, it->c_str(), alen); + + if(len >= alen) + { + // + // We saturated the args buffer. Null terminate it and return + // + sctinfo->env[SCAP_MAX_ENV_SIZE - 1] = 0; + sctinfo->env_len = SCAP_MAX_ENV_SIZE; + return; + } + else + { + tlen += len; + alen -= len; + } } sctinfo->env_len = tlen; @@ -910,14 +993,27 @@ uint32_t tlen = 0; char* dst = sctinfo->cgroups; - for(auto cg : m_cgroups) + for(auto it = m_cgroups.begin(); it != m_cgroups.end(); ++it) { - string a = cg.first + "=" + cg.second; + string a = it->first + "=" + it->second; uint32_t len = a.size() + 1; - strncpy(dst + tlen, a.c_str(), alen); - tlen += len; - alen -= len; + scpy(dst + tlen, a.c_str(), alen); + + if(len >= alen) + { + // + // We saturated the args buffer. Null terminate it and return + // + sctinfo->cgroups[SCAP_MAX_CGROUPS_SIZE - 1] = 0; + sctinfo->cgroups_len = SCAP_MAX_CGROUPS_SIZE; + return; + } + else + { + tlen += len; + alen -= len; + } } sctinfo->cgroups_len = tlen; @@ -959,6 +1055,10 @@ dst->info.unix_socket_info.destination = src->m_sockinfo.m_unixinfo.m_fields.m_dest; strncpy(dst->info.unix_socket_info.fname, src->m_name.c_str(), SCAP_MAX_PATH_SIZE); break; + case SCAP_FD_FILE_V2: + dst->info.regularinfo.open_flags = src->m_openflags; + strncpy(dst->info.regularinfo.fname, src->m_name.c_str(), SCAP_MAX_PATH_SIZE); + break; case SCAP_FD_FIFO: case SCAP_FD_FILE: case SCAP_FD_DIRECTORY: @@ -968,6 +1068,7 @@ case SCAP_FD_EVENT: case SCAP_FD_INOTIFY: case SCAP_FD_TIMERFD: + case SCAP_FD_NETLINK: strncpy(dst->info.fname, src->m_name.c_str(), SCAP_MAX_PATH_SIZE); break; default: @@ -1242,89 +1343,186 @@ #endif } -void sinsp_thread_manager::to_scap() +void sinsp_thread_manager::free_dump_fdinfos(vector* fdinfos_to_free) { - scap_proc_free_table(m_inspector->m_h); + for(uint32_t j = 0; j < fdinfos_to_free->size(); j++) + { + free(fdinfos_to_free->at(j)); + } + + fdinfos_to_free->clear(); +} + +void sinsp_thread_manager::thread_to_scap(sinsp_threadinfo& tinfo, scap_threadinfo* sctinfo) +{ + // + // Fill in the thread data + // + sctinfo->tid = tinfo.m_tid; + sctinfo->pid = tinfo.m_pid; + sctinfo->ptid = tinfo.m_ptid; + sctinfo->sid = tinfo.m_sid; + + strncpy(sctinfo->comm, tinfo.m_comm.c_str(), SCAP_MAX_PATH_SIZE); + strncpy(sctinfo->exe, tinfo.m_exe.c_str(), SCAP_MAX_PATH_SIZE); + tinfo.args_to_scap(sctinfo); + tinfo.env_to_scap(sctinfo); + string tcwd = (tinfo.m_cwd == "")? "/": tinfo.m_cwd; + strncpy(sctinfo->cwd, tcwd.c_str(), SCAP_MAX_PATH_SIZE); + sctinfo->flags = tinfo.m_flags ; + sctinfo->fdlimit = tinfo.m_fdlimit; + sctinfo->uid = tinfo.m_uid; + sctinfo->gid = tinfo.m_gid; + sctinfo->vmsize_kb = tinfo.m_vmsize_kb; + sctinfo->vmrss_kb = tinfo.m_vmrss_kb; + sctinfo->vmswap_kb = tinfo.m_vmswap_kb; + sctinfo->pfmajor = tinfo.m_pfmajor; + sctinfo->pfminor = tinfo.m_pfminor; + sctinfo->vtid = tinfo.m_vtid; + sctinfo->vpid = tinfo.m_vpid; + sctinfo->fdlist = NULL; + tinfo.cgroups_to_scap(sctinfo); + strncpy(sctinfo->root, tinfo.m_root.c_str(), SCAP_MAX_PATH_SIZE); + sctinfo->filtered_out = false; +} + +void sinsp_thread_manager::dump_threads_to_file(scap_dumper_t* dumper) +{ + scap_threadinfo sctinfo; + + // + // First pass of the table to calculate the length + // + uint32_t totlen = 0; for(auto it = m_threadtable.begin(); it != m_threadtable.end(); ++it) { sinsp_threadinfo& tinfo = it->second; - // - // Allocate the scap thread info - // - scap_threadinfo* sctinfo = (scap_threadinfo*)malloc(sizeof(scap_threadinfo)); - if(sctinfo == NULL) + tinfo.args_to_scap(&sctinfo); + tinfo.env_to_scap(&sctinfo); + tinfo.cgroups_to_scap(&sctinfo); + + string tcwd = (tinfo.m_cwd == "")? "/": tinfo.m_cwd; + + uint32_t il = (uint32_t) + (sizeof(uint64_t) + // tid + sizeof(uint64_t) + // pid + sizeof(uint64_t) + // ptid + sizeof(uint64_t) + // sid + 2 + MIN(tinfo.m_comm.size(), SCAP_MAX_PATH_SIZE) + + 2 + MIN(tinfo.m_exe.size(), SCAP_MAX_PATH_SIZE) + + 2 + sctinfo.args_len + + 2 + MIN(tcwd.size(), SCAP_MAX_PATH_SIZE) + + sizeof(uint64_t) + // fdlimit + sizeof(uint32_t) + // uid + sizeof(uint32_t) + // gid + sizeof(uint32_t) + // vmsize_kb + sizeof(uint32_t) + // vmrss_kb + sizeof(uint32_t) + // vmswap_kb + sizeof(uint64_t) + // pfmajor + sizeof(uint64_t) + // pfminor + 2 + sctinfo.env_len + + sizeof(int64_t) + // vtid + sizeof(int64_t) + // vpid + 2 + sctinfo.cgroups_len + + sizeof(uint32_t) + + 2 + MIN(tinfo.m_root.size(), SCAP_MAX_PATH_SIZE)); + + totlen += il; + } + + // + // Second pass of the table to dump the Threads + // + if(scap_write_proclist_header(m_inspector->m_h, dumper, totlen) != SCAP_SUCCESS) + { + throw sinsp_exception(scap_getlasterr(m_inspector->m_h)); + } + + for(auto it = m_threadtable.begin(); it != m_threadtable.end(); ++it) + { + sinsp_threadinfo& tinfo = it->second; + + thread_to_scap(tinfo, &sctinfo); + + if(scap_write_proclist_entry(m_inspector->m_h, dumper, &sctinfo) != SCAP_SUCCESS) { - throw sinsp_exception("memory allocation error in sinsp_thread_manager::to_scap"); + throw sinsp_exception(scap_getlasterr(m_inspector->m_h)); } + } - // - // Fill in the thread data - // - sctinfo->tid = tinfo.m_tid; - sctinfo->pid = tinfo.m_pid; - sctinfo->ptid = tinfo.m_ptid; - sctinfo->sid = tinfo.m_sid; - - strncpy(sctinfo->comm, tinfo.m_comm.c_str(), SCAP_MAX_PATH_SIZE); - strncpy(sctinfo->exe, tinfo.m_exe.c_str(), SCAP_MAX_PATH_SIZE); - tinfo.args_to_scap(sctinfo); - tinfo.env_to_scap(sctinfo); - string tcwd = (tinfo.m_cwd == "")? "/": tinfo.m_cwd; - strncpy(sctinfo->cwd, tcwd.c_str(), SCAP_MAX_PATH_SIZE); - sctinfo->flags = tinfo.m_flags ; - sctinfo->fdlimit = tinfo.m_fdlimit; - sctinfo->uid = tinfo.m_uid; - sctinfo->gid = tinfo.m_gid; - sctinfo->vmsize_kb = tinfo.m_vmsize_kb; - sctinfo->vmrss_kb = tinfo.m_vmrss_kb; - sctinfo->vmswap_kb = tinfo.m_vmswap_kb; - sctinfo->pfmajor = tinfo.m_pfmajor; - sctinfo->pfminor = tinfo.m_pfminor; - sctinfo->vtid = tinfo.m_vtid; - sctinfo->vpid = tinfo.m_vpid; - sctinfo->fdlist = NULL; - tinfo.cgroups_to_scap(sctinfo); - strncpy(sctinfo->root, tinfo.m_root.c_str(), SCAP_MAX_PATH_SIZE); - sctinfo->filtered_out = false; + if(scap_write_proclist_trailer(m_inspector->m_h, dumper, totlen) != SCAP_SUCCESS) + { + throw sinsp_exception(scap_getlasterr(m_inspector->m_h)); + } - // - // Add the FDs - // - unordered_map& fdtable = tinfo.get_fd_table()->m_table; - for(auto it = fdtable.begin(); it != fdtable.end(); ++it) + // + // Third pass of the table to dump the FDs + // + vector* fdinfos_to_free = new vector(); + + for(auto it = m_threadtable.begin(); it != m_threadtable.end(); ++it) + { + sinsp_threadinfo& tinfo = it->second; + + thread_to_scap(tinfo, &sctinfo); + + fdinfos_to_free->clear(); + + + if(tinfo.is_main_thread()) { // - // Allocate the scap fd info + // Add the FDs // - scap_fdinfo* scfdinfo = (scap_fdinfo*)malloc(sizeof(scap_fdinfo)); - if(scfdinfo == NULL) + unordered_map& fdtable = tinfo.get_fd_table()->m_table; + for(auto it = fdtable.begin(); it != fdtable.end(); ++it) { - throw sinsp_exception("thread memory allocation error in sinsp_thread_manager::to_scap"); - } + // + // Allocate the scap fd info + // + scap_fdinfo* scfdinfo = (scap_fdinfo*)malloc(sizeof(scap_fdinfo)); + if(scfdinfo == NULL) + { + free_dump_fdinfos(fdinfos_to_free); + delete fdinfos_to_free; + throw sinsp_exception("thread memory allocation error in sinsp_thread_manager::to_scap"); + } - // - // Populate the fd info - // - scfdinfo->fd = it->first; - tinfo.fd_to_scap(scfdinfo, &it->second); + fdinfos_to_free->push_back(scfdinfo); - // - // Add the new fd to the scap table - // - if(scap_fd_add(sctinfo, it->first, scfdinfo) != SCAP_SUCCESS) - { - throw sinsp_exception("error calling scap_fd_add in sinsp_thread_manager::to_scap"); + // + // Populate the fd info + // + scfdinfo->fd = it->first; + tinfo.fd_to_scap(scfdinfo, &it->second); + + // + // Add the new fd to the scap table + // + if(scap_fd_add(&sctinfo, it->first, scfdinfo) != SCAP_SUCCESS) + { + free_dump_fdinfos(fdinfos_to_free); + delete fdinfos_to_free; + throw sinsp_exception("error calling scap_fd_add in sinsp_thread_manager::to_scap"); + } } } // - // Add the created info to scap + // Dump the thread to disk // - if(scap_proc_add(m_inspector->m_h, it->second.m_tid, sctinfo) != SCAP_SUCCESS) + if(scap_write_proc_fds(m_inspector->m_h, &sctinfo, dumper) != SCAP_SUCCESS) { + free_dump_fdinfos(fdinfos_to_free); + delete fdinfos_to_free; throw sinsp_exception("error calling scap_proc_add in sinsp_thread_manager::to_scap"); } + + free_dump_fdinfos(fdinfos_to_free); } + + free_dump_fdinfos(fdinfos_to_free); + delete fdinfos_to_free; } diff -Nru sysdig-0.16.0/userspace/libsinsp/threadinfo.h sysdig-0.17.0/userspace/libsinsp/threadinfo.h --- sysdig-0.16.0/userspace/libsinsp/threadinfo.h 2017-05-08 09:30:22.000000000 +0000 +++ sysdig-0.17.0/userspace/libsinsp/threadinfo.h 2017-07-24 16:13:14.000000000 +0000 @@ -28,6 +28,7 @@ class sinsp_threadtable_listener; class thread_analyzer_info; class sinsp_tracerparser; +class blprogram; typedef struct erase_fd_params { @@ -80,21 +81,18 @@ \brief Return the values of all environment variables for the process containing this thread. */ - const vector& get_env() const - { - return m_env; - } + const vector& get_env(); /*! \brief Return the value of the specified environment variable for the process containing this thread. Returns empty string if variable is not found. */ - string get_env(const string& name) const; + string get_env(const string& name); /*! \brief Return true if this is a process' main thread. */ - inline bool is_main_thread() + inline bool is_main_thread() const { return m_tid == m_pid; } @@ -314,9 +312,9 @@ void allocate_private_state(); void compute_program_hash(); sinsp_threadinfo* lookup_thread(); - void args_to_scap(scap_threadinfo* sctinfo); - void env_to_scap(scap_threadinfo* sctinfo); - void cgroups_to_scap(scap_threadinfo* sctinfo); + inline void args_to_scap(scap_threadinfo* sctinfo); + inline void env_to_scap(scap_threadinfo* sctinfo); + inline void cgroups_to_scap(scap_threadinfo* sctinfo); void fd_to_scap(scap_fdinfo *dst, sinsp_fdinfo_t* src); // void push_fdop(sinsp_fdop* op); @@ -337,6 +335,7 @@ uint16_t m_lastevent_cpuid; sinsp_evt::category m_lastevent_category; bool m_parent_loop_detected; + blprogram* m_blprogram; friend class sinsp; friend class sinsp_parser; @@ -348,7 +347,7 @@ friend class thread_analyzer_info; friend class sinsp_tracerparser; friend class lua_cbacks; - friend class sisnp_baseliner; + friend class sinsp_baseliner; }; /*@}*/ @@ -403,7 +402,7 @@ void create_child_dependencies(); void recreate_child_dependencies(); - void to_scap(); + void dump_threads_to_file(scap_dumper_t* dumper); uint32_t get_thread_count() { @@ -423,6 +422,8 @@ void remove_thread(threadinfo_map_iterator_t it, bool force); void increment_mainthread_childcount(sinsp_threadinfo* threadinfo); inline void clear_thread_pointers(threadinfo_map_iterator_t it); + void free_dump_fdinfos(vector* fdinfos_to_free); + void thread_to_scap(sinsp_threadinfo& tinfo, scap_threadinfo* sctinfo); sinsp* m_inspector; threadinfo_map_t m_threadtable; @@ -444,5 +445,5 @@ friend class sinsp_analyzer; friend class sinsp; friend class sinsp_threadinfo; - friend class sisnp_baseliner; + friend class sinsp_baseliner; }; diff -Nru sysdig-0.16.0/userspace/sysdig/fields_info.cpp sysdig-0.17.0/userspace/sysdig/fields_info.cpp --- sysdig-0.16.0/userspace/sysdig/fields_info.cpp 2017-05-08 09:30:22.000000000 +0000 +++ sysdig-0.17.0/userspace/sysdig/fields_info.cpp 2017-07-24 16:13:14.000000000 +0000 @@ -247,6 +247,12 @@ case PT_DOUBLE: return "DOUBLE"; break; + case PT_CHARBUFARRAY: + return "CHARBUFARRAY"; + break; + case PT_CHARBUF_PAIR_ARRAY: + return "CHARBUF_PAIR_ARRAY"; + break; default: ASSERT(false); return "";