rpc: add support for filtering @acls by uint params

CVE-2020-25637

Add a new field to @acl annotations for filtering by
unsigned int parameters.

Signed-off-by: Ján Tomko <jtomko@redhat.com>
Reviewed-by: Jiri Denemark <jdenemar@redhat.com>
This commit is contained in:
Ján Tomko 2020-09-18 16:09:25 +02:00
parent 955029bd0a
commit 50864dcda1
2 changed files with 23 additions and 1 deletions

View File

@ -3805,6 +3805,7 @@ enum remote_procedure {
*
* - @acl: <object>:<permission>
* - @acl: <object>:<permission>:<flagname>
* - @acl: <object>:<permission>::<param>:<value>
*
* Declare the access control requirements for the API. May be repeated
* multiple times, if multiple rules are required.
@ -3814,6 +3815,8 @@ enum remote_procedure {
* <permission> is one of the permissions in access/viraccessperm.h
* <flagname> indicates the rule only applies if the named flag
* is set in the API call
* <param> and <value> can be used to check an unsigned int parameter
* against value
*
* - @aclfilter: <object>:<permission>
*

View File

@ -2111,10 +2111,12 @@ elsif ($mode eq "client") {
my @acl;
foreach (@{$acl}) {
my @bits = split /:/;
push @acl, { object => $bits[0], perm => $bits[1], flags => $bits[2] }
push @acl, { object => $bits[0], perm => $bits[1], flags => $bits[2],
param => $bits[3], value => $bits[4] }
}
my $checkflags = 0;
my $paramtocheck = undef;
for (my $i = 1 ; $i <= $#acl ; $i++) {
if ($acl[$i]->{object} ne $acl[0]->{object}) {
die "acl for '$call->{ProcName}' cannot check different objects";
@ -2122,6 +2124,9 @@ elsif ($mode eq "client") {
if (defined $acl[$i]->{flags} && length $acl[$i]->{flags}) {
$checkflags = 1;
}
if (defined $acl[$i]->{param}) {
$paramtocheck = $acl[$i]->{param};
}
}
my $apiname = $prefix . $call->{ProcName};
@ -2157,6 +2162,9 @@ elsif ($mode eq "client") {
if ($checkflags) {
push @argdecls, "unsigned int flags";
}
if (defined $paramtocheck) {
push @argdecls, "unsigned int " . $paramtocheck;
}
my $ret;
my $pass;
@ -2217,6 +2225,17 @@ elsif ($mode eq "client") {
}
print " ";
}
if (defined $acl->{param}) {
my $param = $acl->{param};
my $value = $acl->{value};
if ($value =~ /^\!/) {
$value = substr $value, 1;
print "($param != ($value)) &&\n";
} else {
print "($param == ($value)) &&\n";
}
print " ";
}
print "(rv = $method(" . join(", ", @argvars, $perm) . ")) <= 0) {\n";
print " virObjectUnref(mgr);\n";
if ($action eq "Ensure") {