Blob Blame History Raw
From 7bb8b4580b19f1d48e9beb201387d6c321b3ae7b Mon Sep 17 00:00:00 2001
From: Jan Synacek <jsynacek@redhat.com>
Date: Tue, 2 Oct 2018 16:07:00 +0200
Subject: [PATCH] detect-virt: do not try to read all of /proc/cpuinfo

Quoting #10074:
> detect_vm_uml() reads /proc/cpuinfo with read_full_file()
> read_full_file() has a file max limit size of READ_FULL_BYTES_MAX=(4U*1024U*1024U)
> Unfortunately, the size of my /proc/cpuinfo is bigger, approximately:
> echo $(( 4* $(cat /proc/cpuinfo | wc -c)))
> 9918072
> This causes read_full_file() to fail and the Condition test fallout.

Let's just read line by line until we find an intersting line. This also
helps if not running under UML, because we avoid reading as much data.

(cherry picked from commit 6058516a14ada1748313af6783f5b4e7e3006654)
Resolves: #1631531
---
 src/shared/virt.c | 40 ++++++++++++++++++++++++++++++++--------
 1 file changed, 32 insertions(+), 8 deletions(-)

diff --git a/src/shared/virt.c b/src/shared/virt.c
index 55a6ca90fb..e6362f6645 100644
--- a/src/shared/virt.c
+++ b/src/shared/virt.c
@@ -185,7 +185,8 @@ static int detect_vm_dmi(const char **_id) {
 
 /* Returns a short identifier for the various VM implementations */
 int detect_vm(const char **id) {
-        _cleanup_free_ char *domcap = NULL, *cpuinfo_contents = NULL;
+        _cleanup_free_ char *domcap = NULL;
+        _cleanup_fclose_ FILE *f = NULL;
         static thread_local int cached_found = -1;
         static thread_local const char *cached_id = NULL;
         const char *_id = NULL;
@@ -252,13 +253,36 @@ int detect_vm(const char **id) {
         }
 
         /* Detect User-Mode Linux by reading /proc/cpuinfo */
-        r = read_full_file("/proc/cpuinfo", &cpuinfo_contents, NULL);
-        if (r < 0)
-                return r;
-        if (strstr(cpuinfo_contents, "\nvendor_id\t: User Mode Linux\n")) {
-                _id = "uml";
-                r = 1;
-                goto finish;
+        f = fopen("/proc/cpuinfo", "re");
+        if (!f) {
+                if (errno == ENOENT) {
+                        log_debug("/proc/cpuinfo not found, assuming no UML virtualization.");
+                        r = 0;
+                        goto finish;
+                }
+                return -errno;
+        }
+        for (;;) {
+                _cleanup_free_ char *line = NULL;
+                const char *t;
+
+                r = read_line(f, LONG_LINE_MAX, &line);
+                if (r < 0)
+                        return r;
+                if (r == 0)
+                        break;
+
+                t = startswith(line, "vendor_id\t: ");
+                if (t) {
+                        if (startswith(t, "User Mode Linux")) {
+                                log_debug("UML virtualization found in /proc/cpuinfo");
+                                _id = "uml";
+                                r = 1;
+                                goto finish;
+                        }
+
+                        break;
+                }
         }
 
 #if defined(__s390__)