|
|
923a60 |
From 650d5c39753d095f8ae6cff418306cf1a6b8fd25 Mon Sep 17 00:00:00 2001
|
|
|
923a60 |
From: Jan Synacek <jsynacek@redhat.com>
|
|
|
923a60 |
Date: Fri, 2 Nov 2018 08:40:40 +0100
|
|
|
923a60 |
Subject: [PATCH] =?UTF-8?q?core:=20when=20deserializing=20state=20always?=
|
|
|
923a60 |
=?UTF-8?q?=20use=20read=5Fline(=E2=80=A6,=20LONG=5FLINE=5FMAX,=20?=
|
|
|
923a60 |
=?UTF-8?q?=E2=80=A6)?=
|
|
|
923a60 |
MIME-Version: 1.0
|
|
|
923a60 |
Content-Type: text/plain; charset=UTF-8
|
|
|
923a60 |
Content-Transfer-Encoding: 8bit
|
|
|
923a60 |
|
|
|
923a60 |
This should be much better than fgets(), as we can read substantially
|
|
|
923a60 |
longer lines and overly long lines result in proper errors.
|
|
|
923a60 |
|
|
|
923a60 |
Fixes a vulnerability discovered by Jann Horn at Google.
|
|
|
923a60 |
|
|
|
923a60 |
(cherry picked from commit 8948b3415d762245ebf5e19d80b97d4d8cc208c1)
|
|
|
923a60 |
|
|
|
923a60 |
Resolves: CVE-2018-15686
|
|
|
923a60 |
|
|
|
923a60 |
[jsynacek] There were more commits in the pull request of which the cherry
|
|
|
923a60 |
picked commit was a part of, see
|
|
|
923a60 |
https://github.com/systemd/systemd/pull/10519/commits.
|
|
|
923a60 |
I decided not to backport any of the remaining ones, because they were
|
|
|
923a60 |
mostly irrelevant to the actual fix.
|
|
|
923a60 |
---
|
|
|
923a60 |
src/core/job.c | 19 +++++++++++--------
|
|
|
923a60 |
src/core/manager.c | 38 ++++++++++++++++----------------------
|
|
|
923a60 |
src/core/unit.c | 17 ++++++++---------
|
|
|
923a60 |
3 files changed, 35 insertions(+), 39 deletions(-)
|
|
|
923a60 |
|
|
|
923a60 |
diff --git a/src/core/job.c b/src/core/job.c
|
|
|
923a60 |
index 275503169b..998b231ed9 100644
|
|
|
923a60 |
--- a/src/core/job.c
|
|
|
923a60 |
+++ b/src/core/job.c
|
|
|
923a60 |
@@ -38,6 +38,7 @@
|
|
|
923a60 |
#include "async.h"
|
|
|
923a60 |
#include "virt.h"
|
|
|
923a60 |
#include "dbus.h"
|
|
|
923a60 |
+#include "fileio.h"
|
|
|
923a60 |
|
|
|
923a60 |
Job* job_new_raw(Unit *unit) {
|
|
|
923a60 |
Job *j;
|
|
|
923a60 |
@@ -1035,23 +1036,25 @@ int job_serialize(Job *j, FILE *f, FDSet *fds) {
|
|
|
923a60 |
}
|
|
|
923a60 |
|
|
|
923a60 |
int job_deserialize(Job *j, FILE *f, FDSet *fds) {
|
|
|
923a60 |
+ int r = 0;
|
|
|
923a60 |
+
|
|
|
923a60 |
assert(j);
|
|
|
923a60 |
|
|
|
923a60 |
for (;;) {
|
|
|
923a60 |
- char line[LINE_MAX], *l, *v;
|
|
|
923a60 |
+ _cleanup_free_ char *line = NULL;
|
|
|
923a60 |
+ char *l, *v;
|
|
|
923a60 |
size_t k;
|
|
|
923a60 |
|
|
|
923a60 |
- if (!fgets(line, sizeof(line), f)) {
|
|
|
923a60 |
- if (feof(f))
|
|
|
923a60 |
- return 0;
|
|
|
923a60 |
- return -errno;
|
|
|
923a60 |
- }
|
|
|
923a60 |
+ r = read_line(f, LONG_LINE_MAX, &line);
|
|
|
923a60 |
+ if (r < 0)
|
|
|
923a60 |
+ return log_error_errno(r, "Failed to read serialization line: %m");
|
|
|
923a60 |
+ if (r == 0)
|
|
|
923a60 |
+ return 0;
|
|
|
923a60 |
|
|
|
923a60 |
- char_array_0(line);
|
|
|
923a60 |
l = strstrip(line);
|
|
|
923a60 |
|
|
|
923a60 |
/* End marker */
|
|
|
923a60 |
- if (l[0] == 0)
|
|
|
923a60 |
+ if (isempty(l))
|
|
|
923a60 |
return 0;
|
|
|
923a60 |
|
|
|
923a60 |
k = strcspn(l, "=");
|
|
|
923a60 |
diff --git a/src/core/manager.c b/src/core/manager.c
|
|
|
923a60 |
index 0466e4bb8a..73d6c81fdb 100644
|
|
|
923a60 |
--- a/src/core/manager.c
|
|
|
923a60 |
+++ b/src/core/manager.c
|
|
|
923a60 |
@@ -37,6 +37,7 @@
|
|
|
923a60 |
#include <sys/stat.h>
|
|
|
923a60 |
#include <dirent.h>
|
|
|
923a60 |
#include <sys/timerfd.h>
|
|
|
923a60 |
+#include <fileio.h>
|
|
|
923a60 |
|
|
|
923a60 |
#ifdef HAVE_AUDIT
|
|
|
923a60 |
#include <libaudit.h>
|
|
|
923a60 |
@@ -2559,21 +2560,19 @@ int manager_deserialize(Manager *m, FILE *f, FDSet *fds) {
|
|
|
923a60 |
m->n_reloading ++;
|
|
|
923a60 |
|
|
|
923a60 |
for (;;) {
|
|
|
923a60 |
- char line[LINE_MAX], *l;
|
|
|
923a60 |
+ _cleanup_free_ char *line = NULL;
|
|
|
923a60 |
+ char *l;
|
|
|
923a60 |
|
|
|
923a60 |
- if (!fgets(line, sizeof(line), f)) {
|
|
|
923a60 |
- if (feof(f))
|
|
|
923a60 |
- r = 0;
|
|
|
923a60 |
- else
|
|
|
923a60 |
- r = -errno;
|
|
|
923a60 |
|
|
|
923a60 |
- goto finish;
|
|
|
923a60 |
- }
|
|
|
923a60 |
+ r = read_line(f, LONG_LINE_MAX, &line);
|
|
|
923a60 |
+ if (r < 0)
|
|
|
923a60 |
+ return log_error_errno(r, "Failed to read serialization line: %m");
|
|
|
923a60 |
+ if (r == 0)
|
|
|
923a60 |
+ break;
|
|
|
923a60 |
|
|
|
923a60 |
- char_array_0(line);
|
|
|
923a60 |
l = strstrip(line);
|
|
|
923a60 |
|
|
|
923a60 |
- if (l[0] == 0)
|
|
|
923a60 |
+ if (isempty(l)) /* end marker */
|
|
|
923a60 |
break;
|
|
|
923a60 |
|
|
|
923a60 |
if (startswith(l, "current-job-id=")) {
|
|
|
923a60 |
@@ -2708,22 +2707,17 @@ int manager_deserialize(Manager *m, FILE *f, FDSet *fds) {
|
|
|
923a60 |
}
|
|
|
923a60 |
|
|
|
923a60 |
for (;;) {
|
|
|
923a60 |
+ _cleanup_free_ char *line = NULL;
|
|
|
923a60 |
Unit *u;
|
|
|
923a60 |
- char name[UNIT_NAME_MAX+2];
|
|
|
923a60 |
|
|
|
923a60 |
/* Start marker */
|
|
|
923a60 |
- if (!fgets(name, sizeof(name), f)) {
|
|
|
923a60 |
- if (feof(f))
|
|
|
923a60 |
- r = 0;
|
|
|
923a60 |
- else
|
|
|
923a60 |
- r = -errno;
|
|
|
923a60 |
-
|
|
|
923a60 |
- goto finish;
|
|
|
923a60 |
- }
|
|
|
923a60 |
-
|
|
|
923a60 |
- char_array_0(name);
|
|
|
923a60 |
+ r = read_line(f, LONG_LINE_MAX, &line);
|
|
|
923a60 |
+ if (r < 0)
|
|
|
923a60 |
+ return log_error_errno(r, "Failed to read serialization line: %m");
|
|
|
923a60 |
+ if (r == 0)
|
|
|
923a60 |
+ break;
|
|
|
923a60 |
|
|
|
923a60 |
- r = manager_load_unit(m, strstrip(name), NULL, NULL, &u);
|
|
|
923a60 |
+ r = manager_load_unit(m, strstrip(line), NULL, NULL, &u);
|
|
|
923a60 |
if (r < 0)
|
|
|
923a60 |
goto finish;
|
|
|
923a60 |
|
|
|
923a60 |
diff --git a/src/core/unit.c b/src/core/unit.c
|
|
|
923a60 |
index e8532a057d..37fac8db3a 100644
|
|
|
923a60 |
--- a/src/core/unit.c
|
|
|
923a60 |
+++ b/src/core/unit.c
|
|
|
923a60 |
@@ -2644,20 +2644,19 @@ int unit_deserialize(Unit *u, FILE *f, FDSet *fds) {
|
|
|
923a60 |
rt = (ExecRuntime**) ((uint8_t*) u + offset);
|
|
|
923a60 |
|
|
|
923a60 |
for (;;) {
|
|
|
923a60 |
- char line[LINE_MAX], *l, *v;
|
|
|
923a60 |
+ _cleanup_free_ char *line = NULL;
|
|
|
923a60 |
+ char *l, *v;
|
|
|
923a60 |
size_t k;
|
|
|
923a60 |
|
|
|
923a60 |
- if (!fgets(line, sizeof(line), f)) {
|
|
|
923a60 |
- if (feof(f))
|
|
|
923a60 |
- return 0;
|
|
|
923a60 |
- return -errno;
|
|
|
923a60 |
- }
|
|
|
923a60 |
+ r = read_line(f, LONG_LINE_MAX, &line);
|
|
|
923a60 |
+ if (r < 0)
|
|
|
923a60 |
+ return log_error_errno(r, "Failed to read serialization line: %m");
|
|
|
923a60 |
+ if (r == 0) /* eof */
|
|
|
923a60 |
+ return 0;
|
|
|
923a60 |
|
|
|
923a60 |
- char_array_0(line);
|
|
|
923a60 |
l = strstrip(line);
|
|
|
923a60 |
-
|
|
|
923a60 |
/* End marker */
|
|
|
923a60 |
- if (l[0] == 0)
|
|
|
923a60 |
+ if (isempty(l))
|
|
|
923a60 |
return 0;
|
|
|
923a60 |
|
|
|
923a60 |
k = strcspn(l, "=");
|