Firejail: [Enhancement] syscall script

Created on 1 Jun 2019  路  11Comments  路  Source: netblue30/firejail

There is a link on the homepage of this project to a script on https://github.com/avilum/syscalls to get a list a syscalls.

I suggest an improved and more useful script:

#!/bin/bash

echo -e "Execute this as:\n"
echo -e "\e[96m   syscalls /full/path/to/program\n"
echo -e "\e[39mif you saved this script in a directory in your PATH (e.g., in ${HOME}/bin), otherwise as:\n"
echo -e "\e[96m   ./syscalls /full/path/to/program\n"
echo -e "\e[39mUse the full path to the respective program to avoid executing it sandboxed with Firejail (if a Firejail profile for it already exits and 'sudo firecfg' was executed earlier)\nin order to determine the necessary system calls."
echo
STRACE_OUTPUT_FILE="$(pwd)/strace_output.txt"
SYSCALLS_OUTPUT_FILE="$(pwd)/syscalls.txt"
SYSCALLS_SORTED="$(pwd)/syscalls_sorted.txt"


strace -o $STRACE_OUTPUT_FILE "$@" && grep -oP '^.+?(?=\()' $STRACE_OUTPUT_FILE > $SYSCALLS_OUTPUT_FILE
echo -e "The syscalls for the executed program were saved to:\n\n\e[96m$SYSCALLS_OUTPUT_FILE"
sort -u < $SYSCALLS_OUTPUT_FILE | awk -vORS=, '{ print $1 }' | sed 's/,$/\n/' > $SYSCALLS_SORTED
echo
echo -e "\e[39mThese are the syscalls sorted and deduplicated:\n\e[93m"
cat $SYSCALLS_SORTED
echo
echo -e "\e[39mThe sorted and deduplicated syscalls were saved to:\n\n\e[96m$SYSCALLS_SORTED"
exit 0

It produces a comma-delimited line with an alphabetized and deduplicated list of the necessary syscalls ready to be copied over to a profile. I suggest to add it as a helper script to this repo.

Feel free to modify it if necessary. I'm not a scripting expert so improvements are certainly possible.

enhancement

Most helpful comment

Wouldn't it be more robust to use strace -c rather than parsing normal strace output? It produces this kind of summary:

% time     seconds  usecs/call     calls    errors syscall
------ ----------- ----------- --------- --------- ----------------
 53,95    0,026222          54       478        23 openat
 24,74    0,012027          55       215           stat
 11,11    0,005400          12       440           read
  8,11    0,003944           8       455           close
  0,55    0,000265           8        30           fstat
  0,40    0,000196          98         2           getdents64
  0,28    0,000134           2        63           mmap
  0,20    0,000097           5        17           mprotect
  0,18    0,000089           3        24           rt_sigaction
  0,18    0,000086          43         2           ioctl
  0,10    0,000051          17         3           readlink
  0,07    0,000036           9         4           write
  0,03    0,000014          14         1           munmap
  0,02    0,000009           4         2           lseek
  0,02    0,000009           3         3           brk
  0,01    0,000005           5         1           futex
  0,01    0,000004           4         1           geteuid
  0,01    0,000004           4         1           arch_prctl
  0,01    0,000004           4         1           set_tid_address
  0,01    0,000004           4         1           set_robust_list
  0,01    0,000004           4         1           prlimit64
  0,01    0,000003           3         1           rt_sigprocmask
  0,00    0,000000           0         1           access
  0,00    0,000000           0         1           execve
------ ----------- ----------- --------- --------- ----------------
100.00    0,048607                  1748        23 total

All 11 comments

I used shellcheck to clean it up a bit:

#!/bin/bash

echo -e "Execute this as:\\n"
echo -e "\\e[96m   syscalls /full/path/to/program\\n"
echo -e "\\e[39mif you saved this script in a directory in your PATH (e.g., in ${HOME}/bin), otherwise as:\\n"
echo -e "\\e[96m   ./syscalls /full/path/to/program\\n"
echo -e "\\e[39mUse the full path to the respective program to avoid executing it sandboxed with Firejail (if a Firejail profile for it already exits and 'sudo firecfg' was executed earlier)\\nin order to determine the necessary system calls."
echo
STRACE_OUTPUT_FILE="$(pwd)/strace_output.txt"
SYSCALLS_OUTPUT_FILE="$(pwd)/syscalls.txt"
SYSCALLS_SORTED="$(pwd)/syscalls_sorted.txt"


strace -o "$STRACE_OUTPUT_FILE" "$@" && grep -oP '^.+?(?=\()' "$STRACE_OUTPUT_FILE" > "$SYSCALLS_OUTPUT_FILE"
echo -e "The syscalls for the executed program were saved to:\\n\\n\\e[96m$SYSCALLS_OUTPUT_FILE"
sort -u < "$SYSCALLS_OUTPUT_FILE" | awk -vORS=, '{ print $1 }' | sed 's/,$/\n/' > "$SYSCALLS_SORTED"
echo
echo -e "\\e[39mThese are the syscalls sorted and deduplicated:\\n\\e[93m"
cat "$SYSCALLS_SORTED"
echo
echo -e "\\e[39mThe sorted and deduplicated syscalls were saved to:\\n\\n\\e[96m$SYSCALLS_SORTED"
exit 0

(mostly just explicitly escaping backslashes, but quoting in a couple of places).

Thanks! I wasn't aware of shellcheck.

I also tried it and it only recommends "Double quote to prevent globbing and word splitting". Escaping the backslashes didn't make a difference for me.

Hmm...interesting. Maybe a newer version then?

It's shellcheck 0.6.0-106 on Manjaro.

Hmm, I have an older version (0.5.0 on Debian sid/experimental). That's probably it then.
[edit] [Yup](https://github.com/koalaman/shellcheck/wiki/SC1117) - it was retired after version 0.5 :joy:.

Here's an improved version which checks for an input argument:

#!/bin/bash

STRACE_OUTPUT_FILE="$(pwd)/strace_output.txt"
SYSCALLS_OUTPUT_FILE="$(pwd)/syscalls.txt"
SYSCALLS_SORTED="$(pwd)/syscalls_sorted.txt"

if [ $# -eq 0 ]
then
echo
echo "No program specified!"
echo    
echo -e "Execute this as:\\n"
echo -e "\\e[96m   syscalls /full/path/to/program\\n"
echo -e "\\e[39mif you saved this script in a directory in your PATH (e.g., in ${HOME}/bin), otherwise as:\\n"
echo -e "\\e[96m   ./syscalls /full/path/to/program\\n"
echo -e "\\e[39mUse the full path to the respective program to avoid executing it sandboxed with Firejail (if a Firejail profile for it already exits and 'sudo firecfg' was executed earlier)\\nin order to determine the necessary system calls."
echo
exit 0

else

strace -o "$STRACE_OUTPUT_FILE" "$@" && grep -oP '^.+?(?=\()' "$STRACE_OUTPUT_FILE" > "$SYSCALLS_OUTPUT_FILE"
echo -e "The syscalls for the executed program were saved to:\\n\\n\\e[96m$SYSCALLS_OUTPUT_FILE"
sort -u < "$SYSCALLS_OUTPUT_FILE" | awk -vORS=, '{ print $1 }' | sed 's/,$/\n/' > "$SYSCALLS_SORTED"
echo
echo -e "\\e[39mThese are the syscalls sorted and deduplicated:\\n\\e[93m"
cat "$SYSCALLS_SORTED"
echo
echo -e "\\e[39mThe sorted and deduplicated syscalls were saved to:\\n\\n\\e[96m$SYSCALLS_SORTED"
echo
exit 0

fi

Wouldn't it be more robust to use strace -c rather than parsing normal strace output? It produces this kind of summary:

% time     seconds  usecs/call     calls    errors syscall
------ ----------- ----------- --------- --------- ----------------
 53,95    0,026222          54       478        23 openat
 24,74    0,012027          55       215           stat
 11,11    0,005400          12       440           read
  8,11    0,003944           8       455           close
  0,55    0,000265           8        30           fstat
  0,40    0,000196          98         2           getdents64
  0,28    0,000134           2        63           mmap
  0,20    0,000097           5        17           mprotect
  0,18    0,000089           3        24           rt_sigaction
  0,18    0,000086          43         2           ioctl
  0,10    0,000051          17         3           readlink
  0,07    0,000036           9         4           write
  0,03    0,000014          14         1           munmap
  0,02    0,000009           4         2           lseek
  0,02    0,000009           3         3           brk
  0,01    0,000005           5         1           futex
  0,01    0,000004           4         1           geteuid
  0,01    0,000004           4         1           arch_prctl
  0,01    0,000004           4         1           set_tid_address
  0,01    0,000004           4         1           set_robust_list
  0,01    0,000004           4         1           prlimit64
  0,01    0,000003           3         1           rt_sigprocmask
  0,00    0,000000           0         1           access
  0,00    0,000000           0         1           execve
------ ----------- ----------- --------- --------- ----------------
100.00    0,048607                  1748        23 total

@topimiettinen : I guess, you're right. This could be done this way:

#!/bin/bash

STRACE_OUTPUT_FILE="$(pwd)/strace_output.txt"
SYSCALLS_OUTPUT_FILE="$(pwd)/syscalls.txt"
SYSCALLS_SORTED="$(pwd)/syscalls_sorted.txt"

if [ $# -eq 0 ]
then
echo
echo "   *** No program specified!!! ***"
echo    
echo -e "Execute this as:\\n"
echo -e "\\e[96m   syscalls /full/path/to/program\\n"
echo -e "\\e[39mif you saved this script in a directory in your PATH (e.g., in ${HOME}/bin), otherwise as:\\n"
echo -e "\\e[96m   ./syscalls /full/path/to/program\\n"
echo -e "\\e[39mUse the full path to the respective program to avoid executing it sandboxed with Firejail\\n(if a Firejail profile for it already exits and 'sudo firecfg' was executed earlier)\\nin order to determine the necessary system calls."
echo
exit 0

else

strace -cfo $STRACE_OUTPUT_FILE "$@" && awk '{print $NF}' $STRACE_OUTPUT_FILE | sed '/syscall\|-\|total/d' > $SYSCALLS_OUTPUT_FILE
echo -e "The syscalls were saved to:\n\n\e[96m$SYSCALLS_OUTPUT_FILE"
sort -u < $SYSCALLS_OUTPUT_FILE  | awk -vORS=, '{ print $1 }' | sed 's/,$/\n/' > $SYSCALLS_SORTED
echo
echo -e "\e[39mThese are the syscalls sorted and deduplicated:\n\e[93m"
cat $SYSCALLS_SORTED
echo
echo -e "\e[39mThe sorted and deduplicated syscalls were saved to:\n\n\e[96m$SYSCALLS_SORTED"
exit 0

fi

Actually this can be simplified:

#!/bin/bash

STRACE_OUTPUT_FILE="$(pwd)/strace_output.txt"
SYSCALLS_OUTPUT_FILE="$(pwd)/syscalls.txt"

if [ $# -eq 0 ]
then
echo
echo "   *** No program specified!!! ***"
echo    
echo -e "Execute this as:\\n"
echo -e "\\e[96m   syscalls /full/path/to/program\\n"
echo -e "\\e[39mif you saved this script in a directory in your PATH (e.g., in ${HOME}/bin), otherwise as:\\n"
echo -e "\\e[96m   ./syscalls /full/path/to/program\\n"
echo -e "\\e[39mUse the full path to the respective program to avoid executing it sandboxed with Firejail\\n(if a Firejail profile for it already exits and 'sudo firecfg' was executed earlier)\\nin order to determine the necessary system calls."
echo
exit 0

else

strace -cfo $STRACE_OUTPUT_FILE "$@" && awk '{print $NF}' $STRACE_OUTPUT_FILE | sed '/syscall\|-\|total/d' | sort -u | awk -vORS=, '{ print $1 }' | sed 's/,$/\n/' > $SYSCALLS_OUTPUT_FILE
echo
echo -e "\e[39mThese are the sorted syscalls:\n\e[93m"
cat $SYSCALLS_OUTPUT_FILE
echo
echo -e "\e[39mThe sorted syscalls were saved to:\n\n\e[96m$SYSCALLS_OUTPUT_FILE"
echo
exit 0

fi

@curiosity-seeker - we can add the script in contrib directory, send a pull request! All the files there are installed in /usr/lib/firejail directory.

Thanks! Done!

Was this page helpful?
0 / 5 - 0 ratings

Related issues

kmotoko picture kmotoko  路  3Comments

ghost picture ghost  路  3Comments

ericschdt picture ericschdt  路  3Comments

Vincent43 picture Vincent43  路  3Comments

bryce-lynch picture bryce-lynch  路  4Comments