summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>2018-09-13 09:24:36 +0200
committerZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>2018-09-18 16:53:36 +0200
commit6058516a14ada1748313af6783f5b4e7e3006654 (patch)
tree4de218e9b74245ae5f81509ab5f2659495218d22
parent010d436e020ab4af57a8b9fc38918f551acc875b (diff)
downloadsystemd-6058516a14ada1748313af6783f5b4e7e3006654.tar.gz
systemd-6058516a14ada1748313af6783f5b4e7e3006654.tar.bz2
systemd-6058516a14ada1748313af6783f5b4e7e3006654.zip
detect-virt: do not try to read all of /proc/cpuinfo
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.
-rw-r--r--src/basic/virt.c38
1 files changed, 28 insertions, 10 deletions
diff --git a/src/basic/virt.c b/src/basic/virt.c
index d347732bb3..e05b3e6d99 100644
--- a/src/basic/virt.c
+++ b/src/basic/virt.c
@@ -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.");