diff --git a/rpc-add-support-for-filtering-acls-by-uint-params.patch b/rpc-add-support-for-filtering-acls-by-uint-params.patch new file mode 100644 index 0000000..1c9b4e7 --- /dev/null +++ b/rpc-add-support-for-filtering-acls-by-uint-params.patch @@ -0,0 +1,100 @@ +From c0f2166a6c110043b55c484e69d716b1a7f64b64 Mon Sep 17 00:00:00 2001 +From: Jan Tomko +Date: Wed, 14 Oct 2020 17:06:09 +0800 +Subject: [PATCH] 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: Jan Tomko +Reviewed-by: Jiri Denemark + +cherry-pick from commit 50864dcda191eb35732dbd80fb6ca251a6bba923 +Signed-off-by: Jiajie Li +--- + 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 d4393680e9..5f3858c00c 100644 +--- a/src/remote/remote_protocol.x ++++ b/src/remote/remote_protocol.x +@@ -3805,6 +3805,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. +@@ -3814,6 +3815,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 in parameter ++ * against value + * + * - @aclfilter: : + * +diff --git a/src/rpc/gendispatch.pl b/src/rpc/gendispatch.pl +index 6feb1c8320..590a46ef66 100755 +--- a/src/rpc/gendispatch.pl ++++ b/src/rpc/gendispatch.pl +@@ -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") { +-- +2.23.0 +