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