Blame SOURCES/kvm-virtiofsd-stay-below-fs.file-max-sysctl-value-CVE-20.patch

77c23f
From 301f19f2ebd617e43e3a8e7bdcf694de580fe689 Mon Sep 17 00:00:00 2001
77c23f
From: "Dr. David Alan Gilbert" <dgilbert@redhat.com>
77c23f
Date: Tue, 5 May 2020 16:35:56 +0100
77c23f
Subject: [PATCH 5/9] virtiofsd: stay below fs.file-max sysctl value
77c23f
 (CVE-2020-10717)
77c23f
77c23f
RH-Author: Dr. David Alan Gilbert <dgilbert@redhat.com>
77c23f
Message-id: <20200505163600.22956-4-dgilbert@redhat.com>
77c23f
Patchwork-id: 96271
77c23f
O-Subject: [RHEL-AV-8.2.1 qemu-kvm PATCH 3/7] virtiofsd: stay below fs.file-max sysctl value (CVE-2020-10717)
77c23f
Bugzilla: 1817445
77c23f
RH-Acked-by: Stefan Hajnoczi <stefanha@redhat.com>
77c23f
RH-Acked-by: Max Reitz <mreitz@redhat.com>
77c23f
RH-Acked-by: Michael S. Tsirkin <mst@redhat.com>
77c23f
77c23f
From: Stefan Hajnoczi <stefanha@redhat.com>
77c23f
77c23f
The system-wide fs.file-max sysctl value determines how many files can
77c23f
be open.  It defaults to a value calculated based on the machine's RAM
77c23f
size.  Previously virtiofsd would try to set RLIMIT_NOFILE to 1,000,000
77c23f
and this allowed the FUSE client to exhaust the number of open files
77c23f
system-wide on Linux hosts with less than 10 GB of RAM!
77c23f
77c23f
Take fs.file-max into account when choosing the default RLIMIT_NOFILE
77c23f
value.
77c23f
77c23f
Fixes: CVE-2020-10717
77c23f
Reported-by: Yuval Avrahami <yavrahami@paloaltonetworks.com>
77c23f
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
77c23f
Reviewed-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
77c23f
Message-Id: <20200501140644.220940-3-stefanha@redhat.com>
77c23f
Signed-off-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
77c23f
(cherry picked from commit 8c1d353d107b4fc344e27f2f08ea7fa25de2eea2)
77c23f
Signed-off-by: Danilo C. L. de Paula <ddepaula@redhat.com>
77c23f
---
77c23f
 tools/virtiofsd/helper.c | 26 +++++++++++++++++++++++++-
77c23f
 1 file changed, 25 insertions(+), 1 deletion(-)
77c23f
77c23f
diff --git a/tools/virtiofsd/helper.c b/tools/virtiofsd/helper.c
77c23f
index 9b3eddc..5b222ea 100644
77c23f
--- a/tools/virtiofsd/helper.c
77c23f
+++ b/tools/virtiofsd/helper.c
77c23f
@@ -176,7 +176,8 @@ void fuse_cmdline_help(void)
77c23f
            "                               default: no_xattr\n"
77c23f
            "    --rlimit-nofile=<num>      set maximum number of file descriptors\n"
77c23f
            "                               (0 leaves rlimit unchanged)\n"
77c23f
-           "                               default: 1,000,000 if the current rlimit is lower\n"
77c23f
+           "                               default: min(1000000, fs.file-max - 16384)\n"
77c23f
+           "                                        if the current rlimit is lower\n"
77c23f
            );
77c23f
 }
77c23f
 
77c23f
@@ -199,9 +200,32 @@ static int fuse_helper_opt_proc(void *data, const char *arg, int key,
77c23f
 
77c23f
 static unsigned long get_default_rlimit_nofile(void)
77c23f
 {
77c23f
+    g_autofree gchar *file_max_str = NULL;
77c23f
+    const rlim_t reserved_fds = 16384; /* leave at least this many fds free */
77c23f
     rlim_t max_fds = 1000000; /* our default RLIMIT_NOFILE target */
77c23f
+    rlim_t file_max;
77c23f
     struct rlimit rlim;
77c23f
 
77c23f
+    /*
77c23f
+     * Reduce max_fds below the system-wide maximum, if necessary.  This
77c23f
+     * ensures there are fds available for other processes so we don't
77c23f
+     * cause resource exhaustion.
77c23f
+     */
77c23f
+    if (!g_file_get_contents("/proc/sys/fs/file-max", &file_max_str,
77c23f
+                             NULL, NULL)) {
77c23f
+        fuse_log(FUSE_LOG_ERR, "can't read /proc/sys/fs/file-max\n");
77c23f
+        exit(1);
77c23f
+    }
77c23f
+    file_max = g_ascii_strtoull(file_max_str, NULL, 10);
77c23f
+    if (file_max < 2 * reserved_fds) {
77c23f
+        fuse_log(FUSE_LOG_ERR,
77c23f
+                 "The fs.file-max sysctl is too low (%lu) to allow a "
77c23f
+                 "reasonable number of open files.\n",
77c23f
+                 (unsigned long)file_max);
77c23f
+        exit(1);
77c23f
+    }
77c23f
+    max_fds = MIN(file_max - reserved_fds, max_fds);
77c23f
+
77c23f
     if (getrlimit(RLIMIT_NOFILE, &rlim) < 0) {
77c23f
         fuse_log(FUSE_LOG_ERR, "getrlimit(RLIMIT_NOFILE): %m\n");
77c23f
         exit(1);
77c23f
-- 
77c23f
1.8.3.1
77c23f