"Fossies" - the Fresh Open Source Software Archive

Member "sysdig-0.26.1/userspace/libscap/scap_procs.c" (24 May 2019, 32514 Bytes) of package /linux/misc/sysdig-0.26.1.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "scap_procs.c" see the Fossies "Dox" file reference documentation and the last Fossies "Diffs" side-by-side code changes report: 0.24.2_vs_0.25.

    1 /*
    2 Copyright (C) 2013-2018 Draios Inc dba Sysdig.
    3 
    4 This file is part of sysdig.
    5 
    6 Licensed under the Apache License, Version 2.0 (the "License");
    7 you may not use this file except in compliance with the License.
    8 You may obtain a copy of the License at
    9 
   10     http://www.apache.org/licenses/LICENSE-2.0
   11 
   12 Unless required by applicable law or agreed to in writing, software
   13 distributed under the License is distributed on an "AS IS" BASIS,
   14 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   15 See the License for the specific language governing permissions and
   16 limitations under the License.
   17 
   18 */
   19 
   20 #include <errno.h>
   21 #include <stdio.h>
   22 #include <stdlib.h>
   23 #include <string.h>
   24 #ifdef HAS_CAPTURE
   25 #ifndef CYGWING_AGENT
   26 #include <unistd.h>
   27 #include <sys/param.h>
   28 #include <dirent.h>
   29 #include <sys/resource.h>
   30 #include <sys/syscall.h>
   31 #include <sys/ioctl.h>
   32 #include <sys/stat.h>
   33 #endif // CYGWING_AGENT
   34 #endif // HAS_CAPTURE
   35 
   36 #include "scap.h"
   37 #include "../../driver/ppm_ringbuffer.h"
   38 #include "scap-int.h"
   39 #ifdef CYGWING_AGENT
   40 #include "windows_hal.h"
   41 #endif
   42 
   43 #if defined(_WIN64) || defined(WIN64) || defined(_WIN32) || defined(WIN32)
   44 #define strerror_r(errnum, buf, size) strerror_s(buf, size, errnum)
   45 #endif
   46 
   47 #if defined(HAS_CAPTURE)
   48 #ifndef CYGWING_AGENT
   49 int32_t scap_proc_fill_cwd(scap_t *handle, char* procdirname, struct scap_threadinfo* tinfo)
   50 {
   51     int target_res;
   52     char filename[SCAP_MAX_PATH_SIZE];
   53 
   54     snprintf(filename, sizeof(filename), "%scwd", procdirname);
   55 
   56     target_res = readlink(filename, tinfo->cwd, sizeof(tinfo->cwd) - 1);
   57     if(target_res <= 0)
   58     {
   59         snprintf(handle->m_lasterr, SCAP_LASTERR_SIZE, "readlink %s failed (%s)",
   60              filename, scap_strerror(handle, errno));
   61         return SCAP_FAILURE;
   62     }
   63 
   64     tinfo->cwd[target_res] = '\0';
   65     return SCAP_SUCCESS;
   66 }
   67 
   68 int32_t scap_proc_fill_info_from_stats(scap_t *handle, char* procdirname, struct scap_threadinfo* tinfo)
   69 {
   70     char filename[SCAP_MAX_PATH_SIZE];
   71     uint32_t nfound = 0;
   72     int64_t tmp;
   73     uint32_t uid;
   74     uint64_t ppid;
   75     uint64_t vpid;
   76     uint64_t vtid;
   77     int64_t sid;
   78     int64_t pgid;
   79     int64_t vpgid;
   80     uint32_t vmsize_kb;
   81     uint32_t vmrss_kb;
   82     uint32_t vmswap_kb;
   83     uint64_t pfmajor;
   84     uint64_t pfminor;
   85     int32_t tty;
   86     char line[512];
   87     char tmpc;
   88     char* s;
   89 
   90     tinfo->uid = (uint32_t)-1;
   91     tinfo->ptid = (uint32_t)-1LL;
   92     tinfo->sid = 0;
   93     tinfo->vpgid = 0;
   94     tinfo->vmsize_kb = 0;
   95     tinfo->vmrss_kb = 0;
   96     tinfo->vmswap_kb = 0;
   97     tinfo->pfmajor = 0;
   98     tinfo->pfminor = 0;
   99     tinfo->filtered_out = 0;
  100     tinfo->tty = 0;
  101 
  102     snprintf(filename, sizeof(filename), "%sstatus", procdirname);
  103 
  104     FILE* f = fopen(filename, "r");
  105     if(f == NULL)
  106     {
  107         ASSERT(false);
  108         snprintf(handle->m_lasterr, SCAP_LASTERR_SIZE, "open status file %s failed (%s)",
  109              filename, scap_strerror(handle, errno));
  110         return SCAP_FAILURE;
  111     }
  112 
  113     while(fgets(line, sizeof(line), f) != NULL)
  114     {
  115         if(strstr(line, "Uid") == line)
  116         {
  117             nfound++;
  118 
  119             if(sscanf(line, "Uid: %" PRIu64 " %" PRIu32, &tmp, &uid) == 2)
  120             {
  121                 tinfo->uid = uid;
  122             }
  123             else
  124             {
  125                 ASSERT(false);
  126             }
  127         }
  128         else if(strstr(line, "Gid") == line)
  129         {
  130             nfound++;
  131 
  132             if(sscanf(line, "Gid: %" PRIu64 " %" PRIu32, &tmp, &uid) == 2)
  133             {
  134                 tinfo->gid = uid;
  135             }
  136             else
  137             {
  138                 ASSERT(false);
  139             }
  140         }
  141         else if(strstr(line, "PPid") == line)
  142         {
  143             nfound++;
  144 
  145             if(sscanf(line, "PPid: %" PRIu64, &ppid) == 1)
  146             {
  147                 tinfo->ptid = ppid;
  148             }
  149             else
  150             {
  151                 ASSERT(false);
  152             }
  153         }
  154         else if(strstr(line, "VmSize:") == line)
  155         {
  156             nfound++;
  157 
  158             if(sscanf(line, "VmSize: %" PRIu32, &vmsize_kb) == 1)
  159             {
  160                 tinfo->vmsize_kb = vmsize_kb;
  161             }
  162             else
  163             {
  164                 ASSERT(false);
  165             }
  166         }
  167         else if(strstr(line, "VmRSS:") == line)
  168         {
  169             nfound++;
  170 
  171             if(sscanf(line, "VmRSS: %" PRIu32, &vmrss_kb) == 1)
  172             {
  173                 tinfo->vmrss_kb = vmrss_kb;
  174             }
  175             else
  176             {
  177                 ASSERT(false);
  178             }
  179         }
  180         else if(strstr(line, "VmSwap:") == line)
  181         {
  182             nfound++;
  183 
  184             if(sscanf(line, "VmSwap: %" PRIu32, &vmswap_kb) == 1)
  185             {
  186                 tinfo->vmswap_kb = vmswap_kb;
  187             }
  188             else
  189             {
  190                 ASSERT(false);
  191             }
  192         }
  193         else if(strstr(line, "NSpid:") == line)
  194         {
  195             nfound++;
  196             if(sscanf(line, "NSpid: %*u %" PRIu64, &vtid) == 1)
  197             {
  198                 tinfo->vtid = vtid;
  199             }
  200             else
  201             {
  202                 tinfo->vtid = tinfo->tid;
  203             }
  204         }
  205         else if(strstr(line, "NSpgid:") == line)
  206         {
  207             nfound++;
  208             if(sscanf(line, "NSpgid: %*u %" PRIu64, &vpgid) == 1)
  209             {
  210                 tinfo->vpgid = vpgid;
  211             }
  212         }
  213         else if(strstr(line, "NStgid:") == line)
  214         {
  215             nfound++;
  216             if(sscanf(line, "NStgid: %*u %" PRIu64, &vpid) == 1)
  217             {
  218                 tinfo->vpid = vpid;
  219             }
  220             else
  221             {
  222                 tinfo->vpid = tinfo->pid;
  223             }
  224         }
  225 
  226         if(nfound == 9)
  227         {
  228             break;
  229         }
  230     }
  231 
  232     ASSERT(nfound == 9 || nfound == 6 || nfound == 5);
  233 
  234     fclose(f);
  235 
  236     snprintf(filename, sizeof(filename), "%sstat", procdirname);
  237 
  238     f = fopen(filename, "r");
  239     if(f == NULL)
  240     {
  241         ASSERT(false);
  242         snprintf(handle->m_lasterr, SCAP_LASTERR_SIZE, "read stat file %s failed (%s)",
  243              filename, scap_strerror(handle, errno));
  244         return SCAP_FAILURE;
  245     }
  246 
  247     if(fgets(line, sizeof(line), f) == NULL)
  248     {
  249         ASSERT(false);
  250         fclose(f);
  251         snprintf(handle->m_lasterr, SCAP_LASTERR_SIZE, "Could not read from stat file %s (%s)",
  252              filename, scap_strerror(handle, errno));
  253         return SCAP_FAILURE;
  254     }
  255 
  256     s = strrchr(line, ')');
  257     if(s == NULL)
  258     {
  259         ASSERT(false);
  260         fclose(f);
  261         snprintf(handle->m_lasterr, SCAP_LASTERR_SIZE, "Could not find closng parens in stat file %s",
  262              filename);
  263         return SCAP_FAILURE;
  264     }
  265 
  266     //
  267     // Extract the line content
  268     //
  269     if(sscanf(s + 2, "%c %" PRId64 " %" PRId64 " %" PRId64 " %" PRId32 " %" PRId64 " %" PRId64 " %" PRId64 " %" PRId64 " %" PRId64,
  270         &tmpc,
  271         &tmp,
  272         &pgid,
  273         &sid,
  274         &tty,
  275         &tmp,
  276         &tmp,
  277         &pfminor,
  278         &tmp,
  279         &pfmajor) != 10)
  280     {
  281         ASSERT(false);
  282         fclose(f);
  283         snprintf(handle->m_lasterr, SCAP_LASTERR_SIZE, "Could not read expected fields from stat file %s",
  284              filename);
  285         return SCAP_FAILURE;
  286     }
  287 
  288     tinfo->pfmajor = pfmajor;
  289     tinfo->pfminor = pfminor;
  290     tinfo->sid = (uint64_t) sid;
  291 
  292     // If we did not find vpgid above, set it to pgid from the
  293     // global namespace.
  294     if(tinfo->vpgid == 0)
  295     {
  296         tinfo->vpgid = pgid;
  297     }
  298 
  299     tinfo->tty = tty;
  300 
  301     fclose(f);
  302     return SCAP_SUCCESS;
  303 }
  304 
  305 //
  306 // use prlimit to extract the RLIMIT_NOFILE for the tid. On systems where prlimit
  307 // is not supported, just return -1
  308 //
  309 static int32_t scap_proc_fill_flimit(scap_t *handle, uint64_t tid, struct scap_threadinfo* tinfo)
  310 #ifdef SYS_prlimit64
  311 {
  312     struct rlimit rl;
  313 
  314 #ifdef __NR_prlimit64
  315     if(syscall(SYS_prlimit64, tid, RLIMIT_NOFILE, NULL, &rl) == 0)
  316     {
  317         tinfo->fdlimit = rl.rlim_cur;
  318         return SCAP_SUCCESS;
  319     }
  320 #endif
  321 
  322     tinfo->fdlimit = -1;
  323     return SCAP_SUCCESS;
  324 }
  325 #else
  326 {
  327     tinfo->fdlimit = -1;
  328     return SCAP_SUCCESS;
  329 }
  330 #endif
  331 
  332 int32_t scap_proc_fill_cgroups(scap_t *handle, struct scap_threadinfo* tinfo, const char* procdirname)
  333 {
  334     char filename[SCAP_MAX_PATH_SIZE];
  335     char line[SCAP_MAX_CGROUPS_SIZE];
  336 
  337     tinfo->cgroups_len = 0;
  338     snprintf(filename, sizeof(filename), "%scgroup", procdirname);
  339 
  340     if(access(filename, R_OK) == -1)
  341     {
  342         return SCAP_SUCCESS;
  343     }
  344 
  345     FILE* f = fopen(filename, "r");
  346     if(f == NULL)
  347     {
  348         ASSERT(false);
  349         snprintf(handle->m_lasterr, SCAP_LASTERR_SIZE, "open cgroup file %s failed (%s)",
  350              filename, scap_strerror(handle, errno));
  351         return SCAP_FAILURE;
  352     }
  353 
  354     while(fgets(line, sizeof(line), f) != NULL)
  355     {
  356         char* token;
  357         char* subsys_list;
  358         char* cgroup;
  359         char* scratch;
  360 
  361         // id
  362         token = strtok_r(line, ":", &scratch);
  363         if(token == NULL)
  364         {
  365             ASSERT(false);
  366             fclose(f);
  367             snprintf(handle->m_lasterr, SCAP_LASTERR_SIZE, "Did not find id in cgroup file %s",
  368                  filename);
  369             return SCAP_FAILURE;
  370         }
  371 
  372         // subsys
  373         subsys_list = strtok_r(NULL, ":", &scratch);
  374         if(subsys_list == NULL)
  375         {
  376             ASSERT(false);
  377             fclose(f);
  378             snprintf(handle->m_lasterr, SCAP_LASTERR_SIZE, "Did not find subsys in cgroup file %s",
  379                  filename);
  380             return SCAP_FAILURE;
  381         }
  382 
  383         // Hack to detect empty fields, because strtok does not support it
  384         // strsep() should be used to fix this but it's not available
  385         // on CentOS 6 (has been added from Glibc 2.19)
  386         if(subsys_list-token-strlen(token) > 1)
  387         {
  388             // skip cgroups like this:
  389             // 0::/init.scope
  390             continue;
  391         }
  392 
  393         // cgroup
  394         cgroup = strtok_r(NULL, ":", &scratch);
  395         if(cgroup == NULL)
  396         {
  397             ASSERT(false);
  398             fclose(f);
  399             snprintf(handle->m_lasterr, SCAP_LASTERR_SIZE, "Did not find cgroup in cgroup file %s",
  400                  filename);
  401             return SCAP_FAILURE;
  402         }
  403 
  404         // remove the \n
  405         cgroup[strlen(cgroup) - 1] = 0;
  406 
  407         while((token = strtok_r(subsys_list, ",", &scratch)) != NULL)
  408         {
  409             subsys_list = NULL;
  410             if(strlen(cgroup) + 1 + strlen(token) + 1 > SCAP_MAX_CGROUPS_SIZE - tinfo->cgroups_len)
  411             {
  412                 ASSERT(false);
  413                 fclose(f);
  414                 return SCAP_SUCCESS;
  415             }
  416 
  417             snprintf(tinfo->cgroups + tinfo->cgroups_len, SCAP_MAX_CGROUPS_SIZE - tinfo->cgroups_len, "%s=%s", token, cgroup);
  418             tinfo->cgroups_len += strlen(cgroup) + 1 + strlen(token) + 1;
  419         }
  420     }
  421 
  422     fclose(f);
  423     return SCAP_SUCCESS;
  424 }
  425 
  426 static int32_t scap_get_vtid(scap_t* handle, int64_t tid, int64_t *vtid)
  427 {
  428     if(handle->m_mode != SCAP_MODE_LIVE)
  429     {
  430         snprintf(handle->m_lasterr, SCAP_LASTERR_SIZE, "Cannot get vtid (not in live mode)");
  431         return SCAP_FAILURE;
  432     }
  433 
  434 #if !defined(HAS_CAPTURE)
  435     ASSERT(false)
  436     return SCAP_FAILURE;
  437 #else
  438 
  439     if(handle->m_bpf)
  440     {
  441         *vtid = 0;
  442     }
  443     else
  444     {
  445         *vtid = ioctl(handle->m_devs[0].m_fd, PPM_IOCTL_GET_VTID, tid);
  446 
  447         if(*vtid == -1)
  448         {
  449             ASSERT(false);
  450             snprintf(handle->m_lasterr, SCAP_LASTERR_SIZE, "ioctl to get vtid failed (%s)",
  451                  scap_strerror(handle, errno));
  452             return SCAP_FAILURE;
  453         }
  454     }
  455 
  456     return SCAP_SUCCESS;
  457 #endif
  458 }
  459 
  460 static int32_t scap_get_vpid(scap_t* handle, int64_t tid, int64_t *vpid)
  461 {
  462     if(handle->m_mode != SCAP_MODE_LIVE)
  463     {
  464         snprintf(handle->m_lasterr, SCAP_LASTERR_SIZE, "Cannot get vtid (not in live mode)");
  465         return SCAP_FAILURE;
  466     }
  467 
  468 #if !defined(HAS_CAPTURE)
  469     ASSERT(false)
  470     return SCAP_FAILURE;
  471 #else
  472 
  473     if(handle->m_bpf)
  474     {
  475         *vpid = 0;
  476     }
  477     else
  478     {
  479         *vpid = ioctl(handle->m_devs[0].m_fd, PPM_IOCTL_GET_VPID, tid);
  480 
  481         if(*vpid == -1)
  482         {
  483             ASSERT(false);
  484             snprintf(handle->m_lasterr, SCAP_LASTERR_SIZE, "ioctl to get vpid failed (%s)",
  485                  scap_strerror(handle, errno));
  486             return SCAP_FAILURE;
  487         }
  488     }
  489 
  490     return SCAP_SUCCESS;
  491 #endif
  492 }
  493 
  494 int32_t scap_proc_fill_root(scap_t *handle, struct scap_threadinfo* tinfo, const char* procdirname)
  495 {
  496     char root_path[SCAP_MAX_PATH_SIZE];
  497     snprintf(root_path, sizeof(root_path), "%sroot", procdirname);
  498     if ( readlink(root_path, tinfo->root, sizeof(tinfo->root)) > 0)
  499     {
  500         return SCAP_SUCCESS;
  501     }
  502     else
  503     {
  504         snprintf(handle->m_lasterr, SCAP_LASTERR_SIZE, "readlink %s failed (%s)",
  505              root_path, scap_strerror(handle, errno));
  506         return SCAP_FAILURE;
  507     }
  508 }
  509 
  510 int32_t scap_proc_fill_loginuid(scap_t *handle, struct scap_threadinfo* tinfo, const char* procdirname)
  511 {
  512     uint32_t loginuid;
  513     char loginuid_path[SCAP_MAX_PATH_SIZE];
  514     char line[512];
  515     snprintf(loginuid_path, sizeof(loginuid_path), "%sloginuid", procdirname);
  516     FILE* f = fopen(loginuid_path, "r");
  517     if(f == NULL)
  518     {
  519         ASSERT(false);
  520         snprintf(handle->m_lasterr, SCAP_LASTERR_SIZE, "Open loginuid file %s failed (%s)",
  521              loginuid_path, scap_strerror(handle, errno));
  522         return SCAP_FAILURE;
  523     }
  524     if (fgets(line, sizeof(line), f) == NULL)
  525     {
  526         ASSERT(false);
  527         snprintf(handle->m_lasterr, SCAP_LASTERR_SIZE, "Could not read loginuid from %s (%s)",
  528              loginuid_path, scap_strerror(handle, errno));
  529         fclose(f);
  530         return SCAP_FAILURE;
  531     }
  532 
  533     fclose(f);
  534 
  535     if(sscanf(line, "%" PRId32, &loginuid) == 1)
  536     {
  537         tinfo->loginuid = loginuid;
  538         return SCAP_SUCCESS;
  539     }
  540     else
  541     {
  542         ASSERT(false);
  543         snprintf(handle->m_lasterr, SCAP_LASTERR_SIZE, "Could not read loginuid from %s",
  544              loginuid_path);
  545         return SCAP_FAILURE;
  546     }
  547 }
  548 
  549 //
  550 // Add a process to the list by parsing its entry under /proc
  551 //
  552 static int32_t scap_proc_add_from_proc(scap_t* handle, uint32_t tid, int parenttid, int tid_to_scan, char* procdirname, struct scap_ns_socket_list** sockets_by_ns, scap_threadinfo** procinfo, char *error)
  553 {
  554     char dir_name[256];
  555     char target_name[SCAP_MAX_PATH_SIZE];
  556     int target_res;
  557     char filename[252];
  558     char line[SCAP_MAX_ENV_SIZE];
  559     struct scap_threadinfo* tinfo;
  560     int32_t uth_status = SCAP_SUCCESS;
  561     FILE* f;
  562     size_t filesize;
  563     size_t exe_len;
  564     bool free_tinfo = false;
  565     int32_t res = SCAP_SUCCESS;
  566     struct stat dirstat;
  567 
  568     snprintf(dir_name, sizeof(dir_name), "%s/%u/", procdirname, tid);
  569     snprintf(filename, sizeof(filename), "%sexe", dir_name);
  570 
  571     //
  572     // Gather the executable full name
  573     //
  574     target_res = readlink(filename, target_name, sizeof(target_name) - 1);          // Getting the target of the exe, i.e. to which binary it points to
  575 
  576     if(target_res <= 0)
  577     {
  578         //
  579         // No exe. This either
  580         //  - a kernel thread (if there is no cmdline). In that case we skip it.
  581         //  - a process that has been containerized or has some weird thing going on. In that case
  582         //    we accept it.
  583         //
  584         snprintf(filename, sizeof(filename), "%scmdline", dir_name);
  585         f = fopen(filename, "r");
  586         if(f == NULL)
  587         {
  588             return SCAP_SUCCESS;
  589         }
  590 
  591         ASSERT(sizeof(line) >= SCAP_MAX_PATH_SIZE);
  592 
  593         if(fgets(line, SCAP_MAX_PATH_SIZE, f) == NULL)
  594         {
  595             fclose(f);
  596             return SCAP_SUCCESS;
  597         }
  598         else
  599         {
  600             fclose(f);
  601         }
  602 
  603         target_name[0] = 0;
  604     }
  605     else
  606     {
  607         // null-terminate target_name (readlink() does not append a null byte)
  608         target_name[target_res] = 0;
  609     }
  610 
  611     //
  612     // This is a real user level process. Allocate the procinfo structure.
  613     //
  614     if((tinfo = scap_proc_alloc(handle)) == NULL)
  615     {
  616         // Error message saved in handle->m_lasterr
  617         snprintf(error, SCAP_LASTERR_SIZE, "can't allocate procinfo struct: %s", handle->m_lasterr);
  618         return SCAP_FAILURE;
  619     }
  620 
  621     tinfo->tid = tid;
  622     if(parenttid != -1)
  623     {
  624         tinfo->pid = parenttid;
  625     }
  626     else
  627     {
  628         tinfo->pid = tid;
  629     }
  630 
  631     tinfo->fdlist = NULL;
  632 
  633     //
  634     // If tid is different from pid, assume this is a thread and that the FDs are shared, and set the
  635     // corresponding process flags.
  636     // XXX we should see if the process creation flags are stored somewhere in /proc and handle this
  637     // properly instead of making assumptions.
  638     //
  639     if(tinfo->tid == tinfo->pid)
  640     {
  641         tinfo->flags = 0;
  642     }
  643     else
  644     {
  645         tinfo->flags = PPM_CL_CLONE_THREAD | PPM_CL_CLONE_FILES;
  646     }
  647 
  648     //
  649     // Gathers the exepath
  650     //
  651     snprintf(tinfo->exepath, sizeof(tinfo->exepath), "%s", target_name);
  652 
  653     //
  654     // Gather the command name
  655     //
  656     snprintf(filename, sizeof(filename), "%sstatus", dir_name);
  657 
  658     f = fopen(filename, "r");
  659     if(f == NULL)
  660     {
  661         snprintf(error, SCAP_LASTERR_SIZE, "can't open %s (error %s)", filename, scap_strerror(handle, errno));
  662         free(tinfo);
  663         return SCAP_FAILURE;
  664     }
  665     else
  666     {
  667         ASSERT(sizeof(line) >= SCAP_MAX_PATH_SIZE);
  668 
  669         if(fgets(line, SCAP_MAX_PATH_SIZE, f) == NULL)
  670         {
  671             snprintf(error, SCAP_LASTERR_SIZE, "can't read from %s (%s)",
  672                  filename, scap_strerror(handle, errno));
  673             fclose(f);
  674             free(tinfo);
  675             return SCAP_FAILURE;
  676         }
  677 
  678         line[SCAP_MAX_PATH_SIZE - 1] = 0;
  679         sscanf(line, "Name:%s", tinfo->comm);
  680         fclose(f);
  681     }
  682 
  683     bool suppressed;
  684     if ((res = scap_update_suppressed(handle, tinfo->comm, tid, 0, &suppressed)) != SCAP_SUCCESS)
  685     {
  686         snprintf(error, SCAP_LASTERR_SIZE, "can't update set of suppressed tids (%s)", handle->m_lasterr);
  687         free(tinfo);
  688         return res;
  689     }
  690 
  691     if (suppressed && tid_to_scan == -1)
  692     {
  693         free(tinfo);
  694         return SCAP_SUCCESS;
  695     }
  696 
  697     //
  698     // Gather the command line
  699     //
  700     snprintf(filename, sizeof(filename), "%scmdline", dir_name);
  701 
  702     f = fopen(filename, "r");
  703     if(f == NULL)
  704     {
  705         snprintf(error, SCAP_LASTERR_SIZE, "can't open cmdline file %s (%s)",
  706              filename, scap_strerror(handle, errno));
  707         free(tinfo);
  708         return SCAP_FAILURE;
  709     }
  710     else
  711     {
  712         ASSERT(sizeof(line) >= SCAP_MAX_ARGS_SIZE);
  713 
  714         filesize = fread(line, 1, SCAP_MAX_ARGS_SIZE - 1, f);
  715         if(filesize > 0)
  716         {
  717             line[filesize] = 0;
  718 
  719             exe_len = strlen(line);
  720             if(exe_len < filesize)
  721             {
  722                 ++exe_len;
  723             }
  724 
  725             snprintf(tinfo->exe, SCAP_MAX_PATH_SIZE, "%s", line);
  726 
  727             tinfo->args_len = filesize - exe_len;
  728 
  729             memcpy(tinfo->args, line + exe_len, tinfo->args_len);
  730             tinfo->args[SCAP_MAX_ARGS_SIZE - 1] = 0;
  731         }
  732         else
  733         {
  734             tinfo->args[0] = 0;
  735             tinfo->exe[0] = 0;
  736         }
  737 
  738         fclose(f);
  739     }
  740 
  741     //
  742     // Gather the environment
  743     //
  744     snprintf(filename, sizeof(filename), "%senviron", dir_name);
  745 
  746     f = fopen(filename, "r");
  747     if(f == NULL)
  748     {
  749         snprintf(error, SCAP_LASTERR_SIZE, "can't open environ file %s (%s)",
  750              filename, scap_strerror(handle, errno));
  751         free(tinfo);
  752         return SCAP_FAILURE;
  753     }
  754     else
  755     {
  756         ASSERT(sizeof(line) >= SCAP_MAX_ENV_SIZE);
  757 
  758         filesize = fread(line, 1, SCAP_MAX_ENV_SIZE, f);
  759 
  760         if(filesize > 0)
  761         {
  762             line[filesize - 1] = 0;
  763 
  764             tinfo->env_len = filesize;
  765 
  766             memcpy(tinfo->env, line, tinfo->env_len);
  767             tinfo->env[SCAP_MAX_ENV_SIZE - 1] = 0;
  768         }
  769         else
  770         {
  771             tinfo->env[0] = 0;
  772         }
  773 
  774         fclose(f);
  775     }
  776 
  777     //
  778     // set the current working directory of the process
  779     //
  780     if(SCAP_FAILURE == scap_proc_fill_cwd(handle, dir_name, tinfo))
  781     {
  782         snprintf(error, SCAP_LASTERR_SIZE, "can't fill cwd for %s (%s)",
  783              dir_name, handle->m_lasterr);
  784         free(tinfo);
  785         return SCAP_FAILURE;
  786     }
  787 
  788     //
  789     // extract the user id and ppid from /proc/pid/status
  790     //
  791     if(SCAP_FAILURE == scap_proc_fill_info_from_stats(handle, dir_name, tinfo))
  792     {
  793         snprintf(error, SCAP_LASTERR_SIZE, "can't fill cwd for %s (%s)",
  794              dir_name, handle->m_lasterr);
  795         free(tinfo);
  796         return SCAP_FAILURE;
  797     }
  798 
  799     //
  800     // Set the file limit
  801     //
  802     if(SCAP_FAILURE == scap_proc_fill_flimit(handle, tinfo->tid, tinfo))
  803     {
  804         snprintf(error, SCAP_LASTERR_SIZE, "can't fill flimit for %s (%s)",
  805              dir_name, handle->m_lasterr);
  806         free(tinfo);
  807         return SCAP_FAILURE;
  808     }
  809 
  810     if(scap_proc_fill_cgroups(handle, tinfo, dir_name) == SCAP_FAILURE)
  811     {
  812         snprintf(error, SCAP_LASTERR_SIZE, "can't fill cgroups for %s (%s)",
  813              dir_name, handle->m_lasterr);
  814         free(tinfo);
  815         return SCAP_FAILURE;
  816     }
  817 
  818     // These values should be read already from /status file, leave these
  819     // fallback functions for older kernels < 4.1
  820     if(tinfo->vtid == 0 && scap_get_vtid(handle, tinfo->tid, &tinfo->vtid) == SCAP_FAILURE)
  821     {
  822         tinfo->vtid = tinfo->tid;
  823     }
  824 
  825     if(tinfo->vpid == 0 && scap_get_vpid(handle, tinfo->tid, &tinfo->vpid) == SCAP_FAILURE)
  826     {
  827         tinfo->vpid = tinfo->pid;
  828     }
  829 
  830     //
  831     // set the current root of the process
  832     //
  833     if(SCAP_FAILURE == scap_proc_fill_root(handle, tinfo, dir_name))
  834     {
  835         snprintf(error, SCAP_LASTERR_SIZE, "can't fill root for %s (%s)",
  836              dir_name, handle->m_lasterr);
  837         free(tinfo);
  838         return SCAP_FAILURE;
  839     }
  840 
  841     //
  842     // set the loginuid
  843     //
  844     if(SCAP_FAILURE == scap_proc_fill_loginuid(handle, tinfo, dir_name))
  845     {
  846         snprintf(error, SCAP_LASTERR_SIZE, "can't fill loginuid for %s (%s)",
  847              dir_name, handle->m_lasterr);
  848         free(tinfo);
  849         return SCAP_FAILURE;
  850     }
  851 
  852     if(stat(dir_name, &dirstat) == 0)
  853     {
  854         tinfo->clone_ts = dirstat.st_ctim.tv_sec*1000000000 + dirstat.st_ctim.tv_nsec;
  855     }
  856 
  857     //
  858     // if tid_to_scan is set we assume this is a runtime lookup so no
  859     // need to use the table
  860     //
  861     if(tid_to_scan == -1)
  862     {
  863         //
  864         // Done. Add the entry to the process table, or fire the notification callback
  865         //
  866         if(handle->m_proc_callback == NULL)
  867         {
  868             HASH_ADD_INT64(handle->m_proclist, tid, tinfo);
  869             if(uth_status != SCAP_SUCCESS)
  870             {
  871                 snprintf(error, SCAP_LASTERR_SIZE, "process table allocation error (2)");
  872                 return SCAP_FAILURE;
  873             }
  874         }
  875         else
  876         {
  877             handle->m_proc_callback(handle->m_proc_callback_context, handle, tinfo->tid, tinfo, NULL);
  878             free_tinfo = true;
  879         }
  880     }
  881     else
  882     {
  883         *procinfo = tinfo;
  884     }
  885 
  886     //
  887     // Only add fds for processes, not threads
  888     //
  889     if(parenttid == -1)
  890     {
  891         res = scap_fd_scan_fd_dir(handle, dir_name, tinfo, sockets_by_ns, error);
  892     }
  893 
  894     if(free_tinfo)
  895     {
  896         free(tinfo);
  897     }
  898 
  899     return res;
  900 }
  901 
  902 //
  903 // Scan a directory containing multiple processes under /proc
  904 //
  905 int32_t scap_proc_scan_proc_dir(scap_t* handle, char* procdirname, int parenttid, int tid_to_scan, struct scap_threadinfo** procinfo, char *error, bool scan_sockets)
  906 {
  907     DIR *dir_p;
  908     struct dirent *dir_entry_p;
  909     scap_threadinfo* tinfo;
  910     uint64_t tid;
  911     int32_t res = SCAP_SUCCESS;
  912     char childdir[SCAP_MAX_PATH_SIZE];
  913 
  914     struct scap_ns_socket_list* sockets_by_ns = NULL;
  915 
  916     tid = 0;
  917     dir_p = opendir(procdirname);
  918 
  919     if(dir_p == NULL)
  920     {
  921         snprintf(error, SCAP_LASTERR_SIZE, "error opening the %s directory (%s)",
  922              procdirname, scap_strerror(handle, errno));
  923         return SCAP_NOTFOUND;
  924     }
  925 
  926     if(-1 == parenttid)
  927     {
  928         if(!scan_sockets)
  929         {
  930             sockets_by_ns = (void*)-1;
  931         }
  932     }
  933 
  934     if(tid_to_scan != -1)
  935     {
  936         *procinfo = NULL;
  937     }
  938 
  939     while((dir_entry_p = readdir(dir_p)) != NULL)
  940     {
  941         if(strspn(dir_entry_p->d_name, "0123456789") != strlen(dir_entry_p->d_name))
  942         {
  943             continue;
  944         }
  945 
  946         //
  947         // Gather the process TID, which is the directory name
  948         //
  949         tid = atoi(dir_entry_p->d_name);
  950 
  951         //
  952         // Skip the main thread entry
  953         //
  954         if(parenttid != -1 && tid == parenttid)
  955         {
  956             continue;
  957         }
  958 
  959         //
  960         // if tid_to_scan is set we assume is a runtime lookup so no
  961         // need to use the table
  962         //
  963         if(tid_to_scan == -1)
  964         {
  965             HASH_FIND_INT64(handle->m_proclist, &tid, tinfo);
  966             if(tinfo != NULL)
  967             {
  968                 ASSERT(false);
  969                 snprintf(error, SCAP_LASTERR_SIZE, "duplicate process %"PRIu64, tid);
  970                 res = SCAP_FAILURE;
  971                 break;
  972             }
  973         }
  974 
  975         if(tid_to_scan == -1 || tid_to_scan == tid)
  976         {
  977             char add_error[SCAP_LASTERR_SIZE];
  978 
  979             //
  980             // We have a process that needs to be explored
  981             //
  982             res = scap_proc_add_from_proc(handle, tid, parenttid, tid_to_scan, procdirname, &sockets_by_ns, procinfo, add_error);
  983             if(res != SCAP_SUCCESS)
  984             {
  985                 snprintf(error, SCAP_LASTERR_SIZE, "cannot add procs tid = %"PRIu64", parenttid = %"PRIi32", dirname = %s, error=%s", tid, parenttid, procdirname, add_error);
  986                 break;
  987             }
  988 
  989             if(tid_to_scan != -1)
  990             {
  991                 //
  992                 // procinfo should be filled, except when
  993                 // the main thread already terminated and
  994                 // the various proc files were not readable
  995                 //
  996                 // ASSERT(*procinfo);
  997                 break;
  998             }
  999         }
 1000 
 1001         //
 1002         // See if this process includes tasks that need to be added
 1003         //
 1004         if(parenttid == -1 && handle->m_mode != SCAP_MODE_NODRIVER)
 1005         {
 1006             snprintf(childdir, sizeof(childdir), "%s/%u/task", procdirname, (int)tid);
 1007             if(scap_proc_scan_proc_dir(handle, childdir, tid, tid_to_scan, procinfo, error, scan_sockets) == SCAP_FAILURE)
 1008             {
 1009                 res = SCAP_FAILURE;
 1010                 break;
 1011             }
 1012         }
 1013 
 1014         if(tid_to_scan != -1 && *procinfo)
 1015         {
 1016             //
 1017             // We found the process we were looking for, no need to keep iterating
 1018             //
 1019             break;
 1020         }
 1021     }
 1022 
 1023     closedir(dir_p);
 1024     if(sockets_by_ns != NULL && sockets_by_ns != (void*)-1)
 1025     {
 1026         scap_fd_free_ns_sockets_list(handle, &sockets_by_ns);
 1027     }
 1028     return res;
 1029 }
 1030 
 1031 #endif // CYGWING_AGENT
 1032 
 1033 int32_t scap_getpid_global(scap_t* handle, int64_t* pid)
 1034 {
 1035 #ifndef CYGWING_AGENT
 1036     if(handle->m_mode != SCAP_MODE_LIVE)
 1037     {
 1038         snprintf(handle->m_lasterr, SCAP_LASTERR_SIZE, "Cannot get pid (not in live mode)");
 1039         ASSERT(false);
 1040         return SCAP_FAILURE;
 1041     }
 1042 
 1043 #if !defined(HAS_CAPTURE)
 1044     ASSERT(false);
 1045     snprintf(handle->m_lasterr, SCAP_LASTERR_SIZE, "Cannot get pid (capture not enabled)");
 1046     return SCAP_FAILURE;
 1047 #else
 1048 
 1049     if(handle->m_bpf)
 1050     {
 1051         char filename[SCAP_MAX_PATH_SIZE];
 1052         char line[512];
 1053 
 1054         snprintf(filename, sizeof(filename), "%s/proc/self/status", scap_get_host_root());
 1055 
 1056         FILE* f = fopen(filename, "r");
 1057         if(f == NULL)
 1058         {
 1059             ASSERT(false);
 1060             snprintf(handle->m_lasterr, SCAP_LASTERR_SIZE, "can not open status file %s (%s)",
 1061                  filename, scap_strerror(handle, errno));
 1062             return SCAP_FAILURE;
 1063         }
 1064 
 1065         while(fgets(line, sizeof(line), f) != NULL)
 1066         {
 1067             if(sscanf(line, "Tgid: %" PRId64, pid) == 1)
 1068             {
 1069                 fclose(f);
 1070                 return SCAP_SUCCESS;
 1071             }
 1072         }
 1073 
 1074         fclose(f);
 1075         snprintf(handle->m_lasterr, SCAP_LASTERR_SIZE, "could not find tgid in status file %s",
 1076              filename);
 1077         return SCAP_FAILURE;
 1078     }
 1079     else
 1080     {
 1081         *pid = ioctl(handle->m_devs[0].m_fd, PPM_IOCTL_GET_CURRENT_PID);
 1082         if(*pid == -1)
 1083         {
 1084             ASSERT(false);
 1085             snprintf(handle->m_lasterr, SCAP_LASTERR_SIZE, "ioctl to get pid failed (%s)",
 1086                  scap_strerror(handle, errno));
 1087             return SCAP_FAILURE;
 1088         }
 1089     }
 1090 
 1091     return SCAP_SUCCESS;
 1092 #endif
 1093 #else // CYGWING_AGENT
 1094     return getpid();
 1095 #endif // CYGWING_AGENT
 1096 }
 1097 
 1098 #endif // HAS_CAPTURE
 1099 
 1100 #ifdef CYGWING_AGENT
 1101 int32_t scap_proc_scan_proc_dir(scap_t* handle, char* procdirname, int parenttid, int tid_to_scan, struct scap_threadinfo** procinfo, char *error, bool scan_sockets)
 1102 {
 1103     return scap_proc_scan_proc_dir_windows(handle, procinfo, error);
 1104 }
 1105 #endif
 1106 
 1107 //
 1108 // Delete a process entry
 1109 //
 1110 void scap_proc_delete(scap_t* handle, scap_threadinfo* proc)
 1111 {
 1112     //
 1113     // First, free the fd table for this process descriptor
 1114     //
 1115     scap_fd_free_proc_fd_table(handle, proc);
 1116 
 1117     //
 1118     // Second, remove the process descriptor from the table
 1119     //
 1120     HASH_DEL(handle->m_proclist, proc);
 1121 
 1122     //
 1123     // Third, free the memory
 1124     //
 1125     free(proc);
 1126 }
 1127 
 1128 //
 1129 // Free the process table
 1130 //
 1131 void scap_proc_free_table(scap_t* handle)
 1132 {
 1133     struct scap_threadinfo* tinfo;
 1134     struct scap_threadinfo* ttinfo;
 1135 
 1136     HASH_ITER(hh, handle->m_proclist, tinfo, ttinfo)
 1137     {
 1138         scap_proc_delete(handle, tinfo);
 1139     }
 1140 }
 1141 
 1142 struct scap_threadinfo* scap_proc_get(scap_t* handle, int64_t tid, bool scan_sockets)
 1143 {
 1144 #if !defined(HAS_CAPTURE)
 1145     return NULL;
 1146 #else
 1147 
 1148     //
 1149     // No /proc parsing for offline captures
 1150     //
 1151     if(handle->m_mode == SCAP_MODE_CAPTURE)
 1152     {
 1153         return NULL;
 1154     }
 1155 
 1156     struct scap_threadinfo* tinfo = NULL;
 1157     char filename[SCAP_MAX_PATH_SIZE];
 1158     snprintf(filename, sizeof(filename), "%s/proc", scap_get_host_root());
 1159     if(scap_proc_scan_proc_dir(handle, filename, -1, tid, &tinfo, handle->m_lasterr, scan_sockets) != SCAP_SUCCESS)
 1160     {
 1161         return NULL;
 1162     }
 1163 
 1164     return tinfo;
 1165 #endif // HAS_CAPTURE
 1166 }
 1167 
 1168 bool scap_is_thread_alive(scap_t* handle, int64_t pid, int64_t tid, const char* comm)
 1169 {
 1170 #if !defined(HAS_CAPTURE)
 1171     return false;
 1172 #else
 1173     char charbuf[SCAP_MAX_PATH_SIZE];
 1174     FILE* f;
 1175 
 1176 
 1177     //
 1178     // No /proc parsing for offline captures
 1179     //
 1180     if(handle->m_mode == SCAP_MODE_CAPTURE)
 1181     {
 1182         return false;
 1183     }
 1184 
 1185     snprintf(charbuf, sizeof(charbuf), "%s/proc/%" PRId64 "/task/%" PRId64 "/comm", scap_get_host_root(), pid, tid);
 1186 
 1187     f = fopen(charbuf, "r");
 1188 
 1189     if(f != NULL)
 1190     {
 1191         if(fgets(charbuf, sizeof(charbuf), f) != NULL)
 1192         {
 1193             if(strncmp(charbuf, comm, strlen(comm)) == 0)
 1194             {
 1195                 fclose(f);
 1196                 return true;
 1197             }
 1198         }
 1199 
 1200         fclose(f);
 1201     }
 1202     else
 1203     {
 1204         //
 1205         // If /proc/<pid>/task/<tid>/comm does not exist but /proc/<pid>/task/<tid>/exe does exist, we assume we're on an ancient
 1206         // OS like RHEL5 and we return true.
 1207         // This could generate some false positives on such old distros, and we're going to accept it.
 1208         //
 1209         snprintf(charbuf, sizeof(charbuf), "%s/proc/%" PRId64 "/task/%" PRId64 "/exe", scap_get_host_root(), pid, tid);
 1210         f = fopen(charbuf, "r");
 1211         if(f != NULL)
 1212         {
 1213             fclose(f);
 1214             return true;
 1215         }
 1216 
 1217     }
 1218 
 1219     return false;
 1220 #endif // HAS_CAPTURE
 1221 }
 1222 
 1223 #if defined(HAS_CAPTURE)
 1224 int scap_proc_scan_proc_table(scap_t *handle)
 1225 {
 1226     char filename[SCAP_MAX_PATH_SIZE];
 1227     //
 1228     // Create the process list
 1229     //
 1230     handle->m_lasterr[0] = '\0';
 1231 
 1232     snprintf(filename, sizeof(filename), "%s/proc", scap_get_host_root());
 1233     return scap_proc_scan_proc_dir(handle, filename, -1, -1, NULL, handle->m_lasterr, true);
 1234 }
 1235 
 1236 void scap_refresh_proc_table(scap_t* handle)
 1237 {
 1238     if(handle->m_proclist)
 1239     {
 1240         scap_proc_free_table(handle);
 1241         handle->m_proclist = NULL;
 1242     }
 1243     scap_proc_scan_proc_table(handle);
 1244 }
 1245 #else
 1246 void scap_refresh_proc_table(scap_t* handle)
 1247 {
 1248 }
 1249 #endif // HAS_CAPTURE
 1250 
 1251 struct scap_threadinfo *scap_proc_alloc(scap_t *handle)
 1252 {
 1253     struct scap_threadinfo *tinfo = (struct scap_threadinfo*) calloc(1, sizeof(scap_threadinfo));
 1254     if(tinfo == NULL)
 1255     {
 1256         snprintf(handle->m_lasterr, SCAP_LASTERR_SIZE, "process table allocation error (1)");
 1257         return NULL;
 1258     }
 1259 
 1260     return tinfo;
 1261 }
 1262 
 1263 void scap_proc_free(scap_t* handle, struct scap_threadinfo* proc)
 1264 {
 1265     scap_fd_free_proc_fd_table(handle, proc);
 1266     free(proc);
 1267 }
 1268 
 1269 int32_t scap_proc_add(scap_t* handle, uint64_t tid, scap_threadinfo* tinfo)
 1270 {
 1271     int32_t uth_status = SCAP_SUCCESS;
 1272 
 1273     HASH_ADD_INT64(handle->m_proclist, tid, tinfo);
 1274     if(uth_status == SCAP_SUCCESS)
 1275     {
 1276         return SCAP_SUCCESS;
 1277     }
 1278     else
 1279     {
 1280         snprintf(handle->m_lasterr, SCAP_LASTERR_SIZE, "Could not add tid to hash table");
 1281         return SCAP_FAILURE;
 1282     }
 1283 }
 1284 
 1285 int32_t scap_fd_add(scap_t *handle, scap_threadinfo* tinfo, uint64_t fd, scap_fdinfo* fdinfo)
 1286 {
 1287     int32_t uth_status = SCAP_SUCCESS;
 1288 
 1289     HASH_ADD_INT64(tinfo->fdlist, fd, fdinfo);
 1290     if(uth_status == SCAP_SUCCESS)
 1291     {
 1292         return SCAP_SUCCESS;
 1293     }
 1294     else
 1295     {
 1296         snprintf(handle->m_lasterr, SCAP_LASTERR_SIZE, "Could not add fd to hash table");
 1297         return SCAP_FAILURE;
 1298     }
 1299 }
 1300 
 1301 //
 1302 // Internal helper functions to output the process table to screen
 1303 //
 1304 void scap_proc_print_info(scap_t *handle, scap_threadinfo* tinfo)
 1305 {
 1306     fprintf(stderr, "TID:%"PRIu64" PID:%"PRIu64" FLAGS:%"PRIu32" COMM:%s EXE:%s ARGS:%s CWD:%s FLIMIT:%" PRId64 "\n", tinfo->tid, tinfo->pid, tinfo->flags,tinfo->comm, tinfo->exe, tinfo->args, tinfo->cwd, tinfo->fdlimit);
 1307     scap_fd_print_table(handle, tinfo);
 1308 }
 1309 
 1310 void scap_proc_print_proc_by_tid(scap_t* handle, uint64_t tid)
 1311 {
 1312     scap_threadinfo* tinfo;
 1313     scap_threadinfo* ttinfo;
 1314 
 1315     HASH_ITER(hh, handle->m_proclist, tinfo, ttinfo)
 1316     {
 1317         if(tinfo->tid == tid)
 1318         {
 1319             scap_proc_print_info(handle, tinfo);
 1320         }
 1321     }
 1322 }
 1323 
 1324 void scap_proc_print_table(scap_t* handle)
 1325 {
 1326     scap_threadinfo* tinfo;
 1327     scap_threadinfo* ttinfo;
 1328 
 1329     printf("************** PROCESS TABLE **************\n");
 1330 
 1331     HASH_ITER(hh, handle->m_proclist, tinfo, ttinfo)
 1332     {
 1333         scap_proc_print_info(handle, tinfo);
 1334     }
 1335 
 1336     printf("*******************************************\n");
 1337 }
 1338 
 1339 const char *scap_strerror(scap_t *handle, int errnum)
 1340 {
 1341     int rc;
 1342     if((rc = strerror_r(errnum, handle->m_strerror_buf, SCAP_LASTERR_SIZE) != 0))
 1343     {
 1344         if(rc != ERANGE)
 1345         {
 1346             snprintf(handle->m_strerror_buf, SCAP_LASTERR_SIZE, "Errno %d", errnum);
 1347         }
 1348     }
 1349 
 1350     return handle->m_strerror_buf;
 1351 }
 1352 
 1353 int32_t scap_update_suppressed(scap_t *handle,
 1354                    const char *comm,
 1355                    uint64_t tid, uint64_t ptid,
 1356                    bool *suppressed)
 1357 {
 1358     uint32_t i;
 1359     scap_tid *stid;
 1360 
 1361     *suppressed = false;
 1362 
 1363     HASH_FIND_INT64(handle->m_suppressed_tids, &ptid, stid);
 1364 
 1365     if(stid != NULL)
 1366     {
 1367         *suppressed = true;
 1368     }
 1369     else
 1370     {
 1371         for(i=0; i < handle->m_num_suppressed_comms; i++)
 1372         {
 1373             if(strcmp(handle->m_suppressed_comms[i], comm) == 0)
 1374             {
 1375                 *suppressed = true;
 1376                 break;
 1377             }
 1378         }
 1379     }
 1380 
 1381     // Also check to see if the tid is already in the set of
 1382     // suppressed tids.
 1383 
 1384     HASH_FIND_INT64(handle->m_suppressed_tids, &tid, stid);
 1385 
 1386     if(*suppressed && stid == NULL)
 1387     {
 1388         stid = (scap_tid *) malloc(sizeof(scap_tid));
 1389         stid->tid = tid;
 1390         int32_t uth_status = SCAP_SUCCESS;
 1391 
 1392         HASH_ADD_INT64(handle->m_suppressed_tids, tid, stid);
 1393 
 1394         if(uth_status != SCAP_SUCCESS)
 1395         {
 1396             snprintf(handle->m_lasterr, SCAP_LASTERR_SIZE, "can't add tid to suppressed hash table");
 1397             return SCAP_FAILURE;
 1398         }
 1399         *suppressed = true;
 1400     }
 1401     else if (!*suppressed && stid != NULL)
 1402     {
 1403         HASH_DEL(handle->m_suppressed_tids, stid);
 1404         free(stid);
 1405         *suppressed = false;
 1406     }
 1407 
 1408     return SCAP_SUCCESS;
 1409 }
 1410 
 1411 int32_t scap_check_suppressed(scap_t *handle, scap_evt *pevent, bool *suppressed)
 1412 {
 1413     uint16_t *lens;
 1414     char *valptr;
 1415     uint32_t j;
 1416     int32_t res = SCAP_SUCCESS;
 1417     const char *comm = NULL;
 1418     uint64_t *ptid = NULL;
 1419     scap_tid *stid;
 1420 
 1421     *suppressed = false;
 1422 
 1423     // For events that can create a new tid (fork, vfork, clone),
 1424     // we need to check the comm, which might also update the set
 1425     // of suppressed tids.
 1426 
 1427     switch(pevent->type)
 1428     {
 1429     case PPME_SYSCALL_CLONE_20_X:
 1430     case PPME_SYSCALL_FORK_20_X:
 1431     case PPME_SYSCALL_VFORK_20_X:
 1432     case PPME_SYSCALL_EXECVE_19_X:
 1433 
 1434         lens = (uint16_t *)((char *)pevent + sizeof(struct ppm_evt_hdr));
 1435         valptr = (char *)lens + pevent->nparams * sizeof(uint16_t);
 1436 
 1437         if(pevent->nparams < 14)
 1438         {
 1439             snprintf(handle->m_lasterr, SCAP_LASTERR_SIZE, "Could not find process comm in event argument list");
 1440             return SCAP_FAILURE;
 1441         }
 1442 
 1443         // For all of these events, the comm is argument 14,
 1444         // so we need to walk the list of params that far to
 1445         // find the comm.
 1446         for(j = 0; j < 13; j++)
 1447         {
 1448             if(j == 5)
 1449             {
 1450                 ptid = (uint64_t *) valptr;
 1451             }
 1452 
 1453             valptr += lens[j];
 1454         }
 1455 
 1456         if(ptid == NULL)
 1457         {
 1458             snprintf(handle->m_lasterr, SCAP_LASTERR_SIZE, "Could not find ptid in event argument list");
 1459             return SCAP_FAILURE;
 1460         }
 1461 
 1462         comm = valptr;
 1463 
 1464         if((res = scap_update_suppressed(handle,
 1465                          comm,
 1466                          pevent->tid, *ptid,
 1467                          suppressed)) != SCAP_SUCCESS)
 1468         {
 1469             // scap_update_suppressed already set handle->m_lasterr on error.
 1470             return res;
 1471         }
 1472 
 1473         break;
 1474 
 1475     default:
 1476 
 1477         HASH_FIND_INT64(handle->m_suppressed_tids, &(pevent->tid), stid);
 1478 
 1479         // When threads exit they are always removed and no longer suppressed.
 1480         if(pevent->type == PPME_PROCEXIT_1_E)
 1481         {
 1482             if(stid != NULL)
 1483             {
 1484                 HASH_DEL(handle->m_suppressed_tids, stid);
 1485                 free(stid);
 1486                 *suppressed = true;
 1487             }
 1488             else
 1489             {
 1490                 *suppressed = false;
 1491             }
 1492         }
 1493         else
 1494         {
 1495             *suppressed = (stid != NULL);
 1496         }
 1497 
 1498         break;
 1499     }
 1500 
 1501     return SCAP_SUCCESS;
 1502 }