|
|
a3e2b5 |
From 55a1c766445750aaefe28bd7bea454f5f1cff9bb Mon Sep 17 00:00:00 2001
|
|
|
a3e2b5 |
From: Lennart Poettering <lennart@poettering.net>
|
|
|
a3e2b5 |
Date: Wed, 17 Oct 2018 18:36:24 +0200
|
|
|
a3e2b5 |
Subject: [PATCH] =?UTF-8?q?core:=20when=20deserializing=20state=20always?=
|
|
|
a3e2b5 |
=?UTF-8?q?=20use=20read=5Fline(=E2=80=A6,=20LONG=5FLINE=5FMAX,=20?=
|
|
|
a3e2b5 |
=?UTF-8?q?=E2=80=A6)?=
|
|
|
a3e2b5 |
MIME-Version: 1.0
|
|
|
a3e2b5 |
Content-Type: text/plain; charset=UTF-8
|
|
|
a3e2b5 |
Content-Transfer-Encoding: 8bit
|
|
|
a3e2b5 |
|
|
|
a3e2b5 |
This should be much better than fgets(), as we can read substantially
|
|
|
a3e2b5 |
longer lines and overly long lines result in proper errors.
|
|
|
a3e2b5 |
|
|
|
a3e2b5 |
Fixes a vulnerability discovered by Jann Horn at Google.
|
|
|
a3e2b5 |
|
|
|
a3e2b5 |
CVE-2018-15686
|
|
|
a3e2b5 |
LP: #1796402
|
|
|
a3e2b5 |
https://bugzilla.redhat.com/show_bug.cgi?id=1639071
|
|
|
a3e2b5 |
|
|
|
a3e2b5 |
(cherry picked from commit 8948b3415d762245ebf5e19d80b97d4d8cc208c1)
|
|
|
a3e2b5 |
|
|
|
a3e2b5 |
Resolves: CVE-2018-15686
|
|
|
a3e2b5 |
---
|
|
|
a3e2b5 |
src/core/job.c | 19 +++++++++++--------
|
|
|
a3e2b5 |
src/core/manager.c | 47 ++++++++++++++++++++--------------------------
|
|
|
a3e2b5 |
src/core/unit.c | 34 +++++++++++++++++----------------
|
|
|
a3e2b5 |
src/core/unit.h | 2 +-
|
|
|
a3e2b5 |
4 files changed, 50 insertions(+), 52 deletions(-)
|
|
|
a3e2b5 |
|
|
|
a3e2b5 |
diff --git a/src/core/job.c b/src/core/job.c
|
|
|
a3e2b5 |
index 734756b666..8552ffb704 100644
|
|
|
a3e2b5 |
--- a/src/core/job.c
|
|
|
a3e2b5 |
+++ b/src/core/job.c
|
|
|
a3e2b5 |
@@ -10,6 +10,7 @@
|
|
|
a3e2b5 |
#include "dbus-job.h"
|
|
|
a3e2b5 |
#include "dbus.h"
|
|
|
a3e2b5 |
#include "escape.h"
|
|
|
a3e2b5 |
+#include "fileio.h"
|
|
|
a3e2b5 |
#include "job.h"
|
|
|
a3e2b5 |
#include "log.h"
|
|
|
a3e2b5 |
#include "macro.h"
|
|
|
a3e2b5 |
@@ -1091,24 +1092,26 @@ int job_serialize(Job *j, FILE *f) {
|
|
|
a3e2b5 |
}
|
|
|
a3e2b5 |
|
|
|
a3e2b5 |
int job_deserialize(Job *j, FILE *f) {
|
|
|
a3e2b5 |
+ int r;
|
|
|
a3e2b5 |
+
|
|
|
a3e2b5 |
assert(j);
|
|
|
a3e2b5 |
assert(f);
|
|
|
a3e2b5 |
|
|
|
a3e2b5 |
for (;;) {
|
|
|
a3e2b5 |
- char line[LINE_MAX], *l, *v;
|
|
|
a3e2b5 |
+ _cleanup_free_ char *line = NULL;
|
|
|
a3e2b5 |
+ char *l, *v;
|
|
|
a3e2b5 |
size_t k;
|
|
|
a3e2b5 |
|
|
|
a3e2b5 |
- if (!fgets(line, sizeof(line), f)) {
|
|
|
a3e2b5 |
- if (feof(f))
|
|
|
a3e2b5 |
- return 0;
|
|
|
a3e2b5 |
- return -errno;
|
|
|
a3e2b5 |
- }
|
|
|
a3e2b5 |
+ r = read_line(f, LONG_LINE_MAX, &line);
|
|
|
a3e2b5 |
+ if (r < 0)
|
|
|
a3e2b5 |
+ return log_error_errno(r, "Failed to read serialization line: %m");
|
|
|
a3e2b5 |
+ if (r == 0)
|
|
|
a3e2b5 |
+ return 0;
|
|
|
a3e2b5 |
|
|
|
a3e2b5 |
- char_array_0(line);
|
|
|
a3e2b5 |
l = strstrip(line);
|
|
|
a3e2b5 |
|
|
|
a3e2b5 |
/* End marker */
|
|
|
a3e2b5 |
- if (l[0] == 0)
|
|
|
a3e2b5 |
+ if (isempty(l))
|
|
|
a3e2b5 |
return 0;
|
|
|
a3e2b5 |
|
|
|
a3e2b5 |
k = strcspn(l, "=");
|
|
|
a3e2b5 |
diff --git a/src/core/manager.c b/src/core/manager.c
|
|
|
a3e2b5 |
index 3b2fe11e87..c83e296cf3 100644
|
|
|
a3e2b5 |
--- a/src/core/manager.c
|
|
|
a3e2b5 |
+++ b/src/core/manager.c
|
|
|
a3e2b5 |
@@ -3144,22 +3144,17 @@ int manager_deserialize(Manager *m, FILE *f, FDSet *fds) {
|
|
|
a3e2b5 |
m->n_reloading++;
|
|
|
a3e2b5 |
|
|
|
a3e2b5 |
for (;;) {
|
|
|
a3e2b5 |
- char line[LINE_MAX];
|
|
|
a3e2b5 |
+ _cleanup_free_ char *line = NULL;
|
|
|
a3e2b5 |
const char *val, *l;
|
|
|
a3e2b5 |
|
|
|
a3e2b5 |
- if (!fgets(line, sizeof(line), f)) {
|
|
|
a3e2b5 |
- if (feof(f))
|
|
|
a3e2b5 |
- r = 0;
|
|
|
a3e2b5 |
- else
|
|
|
a3e2b5 |
- r = -errno;
|
|
|
a3e2b5 |
-
|
|
|
a3e2b5 |
- goto finish;
|
|
|
a3e2b5 |
- }
|
|
|
a3e2b5 |
+ r = read_line(f, LONG_LINE_MAX, &line);
|
|
|
a3e2b5 |
+ if (r < 0)
|
|
|
a3e2b5 |
+ return log_error_errno(r, "Failed to read serialization line: %m");
|
|
|
a3e2b5 |
+ if (r == 0)
|
|
|
a3e2b5 |
+ break;
|
|
|
a3e2b5 |
|
|
|
a3e2b5 |
- char_array_0(line);
|
|
|
a3e2b5 |
l = strstrip(line);
|
|
|
a3e2b5 |
-
|
|
|
a3e2b5 |
- if (l[0] == 0)
|
|
|
a3e2b5 |
+ if (isempty(l)) /* end marker */
|
|
|
a3e2b5 |
break;
|
|
|
a3e2b5 |
|
|
|
a3e2b5 |
if ((val = startswith(l, "current-job-id="))) {
|
|
|
a3e2b5 |
@@ -3326,29 +3321,27 @@ int manager_deserialize(Manager *m, FILE *f, FDSet *fds) {
|
|
|
a3e2b5 |
}
|
|
|
a3e2b5 |
|
|
|
a3e2b5 |
for (;;) {
|
|
|
a3e2b5 |
- Unit *u;
|
|
|
a3e2b5 |
- char name[UNIT_NAME_MAX+2];
|
|
|
a3e2b5 |
+ _cleanup_free_ char *line = NULL;
|
|
|
a3e2b5 |
const char* unit_name;
|
|
|
a3e2b5 |
+ Unit *u;
|
|
|
a3e2b5 |
|
|
|
a3e2b5 |
/* Start marker */
|
|
|
a3e2b5 |
- if (!fgets(name, sizeof(name), f)) {
|
|
|
a3e2b5 |
- if (feof(f))
|
|
|
a3e2b5 |
- r = 0;
|
|
|
a3e2b5 |
- else
|
|
|
a3e2b5 |
- r = -errno;
|
|
|
a3e2b5 |
-
|
|
|
a3e2b5 |
- goto finish;
|
|
|
a3e2b5 |
- }
|
|
|
a3e2b5 |
+ r = read_line(f, LONG_LINE_MAX, &line);
|
|
|
a3e2b5 |
+ if (r < 0)
|
|
|
a3e2b5 |
+ return log_error_errno(r, "Failed to read serialization line: %m");
|
|
|
a3e2b5 |
+ if (r == 0)
|
|
|
a3e2b5 |
+ break;
|
|
|
a3e2b5 |
|
|
|
a3e2b5 |
- char_array_0(name);
|
|
|
a3e2b5 |
- unit_name = strstrip(name);
|
|
|
a3e2b5 |
+ unit_name = strstrip(line);
|
|
|
a3e2b5 |
|
|
|
a3e2b5 |
r = manager_load_unit(m, unit_name, NULL, NULL, &u);
|
|
|
a3e2b5 |
if (r < 0) {
|
|
|
a3e2b5 |
log_notice_errno(r, "Failed to load unit \"%s\", skipping deserialization: %m", unit_name);
|
|
|
a3e2b5 |
- if (r == -ENOMEM)
|
|
|
a3e2b5 |
- goto finish;
|
|
|
a3e2b5 |
- unit_deserialize_skip(f);
|
|
|
a3e2b5 |
+
|
|
|
a3e2b5 |
+ r = unit_deserialize_skip(f);
|
|
|
a3e2b5 |
+ if (r < 0)
|
|
|
a3e2b5 |
+ return r;
|
|
|
a3e2b5 |
+
|
|
|
a3e2b5 |
continue;
|
|
|
a3e2b5 |
}
|
|
|
a3e2b5 |
|
|
|
a3e2b5 |
diff --git a/src/core/unit.c b/src/core/unit.c
|
|
|
a3e2b5 |
index 721d8d60a3..cc43ddc4f1 100644
|
|
|
a3e2b5 |
--- a/src/core/unit.c
|
|
|
a3e2b5 |
+++ b/src/core/unit.c
|
|
|
a3e2b5 |
@@ -3368,21 +3368,19 @@ int unit_deserialize(Unit *u, FILE *f, FDSet *fds) {
|
|
|
a3e2b5 |
assert(fds);
|
|
|
a3e2b5 |
|
|
|
a3e2b5 |
for (;;) {
|
|
|
a3e2b5 |
- char line[LINE_MAX], *l, *v;
|
|
|
a3e2b5 |
+ _cleanup_free_ char *line = NULL;
|
|
|
a3e2b5 |
CGroupIPAccountingMetric m;
|
|
|
a3e2b5 |
+ char *l, *v;
|
|
|
a3e2b5 |
size_t k;
|
|
|
a3e2b5 |
|
|
|
a3e2b5 |
- if (!fgets(line, sizeof(line), f)) {
|
|
|
a3e2b5 |
- if (feof(f))
|
|
|
a3e2b5 |
- return 0;
|
|
|
a3e2b5 |
- return -errno;
|
|
|
a3e2b5 |
- }
|
|
|
a3e2b5 |
+ r = read_line(f, LONG_LINE_MAX, &line);
|
|
|
a3e2b5 |
+ if (r < 0)
|
|
|
a3e2b5 |
+ return log_error_errno(r, "Failed to read serialization line: %m");
|
|
|
a3e2b5 |
+ if (r == 0) /* eof */
|
|
|
a3e2b5 |
+ break;
|
|
|
a3e2b5 |
|
|
|
a3e2b5 |
- char_array_0(line);
|
|
|
a3e2b5 |
l = strstrip(line);
|
|
|
a3e2b5 |
-
|
|
|
a3e2b5 |
- /* End marker */
|
|
|
a3e2b5 |
- if (isempty(l))
|
|
|
a3e2b5 |
+ if (isempty(l)) /* End marker */
|
|
|
a3e2b5 |
break;
|
|
|
a3e2b5 |
|
|
|
a3e2b5 |
k = strcspn(l, "=");
|
|
|
a3e2b5 |
@@ -3657,23 +3655,27 @@ int unit_deserialize(Unit *u, FILE *f, FDSet *fds) {
|
|
|
a3e2b5 |
return 0;
|
|
|
a3e2b5 |
}
|
|
|
a3e2b5 |
|
|
|
a3e2b5 |
-void unit_deserialize_skip(FILE *f) {
|
|
|
a3e2b5 |
+int unit_deserialize_skip(FILE *f) {
|
|
|
a3e2b5 |
+ int r;
|
|
|
a3e2b5 |
assert(f);
|
|
|
a3e2b5 |
|
|
|
a3e2b5 |
/* Skip serialized data for this unit. We don't know what it is. */
|
|
|
a3e2b5 |
|
|
|
a3e2b5 |
for (;;) {
|
|
|
a3e2b5 |
- char line[LINE_MAX], *l;
|
|
|
a3e2b5 |
+ _cleanup_free_ char *line = NULL;
|
|
|
a3e2b5 |
+ char *l;
|
|
|
a3e2b5 |
|
|
|
a3e2b5 |
- if (!fgets(line, sizeof line, f))
|
|
|
a3e2b5 |
- return;
|
|
|
a3e2b5 |
+ r = read_line(f, LONG_LINE_MAX, &line);
|
|
|
a3e2b5 |
+ if (r < 0)
|
|
|
a3e2b5 |
+ return log_error_errno(r, "Failed to read serialization line: %m");
|
|
|
a3e2b5 |
+ if (r == 0)
|
|
|
a3e2b5 |
+ return 0;
|
|
|
a3e2b5 |
|
|
|
a3e2b5 |
- char_array_0(line);
|
|
|
a3e2b5 |
l = strstrip(line);
|
|
|
a3e2b5 |
|
|
|
a3e2b5 |
/* End marker */
|
|
|
a3e2b5 |
if (isempty(l))
|
|
|
a3e2b5 |
- return;
|
|
|
a3e2b5 |
+ return 1;
|
|
|
a3e2b5 |
}
|
|
|
a3e2b5 |
}
|
|
|
a3e2b5 |
|
|
|
a3e2b5 |
diff --git a/src/core/unit.h b/src/core/unit.h
|
|
|
a3e2b5 |
index b3131eba1b..e1a60da244 100644
|
|
|
a3e2b5 |
--- a/src/core/unit.h
|
|
|
a3e2b5 |
+++ b/src/core/unit.h
|
|
|
a3e2b5 |
@@ -679,7 +679,7 @@ bool unit_can_serialize(Unit *u) _pure_;
|
|
|
a3e2b5 |
|
|
|
a3e2b5 |
int unit_serialize(Unit *u, FILE *f, FDSet *fds, bool serialize_jobs);
|
|
|
a3e2b5 |
int unit_deserialize(Unit *u, FILE *f, FDSet *fds);
|
|
|
a3e2b5 |
-void unit_deserialize_skip(FILE *f);
|
|
|
a3e2b5 |
+int unit_deserialize_skip(FILE *f);
|
|
|
a3e2b5 |
|
|
|
a3e2b5 |
int unit_serialize_item(Unit *u, FILE *f, const char *key, const char *value);
|
|
|
a3e2b5 |
int unit_serialize_item_escaped(Unit *u, FILE *f, const char *key, const char *value);
|