From 61295cefe491504ed50a2046f6cd9e3786370538 Mon Sep 17 00:00:00 2001 From: netblue30 Date: Thu, 19 Mar 2020 08:28:58 -0400 Subject: profile stats --- .gitignore | 1 + Makefile.in | 3 +- README.md | 23 +++++ configure | 17 +++- configure.ac | 3 +- src/profstats/Makefile.in | 14 +++ src/profstats/main.c | 240 ++++++++++++++++++++++++++++++++++++++++++++++ 7 files changed, 297 insertions(+), 4 deletions(-) create mode 100644 src/profstats/Makefile.in create mode 100644 src/profstats/main.c diff --git a/.gitignore b/.gitignore index 9995da44c..661370b02 100644 --- a/.gitignore +++ b/.gitignore @@ -33,6 +33,7 @@ src/fsec-optimize/fsec-optimize src/fcopy/fcopy src/fldd/fldd src/fbuilder/fbuilder +etc/profstats uids.h seccomp seccomp.debug diff --git a/Makefile.in b/Makefile.in index 0285d8592..f7c94aa09 100644 --- a/Makefile.in +++ b/Makefile.in @@ -1,6 +1,7 @@ all: apps man filters MYLIBS = src/lib -APPS = src/firejail src/firemon src/fsec-print src/fsec-optimize src/firecfg src/fnetfilter src/libtrace src/libtracelog src/ftee src/faudit src/fnet src/fseccomp src/fbuilder src/fcopy src/fldd src/libpostexecseccomp +APPS = src/firejail src/firemon src/fsec-print src/fsec-optimize src/firecfg src/fnetfilter src/libtrace src/libtracelog src/ftee \ +src/faudit src/fnet src/fseccomp src/fbuilder src/fcopy src/fldd src/libpostexecseccomp src/profstats MANPAGES = firejail.1 firemon.1 firecfg.1 firejail-profile.5 firejail-login.5 firejail-users.5 SECCOMP_FILTERS = seccomp seccomp.debug seccomp.32 seccomp.block_secondary seccomp.mdwx diff --git a/README.md b/README.md index 8fc636194..58db16108 100644 --- a/README.md +++ b/README.md @@ -149,6 +149,29 @@ We also keep a list of profile fixes for previous released versions in [etc-fixe ## Current development version: 0.9.63 +### Profile Statistics + +A small tool to print profile statistics. Compile as usual (the executable is placed in etc directory( and run: +````` +$ make +$ cd etc +$ ./profstats *.profile +Stats: + profiles 925 + include local profile 925 (include profile-name.local) + include globals 925 (include globals.local) + blacklist ~/.ssh 910 (include disable-common.inc) + seccomp 868 + capabilities 924 + noexec 785 (include disable-exec.inc) + apparmor 426 + private-dev 788 + private-tmp 687 + whitelist var directory 595 (include whitelist-var-common.inc) + net none 274 + +Run ./profstats -h for help. + ### New profiles: gfeeds, firefox-x11, tvbrowser, rtv, clipgrab, gnome-passwordsafe, bibtex, gummi, latex, pdflatex, tex, wpp, wpspdf, wps, et, multimc, gnome-hexgl, com.github.johnfactotum.Foliate, desktopeditors, impressive, mupdf-gl, mupdf-x11, mupdf-x11-curl, muraster, mutool, planmaker18, planmaker18free, presentations18, presentations18free, textmaker18, textmaker18free, teams, xournal, gnome-screenshot diff --git a/configure b/configure index 53ea8f19d..f587bb25e 100755 --- a/configure +++ b/configure @@ -683,6 +683,7 @@ infodir docdir oldincludedir includedir +runstatedir localstatedir sharedstatedir sysconfdir @@ -776,6 +777,7 @@ datadir='${datarootdir}' sysconfdir='${prefix}/etc' sharedstatedir='${prefix}/com' localstatedir='${prefix}/var' +runstatedir='${localstatedir}/run' includedir='${prefix}/include' oldincludedir='/usr/include' docdir='${datarootdir}/doc/${PACKAGE_TARNAME}' @@ -1028,6 +1030,15 @@ do | -silent | --silent | --silen | --sile | --sil) silent=yes ;; + -runstatedir | --runstatedir | --runstatedi | --runstated \ + | --runstate | --runstat | --runsta | --runst | --runs \ + | --run | --ru | --r) + ac_prev=runstatedir ;; + -runstatedir=* | --runstatedir=* | --runstatedi=* | --runstated=* \ + | --runstate=* | --runstat=* | --runsta=* | --runst=* | --runs=* \ + | --run=* | --ru=* | --r=*) + runstatedir=$ac_optarg ;; + -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) ac_prev=sbindir ;; -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ @@ -1165,7 +1176,7 @@ fi for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \ datadir sysconfdir sharedstatedir localstatedir includedir \ oldincludedir docdir infodir htmldir dvidir pdfdir psdir \ - libdir localedir mandir + libdir localedir mandir runstatedir do eval ac_val=\$$ac_var # Remove trailing slashes. @@ -1318,6 +1329,7 @@ Fine tuning of the installation directories: --sysconfdir=DIR read-only single-machine data [PREFIX/etc] --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com] --localstatedir=DIR modifiable single-machine data [PREFIX/var] + --runstatedir=DIR modifiable per-process data [LOCALSTATEDIR/run] --libdir=DIR object code libraries [EPREFIX/lib] --includedir=DIR C header files [PREFIX/include] --oldincludedir=DIR C header files for non-gcc [/usr/include] @@ -4174,7 +4186,7 @@ if test "$prefix" = /usr; then test "$sysconfdir" = '${prefix}/etc' && sysconfdir="/etc" fi -ac_config_files="$ac_config_files Makefile src/common.mk src/lib/Makefile src/fcopy/Makefile src/fnet/Makefile src/firejail/Makefile src/fnetfilter/Makefile src/firemon/Makefile src/libtrace/Makefile src/libtracelog/Makefile src/firecfg/Makefile src/fbuilder/Makefile src/fsec-print/Makefile src/ftee/Makefile src/faudit/Makefile src/fseccomp/Makefile src/fldd/Makefile src/libpostexecseccomp/Makefile src/fsec-optimize/Makefile" +ac_config_files="$ac_config_files Makefile src/common.mk src/lib/Makefile src/fcopy/Makefile src/fnet/Makefile src/firejail/Makefile src/fnetfilter/Makefile src/firemon/Makefile src/libtrace/Makefile src/libtracelog/Makefile src/firecfg/Makefile src/fbuilder/Makefile src/fsec-print/Makefile src/ftee/Makefile src/faudit/Makefile src/fseccomp/Makefile src/fldd/Makefile src/libpostexecseccomp/Makefile src/fsec-optimize/Makefile src/profstats/Makefile" cat >confcache <<\_ACEOF # This file is a shell script that caches the results of configure @@ -4902,6 +4914,7 @@ do "src/fldd/Makefile") CONFIG_FILES="$CONFIG_FILES src/fldd/Makefile" ;; "src/libpostexecseccomp/Makefile") CONFIG_FILES="$CONFIG_FILES src/libpostexecseccomp/Makefile" ;; "src/fsec-optimize/Makefile") CONFIG_FILES="$CONFIG_FILES src/fsec-optimize/Makefile" ;; + "src/profstats/Makefile") CONFIG_FILES="$CONFIG_FILES src/profstats/Makefile" ;; *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;; esac diff --git a/configure.ac b/configure.ac index 3c9f901cb..8cf170c80 100644 --- a/configure.ac +++ b/configure.ac @@ -206,7 +206,8 @@ fi AC_OUTPUT(Makefile src/common.mk src/lib/Makefile src/fcopy/Makefile src/fnet/Makefile src/firejail/Makefile src/fnetfilter/Makefile \ src/firemon/Makefile src/libtrace/Makefile src/libtracelog/Makefile src/firecfg/Makefile src/fbuilder/Makefile src/fsec-print/Makefile \ -src/ftee/Makefile src/faudit/Makefile src/fseccomp/Makefile src/fldd/Makefile src/libpostexecseccomp/Makefile src/fsec-optimize/Makefile) +src/ftee/Makefile src/faudit/Makefile src/fseccomp/Makefile src/fldd/Makefile src/libpostexecseccomp/Makefile src/fsec-optimize/Makefile \ +src/profstats/Makefile) echo echo "Configuration options:" diff --git a/src/profstats/Makefile.in b/src/profstats/Makefile.in new file mode 100644 index 000000000..4ada23c23 --- /dev/null +++ b/src/profstats/Makefile.in @@ -0,0 +1,14 @@ +all: ../../etc/profstats + +include ../common.mk + +%.o : %.c $(H_FILE_LIST) + $(CC) $(CFLAGS) $(EXTRA_CFLAGS) $(INCLUDE) -c $< -o $@ + +../../etc/profstats: $(OBJS) + $(CC) $(LDFLAGS) -o $@ $(OBJS) $(LIBS) $(EXTRA_LDFLAGS) + +clean:; rm -fr *.o ../../etc/profstats *.gcov *.gcda *.gcno *.plist + +distclean: clean + rm -fr Makefile diff --git a/src/profstats/main.c b/src/profstats/main.c new file mode 100644 index 000000000..775142643 --- /dev/null +++ b/src/profstats/main.c @@ -0,0 +1,240 @@ + /* + * Copyright (C) 2014-2020 Firejail Authors + * + * This file is part of firejail project + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ +#include +#include +#include +#include + +#define MAXBUF 2048 +// stats +static int cnt_profiles = 0; +static int cnt_apparmor = 0; +static int cnt_seccomp = 0; +static int cnt_caps = 0; +static int cnt_dotlocal = 0; +static int cnt_globalsdotlocal = 0; +static int cnt_netnone = 0; +static int cnt_noexec = 0; // include disable-exec.inc +static int cnt_privatedev = 0; +static int cnt_privatetmp = 0; +static int cnt_whitelistvar = 0; // include whitelist-var-common.inc +static int cnt_ssh = 0; + +static int level = 0; +static int arg_debug = 0; +static int arg_apparmor = 0; +static int arg_caps = 0; +static int arg_seccomp = 0; +static int arg_noexec = 0; +static int arg_privatedev = 0; +static int arg_privatetmp = 0; +static int arg_whitelistvar = 0; +static int arg_ssh = 0; + +static void usage(void) { + printf("proftool - print profile statistics\n"); + printf("Usage: proftool [options] file[s]\n"); + printf("Options:\n"); + printf(" --apparmor - print profiles without apparmor\n"); + printf(" --caps - print profiles without caps\n"); + printf(" --ssh - print profiles without \"include disable-common.inc\"\n"); + printf(" --noexec - print profiles without \"include disable-exec.inc\"\n"); + printf(" --private-dev - print profiles without private-dev\n"); + printf(" --private-tmp - print profiles without private-tmp\n"); + printf(" --seccomp - print profiles without seccomp\n"); + printf(" --whitelist-var - print profiles without \"include whitelist-var-common.inc\"\n"); + printf(" --debug\n"); + printf("\n"); +} + +void process_file(const char *fname) { + assert(fname); + + if (arg_debug) + printf("processing #%s#\n", fname); + level++; + assert(level < 32); // to do - check in firejail code + + FILE *fp = fopen(fname, "r"); + if (!fp) { + fprintf(stderr, "Error: cannot open %s\n", fname); + exit(1); + } + + char buf[MAXBUF]; + while (fgets(buf, MAXBUF, fp)) { + char *ptr = strchr(buf, '\n'); + if (ptr) + *ptr = '\0'; + ptr = buf; + + while (*ptr == ' ' || *ptr == '\t') + ptr++; + if (*ptr == '\n' || *ptr == '#') + continue; + + if (strncmp(ptr, "seccomp", 7) == 0) + cnt_seccomp++; + else if (strncmp(ptr, "caps", 4) == 0) + cnt_caps++; + else if (strncmp(ptr, "include disable-exec.inc", 24) == 0) + cnt_noexec++; + else if (strncmp(ptr, "include whitelist-var-common.inc", 32) == 0) + cnt_whitelistvar++; + else if (strncmp(ptr, "include disable-common.inc", 26) == 0) + cnt_ssh++; + else if (strncmp(ptr, "net none", 8) == 0) + cnt_netnone++; + else if (strncmp(ptr, "apparmor", 8) == 0) + cnt_apparmor++; + else if (strncmp(ptr, "private-dev", 11) == 0) + cnt_privatedev++; + else if (strncmp(ptr, "private-tmp", 11) == 0) + cnt_privatetmp++; + else if (strncmp(ptr, "include ", 8) == 0) { + // not processing .local files + if (strstr(ptr, ".local")) { +//printf("dotlocal %d, level %d - #%s#, redirect #%s#\n", cnt_dotlocal, level, fname, buf + 8); + if (strstr(ptr, "globals.local")) + cnt_globalsdotlocal++; + else + cnt_dotlocal++; + continue; + } + process_file(buf + 8); + } + } + + fclose(fp); + level--; +} + +int main(int argc, char **argv) { + if (argc <= 1) { + usage(); + return 1; + } + + int start = 1; + int i; + for (i = 1; i < argc; i++) { + if (strcmp(argv[i], "--help") == 0) { + usage(); + return 0; + } + else if (strcmp(argv[i], "--debug") == 0) + arg_debug = 1; + else if (strcmp(argv[i], "--apparmor") == 0) + arg_apparmor = 1; + else if (strcmp(argv[i], "--caps") == 0) + arg_caps = 1; + else if (strcmp(argv[i], "--seccomp") == 0) + arg_seccomp = 1; + else if (strcmp(argv[i], "--noexec") == 0) + arg_noexec = 1; + else if (strcmp(argv[i], "--private-dev") == 0) + arg_privatedev = 1; + else if (strcmp(argv[i], "--private-tmp") == 0) + arg_privatetmp = 1; + else if (strcmp(argv[i], "--whitelist-var") == 0) + arg_whitelistvar = 1; + else if (strcmp(argv[i], "--ssh") == 0) + arg_ssh = 1; + else if (*argv[i] == '-') { + fprintf(stderr, "Error: invalid option %s\n", argv[i]); + return 1; + } + else + break; + } + + start = i; + if (i == argc) { + fprintf(stderr, "Error: no porfile file specified\n"); + return 1; + } + + for (i = start; i < argc; i++) { + cnt_profiles++; + + // watch seccomp + int seccomp = cnt_seccomp; + int caps = cnt_caps; + int apparmor = cnt_apparmor; + int noexec = cnt_noexec; + int privatetmp = cnt_privatetmp; + int privatedev = cnt_privatedev; + int dotlocal = cnt_dotlocal; + int globalsdotlocal = cnt_globalsdotlocal; + int whitelistvar = cnt_whitelistvar; + int ssh = cnt_ssh; + + // process file + process_file(argv[i]); + + // warnings + if ((caps + 2) <= cnt_caps) { + printf("Warning: multiple caps in %s\n", argv[i]); + cnt_caps = caps + 1; + } + + // fix redirections + if (cnt_dotlocal > (dotlocal + 1)) + cnt_dotlocal = dotlocal + 1; + if (cnt_globalsdotlocal > (globalsdotlocal + 1)) + cnt_globalsdotlocal = globalsdotlocal + 1; + + if (arg_apparmor && apparmor == cnt_apparmor) + printf("No apparmor found in %s\n", argv[i]); + if (arg_caps && caps == cnt_caps) + printf("No caps found in %s\n", argv[i]); + if (arg_seccomp && seccomp == cnt_seccomp) + printf("No seccomp found in %s\n", argv[i]); + if (arg_noexec && noexec == cnt_noexec) + printf("No include disable-exec.inc found in %s\n", argv[i]); + if (arg_privatedev && privatedev == cnt_privatedev) + printf("No private-dev found in %s\n", argv[i]); + if (arg_privatetmp && privatetmp == cnt_privatetmp) + printf("No private-tmp found in %s\n", argv[i]); + if (arg_whitelistvar && whitelistvar == cnt_whitelistvar) + printf("No include whitelist-var-common.inc found in %s\n", argv[i]); + if (arg_ssh && ssh == cnt_ssh) + printf("No include disable-common.inc found in %s\n", argv[i]); + + assert(level == 0); + } + + printf("\n"); + printf("Stats:\n"); + printf(" profiles\t\t\t%d\n", cnt_profiles); + printf(" include local profile\t%d (include profile-name.local)\n", cnt_dotlocal); + printf(" include globals\t\t%d (include globals.local)\n", cnt_dotlocal); + printf(" blacklist ~/.ssh\t\t%d (include disable-common.inc)\n", cnt_ssh); + printf(" seccomp\t\t\t%d\n", cnt_seccomp); + printf(" capabilities\t\t%d\n", cnt_caps); + printf(" noexec\t\t\t%d (include disable-exec.inc)\n", cnt_noexec); + printf(" apparmor\t\t\t%d\n", cnt_apparmor); + printf(" private-dev\t\t\t%d\n", cnt_privatedev); + printf(" private-tmp\t\t\t%d\n", cnt_privatetmp); + printf(" whitelist var directory\t%d (include whitelist-var-common.inc)\n", cnt_whitelistvar); + printf(" net none\t\t\t%d\n", cnt_netnone); + printf("\n"); + return 0; +} \ No newline at end of file -- cgit v1.2.3-54-g00ecf