1
0
mirror of https://gitlab.com/libvirt/libvirt.git synced 2024-12-22 17:34:18 +03:00

tests: rewrite file access checker in Python

As part of a goal to eliminate Perl from libvirt build tools,
rewrite the check-file-access.pl tool in Python.

This was a straight conversion, manually going line-by-line to
change the syntax from Perl to Python. Thus the overall structure
of the file and approach is the same.

Reviewed-by: Cole Robinson <crobinso@redhat.com>
Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
This commit is contained in:
Daniel P. Berrangé 2019-08-30 13:22:54 +01:00
parent 6ca74054b9
commit 06e6efe294
5 changed files with 128 additions and 133 deletions

View File

@ -52,6 +52,7 @@ EXTRA_DIST = \
scripts/check-aclrules.py \
scripts/check-drivername.py \
scripts/check-driverimpls.py \
scripts/check-file-access.py \
scripts/check-remote-protocol.py \
scripts/check-symfile.py \
scripts/check-symsorting.py \

125
scripts/check-file-access.py Executable file
View File

@ -0,0 +1,125 @@
#!/usr/bin/env python3
#
# Copyright (C) 2016-2019 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
# <http://www.gnu.org/licenses/>.
#
# This script is supposed to check test_file_access.txt file and
# warn about file accesses outside our working tree.
#
#
import re
import sys
if len(sys.argv) != 3:
print("syntax: %s ACCESS-FILE ACCESS-WHITELIST")
sys.exit(1)
access_file = sys.argv[1]
whitelist_file = sys.argv[2]
known_actions = ["open", "fopen", "access", "stat", "lstat", "connect"]
files = []
whitelist = []
with open(access_file, "r") as fh:
for line in fh:
line = line.rstrip("\n")
m = re.search(r'''^(\S*):\s*(\S*):\s*(\S*)(\s*:\s*(.*))?$''', line)
if m is not None:
rec = {
"path": m.group(1),
"action": m.group(2),
"progname": m.group(3),
"testname": m.group(5),
}
files.append(rec)
else:
raise Exception("Malformed line %s" % line)
with open(whitelist_file, "r") as fh:
for line in fh:
line = line.rstrip("\n")
if re.search(r'''^\s*#.*$''', line):
continue # comment
if line == "":
continue
m = re.search(r'''^(\S*):\s*(\S*)(:\s*(\S*)(\s*:\s*(.*))?)?$''', line)
if m is not None and m.group(2) in known_actions:
# $path: $action: $progname: $testname
rec = {
"path": m.group(1),
"action": m.group(3),
"progname": m.group(4),
"testname": m.group(6),
}
whitelist.append(rec)
else:
m = re.search(r'''^(\S*)(:\s*(\S*)(\s*:\s*(.*))?)?$''', line)
if m is not None:
# $path: $progname: $testname
rec = {
"path": m.group(1),
"action": None,
"progname": m.group(3),
"testname": m.group(5),
}
whitelist.append(rec)
else:
raise Exception("Malformed line %s" % line)
# Now we should check if %traces is included in $whitelist. For
# now checking just keys is sufficient
err = False
for file in files:
match = False
for rule in whitelist:
if not re.match("^" + rule["path"] + "$", file["path"]):
continue
if (rule["action"] is not None and
not re.match("^" + rule["action"] + "$", file["action"])):
continue
if (rule["progname"] is not None and
not re.match("^" + rule["progname"] + "$", file["progname"])):
continue
if (rule["testname"] is not None and
file["testname"] is not None and
not re.match("^" + rule["testname"] + "$", file["testname"])):
continue
match = True
if not match:
err = True
print("%s: %s: %s" %
(file["path"], file["action"], file["progname"]),
end="")
if file["testname"] is not None:
print(": %s" % file["testname"], end="")
print("")
if err:
sys.exit(1)
sys.exit(0)

View File

@ -456,7 +456,7 @@ EXTRA_DIST += $(test_scripts)
if WITH_LINUX
check-access: file-access-clean
VIR_TEST_FILE_ACCESS=1 $(MAKE) $(AM_MAKEFLAGS) check
$(PERL) $(abs_srcdir)/check-file-access.pl \
$(RUNUTF8) $(PYTHON) $(top_srcdir)/scripts/check-file-access.py \
$(abs_builddir)/test_file_access.txt \
$(abs_srcdir)/file_access_whitelist.txt | sort -u
@ -465,7 +465,6 @@ file-access-clean:
endif WITH_LINUX
EXTRA_DIST += \
check-file-access.pl \
file_access_whitelist.txt
if WITH_TESTS

View File

@ -1,130 +0,0 @@
#!/usr/bin/env perl
#
# 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
# <http://www.gnu.org/licenses/>.
#
# This script is supposed to check test_file_access.txt file and
# warn about file accesses outside our working tree.
#
#
use strict;
use warnings;
sub usage {
die "$0 access_file file_access_whitelist\n";
}
my $access_file = shift or usage();
my $whitelist_file = shift or usage();
my @known_actions = ("open", "fopen", "access", "stat", "lstat", "connect");
my @files;
my @whitelist;
open FILE, "<", $access_file or die "Unable to open $access_file: $!";
while (<FILE>) {
chomp;
if (/^(\S*):\s*(\S*):\s*(\S*)(\s*:\s*(.*))?$/) {
my %rec;
${rec}{path} = $1;
${rec}{action} = $2;
${rec}{progname} = $3;
if (defined $5) {
${rec}{testname} = $5;
}
push (@files, \%rec);
} else {
die "Malformed line $_";
}
}
close FILE;
open FILE, "<", $whitelist_file or die "Unable to open $whitelist_file: $!";
while (<FILE>) {
chomp;
if (/^\s*#.*$/) {
# comment
} elsif (/^(\S*):\s*(\S*)(:\s*(\S*)(\s*:\s*(.*))?)?$/ and
grep /^$2$/, @known_actions) {
# $path: $action: $progname: $testname
my %rec;
${rec}{path} = $1;
${rec}{action} = $3;
if (defined $4) {
${rec}{progname} = $4;
}
if (defined $6) {
${rec}{testname} = $6;
}
push (@whitelist, \%rec);
} elsif (/^(\S*)(:\s*(\S*)(\s*:\s*(.*))?)?$/) {
# $path: $progname: $testname
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}{action} and
not %${file}{action} =~ m/^$rule->{action}$/) {
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->{action}: $file->{progname}";
print ": $file->{testname}" if defined %${file}{testname};
print "\n";
}
}
exit $error;

View File

@ -5,7 +5,7 @@
# $path: $progname: $testname
# $path: $action: $progname: $testname
#
# All these variables are evaluated as perl RE. So to allow
# All these variables are evaluated as python 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, $action, $progname and $testname can be empty, in which