diff --git a/Makefile.am b/Makefile.am index c52a4cbc43..da07e6c0d2 100644 --- a/Makefile.am +++ b/Makefile.am @@ -67,6 +67,9 @@ rpm: clean check-local: all tests +check-access: + @($(MAKE) $(AM_MAKEFLAGS) -C tests check-access) + cov: clean-cov $(MKDIR_P) $(top_builddir)/coverage $(LCOV) -c -o $(top_builddir)/coverage/libvirt.info.tmp \ diff --git a/tests/Makefile.am b/tests/Makefile.am index ca3c8c34a1..238f6da020 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -451,6 +451,19 @@ test_libraries += virusbmock.la \ $(NULL) endif WITH_LINUX +if WITH_LINUX +check-access: file-access-clean + VIR_TEST_FILE_ACCESS=1 $(MAKE) $(AM_MAKEFLAGS) check + $(PERL) check-file-access.pl | sort -u + +file-access-clean: + > test_file_access.txt +endif WITH_LINUX + +EXTRA_DIST += \ + check-file-access.pl \ + file_access_whitelist.txt + if WITH_TESTS noinst_PROGRAMS = $(test_programs) $(test_helpers) noinst_LTLIBRARIES = $(test_libraries) diff --git a/tests/check-file-access.pl b/tests/check-file-access.pl new file mode 100755 index 0000000000..0c75ae9984 --- /dev/null +++ b/tests/check-file-access.pl @@ -0,0 +1,104 @@ +#!/usr/bin/perl -w +# +# Copyright (C) 2016 Red Hat, Inc. +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library 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 +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library. If not, see +# . +# +# This script is supposed to check test_file_access.txt file and +# warn about file accesses outside our working tree. +# +# + +use strict; +use warnings; + +my $access_file = "test_file_access.txt"; +my $whitelist_file = "file_access_whitelist.txt"; + +my @files; +my @whitelist; + +open FILE, "<", $access_file or die "Unable to open $access_file: $!"; +while () { + chomp; + if (/^(\S*):\s*(\S*)(\s*:\s*(.*))?$/) { + my %rec; + ${rec}{path} = $1; + ${rec}{progname} = $2; + if (defined $4) { + ${rec}{testname} = $4; + } + push (@files, \%rec); + } else { + die "Malformed line $_"; + } +} +close FILE; + +open FILE, "<", $whitelist_file or die "Unable to open $whitelist_file: $!"; +while () { + chomp; + if (/^\s*#.*$/) { + # comment + } elsif (/^(\S*)(:\s*(\S*)(\s*:\s*(.*))?)?$/) { + my %rec; + ${rec}{path} = $1; + if (defined $3) { + ${rec}{progname} = $3; + } + if (defined $5) { + ${rec}{testname} = $5; + } + push (@whitelist, \%rec); + } else { + die "Malformed line $_"; + } +} +close FILE; + +# Now we should check if %traces is included in $whitelist. For +# now checking just keys is sufficient +my $error = 0; +for my $file (@files) { + my $match = 0; + + for my $rule (@whitelist) { + if (not %${file}{path} =~ m/^$rule->{path}$/) { + next; + } + + if (defined %${rule}{progname} and + not %${file}{progname} =~ m/^$rule->{progname}$/) { + next; + } + + if (defined %${rule}{testname} and + defined %${file}{testname} and + not %${file}{testname} =~ m/^$rule->{testname}$/) { + next; + } + + $match = 1; + } + + if (not $match) { + $error = 1; + print "$file->{path}: $file->{progname}"; + print ": $file->{testname}" if defined %${file}{testname}; + print "\n"; + } +} + +exit $error; diff --git a/tests/file_access_whitelist.txt b/tests/file_access_whitelist.txt new file mode 100644 index 0000000000..850b28506e --- /dev/null +++ b/tests/file_access_whitelist.txt @@ -0,0 +1,23 @@ +# This is a whitelist that allows accesses to files not in our +# build directory nor source directory. The records are in the +# following format: +# +# $path: $progname: $testname +# +# All these three are evaluated as perl RE. So to allow /dev/sda +# and /dev/sdb, you can just '/dev/sd[a-b]', or to allow +# /proc/$pid/status you can '/proc/\d+/status' and so on. +# Moreover, $progname and $testname can be empty, in which which +# case $path is allowed for all tests. + +/bin/cat: sysinfotest +/bin/dirname: sysinfotest: x86 sysinfo +/bin/sleep: commandtest +/bin/true: commandtest +/dev/null +/dev/urandom +/etc/hosts +/proc/\d+/status + +# This is just a dummy example, DO NOT USE IT LIKE THAT! +.*: nonexistent-test-touching-everything