Blame SOURCES/0045-detect-virt-do-not-try-to-read-all-of-proc-cpuinfo.patch

a3e2b5
From 886e5b028953404f2d924b561c0689d3e50dbbf4 Mon Sep 17 00:00:00 2001
a3e2b5
From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= <zbyszek@in.waw.pl>
a3e2b5
Date: Thu, 13 Sep 2018 09:24:36 +0200
a3e2b5
Subject: [PATCH] detect-virt: do not try to read all of /proc/cpuinfo
a3e2b5
a3e2b5
Quoting https://github.com/systemd/systemd/issues/10074:
a3e2b5
> detect_vm_uml() reads /proc/cpuinfo with read_full_file()
a3e2b5
> read_full_file() has a file max limit size of READ_FULL_BYTES_MAX=(4U*1024U*1024U)
a3e2b5
> Unfortunately, the size of my /proc/cpuinfo is bigger, approximately:
a3e2b5
> echo $(( 4* $(cat /proc/cpuinfo | wc -c)))
a3e2b5
> 9918072
a3e2b5
> This causes read_full_file() to fail and the Condition test fallout.
a3e2b5
a3e2b5
Let's just read line by line until we find an intersting line. This also
a3e2b5
helps if not running under UML, because we avoid reading as much data.
a3e2b5
a3e2b5
(cherry picked from commit 6058516a14ada1748313af6783f5b4e7e3006654)
a3e2b5
a3e2b5
Resolves: #1631532
a3e2b5
---
a3e2b5
 src/basic/virt.c | 38 ++++++++++++++++++++++++++++----------
a3e2b5
 1 file changed, 28 insertions(+), 10 deletions(-)
a3e2b5
a3e2b5
diff --git a/src/basic/virt.c b/src/basic/virt.c
a3e2b5
index d347732bb3..e05b3e6d99 100644
a3e2b5
--- a/src/basic/virt.c
a3e2b5
+++ b/src/basic/virt.c
a3e2b5
@@ -11,6 +11,7 @@
a3e2b5
 
a3e2b5
 #include "alloc-util.h"
a3e2b5
 #include "dirent-util.h"
a3e2b5
+#include "def.h"
a3e2b5
 #include "env-util.h"
a3e2b5
 #include "fd-util.h"
a3e2b5
 #include "fileio.h"
a3e2b5
@@ -259,21 +260,38 @@ static int detect_vm_hypervisor(void) {
a3e2b5
 }
a3e2b5
 
a3e2b5
 static int detect_vm_uml(void) {
a3e2b5
-        _cleanup_free_ char *cpuinfo_contents = NULL;
a3e2b5
+        _cleanup_fclose_ FILE *f = NULL;
a3e2b5
         int r;
a3e2b5
 
a3e2b5
         /* Detect User-Mode Linux by reading /proc/cpuinfo */
a3e2b5
-        r = read_full_file("/proc/cpuinfo", &cpuinfo_contents, NULL);
a3e2b5
-        if (r == -ENOENT) {
a3e2b5
-                log_debug("/proc/cpuinfo not found, assuming no UML virtualization.");
a3e2b5
-                return VIRTUALIZATION_NONE;
a3e2b5
+        f = fopen("/proc/cpuinfo", "re");
a3e2b5
+        if (!f) {
a3e2b5
+                if (errno == ENOENT) {
a3e2b5
+                        log_debug("/proc/cpuinfo not found, assuming no UML virtualization.");
a3e2b5
+                        return VIRTUALIZATION_NONE;
a3e2b5
+                }
a3e2b5
+                return -errno;
a3e2b5
         }
a3e2b5
-        if (r < 0)
a3e2b5
-                return r;
a3e2b5
 
a3e2b5
-        if (strstr(cpuinfo_contents, "\nvendor_id\t: User Mode Linux\n")) {
a3e2b5
-                log_debug("UML virtualization found in /proc/cpuinfo");
a3e2b5
-                return VIRTUALIZATION_UML;
a3e2b5
+        for (;;) {
a3e2b5
+                _cleanup_free_ char *line = NULL;
a3e2b5
+                const char *t;
a3e2b5
+
a3e2b5
+                r = read_line(f, LONG_LINE_MAX, &line);
a3e2b5
+                if (r < 0)
a3e2b5
+                        return r;
a3e2b5
+                if (r == 0)
a3e2b5
+                        break;
a3e2b5
+
a3e2b5
+                t = startswith(line, "vendor_id\t: ");
a3e2b5
+                if (t) {
a3e2b5
+                        if (startswith(t, "User Mode Linux")) {
a3e2b5
+                                log_debug("UML virtualization found in /proc/cpuinfo");
a3e2b5
+                                return VIRTUALIZATION_UML;
a3e2b5
+                        }
a3e2b5
+
a3e2b5
+                        break;
a3e2b5
+                }
a3e2b5
         }
a3e2b5
 
a3e2b5
         log_debug("UML virtualization not found in /proc/cpuinfo.");