#! /usr/bin/env stap # Copyright (C) 2016-2018 Red Hat, Inc. # Written by William Cohen # # container_check.stp watches for use of # prohibited capabilities, use of prohibited syscalls, and # syscall failures) that would indicate that this application # would not operate properly in a restricted contiainer. # # By default this script monitors all systemcalls system-wide. # To limit to limit container_check.stp to monitoring a particular # process and it children use the systemtap -x option # or -c option. # # By default this script lists all capabilities requested. # To limit it to a subset of capabilities use the following # option on the command line with a '-' separated list of # forbidden capabilites: # # -G forbidden_capabilities="badcap1-badcap2" # # By default this script allows all syscalls. # To mark syscalls as forbidden use a '-' separate list: # # -G forbidden_syscalls="syscall1-syscall2" # # control-c to exit data collection global forbidden_capabilities="" # '-' separated list of forbidden capabilities global forbidden_syscalls="" # '-' separated list of forbidden syscalls global capability, cap_use global badcaps = -1, cap_name global cap_syscall global badsyscall global problem_syscall global syscall_errno # Determine whether t is a ancestor of target() # returns 1 if ancestor of target() # returns 0 if not an ancestor of target() function child_of_target:long (t:long) { if (!target()) return 1 while(t && t != task_parent(t)) { if (task_pid(t) == target()) return 1 t = task_parent(t) } return 0 } function init_cap_name2num() { /* set up the names */ cap_name[0]="cap_chown" cap_name[1]="cap_dac_override" cap_name[2]="cap_dac_read_search" cap_name[3]="cap_fowner" cap_name[4]="cap_fsetid" cap_name[5]="cap_kill" cap_name[6]="cap_setgid" cap_name[7]="cap_setuid" cap_name[8]="cap_setpcap" cap_name[9]="cap_linux_immutable" cap_name[10]="cap_net_bind_service" cap_name[11]="cap_net_broadcast" cap_name[12]="cap_net_admin" cap_name[13]="cap_net_raw" cap_name[14]="cap_ipc_lock" cap_name[15]="cap_ipc_owner" cap_name[16]="cap_sys_module" cap_name[17]="cap_sys_rawio" cap_name[18]="cap_sys_chroot" cap_name[19]="cap_sys_ptrace" cap_name[20]="cap_sys_pacct" cap_name[21]="cap_sys_admin" cap_name[22]="cap_sys_boot" cap_name[23]="cap_sys_nice" cap_name[24]="cap_sys_resource" cap_name[25]="cap_sys_time" cap_name[26]="cap_sys_tty_config" cap_name[27]="cap_mknod" cap_name[28]="cap_lease" cap_name[29]="cap_audit_write" cap_name[30]="cap_audit_control" cap_name[31]="cap_setfcap" cap_name[32]="cap_mac_override" cap_name[33]="cap_mac_admin" cap_name[34]="cap_syslog" cap_name[35]="cap_wake_alarm" cap_name[36]="cap_block_suspend" } function parse_capabilities() { /* convert optional list of forbidden capabilities into a bitmask */ caps = 0 cname = tokenize(forbidden_capabilities, "-") while (cname != "") { i =36 while(i>0) { if(cname == cap_name[i]) { caps |= 1<> 1 i += 1 } printf("\n") } printf("\n\ncapabilities used by syscalls\n"); printf("%16s, %20s ( %16s ) : %16s\n", "executable", "syscall", "capability", "count") foreach([e+,s,c] in cap_syscall){ printf("%16s, %20s ( ", e, s); cap = c i=0 while (cap) { if (cap & 1) printf("%16s ", cap_name[i] ); cap = cap >> 1 i += 1 } printf(") : %16d\n", @count(cap_syscall[e,s,c]) ); } printf("\n\nforbidden syscalls\n"); printf("%16s, %20s: %16s\n", "executable", "syscall", "count") foreach([e+,s] in problem_syscall){ printf("%16s, %20s: %16d\n", e, s, @count(problem_syscall[e,s]) ); } printf("\n\nfailed syscalls\n"); printf("%16s, %20s = %16s: %16s\n", "executable", "syscall", "errno", "count") foreach([e+,s,v] in syscall_errno){ printf("%16s, %20s = %16s: %16d\n", e, s, errno_str(v), @count(syscall_errno[e,s,v]) ); } }