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