]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
detect-virt: do not try to read all of /proc/cpuinfo
authorZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>
Thu, 13 Sep 2018 07:24:36 +0000 (09:24 +0200)
committerLukáš Nykrýn <lnykryn@redhat.com>
Thu, 6 Dec 2018 08:04:56 +0000 (09:04 +0100)
Quoting https://github.com/systemd/systemd/issues/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: #1631532

src/basic/virt.c

index d347732bb3da41f002678f4ecd249b1734086983..e05b3e6d990c5d7b0210b698b5dd7fba64244e29 100644 (file)
@@ -11,6 +11,7 @@
 
 #include "alloc-util.h"
 #include "dirent-util.h"
+#include "def.h"
 #include "env-util.h"
 #include "fd-util.h"
 #include "fileio.h"
@@ -259,21 +260,38 @@ static int detect_vm_hypervisor(void) {
 }
 
 static int detect_vm_uml(void) {
-        _cleanup_free_ char *cpuinfo_contents = NULL;
+        _cleanup_fclose_ FILE *f = NULL;
         int r;
 
         /* Detect User-Mode Linux by reading /proc/cpuinfo */
-        r = read_full_file("/proc/cpuinfo", &cpuinfo_contents, NULL);
-        if (r == -ENOENT) {
-                log_debug("/proc/cpuinfo not found, assuming no UML virtualization.");
-                return VIRTUALIZATION_NONE;
+        f = fopen("/proc/cpuinfo", "re");
+        if (!f) {
+                if (errno == ENOENT) {
+                        log_debug("/proc/cpuinfo not found, assuming no UML virtualization.");
+                        return VIRTUALIZATION_NONE;
+                }
+                return -errno;
         }
-        if (r < 0)
-                return r;
 
-        if (strstr(cpuinfo_contents, "\nvendor_id\t: User Mode Linux\n")) {
-                log_debug("UML virtualization found in /proc/cpuinfo");
-                return VIRTUALIZATION_UML;
+        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");
+                                return VIRTUALIZATION_UML;
+                        }
+
+                        break;
+                }
         }
 
         log_debug("UML virtualization not found in /proc/cpuinfo.");