Pablo Greco 48fc63
From 7bb8b4580b19f1d48e9beb201387d6c321b3ae7b Mon Sep 17 00:00:00 2001
Pablo Greco 48fc63
From: Jan Synacek <jsynacek@redhat.com>
Pablo Greco 48fc63
Date: Tue, 2 Oct 2018 16:07:00 +0200
Pablo Greco 48fc63
Subject: [PATCH] detect-virt: do not try to read all of /proc/cpuinfo
Pablo Greco 48fc63
Pablo Greco 48fc63
Quoting #10074:
Pablo Greco 48fc63
> detect_vm_uml() reads /proc/cpuinfo with read_full_file()
Pablo Greco 48fc63
> read_full_file() has a file max limit size of READ_FULL_BYTES_MAX=(4U*1024U*1024U)
Pablo Greco 48fc63
> Unfortunately, the size of my /proc/cpuinfo is bigger, approximately:
Pablo Greco 48fc63
> echo $(( 4* $(cat /proc/cpuinfo | wc -c)))
Pablo Greco 48fc63
> 9918072
Pablo Greco 48fc63
> This causes read_full_file() to fail and the Condition test fallout.
Pablo Greco 48fc63
Pablo Greco 48fc63
Let's just read line by line until we find an intersting line. This also
Pablo Greco 48fc63
helps if not running under UML, because we avoid reading as much data.
Pablo Greco 48fc63
Pablo Greco 48fc63
(cherry picked from commit 6058516a14ada1748313af6783f5b4e7e3006654)
Pablo Greco 48fc63
Resolves: #1631531
Pablo Greco 48fc63
---
Pablo Greco 48fc63
 src/shared/virt.c | 40 ++++++++++++++++++++++++++++++++--------
Pablo Greco 48fc63
 1 file changed, 32 insertions(+), 8 deletions(-)
Pablo Greco 48fc63
Pablo Greco 48fc63
diff --git a/src/shared/virt.c b/src/shared/virt.c
Pablo Greco 48fc63
index 55a6ca90fb..e6362f6645 100644
Pablo Greco 48fc63
--- a/src/shared/virt.c
Pablo Greco 48fc63
+++ b/src/shared/virt.c
Pablo Greco 48fc63
@@ -185,7 +185,8 @@ static int detect_vm_dmi(const char **_id) {
Pablo Greco 48fc63
 
Pablo Greco 48fc63
 /* Returns a short identifier for the various VM implementations */
Pablo Greco 48fc63
 int detect_vm(const char **id) {
Pablo Greco 48fc63
-        _cleanup_free_ char *domcap = NULL, *cpuinfo_contents = NULL;
Pablo Greco 48fc63
+        _cleanup_free_ char *domcap = NULL;
Pablo Greco 48fc63
+        _cleanup_fclose_ FILE *f = NULL;
Pablo Greco 48fc63
         static thread_local int cached_found = -1;
Pablo Greco 48fc63
         static thread_local const char *cached_id = NULL;
Pablo Greco 48fc63
         const char *_id = NULL;
Pablo Greco 48fc63
@@ -252,13 +253,36 @@ int detect_vm(const char **id) {
Pablo Greco 48fc63
         }
Pablo Greco 48fc63
 
Pablo Greco 48fc63
         /* Detect User-Mode Linux by reading /proc/cpuinfo */
Pablo Greco 48fc63
-        r = read_full_file("/proc/cpuinfo", &cpuinfo_contents, NULL);
Pablo Greco 48fc63
-        if (r < 0)
Pablo Greco 48fc63
-                return r;
Pablo Greco 48fc63
-        if (strstr(cpuinfo_contents, "\nvendor_id\t: User Mode Linux\n")) {
Pablo Greco 48fc63
-                _id = "uml";
Pablo Greco 48fc63
-                r = 1;
Pablo Greco 48fc63
-                goto finish;
Pablo Greco 48fc63
+        f = fopen("/proc/cpuinfo", "re");
Pablo Greco 48fc63
+        if (!f) {
Pablo Greco 48fc63
+                if (errno == ENOENT) {
Pablo Greco 48fc63
+                        log_debug("/proc/cpuinfo not found, assuming no UML virtualization.");
Pablo Greco 48fc63
+                        r = 0;
Pablo Greco 48fc63
+                        goto finish;
Pablo Greco 48fc63
+                }
Pablo Greco 48fc63
+                return -errno;
Pablo Greco 48fc63
+        }
Pablo Greco 48fc63
+        for (;;) {
Pablo Greco 48fc63
+                _cleanup_free_ char *line = NULL;
Pablo Greco 48fc63
+                const char *t;
Pablo Greco 48fc63
+
Pablo Greco 48fc63
+                r = read_line(f, LONG_LINE_MAX, &line);
Pablo Greco 48fc63
+                if (r < 0)
Pablo Greco 48fc63
+                        return r;
Pablo Greco 48fc63
+                if (r == 0)
Pablo Greco 48fc63
+                        break;
Pablo Greco 48fc63
+
Pablo Greco 48fc63
+                t = startswith(line, "vendor_id\t: ");
Pablo Greco 48fc63
+                if (t) {
Pablo Greco 48fc63
+                        if (startswith(t, "User Mode Linux")) {
Pablo Greco 48fc63
+                                log_debug("UML virtualization found in /proc/cpuinfo");
Pablo Greco 48fc63
+                                _id = "uml";
Pablo Greco 48fc63
+                                r = 1;
Pablo Greco 48fc63
+                                goto finish;
Pablo Greco 48fc63
+                        }
Pablo Greco 48fc63
+
Pablo Greco 48fc63
+                        break;
Pablo Greco 48fc63
+                }
Pablo Greco 48fc63
         }
Pablo Greco 48fc63
 
Pablo Greco 48fc63
 #if defined(__s390__)