From 08f8c359dd6a090c1d5668df9f09159c53b55366 Mon Sep 17 00:00:00 2001 Message-Id: <08f8c359dd6a090c1d5668df9f09159c53b55366@dist-git> From: =?UTF-8?q?J=C3=A1n=20Tomko?= Date: Wed, 30 Sep 2020 17:38:13 +0200 Subject: [PATCH] rpc: add support for filtering @acls by uint params MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit CVE-2020-25637 Add a new field to @acl annotations for filtering by unsigned int parameters. Signed-off-by: Ján Tomko (cherry picked from commit 50864dcda191eb35732dbd80fb6ca251a6bba923) Signed-off-by: Ján Tomko Message-Id: <92146976a682e6cc7e1490bcc542e9155a0207fb.1601480224.git.jtomko@redhat.com> Reviewed-by: Jiri Denemark --- src/remote/remote_protocol.x | 3 +++ src/rpc/gendispatch.pl | 21 ++++++++++++++++++++- 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/src/remote/remote_protocol.x b/src/remote/remote_protocol.x index 52b92334fa..c370755f68 100644 --- a/src/remote/remote_protocol.x +++ b/src/remote/remote_protocol.x @@ -3591,6 +3591,7 @@ enum remote_procedure { * * - @acl: : * - @acl: :: + * - @acl: :::: * * Declare the access control requirements for the API. May be repeated * multiple times, if multiple rules are required. @@ -3600,6 +3601,8 @@ enum remote_procedure { * is one of the permissions in access/viraccessperm.h * indicates the rule only applies if the named flag * is set in the API call + * and can be used to check an unsigned int parameter + * against value * * - @aclfilter: : * diff --git a/src/rpc/gendispatch.pl b/src/rpc/gendispatch.pl index c243ac200f..cec3736066 100755 --- a/src/rpc/gendispatch.pl +++ b/src/rpc/gendispatch.pl @@ -2093,10 +2093,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"; @@ -2104,6 +2106,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}; @@ -2137,6 +2142,9 @@ elsif ($mode eq "client") { if ($checkflags) { push @argdecls, "unsigned int flags"; } + if (defined $paramtocheck) { + push @argdecls, "unsigned int " . $paramtocheck; + } my $ret; my $pass; @@ -2195,6 +2203,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") { -- 2.28.0