import systemd-239-36.el8
This commit is contained in:
parent
22bbbfe74c
commit
010588050b
531
SOURCES/0296-catalog-fix-name-of-variable.patch
Normal file
531
SOURCES/0296-catalog-fix-name-of-variable.patch
Normal file
@ -0,0 +1,531 @@
|
||||
From c3513c7bcc27210c89edad1740e1190e693df86f Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= <zbyszek@in.waw.pl>
|
||||
Date: Mon, 15 Oct 2018 22:41:49 +0200
|
||||
Subject: [PATCH] catalog: fix name of variable
|
||||
|
||||
All the messages would (literally) say "The start-up result is RESULT."
|
||||
because @RESULT@ was not defined.
|
||||
|
||||
Fixes https://bugzilla.redhat.com/show_bug.cgi?id=1639482
|
||||
and the first part of #8005.
|
||||
|
||||
Fixup for 646cc98dc81c4d0edbc1b57e7bca0f474b47e270.
|
||||
|
||||
(cherry picked from commit 65d51875c2a7b27b61de090f1bd6311b0cef2016)
|
||||
|
||||
Resolves: #1677768
|
||||
---
|
||||
catalog/systemd.be.catalog.in | 6 +++---
|
||||
catalog/systemd.be@latin.catalog.in | 6 +++---
|
||||
catalog/systemd.bg.catalog.in | 6 +++---
|
||||
catalog/systemd.catalog.in | 6 +++---
|
||||
catalog/systemd.da.catalog.in | 6 +++---
|
||||
catalog/systemd.fr.catalog.in | 6 +++---
|
||||
catalog/systemd.hr.catalog.in | 6 +++---
|
||||
catalog/systemd.hu.catalog.in | 6 +++---
|
||||
catalog/systemd.it.catalog.in | 6 +++---
|
||||
catalog/systemd.ko.catalog.in | 6 +++---
|
||||
catalog/systemd.pl.catalog.in | 6 +++---
|
||||
catalog/systemd.pt_BR.catalog.in | 6 +++---
|
||||
catalog/systemd.ru.catalog.in | 6 +++---
|
||||
catalog/systemd.sr.catalog.in | 6 +++---
|
||||
catalog/systemd.zh_CN.catalog.in | 6 +++---
|
||||
catalog/systemd.zh_TW.catalog.in | 6 +++---
|
||||
16 files changed, 48 insertions(+), 48 deletions(-)
|
||||
|
||||
diff --git a/catalog/systemd.be.catalog.in b/catalog/systemd.be.catalog.in
|
||||
index 5011ea268d..2c59898683 100644
|
||||
--- a/catalog/systemd.be.catalog.in
|
||||
+++ b/catalog/systemd.be.catalog.in
|
||||
@@ -175,7 +175,7 @@ Support: %SUPPORT_URL%
|
||||
|
||||
Працэс запуску юніта @UNIT@ завершаны.
|
||||
|
||||
-Вынік: @RESULT@.
|
||||
+Вынік: @JOB_RESULT@.
|
||||
|
||||
-- de5b426a63be47a7b6ac3eaac82e2f6f
|
||||
Subject: Юніт @UNIT@ спыняецца
|
||||
@@ -198,7 +198,7 @@ Support: %SUPPORT_URL%
|
||||
|
||||
Збой юніта @UNIT@.
|
||||
|
||||
-Вынік: @RESULT@.
|
||||
+Вынік: @JOB_RESULT@.
|
||||
|
||||
-- d34d037fff1847e6ae669a370e694725
|
||||
Subject: Юніт @UNIT@ перачытвае сваю канфігурацыю
|
||||
@@ -214,7 +214,7 @@ Support: %SUPPORT_URL%
|
||||
|
||||
Юніт @UNIT@ перачытаў сваю канфігурацыю.
|
||||
|
||||
-Вынік: @RESULT@.
|
||||
+Вынік: @JOB_RESULT@.
|
||||
|
||||
-- 641257651c1b4ec9a8624d7a40a9e1e7
|
||||
Subject: Працэс @EXECUTABLE@ не можа быць выкананы
|
||||
diff --git a/catalog/systemd.be@latin.catalog.in b/catalog/systemd.be@latin.catalog.in
|
||||
index 6a8b092669..1d024fea12 100644
|
||||
--- a/catalog/systemd.be@latin.catalog.in
|
||||
+++ b/catalog/systemd.be@latin.catalog.in
|
||||
@@ -178,7 +178,7 @@ Support: %SUPPORT_URL%
|
||||
|
||||
Praces zapusku junita @UNIT@ zavieršany.
|
||||
|
||||
-Vynik: @RESULT@.
|
||||
+Vynik: @JOB_RESULT@.
|
||||
|
||||
-- de5b426a63be47a7b6ac3eaac82e2f6f
|
||||
Subject: Junit @UNIT@ spyniajecca
|
||||
@@ -201,7 +201,7 @@ Support: %SUPPORT_URL%
|
||||
|
||||
Zboj junita @UNIT@.
|
||||
|
||||
-Vynik: @RESULT@.
|
||||
+Vynik: @JOB_RESULT@.
|
||||
|
||||
-- d34d037fff1847e6ae669a370e694725
|
||||
Subject: Junit @UNIT@ pieračytvaje svaju kanfihuracyju
|
||||
@@ -217,7 +217,7 @@ Support: %SUPPORT_URL%
|
||||
|
||||
Junit @UNIT@ pieračytaŭ svaju kanfihuracyju.
|
||||
|
||||
-Vynik: @RESULT@.
|
||||
+Vynik: @JOB_RESULT@.
|
||||
|
||||
-- 641257651c1b4ec9a8624d7a40a9e1e7
|
||||
Subject: Praces @EXECUTABLE@ nie moža być vykanany
|
||||
diff --git a/catalog/systemd.bg.catalog.in b/catalog/systemd.bg.catalog.in
|
||||
index 64d616f381..41f7b21bce 100644
|
||||
--- a/catalog/systemd.bg.catalog.in
|
||||
+++ b/catalog/systemd.bg.catalog.in
|
||||
@@ -178,7 +178,7 @@ Support: %SUPPORT_URL%
|
||||
|
||||
Стартирането на модул „@UNIT@“ завърши.
|
||||
|
||||
-Резултатът е: @RESULT@
|
||||
+Резултатът е: @JOB_RESULT@
|
||||
|
||||
-- de5b426a63be47a7b6ac3eaac82e2f6f
|
||||
Subject: Модул „@UNIT@“ се спира
|
||||
@@ -201,7 +201,7 @@ Support: %SUPPORT_URL%
|
||||
|
||||
Модулът „@UNIT@“ не успя да стартира.
|
||||
|
||||
-Резултатът е: @RESULT@
|
||||
+Резултатът е: @JOB_RESULT@
|
||||
|
||||
-- d34d037fff1847e6ae669a370e694725
|
||||
Subject: Модулът „@UNIT@“ започна презареждане на настройките си
|
||||
@@ -217,7 +217,7 @@ Support: %SUPPORT_URL%
|
||||
|
||||
Модулът „@UNIT@“ завърши презареждането на настройките си.
|
||||
|
||||
-Резултатът e: @RESULT@
|
||||
+Резултатът e: @JOB_RESULT@
|
||||
|
||||
-- 641257651c1b4ec9a8624d7a40a9e1e7
|
||||
Subject: Програмата „@EXECUTABLE@“ не успя да се стартира
|
||||
diff --git a/catalog/systemd.catalog.in b/catalog/systemd.catalog.in
|
||||
index 8234e387cf..49a45890f6 100644
|
||||
--- a/catalog/systemd.catalog.in
|
||||
+++ b/catalog/systemd.catalog.in
|
||||
@@ -202,7 +202,7 @@ Support: %SUPPORT_URL%
|
||||
|
||||
Unit @UNIT@ has finished starting up.
|
||||
|
||||
-The start-up result is @RESULT@.
|
||||
+The start-up result is @JOB_RESULT@.
|
||||
|
||||
-- de5b426a63be47a7b6ac3eaac82e2f6f
|
||||
Subject: Unit @UNIT@ has begun shutting down
|
||||
@@ -225,7 +225,7 @@ Support: %SUPPORT_URL%
|
||||
|
||||
Unit @UNIT@ has failed.
|
||||
|
||||
-The result is @RESULT@.
|
||||
+The result is @JOB_RESULT@.
|
||||
|
||||
-- d34d037fff1847e6ae669a370e694725
|
||||
Subject: Unit @UNIT@ has begun reloading its configuration
|
||||
@@ -241,7 +241,7 @@ Support: %SUPPORT_URL%
|
||||
|
||||
Unit @UNIT@ has finished reloading its configuration
|
||||
|
||||
-The result is @RESULT@.
|
||||
+The result is @JOB_RESULT@.
|
||||
|
||||
-- 641257651c1b4ec9a8624d7a40a9e1e7
|
||||
Subject: Process @EXECUTABLE@ could not be executed
|
||||
diff --git a/catalog/systemd.da.catalog.in b/catalog/systemd.da.catalog.in
|
||||
index 4e2bec8a0f..aecfafa05f 100644
|
||||
--- a/catalog/systemd.da.catalog.in
|
||||
+++ b/catalog/systemd.da.catalog.in
|
||||
@@ -159,7 +159,7 @@ Support: %SUPPORT_URL%
|
||||
|
||||
Enhed @UNIT@ er færdig med at starte op.
|
||||
|
||||
-Resultat for opstart er @RESULT@.
|
||||
+Resultat for opstart er @JOB_RESULT@.
|
||||
|
||||
-- de5b426a63be47a7b6ac3eaac82e2f6f
|
||||
Subject: Enhed @UNIT@ har påbegyndt nedlukning
|
||||
@@ -182,7 +182,7 @@ Support: %SUPPORT_URL%
|
||||
|
||||
Enhed @UNIT@ har fejlet.
|
||||
|
||||
-Resultatet er @RESULT@
|
||||
+Resultatet er @JOB_RESULT@
|
||||
|
||||
-- d34d037fff1847e6ae669a370e694725
|
||||
Subject: Enhed @UNIT@ har påbegyndt genindlæsning af sin konfiguration
|
||||
@@ -198,7 +198,7 @@ Support: %SUPPORT_URL%
|
||||
|
||||
Enhed @UNIT@ er færdig med at genindlæse sin konfiguration
|
||||
|
||||
-Resultatet er: @RESULT@.
|
||||
+Resultatet er: @JOB_RESULT@.
|
||||
|
||||
-- 641257651c1b4ec9a8624d7a40a9e1e7
|
||||
Subject: Process @EXECUTABLE@ kunne ikke eksekveres
|
||||
diff --git a/catalog/systemd.fr.catalog.in b/catalog/systemd.fr.catalog.in
|
||||
index 156b1a37dc..13edd083cb 100644
|
||||
--- a/catalog/systemd.fr.catalog.in
|
||||
+++ b/catalog/systemd.fr.catalog.in
|
||||
@@ -191,7 +191,7 @@ Subject: L'unité (unit) @UNIT@ a terminé son démarrage
|
||||
Defined-By: systemd
|
||||
Support: %SUPPORT_URL%
|
||||
|
||||
-L'unité (unit) @UNIT@ a terminé son démarrage, avec le résultat @RESULT@.
|
||||
+L'unité (unit) @UNIT@ a terminé son démarrage, avec le résultat @JOB_RESULT@.
|
||||
|
||||
-- de5b426a63be47a7b6ac3eaac82e2f6f
|
||||
Subject: L'unité (unit) @UNIT@ a commencé à s'arrêter
|
||||
@@ -212,7 +212,7 @@ Subject: L'unité (unit) @UNIT@ a échoué
|
||||
Defined-By: systemd
|
||||
Support: %SUPPORT_URL%
|
||||
|
||||
-L'unité (unit) @UNIT@ a échoué, avec le résultat @RESULT@.
|
||||
+L'unité (unit) @UNIT@ a échoué, avec le résultat @JOB_RESULT@.
|
||||
|
||||
-- d34d037fff1847e6ae669a370e694725
|
||||
Subject: L'unité (unit) @UNIT@ a commencé à recharger sa configuration
|
||||
@@ -227,7 +227,7 @@ Defined-By: systemd
|
||||
Support: %SUPPORT_URL%
|
||||
|
||||
L'unité (unit) @UNIT@ a terminé de recharger configuration,
|
||||
-avec le résultat @RESULT@.
|
||||
+avec le résultat @JOB_RESULT@.
|
||||
|
||||
-- 641257651c1b4ec9a8624d7a40a9e1e7
|
||||
Subject: Le processus @EXECUTABLE@ n'a pas pu être exécuté
|
||||
diff --git a/catalog/systemd.hr.catalog.in b/catalog/systemd.hr.catalog.in
|
||||
index c4808b4c7d..4526ae2a8c 100644
|
||||
--- a/catalog/systemd.hr.catalog.in
|
||||
+++ b/catalog/systemd.hr.catalog.in
|
||||
@@ -173,7 +173,7 @@ Support: %SUPPORT_URL%
|
||||
|
||||
Jedinica @UNIT@ je završila pokretanje.
|
||||
|
||||
-Rezultat pokretanja je @RESULT@.
|
||||
+Rezultat pokretanja je @JOB_RESULT@.
|
||||
|
||||
-- de5b426a63be47a7b6ac3eaac82e2f6f
|
||||
Subject: Jedinica @UNIT@ je započela isključivanje
|
||||
@@ -196,7 +196,7 @@ Support: %SUPPORT_URL%
|
||||
|
||||
Jedinica @UNIT@ nije uspjela.
|
||||
|
||||
-Rezultat je @RESULT@.
|
||||
+Rezultat je @JOB_RESULT@.
|
||||
|
||||
-- d34d037fff1847e6ae669a370e694725
|
||||
Subject: Jedinica @UNIT@ je započela ponovno učitavati podešavanja
|
||||
@@ -212,7 +212,7 @@ Support: %SUPPORT_URL%
|
||||
|
||||
Jedinica @UNIT@ je završila ponovno učitavati podešavanja
|
||||
|
||||
-Rezultat je @RESULT@.
|
||||
+Rezultat je @JOB_RESULT@.
|
||||
|
||||
-- 641257651c1b4ec9a8624d7a40a9e1e7
|
||||
Subject: Proces @EXECUTABLE@ se ne može pokrenuti
|
||||
diff --git a/catalog/systemd.hu.catalog.in b/catalog/systemd.hu.catalog.in
|
||||
index 6c6d7e7934..5565b80b2a 100644
|
||||
--- a/catalog/systemd.hu.catalog.in
|
||||
+++ b/catalog/systemd.hu.catalog.in
|
||||
@@ -161,7 +161,7 @@ Support: %SUPPORT_URL%
|
||||
|
||||
A(z) @UNIT@ egység befejezte az indulást
|
||||
|
||||
-Az indítás eredménye: @RESULT@.
|
||||
+Az indítás eredménye: @JOB_RESULT@.
|
||||
|
||||
-- de5b426a63be47a7b6ac3eaac82e2f6f
|
||||
Subject: A(z) @UNIT@ egység megkezdte a leállást
|
||||
@@ -184,7 +184,7 @@ Support: %SUPPORT_URL%
|
||||
|
||||
A(z) @UNIT@ egység hibát jelzett.
|
||||
|
||||
-Az eredmény: @RESULT@.
|
||||
+Az eredmény: @JOB_RESULT@.
|
||||
|
||||
-- d34d037fff1847e6ae669a370e694725
|
||||
Subject: A(z) @UNIT@ egység megkezdte a beállításainak újratöltését
|
||||
@@ -200,7 +200,7 @@ Support: %SUPPORT_URL%
|
||||
|
||||
A(z) @UNIT@ egység befejezte a beállításainak újratöltését.
|
||||
|
||||
-Az eredmény: @RESULT@.
|
||||
+Az eredmény: @JOB_RESULT@.
|
||||
|
||||
-- 641257651c1b4ec9a8624d7a40a9e1e7
|
||||
Subject: A folyamat végrehajtása sikertelen: @EXECUTABLE@
|
||||
diff --git a/catalog/systemd.it.catalog.in b/catalog/systemd.it.catalog.in
|
||||
index 4fd1f2a933..8ce4fa5d92 100644
|
||||
--- a/catalog/systemd.it.catalog.in
|
||||
+++ b/catalog/systemd.it.catalog.in
|
||||
@@ -191,7 +191,7 @@ Support: %SUPPORT_URL%
|
||||
|
||||
L'unità @UNIT@ ha terminato la fase di avvio.
|
||||
|
||||
-La fase di avvio è @RESULT@.
|
||||
+La fase di avvio è @JOB_RESULT@.
|
||||
|
||||
-- de5b426a63be47a7b6ac3eaac82e2f6f
|
||||
Subject: L'unità @UNIT@ inizia la fase di spegnimento
|
||||
@@ -214,7 +214,7 @@ Support: %SUPPORT_URL%
|
||||
|
||||
L'unità @UNIT@ è fallita.
|
||||
|
||||
-Il risultato è @RESULT@.
|
||||
+Il risultato è @JOB_RESULT@.
|
||||
|
||||
-- d34d037fff1847e6ae669a370e694725
|
||||
Subject: L'unità @UNIT@ inizia a caricare la propria configurazione
|
||||
@@ -230,7 +230,7 @@ Support: %SUPPORT_URL%
|
||||
|
||||
L'unità @UNIT@ è terminata ricaricando la propria configurazione
|
||||
|
||||
-Il risultato è @RESULT@.
|
||||
+Il risultato è @JOB_RESULT@.
|
||||
|
||||
-- 641257651c1b4ec9a8624d7a40a9e1e7
|
||||
Subject: Il processo @EXECUTABLE@ non può essere eseguito
|
||||
diff --git a/catalog/systemd.ko.catalog.in b/catalog/systemd.ko.catalog.in
|
||||
index fc0faad02c..59fbde8b62 100644
|
||||
--- a/catalog/systemd.ko.catalog.in
|
||||
+++ b/catalog/systemd.ko.catalog.in
|
||||
@@ -182,7 +182,7 @@ Support: %SUPPORT_URL%
|
||||
|
||||
@UNIT@ 유닛 시동을 마쳤습니다.
|
||||
|
||||
-시동 결과는 @RESULT@ 입니다.
|
||||
+시동 결과는 @JOB_RESULT@ 입니다.
|
||||
|
||||
-- de5b426a63be47a7b6ac3eaac82e2f6f
|
||||
Subject: @UNIT@ 유닛 끝내기 동작 시작
|
||||
@@ -205,7 +205,7 @@ Support: %SUPPORT_URL%
|
||||
|
||||
@UNIT@ 유닛 동작에 실패했습니다.
|
||||
|
||||
-결과는 @RESULT@ 입니다.
|
||||
+결과는 @JOB_RESULT@ 입니다.
|
||||
|
||||
-- d34d037fff1847e6ae669a370e694725
|
||||
Subject: @UNIT@ 유닛 설정 다시 읽기 시작
|
||||
@@ -221,7 +221,7 @@ Support: %SUPPORT_URL%
|
||||
|
||||
@UNIT@ 유닛의 설정 다시 읽기 동작을 끝냈습니다.
|
||||
|
||||
-결과는 @RESULT@ 입니다.
|
||||
+결과는 @JOB_RESULT@ 입니다.
|
||||
|
||||
-- 641257651c1b4ec9a8624d7a40a9e1e7
|
||||
Subject: @EXECUTABLE@ 프로세스 시작할 수 없음
|
||||
diff --git a/catalog/systemd.pl.catalog.in b/catalog/systemd.pl.catalog.in
|
||||
index 998894bd0a..b73f56ca11 100644
|
||||
--- a/catalog/systemd.pl.catalog.in
|
||||
+++ b/catalog/systemd.pl.catalog.in
|
||||
@@ -201,7 +201,7 @@ Support: %SUPPORT_URL%
|
||||
|
||||
Jednostka @UNIT@ ukończyła uruchamianie.
|
||||
|
||||
-Wynik uruchamiania: @RESULT@.
|
||||
+Wynik uruchamiania: @JOB_RESULT@.
|
||||
|
||||
-- de5b426a63be47a7b6ac3eaac82e2f6f
|
||||
Subject: Rozpoczęto wyłączanie jednostki @UNIT@
|
||||
@@ -224,7 +224,7 @@ Support: %SUPPORT_URL%
|
||||
|
||||
Jednostka @UNIT@ się nie powiodła.
|
||||
|
||||
-Wynik: @RESULT@.
|
||||
+Wynik: @JOB_RESULT@.
|
||||
|
||||
-- d34d037fff1847e6ae669a370e694725
|
||||
Subject: Rozpoczęto ponowne wczytywanie konfiguracji jednostki @UNIT@
|
||||
@@ -240,7 +240,7 @@ Support: %SUPPORT_URL%
|
||||
|
||||
Jednostka @UNIT@ ukończyła ponowne wczytywanie swojej konfiguracji.
|
||||
|
||||
-Wynik: @RESULT@.
|
||||
+Wynik: @JOB_RESULT@.
|
||||
|
||||
-- 641257651c1b4ec9a8624d7a40a9e1e7
|
||||
Subject: Nie można wykonać procesu @EXECUTABLE@
|
||||
diff --git a/catalog/systemd.pt_BR.catalog.in b/catalog/systemd.pt_BR.catalog.in
|
||||
index db1cb03198..edaefb7164 100644
|
||||
--- a/catalog/systemd.pt_BR.catalog.in
|
||||
+++ b/catalog/systemd.pt_BR.catalog.in
|
||||
@@ -162,7 +162,7 @@ Support: %SUPPORT_URL%
|
||||
|
||||
A unidade @UNIT@ concluiu a inicialização.
|
||||
|
||||
-The start-up result is @RESULT@.
|
||||
+The start-up result is @JOB_RESULT@.
|
||||
|
||||
-- de5b426a63be47a7b6ac3eaac82e2f6f
|
||||
Subject: Unidade @UNIT@ sendo desligado
|
||||
@@ -185,7 +185,7 @@ Support: %SUPPORT_URL%
|
||||
|
||||
A unidade @UNIT@ falhou.
|
||||
|
||||
-O resultado é @RESULT@.
|
||||
+O resultado é @JOB_RESULT@.
|
||||
|
||||
-- d34d037fff1847e6ae669a370e694725
|
||||
Subject: Unidade @UNIT@ iniciou recarregamento de sua configuração
|
||||
@@ -201,7 +201,7 @@ Support: %SUPPORT_URL%
|
||||
|
||||
A unidade @UNIT@ concluiu o recarregamento de sua configuração.
|
||||
|
||||
-O resultado é @RESULT@.
|
||||
+O resultado é @JOB_RESULT@.
|
||||
|
||||
-- 641257651c1b4ec9a8624d7a40a9e1e7
|
||||
Subject: Processo @EXECUTABLE@ não pôde ser executado
|
||||
diff --git a/catalog/systemd.ru.catalog.in b/catalog/systemd.ru.catalog.in
|
||||
index 645edaa922..ccdc685037 100644
|
||||
--- a/catalog/systemd.ru.catalog.in
|
||||
+++ b/catalog/systemd.ru.catalog.in
|
||||
@@ -227,7 +227,7 @@ Support: %SUPPORT_URL%
|
||||
|
||||
Процесс запуска юнита @UNIT@ был завершен.
|
||||
|
||||
-Результат: @RESULT@.
|
||||
+Результат: @JOB_RESULT@.
|
||||
|
||||
# Subject: Unit @UNIT@ has begun shutting down
|
||||
-- de5b426a63be47a7b6ac3eaac82e2f6f
|
||||
@@ -253,7 +253,7 @@ Support: %SUPPORT_URL%
|
||||
|
||||
Произошел сбой юнита @UNIT@.
|
||||
|
||||
-Результат: @RESULT@.
|
||||
+Результат: @JOB_RESULT@.
|
||||
|
||||
# Subject: Unit @UNIT@ has begun with reloading its configuration
|
||||
-- d34d037fff1847e6ae669a370e694725
|
||||
@@ -271,7 +271,7 @@ Support: %SUPPORT_URL%
|
||||
|
||||
Юнит @UNIT@ завершил процесс перечитывания своей конфигурации.
|
||||
|
||||
-Результат: @RESULT@.
|
||||
+Результат: @JOB_RESULT@.
|
||||
|
||||
# Subject: Process @EXECUTABLE@ could not be executed
|
||||
-- 641257651c1b4ec9a8624d7a40a9e1e7
|
||||
diff --git a/catalog/systemd.sr.catalog.in b/catalog/systemd.sr.catalog.in
|
||||
index f5746715a4..7cb6546d43 100644
|
||||
--- a/catalog/systemd.sr.catalog.in
|
||||
+++ b/catalog/systemd.sr.catalog.in
|
||||
@@ -158,7 +158,7 @@ Support: %SUPPORT_URL%
|
||||
|
||||
Јединица @UNIT@ је завршила са покретањем.
|
||||
|
||||
-Исход покретања је @RESULT@.
|
||||
+Исход покретања је @JOB_RESULT@.
|
||||
|
||||
-- de5b426a63be47a7b6ac3eaac82e2f6f
|
||||
Subject: Јединица @UNIT@ је почела са гашењем
|
||||
@@ -181,7 +181,7 @@ Support: %SUPPORT_URL%
|
||||
|
||||
Јединица @UNIT@ је пукла.
|
||||
|
||||
-Исход је @RESULT@.
|
||||
+Исход је @JOB_RESULT@.
|
||||
|
||||
-- d34d037fff1847e6ae669a370e694725
|
||||
Subject: Јединица @UNIT@ је почела са поновним учитавањем свог подешавања
|
||||
@@ -197,7 +197,7 @@ Support: %SUPPORT_URL%
|
||||
|
||||
Јединица @UNIT@ је завршила са поновним учитавањем свог подешавања
|
||||
|
||||
-Исход је @RESULT@.
|
||||
+Исход је @JOB_RESULT@.
|
||||
|
||||
-- 641257651c1b4ec9a8624d7a40a9e1e7
|
||||
Subject: Процес @EXECUTABLE@ није могао бити извршен
|
||||
diff --git a/catalog/systemd.zh_CN.catalog.in b/catalog/systemd.zh_CN.catalog.in
|
||||
index fa58448acf..d6ac2592b8 100644
|
||||
--- a/catalog/systemd.zh_CN.catalog.in
|
||||
+++ b/catalog/systemd.zh_CN.catalog.in
|
||||
@@ -156,7 +156,7 @@ Support: %SUPPORT_URL%
|
||||
|
||||
@UNIT@ 单元已结束启动。
|
||||
|
||||
-启动结果为“@RESULT@”。
|
||||
+启动结果为“@JOB_RESULT@”。
|
||||
|
||||
-- de5b426a63be47a7b6ac3eaac82e2f6f
|
||||
Subject: @UNIT@ 单元已开始停止操作
|
||||
@@ -179,7 +179,7 @@ Support: %SUPPORT_URL%
|
||||
|
||||
@UNIT@ 单元已失败。
|
||||
|
||||
-结果为“@RESULT@”。
|
||||
+结果为“@JOB_RESULT@”。
|
||||
|
||||
-- d34d037fff1847e6ae669a370e694725
|
||||
Subject: @UNIT@ 单元已开始重新载入其配置
|
||||
@@ -195,7 +195,7 @@ Support: %SUPPORT_URL%
|
||||
|
||||
@UNIT@ 单元已结束配置重载入操作。
|
||||
|
||||
-结果为“@RESULT@”。
|
||||
+结果为“@JOB_RESULT@”。
|
||||
|
||||
-- 641257651c1b4ec9a8624d7a40a9e1e7
|
||||
Subject: 进程 @EXECUTABLE@ 无法执行
|
||||
diff --git a/catalog/systemd.zh_TW.catalog.in b/catalog/systemd.zh_TW.catalog.in
|
||||
index 17bd2bc9af..a468c2f6bf 100644
|
||||
--- a/catalog/systemd.zh_TW.catalog.in
|
||||
+++ b/catalog/systemd.zh_TW.catalog.in
|
||||
@@ -160,7 +160,7 @@ Support: %SUPPORT_URL%
|
||||
|
||||
單位 @UNIT@ 啟動已結束。
|
||||
|
||||
-啟動結果為 @RESULT@。
|
||||
+啟動結果為 @JOB_RESULT@。
|
||||
|
||||
-- de5b426a63be47a7b6ac3eaac82e2f6f
|
||||
Subject: 單位 @UNIT@ 已開始關閉
|
||||
@@ -183,7 +183,7 @@ Support: %SUPPORT_URL%
|
||||
|
||||
單位 @UNIT@ 已失敗。
|
||||
|
||||
-結果為 @RESULT@。
|
||||
+結果為 @JOB_RESULT@。
|
||||
|
||||
-- d34d037fff1847e6ae669a370e694725
|
||||
Subject: 單位 @UNIT@ 已開始重新載入其設定
|
||||
@@ -199,7 +199,7 @@ Support: %SUPPORT_URL%
|
||||
|
||||
單位 @UNIT@ 已結束重新載入其設定
|
||||
|
||||
-結果為 @RESULT@。
|
||||
+結果為 @JOB_RESULT@。
|
||||
|
||||
-- 641257651c1b4ec9a8624d7a40a9e1e7
|
||||
Subject: 行程 @EXECUTABLE@ 無法執行
|
@ -0,0 +1,273 @@
|
||||
From 0f7a4f49a7ce95e87061afe03ac40662a1eb0e2d Mon Sep 17 00:00:00 2001
|
||||
From: shinygold <10763595+shinygold@users.noreply.github.com>
|
||||
Date: Tue, 16 Jul 2019 13:06:16 +0200
|
||||
Subject: [PATCH] cryptsetup: add keyfile-timeout to allow a keydev timeout and
|
||||
allow to fallback to a password if it fails.
|
||||
|
||||
(cherry picked from commit 50d2eba27b9bfc77ef6b40e5721713846815418b)
|
||||
|
||||
Resolves: #1763155
|
||||
---
|
||||
src/cryptsetup/cryptsetup-generator.c | 119 ++++++++++++++++++--------
|
||||
src/cryptsetup/cryptsetup.c | 5 +-
|
||||
2 files changed, 89 insertions(+), 35 deletions(-)
|
||||
|
||||
diff --git a/src/cryptsetup/cryptsetup-generator.c b/src/cryptsetup/cryptsetup-generator.c
|
||||
index 52c1262728..1e8e3ba00d 100644
|
||||
--- a/src/cryptsetup/cryptsetup-generator.c
|
||||
+++ b/src/cryptsetup/cryptsetup-generator.c
|
||||
@@ -40,10 +40,39 @@ static Hashmap *arg_disks = NULL;
|
||||
static char *arg_default_options = NULL;
|
||||
static char *arg_default_keyfile = NULL;
|
||||
|
||||
-static int generate_keydev_mount(const char *name, const char *keydev, char **unit, char **mount) {
|
||||
- _cleanup_free_ char *u = NULL, *what = NULL, *where = NULL, *name_escaped = NULL;
|
||||
+static int split_keyspec(const char *keyspec, char **keyfile, char **keydev) {
|
||||
+ _cleanup_free_ char *kfile = NULL, *kdev = NULL;
|
||||
+ char *c;
|
||||
+
|
||||
+ assert(keyspec);
|
||||
+ assert(keyfile);
|
||||
+ assert(keydev);
|
||||
+
|
||||
+ c = strrchr(keyspec, ':');
|
||||
+ if (c) {
|
||||
+ kfile = strndup(keyspec, c-keyspec);
|
||||
+ kdev = strdup(c + 1);
|
||||
+ if (!*kfile || !*kdev)
|
||||
+ return log_oom();
|
||||
+ } else {
|
||||
+ /* No keydev specified */
|
||||
+ kfile = strdup(keyspec);
|
||||
+ kdev = NULL;
|
||||
+ if (!*kfile)
|
||||
+ return log_oom();
|
||||
+ }
|
||||
+
|
||||
+ *keyfile = TAKE_PTR(kfile);
|
||||
+ *keydev = TAKE_PTR(kdev);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int generate_keydev_mount(const char *name, const char *keydev, const char *keydev_timeout, bool canfail, char **unit, char **mount) {
|
||||
+ _cleanup_free_ char *u = NULL, *what = NULL, *where = NULL, *name_escaped = NULL, *device_unit = NULL;
|
||||
_cleanup_fclose_ FILE *f = NULL;
|
||||
int r;
|
||||
+ usec_t timeout_us;
|
||||
|
||||
assert(name);
|
||||
assert(keydev);
|
||||
@@ -88,7 +117,25 @@ static int generate_keydev_mount(const char *name, const char *keydev, char **un
|
||||
"[Mount]\n"
|
||||
"What=%s\n"
|
||||
"Where=%s\n"
|
||||
- "Options=ro\n", what, where);
|
||||
+ "Options=ro%s\n", what, where, canfail ? ",nofail" : "");
|
||||
+
|
||||
+ if (keydev_timeout) {
|
||||
+ r = parse_sec_fix_0(keydev_timeout, &timeout_us);
|
||||
+ if (r >= 0) {
|
||||
+ r = unit_name_from_path(what, ".device", &device_unit);
|
||||
+ if (r < 0)
|
||||
+ return log_error_errno(r, "Failed to generate unit name: %m");
|
||||
+
|
||||
+ r = write_drop_in_format(arg_dest, device_unit, 90, "device-timeout",
|
||||
+ "# Automatically generated by systemd-cryptsetup-generator \n\n"
|
||||
+ "[Unit]\nJobRunningTimeoutSec=%s", keydev_timeout);
|
||||
+ if (r < 0)
|
||||
+ return log_error_errno(r, "Failed to write device drop-in: %m");
|
||||
+
|
||||
+ } else
|
||||
+ log_warning_errno(r, "Failed to parse %s, ignoring: %m", keydev_timeout);
|
||||
+
|
||||
+ }
|
||||
|
||||
r = fflush_and_check(f);
|
||||
if (r < 0)
|
||||
@@ -103,16 +150,17 @@ static int generate_keydev_mount(const char *name, const char *keydev, char **un
|
||||
static int create_disk(
|
||||
const char *name,
|
||||
const char *device,
|
||||
- const char *keydev,
|
||||
const char *password,
|
||||
+ const char *keydev,
|
||||
const char *options) {
|
||||
|
||||
_cleanup_free_ char *n = NULL, *d = NULL, *u = NULL, *e = NULL,
|
||||
- *filtered = NULL, *u_escaped = NULL, *password_escaped = NULL, *filtered_escaped = NULL, *name_escaped = NULL, *keydev_mount = NULL;
|
||||
+ *keydev_mount = NULL, *keyfile_timeout_value = NULL, *password_escaped = NULL,
|
||||
+ *filtered = NULL, *u_escaped = NULL, *filtered_escaped = NULL, *name_escaped = NULL;
|
||||
_cleanup_fclose_ FILE *f = NULL;
|
||||
const char *dmname;
|
||||
bool noauto, nofail, tmp, swap, netdev;
|
||||
- int r;
|
||||
+ int r, keyfile_can_timeout;
|
||||
|
||||
assert(name);
|
||||
assert(device);
|
||||
@@ -123,6 +171,10 @@ static int create_disk(
|
||||
swap = fstab_test_option(options, "swap\0");
|
||||
netdev = fstab_test_option(options, "_netdev\0");
|
||||
|
||||
+ keyfile_can_timeout = fstab_filter_options(options, "keyfile-timeout\0", NULL, &keyfile_timeout_value, NULL);
|
||||
+ if (keyfile_can_timeout < 0)
|
||||
+ return log_error_errno(keyfile_can_timeout, "Failed to parse keyfile-timeout= option value: %m");
|
||||
+
|
||||
if (tmp && swap) {
|
||||
log_error("Device '%s' cannot be both 'tmp' and 'swap'. Ignoring.", name);
|
||||
return -EINVAL;
|
||||
@@ -152,12 +204,6 @@ static int create_disk(
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to generate unit name: %m");
|
||||
|
||||
- if (password) {
|
||||
- password_escaped = specifier_escape(password);
|
||||
- if (!password_escaped)
|
||||
- return log_oom();
|
||||
- }
|
||||
-
|
||||
if (keydev && !password) {
|
||||
log_error("Key device is specified, but path to the password file is missing.");
|
||||
return -EINVAL;
|
||||
@@ -178,10 +224,16 @@ static int create_disk(
|
||||
"After=%s\n",
|
||||
netdev ? "remote-fs-pre.target" : "cryptsetup-pre.target");
|
||||
|
||||
+ if (password) {
|
||||
+ password_escaped = specifier_escape(password);
|
||||
+ if (!password_escaped)
|
||||
+ return log_oom();
|
||||
+ }
|
||||
+
|
||||
if (keydev) {
|
||||
_cleanup_free_ char *unit = NULL, *p = NULL;
|
||||
|
||||
- r = generate_keydev_mount(name, keydev, &unit, &keydev_mount);
|
||||
+ r = generate_keydev_mount(name, keydev, keyfile_timeout_value, keyfile_can_timeout > 0, &unit, &keydev_mount);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to generate keydev mount unit: %m");
|
||||
|
||||
@@ -190,6 +242,12 @@ static int create_disk(
|
||||
return log_oom();
|
||||
|
||||
free_and_replace(password_escaped, p);
|
||||
+
|
||||
+ fprintf(f, "After=%s\n", unit);
|
||||
+ if (keyfile_can_timeout > 0)
|
||||
+ fprintf(f, "Wants=%s\n", unit);
|
||||
+ else
|
||||
+ fprintf(f, "Requires=%s\n", unit);
|
||||
}
|
||||
|
||||
if (!nofail)
|
||||
@@ -197,7 +255,7 @@ static int create_disk(
|
||||
"Before=%s\n",
|
||||
netdev ? "remote-cryptsetup.target" : "cryptsetup.target");
|
||||
|
||||
- if (password) {
|
||||
+ if (password && !keydev) {
|
||||
if (STR_IN_SET(password, "/dev/urandom", "/dev/random", "/dev/hw_random"))
|
||||
fputs("After=systemd-random-seed.service\n", f);
|
||||
else if (!STR_IN_SET(password, "-", "none")) {
|
||||
@@ -271,7 +329,7 @@ static int create_disk(
|
||||
|
||||
if (keydev)
|
||||
fprintf(f,
|
||||
- "ExecStartPost=" UMOUNT_PATH " %s\n\n",
|
||||
+ "ExecStartPost=-" UMOUNT_PATH " %s\n\n",
|
||||
keydev_mount);
|
||||
|
||||
r = fflush_and_check(f);
|
||||
@@ -394,7 +452,6 @@ static int parse_proc_cmdline_item(const char *key, const char *value, void *dat
|
||||
} else if (streq(key, "luks.key")) {
|
||||
size_t n;
|
||||
_cleanup_free_ char *keyfile = NULL, *keydev = NULL;
|
||||
- char *c;
|
||||
const char *keyspec;
|
||||
|
||||
if (proc_cmdline_value_missing(key, value))
|
||||
@@ -421,23 +478,13 @@ static int parse_proc_cmdline_item(const char *key, const char *value, void *dat
|
||||
return log_oom();
|
||||
|
||||
keyspec = value + n + 1;
|
||||
- c = strrchr(keyspec, ':');
|
||||
- if (c) {
|
||||
- *c = '\0';
|
||||
- keyfile = strdup(keyspec);
|
||||
- keydev = strdup(c + 1);
|
||||
-
|
||||
- if (!keyfile || !keydev)
|
||||
- return log_oom();
|
||||
- } else {
|
||||
- /* No keydev specified */
|
||||
- keyfile = strdup(keyspec);
|
||||
- if (!keyfile)
|
||||
- return log_oom();
|
||||
- }
|
||||
+ r = split_keyspec(keyspec, &keyfile, &keydev);
|
||||
+ if (r < 0)
|
||||
+ return r;
|
||||
|
||||
free_and_replace(d->keyfile, keyfile);
|
||||
free_and_replace(d->keydev, keydev);
|
||||
+
|
||||
} else if (streq(key, "luks.name")) {
|
||||
|
||||
if (proc_cmdline_value_missing(key, value))
|
||||
@@ -485,7 +532,7 @@ static int add_crypttab_devices(void) {
|
||||
int r, k;
|
||||
char line[LINE_MAX], *l, *uuid;
|
||||
crypto_device *d = NULL;
|
||||
- _cleanup_free_ char *name = NULL, *device = NULL, *keyfile = NULL, *options = NULL;
|
||||
+ _cleanup_free_ char *name = NULL, *device = NULL, *keydev = NULL, *keyfile = NULL, *keyspec = NULL, *options = NULL;
|
||||
|
||||
if (!fgets(line, sizeof(line), f))
|
||||
break;
|
||||
@@ -496,7 +543,7 @@ static int add_crypttab_devices(void) {
|
||||
if (IN_SET(*l, 0, '#'))
|
||||
continue;
|
||||
|
||||
- k = sscanf(l, "%ms %ms %ms %ms", &name, &device, &keyfile, &options);
|
||||
+ k = sscanf(l, "%ms %ms %ms %ms", &name, &device, &keyspec, &options);
|
||||
if (k < 2 || k > 4) {
|
||||
log_error("Failed to parse /etc/crypttab:%u, ignoring.", crypttab_line);
|
||||
continue;
|
||||
@@ -515,7 +562,11 @@ static int add_crypttab_devices(void) {
|
||||
continue;
|
||||
}
|
||||
|
||||
- r = create_disk(name, device, NULL, keyfile, (d && d->options) ? d->options : options);
|
||||
+ r = split_keyspec(keyspec, &keyfile, &keydev);
|
||||
+ if (r < 0)
|
||||
+ return r;
|
||||
+
|
||||
+ r = create_disk(name, device, keyfile, keydev, (d && d->options) ? d->options : options);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
@@ -555,7 +606,7 @@ static int add_proc_cmdline_devices(void) {
|
||||
else
|
||||
options = "timeout=0";
|
||||
|
||||
- r = create_disk(d->name, device, d->keydev, d->keyfile ?: arg_default_keyfile, options);
|
||||
+ r = create_disk(d->name, device, d->keyfile ?: arg_default_keyfile, d->keydev, options);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
diff --git a/src/cryptsetup/cryptsetup.c b/src/cryptsetup/cryptsetup.c
|
||||
index 9071126c2e..0881aea915 100644
|
||||
--- a/src/cryptsetup/cryptsetup.c
|
||||
+++ b/src/cryptsetup/cryptsetup.c
|
||||
@@ -69,7 +69,10 @@ static int parse_one_option(const char *option) {
|
||||
assert(option);
|
||||
|
||||
/* Handled outside of this tool */
|
||||
- if (STR_IN_SET(option, "noauto", "auto", "nofail", "fail", "_netdev"))
|
||||
+ if (STR_IN_SET(option, "noauto", "auto", "nofail", "fail", "_netdev", "keyfile-timeout"))
|
||||
+ return 0;
|
||||
+
|
||||
+ if (startswith(option, "keyfile-timeout="))
|
||||
return 0;
|
||||
|
||||
if ((val = startswith(option, "cipher="))) {
|
@ -0,0 +1,44 @@
|
||||
From fdb86185b56619c59602c6546fd0710eec4a6e85 Mon Sep 17 00:00:00 2001
|
||||
From: shinygold <10763595+shinygold@users.noreply.github.com>
|
||||
Date: Tue, 16 Jul 2019 13:05:34 +0200
|
||||
Subject: [PATCH] cryptsetup: add documentation for keyfile-timeout
|
||||
|
||||
(cherry picked from commit 4e1334512debb27f4a0c4a6da237a4b8d59fea08)
|
||||
|
||||
Related: #1763155
|
||||
---
|
||||
man/crypttab.xml | 14 +++++++++++++-
|
||||
1 file changed, 13 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/man/crypttab.xml b/man/crypttab.xml
|
||||
index 3574ce00da..6074315980 100644
|
||||
--- a/man/crypttab.xml
|
||||
+++ b/man/crypttab.xml
|
||||
@@ -150,6 +150,17 @@
|
||||
sequential order.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
+ <varlistentry>
|
||||
+ <term><option>keyfile-timeout=</option></term>
|
||||
+
|
||||
+ <listitem><para> Specifies the timeout for the device on
|
||||
+ which the key file resides and falls back to a password if
|
||||
+ it could not be mounted. See
|
||||
+ <citerefentry><refentrytitle>systemd-cryptsetup-generator</refentrytitle><manvolnum>8</manvolnum></citerefentry>
|
||||
+ for key files on external devices.
|
||||
+ </para></listitem>
|
||||
+ </varlistentry>
|
||||
+
|
||||
<varlistentry>
|
||||
<term><option>luks</option></term>
|
||||
|
||||
@@ -417,7 +428,8 @@
|
||||
<programlisting>luks UUID=2505567a-9e27-4efe-a4d5-15ad146c258b
|
||||
swap /dev/sda7 /dev/urandom swap
|
||||
truecrypt /dev/sda2 /etc/container_password tcrypt
|
||||
-hidden /mnt/tc_hidden /dev/null tcrypt-hidden,tcrypt-keyfile=/etc/keyfile</programlisting>
|
||||
+hidden /mnt/tc_hidden /dev/null tcrypt-hidden,tcrypt-keyfile=/etc/keyfile
|
||||
+external /dev/sda3 keyfile:LABEL=keydev keyfile-timeout=10s</programlisting>
|
||||
</example>
|
||||
</refsect1>
|
||||
|
@ -0,0 +1,63 @@
|
||||
From 0577d8378645c1ecd909b74403cefe31ed569398 Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= <zbyszek@in.waw.pl>
|
||||
Date: Thu, 1 Aug 2019 08:13:13 +0200
|
||||
Subject: [PATCH] cryptsetup: use unabbrieviated variable names
|
||||
|
||||
Now that "ret_" has been added to the output variables, we can name
|
||||
the internal variables without artificial abbrevs.
|
||||
|
||||
(cherry picked from commit 5d2100dc4c32abbce4109e75cbfbbef6e1b2b7b1)
|
||||
|
||||
Related: #1763155
|
||||
---
|
||||
src/cryptsetup/cryptsetup-generator.c | 26 +++++++++++++-------------
|
||||
1 file changed, 13 insertions(+), 13 deletions(-)
|
||||
|
||||
diff --git a/src/cryptsetup/cryptsetup-generator.c b/src/cryptsetup/cryptsetup-generator.c
|
||||
index 1e8e3ba00d..7b234e37be 100644
|
||||
--- a/src/cryptsetup/cryptsetup-generator.c
|
||||
+++ b/src/cryptsetup/cryptsetup-generator.c
|
||||
@@ -40,30 +40,30 @@ static Hashmap *arg_disks = NULL;
|
||||
static char *arg_default_options = NULL;
|
||||
static char *arg_default_keyfile = NULL;
|
||||
|
||||
-static int split_keyspec(const char *keyspec, char **keyfile, char **keydev) {
|
||||
- _cleanup_free_ char *kfile = NULL, *kdev = NULL;
|
||||
- char *c;
|
||||
+static int split_keyspec(const char *keyspec, char **ret_keyfile, char **ret_keydev) {
|
||||
+ _cleanup_free_ char *keyfile = NULL, *keydev = NULL;
|
||||
+ const char *c;
|
||||
|
||||
assert(keyspec);
|
||||
- assert(keyfile);
|
||||
- assert(keydev);
|
||||
+ assert(ret_keyfile);
|
||||
+ assert(ret_keydev);
|
||||
|
||||
c = strrchr(keyspec, ':');
|
||||
if (c) {
|
||||
- kfile = strndup(keyspec, c-keyspec);
|
||||
- kdev = strdup(c + 1);
|
||||
- if (!*kfile || !*kdev)
|
||||
+ keyfile = strndup(keyspec, c-keyspec);
|
||||
+ keydev = strdup(c + 1);
|
||||
+ if (!keyfile || !keydev)
|
||||
return log_oom();
|
||||
} else {
|
||||
/* No keydev specified */
|
||||
- kfile = strdup(keyspec);
|
||||
- kdev = NULL;
|
||||
- if (!*kfile)
|
||||
+ keyfile = strdup(keyspec);
|
||||
+ keydev = NULL;
|
||||
+ if (!keyfile)
|
||||
return log_oom();
|
||||
}
|
||||
|
||||
- *keyfile = TAKE_PTR(kfile);
|
||||
- *keydev = TAKE_PTR(kdev);
|
||||
+ *ret_keyfile = TAKE_PTR(keyfile);
|
||||
+ *ret_keydev = TAKE_PTR(keydev);
|
||||
|
||||
return 0;
|
||||
}
|
@ -0,0 +1,37 @@
|
||||
From 5cdb2b0b2a0f8f89f97053b0633b8419506d4e28 Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= <zbyszek@in.waw.pl>
|
||||
Date: Thu, 1 Aug 2019 08:15:43 +0200
|
||||
Subject: [PATCH] cryptsetup: don't assert on variable which is optional
|
||||
|
||||
https://github.com/systemd/systemd/commit/50d2eba27b9bfc77ef6b40e5721713846815418b#commitcomment-34519739
|
||||
|
||||
In add_crypttab_devices() split_keyspec is called on the keyfile argument,
|
||||
which may be NULL.
|
||||
|
||||
(cherry picked from commit fef716b28be6e866b8afe995805d5ebe2af6bbfa)
|
||||
|
||||
Related: #1763155
|
||||
---
|
||||
src/cryptsetup/cryptsetup-generator.c | 6 +++++-
|
||||
1 file changed, 5 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/src/cryptsetup/cryptsetup-generator.c b/src/cryptsetup/cryptsetup-generator.c
|
||||
index 7b234e37be..a09983b576 100644
|
||||
--- a/src/cryptsetup/cryptsetup-generator.c
|
||||
+++ b/src/cryptsetup/cryptsetup-generator.c
|
||||
@@ -44,10 +44,14 @@ static int split_keyspec(const char *keyspec, char **ret_keyfile, char **ret_key
|
||||
_cleanup_free_ char *keyfile = NULL, *keydev = NULL;
|
||||
const char *c;
|
||||
|
||||
- assert(keyspec);
|
||||
assert(ret_keyfile);
|
||||
assert(ret_keydev);
|
||||
|
||||
+ if (!keyspec) {
|
||||
+ *ret_keyfile = *ret_keydev = NULL;
|
||||
+ return 0;
|
||||
+ }
|
||||
+
|
||||
c = strrchr(keyspec, ':');
|
||||
if (c) {
|
||||
keyfile = strndup(keyspec, c-keyspec);
|
@ -0,0 +1,100 @@
|
||||
From 9040e15cd3cba546b47aeae0ea133afa1a6ad292 Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= <zbyszek@in.waw.pl>
|
||||
Date: Wed, 13 Nov 2019 10:32:30 +0100
|
||||
Subject: [PATCH] cryptsetup-generator: guess whether the keyfile argument is
|
||||
two items or one
|
||||
|
||||
Fixes #13615.
|
||||
|
||||
See the inline comment for documentation.
|
||||
|
||||
(cherry picked from commit 32c6237a7c2e697d2fc4f3403319db16858fb8e3)
|
||||
|
||||
Related: #1763155
|
||||
---
|
||||
src/cryptsetup/cryptsetup-generator.c | 45 ++++++++++++++++++---------
|
||||
1 file changed, 30 insertions(+), 15 deletions(-)
|
||||
|
||||
diff --git a/src/cryptsetup/cryptsetup-generator.c b/src/cryptsetup/cryptsetup-generator.c
|
||||
index a09983b576..4117930925 100644
|
||||
--- a/src/cryptsetup/cryptsetup-generator.c
|
||||
+++ b/src/cryptsetup/cryptsetup-generator.c
|
||||
@@ -54,17 +54,36 @@ static int split_keyspec(const char *keyspec, char **ret_keyfile, char **ret_key
|
||||
|
||||
c = strrchr(keyspec, ':');
|
||||
if (c) {
|
||||
- keyfile = strndup(keyspec, c-keyspec);
|
||||
- keydev = strdup(c + 1);
|
||||
- if (!keyfile || !keydev)
|
||||
+ /* The keydev part has to be either an absolute path to device node (/dev/something,
|
||||
+ * /dev/foo/something, or even possibly /dev/foo/something:part), or a fstab device
|
||||
+ * specification starting with LABEL= or similar. The keyfile part has the same syntax.
|
||||
+ *
|
||||
+ * Let's try to guess if the second part looks like a keydev specification, or just part of a
|
||||
+ * filename with a colon. fstab_node_to_udev_node() will convert the fstab device syntax to
|
||||
+ * an absolute path. If we didn't get an absolute path, assume that it is just part of the
|
||||
+ * first keyfile argument. */
|
||||
+
|
||||
+ keydev = fstab_node_to_udev_node(c + 1);
|
||||
+ if (!keydev)
|
||||
return log_oom();
|
||||
- } else {
|
||||
+
|
||||
+ if (path_is_absolute(keydev))
|
||||
+ keyfile = strndup(keyspec, c-keyspec);
|
||||
+ else {
|
||||
+ log_debug("Keyspec argument contains a colon, but \"%s\" doesn't look like a device specification.\n"
|
||||
+ "Assuming that \"%s\" is a single device specification.",
|
||||
+ c + 1, keyspec);
|
||||
+ keydev = mfree(keydev);
|
||||
+ c = NULL;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ if (!c)
|
||||
/* No keydev specified */
|
||||
keyfile = strdup(keyspec);
|
||||
- keydev = NULL;
|
||||
- if (!keyfile)
|
||||
- return log_oom();
|
||||
- }
|
||||
+
|
||||
+ if (!keyfile)
|
||||
+ return log_oom();
|
||||
|
||||
*ret_keyfile = TAKE_PTR(keyfile);
|
||||
*ret_keydev = TAKE_PTR(keydev);
|
||||
@@ -73,7 +92,7 @@ static int split_keyspec(const char *keyspec, char **ret_keyfile, char **ret_key
|
||||
}
|
||||
|
||||
static int generate_keydev_mount(const char *name, const char *keydev, const char *keydev_timeout, bool canfail, char **unit, char **mount) {
|
||||
- _cleanup_free_ char *u = NULL, *what = NULL, *where = NULL, *name_escaped = NULL, *device_unit = NULL;
|
||||
+ _cleanup_free_ char *u = NULL, *where = NULL, *name_escaped = NULL, *device_unit = NULL;
|
||||
_cleanup_fclose_ FILE *f = NULL;
|
||||
int r;
|
||||
usec_t timeout_us;
|
||||
@@ -111,22 +130,18 @@ static int generate_keydev_mount(const char *name, const char *keydev, const cha
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
- what = fstab_node_to_udev_node(keydev);
|
||||
- if (!what)
|
||||
- return -ENOMEM;
|
||||
-
|
||||
fprintf(f,
|
||||
"[Unit]\n"
|
||||
"DefaultDependencies=no\n\n"
|
||||
"[Mount]\n"
|
||||
"What=%s\n"
|
||||
"Where=%s\n"
|
||||
- "Options=ro%s\n", what, where, canfail ? ",nofail" : "");
|
||||
+ "Options=ro%s\n", keydev, where, canfail ? ",nofail" : "");
|
||||
|
||||
if (keydev_timeout) {
|
||||
r = parse_sec_fix_0(keydev_timeout, &timeout_us);
|
||||
if (r >= 0) {
|
||||
- r = unit_name_from_path(what, ".device", &device_unit);
|
||||
+ r = unit_name_from_path(keydev, ".device", &device_unit);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to generate unit name: %m");
|
||||
|
@ -0,0 +1,46 @@
|
||||
From 05e184dea3f0182e5787812adfd52b68cff9418d Mon Sep 17 00:00:00 2001
|
||||
From: Jan Janssen <medhefgo@web.de>
|
||||
Date: Mon, 25 Jun 2018 20:33:31 +0200
|
||||
Subject: [PATCH] crypt-util: Translate libcryptsetup log level instead of
|
||||
using log_debug()
|
||||
|
||||
This makes sure that errors reported by libcryptsetup are shown to the
|
||||
user instead of getting swallowed up by log_debug().
|
||||
|
||||
(cherry picked from commit aa2cc005d77890b07e8c579f25e1333ff8ba8dac)
|
||||
|
||||
Resolves: #1776408
|
||||
---
|
||||
src/basic/crypt-util.c | 20 +++++++++++++++++++-
|
||||
1 file changed, 19 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/src/basic/crypt-util.c b/src/basic/crypt-util.c
|
||||
index b181ba3ba0..20bdc5489e 100644
|
||||
--- a/src/basic/crypt-util.c
|
||||
+++ b/src/basic/crypt-util.c
|
||||
@@ -5,6 +5,24 @@
|
||||
#include "log.h"
|
||||
|
||||
void cryptsetup_log_glue(int level, const char *msg, void *usrptr) {
|
||||
- log_debug("%s", msg);
|
||||
+ switch (level) {
|
||||
+ case CRYPT_LOG_NORMAL:
|
||||
+ level = LOG_NOTICE;
|
||||
+ break;
|
||||
+ case CRYPT_LOG_ERROR:
|
||||
+ level = LOG_ERR;
|
||||
+ break;
|
||||
+ case CRYPT_LOG_VERBOSE:
|
||||
+ level = LOG_INFO;
|
||||
+ break;
|
||||
+ case CRYPT_LOG_DEBUG:
|
||||
+ level = LOG_DEBUG;
|
||||
+ break;
|
||||
+ default:
|
||||
+ log_error("Unknown libcryptsetup log level: %d", level);
|
||||
+ level = LOG_ERR;
|
||||
+ }
|
||||
+
|
||||
+ log_full(level, "%s", msg);
|
||||
}
|
||||
#endif
|
@ -0,0 +1,25 @@
|
||||
From ea0c4c31f6dff7d01e585bd8d5f962b373844544 Mon Sep 17 00:00:00 2001
|
||||
From: Lennart Poettering <lennart@poettering.net>
|
||||
Date: Mon, 21 Jan 2019 20:13:11 +0100
|
||||
Subject: [PATCH] cryptsetup: add some commenting about EAGAIN generation
|
||||
|
||||
(cherry picked from commit b7a0fead10959b03a1fa642a5ae7aca3a6a3dee9)
|
||||
|
||||
Related: #1776408
|
||||
---
|
||||
src/cryptsetup/cryptsetup.c | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/src/cryptsetup/cryptsetup.c b/src/cryptsetup/cryptsetup.c
|
||||
index 0881aea915..f2b2557497 100644
|
||||
--- a/src/cryptsetup/cryptsetup.c
|
||||
+++ b/src/cryptsetup/cryptsetup.c
|
||||
@@ -455,7 +455,7 @@ static int attach_tcrypt(
|
||||
r = read_one_line_file(key_file, &passphrase);
|
||||
if (r < 0) {
|
||||
log_error_errno(r, "Failed to read password file '%s': %m", key_file);
|
||||
- return -EAGAIN;
|
||||
+ return -EAGAIN; /* log with the actual error, but return EAGAIN */
|
||||
}
|
||||
|
||||
params.passphrase = passphrase;
|
@ -0,0 +1,25 @@
|
||||
From 3bbacfb22a9266769a41dee6f8f594fbeb6287fc Mon Sep 17 00:00:00 2001
|
||||
From: Lennart Poettering <lennart@poettering.net>
|
||||
Date: Mon, 21 Jan 2019 20:19:57 +0100
|
||||
Subject: [PATCH] cryptsetup: downgrade a log message we ignore
|
||||
|
||||
(cherry picked from commit 44ce4255147ab308c1f13580147c693204c322e8)
|
||||
|
||||
Related: #1776408
|
||||
---
|
||||
src/cryptsetup/cryptsetup.c | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/src/cryptsetup/cryptsetup.c b/src/cryptsetup/cryptsetup.c
|
||||
index f2b2557497..53fe04a73f 100644
|
||||
--- a/src/cryptsetup/cryptsetup.c
|
||||
+++ b/src/cryptsetup/cryptsetup.c
|
||||
@@ -621,7 +621,7 @@ int main(int argc, char *argv[]) {
|
||||
!streq(argv[4], "none")) {
|
||||
|
||||
if (!path_is_absolute(argv[4]))
|
||||
- log_error("Password file path '%s' is not absolute. Ignoring.", argv[4]);
|
||||
+ log_warning("Password file path '%s' is not absolute. Ignoring.", argv[4]);
|
||||
else
|
||||
key_file = argv[4];
|
||||
}
|
@ -0,0 +1,102 @@
|
||||
From 966ecf0011a02c7823083a7868b8589fdf850be8 Mon Sep 17 00:00:00 2001
|
||||
From: Lennart Poettering <lennart@poettering.net>
|
||||
Date: Mon, 21 Jan 2019 20:20:35 +0100
|
||||
Subject: [PATCH] cryptsetup: rework how we log about activation failures
|
||||
|
||||
First of all let's always log where the errors happen, and not in an
|
||||
upper stackframe, in all cases. Previously we'd do this somethis one way
|
||||
and sometimes another, which resulted in sometimes duplicate logging and
|
||||
sometimes none.
|
||||
|
||||
When we cannot activate something due to bad password the kernel gives
|
||||
us EPERM. Let's uniformly return this EAGAIN, so tha the next password
|
||||
is tried. (previously this was done in most cases but not in all)
|
||||
|
||||
When we get EPERM let's also explicitly indicate that this probably
|
||||
means the password is simply wrong.
|
||||
|
||||
Fixes: #11498
|
||||
(cherry picked from commit 6f177c7dc092eb68762b4533d41b14244adb2a73)
|
||||
|
||||
Related: #1776408
|
||||
---
|
||||
src/cryptsetup/cryptsetup.c | 36 ++++++++++++++++++++++--------------
|
||||
1 file changed, 22 insertions(+), 14 deletions(-)
|
||||
|
||||
diff --git a/src/cryptsetup/cryptsetup.c b/src/cryptsetup/cryptsetup.c
|
||||
index 53fe04a73f..33c215eaa1 100644
|
||||
--- a/src/cryptsetup/cryptsetup.c
|
||||
+++ b/src/cryptsetup/cryptsetup.c
|
||||
@@ -469,10 +469,15 @@ static int attach_tcrypt(
|
||||
log_error("Failed to activate using password file '%s'.", key_file);
|
||||
return -EAGAIN;
|
||||
}
|
||||
- return r;
|
||||
+
|
||||
+ return log_error_errno(r, "Failed to load tcrypt superblock on device %s: %m", crypt_get_device_name(cd));
|
||||
}
|
||||
|
||||
- return crypt_activate_by_volume_key(cd, name, NULL, 0, flags);
|
||||
+ r = crypt_activate_by_volume_key(cd, name, NULL, 0, flags);
|
||||
+ if (r < 0)
|
||||
+ return log_error_errno(r, "Failed to activate tcrypt device %s: %m", crypt_get_device_name(cd));
|
||||
+
|
||||
+ return 0;
|
||||
}
|
||||
|
||||
static int attach_luks_or_plain(struct crypt_device *cd,
|
||||
@@ -549,22 +554,30 @@ static int attach_luks_or_plain(struct crypt_device *cd,
|
||||
|
||||
if (key_file) {
|
||||
r = crypt_activate_by_keyfile_offset(cd, name, arg_key_slot, key_file, arg_keyfile_size, arg_keyfile_offset, flags);
|
||||
- if (r < 0) {
|
||||
- log_error_errno(r, "Failed to activate with key file '%s': %m", key_file);
|
||||
- return -EAGAIN;
|
||||
+ if (r == -EPERM) {
|
||||
+ log_error_errno(r, "Failed to activate with key file '%s'. (Key data incorrect?)", key_file);
|
||||
+ return -EAGAIN; /* Log actual error, but return EAGAIN */
|
||||
}
|
||||
+ if (r < 0)
|
||||
+ return log_error_errno(r, "Failed to activate with key file '%s': %m", key_file);
|
||||
} else {
|
||||
char **p;
|
||||
|
||||
+ r = -EINVAL;
|
||||
STRV_FOREACH(p, passwords) {
|
||||
if (pass_volume_key)
|
||||
r = crypt_activate_by_volume_key(cd, name, *p, arg_key_size, flags);
|
||||
else
|
||||
r = crypt_activate_by_passphrase(cd, name, arg_key_slot, *p, strlen(*p), flags);
|
||||
-
|
||||
if (r >= 0)
|
||||
break;
|
||||
}
|
||||
+ if (r == -EPERM) {
|
||||
+ log_error_errno(r, "Failed to activate with specified passphrase. (Passphrase incorrect?)");
|
||||
+ return -EAGAIN; /* log actual error, but return EAGAIN */
|
||||
+ }
|
||||
+ if (r < 0)
|
||||
+ return log_error_errno(r, "Failed to activate with specified passphrase: %m");
|
||||
}
|
||||
|
||||
return r;
|
||||
@@ -726,16 +739,11 @@ int main(int argc, char *argv[]) {
|
||||
flags);
|
||||
if (r >= 0)
|
||||
break;
|
||||
- if (r == -EAGAIN) {
|
||||
- key_file = NULL;
|
||||
- continue;
|
||||
- }
|
||||
- if (r != -EPERM) {
|
||||
- log_error_errno(r, "Failed to activate: %m");
|
||||
+ if (r != -EAGAIN)
|
||||
goto finish;
|
||||
- }
|
||||
|
||||
- log_warning("Invalid passphrase.");
|
||||
+ /* Passphrase not correct? Let's try again! */
|
||||
+ key_file = NULL;
|
||||
}
|
||||
|
||||
if (arg_tries != 0 && tries >= arg_tries) {
|
41
SOURCES/0306-rules-reintroduce-60-alias-kmsg.rules.patch
Normal file
41
SOURCES/0306-rules-reintroduce-60-alias-kmsg.rules.patch
Normal file
@ -0,0 +1,41 @@
|
||||
From b7f9d757dd6f276203b8b04f0c0ba1c61bcf8937 Mon Sep 17 00:00:00 2001
|
||||
From: Jan Synacek <jsynacek@redhat.com>
|
||||
Date: Wed, 18 Dec 2019 09:41:29 +0100
|
||||
Subject: [PATCH] rules: reintroduce 60-alias-kmsg.rules
|
||||
|
||||
Resolves:#1739353
|
||||
rhel-only
|
||||
---
|
||||
rules/60-alias-kmsg.rules | 10 ++++++++++
|
||||
rules/meson.build | 1 +
|
||||
2 files changed, 11 insertions(+)
|
||||
create mode 100644 rules/60-alias-kmsg.rules
|
||||
|
||||
diff --git a/rules/60-alias-kmsg.rules b/rules/60-alias-kmsg.rules
|
||||
new file mode 100644
|
||||
index 0000000000..9c7236a730
|
||||
--- /dev/null
|
||||
+++ b/rules/60-alias-kmsg.rules
|
||||
@@ -0,0 +1,10 @@
|
||||
+SUBSYSTEM!="block", GOTO="log_end"
|
||||
+KERNEL=="loop*|ram*", GOTO="log_end"
|
||||
+ACTION=="remove", GOTO="log_end"
|
||||
+ENV{DM_UDEV_DISABLE_OTHER_RULES_FLAG}=="1", GOTO="log_end"
|
||||
+ENV{DM_UDEV_DISABLE_DISK_RULES_FLAG}=="1", GOTO="log_end"
|
||||
+
|
||||
+IMPORT{cmdline}="udev.alias"
|
||||
+ENV{udev.alias}=="1", RUN+="/bin/sh -c 'echo udev-alias: $name \($links\) > /dev/kmsg'"
|
||||
+
|
||||
+LABEL="log_end"
|
||||
diff --git a/rules/meson.build b/rules/meson.build
|
||||
index 6363f8bf2e..7b5b2472de 100644
|
||||
--- a/rules/meson.build
|
||||
+++ b/rules/meson.build
|
||||
@@ -3,6 +3,7 @@
|
||||
rules = files('''
|
||||
40-redhat.rules
|
||||
40-elevator.rules
|
||||
+ 60-alias-kmsg.rules
|
||||
60-block.rules
|
||||
60-cdrom_id.rules
|
||||
60-drm.rules
|
@ -0,0 +1,49 @@
|
||||
From 1d8e642b0b67f07b0bf469c25126b878380bae6a Mon Sep 17 00:00:00 2001
|
||||
From: Lennart Poettering <lennart@poettering.net>
|
||||
Date: Thu, 17 Jan 2019 18:13:03 +0100
|
||||
Subject: [PATCH] sd-bus: make rqueue/wqueue sizes of type size_t
|
||||
|
||||
Let's do this like we usually do and size arrays with size_t.
|
||||
|
||||
We already do this for the "allocated" counter correctly, and externally
|
||||
we expose the queue sizes as uint64_t anyway, hence there's really no
|
||||
point in usigned "unsigned" internally.
|
||||
|
||||
(cherry picked from commit 143d4e045a798ccc87889b2a8a60d7fbe44be441)
|
||||
Related: CVE-2020-1712
|
||||
---
|
||||
src/libsystemd/sd-bus/bus-internal.h | 4 ++--
|
||||
src/libsystemd/sd-bus/sd-bus.c | 2 +-
|
||||
2 files changed, 3 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/src/libsystemd/sd-bus/bus-internal.h b/src/libsystemd/sd-bus/bus-internal.h
|
||||
index 5d773b14c4..06bd7862cb 100644
|
||||
--- a/src/libsystemd/sd-bus/bus-internal.h
|
||||
+++ b/src/libsystemd/sd-bus/bus-internal.h
|
||||
@@ -221,11 +221,11 @@ struct sd_bus {
|
||||
size_t rbuffer_size;
|
||||
|
||||
sd_bus_message **rqueue;
|
||||
- unsigned rqueue_size;
|
||||
+ size_t rqueue_size;
|
||||
size_t rqueue_allocated;
|
||||
|
||||
sd_bus_message **wqueue;
|
||||
- unsigned wqueue_size;
|
||||
+ size_t wqueue_size;
|
||||
size_t windex;
|
||||
size_t wqueue_allocated;
|
||||
|
||||
diff --git a/src/libsystemd/sd-bus/sd-bus.c b/src/libsystemd/sd-bus/sd-bus.c
|
||||
index 1c9e967ae0..64026f7ee1 100644
|
||||
--- a/src/libsystemd/sd-bus/sd-bus.c
|
||||
+++ b/src/libsystemd/sd-bus/sd-bus.c
|
||||
@@ -2080,7 +2080,7 @@ _public_ int sd_bus_call(
|
||||
_cleanup_(sd_bus_message_unrefp) sd_bus_message *m = sd_bus_message_ref(_m);
|
||||
usec_t timeout;
|
||||
uint64_t cookie;
|
||||
- unsigned i;
|
||||
+ size_t i;
|
||||
int r;
|
||||
|
||||
bus_assert_return(m, -EINVAL, error);
|
@ -0,0 +1,51 @@
|
||||
From 9c23ceef0a08ffdf4aed7a96ec440e1b110568ac Mon Sep 17 00:00:00 2001
|
||||
From: Lennart Poettering <lennart@poettering.net>
|
||||
Date: Thu, 17 Jan 2019 18:14:17 +0100
|
||||
Subject: [PATCH] sd-bus: reorder bus ref and bus message ref handling
|
||||
|
||||
Let's always place handling of these references together, so that all
|
||||
reference counting during allocation is at a single place.
|
||||
|
||||
(cherry picked from commit e593b6a87a335267e5f7238b14683b7f840a01a3)
|
||||
Related: CVE-2020-1712
|
||||
---
|
||||
src/libsystemd/sd-bus/bus-message.c | 5 +++--
|
||||
1 file changed, 3 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/src/libsystemd/sd-bus/bus-message.c b/src/libsystemd/sd-bus/bus-message.c
|
||||
index 19cb2b9a97..e9cdf46c91 100644
|
||||
--- a/src/libsystemd/sd-bus/bus-message.c
|
||||
+++ b/src/libsystemd/sd-bus/bus-message.c
|
||||
@@ -461,7 +461,6 @@ int bus_message_from_header(
|
||||
if (!m)
|
||||
return -ENOMEM;
|
||||
|
||||
- m->n_ref = 1;
|
||||
m->sealed = true;
|
||||
m->header = header;
|
||||
m->header_accessible = header_accessible;
|
||||
@@ -515,7 +514,9 @@ int bus_message_from_header(
|
||||
m->creds.mask |= SD_BUS_CREDS_SELINUX_CONTEXT;
|
||||
}
|
||||
|
||||
+ m->n_ref = 1;
|
||||
m->bus = sd_bus_ref(bus);
|
||||
+
|
||||
*ret = TAKE_PTR(m);
|
||||
|
||||
return 0;
|
||||
@@ -588,13 +589,13 @@ _public_ int sd_bus_message_new(
|
||||
return -ENOMEM;
|
||||
|
||||
t->n_ref = 1;
|
||||
+ t->bus = sd_bus_ref(bus);
|
||||
t->header = (struct bus_header*) ((uint8_t*) t + ALIGN(sizeof(struct sd_bus_message)));
|
||||
t->header->endian = BUS_NATIVE_ENDIAN;
|
||||
t->header->type = type;
|
||||
t->header->version = bus->message_version;
|
||||
t->allow_fds = bus->can_fds || !IN_SET(bus->state, BUS_HELLO, BUS_RUNNING);
|
||||
t->root_container.need_offsets = BUS_MESSAGE_IS_GVARIANT(t);
|
||||
- t->bus = sd_bus_ref(bus);
|
||||
|
||||
if (bus->allow_interactive_authorization)
|
||||
t->header->flags |= BUS_MESSAGE_ALLOW_INTERACTIVE_AUTHORIZATION;
|
@ -0,0 +1,32 @@
|
||||
From 19a9c67b79ebb9a65bc2aec8d8f2799262ef0cb2 Mon Sep 17 00:00:00 2001
|
||||
From: Lennart Poettering <lennart@poettering.net>
|
||||
Date: Thu, 17 Jan 2019 18:15:37 +0100
|
||||
Subject: [PATCH] sd-bus: make sure dispatch_rqueue() initializes return
|
||||
parameter on all types of success
|
||||
|
||||
Let's make sure our own code follows coding style and initializes all
|
||||
return values on all types of success (and leaves it uninitialized in
|
||||
all types of failure).
|
||||
|
||||
(cherry picked from commit c0bc4ec5cc17ac61773d1e9362b0ffa8382c1ff1)
|
||||
Related: CVE-2020-1712
|
||||
---
|
||||
src/libsystemd/sd-bus/sd-bus.c | 4 +++-
|
||||
1 file changed, 3 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/src/libsystemd/sd-bus/sd-bus.c b/src/libsystemd/sd-bus/sd-bus.c
|
||||
index 64026f7ee1..55b008cc9f 100644
|
||||
--- a/src/libsystemd/sd-bus/sd-bus.c
|
||||
+++ b/src/libsystemd/sd-bus/sd-bus.c
|
||||
@@ -1814,8 +1814,10 @@ static int dispatch_rqueue(sd_bus *bus, bool hint_priority, int64_t priority, sd
|
||||
r = bus_read_message(bus, hint_priority, priority);
|
||||
if (r < 0)
|
||||
return r;
|
||||
- if (r == 0)
|
||||
+ if (r == 0) {
|
||||
+ *m = NULL;
|
||||
return ret;
|
||||
+ }
|
||||
|
||||
ret = 1;
|
||||
}
|
31
SOURCES/0310-sd-bus-drop-two-inappropriate-empty-lines.patch
Normal file
31
SOURCES/0310-sd-bus-drop-two-inappropriate-empty-lines.patch
Normal file
@ -0,0 +1,31 @@
|
||||
From 7e9944795e3f0046857379a5f878b365597ed373 Mon Sep 17 00:00:00 2001
|
||||
From: Lennart Poettering <lennart@poettering.net>
|
||||
Date: Thu, 17 Jan 2019 18:18:18 +0100
|
||||
Subject: [PATCH] sd-bus: drop two inappropriate empty lines
|
||||
|
||||
(cherry picked from commit 39feb2ce417e54cf9746e64b5dfd610cef6ac440)
|
||||
Related: CVE-2020-1712
|
||||
---
|
||||
src/libsystemd/sd-bus/sd-bus.c | 2 --
|
||||
1 file changed, 2 deletions(-)
|
||||
|
||||
diff --git a/src/libsystemd/sd-bus/sd-bus.c b/src/libsystemd/sd-bus/sd-bus.c
|
||||
index 55b008cc9f..01060d105c 100644
|
||||
--- a/src/libsystemd/sd-bus/sd-bus.c
|
||||
+++ b/src/libsystemd/sd-bus/sd-bus.c
|
||||
@@ -2634,7 +2634,6 @@ static int process_builtin(sd_bus *bus, sd_bus_message *m) {
|
||||
SD_BUS_ERROR_UNKNOWN_METHOD,
|
||||
"Unknown method '%s' on interface '%s'.", m->member, m->interface);
|
||||
}
|
||||
-
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
@@ -2758,7 +2757,6 @@ static int process_running(sd_bus *bus, bool hint_priority, int64_t priority, sd
|
||||
return r;
|
||||
|
||||
*ret = TAKE_PTR(m);
|
||||
-
|
||||
return 1;
|
||||
}
|
||||
|
@ -0,0 +1,33 @@
|
||||
From 247d4f826ab189c4dfc4706aaa94782342655218 Mon Sep 17 00:00:00 2001
|
||||
From: Lennart Poettering <lennart@poettering.net>
|
||||
Date: Thu, 17 Jan 2019 21:06:30 +0100
|
||||
Subject: [PATCH] sd-bus: initialize mutex after we allocated the wqueue
|
||||
|
||||
That way the mutex doesn't have to be destroyed when we exit early due
|
||||
to OOM.
|
||||
|
||||
(cherry picked from commit 2fe9a10d7695c4c3a748969a0d1662c624e50e5e)
|
||||
Related: CVE-2020-1712
|
||||
---
|
||||
src/libsystemd/sd-bus/sd-bus.c | 4 ++--
|
||||
1 file changed, 2 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/src/libsystemd/sd-bus/sd-bus.c b/src/libsystemd/sd-bus/sd-bus.c
|
||||
index 01060d105c..e49d58137d 100644
|
||||
--- a/src/libsystemd/sd-bus/sd-bus.c
|
||||
+++ b/src/libsystemd/sd-bus/sd-bus.c
|
||||
@@ -248,12 +248,12 @@ _public_ int sd_bus_new(sd_bus **ret) {
|
||||
b->original_pid = getpid_cached();
|
||||
b->n_groups = (size_t) -1;
|
||||
|
||||
- assert_se(pthread_mutex_init(&b->memfd_cache_mutex, NULL) == 0);
|
||||
-
|
||||
/* We guarantee that wqueue always has space for at least one entry */
|
||||
if (!GREEDY_REALLOC(b->wqueue, b->wqueue_allocated, 1))
|
||||
return -ENOMEM;
|
||||
|
||||
+ assert_se(pthread_mutex_init(&b->memfd_cache_mutex, NULL) == 0);
|
||||
+
|
||||
*ret = TAKE_PTR(b);
|
||||
return 0;
|
||||
}
|
@ -0,0 +1,74 @@
|
||||
From 6180d5ee908c9c742f816c6922c229aefd533117 Mon Sep 17 00:00:00 2001
|
||||
From: Lennart Poettering <lennart@poettering.net>
|
||||
Date: Thu, 17 Jan 2019 21:07:42 +0100
|
||||
Subject: [PATCH] sd-bus: always go through sd_bus_unref() to free messages
|
||||
|
||||
Don't try to be smart, don't bypass the ref counting logic if there's no
|
||||
real reason to.
|
||||
|
||||
This matters if we want to tweak the ref counting logic later.
|
||||
|
||||
(cherry picked from commit b41812d1e308de03c879cfca490105216d528c4b)
|
||||
Related: CVE-2020-1712
|
||||
---
|
||||
src/libsystemd/sd-bus/bus-message.c | 12 +++++-------
|
||||
1 file changed, 5 insertions(+), 7 deletions(-)
|
||||
|
||||
diff --git a/src/libsystemd/sd-bus/bus-message.c b/src/libsystemd/sd-bus/bus-message.c
|
||||
index e9cdf46c91..306b6d6816 100644
|
||||
--- a/src/libsystemd/sd-bus/bus-message.c
|
||||
+++ b/src/libsystemd/sd-bus/bus-message.c
|
||||
@@ -138,8 +138,6 @@ static sd_bus_message* message_free(sd_bus_message *m) {
|
||||
return mfree(m);
|
||||
}
|
||||
|
||||
-DEFINE_TRIVIAL_CLEANUP_FUNC(sd_bus_message*, message_free);
|
||||
-
|
||||
static void *message_extend_fields(sd_bus_message *m, size_t align, size_t sz, bool add_offset) {
|
||||
void *op, *np;
|
||||
size_t old_size, new_size, start;
|
||||
@@ -531,7 +529,7 @@ int bus_message_from_malloc(
|
||||
const char *label,
|
||||
sd_bus_message **ret) {
|
||||
|
||||
- _cleanup_(message_freep) sd_bus_message *m = NULL;
|
||||
+ _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
|
||||
size_t sz;
|
||||
int r;
|
||||
|
||||
@@ -651,7 +649,7 @@ _public_ int sd_bus_message_new_method_call(
|
||||
const char *interface,
|
||||
const char *member) {
|
||||
|
||||
- _cleanup_(message_freep) sd_bus_message *t = NULL;
|
||||
+ _cleanup_(sd_bus_message_unrefp) sd_bus_message *t = NULL;
|
||||
int r;
|
||||
|
||||
assert_return(bus, -ENOTCONN);
|
||||
@@ -696,7 +694,7 @@ static int message_new_reply(
|
||||
uint8_t type,
|
||||
sd_bus_message **m) {
|
||||
|
||||
- _cleanup_(message_freep) sd_bus_message *t = NULL;
|
||||
+ _cleanup_(sd_bus_message_unrefp) sd_bus_message *t = NULL;
|
||||
uint64_t cookie;
|
||||
int r;
|
||||
|
||||
@@ -747,7 +745,7 @@ _public_ int sd_bus_message_new_method_error(
|
||||
sd_bus_message **m,
|
||||
const sd_bus_error *e) {
|
||||
|
||||
- _cleanup_(message_freep) sd_bus_message *t = NULL;
|
||||
+ _cleanup_(sd_bus_message_unrefp) sd_bus_message *t = NULL;
|
||||
int r;
|
||||
|
||||
assert_return(sd_bus_error_is_set(e), -EINVAL);
|
||||
@@ -850,7 +848,7 @@ int bus_message_new_synthetic_error(
|
||||
const sd_bus_error *e,
|
||||
sd_bus_message **m) {
|
||||
|
||||
- _cleanup_(message_freep) sd_bus_message *t = NULL;
|
||||
+ _cleanup_(sd_bus_message_unrefp) sd_bus_message *t = NULL;
|
||||
int r;
|
||||
|
||||
assert(bus);
|
@ -0,0 +1,182 @@
|
||||
From bc2d7df4fc21e9e54413169d5aad21616314d65e Mon Sep 17 00:00:00 2001
|
||||
From: Lennart Poettering <lennart@poettering.net>
|
||||
Date: Thu, 17 Jan 2019 18:18:54 +0100
|
||||
Subject: [PATCH] bus-message: introduce two kinds of references to bus
|
||||
messages
|
||||
|
||||
Before this commit bus messages had a single reference count: when it
|
||||
reached zero the message would be freed. This simple approach meant a
|
||||
cyclic dependency was typically seen: a message that was enqueued in a
|
||||
bus connection object would reference the bus connection object but also
|
||||
itself be referenced by the bus connection object. So far out strategy
|
||||
to avoid cases like this was: make sure to process the bus connection
|
||||
regularly so that messages don#t stay queued, and at exit flush/close
|
||||
the connection so that the message queued would be emptied, and thus the
|
||||
cyclic dependencies resolved. Im many cases this isn't done properly
|
||||
however.
|
||||
|
||||
With this change, let's address the issue more systematically: let's
|
||||
break the reference cycle. Specifically, there are now two types of
|
||||
references to a bus message:
|
||||
|
||||
1. A regular one, which keeps both the message and the bus object it is
|
||||
associated with pinned.
|
||||
|
||||
2. A "queue" reference, which is weaker: it pins the message, but not
|
||||
the bus object it is associated with.
|
||||
|
||||
The idea is then that regular user handling uses regular references, but
|
||||
when a message is enqueued on its connection, then this takes a "queue"
|
||||
reference instead. This then means that a queued message doesn't imply
|
||||
the connection itself remains pinned, only regular references to the
|
||||
connection or a message associated with it do. Thus, if we end up in the
|
||||
situation where a user allocates a bus and a message and enqueues the
|
||||
latter in the former and drops all refs to both, then this will detect
|
||||
this case and free both.
|
||||
|
||||
Note that this scheme isn't perfect, it only covers references between
|
||||
messages and the busses they are associated with. If OTOH a bus message
|
||||
is enqueued on a different bus than it is associated with cyclic deps
|
||||
cannot be recognized with this simple algorithm, and thus if you enqueue
|
||||
a message associated with a bus A on a bus B, and another message
|
||||
associated with bus B on a bus A, a cyclic ref will be in effect and not
|
||||
be discovered. However, given that this is an exotic case (though one
|
||||
that happens, consider systemd-bus-stdio-bridge), it should be OK not to
|
||||
cover with this, and people have to explicit flush all queues on exit in
|
||||
that case.
|
||||
|
||||
Note that this commit only establishes the separate reference counters
|
||||
per message. A follow-up commit will start making use of this from the
|
||||
bus connection object.
|
||||
|
||||
(cherry picked from commit 1b3f9dd759ca0ea215e7b89f8ce66d1b724497b9)
|
||||
Related: CVE-2020-1712
|
||||
---
|
||||
src/libsystemd/sd-bus/bus-message.c | 60 ++++++++++++++++++++++++++---
|
||||
src/libsystemd/sd-bus/bus-message.h | 14 ++++++-
|
||||
2 files changed, 68 insertions(+), 6 deletions(-)
|
||||
|
||||
diff --git a/src/libsystemd/sd-bus/bus-message.c b/src/libsystemd/sd-bus/bus-message.c
|
||||
index 306b6d6816..7fe8929f82 100644
|
||||
--- a/src/libsystemd/sd-bus/bus-message.c
|
||||
+++ b/src/libsystemd/sd-bus/bus-message.c
|
||||
@@ -120,7 +120,8 @@ static sd_bus_message* message_free(sd_bus_message *m) {
|
||||
|
||||
message_reset_parts(m);
|
||||
|
||||
- sd_bus_unref(m->bus);
|
||||
+ /* Note that we don't unref m->bus here. That's already done by sd_bus_message_unref() as each user
|
||||
+ * reference to the bus message also is considered a reference to the bus connection itself. */
|
||||
|
||||
if (m->free_fds) {
|
||||
close_many(m->fds, m->n_fds);
|
||||
@@ -893,27 +894,76 @@ int bus_message_new_synthetic_error(
|
||||
}
|
||||
|
||||
_public_ sd_bus_message* sd_bus_message_ref(sd_bus_message *m) {
|
||||
-
|
||||
if (!m)
|
||||
return NULL;
|
||||
|
||||
- assert(m->n_ref > 0);
|
||||
+ /* We are fine if this message so far was either explicitly reffed or not reffed but queued into at
|
||||
+ * least one bus connection object. */
|
||||
+ assert(m->n_ref > 0 || m->n_queued > 0);
|
||||
+
|
||||
m->n_ref++;
|
||||
|
||||
+ /* Each user reference to a bus message shall also be considered a ref on the bus */
|
||||
+ sd_bus_ref(m->bus);
|
||||
return m;
|
||||
}
|
||||
|
||||
_public_ sd_bus_message* sd_bus_message_unref(sd_bus_message *m) {
|
||||
-
|
||||
if (!m)
|
||||
return NULL;
|
||||
|
||||
assert(m->n_ref > 0);
|
||||
+
|
||||
+ sd_bus_unref(m->bus); /* Each regular ref is also a ref on the bus connection. Let's hence drop it
|
||||
+ * here. Note we have to do this before decrementing our own n_ref here, since
|
||||
+ * otherwise, if this message is currently queued sd_bus_unref() might call
|
||||
+ * bus_message_unref_queued() for this which might then destroy the message
|
||||
+ * while we are still processing it. */
|
||||
m->n_ref--;
|
||||
|
||||
- if (m->n_ref > 0)
|
||||
+ if (m->n_ref > 0 || m->n_queued > 0)
|
||||
return NULL;
|
||||
|
||||
+ /* Unset the bus field if neither the user has a reference nor this message is queued. We are careful
|
||||
+ * to reset the field only after the last reference to the bus is dropped, after all we might keep
|
||||
+ * multiple references to the bus, once for each reference kept on outselves. */
|
||||
+ m->bus = NULL;
|
||||
+
|
||||
+ return message_free(m);
|
||||
+}
|
||||
+
|
||||
+sd_bus_message* bus_message_ref_queued(sd_bus_message *m, sd_bus *bus) {
|
||||
+ if (!m)
|
||||
+ return NULL;
|
||||
+
|
||||
+ /* If this is a different bus than the message is associated with, then implicitly turn this into a
|
||||
+ * regular reference. This means that you can create a memory leak by enqueuing a message generated
|
||||
+ * on one bus onto another at the same time as enqueueing a message from the second one on the first,
|
||||
+ * as we'll not detect the cyclic references there. */
|
||||
+ if (bus != m->bus)
|
||||
+ return sd_bus_message_ref(m);
|
||||
+
|
||||
+ assert(m->n_ref > 0 || m->n_queued > 0);
|
||||
+ m->n_queued++;
|
||||
+
|
||||
+ return m;
|
||||
+}
|
||||
+
|
||||
+sd_bus_message* bus_message_unref_queued(sd_bus_message *m, sd_bus *bus) {
|
||||
+ if (!m)
|
||||
+ return NULL;
|
||||
+
|
||||
+ if (bus != m->bus)
|
||||
+ return sd_bus_message_unref(m);
|
||||
+
|
||||
+ assert(m->n_queued > 0);
|
||||
+ m->n_queued--;
|
||||
+
|
||||
+ if (m->n_ref > 0 || m->n_queued > 0)
|
||||
+ return NULL;
|
||||
+
|
||||
+ m->bus = NULL;
|
||||
+
|
||||
return message_free(m);
|
||||
}
|
||||
|
||||
diff --git a/src/libsystemd/sd-bus/bus-message.h b/src/libsystemd/sd-bus/bus-message.h
|
||||
index 97f6060e30..ded88005e2 100644
|
||||
--- a/src/libsystemd/sd-bus/bus-message.h
|
||||
+++ b/src/libsystemd/sd-bus/bus-message.h
|
||||
@@ -51,7 +51,16 @@ struct bus_body_part {
|
||||
};
|
||||
|
||||
struct sd_bus_message {
|
||||
- unsigned n_ref;
|
||||
+ /* Caveat: a message can be referenced in two different ways: the main (user-facing) way will also
|
||||
+ * pin the bus connection object the message is associated with. The secondary way ("queued") is used
|
||||
+ * when a message is in the read or write queues of the bus connection object, which will not pin the
|
||||
+ * bus connection object. This is necessary so that we don't have to have a pair of cyclic references
|
||||
+ * between a message that is queued and its connection: as soon as a message is only referenced by
|
||||
+ * the connection (by means of being queued) and the connection itself has no other references it
|
||||
+ * will be freed. */
|
||||
+
|
||||
+ unsigned n_ref; /* Counter of references that pin the connection */
|
||||
+ unsigned n_queued; /* Counter of references that do not pin the connection */
|
||||
|
||||
sd_bus *bus;
|
||||
|
||||
@@ -216,3 +225,6 @@ int bus_message_append_sender(sd_bus_message *m, const char *sender);
|
||||
|
||||
void bus_message_set_sender_driver(sd_bus *bus, sd_bus_message *m);
|
||||
void bus_message_set_sender_local(sd_bus *bus, sd_bus_message *m);
|
||||
+
|
||||
+sd_bus_message* bus_message_ref_queued(sd_bus_message *m, sd_bus *bus);
|
||||
+sd_bus_message* bus_message_unref_queued(sd_bus_message *m, sd_bus *bus);
|
@ -0,0 +1,74 @@
|
||||
From 8efdae75ddf035c8c04983820f8d8cf767cc17b1 Mon Sep 17 00:00:00 2001
|
||||
From: Jan Synacek <jsynacek@redhat.com>
|
||||
Date: Fri, 31 Jan 2020 11:34:45 +0100
|
||||
Subject: [PATCH] sd-bus: introduce API for re-enqueuing incoming messages
|
||||
|
||||
When authorizing via PolicyKit we want to process incoming method calls
|
||||
twice: once to process and figure out that we need PK authentication,
|
||||
and a second time after we aquired PK authentication to actually execute
|
||||
the operation. With this new call sd_bus_enqueue_for_read() we have a
|
||||
way to put an incoming message back into the read queue for this
|
||||
purpose.
|
||||
|
||||
This might have other uses too, for example debugging.
|
||||
Related: CVE-2020-1712
|
||||
---
|
||||
src/libsystemd/libsystemd.sym | 1 +
|
||||
src/libsystemd/sd-bus/sd-bus.c | 24 ++++++++++++++++++++++++
|
||||
src/systemd/sd-bus.h | 1 +
|
||||
3 files changed, 26 insertions(+)
|
||||
|
||||
diff --git a/src/libsystemd/libsystemd.sym b/src/libsystemd/libsystemd.sym
|
||||
index 1eec17db50..e9972593a6 100644
|
||||
--- a/src/libsystemd/libsystemd.sym
|
||||
+++ b/src/libsystemd/libsystemd.sym
|
||||
@@ -569,4 +569,5 @@ global:
|
||||
sd_event_source_get_inotify_mask;
|
||||
sd_event_source_set_destroy_callback;
|
||||
sd_event_source_get_destroy_callback;
|
||||
+ sd_bus_enqueue_for_read;
|
||||
} LIBSYSTEMD_238;
|
||||
diff --git a/src/libsystemd/sd-bus/sd-bus.c b/src/libsystemd/sd-bus/sd-bus.c
|
||||
index e49d58137d..68ad6cbe89 100644
|
||||
--- a/src/libsystemd/sd-bus/sd-bus.c
|
||||
+++ b/src/libsystemd/sd-bus/sd-bus.c
|
||||
@@ -4120,3 +4120,27 @@ _public_ int sd_bus_get_n_queued_write(sd_bus *bus, uint64_t *ret) {
|
||||
*ret = bus->wqueue_size;
|
||||
return 0;
|
||||
}
|
||||
+
|
||||
+_public_ int sd_bus_enqueue_for_read(sd_bus *bus, sd_bus_message *m) {
|
||||
+ int r;
|
||||
+
|
||||
+ assert_return(bus, -EINVAL);
|
||||
+ assert_return(bus = bus_resolve(bus), -ENOPKG);
|
||||
+ assert_return(m, -EINVAL);
|
||||
+ assert_return(m->sealed, -EINVAL);
|
||||
+ assert_return(!bus_pid_changed(bus), -ECHILD);
|
||||
+
|
||||
+ if (!BUS_IS_OPEN(bus->state))
|
||||
+ return -ENOTCONN;
|
||||
+
|
||||
+ /* Re-enqeue a message for reading. This is primarily useful for PolicyKit-style authentication,
|
||||
+ * where we want accept a message, then determine we need to interactively authenticate the user, and
|
||||
+ * when we have that process the message again. */
|
||||
+
|
||||
+ r = bus_rqueue_make_room(bus);
|
||||
+ if (r < 0)
|
||||
+ return r;
|
||||
+
|
||||
+ bus->rqueue[bus->rqueue_size++] = bus_message_ref_queued(m, bus);
|
||||
+ return 0;
|
||||
+}
|
||||
diff --git a/src/systemd/sd-bus.h b/src/systemd/sd-bus.h
|
||||
index 54c4b1ca83..9ba757b13d 100644
|
||||
--- a/src/systemd/sd-bus.h
|
||||
+++ b/src/systemd/sd-bus.h
|
||||
@@ -193,6 +193,7 @@ int sd_bus_process(sd_bus *bus, sd_bus_message **r);
|
||||
int sd_bus_process_priority(sd_bus *bus, int64_t max_priority, sd_bus_message **r);
|
||||
int sd_bus_wait(sd_bus *bus, uint64_t timeout_usec);
|
||||
int sd_bus_flush(sd_bus *bus);
|
||||
+int sd_bus_enqueue_for_read(sd_bus *bus, sd_bus_message *m);
|
||||
|
||||
sd_bus_slot* sd_bus_get_current_slot(sd_bus *bus);
|
||||
sd_bus_message* sd_bus_get_current_message(sd_bus *bus);
|
@ -0,0 +1,130 @@
|
||||
From 73b87f8c73af714a32e7b56b217cd4e4f46a5ea7 Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= <zbyszek@in.waw.pl>
|
||||
Date: Wed, 8 May 2019 14:39:57 +0200
|
||||
Subject: [PATCH] sd-event: add sd_event_source_disable_unref() helper
|
||||
|
||||
(cherry picked from commit afd15bbb4b6414b9356799c63029e36642dae8e4)
|
||||
Related: CVE-2020-1712
|
||||
---
|
||||
man/rules/meson.build | 4 +++-
|
||||
man/sd_event_source_unref.xml | 30 +++++++++++++++++++-----------
|
||||
src/libsystemd/libsystemd.sym | 1 +
|
||||
src/libsystemd/sd-event/sd-event.c | 6 ++++++
|
||||
src/systemd/sd-event.h | 1 +
|
||||
5 files changed, 30 insertions(+), 12 deletions(-)
|
||||
|
||||
diff --git a/man/rules/meson.build b/man/rules/meson.build
|
||||
index 989d11c9b9..7ae94ea265 100644
|
||||
--- a/man/rules/meson.build
|
||||
+++ b/man/rules/meson.build
|
||||
@@ -340,7 +340,9 @@ manpages = [
|
||||
['sd_event_source_set_userdata', '3', ['sd_event_source_get_userdata'], ''],
|
||||
['sd_event_source_unref',
|
||||
'3',
|
||||
- ['sd_event_source_ref', 'sd_event_source_unrefp'],
|
||||
+ ['sd_event_source_disable_unref',
|
||||
+ 'sd_event_source_ref',
|
||||
+ 'sd_event_source_unrefp'],
|
||||
''],
|
||||
['sd_event_wait',
|
||||
'3',
|
||||
diff --git a/man/sd_event_source_unref.xml b/man/sd_event_source_unref.xml
|
||||
index d1b83c57aa..af8fed33f2 100644
|
||||
--- a/man/sd_event_source_unref.xml
|
||||
+++ b/man/sd_event_source_unref.xml
|
||||
@@ -22,6 +22,7 @@
|
||||
<refname>sd_event_source_unref</refname>
|
||||
<refname>sd_event_source_unrefp</refname>
|
||||
<refname>sd_event_source_ref</refname>
|
||||
+ <refname>sd_event_source_disable_unref</refname>
|
||||
|
||||
<refpurpose>Increase or decrease event source reference counters</refpurpose>
|
||||
</refnamediv>
|
||||
@@ -45,6 +46,10 @@
|
||||
<paramdef>sd_event_source *<parameter>source</parameter></paramdef>
|
||||
</funcprototype>
|
||||
|
||||
+ <funcprototype>
|
||||
+ <funcdef>sd_event_source* <function>sd_event_source_disable_unref</function></funcdef>
|
||||
+ <paramdef>sd_event_source *<parameter>source</parameter></paramdef>
|
||||
+ </funcprototype>
|
||||
</funcsynopsis>
|
||||
</refsynopsisdiv>
|
||||
|
||||
@@ -80,23 +85,26 @@
|
||||
the passed event source object is
|
||||
<constant>NULL</constant>.</para>
|
||||
|
||||
- <para>Note that event source objects stay alive and may be
|
||||
- dispatched as long as they have a reference counter greater than
|
||||
- zero. In order to drop a reference of an event source and make
|
||||
- sure the associated event source handler function is not called
|
||||
- anymore it is recommended to combine a call of
|
||||
+ <para>Note that event source objects stay alive and may be dispatched as long as they have a reference
|
||||
+ counter greater than zero. In order to drop a reference of an event source and make sure the associated
|
||||
+ event source handler function is not called anymore it is recommended to combine a call of
|
||||
<function>sd_event_source_unref()</function> with a prior call to
|
||||
- <function>sd_event_source_set_enabled()</function> with
|
||||
- <constant>SD_EVENT_OFF</constant>.</para>
|
||||
+ <function>sd_event_source_set_enabled()</function> with <constant>SD_EVENT_OFF</constant> or call
|
||||
+ <function>sd_event_source_disable_unref()</function>, see below.</para>
|
||||
+
|
||||
+ <para><function>sd_event_source_disable_unref()</function> combines a call to
|
||||
+ <function>sd_event_source_set_enabled()</function> with <constant>SD_EVENT_OFF</constant> with
|
||||
+ <function>sd_event_source_unref()</function>. This ensures that the source is disabled before the local
|
||||
+ reference to it is lost. The <parameter>source</parameter> parameter is allowed to be
|
||||
+ <constant>NULL</constant>.</para>
|
||||
</refsect1>
|
||||
|
||||
<refsect1>
|
||||
<title>Return Value</title>
|
||||
|
||||
- <para><function>sd_event_source_unref()</function> always returns
|
||||
- <constant>NULL</constant>.
|
||||
- <function>sd_event_source_ref()</function> always returns the
|
||||
- event source object passed in.</para>
|
||||
+ <para><function>sd_event_source_unref()</function> and
|
||||
+ <function>sd_event_source_disable_unref()</function> always return <constant>NULL</constant>.
|
||||
+ <function>sd_event_source_ref()</function> always returns the event source object passed in.</para>
|
||||
</refsect1>
|
||||
|
||||
<xi:include href="libsystemd-pkgconfig.xml" />
|
||||
diff --git a/src/libsystemd/libsystemd.sym b/src/libsystemd/libsystemd.sym
|
||||
index e9972593a6..778e88a16c 100644
|
||||
--- a/src/libsystemd/libsystemd.sym
|
||||
+++ b/src/libsystemd/libsystemd.sym
|
||||
@@ -570,4 +570,5 @@ global:
|
||||
sd_event_source_set_destroy_callback;
|
||||
sd_event_source_get_destroy_callback;
|
||||
sd_bus_enqueue_for_read;
|
||||
+ sd_event_source_disable_unref;
|
||||
} LIBSYSTEMD_238;
|
||||
diff --git a/src/libsystemd/sd-event/sd-event.c b/src/libsystemd/sd-event/sd-event.c
|
||||
index d53b9a7026..0d3bf5cbb6 100644
|
||||
--- a/src/libsystemd/sd-event/sd-event.c
|
||||
+++ b/src/libsystemd/sd-event/sd-event.c
|
||||
@@ -580,6 +580,12 @@ _public_ sd_event* sd_event_unref(sd_event *e) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
+_public_ sd_event_source* sd_event_source_disable_unref(sd_event_source *s) {
|
||||
+ if (s)
|
||||
+ (void) sd_event_source_set_enabled(s, SD_EVENT_OFF);
|
||||
+ return sd_event_source_unref(s);
|
||||
+}
|
||||
+
|
||||
static bool event_pid_changed(sd_event *e) {
|
||||
assert(e);
|
||||
|
||||
diff --git a/src/systemd/sd-event.h b/src/systemd/sd-event.h
|
||||
index 7fcae4ac49..9876be01c6 100644
|
||||
--- a/src/systemd/sd-event.h
|
||||
+++ b/src/systemd/sd-event.h
|
||||
@@ -113,6 +113,7 @@ int sd_event_get_iteration(sd_event *e, uint64_t *ret);
|
||||
|
||||
sd_event_source* sd_event_source_ref(sd_event_source *s);
|
||||
sd_event_source* sd_event_source_unref(sd_event_source *s);
|
||||
+sd_event_source* sd_event_source_disable_unref(sd_event_source *s);
|
||||
|
||||
sd_event *sd_event_source_get_event(sd_event_source *s);
|
||||
void* sd_event_source_get_userdata(sd_event_source *s);
|
@ -0,0 +1,156 @@
|
||||
From 2ec3c78b1d1ba907cd888aac3cdc3a86c03cda90 Mon Sep 17 00:00:00 2001
|
||||
From: Jan Synacek <jsynacek@redhat.com>
|
||||
Date: Fri, 31 Jan 2020 15:17:25 +0100
|
||||
Subject: [PATCH] polkit: when authorizing via PK let's re-resolve
|
||||
callback/userdata instead of caching it
|
||||
|
||||
Previously, when doing an async PK query we'd store the original
|
||||
callback/userdata pair and call it again after the PK request is
|
||||
complete. This is problematic, since PK queries might be slow and in the
|
||||
meantime the userdata might be released and re-acquired. Let's avoid
|
||||
this by always traversing through the message handlers so that we always
|
||||
re-resolve the callback and userdata pair and thus can be sure it's
|
||||
up-to-date and properly valid.
|
||||
|
||||
Resolves: CVE-2020-1712
|
||||
---
|
||||
src/shared/bus-util.c | 74 +++++++++++++++++++++++++++++--------------
|
||||
1 file changed, 50 insertions(+), 24 deletions(-)
|
||||
|
||||
diff --git a/src/shared/bus-util.c b/src/shared/bus-util.c
|
||||
index 2d908eb45c..5ed68429be 100644
|
||||
--- a/src/shared/bus-util.c
|
||||
+++ b/src/shared/bus-util.c
|
||||
@@ -319,10 +319,10 @@ int bus_test_polkit(
|
||||
|
||||
typedef struct AsyncPolkitQuery {
|
||||
sd_bus_message *request, *reply;
|
||||
- sd_bus_message_handler_t callback;
|
||||
- void *userdata;
|
||||
sd_bus_slot *slot;
|
||||
+
|
||||
Hashmap *registry;
|
||||
+ sd_event_source *defer_event_source;
|
||||
} AsyncPolkitQuery;
|
||||
|
||||
static void async_polkit_query_free(AsyncPolkitQuery *q) {
|
||||
@@ -338,9 +338,22 @@ static void async_polkit_query_free(AsyncPolkitQuery *q) {
|
||||
sd_bus_message_unref(q->request);
|
||||
sd_bus_message_unref(q->reply);
|
||||
|
||||
+ sd_event_source_disable_unref(q->defer_event_source);
|
||||
free(q);
|
||||
}
|
||||
|
||||
+static int async_polkit_defer(sd_event_source *s, void *userdata) {
|
||||
+ AsyncPolkitQuery *q = userdata;
|
||||
+
|
||||
+ assert(s);
|
||||
+
|
||||
+ /* This is called as idle event source after we processed the async polkit reply, hopefully after the
|
||||
+ * method call we re-enqueued has been properly processed. */
|
||||
+
|
||||
+ async_polkit_query_free(q);
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
static int async_polkit_callback(sd_bus_message *reply, void *userdata, sd_bus_error *error) {
|
||||
_cleanup_(sd_bus_error_free) sd_bus_error error_buffer = SD_BUS_ERROR_NULL;
|
||||
AsyncPolkitQuery *q = userdata;
|
||||
@@ -349,19 +362,45 @@ static int async_polkit_callback(sd_bus_message *reply, void *userdata, sd_bus_e
|
||||
assert(reply);
|
||||
assert(q);
|
||||
|
||||
+ assert(q->slot);
|
||||
q->slot = sd_bus_slot_unref(q->slot);
|
||||
+
|
||||
+ assert(!q->reply);
|
||||
q->reply = sd_bus_message_ref(reply);
|
||||
|
||||
+ /* Now, let's dispatch the original message a second time be re-enqueing. This will then traverse the
|
||||
+ * whole message processing again, and thus re-validating and re-retrieving the "userdata" field
|
||||
+ * again.
|
||||
+ *
|
||||
+ * We install an idle event loop event to clean-up the PolicyKit request data when we are idle again,
|
||||
+ * i.e. after the second time the message is processed is complete. */
|
||||
+
|
||||
+ assert(!q->defer_event_source);
|
||||
+ r = sd_event_add_defer(sd_bus_get_event(sd_bus_message_get_bus(reply)), &q->defer_event_source, async_polkit_defer, q);
|
||||
+ if (r < 0)
|
||||
+ goto fail;
|
||||
+
|
||||
+ r = sd_event_source_set_priority(q->defer_event_source, SD_EVENT_PRIORITY_IDLE);
|
||||
+ if (r < 0)
|
||||
+ goto fail;
|
||||
+
|
||||
+ r = sd_event_source_set_enabled(q->defer_event_source, SD_EVENT_ONESHOT);
|
||||
+ if (r < 0)
|
||||
+ goto fail;
|
||||
+
|
||||
r = sd_bus_message_rewind(q->request, true);
|
||||
- if (r < 0) {
|
||||
- r = sd_bus_reply_method_errno(q->request, r, NULL);
|
||||
- goto finish;
|
||||
- }
|
||||
+ if (r < 0)
|
||||
+ goto fail;
|
||||
|
||||
- r = q->callback(q->request, q->userdata, &error_buffer);
|
||||
- r = bus_maybe_reply_error(q->request, r, &error_buffer);
|
||||
+ r = sd_bus_enqueue_for_read(sd_bus_message_get_bus(q->request), q->request);
|
||||
+ if (r < 0)
|
||||
+ goto fail;
|
||||
|
||||
-finish:
|
||||
+ return 1;
|
||||
+
|
||||
+fail:
|
||||
+ log_debug_errno(r, "Processing asynchronous PolicyKit reply failed, ignoring: %m");
|
||||
+ (void) sd_bus_reply_method_errno(q->request, r, NULL);
|
||||
async_polkit_query_free(q);
|
||||
|
||||
return r;
|
||||
@@ -382,11 +421,9 @@ int bus_verify_polkit_async(
|
||||
#if ENABLE_POLKIT
|
||||
_cleanup_(sd_bus_message_unrefp) sd_bus_message *pk = NULL;
|
||||
AsyncPolkitQuery *q;
|
||||
- const char *sender, **k, **v;
|
||||
- sd_bus_message_handler_t callback;
|
||||
- void *userdata;
|
||||
int c;
|
||||
#endif
|
||||
+ const char *sender, **k, **v;
|
||||
int r;
|
||||
|
||||
assert(call);
|
||||
@@ -444,20 +481,11 @@ int bus_verify_polkit_async(
|
||||
else if (r > 0)
|
||||
return 1;
|
||||
|
||||
-#if ENABLE_POLKIT
|
||||
- if (sd_bus_get_current_message(call->bus) != call)
|
||||
- return -EINVAL;
|
||||
-
|
||||
- callback = sd_bus_get_current_handler(call->bus);
|
||||
- if (!callback)
|
||||
- return -EINVAL;
|
||||
-
|
||||
- userdata = sd_bus_get_current_userdata(call->bus);
|
||||
-
|
||||
sender = sd_bus_message_get_sender(call);
|
||||
if (!sender)
|
||||
return -EBADMSG;
|
||||
|
||||
+#if ENABLE_POLKIT
|
||||
c = sd_bus_message_get_allow_interactive_authorization(call);
|
||||
if (c < 0)
|
||||
return c;
|
||||
@@ -509,8 +537,6 @@ int bus_verify_polkit_async(
|
||||
return -ENOMEM;
|
||||
|
||||
q->request = sd_bus_message_ref(call);
|
||||
- q->callback = callback;
|
||||
- q->userdata = userdata;
|
||||
|
||||
r = hashmap_put(*registry, call, q);
|
||||
if (r < 0) {
|
@ -0,0 +1,70 @@
|
||||
From b9be2c6b48227642ba85c5a741f121cc99655904 Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Michal=20Sekleta=CC=81r?= <msekleta@redhat.com>
|
||||
Date: Mon, 6 Jan 2020 12:30:58 +0100
|
||||
Subject: [PATCH] sysctl: let's by default increase the numeric PID range from
|
||||
2^16 to 2^22
|
||||
|
||||
This should PID collisions a tiny bit less likely, and thus improve
|
||||
security and robustness.
|
||||
|
||||
2^22 isn't particularly a lot either, but it's the current kernel
|
||||
limitation.
|
||||
|
||||
Bumping this limit was suggested by Linus himself:
|
||||
|
||||
https://lwn.net/ml/linux-kernel/CAHk-=wiZ40LVjnXSi9iHLE_-ZBsWFGCgdmNiYZUXn1-V5YBg2g@mail.gmail.com/
|
||||
|
||||
Let's experiment with this in systemd upstream first. Downstreams and
|
||||
users can after all still comment this easily.
|
||||
|
||||
Besides compat concern the most often heard issue with such high PIDs is
|
||||
usability, since they are potentially hard to type. I am not entirely sure though
|
||||
whether 4194304 (as largest new PID) is that much worse to type or to
|
||||
copy than 65563.
|
||||
|
||||
This should also simplify management of per system tasks limits as by
|
||||
this move the sysctl /proc/sys/kernel/threads-max becomes the primary
|
||||
knob to control how many processes to have in parallel.
|
||||
|
||||
Resolves: #1744214
|
||||
---
|
||||
sysctl.d/50-pid-max.conf | 17 +++++++++++++++++
|
||||
sysctl.d/meson.build | 1 +
|
||||
2 files changed, 18 insertions(+)
|
||||
create mode 100644 sysctl.d/50-pid-max.conf
|
||||
|
||||
diff --git a/sysctl.d/50-pid-max.conf b/sysctl.d/50-pid-max.conf
|
||||
new file mode 100644
|
||||
index 0000000000..3a8393d185
|
||||
--- /dev/null
|
||||
+++ b/sysctl.d/50-pid-max.conf
|
||||
@@ -0,0 +1,17 @@
|
||||
+# This file is part of systemd.
|
||||
+#
|
||||
+# systemd is free software; you can redistribute it and/or modify it
|
||||
+# under the terms of the GNU Lesser General Public License as published by
|
||||
+# the Free Software Foundation; either version 2.1 of the License, or
|
||||
+# (at your option) any later version.
|
||||
+
|
||||
+# See sysctl.d(5) and core(5) for documentation.
|
||||
+
|
||||
+# To override settings in this file, create a local file in /etc
|
||||
+# (e.g. /etc/sysctl.d/90-override.conf), and put any assignments
|
||||
+# there.
|
||||
+
|
||||
+# Bump the numeric PID range to its maximum of 2^22 (from the in-kernel default
|
||||
+# of 2^16), to make PID collisions less likely.
|
||||
+kernel.pid_max = 4194304
|
||||
+
|
||||
diff --git a/sysctl.d/meson.build b/sysctl.d/meson.build
|
||||
index 64f6ce942e..a95957ad7d 100644
|
||||
--- a/sysctl.d/meson.build
|
||||
+++ b/sysctl.d/meson.build
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
install_data(
|
||||
'50-default.conf',
|
||||
+ '50-pid-max.conf',
|
||||
install_dir : sysctldir)
|
||||
|
||||
in_files = []
|
@ -0,0 +1,49 @@
|
||||
From dc4c3a5aa35a5e88adcf210471d9460262c8c0d9 Mon Sep 17 00:00:00 2001
|
||||
From: Yu Watanabe <watanabe.yu+github@gmail.com>
|
||||
Date: Tue, 28 May 2019 12:40:17 +0900
|
||||
Subject: [PATCH] journal: do not trigger assertion when journal_file_close()
|
||||
get NULL
|
||||
|
||||
We generally expect destructors to not complain if a NULL argument is passed.
|
||||
|
||||
Closes #12400.
|
||||
|
||||
(cherry picked from commit c377a6f3ad3d9bed4ce7e873e8e9ec6b1650c57d)
|
||||
Resolves: #1788085
|
||||
---
|
||||
src/journal/journal-file.c | 3 ++-
|
||||
src/journal/journald-server.c | 7 ++-----
|
||||
2 files changed, 4 insertions(+), 6 deletions(-)
|
||||
|
||||
diff --git a/src/journal/journal-file.c b/src/journal/journal-file.c
|
||||
index efc3ee052b..8249b11b23 100644
|
||||
--- a/src/journal/journal-file.c
|
||||
+++ b/src/journal/journal-file.c
|
||||
@@ -335,7 +335,8 @@ bool journal_file_is_offlining(JournalFile *f) {
|
||||
}
|
||||
|
||||
JournalFile* journal_file_close(JournalFile *f) {
|
||||
- assert(f);
|
||||
+ if (!f)
|
||||
+ return NULL;
|
||||
|
||||
#if HAVE_GCRYPT
|
||||
/* Write the final tag */
|
||||
diff --git a/src/journal/journald-server.c b/src/journal/journald-server.c
|
||||
index 6aecb67d6c..6250eab831 100644
|
||||
--- a/src/journal/journald-server.c
|
||||
+++ b/src/journal/journald-server.c
|
||||
@@ -1906,11 +1906,8 @@ void server_done(Server *s) {
|
||||
|
||||
client_context_flush_all(s);
|
||||
|
||||
- if (s->system_journal)
|
||||
- (void) journal_file_close(s->system_journal);
|
||||
-
|
||||
- if (s->runtime_journal)
|
||||
- (void) journal_file_close(s->runtime_journal);
|
||||
+ (void) journal_file_close(s->system_journal);
|
||||
+ (void) journal_file_close(s->runtime_journal);
|
||||
|
||||
ordered_hashmap_free_with_destructor(s->user_journals, journal_file_close);
|
||||
|
@ -0,0 +1,58 @@
|
||||
From ceacf935ac9f59bc08b5901f70f227958a2bcf52 Mon Sep 17 00:00:00 2001
|
||||
From: Yu Watanabe <watanabe.yu+github@gmail.com>
|
||||
Date: Tue, 28 May 2019 18:07:01 +0900
|
||||
Subject: [PATCH] journal: use cleanup attribute at one more place
|
||||
|
||||
(cherry picked from commit 627df1dc42b68a74b0882b06366d1185b1a34332)
|
||||
|
||||
Conflicts:
|
||||
src/journal/journald-server.c
|
||||
|
||||
Related: #1788085
|
||||
---
|
||||
src/journal/journal-file.h | 1 +
|
||||
src/journal/journald-server.c | 9 ++++-----
|
||||
2 files changed, 5 insertions(+), 5 deletions(-)
|
||||
|
||||
diff --git a/src/journal/journal-file.h b/src/journal/journal-file.h
|
||||
index cd8a48a364..6a44fd39d2 100644
|
||||
--- a/src/journal/journal-file.h
|
||||
+++ b/src/journal/journal-file.h
|
||||
@@ -144,6 +144,7 @@ int journal_file_open(
|
||||
int journal_file_set_offline(JournalFile *f, bool wait);
|
||||
bool journal_file_is_offlining(JournalFile *f);
|
||||
JournalFile* journal_file_close(JournalFile *j);
|
||||
+DEFINE_TRIVIAL_CLEANUP_FUNC(JournalFile*, journal_file_close);
|
||||
|
||||
int journal_file_open_reliably(
|
||||
const char *fname,
|
||||
diff --git a/src/journal/journald-server.c b/src/journal/journald-server.c
|
||||
index 6250eab831..7632e2d9d0 100644
|
||||
--- a/src/journal/journald-server.c
|
||||
+++ b/src/journal/journald-server.c
|
||||
@@ -253,8 +253,9 @@ static int open_journal(
|
||||
bool seal,
|
||||
JournalMetrics *metrics,
|
||||
JournalFile **ret) {
|
||||
+
|
||||
+ _cleanup_(journal_file_closep) JournalFile *f = NULL;
|
||||
int r;
|
||||
- JournalFile *f;
|
||||
|
||||
assert(s);
|
||||
assert(fname);
|
||||
@@ -271,12 +272,10 @@ static int open_journal(
|
||||
return r;
|
||||
|
||||
r = journal_file_enable_post_change_timer(f, s->event, POST_CHANGE_TIMER_INTERVAL_USEC);
|
||||
- if (r < 0) {
|
||||
- (void) journal_file_close(f);
|
||||
+ if (r < 0)
|
||||
return r;
|
||||
- }
|
||||
|
||||
- *ret = f;
|
||||
+ *ret = TAKE_PTR(f);
|
||||
return r;
|
||||
}
|
||||
|
@ -0,0 +1,183 @@
|
||||
From 781a055c17400e953bb7929434fe7a2e6517d5e8 Mon Sep 17 00:00:00 2001
|
||||
From: Lennart Poettering <lennart@poettering.net>
|
||||
Date: Thu, 17 Jan 2019 18:31:59 +0100
|
||||
Subject: [PATCH] sd-bus: use "queue" message references for managing r/w
|
||||
message queues in connection objects
|
||||
|
||||
Let's make use of the new concept the previous commit added.
|
||||
|
||||
See: #4846
|
||||
(cherry picked from commit c1757a70eac0382c4837a3833d683919f6a48ed7)
|
||||
Related: CVE-2020-1712
|
||||
---
|
||||
src/libsystemd/sd-bus/bus-socket.c | 6 ++-
|
||||
src/libsystemd/sd-bus/sd-bus.c | 60 ++++++++++++++----------------
|
||||
2 files changed, 32 insertions(+), 34 deletions(-)
|
||||
|
||||
diff --git a/src/libsystemd/sd-bus/bus-socket.c b/src/libsystemd/sd-bus/bus-socket.c
|
||||
index 17cfa8e1fd..4a72795d2b 100644
|
||||
--- a/src/libsystemd/sd-bus/bus-socket.c
|
||||
+++ b/src/libsystemd/sd-bus/bus-socket.c
|
||||
@@ -1116,8 +1116,10 @@ static int bus_socket_make_message(sd_bus *bus, size_t size) {
|
||||
bus->fds = NULL;
|
||||
bus->n_fds = 0;
|
||||
|
||||
- if (t)
|
||||
- bus->rqueue[bus->rqueue_size++] = t;
|
||||
+ if (t) {
|
||||
+ bus->rqueue[bus->rqueue_size++] = bus_message_ref_queued(t, bus);
|
||||
+ sd_bus_message_unref(t);
|
||||
+ }
|
||||
|
||||
return 1;
|
||||
}
|
||||
diff --git a/src/libsystemd/sd-bus/sd-bus.c b/src/libsystemd/sd-bus/sd-bus.c
|
||||
index 68ad6cbe89..a3509f7e89 100644
|
||||
--- a/src/libsystemd/sd-bus/sd-bus.c
|
||||
+++ b/src/libsystemd/sd-bus/sd-bus.c
|
||||
@@ -148,13 +148,13 @@ static void bus_reset_queues(sd_bus *b) {
|
||||
assert(b);
|
||||
|
||||
while (b->rqueue_size > 0)
|
||||
- sd_bus_message_unref(b->rqueue[--b->rqueue_size]);
|
||||
+ bus_message_unref_queued(b->rqueue[--b->rqueue_size], b);
|
||||
|
||||
b->rqueue = mfree(b->rqueue);
|
||||
b->rqueue_allocated = 0;
|
||||
|
||||
while (b->wqueue_size > 0)
|
||||
- sd_bus_message_unref(b->wqueue[--b->wqueue_size]);
|
||||
+ bus_message_unref_queued(b->wqueue[--b->wqueue_size], b);
|
||||
|
||||
b->wqueue = mfree(b->wqueue);
|
||||
b->wqueue_allocated = 0;
|
||||
@@ -493,7 +493,7 @@ static int synthesize_connected_signal(sd_bus *bus) {
|
||||
|
||||
/* Insert at the very front */
|
||||
memmove(bus->rqueue + 1, bus->rqueue, sizeof(sd_bus_message*) * bus->rqueue_size);
|
||||
- bus->rqueue[0] = TAKE_PTR(m);
|
||||
+ bus->rqueue[0] = bus_message_ref_queued(m, bus);
|
||||
bus->rqueue_size++;
|
||||
|
||||
return 0;
|
||||
@@ -1760,7 +1760,7 @@ static int dispatch_wqueue(sd_bus *bus) {
|
||||
* anyway. */
|
||||
|
||||
bus->wqueue_size--;
|
||||
- sd_bus_message_unref(bus->wqueue[0]);
|
||||
+ bus_message_unref_queued(bus->wqueue[0], bus);
|
||||
memmove(bus->wqueue, bus->wqueue + 1, sizeof(sd_bus_message*) * bus->wqueue_size);
|
||||
bus->windex = 0;
|
||||
|
||||
@@ -1789,6 +1789,15 @@ int bus_rqueue_make_room(sd_bus *bus) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
+static void rqueue_drop_one(sd_bus *bus, size_t i) {
|
||||
+ assert(bus);
|
||||
+ assert(i < bus->rqueue_size);
|
||||
+
|
||||
+ bus_message_unref_queued(bus->rqueue[i], bus);
|
||||
+ memmove(bus->rqueue + i, bus->rqueue + i + 1, sizeof(sd_bus_message*) * (bus->rqueue_size - i - 1));
|
||||
+ bus->rqueue_size--;
|
||||
+}
|
||||
+
|
||||
static int dispatch_rqueue(sd_bus *bus, bool hint_priority, int64_t priority, sd_bus_message **m) {
|
||||
int r, ret = 0;
|
||||
|
||||
@@ -1803,10 +1812,8 @@ static int dispatch_rqueue(sd_bus *bus, bool hint_priority, int64_t priority, sd
|
||||
for (;;) {
|
||||
if (bus->rqueue_size > 0) {
|
||||
/* Dispatch a queued message */
|
||||
-
|
||||
- *m = bus->rqueue[0];
|
||||
- bus->rqueue_size--;
|
||||
- memmove(bus->rqueue, bus->rqueue + 1, sizeof(sd_bus_message*) * bus->rqueue_size);
|
||||
+ *m = sd_bus_message_ref(bus->rqueue[0]);
|
||||
+ rqueue_drop_one(bus, 0);
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -1884,7 +1891,7 @@ _public_ int sd_bus_send(sd_bus *bus, sd_bus_message *_m, uint64_t *cookie) {
|
||||
* of the wqueue array is always allocated so
|
||||
* that we always can remember how much was
|
||||
* written. */
|
||||
- bus->wqueue[0] = sd_bus_message_ref(m);
|
||||
+ bus->wqueue[0] = bus_message_ref_queued(m, bus);
|
||||
bus->wqueue_size = 1;
|
||||
bus->windex = idx;
|
||||
}
|
||||
@@ -1898,7 +1905,7 @@ _public_ int sd_bus_send(sd_bus *bus, sd_bus_message *_m, uint64_t *cookie) {
|
||||
if (!GREEDY_REALLOC(bus->wqueue, bus->wqueue_allocated, bus->wqueue_size + 1))
|
||||
return -ENOMEM;
|
||||
|
||||
- bus->wqueue[bus->wqueue_size++] = sd_bus_message_ref(m);
|
||||
+ bus->wqueue[bus->wqueue_size++] = bus_message_ref_queued(m, bus);
|
||||
}
|
||||
|
||||
finish:
|
||||
@@ -2124,37 +2131,30 @@ _public_ int sd_bus_call(
|
||||
usec_t left;
|
||||
|
||||
while (i < bus->rqueue_size) {
|
||||
- sd_bus_message *incoming = NULL;
|
||||
+ _cleanup_(sd_bus_message_unrefp) sd_bus_message *incoming = NULL;
|
||||
|
||||
- incoming = bus->rqueue[i];
|
||||
+ incoming = sd_bus_message_ref(bus->rqueue[i]);
|
||||
|
||||
if (incoming->reply_cookie == cookie) {
|
||||
/* Found a match! */
|
||||
|
||||
- memmove(bus->rqueue + i, bus->rqueue + i + 1, sizeof(sd_bus_message*) * (bus->rqueue_size - i - 1));
|
||||
- bus->rqueue_size--;
|
||||
+ rqueue_drop_one(bus, i);
|
||||
log_debug_bus_message(incoming);
|
||||
|
||||
if (incoming->header->type == SD_BUS_MESSAGE_METHOD_RETURN) {
|
||||
|
||||
if (incoming->n_fds <= 0 || bus->accept_fd) {
|
||||
if (reply)
|
||||
- *reply = incoming;
|
||||
- else
|
||||
- sd_bus_message_unref(incoming);
|
||||
+ *reply = TAKE_PTR(incoming);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
- r = sd_bus_error_setf(error, SD_BUS_ERROR_INCONSISTENT_MESSAGE, "Reply message contained file descriptors which I couldn't accept. Sorry.");
|
||||
- sd_bus_message_unref(incoming);
|
||||
- return r;
|
||||
+ return sd_bus_error_setf(error, SD_BUS_ERROR_INCONSISTENT_MESSAGE, "Reply message contained file descriptors which I couldn't accept. Sorry.");
|
||||
|
||||
- } else if (incoming->header->type == SD_BUS_MESSAGE_METHOD_ERROR) {
|
||||
- r = sd_bus_error_copy(error, &incoming->error);
|
||||
- sd_bus_message_unref(incoming);
|
||||
- return r;
|
||||
- } else {
|
||||
+ } else if (incoming->header->type == SD_BUS_MESSAGE_METHOD_ERROR)
|
||||
+ return sd_bus_error_copy(error, &incoming->error);
|
||||
+ else {
|
||||
r = -EIO;
|
||||
goto fail;
|
||||
}
|
||||
@@ -2164,15 +2164,11 @@ _public_ int sd_bus_call(
|
||||
incoming->sender &&
|
||||
streq(bus->unique_name, incoming->sender)) {
|
||||
|
||||
- memmove(bus->rqueue + i, bus->rqueue + i + 1, sizeof(sd_bus_message*) * (bus->rqueue_size - i - 1));
|
||||
- bus->rqueue_size--;
|
||||
+ rqueue_drop_one(bus, i);
|
||||
|
||||
- /* Our own message? Somebody is trying
|
||||
- * to send its own client a message,
|
||||
- * let's not dead-lock, let's fail
|
||||
- * immediately. */
|
||||
+ /* Our own message? Somebody is trying to send its own client a message,
|
||||
+ * let's not dead-lock, let's fail immediately. */
|
||||
|
||||
- sd_bus_message_unref(incoming);
|
||||
r = -ELOOP;
|
||||
goto fail;
|
||||
}
|
@ -0,0 +1,261 @@
|
||||
From 77a273e02c1c811485d13ddca0f844512aed2cff Mon Sep 17 00:00:00 2001
|
||||
From: Jan Synacek <jsynacek@redhat.com>
|
||||
Date: Wed, 12 Feb 2020 12:58:54 +0100
|
||||
Subject: [PATCH] pid1: make sure to restore correct default values for some
|
||||
rlimits
|
||||
|
||||
Commit fb39af4ce42d7ef9af63009f271f404038703704 forgot to restore the default
|
||||
rlimit values (RLIMIT_NOFILE and RLIMIT_MEMLOCK) while PID1 is reloading.
|
||||
|
||||
This patch extracts the code in charge of initializing the default values for
|
||||
those rlimits in order to create dedicated functions, which take care of their
|
||||
initialization.
|
||||
|
||||
These functions are then called in parse_configuration() so we make sure that
|
||||
the default values for these rlimits get restored every time PID1 is reloading
|
||||
its configuration.
|
||||
|
||||
(cherry picked from commit a9fd4cd1206832a61aaf61fff583bb133e6cb965)
|
||||
Resolves: #1789930
|
||||
---
|
||||
src/core/main.c | 135 +++++++++++++++++++++++++++++++++++++-----------
|
||||
1 file changed, 106 insertions(+), 29 deletions(-)
|
||||
|
||||
diff --git a/src/core/main.c b/src/core/main.c
|
||||
index c83249a8dc..b8c1e567ad 100644
|
||||
--- a/src/core/main.c
|
||||
+++ b/src/core/main.c
|
||||
@@ -136,7 +136,8 @@ static EmergencyAction arg_cad_burst_action;
|
||||
static CPUSet arg_cpu_affinity;
|
||||
static NUMAPolicy arg_numa_policy;
|
||||
|
||||
-static int parse_configuration(void);
|
||||
+static int parse_configuration(const struct rlimit *saved_rlimit_nofile,
|
||||
+ const struct rlimit *saved_rlimit_memlock);
|
||||
|
||||
_noreturn_ static void freeze_or_reboot(void) {
|
||||
|
||||
@@ -1149,25 +1150,6 @@ static int prepare_reexecute(Manager *m, FILE **_f, FDSet **_fds, bool switching
|
||||
static int bump_rlimit_nofile(struct rlimit *saved_rlimit) {
|
||||
int r, nr;
|
||||
|
||||
- assert(saved_rlimit);
|
||||
-
|
||||
- /* Save the original RLIMIT_NOFILE so that we can reset it
|
||||
- * later when transitioning from the initrd to the main
|
||||
- * systemd or suchlike. */
|
||||
- if (getrlimit(RLIMIT_NOFILE, saved_rlimit) < 0)
|
||||
- return log_warning_errno(errno, "Reading RLIMIT_NOFILE failed, ignoring: %m");
|
||||
-
|
||||
- /* Make sure forked processes get the default kernel setting */
|
||||
- if (!arg_default_rlimit[RLIMIT_NOFILE]) {
|
||||
- struct rlimit *rl;
|
||||
-
|
||||
- rl = newdup(struct rlimit, saved_rlimit, 1);
|
||||
- if (!rl)
|
||||
- return log_oom();
|
||||
-
|
||||
- arg_default_rlimit[RLIMIT_NOFILE] = rl;
|
||||
- }
|
||||
-
|
||||
/* Bump up the resource limit for ourselves substantially, all the way to the maximum the kernel allows */
|
||||
nr = read_nr_open();
|
||||
r = setrlimit_closest(RLIMIT_NOFILE, &RLIMIT_MAKE_CONST(nr));
|
||||
@@ -1180,16 +1162,12 @@ static int bump_rlimit_nofile(struct rlimit *saved_rlimit) {
|
||||
static int bump_rlimit_memlock(struct rlimit *saved_rlimit) {
|
||||
int r;
|
||||
|
||||
- assert(saved_rlimit);
|
||||
assert(getuid() == 0);
|
||||
|
||||
/* BPF_MAP_TYPE_LPM_TRIE bpf maps are charged against RLIMIT_MEMLOCK, even though we have CAP_IPC_LOCK which
|
||||
* should normally disable such checks. We need them to implement IPAccessAllow= and IPAccessDeny=, hence let's
|
||||
* bump the value high enough for the root user. */
|
||||
|
||||
- if (getrlimit(RLIMIT_MEMLOCK, saved_rlimit) < 0)
|
||||
- return log_warning_errno(errno, "Reading RLIMIT_MEMLOCK failed, ignoring: %m");
|
||||
-
|
||||
r = setrlimit_closest(RLIMIT_MEMLOCK, &RLIMIT_MAKE_CONST(1024ULL*1024ULL*16ULL));
|
||||
if (r < 0)
|
||||
return log_warning_errno(r, "Setting RLIMIT_MEMLOCK failed, ignoring: %m");
|
||||
@@ -1651,6 +1629,8 @@ static void do_reexecute(
|
||||
|
||||
static int invoke_main_loop(
|
||||
Manager *m,
|
||||
+ const struct rlimit *saved_rlimit_nofile,
|
||||
+ const struct rlimit *saved_rlimit_memlock,
|
||||
bool *ret_reexecute,
|
||||
int *ret_retval, /* Return parameters relevant for shutting down */
|
||||
const char **ret_shutdown_verb, /* … */
|
||||
@@ -1662,6 +1642,8 @@ static int invoke_main_loop(
|
||||
int r;
|
||||
|
||||
assert(m);
|
||||
+ assert(saved_rlimit_nofile);
|
||||
+ assert(saved_rlimit_memlock);
|
||||
assert(ret_reexecute);
|
||||
assert(ret_retval);
|
||||
assert(ret_shutdown_verb);
|
||||
@@ -1691,7 +1673,7 @@ static int invoke_main_loop(
|
||||
saved_log_level = m->log_level_overridden ? log_get_max_level() : -1;
|
||||
saved_log_target = m->log_target_overridden ? log_get_target() : _LOG_TARGET_INVALID;
|
||||
|
||||
- (void) parse_configuration();
|
||||
+ (void) parse_configuration(saved_rlimit_nofile, saved_rlimit_memlock);
|
||||
|
||||
set_manager_defaults(m);
|
||||
|
||||
@@ -1983,6 +1965,80 @@ static int do_queue_default_job(
|
||||
return 0;
|
||||
}
|
||||
|
||||
+static void save_rlimits(struct rlimit *saved_rlimit_nofile,
|
||||
+ struct rlimit *saved_rlimit_memlock) {
|
||||
+
|
||||
+ assert(saved_rlimit_nofile);
|
||||
+ assert(saved_rlimit_memlock);
|
||||
+
|
||||
+ if (getrlimit(RLIMIT_NOFILE, saved_rlimit_nofile) < 0)
|
||||
+ log_warning_errno(errno, "Reading RLIMIT_NOFILE failed, ignoring: %m");
|
||||
+
|
||||
+ if (getrlimit(RLIMIT_MEMLOCK, saved_rlimit_memlock) < 0)
|
||||
+ log_warning_errno(errno, "Reading RLIMIT_MEMLOCK failed, ignoring: %m");
|
||||
+}
|
||||
+
|
||||
+static void fallback_rlimit_nofile(const struct rlimit *saved_rlimit_nofile) {
|
||||
+ struct rlimit *rl;
|
||||
+
|
||||
+ if (arg_default_rlimit[RLIMIT_NOFILE])
|
||||
+ return;
|
||||
+
|
||||
+ /* Make sure forked processes get limits based on the original kernel setting */
|
||||
+
|
||||
+ rl = newdup(struct rlimit, saved_rlimit_nofile, 1);
|
||||
+ if (!rl) {
|
||||
+ log_oom();
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ /* Bump the hard limit for system services to a substantially higher value. The default
|
||||
+ * hard limit current kernels set is pretty low (4K), mostly for historical
|
||||
+ * reasons. According to kernel developers, the fd handling in recent kernels has been
|
||||
+ * optimized substantially enough, so that we can bump the limit now, without paying too
|
||||
+ * high a price in memory or performance. Note however that we only bump the hard limit,
|
||||
+ * not the soft limit. That's because select() works the way it works, and chokes on fds
|
||||
+ * >= 1024. If we'd bump the soft limit globally, it might accidentally happen to
|
||||
+ * unexpecting programs that they get fds higher than what they can process using
|
||||
+ * select(). By only bumping the hard limit but leaving the low limit as it is we avoid
|
||||
+ * this pitfall: programs that are written by folks aware of the select() problem in mind
|
||||
+ * (and thus use poll()/epoll instead of select(), the way everybody should) can
|
||||
+ * explicitly opt into high fds by bumping their soft limit beyond 1024, to the hard limit
|
||||
+ * we pass. */
|
||||
+ if (arg_system) {
|
||||
+ int nr;
|
||||
+
|
||||
+ /* Get the underlying absolute limit the kernel enforces */
|
||||
+ nr = read_nr_open();
|
||||
+
|
||||
+ rl->rlim_max = MIN((rlim_t) nr, MAX(rl->rlim_max, (rlim_t) HIGH_RLIMIT_NOFILE));
|
||||
+ }
|
||||
+
|
||||
+ /* If for some reason we were invoked with a soft limit above 1024 (which should never
|
||||
+ * happen!, but who knows what we get passed in from pam_limit when invoked as --user
|
||||
+ * instance), then lower what we pass on to not confuse our children */
|
||||
+ rl->rlim_cur = MIN(rl->rlim_cur, (rlim_t) FD_SETSIZE);
|
||||
+
|
||||
+ arg_default_rlimit[RLIMIT_NOFILE] = rl;
|
||||
+}
|
||||
+
|
||||
+static void fallback_rlimit_memlock(const struct rlimit *saved_rlimit_memlock) {
|
||||
+ struct rlimit *rl;
|
||||
+
|
||||
+ /* Pass the original value down to invoked processes */
|
||||
+
|
||||
+ if (arg_default_rlimit[RLIMIT_MEMLOCK])
|
||||
+ return;
|
||||
+
|
||||
+ rl = newdup(struct rlimit, saved_rlimit_memlock, 1);
|
||||
+ if (!rl) {
|
||||
+ log_oom();
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ arg_default_rlimit[RLIMIT_MEMLOCK] = rl;
|
||||
+}
|
||||
+
|
||||
static void reset_arguments(void) {
|
||||
/* Frees/resets arg_* variables, with a few exceptions commented below. */
|
||||
|
||||
@@ -2040,9 +2096,13 @@ static void reset_arguments(void) {
|
||||
numa_policy_reset(&arg_numa_policy);
|
||||
}
|
||||
|
||||
-static int parse_configuration(void) {
|
||||
+static int parse_configuration(const struct rlimit *saved_rlimit_nofile,
|
||||
+ const struct rlimit *saved_rlimit_memlock) {
|
||||
int r;
|
||||
|
||||
+ assert(saved_rlimit_nofile);
|
||||
+ assert(saved_rlimit_memlock);
|
||||
+
|
||||
arg_default_tasks_max = system_tasks_max_scale(DEFAULT_TASKS_MAX_PERCENTAGE, 100U);
|
||||
|
||||
/* Assign configuration defaults */
|
||||
@@ -2058,18 +2118,29 @@ static int parse_configuration(void) {
|
||||
log_warning_errno(r, "Failed to parse kernel command line, ignoring: %m");
|
||||
}
|
||||
|
||||
+ /* Initialize some default rlimits for services if they haven't been configured */
|
||||
+ fallback_rlimit_nofile(saved_rlimit_nofile);
|
||||
+ fallback_rlimit_memlock(saved_rlimit_memlock);
|
||||
+
|
||||
/* Note that this also parses bits from the kernel command line, including "debug". */
|
||||
log_parse_environment();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
-static int load_configuration(int argc, char **argv, const char **ret_error_message) {
|
||||
+static int load_configuration(
|
||||
+ int argc,
|
||||
+ char **argv,
|
||||
+ const struct rlimit *saved_rlimit_nofile,
|
||||
+ const struct rlimit *saved_rlimit_memlock,
|
||||
+ const char **ret_error_message) {
|
||||
int r;
|
||||
|
||||
+ assert(saved_rlimit_nofile);
|
||||
+ assert(saved_rlimit_memlock);
|
||||
assert(ret_error_message);
|
||||
|
||||
- (void) parse_configuration();
|
||||
+ (void) parse_configuration(saved_rlimit_nofile, saved_rlimit_memlock);
|
||||
|
||||
r = parse_argv(argc, argv);
|
||||
if (r < 0) {
|
||||
@@ -2403,11 +2474,15 @@ int main(int argc, char *argv[]) {
|
||||
}
|
||||
}
|
||||
|
||||
+ /* Save the original RLIMIT_NOFILE/RLIMIT_MEMLOCK so that we can reset it later when
|
||||
+ * transitioning from the initrd to the main systemd or suchlike. */
|
||||
+ save_rlimits(&saved_rlimit_nofile, &saved_rlimit_memlock);
|
||||
+
|
||||
/* Reset all signal handlers. */
|
||||
(void) reset_all_signal_handlers();
|
||||
(void) ignore_signals(SIGNALS_IGNORE, -1);
|
||||
|
||||
- r = load_configuration(argc, argv, &error_message);
|
||||
+ r = load_configuration(argc, argv, &saved_rlimit_nofile, &saved_rlimit_memlock, &error_message);
|
||||
if (r < 0)
|
||||
goto finish;
|
||||
|
||||
@@ -2522,6 +2597,8 @@ int main(int argc, char *argv[]) {
|
||||
}
|
||||
|
||||
(void) invoke_main_loop(m,
|
||||
+ &saved_rlimit_nofile,
|
||||
+ &saved_rlimit_memlock,
|
||||
&reexecute,
|
||||
&retval,
|
||||
&shutdown_verb,
|
@ -0,0 +1,37 @@
|
||||
From 0528a880ddf797a42b2de274e5c7bd2d9896c991 Mon Sep 17 00:00:00 2001
|
||||
From: Lennart Poettering <lennart@poettering.net>
|
||||
Date: Thu, 11 Oct 2018 18:31:11 +0200
|
||||
Subject: [PATCH] main: introduce a define HIGH_RLIMIT_MEMLOCK similar to
|
||||
HIGH_RLIMIT_NOFILE
|
||||
|
||||
(cherry picked from commit c8884aceefc85245b9bdfb626e2daf27521259bd)
|
||||
Related: #1789930
|
||||
---
|
||||
src/basic/def.h | 3 +++
|
||||
src/core/main.c | 2 +-
|
||||
2 files changed, 4 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/src/basic/def.h b/src/basic/def.h
|
||||
index 4d515c11b6..65ad659999 100644
|
||||
--- a/src/basic/def.h
|
||||
+++ b/src/basic/def.h
|
||||
@@ -75,3 +75,6 @@
|
||||
_CONF_PATHS_SPLIT_USR(n))
|
||||
|
||||
#define LONG_LINE_MAX (1U*1024U*1024U)
|
||||
+
|
||||
+#define HIGH_RLIMIT_NOFILE (256*1024)
|
||||
+#define HIGH_RLIMIT_MEMLOCK (1024ULL*1024ULL*64ULL)
|
||||
diff --git a/src/core/main.c b/src/core/main.c
|
||||
index b8c1e567ad..d6550ea161 100644
|
||||
--- a/src/core/main.c
|
||||
+++ b/src/core/main.c
|
||||
@@ -1168,7 +1168,7 @@ static int bump_rlimit_memlock(struct rlimit *saved_rlimit) {
|
||||
* should normally disable such checks. We need them to implement IPAccessAllow= and IPAccessDeny=, hence let's
|
||||
* bump the value high enough for the root user. */
|
||||
|
||||
- r = setrlimit_closest(RLIMIT_MEMLOCK, &RLIMIT_MAKE_CONST(1024ULL*1024ULL*16ULL));
|
||||
+ r = setrlimit_closest(RLIMIT_MEMLOCK, &RLIMIT_MAKE_CONST(HIGH_RLIMIT_MEMLOCK));
|
||||
if (r < 0)
|
||||
return log_warning_errno(r, "Setting RLIMIT_MEMLOCK failed, ignoring: %m");
|
||||
|
@ -0,0 +1,178 @@
|
||||
From 5a62c0daff82e8343d24f98e1761d27bf8015782 Mon Sep 17 00:00:00 2001
|
||||
From: Lennart Poettering <lennart@poettering.net>
|
||||
Date: Wed, 20 Mar 2019 19:00:28 +0100
|
||||
Subject: [PATCH] seccomp: introduce seccomp_restrict_suid_sgid() for blocking
|
||||
chmod() for suid/sgid files
|
||||
|
||||
(cherry picked from commit 3c27973b13724ede05a06a5d346a569794cda433)
|
||||
Related: #1687512
|
||||
---
|
||||
src/shared/seccomp-util.c | 132 ++++++++++++++++++++++++++++++++++++++
|
||||
src/shared/seccomp-util.h | 1 +
|
||||
2 files changed, 133 insertions(+)
|
||||
|
||||
diff --git a/src/shared/seccomp-util.c b/src/shared/seccomp-util.c
|
||||
index 92910acf0e..fd46b9f88d 100644
|
||||
--- a/src/shared/seccomp-util.c
|
||||
+++ b/src/shared/seccomp-util.c
|
||||
@@ -1,12 +1,14 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1+ */
|
||||
|
||||
#include <errno.h>
|
||||
+#include <fcntl.h>
|
||||
#include <linux/seccomp.h>
|
||||
#include <seccomp.h>
|
||||
#include <stddef.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/prctl.h>
|
||||
#include <sys/shm.h>
|
||||
+#include <sys/stat.h>
|
||||
|
||||
#include "af-list.h"
|
||||
#include "alloc-util.h"
|
||||
@@ -1747,3 +1749,133 @@ int seccomp_lock_personality(unsigned long personality) {
|
||||
|
||||
return 0;
|
||||
}
|
||||
+
|
||||
+int seccomp_restrict_suid_sgid(void) {
|
||||
+ uint32_t arch;
|
||||
+ int r;
|
||||
+
|
||||
+ SECCOMP_FOREACH_LOCAL_ARCH(arch) {
|
||||
+ _cleanup_(seccomp_releasep) scmp_filter_ctx seccomp = NULL;
|
||||
+
|
||||
+ r = seccomp_init_for_arch(&seccomp, arch, SCMP_ACT_ALLOW);
|
||||
+ if (r < 0)
|
||||
+ return r;
|
||||
+
|
||||
+ /* Checks the mode_t parameter of the following system calls:
|
||||
+ *
|
||||
+ * → chmod() + fchmod() + fchmodat()
|
||||
+ * → open() + creat() + openat()
|
||||
+ * → mkdir() + mkdirat()
|
||||
+ * → mknod() + mknodat()
|
||||
+ */
|
||||
+
|
||||
+ for (unsigned bit = 0; bit < 2; bit ++) {
|
||||
+ /* Block S_ISUID in the first iteration, S_ISGID in the second */
|
||||
+ mode_t m = bit == 0 ? S_ISUID : S_ISGID;
|
||||
+
|
||||
+ r = seccomp_rule_add_exact(
|
||||
+ seccomp,
|
||||
+ SCMP_ACT_ERRNO(EPERM),
|
||||
+ SCMP_SYS(chmod),
|
||||
+ 1,
|
||||
+ SCMP_A1(SCMP_CMP_MASKED_EQ, m, m));
|
||||
+ if (r < 0)
|
||||
+ break;
|
||||
+
|
||||
+ r = seccomp_rule_add_exact(
|
||||
+ seccomp,
|
||||
+ SCMP_ACT_ERRNO(EPERM),
|
||||
+ SCMP_SYS(fchmod),
|
||||
+ 1,
|
||||
+ SCMP_A1(SCMP_CMP_MASKED_EQ, m, m));
|
||||
+ if (r < 0)
|
||||
+ break;
|
||||
+
|
||||
+ r = seccomp_rule_add_exact(
|
||||
+ seccomp,
|
||||
+ SCMP_ACT_ERRNO(EPERM),
|
||||
+ SCMP_SYS(fchmodat),
|
||||
+ 1,
|
||||
+ SCMP_A2(SCMP_CMP_MASKED_EQ, m, m));
|
||||
+ if (r < 0)
|
||||
+ break;
|
||||
+
|
||||
+ r = seccomp_rule_add_exact(
|
||||
+ seccomp,
|
||||
+ SCMP_ACT_ERRNO(EPERM),
|
||||
+ SCMP_SYS(mkdir),
|
||||
+ 1,
|
||||
+ SCMP_A1(SCMP_CMP_MASKED_EQ, m, m));
|
||||
+ if (r < 0)
|
||||
+ break;
|
||||
+
|
||||
+ r = seccomp_rule_add_exact(
|
||||
+ seccomp,
|
||||
+ SCMP_ACT_ERRNO(EPERM),
|
||||
+ SCMP_SYS(mkdirat),
|
||||
+ 1,
|
||||
+ SCMP_A2(SCMP_CMP_MASKED_EQ, m, m));
|
||||
+ if (r < 0)
|
||||
+ break;
|
||||
+
|
||||
+ r = seccomp_rule_add_exact(
|
||||
+ seccomp,
|
||||
+ SCMP_ACT_ERRNO(EPERM),
|
||||
+ SCMP_SYS(mknod),
|
||||
+ 1,
|
||||
+ SCMP_A1(SCMP_CMP_MASKED_EQ, m, m));
|
||||
+ if (r < 0)
|
||||
+ break;
|
||||
+
|
||||
+ r = seccomp_rule_add_exact(
|
||||
+ seccomp,
|
||||
+ SCMP_ACT_ERRNO(EPERM),
|
||||
+ SCMP_SYS(mknodat),
|
||||
+ 1,
|
||||
+ SCMP_A2(SCMP_CMP_MASKED_EQ, m, m));
|
||||
+ if (r < 0)
|
||||
+ break;
|
||||
+
|
||||
+ r = seccomp_rule_add_exact(
|
||||
+ seccomp,
|
||||
+ SCMP_ACT_ERRNO(EPERM),
|
||||
+ SCMP_SYS(open),
|
||||
+ 2,
|
||||
+ SCMP_A1(SCMP_CMP_MASKED_EQ, O_CREAT, O_CREAT),
|
||||
+ SCMP_A2(SCMP_CMP_MASKED_EQ, m, m));
|
||||
+ if (r < 0)
|
||||
+ break;
|
||||
+
|
||||
+ r = seccomp_rule_add_exact(
|
||||
+ seccomp,
|
||||
+ SCMP_ACT_ERRNO(EPERM),
|
||||
+ SCMP_SYS(openat),
|
||||
+ 2,
|
||||
+ SCMP_A2(SCMP_CMP_MASKED_EQ, O_CREAT, O_CREAT),
|
||||
+ SCMP_A3(SCMP_CMP_MASKED_EQ, m, m));
|
||||
+ if (r < 0)
|
||||
+ break;
|
||||
+
|
||||
+ r = seccomp_rule_add_exact(
|
||||
+ seccomp,
|
||||
+ SCMP_ACT_ERRNO(EPERM),
|
||||
+ SCMP_SYS(creat),
|
||||
+ 1,
|
||||
+ SCMP_A1(SCMP_CMP_MASKED_EQ, m, m));
|
||||
+ if (r < 0)
|
||||
+ break;
|
||||
+ }
|
||||
+ if (r < 0) {
|
||||
+ log_debug_errno(r, "Failed to add suid/sgid rule for architecture %s, skipping: %m", seccomp_arch_to_string(arch));
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
+ r = seccomp_load(seccomp);
|
||||
+ if (IN_SET(r, -EPERM, -EACCES))
|
||||
+ return r;
|
||||
+ if (r < 0)
|
||||
+ log_debug_errno(r, "Failed to apply suid/sgid restrictions for architecture %s, skipping: %m", seccomp_arch_to_string(arch));
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
diff --git a/src/shared/seccomp-util.h b/src/shared/seccomp-util.h
|
||||
index d8a36c4e21..602f092255 100644
|
||||
--- a/src/shared/seccomp-util.h
|
||||
+++ b/src/shared/seccomp-util.h
|
||||
@@ -85,6 +85,7 @@ int seccomp_restrict_address_families(Set *address_families, bool whitelist);
|
||||
int seccomp_restrict_realtime(void);
|
||||
int seccomp_memory_deny_write_execute(void);
|
||||
int seccomp_lock_personality(unsigned long personality);
|
||||
+int seccomp_restrict_suid_sgid(void);
|
||||
|
||||
extern const uint32_t seccomp_local_archs[];
|
||||
|
265
SOURCES/0324-test-add-test-case-for-restrict_suid_sgid.patch
Normal file
265
SOURCES/0324-test-add-test-case-for-restrict_suid_sgid.patch
Normal file
@ -0,0 +1,265 @@
|
||||
From b39697a80ad388e2063c54e56333882f4307c1a1 Mon Sep 17 00:00:00 2001
|
||||
From: Jan Synacek <jsynacek@redhat.com>
|
||||
Date: Tue, 12 Nov 2019 13:27:49 +0100
|
||||
Subject: [PATCH] test: add test case for restrict_suid_sgid()
|
||||
|
||||
(cherry picked from commit 167fc10cb352b04d442c9010dab4f8dc24219749)
|
||||
Related: #1687512
|
||||
---
|
||||
src/test/test-seccomp.c | 226 ++++++++++++++++++++++++++++++++++++++++
|
||||
1 file changed, 226 insertions(+)
|
||||
|
||||
diff --git a/src/test/test-seccomp.c b/src/test/test-seccomp.c
|
||||
index d177515ac7..4021a06e0e 100644
|
||||
--- a/src/test/test-seccomp.c
|
||||
+++ b/src/test/test-seccomp.c
|
||||
@@ -17,9 +17,11 @@
|
||||
#include "nsflags.h"
|
||||
#include "process-util.h"
|
||||
#include "raw-clone.h"
|
||||
+#include "rm-rf.h"
|
||||
#include "seccomp-util.h"
|
||||
#include "set.h"
|
||||
#include "string-util.h"
|
||||
+#include "umask-util.h"
|
||||
#include "util.h"
|
||||
#include "virt.h"
|
||||
|
||||
@@ -666,6 +668,229 @@ static void test_filter_sets_ordered(void) {
|
||||
}
|
||||
}
|
||||
|
||||
+static int mkostemp_safe(char *pattern) {
|
||||
+ _unused_ _cleanup_umask_ mode_t u = umask(0077);
|
||||
+ int fd;
|
||||
+
|
||||
+ assert(pattern);
|
||||
+
|
||||
+ fd = mkostemp(pattern, O_CLOEXEC);
|
||||
+ if (fd < 0)
|
||||
+ return -errno;
|
||||
+
|
||||
+ return fd;
|
||||
+}
|
||||
+
|
||||
+static int real_open(const char *path, int flags, mode_t mode) {
|
||||
+ /* glibc internally calls openat() when open() is requested. Let's hence define our own wrapper for
|
||||
+ * testing purposes that calls the real syscall, on architectures where SYS_open is defined. On
|
||||
+ * other architectures, let's just fall back to the glibc call. */
|
||||
+
|
||||
+#ifdef SYS_open
|
||||
+ return (int) syscall(SYS_open, path, flags, mode);
|
||||
+#else
|
||||
+ return open(path, flags, mode);
|
||||
+#endif
|
||||
+}
|
||||
+
|
||||
+static void test_restrict_suid_sgid(void) {
|
||||
+ pid_t pid;
|
||||
+
|
||||
+ log_info("/* %s */", __func__);
|
||||
+
|
||||
+ if (!is_seccomp_available()) {
|
||||
+ log_notice("Seccomp not available, skipping %s", __func__);
|
||||
+ return;
|
||||
+ }
|
||||
+ if (geteuid() != 0) {
|
||||
+ log_notice("Not root, skipping %s", __func__);
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ pid = fork();
|
||||
+ assert_se(pid >= 0);
|
||||
+
|
||||
+ if (pid == 0) {
|
||||
+ char path[] = "/tmp/suidsgidXXXXXX", dir[] = "/tmp/suidsgiddirXXXXXX";
|
||||
+ int fd = -1, k = -1;
|
||||
+ const char *z;
|
||||
+
|
||||
+ fd = mkostemp_safe(path);
|
||||
+ assert_se(fd >= 0);
|
||||
+
|
||||
+ assert_se(mkdtemp(dir));
|
||||
+ z = strjoina(dir, "/test");
|
||||
+
|
||||
+ assert_se(chmod(path, 0755 | S_ISUID) >= 0);
|
||||
+ assert_se(chmod(path, 0755 | S_ISGID) >= 0);
|
||||
+ assert_se(chmod(path, 0755 | S_ISGID | S_ISUID) >= 0);
|
||||
+ assert_se(chmod(path, 0755) >= 0);
|
||||
+
|
||||
+ assert_se(fchmod(fd, 0755 | S_ISUID) >= 0);
|
||||
+ assert_se(fchmod(fd, 0755 | S_ISGID) >= 0);
|
||||
+ assert_se(fchmod(fd, 0755 | S_ISGID | S_ISUID) >= 0);
|
||||
+ assert_se(fchmod(fd, 0755) >= 0);
|
||||
+
|
||||
+ assert_se(fchmodat(AT_FDCWD, path, 0755 | S_ISUID, 0) >= 0);
|
||||
+ assert_se(fchmodat(AT_FDCWD, path, 0755 | S_ISGID, 0) >= 0);
|
||||
+ assert_se(fchmodat(AT_FDCWD, path, 0755 | S_ISGID | S_ISUID, 0) >= 0);
|
||||
+ assert_se(fchmodat(AT_FDCWD, path, 0755, 0) >= 0);
|
||||
+
|
||||
+ k = real_open(z, O_CREAT|O_RDWR|O_CLOEXEC|O_EXCL, 0644 | S_ISUID);
|
||||
+ k = safe_close(k);
|
||||
+ assert_se(unlink(z) >= 0);
|
||||
+
|
||||
+ k = real_open(z, O_CREAT|O_RDWR|O_CLOEXEC|O_EXCL, 0644 | S_ISGID);
|
||||
+ k = safe_close(k);
|
||||
+ assert_se(unlink(z) >= 0);
|
||||
+
|
||||
+ k = real_open(z, O_CREAT|O_RDWR|O_CLOEXEC|O_EXCL, 0644 | S_ISUID | S_ISGID);
|
||||
+ k = safe_close(k);
|
||||
+ assert_se(unlink(z) >= 0);
|
||||
+
|
||||
+ k = real_open(z, O_CREAT|O_RDWR|O_CLOEXEC|O_EXCL, 0644);
|
||||
+ k = safe_close(k);
|
||||
+ assert_se(unlink(z) >= 0);
|
||||
+
|
||||
+ k = creat(z, 0644 | S_ISUID);
|
||||
+ k = safe_close(k);
|
||||
+ assert_se(unlink(z) >= 0);
|
||||
+
|
||||
+ k = creat(z, 0644 | S_ISGID);
|
||||
+ k = safe_close(k);
|
||||
+ assert_se(unlink(z) >= 0);
|
||||
+
|
||||
+ k = creat(z, 0644 | S_ISUID | S_ISGID);
|
||||
+ k = safe_close(k);
|
||||
+ assert_se(unlink(z) >= 0);
|
||||
+
|
||||
+ k = creat(z, 0644);
|
||||
+ k = safe_close(k);
|
||||
+ assert_se(unlink(z) >= 0);
|
||||
+
|
||||
+ k = openat(AT_FDCWD, z, O_CREAT|O_RDWR|O_CLOEXEC|O_EXCL, 0644 | S_ISUID);
|
||||
+ k = safe_close(k);
|
||||
+ assert_se(unlink(z) >= 0);
|
||||
+
|
||||
+ k = openat(AT_FDCWD, z, O_CREAT|O_RDWR|O_CLOEXEC|O_EXCL, 0644 | S_ISGID);
|
||||
+ k = safe_close(k);
|
||||
+ assert_se(unlink(z) >= 0);
|
||||
+
|
||||
+ k = openat(AT_FDCWD, z, O_CREAT|O_RDWR|O_CLOEXEC|O_EXCL, 0644 | S_ISUID | S_ISGID);
|
||||
+ k = safe_close(k);
|
||||
+ assert_se(unlink(z) >= 0);
|
||||
+
|
||||
+ k = openat(AT_FDCWD, z, O_CREAT|O_RDWR|O_CLOEXEC|O_EXCL, 0644);
|
||||
+ k = safe_close(k);
|
||||
+ assert_se(unlink(z) >= 0);
|
||||
+
|
||||
+ assert_se(mkdir(z, 0755 | S_ISUID) >= 0);
|
||||
+ assert_se(rmdir(z) >= 0);
|
||||
+ assert_se(mkdir(z, 0755 | S_ISGID) >= 0);
|
||||
+ assert_se(rmdir(z) >= 0);
|
||||
+ assert_se(mkdir(z, 0755 | S_ISUID | S_ISGID) >= 0);
|
||||
+ assert_se(rmdir(z) >= 0);
|
||||
+ assert_se(mkdir(z, 0755) >= 0);
|
||||
+ assert_se(rmdir(z) >= 0);
|
||||
+
|
||||
+ assert_se(mkdirat(AT_FDCWD, z, 0755 | S_ISUID) >= 0);
|
||||
+ assert_se(rmdir(z) >= 0);
|
||||
+ assert_se(mkdirat(AT_FDCWD, z, 0755 | S_ISGID) >= 0);
|
||||
+ assert_se(rmdir(z) >= 0);
|
||||
+ assert_se(mkdirat(AT_FDCWD, z, 0755 | S_ISUID | S_ISGID) >= 0);
|
||||
+ assert_se(rmdir(z) >= 0);
|
||||
+ assert_se(mkdirat(AT_FDCWD, z, 0755) >= 0);
|
||||
+ assert_se(rmdir(z) >= 0);
|
||||
+
|
||||
+ assert_se(mknod(z, S_IFREG | 0755 | S_ISUID, 0) >= 0);
|
||||
+ assert_se(unlink(z) >= 0);
|
||||
+ assert_se(mknod(z, S_IFREG | 0755 | S_ISGID, 0) >= 0);
|
||||
+ assert_se(unlink(z) >= 0);
|
||||
+ assert_se(mknod(z, S_IFREG | 0755 | S_ISUID | S_ISGID, 0) >= 0);
|
||||
+ assert_se(unlink(z) >= 0);
|
||||
+ assert_se(mknod(z, S_IFREG | 0755, 0) >= 0);
|
||||
+ assert_se(unlink(z) >= 0);
|
||||
+
|
||||
+ assert_se(mknodat(AT_FDCWD, z, S_IFREG | 0755 | S_ISUID, 0) >= 0);
|
||||
+ assert_se(unlink(z) >= 0);
|
||||
+ assert_se(mknodat(AT_FDCWD, z, S_IFREG | 0755 | S_ISGID, 0) >= 0);
|
||||
+ assert_se(unlink(z) >= 0);
|
||||
+ assert_se(mknodat(AT_FDCWD, z, S_IFREG | 0755 | S_ISUID | S_ISGID, 0) >= 0);
|
||||
+ assert_se(unlink(z) >= 0);
|
||||
+ assert_se(mknodat(AT_FDCWD, z, S_IFREG | 0755, 0) >= 0);
|
||||
+ assert_se(unlink(z) >= 0);
|
||||
+
|
||||
+ assert_se(seccomp_restrict_suid_sgid() >= 0);
|
||||
+
|
||||
+ assert_se(chmod(path, 0775 | S_ISUID) < 0 && errno == EPERM);
|
||||
+ assert_se(chmod(path, 0775 | S_ISGID) < 0 && errno == EPERM);
|
||||
+ assert_se(chmod(path, 0775 | S_ISGID | S_ISUID) < 0 && errno == EPERM);
|
||||
+ assert_se(chmod(path, 0775) >= 0);
|
||||
+
|
||||
+ assert_se(fchmod(fd, 0775 | S_ISUID) < 0 && errno == EPERM);
|
||||
+ assert_se(fchmod(fd, 0775 | S_ISGID) < 0 && errno == EPERM);
|
||||
+ assert_se(fchmod(fd, 0775 | S_ISGID | S_ISUID) < 0 && errno == EPERM);
|
||||
+ assert_se(fchmod(fd, 0775) >= 0);
|
||||
+
|
||||
+ assert_se(fchmodat(AT_FDCWD, path, 0755 | S_ISUID, 0) < 0 && errno == EPERM);
|
||||
+ assert_se(fchmodat(AT_FDCWD, path, 0755 | S_ISGID, 0) < 0 && errno == EPERM);
|
||||
+ assert_se(fchmodat(AT_FDCWD, path, 0755 | S_ISGID | S_ISUID, 0) < 0 && errno == EPERM);
|
||||
+ assert_se(fchmodat(AT_FDCWD, path, 0755, 0) >= 0);
|
||||
+
|
||||
+ assert_se(real_open(z, O_CREAT|O_RDWR|O_CLOEXEC|O_EXCL, 0644 | S_ISUID) < 0 && errno == EPERM);
|
||||
+ assert_se(real_open(z, O_CREAT|O_RDWR|O_CLOEXEC|O_EXCL, 0644 | S_ISGID) < 0 && errno == EPERM);
|
||||
+ assert_se(real_open(z, O_CREAT|O_RDWR|O_CLOEXEC|O_EXCL, 0644 | S_ISUID | S_ISGID) < 0 && errno == EPERM);
|
||||
+ k = real_open(z, O_CREAT|O_RDWR|O_CLOEXEC|O_EXCL, 0644);
|
||||
+ k = safe_close(k);
|
||||
+ assert_se(unlink(z) >= 0);
|
||||
+
|
||||
+ assert_se(creat(z, 0644 | S_ISUID) < 0 && errno == EPERM);
|
||||
+ assert_se(creat(z, 0644 | S_ISGID) < 0 && errno == EPERM);
|
||||
+ assert_se(creat(z, 0644 | S_ISUID | S_ISGID) < 0 && errno == EPERM);
|
||||
+ k = creat(z, 0644);
|
||||
+ k = safe_close(k);
|
||||
+ assert_se(unlink(z) >= 0);
|
||||
+
|
||||
+ assert_se(openat(AT_FDCWD, z, O_CREAT|O_RDWR|O_CLOEXEC|O_EXCL, 0644 | S_ISUID) < 0 && errno == EPERM);
|
||||
+ assert_se(openat(AT_FDCWD, z, O_CREAT|O_RDWR|O_CLOEXEC|O_EXCL, 0644 | S_ISGID) < 0 && errno == EPERM);
|
||||
+ assert_se(openat(AT_FDCWD, z, O_CREAT|O_RDWR|O_CLOEXEC|O_EXCL, 0644 | S_ISUID | S_ISGID) < 0 && errno == EPERM);
|
||||
+ k = openat(AT_FDCWD, z, O_CREAT|O_RDWR|O_CLOEXEC|O_EXCL, 0644);
|
||||
+ k = safe_close(k);
|
||||
+ assert_se(unlink(z) >= 0);
|
||||
+
|
||||
+ assert_se(mkdir(z, 0755 | S_ISUID) < 0 && errno == EPERM);
|
||||
+ assert_se(mkdir(z, 0755 | S_ISGID) < 0 && errno == EPERM);
|
||||
+ assert_se(mkdir(z, 0755 | S_ISUID | S_ISGID) < 0 && errno == EPERM);
|
||||
+ assert_se(mkdir(z, 0755) >= 0);
|
||||
+ assert_se(rmdir(z) >= 0);
|
||||
+
|
||||
+ assert_se(mkdirat(AT_FDCWD, z, 0755 | S_ISUID) < 0 && errno == EPERM);
|
||||
+ assert_se(mkdirat(AT_FDCWD, z, 0755 | S_ISGID) < 0 && errno == EPERM);
|
||||
+ assert_se(mkdirat(AT_FDCWD, z, 0755 | S_ISUID | S_ISGID) < 0 && errno == EPERM);
|
||||
+ assert_se(mkdirat(AT_FDCWD, z, 0755) >= 0);
|
||||
+ assert_se(rmdir(z) >= 0);
|
||||
+
|
||||
+ assert_se(mknod(z, S_IFREG | 0755 | S_ISUID, 0) < 0 && errno == EPERM);
|
||||
+ assert_se(mknod(z, S_IFREG | 0755 | S_ISGID, 0) < 0 && errno == EPERM);
|
||||
+ assert_se(mknod(z, S_IFREG | 0755 | S_ISUID | S_ISGID, 0) < 0 && errno == EPERM);
|
||||
+ assert_se(mknod(z, S_IFREG | 0755, 0) >= 0);
|
||||
+ assert_se(unlink(z) >= 0);
|
||||
+
|
||||
+ assert_se(mknodat(AT_FDCWD, z, S_IFREG | 0755 | S_ISUID, 0) < 0 && errno == EPERM);
|
||||
+ assert_se(mknodat(AT_FDCWD, z, S_IFREG | 0755 | S_ISGID, 0) < 0 && errno == EPERM);
|
||||
+ assert_se(mknodat(AT_FDCWD, z, S_IFREG | 0755 | S_ISUID | S_ISGID, 0) < 0 && errno == EPERM);
|
||||
+ assert_se(mknodat(AT_FDCWD, z, S_IFREG | 0755, 0) >= 0);
|
||||
+ assert_se(unlink(z) >= 0);
|
||||
+
|
||||
+ assert_se(unlink(path) >= 0);
|
||||
+ assert_se(rm_rf(dir, REMOVE_ROOT|REMOVE_PHYSICAL) >= 0);
|
||||
+
|
||||
+ _exit(EXIT_SUCCESS);
|
||||
+ }
|
||||
+
|
||||
+ assert_se(wait_for_terminate_and_check("suidsgidseccomp", pid, WAIT_LOG) == EXIT_SUCCESS);
|
||||
+}
|
||||
+
|
||||
int main(int argc, char *argv[]) {
|
||||
|
||||
log_set_max_level(LOG_DEBUG);
|
||||
@@ -684,6 +909,7 @@ int main(int argc, char *argv[]) {
|
||||
test_load_syscall_filter_set_raw();
|
||||
test_lock_personality();
|
||||
test_filter_sets_ordered();
|
||||
+ test_restrict_suid_sgid();
|
||||
|
||||
return 0;
|
||||
}
|
@ -0,0 +1,157 @@
|
||||
From f79283a86531e3bbf0854b5f126b7b291fadfb43 Mon Sep 17 00:00:00 2001
|
||||
From: Lennart Poettering <lennart@poettering.net>
|
||||
Date: Wed, 20 Mar 2019 19:09:09 +0100
|
||||
Subject: [PATCH] core: expose SUID/SGID restriction as new unit setting
|
||||
RestrictSUIDSGID=
|
||||
|
||||
(cherry picked from commit f69567cbe26d09eac9d387c0be0fc32c65a83ada)
|
||||
Related: #1687512
|
||||
---
|
||||
src/core/dbus-execute.c | 4 ++++
|
||||
src/core/execute.c | 22 +++++++++++++++++++++
|
||||
src/core/execute.h | 1 +
|
||||
src/core/load-fragment-gperf.gperf.m4 | 2 ++
|
||||
src/shared/bus-unit-util.c | 2 +-
|
||||
test/fuzz/fuzz-unit-file/directives.service | 1 +
|
||||
6 files changed, 31 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/src/core/dbus-execute.c b/src/core/dbus-execute.c
|
||||
index 198f149210..e7c0b893d1 100644
|
||||
--- a/src/core/dbus-execute.c
|
||||
+++ b/src/core/dbus-execute.c
|
||||
@@ -815,6 +815,7 @@ const sd_bus_vtable bus_exec_vtable[] = {
|
||||
SD_BUS_PROPERTY("ConfigurationDirectory", "as", NULL, offsetof(ExecContext, directories[EXEC_DIRECTORY_CONFIGURATION].paths), SD_BUS_VTABLE_PROPERTY_CONST),
|
||||
SD_BUS_PROPERTY("MemoryDenyWriteExecute", "b", bus_property_get_bool, offsetof(ExecContext, memory_deny_write_execute), SD_BUS_VTABLE_PROPERTY_CONST),
|
||||
SD_BUS_PROPERTY("RestrictRealtime", "b", bus_property_get_bool, offsetof(ExecContext, restrict_realtime), SD_BUS_VTABLE_PROPERTY_CONST),
|
||||
+ SD_BUS_PROPERTY("RestrictSUIDSGID", "b", bus_property_get_bool, offsetof(ExecContext, restrict_suid_sgid), SD_BUS_VTABLE_PROPERTY_CONST),
|
||||
SD_BUS_PROPERTY("RestrictNamespaces", "t", bus_property_get_ulong, offsetof(ExecContext, restrict_namespaces), SD_BUS_VTABLE_PROPERTY_CONST),
|
||||
SD_BUS_PROPERTY("BindPaths", "a(ssbt)", property_get_bind_paths, 0, SD_BUS_VTABLE_PROPERTY_CONST),
|
||||
SD_BUS_PROPERTY("BindReadOnlyPaths", "a(ssbt)", property_get_bind_paths, 0, SD_BUS_VTABLE_PROPERTY_CONST),
|
||||
@@ -1179,6 +1180,9 @@ int bus_exec_context_set_transient_property(
|
||||
if (streq(name, "RestrictRealtime"))
|
||||
return bus_set_transient_bool(u, name, &c->restrict_realtime, message, flags, error);
|
||||
|
||||
+ if (streq(name, "RestrictSUIDSGID"))
|
||||
+ return bus_set_transient_bool(u, name, &c->restrict_suid_sgid, message, flags, error);
|
||||
+
|
||||
if (streq(name, "DynamicUser"))
|
||||
return bus_set_transient_bool(u, name, &c->dynamic_user, message, flags, error);
|
||||
|
||||
diff --git a/src/core/execute.c b/src/core/execute.c
|
||||
index 56aa89e1ec..f012023224 100644
|
||||
--- a/src/core/execute.c
|
||||
+++ b/src/core/execute.c
|
||||
@@ -1366,6 +1366,7 @@ static bool context_has_no_new_privileges(const ExecContext *c) {
|
||||
return context_has_address_families(c) ||
|
||||
c->memory_deny_write_execute ||
|
||||
c->restrict_realtime ||
|
||||
+ c->restrict_suid_sgid ||
|
||||
exec_context_restrict_namespaces_set(c) ||
|
||||
c->protect_kernel_tunables ||
|
||||
c->protect_kernel_modules ||
|
||||
@@ -1470,6 +1471,19 @@ static int apply_restrict_realtime(const Unit* u, const ExecContext *c) {
|
||||
return seccomp_restrict_realtime();
|
||||
}
|
||||
|
||||
+static int apply_restrict_suid_sgid(const Unit* u, const ExecContext *c) {
|
||||
+ assert(u);
|
||||
+ assert(c);
|
||||
+
|
||||
+ if (!c->restrict_suid_sgid)
|
||||
+ return 0;
|
||||
+
|
||||
+ if (skip_seccomp_unavailable(u, "RestrictSUIDSGID="))
|
||||
+ return 0;
|
||||
+
|
||||
+ return seccomp_restrict_suid_sgid();
|
||||
+}
|
||||
+
|
||||
static int apply_protect_sysctl(const Unit *u, const ExecContext *c) {
|
||||
assert(u);
|
||||
assert(c);
|
||||
@@ -3404,6 +3418,12 @@ static int exec_child(
|
||||
return log_unit_error_errno(unit, r, "Failed to apply realtime restrictions: %m");
|
||||
}
|
||||
|
||||
+ r = apply_restrict_suid_sgid(unit, context);
|
||||
+ if (r < 0) {
|
||||
+ *exit_status = EXIT_SECCOMP;
|
||||
+ return log_unit_error_errno(unit, r, "Failed to apply SUID/SGID restrictions: %m");
|
||||
+ }
|
||||
+
|
||||
r = apply_restrict_namespaces(unit, context);
|
||||
if (r < 0) {
|
||||
*exit_status = EXIT_SECCOMP;
|
||||
@@ -4023,6 +4043,7 @@ void exec_context_dump(const ExecContext *c, FILE* f, const char *prefix) {
|
||||
"%sIgnoreSIGPIPE: %s\n"
|
||||
"%sMemoryDenyWriteExecute: %s\n"
|
||||
"%sRestrictRealtime: %s\n"
|
||||
+ "%sRestrictSUIDSGID: %s\n"
|
||||
"%sKeyringMode: %s\n",
|
||||
prefix, c->umask,
|
||||
prefix, c->working_directory ? c->working_directory : "/",
|
||||
@@ -4041,6 +4062,7 @@ void exec_context_dump(const ExecContext *c, FILE* f, const char *prefix) {
|
||||
prefix, yes_no(c->ignore_sigpipe),
|
||||
prefix, yes_no(c->memory_deny_write_execute),
|
||||
prefix, yes_no(c->restrict_realtime),
|
||||
+ prefix, yes_no(c->restrict_suid_sgid),
|
||||
prefix, exec_keyring_mode_to_string(c->keyring_mode));
|
||||
|
||||
if (c->root_image)
|
||||
diff --git a/src/core/execute.h b/src/core/execute.h
|
||||
index b2eb55f8f5..2266355962 100644
|
||||
--- a/src/core/execute.h
|
||||
+++ b/src/core/execute.h
|
||||
@@ -245,6 +245,7 @@ struct ExecContext {
|
||||
* that the autofs logic detects that it belongs to us and we
|
||||
* don't enter a trigger loop. */
|
||||
bool same_pgrp;
|
||||
+ bool restrict_suid_sgid;
|
||||
|
||||
unsigned long personality;
|
||||
bool lock_personality;
|
||||
diff --git a/src/core/load-fragment-gperf.gperf.m4 b/src/core/load-fragment-gperf.gperf.m4
|
||||
index cdf4d14c4e..49e938d0ce 100644
|
||||
--- a/src/core/load-fragment-gperf.gperf.m4
|
||||
+++ b/src/core/load-fragment-gperf.gperf.m4
|
||||
@@ -76,6 +76,7 @@ $1.SystemCallErrorNumber, config_parse_syscall_errno, 0,
|
||||
$1.MemoryDenyWriteExecute, config_parse_bool, 0, offsetof($1, exec_context.memory_deny_write_execute)
|
||||
$1.RestrictNamespaces, config_parse_restrict_namespaces, 0, offsetof($1, exec_context)
|
||||
$1.RestrictRealtime, config_parse_bool, 0, offsetof($1, exec_context.restrict_realtime)
|
||||
+$1.RestrictSUIDSGID, config_parse_bool, 0, offsetof($1, exec_context.restrict_suid_sgid)
|
||||
$1.RestrictAddressFamilies, config_parse_address_families, 0, offsetof($1, exec_context)
|
||||
$1.LockPersonality, config_parse_bool, 0, offsetof($1, exec_context.lock_personality)',
|
||||
`$1.SystemCallFilter, config_parse_warn_compat, DISABLED_CONFIGURATION, 0
|
||||
@@ -84,6 +85,7 @@ $1.SystemCallErrorNumber, config_parse_warn_compat, DISABLED_CO
|
||||
$1.MemoryDenyWriteExecute, config_parse_warn_compat, DISABLED_CONFIGURATION, 0
|
||||
$1.RestrictNamespaces, config_parse_warn_compat, DISABLED_CONFIGURATION, 0
|
||||
$1.RestrictRealtime, config_parse_warn_compat, DISABLED_CONFIGURATION, 0
|
||||
+$1.RestrictSUIDSGID, config_parse_warn_compat, DISABLED_CONFIGURATION 0
|
||||
$1.RestrictAddressFamilies, config_parse_warn_compat, DISABLED_CONFIGURATION, 0
|
||||
$1.LockPersonality, config_parse_warn_compat, DISABLED_CONFIGURATION, 0')
|
||||
$1.LimitCPU, config_parse_rlimit, RLIMIT_CPU, offsetof($1, exec_context.rlimit)
|
||||
diff --git a/src/shared/bus-unit-util.c b/src/shared/bus-unit-util.c
|
||||
index 055edd6e22..3c42e97b7a 100644
|
||||
--- a/src/shared/bus-unit-util.c
|
||||
+++ b/src/shared/bus-unit-util.c
|
||||
@@ -697,7 +697,7 @@ static int bus_append_execute_property(sd_bus_message *m, const char *field, con
|
||||
"PrivateMounts", "NoNewPrivileges", "SyslogLevelPrefix",
|
||||
"MemoryDenyWriteExecute", "RestrictRealtime", "DynamicUser", "RemoveIPC",
|
||||
"ProtectKernelTunables", "ProtectKernelModules", "ProtectControlGroups",
|
||||
- "MountAPIVFS", "CPUSchedulingResetOnFork", "LockPersonality"))
|
||||
+ "MountAPIVFS", "CPUSchedulingResetOnFork", "LockPersonality" "RestrictSUIDSGID"))
|
||||
|
||||
return bus_append_parse_boolean(m, field, eq);
|
||||
|
||||
diff --git a/test/fuzz/fuzz-unit-file/directives.service b/test/fuzz/fuzz-unit-file/directives.service
|
||||
index d8d1fc68b8..eab1820e20 100644
|
||||
--- a/test/fuzz/fuzz-unit-file/directives.service
|
||||
+++ b/test/fuzz/fuzz-unit-file/directives.service
|
||||
@@ -849,6 +849,7 @@ ReserveVT=
|
||||
RestrictAddressFamilies=
|
||||
RestrictNamespaces=
|
||||
RestrictRealtime=
|
||||
+RestrictSUIDSGID=
|
||||
RuntimeDirectory=
|
||||
RuntimeDirectoryMode=
|
||||
RuntimeDirectoryPreserve=
|
@ -0,0 +1,52 @@
|
||||
From 3d338556760632b9c8b646a719d56e02e3ad2088 Mon Sep 17 00:00:00 2001
|
||||
From: Lennart Poettering <lennart@poettering.net>
|
||||
Date: Wed, 20 Mar 2019 19:20:35 +0100
|
||||
Subject: [PATCH] analyze: check for RestrictSUIDSGID= in "systemd-analyze
|
||||
security"
|
||||
|
||||
And let's give it a heigh weight, since it pretty much can be used for
|
||||
bad things only.
|
||||
|
||||
(cherry picked from commit 9d880b70ba5c6ca83c82952f4c90e86e56c7b70c)
|
||||
Related: #1687512
|
||||
---
|
||||
src/analyze/analyze-security.c | 12 ++++++++++++
|
||||
1 file changed, 12 insertions(+)
|
||||
|
||||
diff --git a/src/analyze/analyze-security.c b/src/analyze/analyze-security.c
|
||||
index eec040d5c3..969101c57b 100644
|
||||
--- a/src/analyze/analyze-security.c
|
||||
+++ b/src/analyze/analyze-security.c
|
||||
@@ -69,6 +69,7 @@ struct security_info {
|
||||
|
||||
uint64_t restrict_namespaces;
|
||||
bool restrict_realtime;
|
||||
+ bool restrict_suid_sgid;
|
||||
|
||||
char *root_directory;
|
||||
char *root_image;
|
||||
@@ -1130,6 +1131,16 @@ static const struct security_assessor security_assessor_table[] = {
|
||||
.assess = assess_bool,
|
||||
.offset = offsetof(struct security_info, restrict_realtime),
|
||||
},
|
||||
+ {
|
||||
+ .id = "RestrictSUIDSGID=",
|
||||
+ .url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#RestrictSUIDSGID=",
|
||||
+ .description_good = "SUID/SGID file creation by service is restricted",
|
||||
+ .description_bad = "Service may create SUID/SGID files",
|
||||
+ .weight = 1000,
|
||||
+ .range = 1,
|
||||
+ .assess = assess_bool,
|
||||
+ .offset = offsetof(struct security_info, restrict_suid_sgid),
|
||||
+ },
|
||||
{
|
||||
.id = "RestrictNamespaces=~CLONE_NEWUSER",
|
||||
.url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#RestrictNamespaces=",
|
||||
@@ -1862,6 +1873,7 @@ static int acquire_security_info(sd_bus *bus, const char *name, struct security_
|
||||
{ "RestrictAddressFamilies", "(bas)", property_read_restrict_address_families, 0 },
|
||||
{ "RestrictNamespaces", "t", NULL, offsetof(struct security_info, restrict_namespaces) },
|
||||
{ "RestrictRealtime", "b", NULL, offsetof(struct security_info, restrict_realtime) },
|
||||
+ { "RestrictSUIDSGID", "b", NULL, offsetof(struct security_info, restrict_suid_sgid) },
|
||||
{ "RootDirectory", "s", NULL, offsetof(struct security_info, root_directory) },
|
||||
{ "RootImage", "s", NULL, offsetof(struct security_info, root_image) },
|
||||
{ "SupplementaryGroups", "as", NULL, offsetof(struct security_info, supplementary_groups) },
|
@ -0,0 +1,83 @@
|
||||
From 797ebaa8240aefc39de3d1713468b221c83ed3f5 Mon Sep 17 00:00:00 2001
|
||||
From: Lennart Poettering <lennart@poettering.net>
|
||||
Date: Wed, 20 Mar 2019 19:45:32 +0100
|
||||
Subject: [PATCH] man: document the new RestrictSUIDSGID= setting
|
||||
|
||||
(cherry picked from commit 7445db6eb70e8d5989f481d0c5a08ace7047ae5b)
|
||||
Related: #1687512
|
||||
---
|
||||
doc/TRANSIENT-SETTINGS.md | 1 +
|
||||
man/systemd.exec.xml | 41 +++++++++++++++++++++++++++------------
|
||||
2 files changed, 30 insertions(+), 12 deletions(-)
|
||||
|
||||
diff --git a/doc/TRANSIENT-SETTINGS.md b/doc/TRANSIENT-SETTINGS.md
|
||||
index 0ea444b133..c2b5c0dcce 100644
|
||||
--- a/doc/TRANSIENT-SETTINGS.md
|
||||
+++ b/doc/TRANSIENT-SETTINGS.md
|
||||
@@ -149,6 +149,7 @@ All execution-related settings are available for transient units.
|
||||
✓ MemoryDenyWriteExecute=
|
||||
✓ RestrictNamespaces=
|
||||
✓ RestrictRealtime=
|
||||
+✓ RestrictSUIDSGID=
|
||||
✓ RestrictAddressFamilies=
|
||||
✓ LockPersonality=
|
||||
✓ LimitCPU=
|
||||
diff --git a/man/systemd.exec.xml b/man/systemd.exec.xml
|
||||
index 87fb8b34f4..45ed1864f8 100644
|
||||
--- a/man/systemd.exec.xml
|
||||
+++ b/man/systemd.exec.xml
|
||||
@@ -348,18 +348,19 @@ CapabilityBoundingSet=~CAP_B CAP_C</programlisting>
|
||||
<varlistentry>
|
||||
<term><varname>NoNewPrivileges=</varname></term>
|
||||
|
||||
- <listitem><para>Takes a boolean argument. If true, ensures that the service process and all its children can
|
||||
- never gain new privileges through <function>execve()</function> (e.g. via setuid or setgid bits, or filesystem
|
||||
- capabilities). This is the simplest and most effective way to ensure that a process and its children can never
|
||||
- elevate privileges again. Defaults to false, but certain settings override this and ignore the value of this
|
||||
- setting. This is the case when <varname>SystemCallFilter=</varname>,
|
||||
- <varname>SystemCallArchitectures=</varname>, <varname>RestrictAddressFamilies=</varname>,
|
||||
- <varname>RestrictNamespaces=</varname>, <varname>PrivateDevices=</varname>,
|
||||
- <varname>ProtectKernelTunables=</varname>, <varname>ProtectKernelModules=</varname>,
|
||||
- <varname>MemoryDenyWriteExecute=</varname>, <varname>RestrictRealtime=</varname>, or
|
||||
- <varname>LockPersonality=</varname> are specified. Note that even if this setting is overridden by them,
|
||||
- <command>systemctl show</command> shows the original value of this setting. Also see
|
||||
- <ulink url="https://www.kernel.org/doc/html/latest/userspace-api/no_new_privs.html">No New Privileges
|
||||
+ <listitem><para>Takes a boolean argument. If true, ensures that the service process and all its
|
||||
+ children can never gain new privileges through <function>execve()</function> (e.g. via setuid or
|
||||
+ setgid bits, or filesystem capabilities). This is the simplest and most effective way to ensure that
|
||||
+ a process and its children can never elevate privileges again. Defaults to false, but certain
|
||||
+ settings override this and ignore the value of this setting. This is the case when
|
||||
+ <varname>SystemCallFilter=</varname>, <varname>SystemCallArchitectures=</varname>,
|
||||
+ <varname>RestrictAddressFamilies=</varname>, <varname>RestrictNamespaces=</varname>,
|
||||
+ <varname>PrivateDevices=</varname>, <varname>ProtectKernelTunables=</varname>,
|
||||
+ <varname>ProtectKernelModules=</varname>, <varname>MemoryDenyWriteExecute=</varname>,
|
||||
+ <varname>RestrictRealtime=</varname>, <varname>RestrictSUIDSGID=</varname> or
|
||||
+ <varname>LockPersonality=</varname> are specified. Note that even if this setting is overridden by
|
||||
+ them, <command>systemctl show</command> shows the original value of this setting. Also see <ulink
|
||||
+ url="https://www.kernel.org/doc/html/latest/userspace-api/no_new_privs.html">No New Privileges
|
||||
Flag</ulink>. </para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
@@ -1274,6 +1275,22 @@ RestrictNamespaces=~cgroup net</programlisting>
|
||||
that actually require them. Defaults to off.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
+ <varlistentry>
|
||||
+ <term><varname>RestrictSUIDSGID=</varname></term>
|
||||
+
|
||||
+ <listitem><para>Takes a boolean argument. If set, any attempts to set the set-user-ID (SUID) or
|
||||
+ set-group-ID (SGID) bits on files or directories will be denied (for details on these bits see
|
||||
+ <citerefentry
|
||||
+ project='man-pages'><refentrytitle>inode</refentrytitle><manvolnum>7</manvolnum></citerefentry>). If
|
||||
+ running in user mode, or in system mode, but without the <constant>CAP_SYS_ADMIN</constant>
|
||||
+ capability (e.g. setting <varname>User=</varname>), <varname>NoNewPrivileges=yes</varname> is
|
||||
+ implied. As the SUID/SGID bits are mechanisms to elevate privileges, and allows users to acquire the
|
||||
+ identity of other users, it is recommended to restrict creation of SUID/SGID files to the few
|
||||
+ programs that actually require them. Note that this restricts marking of any type of file system
|
||||
+ object with these bits, including both regular files and directories (where the SGID is a different
|
||||
+ meaning than for files, see documentation). Defaults to off.</para></listitem>
|
||||
+ </varlistentry>
|
||||
+
|
||||
<varlistentry>
|
||||
<term><varname>RemoveIPC=</varname></term>
|
||||
|
@ -0,0 +1,157 @@
|
||||
From b0573f1a6f8022aed4954d5ca19cc037d25cd5e7 Mon Sep 17 00:00:00 2001
|
||||
From: Lennart Poettering <lennart@poettering.net>
|
||||
Date: Wed, 20 Mar 2019 19:52:20 +0100
|
||||
Subject: [PATCH] units: turn on RestrictSUIDSGID= in most of our long-running
|
||||
daemons
|
||||
|
||||
(cherry picked from commit 62aa29247c3d74bcec0607c347f2be23cd90675d)
|
||||
Related: #1687512
|
||||
---
|
||||
units/systemd-coredump@.service.in | 1 +
|
||||
units/systemd-hostnamed.service.in | 1 +
|
||||
units/systemd-journal-remote.service.in | 1 +
|
||||
units/systemd-journald.service.in | 1 +
|
||||
units/systemd-localed.service.in | 1 +
|
||||
units/systemd-logind.service.in | 1 +
|
||||
units/systemd-networkd.service.in | 1 +
|
||||
units/systemd-resolved.service.in | 1 +
|
||||
units/systemd-timedated.service.in | 1 +
|
||||
units/systemd-timesyncd.service.in | 1 +
|
||||
units/systemd-udevd.service.in | 3 ++-
|
||||
11 files changed, 12 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/units/systemd-coredump@.service.in b/units/systemd-coredump@.service.in
|
||||
index 68a68a5055..d69ebd8b24 100644
|
||||
--- a/units/systemd-coredump@.service.in
|
||||
+++ b/units/systemd-coredump@.service.in
|
||||
@@ -33,6 +33,7 @@ MemoryDenyWriteExecute=yes
|
||||
RestrictRealtime=yes
|
||||
RestrictNamespaces=yes
|
||||
RestrictAddressFamilies=AF_UNIX
|
||||
+RestrictSUIDSGID=yes
|
||||
SystemCallFilter=@system-service
|
||||
SystemCallErrorNumber=EPERM
|
||||
SystemCallArchitectures=native
|
||||
diff --git a/units/systemd-hostnamed.service.in b/units/systemd-hostnamed.service.in
|
||||
index 4e5470dd29..97d4e142bc 100644
|
||||
--- a/units/systemd-hostnamed.service.in
|
||||
+++ b/units/systemd-hostnamed.service.in
|
||||
@@ -29,6 +29,7 @@ MemoryDenyWriteExecute=yes
|
||||
RestrictRealtime=yes
|
||||
RestrictNamespaces=yes
|
||||
RestrictAddressFamilies=AF_UNIX
|
||||
+RestrictSUIDSGID=yes
|
||||
SystemCallFilter=@system-service sethostname
|
||||
SystemCallErrorNumber=EPERM
|
||||
SystemCallArchitectures=native
|
||||
diff --git a/units/systemd-journal-remote.service.in b/units/systemd-journal-remote.service.in
|
||||
index a94265f215..3c914f5a40 100644
|
||||
--- a/units/systemd-journal-remote.service.in
|
||||
+++ b/units/systemd-journal-remote.service.in
|
||||
@@ -28,6 +28,7 @@ MemoryDenyWriteExecute=yes
|
||||
RestrictRealtime=yes
|
||||
RestrictNamespaces=yes
|
||||
RestrictAddressFamilies=AF_UNIX AF_INET AF_INET6
|
||||
+RestrictSUIDSGID=yes
|
||||
SystemCallArchitectures=native
|
||||
LockPersonality=yes
|
||||
LogsDirectory=journal/remote
|
||||
diff --git a/units/systemd-journald.service.in b/units/systemd-journald.service.in
|
||||
index e109b25792..ab9ec35ff8 100644
|
||||
--- a/units/systemd-journald.service.in
|
||||
+++ b/units/systemd-journald.service.in
|
||||
@@ -21,6 +21,7 @@ Sockets=systemd-journald.socket systemd-journald-dev-log.socket
|
||||
ExecStart=@rootlibexecdir@/systemd-journald
|
||||
Restart=always
|
||||
RestartSec=0
|
||||
+RestrictSUIDSGID=yes
|
||||
StandardOutput=null
|
||||
WatchdogSec=3min
|
||||
FileDescriptorStoreMax=4224
|
||||
diff --git a/units/systemd-localed.service.in b/units/systemd-localed.service.in
|
||||
index ce043db154..b87d60e9eb 100644
|
||||
--- a/units/systemd-localed.service.in
|
||||
+++ b/units/systemd-localed.service.in
|
||||
@@ -29,6 +29,7 @@ MemoryDenyWriteExecute=yes
|
||||
RestrictRealtime=yes
|
||||
RestrictNamespaces=yes
|
||||
RestrictAddressFamilies=AF_UNIX
|
||||
+RestrictSUIDSGID=yes
|
||||
SystemCallFilter=@system-service
|
||||
SystemCallErrorNumber=EPERM
|
||||
SystemCallArchitectures=native
|
||||
diff --git a/units/systemd-logind.service.in b/units/systemd-logind.service.in
|
||||
index 6953fac55b..086338e03b 100644
|
||||
--- a/units/systemd-logind.service.in
|
||||
+++ b/units/systemd-logind.service.in
|
||||
@@ -30,6 +30,7 @@ MemoryDenyWriteExecute=yes
|
||||
RestrictRealtime=yes
|
||||
RestrictNamespaces=yes
|
||||
RestrictAddressFamilies=AF_UNIX AF_NETLINK
|
||||
+RestrictSUIDSGID=yes
|
||||
SystemCallFilter=@system-service
|
||||
SystemCallErrorNumber=EPERM
|
||||
SystemCallArchitectures=native
|
||||
diff --git a/units/systemd-networkd.service.in b/units/systemd-networkd.service.in
|
||||
index 371ab3a9cf..a0f34ac738 100644
|
||||
--- a/units/systemd-networkd.service.in
|
||||
+++ b/units/systemd-networkd.service.in
|
||||
@@ -39,6 +39,7 @@ SystemCallFilter=@system-service
|
||||
SystemCallErrorNumber=EPERM
|
||||
SystemCallArchitectures=native
|
||||
LockPersonality=yes
|
||||
+RestrictSUIDSGID=yes
|
||||
RuntimeDirectory=systemd/netif
|
||||
RuntimeDirectoryPreserve=yes
|
||||
|
||||
diff --git a/units/systemd-resolved.service.in b/units/systemd-resolved.service.in
|
||||
index aaed406ab2..6c2ad5ca86 100644
|
||||
--- a/units/systemd-resolved.service.in
|
||||
+++ b/units/systemd-resolved.service.in
|
||||
@@ -41,6 +41,7 @@ SystemCallFilter=@system-service
|
||||
SystemCallErrorNumber=EPERM
|
||||
SystemCallArchitectures=native
|
||||
LockPersonality=yes
|
||||
+RestrictSUIDSGID=yes
|
||||
RuntimeDirectory=systemd/resolve
|
||||
RuntimeDirectoryPreserve=yes
|
||||
|
||||
diff --git a/units/systemd-timedated.service.in b/units/systemd-timedated.service.in
|
||||
index 662b39557a..1da2bc4bb0 100644
|
||||
--- a/units/systemd-timedated.service.in
|
||||
+++ b/units/systemd-timedated.service.in
|
||||
@@ -27,6 +27,7 @@ MemoryDenyWriteExecute=yes
|
||||
RestrictRealtime=yes
|
||||
RestrictNamespaces=yes
|
||||
RestrictAddressFamilies=AF_UNIX
|
||||
+RestrictSUIDSGID=yes
|
||||
SystemCallFilter=@system-service @clock
|
||||
SystemCallErrorNumber=EPERM
|
||||
SystemCallArchitectures=native
|
||||
diff --git a/units/systemd-timesyncd.service.in b/units/systemd-timesyncd.service.in
|
||||
index 4a490b6e16..c2b9551726 100644
|
||||
--- a/units/systemd-timesyncd.service.in
|
||||
+++ b/units/systemd-timesyncd.service.in
|
||||
@@ -37,6 +37,7 @@ MemoryDenyWriteExecute=yes
|
||||
RestrictRealtime=yes
|
||||
RestrictNamespaces=yes
|
||||
RestrictAddressFamilies=AF_UNIX AF_INET AF_INET6
|
||||
+RestrictSUIDSGID=yes
|
||||
RuntimeDirectory=systemd/timesync
|
||||
SystemCallFilter=@system-service @clock
|
||||
SystemCallErrorNumber=EPERM
|
||||
diff --git a/units/systemd-udevd.service.in b/units/systemd-udevd.service.in
|
||||
index fd9ead3bb8..970cf0f290 100644
|
||||
--- a/units/systemd-udevd.service.in
|
||||
+++ b/units/systemd-udevd.service.in
|
||||
@@ -27,8 +27,9 @@ WatchdogSec=3min
|
||||
TasksMax=infinity
|
||||
PrivateMounts=yes
|
||||
MemoryDenyWriteExecute=yes
|
||||
-RestrictRealtime=yes
|
||||
RestrictAddressFamilies=AF_UNIX AF_NETLINK AF_INET AF_INET6
|
||||
+RestrictRealtime=yes
|
||||
+RestrictSUIDSGID=yes
|
||||
SystemCallFilter=@system-service @module @raw-io
|
||||
SystemCallErrorNumber=EPERM
|
||||
SystemCallArchitectures=native
|
@ -0,0 +1,89 @@
|
||||
From 11f5677752f9b78239214b3064e5a2c3712d71b1 Mon Sep 17 00:00:00 2001
|
||||
From: Lennart Poettering <lennart@poettering.net>
|
||||
Date: Wed, 20 Mar 2019 20:19:38 +0100
|
||||
Subject: [PATCH] core: imply NNP and SUID/SGID restriction for DynamicUser=yes
|
||||
service
|
||||
|
||||
Let's be safe, rather than sorry. This way DynamicUser=yes services can
|
||||
neither take benefit of, nor create SUID/SGID binaries.
|
||||
|
||||
Given that DynamicUser= is a recent addition only we should be able to
|
||||
get away with turning this on, even though this is strictly speaking a
|
||||
binary compatibility breakage.
|
||||
|
||||
(cherry picked from commit bf65b7e0c9fc215897b676ab9a7c9d1c688143ba)
|
||||
Resolves: #1687512
|
||||
---
|
||||
man/systemd.exec.xml | 16 ++++++++++------
|
||||
src/core/unit.c | 10 ++++++++--
|
||||
2 files changed, 18 insertions(+), 8 deletions(-)
|
||||
|
||||
diff --git a/man/systemd.exec.xml b/man/systemd.exec.xml
|
||||
index 45ed1864f8..bdaed68162 100644
|
||||
--- a/man/systemd.exec.xml
|
||||
+++ b/man/systemd.exec.xml
|
||||
@@ -229,7 +229,9 @@
|
||||
created by the executed processes is bound to the runtime of the service, and hence the lifetime of the dynamic
|
||||
user/group. Since <filename>/tmp</filename> and <filename>/var/tmp</filename> are usually the only
|
||||
world-writable directories on a system this ensures that a unit making use of dynamic user/group allocation
|
||||
- cannot leave files around after unit termination. Moreover <varname>ProtectSystem=strict</varname> and
|
||||
+ cannot leave files around after unit termination. Furthermore <varname>NoNewPrivileges=</varname> and
|
||||
+ <varname>RestrictSUIDSGID=</varname> are implicitly enabled to ensure that processes invoked cannot take benefit
|
||||
+ or create SUID/SGID files or directories. Moreover <varname>ProtectSystem=strict</varname> and
|
||||
<varname>ProtectHome=read-only</varname> are implied, thus prohibiting the service to write to arbitrary file
|
||||
system locations. In order to allow the service to write to certain directories, they have to be whitelisted
|
||||
using <varname>ReadWritePaths=</varname>, but care must be taken so that UID/GID recycling doesn't create
|
||||
@@ -357,11 +359,12 @@ CapabilityBoundingSet=~CAP_B CAP_C</programlisting>
|
||||
<varname>RestrictAddressFamilies=</varname>, <varname>RestrictNamespaces=</varname>,
|
||||
<varname>PrivateDevices=</varname>, <varname>ProtectKernelTunables=</varname>,
|
||||
<varname>ProtectKernelModules=</varname>, <varname>MemoryDenyWriteExecute=</varname>,
|
||||
- <varname>RestrictRealtime=</varname>, <varname>RestrictSUIDSGID=</varname> or
|
||||
- <varname>LockPersonality=</varname> are specified. Note that even if this setting is overridden by
|
||||
- them, <command>systemctl show</command> shows the original value of this setting. Also see <ulink
|
||||
+ <varname>RestrictRealtime=</varname>, <varname>RestrictSUIDSGID=</varname>,
|
||||
+ <varname>DynamicUser=</varname> or <varname>LockPersonality=</varname> are specified. Note that even
|
||||
+ if this setting is overridden by them, <command>systemctl show</command> shows the original value of
|
||||
+ this setting. Also see <ulink
|
||||
url="https://www.kernel.org/doc/html/latest/userspace-api/no_new_privs.html">No New Privileges
|
||||
- Flag</ulink>. </para></listitem>
|
||||
+ Flag</ulink>.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
@@ -1288,7 +1291,8 @@ RestrictNamespaces=~cgroup net</programlisting>
|
||||
identity of other users, it is recommended to restrict creation of SUID/SGID files to the few
|
||||
programs that actually require them. Note that this restricts marking of any type of file system
|
||||
object with these bits, including both regular files and directories (where the SGID is a different
|
||||
- meaning than for files, see documentation). Defaults to off.</para></listitem>
|
||||
+ meaning than for files, see documentation). This option is implied if <varname>DynamicUser=</varname>
|
||||
+ is enabled. Defaults to off.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
diff --git a/src/core/unit.c b/src/core/unit.c
|
||||
index 115739f4c6..e1f5e6f7bd 100644
|
||||
--- a/src/core/unit.c
|
||||
+++ b/src/core/unit.c
|
||||
@@ -4161,14 +4161,20 @@ int unit_patch_contexts(Unit *u) {
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
- /* If the dynamic user option is on, let's make sure that the unit can't leave its UID/GID
|
||||
- * around in the file system or on IPC objects. Hence enforce a strict sandbox. */
|
||||
+ /* If the dynamic user option is on, let's make sure that the unit can't leave its
|
||||
+ * UID/GID around in the file system or on IPC objects. Hence enforce a strict
|
||||
+ * sandbox. */
|
||||
|
||||
ec->private_tmp = true;
|
||||
ec->remove_ipc = true;
|
||||
ec->protect_system = PROTECT_SYSTEM_STRICT;
|
||||
if (ec->protect_home == PROTECT_HOME_NO)
|
||||
ec->protect_home = PROTECT_HOME_READ_ONLY;
|
||||
+
|
||||
+ /* Make sure this service can neither benefit from SUID/SGID binaries nor create
|
||||
+ * them. */
|
||||
+ ec->no_new_privileges = true;
|
||||
+ ec->restrict_suid_sgid = true;
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,555 @@
|
||||
From b55c9b8e717d1967e6aa16c1e2646fc81d899ab7 Mon Sep 17 00:00:00 2001
|
||||
From: Pavel Hrdina <phrdina@redhat.com>
|
||||
Date: Mon, 29 Jul 2019 17:50:05 +0200
|
||||
Subject: [PATCH] cgroup: introduce support for cgroup v2 CPUSET controller
|
||||
|
||||
Introduce support for configuring cpus and mems for processes using
|
||||
cgroup v2 CPUSET controller. This allows users to limit which cpus
|
||||
and memory NUMA nodes can be used by processes to better utilize
|
||||
system resources.
|
||||
|
||||
The cgroup v2 interfaces to control it are cpuset.cpus and cpuset.mems
|
||||
where the requested configuration is written. However, it doesn't mean
|
||||
that the requested configuration will be actually used as parent cgroup
|
||||
may limit the cpus or mems as well. In order to reflect the real
|
||||
configuration cgroup v2 provides read-only files cpuset.cpus.effective
|
||||
and cpuset.mems.effective which are exported to users as well.
|
||||
|
||||
(cherry picked from commit 047f5d63d7a1ab75073f8485e2f9b550d25b0772)
|
||||
|
||||
Related: #1724617
|
||||
---
|
||||
doc/TRANSIENT-SETTINGS.md | 2 +
|
||||
man/systemd.resource-control.xml | 30 +++++++++++++
|
||||
src/basic/cgroup-util.c | 1 +
|
||||
src/basic/cgroup-util.h | 2 +
|
||||
src/core/cgroup.c | 63 +++++++++++++++++++++++++++
|
||||
src/core/cgroup.h | 5 +++
|
||||
src/core/dbus-cgroup.c | 59 +++++++++++++++++++++++++
|
||||
src/core/dbus-unit.c | 48 ++++++++++++++++++++
|
||||
src/core/load-fragment-gperf.gperf.m4 | 2 +
|
||||
src/core/load-fragment.c | 38 ++++++++++++++++
|
||||
src/core/load-fragment.h | 2 +
|
||||
src/shared/bus-unit-util.c | 16 +++++++
|
||||
src/systemctl/systemctl.c | 2 +-
|
||||
src/test/test-cgroup-mask.c | 3 +-
|
||||
14 files changed, 271 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/doc/TRANSIENT-SETTINGS.md b/doc/TRANSIENT-SETTINGS.md
|
||||
index c2b5c0dcce..0b2ad66dcb 100644
|
||||
--- a/doc/TRANSIENT-SETTINGS.md
|
||||
+++ b/doc/TRANSIENT-SETTINGS.md
|
||||
@@ -218,6 +218,8 @@ All cgroup/resource control settings are available for transient units
|
||||
✓ CPUShares=
|
||||
✓ StartupCPUShares=
|
||||
✓ CPUQuota=
|
||||
+✓ AllowedCPUs=
|
||||
+✓ AllowedMemoryNodes=
|
||||
✓ MemoryAccounting=
|
||||
✓ MemoryLow=
|
||||
✓ MemoryHigh=
|
||||
diff --git a/man/systemd.resource-control.xml b/man/systemd.resource-control.xml
|
||||
index 370c110592..4329742e94 100644
|
||||
--- a/man/systemd.resource-control.xml
|
||||
+++ b/man/systemd.resource-control.xml
|
||||
@@ -201,6 +201,36 @@
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
+ <varlistentry>
|
||||
+ <term><varname>AllowedCPUs=</varname></term>
|
||||
+
|
||||
+ <listitem>
|
||||
+ <para>Restrict processes to be executed on specific CPUs. Takes a list of CPU indices or ranges separated by either
|
||||
+ whitespace or commas. CPU ranges are specified by the lower and upper CPU indices separated by a dash.</para>
|
||||
+
|
||||
+ <para>Setting <varname>AllowedCPUs=</varname> doesn't guarantee that all of the CPUs will be used by the processes
|
||||
+ as it may be limited by parent units. The effective configuration is reported as <varname>EffectiveCPUs=</varname>.</para>
|
||||
+
|
||||
+ <para>This setting is supported only with the unified control group hierarchy.</para>
|
||||
+ </listitem>
|
||||
+ </varlistentry>
|
||||
+
|
||||
+ <varlistentry>
|
||||
+ <term><varname>AllowedMemoryNodes=</varname></term>
|
||||
+
|
||||
+ <listitem>
|
||||
+ <para>Restrict processes to be executed on specific memory NUMA nodes. Takes a list of memory NUMA nodes indices
|
||||
+ or ranges separated by either whitespace or commas. Memory NUMA nodes ranges are specified by the lower and upper
|
||||
+ CPU indices separated by a dash.</para>
|
||||
+
|
||||
+ <para>Setting <varname>AllowedMemoryNodes=</varname> doesn't guarantee that all of the memory NUMA nodes will
|
||||
+ be used by the processes as it may be limited by parent units. The effective configuration is reported as
|
||||
+ <varname>EffectiveMemoryNodes=</varname>.</para>
|
||||
+
|
||||
+ <para>This setting is supported only with the unified control group hierarchy.</para>
|
||||
+ </listitem>
|
||||
+ </varlistentry>
|
||||
+
|
||||
<varlistentry>
|
||||
<term><varname>MemoryAccounting=</varname></term>
|
||||
|
||||
diff --git a/src/basic/cgroup-util.c b/src/basic/cgroup-util.c
|
||||
index 038ece4b06..6f47c3aacb 100644
|
||||
--- a/src/basic/cgroup-util.c
|
||||
+++ b/src/basic/cgroup-util.c
|
||||
@@ -2763,6 +2763,7 @@ bool fd_is_cgroup_fs(int fd) {
|
||||
static const char *cgroup_controller_table[_CGROUP_CONTROLLER_MAX] = {
|
||||
[CGROUP_CONTROLLER_CPU] = "cpu",
|
||||
[CGROUP_CONTROLLER_CPUACCT] = "cpuacct",
|
||||
+ [CGROUP_CONTROLLER_CPUSET] = "cpuset",
|
||||
[CGROUP_CONTROLLER_IO] = "io",
|
||||
[CGROUP_CONTROLLER_BLKIO] = "blkio",
|
||||
[CGROUP_CONTROLLER_MEMORY] = "memory",
|
||||
diff --git a/src/basic/cgroup-util.h b/src/basic/cgroup-util.h
|
||||
index 26e3ae0404..b414600dca 100644
|
||||
--- a/src/basic/cgroup-util.h
|
||||
+++ b/src/basic/cgroup-util.h
|
||||
@@ -21,6 +21,7 @@
|
||||
typedef enum CGroupController {
|
||||
CGROUP_CONTROLLER_CPU,
|
||||
CGROUP_CONTROLLER_CPUACCT, /* v1 only */
|
||||
+ CGROUP_CONTROLLER_CPUSET, /* v2 only */
|
||||
CGROUP_CONTROLLER_IO, /* v2 only */
|
||||
CGROUP_CONTROLLER_BLKIO, /* v1 only */
|
||||
CGROUP_CONTROLLER_MEMORY,
|
||||
@@ -36,6 +37,7 @@ typedef enum CGroupController {
|
||||
typedef enum CGroupMask {
|
||||
CGROUP_MASK_CPU = CGROUP_CONTROLLER_TO_MASK(CGROUP_CONTROLLER_CPU),
|
||||
CGROUP_MASK_CPUACCT = CGROUP_CONTROLLER_TO_MASK(CGROUP_CONTROLLER_CPUACCT),
|
||||
+ CGROUP_MASK_CPUSET = CGROUP_CONTROLLER_TO_MASK(CGROUP_CONTROLLER_CPUSET),
|
||||
CGROUP_MASK_IO = CGROUP_CONTROLLER_TO_MASK(CGROUP_CONTROLLER_IO),
|
||||
CGROUP_MASK_BLKIO = CGROUP_CONTROLLER_TO_MASK(CGROUP_CONTROLLER_BLKIO),
|
||||
CGROUP_MASK_MEMORY = CGROUP_CONTROLLER_TO_MASK(CGROUP_CONTROLLER_MEMORY),
|
||||
diff --git a/src/core/cgroup.c b/src/core/cgroup.c
|
||||
index 76eafdc082..664d269483 100644
|
||||
--- a/src/core/cgroup.c
|
||||
+++ b/src/core/cgroup.c
|
||||
@@ -161,9 +161,14 @@ void cgroup_context_done(CGroupContext *c) {
|
||||
|
||||
c->ip_address_allow = ip_address_access_free_all(c->ip_address_allow);
|
||||
c->ip_address_deny = ip_address_access_free_all(c->ip_address_deny);
|
||||
+
|
||||
+ cpu_set_reset(&c->cpuset_cpus);
|
||||
+ cpu_set_reset(&c->cpuset_mems);
|
||||
}
|
||||
|
||||
void cgroup_context_dump(CGroupContext *c, FILE* f, const char *prefix) {
|
||||
+ _cleanup_free_ char *cpuset_cpus = NULL;
|
||||
+ _cleanup_free_ char *cpuset_mems = NULL;
|
||||
CGroupIODeviceLimit *il;
|
||||
CGroupIODeviceWeight *iw;
|
||||
CGroupBlockIODeviceBandwidth *b;
|
||||
@@ -177,6 +182,9 @@ void cgroup_context_dump(CGroupContext *c, FILE* f, const char *prefix) {
|
||||
|
||||
prefix = strempty(prefix);
|
||||
|
||||
+ cpuset_cpus = cpu_set_to_range_string(&c->cpuset_cpus);
|
||||
+ cpuset_mems = cpu_set_to_range_string(&c->cpuset_mems);
|
||||
+
|
||||
fprintf(f,
|
||||
"%sCPUAccounting=%s\n"
|
||||
"%sIOAccounting=%s\n"
|
||||
@@ -189,6 +197,8 @@ void cgroup_context_dump(CGroupContext *c, FILE* f, const char *prefix) {
|
||||
"%sCPUShares=%" PRIu64 "\n"
|
||||
"%sStartupCPUShares=%" PRIu64 "\n"
|
||||
"%sCPUQuotaPerSecSec=%s\n"
|
||||
+ "%sAllowedCPUs=%s\n"
|
||||
+ "%sAllowedMemoryNodes=%s\n"
|
||||
"%sIOWeight=%" PRIu64 "\n"
|
||||
"%sStartupIOWeight=%" PRIu64 "\n"
|
||||
"%sBlockIOWeight=%" PRIu64 "\n"
|
||||
@@ -212,6 +222,8 @@ void cgroup_context_dump(CGroupContext *c, FILE* f, const char *prefix) {
|
||||
prefix, c->cpu_shares,
|
||||
prefix, c->startup_cpu_shares,
|
||||
prefix, format_timespan(u, sizeof(u), c->cpu_quota_per_sec_usec, 1),
|
||||
+ prefix, cpuset_cpus,
|
||||
+ prefix, cpuset_mems,
|
||||
prefix, c->io_weight,
|
||||
prefix, c->startup_io_weight,
|
||||
prefix, c->blockio_weight,
|
||||
@@ -541,6 +553,21 @@ static uint64_t cgroup_cpu_weight_to_shares(uint64_t weight) {
|
||||
CGROUP_CPU_SHARES_MIN, CGROUP_CPU_SHARES_MAX);
|
||||
}
|
||||
|
||||
+static void cgroup_apply_unified_cpuset(Unit *u, CPUSet cpus, const char *name) {
|
||||
+ _cleanup_free_ char *buf = NULL;
|
||||
+ int r;
|
||||
+
|
||||
+ buf = cpu_set_to_range_string(&cpus);
|
||||
+ if (!buf)
|
||||
+ return;
|
||||
+
|
||||
+ r = cg_set_attribute("cpuset", u->cgroup_path, name, buf);
|
||||
+ if (r < 0)
|
||||
+ log_unit_full(u, IN_SET(r, -ENOENT, -EROFS, -EACCES) ? LOG_DEBUG : LOG_WARNING, r,
|
||||
+ "Failed to set %s: %m", name);
|
||||
+
|
||||
+}
|
||||
+
|
||||
static bool cgroup_context_has_io_config(CGroupContext *c) {
|
||||
return c->io_accounting ||
|
||||
c->io_weight != CGROUP_WEIGHT_INVALID ||
|
||||
@@ -766,6 +793,11 @@ static void cgroup_context_apply(
|
||||
}
|
||||
}
|
||||
|
||||
+ if ((apply_mask & CGROUP_MASK_CPUSET) && !is_root) {
|
||||
+ cgroup_apply_unified_cpuset(u, c->cpuset_cpus, "cpuset.cpus");
|
||||
+ cgroup_apply_unified_cpuset(u, c->cpuset_mems, "cpuset.mems");
|
||||
+ }
|
||||
+
|
||||
if (apply_mask & CGROUP_MASK_IO) {
|
||||
bool has_io = cgroup_context_has_io_config(c);
|
||||
bool has_blockio = cgroup_context_has_blockio_config(c);
|
||||
@@ -1068,6 +1100,9 @@ CGroupMask cgroup_context_get_mask(CGroupContext *c) {
|
||||
c->cpu_quota_per_sec_usec != USEC_INFINITY)
|
||||
mask |= CGROUP_MASK_CPUACCT | CGROUP_MASK_CPU;
|
||||
|
||||
+ if (c->cpuset_cpus.set || c->cpuset_mems.set)
|
||||
+ mask |= CGROUP_MASK_CPUSET;
|
||||
+
|
||||
if (cgroup_context_has_io_config(c) || cgroup_context_has_blockio_config(c))
|
||||
mask |= CGROUP_MASK_IO | CGROUP_MASK_BLKIO;
|
||||
|
||||
@@ -2697,4 +2732,32 @@ static const char* const cgroup_device_policy_table[_CGROUP_DEVICE_POLICY_MAX] =
|
||||
[CGROUP_STRICT] = "strict",
|
||||
};
|
||||
|
||||
+int unit_get_cpuset(Unit *u, CPUSet *cpus, const char *name) {
|
||||
+ _cleanup_free_ char *v = NULL;
|
||||
+ int r;
|
||||
+
|
||||
+ assert(u);
|
||||
+ assert(cpus);
|
||||
+
|
||||
+ if (!u->cgroup_path)
|
||||
+ return -ENODATA;
|
||||
+
|
||||
+ if ((u->cgroup_realized_mask & CGROUP_MASK_CPUSET) == 0)
|
||||
+ return -ENODATA;
|
||||
+
|
||||
+ r = cg_all_unified();
|
||||
+ if (r < 0)
|
||||
+ return r;
|
||||
+ if (r == 0)
|
||||
+ return -ENODATA;
|
||||
+ if (r > 0)
|
||||
+ r = cg_get_attribute("cpuset", u->cgroup_path, name, &v);
|
||||
+ if (r == -ENOENT)
|
||||
+ return -ENODATA;
|
||||
+ if (r < 0)
|
||||
+ return r;
|
||||
+
|
||||
+ return parse_cpu_set_full(v, cpus, false, NULL, NULL, 0, NULL);
|
||||
+}
|
||||
+
|
||||
DEFINE_STRING_TABLE_LOOKUP(cgroup_device_policy, CGroupDevicePolicy);
|
||||
diff --git a/src/core/cgroup.h b/src/core/cgroup.h
|
||||
index 2d2ff6fc3c..da10575394 100644
|
||||
--- a/src/core/cgroup.h
|
||||
+++ b/src/core/cgroup.h
|
||||
@@ -4,6 +4,7 @@
|
||||
#include <stdbool.h>
|
||||
|
||||
#include "cgroup-util.h"
|
||||
+#include "cpu-set-util.h"
|
||||
#include "ip-address-access.h"
|
||||
#include "list.h"
|
||||
#include "time-util.h"
|
||||
@@ -77,6 +78,9 @@ struct CGroupContext {
|
||||
uint64_t startup_cpu_weight;
|
||||
usec_t cpu_quota_per_sec_usec;
|
||||
|
||||
+ CPUSet cpuset_cpus;
|
||||
+ CPUSet cpuset_mems;
|
||||
+
|
||||
uint64_t io_weight;
|
||||
uint64_t startup_io_weight;
|
||||
LIST_HEAD(CGroupIODeviceWeight, io_device_weights);
|
||||
@@ -205,3 +209,4 @@ const char* cgroup_device_policy_to_string(CGroupDevicePolicy i) _const_;
|
||||
CGroupDevicePolicy cgroup_device_policy_from_string(const char *s) _pure_;
|
||||
|
||||
bool unit_cgroup_delegate(Unit *u);
|
||||
+int unit_get_cpuset(Unit *u, CPUSet *cpus, const char *name);
|
||||
diff --git a/src/core/dbus-cgroup.c b/src/core/dbus-cgroup.c
|
||||
index 540bc77aed..30d4e83932 100644
|
||||
--- a/src/core/dbus-cgroup.c
|
||||
+++ b/src/core/dbus-cgroup.c
|
||||
@@ -53,6 +53,27 @@ static int property_get_delegate_controllers(
|
||||
return sd_bus_message_close_container(reply);
|
||||
}
|
||||
|
||||
+static int property_get_cpuset(
|
||||
+ sd_bus *bus,
|
||||
+ const char *path,
|
||||
+ const char *interface,
|
||||
+ const char *property,
|
||||
+ sd_bus_message *reply,
|
||||
+ void *userdata,
|
||||
+ sd_bus_error *error) {
|
||||
+
|
||||
+ CPUSet *cpus = userdata;
|
||||
+ _cleanup_free_ uint8_t *array = NULL;
|
||||
+ size_t allocated;
|
||||
+
|
||||
+ assert(bus);
|
||||
+ assert(reply);
|
||||
+ assert(cpus);
|
||||
+
|
||||
+ (void) cpu_set_to_dbus(cpus, &array, &allocated);
|
||||
+ return sd_bus_message_append_array(reply, 'y', array, allocated);
|
||||
+}
|
||||
+
|
||||
static int property_get_io_device_weight(
|
||||
sd_bus *bus,
|
||||
const char *path,
|
||||
@@ -283,6 +304,8 @@ const sd_bus_vtable bus_cgroup_vtable[] = {
|
||||
SD_BUS_PROPERTY("CPUShares", "t", NULL, offsetof(CGroupContext, cpu_shares), 0),
|
||||
SD_BUS_PROPERTY("StartupCPUShares", "t", NULL, offsetof(CGroupContext, startup_cpu_shares), 0),
|
||||
SD_BUS_PROPERTY("CPUQuotaPerSecUSec", "t", bus_property_get_usec, offsetof(CGroupContext, cpu_quota_per_sec_usec), 0),
|
||||
+ SD_BUS_PROPERTY("AllowedCPUs", "ay", property_get_cpuset, offsetof(CGroupContext, cpuset_cpus), 0),
|
||||
+ SD_BUS_PROPERTY("AllowedMemoryNodes", "ay", property_get_cpuset, offsetof(CGroupContext, cpuset_mems), 0),
|
||||
SD_BUS_PROPERTY("IOAccounting", "b", bus_property_get_bool, offsetof(CGroupContext, io_accounting), 0),
|
||||
SD_BUS_PROPERTY("IOWeight", "t", NULL, offsetof(CGroupContext, io_weight), 0),
|
||||
SD_BUS_PROPERTY("StartupIOWeight", "t", NULL, offsetof(CGroupContext, startup_io_weight), 0),
|
||||
@@ -671,6 +694,42 @@ int bus_cgroup_set_property(
|
||||
|
||||
return 1;
|
||||
|
||||
+ } else if (STR_IN_SET(name, "AllowedCPUs", "AllowedMemoryNodes")) {
|
||||
+ const void *a;
|
||||
+ size_t n;
|
||||
+ _cleanup_(cpu_set_reset) CPUSet new_set = {};
|
||||
+
|
||||
+ r = sd_bus_message_read_array(message, 'y', &a, &n);
|
||||
+ if (r < 0)
|
||||
+ return r;
|
||||
+
|
||||
+ r = cpu_set_from_dbus(a, n, &new_set);
|
||||
+ if (r < 0)
|
||||
+ return r;
|
||||
+
|
||||
+ if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
|
||||
+ _cleanup_free_ char *setstr = NULL;
|
||||
+ _cleanup_free_ char *data = NULL;
|
||||
+ CPUSet *set;
|
||||
+
|
||||
+ setstr = cpu_set_to_range_string(&new_set);
|
||||
+
|
||||
+ if (streq(name, "AllowedCPUs"))
|
||||
+ set = &c->cpuset_cpus;
|
||||
+ else
|
||||
+ set = &c->cpuset_mems;
|
||||
+
|
||||
+ if (asprintf(&data, "%s=%s", name, setstr) < 0)
|
||||
+ return -ENOMEM;
|
||||
+
|
||||
+ cpu_set_reset(set);
|
||||
+ cpu_set_add_all(set, &new_set);
|
||||
+ unit_invalidate_cgroup(u, CGROUP_MASK_CPUSET);
|
||||
+ unit_write_setting(u, flags, name, data);
|
||||
+ }
|
||||
+
|
||||
+ return 1;
|
||||
+
|
||||
} else if ((iol_type = cgroup_io_limit_type_from_string(name)) >= 0) {
|
||||
const char *path;
|
||||
unsigned n = 0;
|
||||
diff --git a/src/core/dbus-unit.c b/src/core/dbus-unit.c
|
||||
index c5bca10979..aa15e47754 100644
|
||||
--- a/src/core/dbus-unit.c
|
||||
+++ b/src/core/dbus-unit.c
|
||||
@@ -752,6 +752,52 @@ static int property_get_cpu_usage(
|
||||
return sd_bus_message_append(reply, "t", ns);
|
||||
}
|
||||
|
||||
+static int property_get_cpuset_cpus(
|
||||
+ sd_bus *bus,
|
||||
+ const char *path,
|
||||
+ const char *interface,
|
||||
+ const char *property,
|
||||
+ sd_bus_message *reply,
|
||||
+ void *userdata,
|
||||
+ sd_bus_error *error) {
|
||||
+
|
||||
+ Unit *u = userdata;
|
||||
+ _cleanup_(cpu_set_reset) CPUSet cpus = {};
|
||||
+ _cleanup_free_ uint8_t *array = NULL;
|
||||
+ size_t allocated;
|
||||
+
|
||||
+ assert(bus);
|
||||
+ assert(reply);
|
||||
+ assert(u);
|
||||
+
|
||||
+ (void) unit_get_cpuset(u, &cpus, "cpuset.cpus.effective");
|
||||
+ (void) cpu_set_to_dbus(&cpus, &array, &allocated);
|
||||
+ return sd_bus_message_append_array(reply, 'y', array, allocated);
|
||||
+}
|
||||
+
|
||||
+static int property_get_cpuset_mems(
|
||||
+ sd_bus *bus,
|
||||
+ const char *path,
|
||||
+ const char *interface,
|
||||
+ const char *property,
|
||||
+ sd_bus_message *reply,
|
||||
+ void *userdata,
|
||||
+ sd_bus_error *error) {
|
||||
+
|
||||
+ Unit *u = userdata;
|
||||
+ _cleanup_(cpu_set_reset) CPUSet mems = {};
|
||||
+ _cleanup_free_ uint8_t *array = NULL;
|
||||
+ size_t allocated;
|
||||
+
|
||||
+ assert(bus);
|
||||
+ assert(reply);
|
||||
+ assert(u);
|
||||
+
|
||||
+ (void) unit_get_cpuset(u, &mems, "cpuset.mems.effective");
|
||||
+ (void) cpu_set_to_dbus(&mems, &array, &allocated);
|
||||
+ return sd_bus_message_append_array(reply, 'y', array, allocated);
|
||||
+}
|
||||
+
|
||||
static int property_get_cgroup(
|
||||
sd_bus *bus,
|
||||
const char *path,
|
||||
@@ -1074,6 +1120,8 @@ const sd_bus_vtable bus_unit_cgroup_vtable[] = {
|
||||
SD_BUS_PROPERTY("ControlGroup", "s", property_get_cgroup, 0, 0),
|
||||
SD_BUS_PROPERTY("MemoryCurrent", "t", property_get_current_memory, 0, 0),
|
||||
SD_BUS_PROPERTY("CPUUsageNSec", "t", property_get_cpu_usage, 0, 0),
|
||||
+ SD_BUS_PROPERTY("EffectiveCPUs", "ay", property_get_cpuset_cpus, 0, 0),
|
||||
+ SD_BUS_PROPERTY("EffectiveMemoryNodes", "ay", property_get_cpuset_mems, 0, 0),
|
||||
SD_BUS_PROPERTY("TasksCurrent", "t", property_get_current_tasks, 0, 0),
|
||||
SD_BUS_PROPERTY("IPIngressBytes", "t", property_get_ip_counter, 0, 0),
|
||||
SD_BUS_PROPERTY("IPIngressPackets", "t", property_get_ip_counter, 0, 0),
|
||||
diff --git a/src/core/load-fragment-gperf.gperf.m4 b/src/core/load-fragment-gperf.gperf.m4
|
||||
index 49e938d0ce..ebb44df487 100644
|
||||
--- a/src/core/load-fragment-gperf.gperf.m4
|
||||
+++ b/src/core/load-fragment-gperf.gperf.m4
|
||||
@@ -167,6 +167,8 @@ $1.StartupCPUWeight, config_parse_cg_weight, 0,
|
||||
$1.CPUShares, config_parse_cpu_shares, 0, offsetof($1, cgroup_context.cpu_shares)
|
||||
$1.StartupCPUShares, config_parse_cpu_shares, 0, offsetof($1, cgroup_context.startup_cpu_shares)
|
||||
$1.CPUQuota, config_parse_cpu_quota, 0, offsetof($1, cgroup_context)
|
||||
+$1.CPUSetCpus, config_parse_cpuset_cpus, 0, offsetof($1, cgroup_context)
|
||||
+$1.CPUSetMems, config_parse_cpuset_mems, 0, offsetof($1, cgroup_context)
|
||||
$1.MemoryAccounting, config_parse_bool, 0, offsetof($1, cgroup_context.memory_accounting)
|
||||
$1.MemoryLow, config_parse_memory_limit, 0, offsetof($1, cgroup_context)
|
||||
$1.MemoryHigh, config_parse_memory_limit, 0, offsetof($1, cgroup_context)
|
||||
diff --git a/src/core/load-fragment.c b/src/core/load-fragment.c
|
||||
index 35dd595098..6debf82401 100644
|
||||
--- a/src/core/load-fragment.c
|
||||
+++ b/src/core/load-fragment.c
|
||||
@@ -3011,6 +3011,44 @@ int config_parse_cpu_quota(
|
||||
return 0;
|
||||
}
|
||||
|
||||
+int config_parse_cpuset_cpus(
|
||||
+ const char *unit,
|
||||
+ const char *filename,
|
||||
+ unsigned line,
|
||||
+ const char *section,
|
||||
+ unsigned section_line,
|
||||
+ const char *lvalue,
|
||||
+ int ltype,
|
||||
+ const char *rvalue,
|
||||
+ void *data,
|
||||
+ void *userdata) {
|
||||
+
|
||||
+ CGroupContext *c = data;
|
||||
+
|
||||
+ (void) parse_cpu_set_extend(rvalue, &c->cpuset_cpus, true, unit, filename, line, lvalue);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+int config_parse_cpuset_mems(
|
||||
+ const char *unit,
|
||||
+ const char *filename,
|
||||
+ unsigned line,
|
||||
+ const char *section,
|
||||
+ unsigned section_line,
|
||||
+ const char *lvalue,
|
||||
+ int ltype,
|
||||
+ const char *rvalue,
|
||||
+ void *data,
|
||||
+ void *userdata) {
|
||||
+
|
||||
+ CGroupContext *c = data;
|
||||
+
|
||||
+ (void) parse_cpu_set_extend(rvalue, &c->cpuset_mems, true, unit, filename, line, lvalue);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
int config_parse_memory_limit(
|
||||
const char *unit,
|
||||
const char *filename,
|
||||
diff --git a/src/core/load-fragment.h b/src/core/load-fragment.h
|
||||
index f2ca1b8ee7..6612e1fb32 100644
|
||||
--- a/src/core/load-fragment.h
|
||||
+++ b/src/core/load-fragment.h
|
||||
@@ -86,6 +86,8 @@ CONFIG_PARSER_PROTOTYPE(config_parse_set_status);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_namespace_path_strv);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_temporary_filesystems);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_cpu_quota);
|
||||
+CONFIG_PARSER_PROTOTYPE(config_parse_cpuset_cpus);
|
||||
+CONFIG_PARSER_PROTOTYPE(config_parse_cpuset_mems);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_protect_home);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_protect_system);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_bus_name);
|
||||
diff --git a/src/shared/bus-unit-util.c b/src/shared/bus-unit-util.c
|
||||
index 3c42e97b7a..8f3b463c6b 100644
|
||||
--- a/src/shared/bus-unit-util.c
|
||||
+++ b/src/shared/bus-unit-util.c
|
||||
@@ -396,6 +396,22 @@ static int bus_append_cgroup_property(sd_bus_message *m, const char *field, cons
|
||||
|
||||
return bus_append_cg_cpu_shares_parse(m, field, eq);
|
||||
|
||||
+ if (STR_IN_SET(field, "AllowedCPUs", "AllowedMemoryNodes")) {
|
||||
+ _cleanup_(cpu_set_reset) CPUSet cpuset = {};
|
||||
+ _cleanup_free_ uint8_t *array = NULL;
|
||||
+ size_t allocated;
|
||||
+
|
||||
+ r = parse_cpu_set(eq, &cpuset);
|
||||
+ if (r < 0)
|
||||
+ return log_error_errno(r, "Failed to parse %s value: %s", field, eq);
|
||||
+
|
||||
+ r = cpu_set_to_dbus(&cpuset, &array, &allocated);
|
||||
+ if (r < 0)
|
||||
+ return log_error_errno(r, "Failed to serialize CPUSet: %m");
|
||||
+
|
||||
+ return bus_append_byte_array(m, field, array, allocated);
|
||||
+ }
|
||||
+
|
||||
if (STR_IN_SET(field, "BlockIOWeight", "StartupBlockIOWeight"))
|
||||
|
||||
return bus_append_cg_blkio_weight_parse(m, field, eq);
|
||||
diff --git a/src/systemctl/systemctl.c b/src/systemctl/systemctl.c
|
||||
index 7274921e6d..a3074bc5e3 100644
|
||||
--- a/src/systemctl/systemctl.c
|
||||
+++ b/src/systemctl/systemctl.c
|
||||
@@ -4892,7 +4892,7 @@ static int print_property(const char *name, sd_bus_message *m, bool value, bool
|
||||
print_prop(name, "%s", h);
|
||||
|
||||
return 1;
|
||||
- } else if (contents[0] == SD_BUS_TYPE_BYTE && STR_IN_SET(name, "CPUAffinity", "NUMAMask")) {
|
||||
+ } else if (contents[0] == SD_BUS_TYPE_BYTE && STR_IN_SET(name, "CPUAffinity", "NUMAMask", "AllowedCPUs", "AllowedMemoryNodes", "EffectiveCPUs", "EffectiveMemoryNodes")) {
|
||||
_cleanup_free_ char *affinity = NULL;
|
||||
_cleanup_(cpu_set_reset) CPUSet set = {};
|
||||
const void *a;
|
||||
diff --git a/src/test/test-cgroup-mask.c b/src/test/test-cgroup-mask.c
|
||||
index d65959edf1..93c3f5d856 100644
|
||||
--- a/src/test/test-cgroup-mask.c
|
||||
+++ b/src/test/test-cgroup-mask.c
|
||||
@@ -104,9 +104,10 @@ static void test_cg_mask_to_string_one(CGroupMask mask, const char *t) {
|
||||
|
||||
static void test_cg_mask_to_string(void) {
|
||||
test_cg_mask_to_string_one(0, NULL);
|
||||
- test_cg_mask_to_string_one(_CGROUP_MASK_ALL, "cpu cpuacct io blkio memory devices pids");
|
||||
+ test_cg_mask_to_string_one(_CGROUP_MASK_ALL, "cpu cpuacct cpuset io blkio memory devices pids");
|
||||
test_cg_mask_to_string_one(CGROUP_MASK_CPU, "cpu");
|
||||
test_cg_mask_to_string_one(CGROUP_MASK_CPUACCT, "cpuacct");
|
||||
+ test_cg_mask_to_string_one(CGROUP_MASK_CPUSET, "cpuset");
|
||||
test_cg_mask_to_string_one(CGROUP_MASK_IO, "io");
|
||||
test_cg_mask_to_string_one(CGROUP_MASK_BLKIO, "blkio");
|
||||
test_cg_mask_to_string_one(CGROUP_MASK_MEMORY, "memory");
|
38
SOURCES/0331-pid1-fix-DefaultTasksMax-initialization.patch
Normal file
38
SOURCES/0331-pid1-fix-DefaultTasksMax-initialization.patch
Normal file
@ -0,0 +1,38 @@
|
||||
From e809564cfa5af01a26075682d49f81a987c41dd8 Mon Sep 17 00:00:00 2001
|
||||
From: Franck Bui <fbui@suse.com>
|
||||
Date: Wed, 2 Oct 2019 11:58:16 +0200
|
||||
Subject: [PATCH] pid1: fix DefaultTasksMax initialization
|
||||
|
||||
Otherwise DefaultTasksMax is always set to "inifinity".
|
||||
|
||||
This was broken by fb39af4ce42.
|
||||
|
||||
(cherry picked from commit c0000de87d2c7934cb1f4ba66a533a85277600ff)
|
||||
|
||||
Resolves: #1809037
|
||||
---
|
||||
src/core/main.c | 4 +---
|
||||
1 file changed, 1 insertion(+), 3 deletions(-)
|
||||
|
||||
diff --git a/src/core/main.c b/src/core/main.c
|
||||
index d6550ea161..45d09b1e11 100644
|
||||
--- a/src/core/main.c
|
||||
+++ b/src/core/main.c
|
||||
@@ -2088,7 +2088,7 @@ static void reset_arguments(void) {
|
||||
arg_default_blockio_accounting = false;
|
||||
arg_default_memory_accounting = MEMORY_ACCOUNTING_DEFAULT;
|
||||
arg_default_tasks_accounting = true;
|
||||
- arg_default_tasks_max = UINT64_MAX;
|
||||
+ arg_default_tasks_max = system_tasks_max_scale(DEFAULT_TASKS_MAX_PERCENTAGE, 100U);
|
||||
arg_machine_id = (sd_id128_t) {};
|
||||
arg_cad_burst_action = EMERGENCY_ACTION_REBOOT_FORCE;
|
||||
|
||||
@@ -2103,8 +2103,6 @@ static int parse_configuration(const struct rlimit *saved_rlimit_nofile,
|
||||
assert(saved_rlimit_nofile);
|
||||
assert(saved_rlimit_memlock);
|
||||
|
||||
- arg_default_tasks_max = system_tasks_max_scale(DEFAULT_TASKS_MAX_PERCENTAGE, 100U);
|
||||
-
|
||||
/* Assign configuration defaults */
|
||||
reset_arguments();
|
||||
|
@ -0,0 +1,40 @@
|
||||
From 5fc2d94fbf8271bb340e834f832af5d890c267bf Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Michal=20Sekleta=CC=81r?= <msekleta@redhat.com>
|
||||
Date: Tue, 3 Mar 2020 11:45:00 +0100
|
||||
Subject: [PATCH] cgroup: make sure that cpuset is supported on cgroup v2 and
|
||||
disabled with v1
|
||||
|
||||
Resolves: #1808940
|
||||
|
||||
(rhel-only)
|
||||
---
|
||||
src/basic/cgroup-util.c | 7 +++++--
|
||||
1 file changed, 5 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/src/basic/cgroup-util.c b/src/basic/cgroup-util.c
|
||||
index 6f47c3aacb..92bc1f2543 100644
|
||||
--- a/src/basic/cgroup-util.c
|
||||
+++ b/src/basic/cgroup-util.c
|
||||
@@ -2353,10 +2353,10 @@ int cg_mask_supported(CGroupMask *ret) {
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
- /* Currently, we support the cpu, memory, io and pids
|
||||
+ /* Currently, we support the cpu, memory, io, pids and cpuset
|
||||
* controller in the unified hierarchy, mask
|
||||
* everything else off. */
|
||||
- mask &= CGROUP_MASK_CPU | CGROUP_MASK_MEMORY | CGROUP_MASK_IO | CGROUP_MASK_PIDS;
|
||||
+ mask &= CGROUP_MASK_CPU | CGROUP_MASK_MEMORY | CGROUP_MASK_IO | CGROUP_MASK_PIDS | CGROUP_MASK_CPUSET;
|
||||
|
||||
} else {
|
||||
CGroupController c;
|
||||
@@ -2367,6 +2367,9 @@ int cg_mask_supported(CGroupMask *ret) {
|
||||
for (c = 0; c < _CGROUP_CONTROLLER_MAX; c++) {
|
||||
const char *n;
|
||||
|
||||
+ if (c == CGROUP_CONTROLLER_CPUSET)
|
||||
+ continue;
|
||||
+
|
||||
n = cgroup_controller_to_string(c);
|
||||
if (controller_is_accessible(n) >= 0)
|
||||
mask |= CGROUP_CONTROLLER_TO_MASK(c);
|
380
SOURCES/0333-test-introduce-TEST-36-NUMAPOLICY.patch
Normal file
380
SOURCES/0333-test-introduce-TEST-36-NUMAPOLICY.patch
Normal file
@ -0,0 +1,380 @@
|
||||
From 90dda340e4adeb1126639a849d4f31ae327fdc4b Mon Sep 17 00:00:00 2001
|
||||
From: Frantisek Sumsal <frantisek@sumsal.cz>
|
||||
Date: Tue, 25 Jun 2019 23:01:40 +0200
|
||||
Subject: [PATCH] test: introduce TEST-36-NUMAPOLICY
|
||||
|
||||
(cherry picked from commit 8f65e26508969610ac934d1aadbade8223bfcaac)
|
||||
|
||||
Related: #1808940
|
||||
---
|
||||
test/TEST-36-NUMAPOLICY/Makefile | 1 +
|
||||
test/TEST-36-NUMAPOLICY/test.sh | 51 +++++
|
||||
test/TEST-36-NUMAPOLICY/testsuite.sh | 292 +++++++++++++++++++++++++++
|
||||
3 files changed, 344 insertions(+)
|
||||
create mode 120000 test/TEST-36-NUMAPOLICY/Makefile
|
||||
create mode 100755 test/TEST-36-NUMAPOLICY/test.sh
|
||||
create mode 100755 test/TEST-36-NUMAPOLICY/testsuite.sh
|
||||
|
||||
diff --git a/test/TEST-36-NUMAPOLICY/Makefile b/test/TEST-36-NUMAPOLICY/Makefile
|
||||
new file mode 120000
|
||||
index 0000000000..e9f93b1104
|
||||
--- /dev/null
|
||||
+++ b/test/TEST-36-NUMAPOLICY/Makefile
|
||||
@@ -0,0 +1 @@
|
||||
+../TEST-01-BASIC/Makefile
|
||||
\ No newline at end of file
|
||||
diff --git a/test/TEST-36-NUMAPOLICY/test.sh b/test/TEST-36-NUMAPOLICY/test.sh
|
||||
new file mode 100755
|
||||
index 0000000000..a0d8623e8e
|
||||
--- /dev/null
|
||||
+++ b/test/TEST-36-NUMAPOLICY/test.sh
|
||||
@@ -0,0 +1,51 @@
|
||||
+#!/bin/bash
|
||||
+set -e
|
||||
+TEST_DESCRIPTION="test MUMAPolicy= and NUMAMask= options"
|
||||
+TEST_NO_NSPAWN=1
|
||||
+QEMU_OPTIONS="-numa node,nodeid=0"
|
||||
+
|
||||
+. $TEST_BASE_DIR/test-functions
|
||||
+
|
||||
+test_setup() {
|
||||
+ create_empty_image
|
||||
+ mkdir -p $TESTDIR/root
|
||||
+ mount ${LOOPDEV}p1 $TESTDIR/root
|
||||
+
|
||||
+ (
|
||||
+ LOG_LEVEL=5
|
||||
+ eval $(udevadm info --export --query=env --name=${LOOPDEV}p2)
|
||||
+
|
||||
+ setup_basic_environment
|
||||
+ inst_binary mktemp
|
||||
+
|
||||
+ # mask some services that we do not want to run in these tests
|
||||
+ ln -fs /dev/null $initdir/etc/systemd/system/systemd-hwdb-update.service
|
||||
+ ln -fs /dev/null $initdir/etc/systemd/system/systemd-journal-catalog-update.service
|
||||
+ ln -fs /dev/null $initdir/etc/systemd/system/systemd-networkd.service
|
||||
+ ln -fs /dev/null $initdir/etc/systemd/system/systemd-networkd.socket
|
||||
+ ln -fs /dev/null $initdir/etc/systemd/system/systemd-resolved.service
|
||||
+ ln -fs /dev/null $initdir/etc/systemd/system/systemd-machined.service
|
||||
+
|
||||
+ # setup the testsuite service
|
||||
+ cat >$initdir/etc/systemd/system/testsuite.service <<EOF
|
||||
+[Unit]
|
||||
+Description=Testsuite service
|
||||
+
|
||||
+[Service]
|
||||
+ExecStart=/bin/bash -x /testsuite.sh
|
||||
+Type=oneshot
|
||||
+StandardOutput=tty
|
||||
+StandardError=tty
|
||||
+NotifyAccess=all
|
||||
+EOF
|
||||
+ cp testsuite.sh $initdir/
|
||||
+
|
||||
+ setup_testsuite
|
||||
+ ) || return 1
|
||||
+ setup_nspawn_root
|
||||
+
|
||||
+ ddebug "umount $TESTDIR/root"
|
||||
+ umount $TESTDIR/root
|
||||
+}
|
||||
+
|
||||
+do_test "$@"
|
||||
diff --git a/test/TEST-36-NUMAPOLICY/testsuite.sh b/test/TEST-36-NUMAPOLICY/testsuite.sh
|
||||
new file mode 100755
|
||||
index 0000000000..e15087b137
|
||||
--- /dev/null
|
||||
+++ b/test/TEST-36-NUMAPOLICY/testsuite.sh
|
||||
@@ -0,0 +1,292 @@
|
||||
+#!/bin/bash
|
||||
+set -ex
|
||||
+set -o pipefail
|
||||
+
|
||||
+at_exit() {
|
||||
+ if [ $? -ne 0 ]; then
|
||||
+ # We're exiting with a non-zero EC, let's dump test artifacts
|
||||
+ # for easier debugging
|
||||
+ [ -f "$straceLog" ] && cat "$straceLog"
|
||||
+ [ -f "$journalLog" ] && cat "$journalLog"
|
||||
+ fi
|
||||
+}
|
||||
+
|
||||
+trap at_exit EXIT
|
||||
+
|
||||
+systemd-analyze log-level debug
|
||||
+systemd-analyze log-target journal
|
||||
+
|
||||
+# Log files
|
||||
+straceLog='strace.log'
|
||||
+journalLog='journal.log'
|
||||
+
|
||||
+# Systemd config files
|
||||
+testUnit='numa-test.service'
|
||||
+testUnitFile="/etc/systemd/system/$testUnit"
|
||||
+testUnitNUMAConf="$testUnitFile.d/numa.conf"
|
||||
+
|
||||
+# Sleep constants (we should probably figure out something better but nothing comes to mind)
|
||||
+journalSleep=5
|
||||
+sleepAfterStart=1
|
||||
+
|
||||
+startStrace() {
|
||||
+ coproc strace -qq -p 1 -o $straceLog -e set_mempolicy -s 1024 $1
|
||||
+}
|
||||
+
|
||||
+stopStrace() {
|
||||
+ kill -s TERM $COPROC_PID
|
||||
+}
|
||||
+
|
||||
+startJournalctl() {
|
||||
+ coproc journalctl -u init.scope -f > $journalLog
|
||||
+}
|
||||
+
|
||||
+stopJournalctl() {
|
||||
+ # Wait a few seconds until the messages get properly queued...
|
||||
+ sleep $journalSleep
|
||||
+ # ...and then force journald to write them to the backing storage
|
||||
+ # Also, using journalctl --sync should be better than using SIGRTMIN+1, as
|
||||
+ # the --sync wait until the synchronization is complete
|
||||
+ echo "Force journald to write all queued messages"
|
||||
+ journalctl --sync
|
||||
+ kill -s TERM $COPROC_PID
|
||||
+}
|
||||
+
|
||||
+checkNUMA() {
|
||||
+ # NUMA enabled system should have at least NUMA node0
|
||||
+ test -e /sys/devices/system/node/node0
|
||||
+}
|
||||
+
|
||||
+writePID1NUMAPolicy() {
|
||||
+ echo [Manager] > $confDir/numa.conf
|
||||
+ echo NUMAPolicy=$1 >> $confDir/numa.conf
|
||||
+ echo NUMAMask=$2>> $confDir/numa.conf
|
||||
+}
|
||||
+
|
||||
+writeTestUnit() {
|
||||
+ echo [Service] > $testUnitFile
|
||||
+ echo ExecStart=/bin/sleep 3600 >> $testUnitFile
|
||||
+ mkdir -p $testUnitFile.d/
|
||||
+}
|
||||
+
|
||||
+writeTestUnitNUMAPolicy() {
|
||||
+ echo [Service] > $testUnitNUMAConf
|
||||
+ echo NUMAPolicy=$1 >> $testUnitNUMAConf
|
||||
+ echo NUMAMask=$2>> $testUnitNUMAConf
|
||||
+ systemctl daemon-reload
|
||||
+}
|
||||
+
|
||||
+pid1ReloadWithStrace() {
|
||||
+ startStrace
|
||||
+ systemctl daemon-reload
|
||||
+ stopStrace
|
||||
+}
|
||||
+
|
||||
+pid1ReloadWithJournal() {
|
||||
+ startJournalctl
|
||||
+ systemctl daemon-reload
|
||||
+ stopJournalctl
|
||||
+}
|
||||
+
|
||||
+pid1StartUnitWithStrace() {
|
||||
+ startStrace '-f'
|
||||
+ systemctl start $1
|
||||
+ sleep $sleepAfterStart
|
||||
+ stopStrace
|
||||
+}
|
||||
+
|
||||
+pid1StartUnitWithJournal() {
|
||||
+ startJournalctl
|
||||
+ systemctl start $1
|
||||
+ sleep $sleepAfterStart
|
||||
+ stopJournalctl
|
||||
+}
|
||||
+
|
||||
+pid1StopUnit() {
|
||||
+ systemctl stop $1
|
||||
+}
|
||||
+
|
||||
+systemctlCheckNUMAProperties() {
|
||||
+ local LOGFILE="$(mktemp)"
|
||||
+ systemctl show -p NUMAPolicy $1 > "$LOGFILE"
|
||||
+ grep "NUMAPolicy=$2" "$LOGFILE"
|
||||
+
|
||||
+ > "$LOGFILE"
|
||||
+
|
||||
+ if [ -n $3 ]; then
|
||||
+ systemctl show -p NUMAMask $1 > "$LOGFILE"
|
||||
+ grep "NUMAMask=$3" "$LOGFILE"
|
||||
+ fi
|
||||
+}
|
||||
+
|
||||
+checkNUMA
|
||||
+writeTestUnit
|
||||
+
|
||||
+# Create systemd config drop-in directory
|
||||
+confDir="/etc/systemd/system.conf.d/"
|
||||
+mkdir -p "$confDir"
|
||||
+
|
||||
+echo "PID1 NUMAPolicy support - Default policy w/o mask"
|
||||
+writePID1NUMAPolicy "default"
|
||||
+pid1ReloadWithStrace
|
||||
+# Kernel requires that nodemask argument is set to NULL when setting default policy
|
||||
+grep "set_mempolicy(MPOL_DEFAULT, NULL" $straceLog
|
||||
+
|
||||
+echo "PID1 NUMAPolicy support - Default policy w/ mask"
|
||||
+writePID1NUMAPolicy "default" "0"
|
||||
+pid1ReloadWithStrace
|
||||
+grep "set_mempolicy(MPOL_DEFAULT, NULL" $straceLog
|
||||
+
|
||||
+echo "PID1 NUMAPolicy support - Bind policy w/o mask"
|
||||
+writePID1NUMAPolicy "bind"
|
||||
+pid1ReloadWithJournal
|
||||
+grep "Failed to set NUMA memory policy: Invalid argument" $journalLog
|
||||
+
|
||||
+echo "PID1 NUMAPolicy support - Bind policy w/ mask"
|
||||
+writePID1NUMAPolicy "bind" "0"
|
||||
+pid1ReloadWithStrace
|
||||
+grep -P "set_mempolicy\(MPOL_BIND, \[0x0*1\]" $straceLog
|
||||
+
|
||||
+echo "PID1 NUMAPolicy support - Interleave policy w/o mask"
|
||||
+writePID1NUMAPolicy "interleave"
|
||||
+pid1ReloadWithJournal
|
||||
+grep "Failed to set NUMA memory policy: Invalid argument" $journalLog
|
||||
+
|
||||
+echo "PID1 NUMAPolicy support - Interleave policy w/ mask"
|
||||
+writePID1NUMAPolicy "interleave" "0"
|
||||
+pid1ReloadWithStrace
|
||||
+grep -P "set_mempolicy\(MPOL_INTERLEAVE, \[0x0*1\]" $straceLog
|
||||
+
|
||||
+echo "PID1 NUMAPolicy support - Preferred policy w/o mask"
|
||||
+writePID1NUMAPolicy "preferred"
|
||||
+pid1ReloadWithJournal
|
||||
+# Preferred policy with empty node mask is actually allowed and should reset allocation policy to default
|
||||
+! grep "Failed to set NUMA memory policy: Invalid argument" $journalLog
|
||||
+
|
||||
+echo "PID1 NUMAPolicy support - Preferred policy w/ mask"
|
||||
+writePID1NUMAPolicy "preferred" "0"
|
||||
+pid1ReloadWithStrace
|
||||
+grep -P "set_mempolicy\(MPOL_PREFERRED, \[0x0*1\]" $straceLog
|
||||
+
|
||||
+echo "PID1 NUMAPolicy support - Local policy w/o mask"
|
||||
+writePID1NUMAPolicy "local"
|
||||
+pid1ReloadWithStrace
|
||||
+# Kernel requires that nodemask argument is set to NULL when setting default policy
|
||||
+grep "set_mempolicy(MPOL_LOCAL, NULL" $straceLog
|
||||
+
|
||||
+echo "PID1 NUMAPolicy support - Local policy w/ mask"
|
||||
+writePID1NUMAPolicy "local" "0"
|
||||
+pid1ReloadWithStrace
|
||||
+grep "set_mempolicy(MPOL_LOCAL, NULL" $straceLog
|
||||
+
|
||||
+echo "Unit file NUMAPolicy support - Default policy w/o mask"
|
||||
+writeTestUnitNUMAPolicy "default"
|
||||
+pid1StartUnitWithStrace $testUnit
|
||||
+systemctlCheckNUMAProperties $testUnit "default"
|
||||
+pid1StopUnit $testUnit
|
||||
+grep "set_mempolicy(MPOL_DEFAULT, NULL" $straceLog
|
||||
+
|
||||
+echo "Unit file NUMAPolicy support - Default policy w/ mask"
|
||||
+writeTestUnitNUMAPolicy "default" "0"
|
||||
+pid1StartUnitWithStrace $testUnit
|
||||
+systemctlCheckNUMAProperties $testUnit "default" "0"
|
||||
+pid1StopUnit $testUnit
|
||||
+# Maks must be ignored
|
||||
+grep "set_mempolicy(MPOL_DEFAULT, NULL" $straceLog
|
||||
+
|
||||
+echo "Unit file NUMAPolicy support - Bind policy w/o mask"
|
||||
+writeTestUnitNUMAPolicy "bind"
|
||||
+pid1StartUnitWithJournal $testUnit
|
||||
+pid1StopUnit $testUnit
|
||||
+grep "numa-test.service: Main process exited, code=exited, status=242/NUMA" $journalLog
|
||||
+
|
||||
+echo "Unit file NUMAPolicy support - Bind policy w/ mask"
|
||||
+writeTestUnitNUMAPolicy "bind" "0"
|
||||
+pid1StartUnitWithStrace $testUnit
|
||||
+systemctlCheckNUMAProperties $testUnit "bind" "0"
|
||||
+pid1StopUnit $testUnit
|
||||
+grep -P "set_mempolicy\(MPOL_BIND, \[0x0*1\]" $straceLog
|
||||
+
|
||||
+echo "Unit file NUMAPolicy support - Interleave policy w/o mask"
|
||||
+writeTestUnitNUMAPolicy "interleave"
|
||||
+pid1StartUnitWithStrace $testUnit
|
||||
+pid1StopUnit $testUnit
|
||||
+grep "numa-test.service: Main process exited, code=exited, status=242/NUMA" $journalLog
|
||||
+
|
||||
+echo "Unit file NUMAPolicy support - Interleave policy w/ mask"
|
||||
+writeTestUnitNUMAPolicy "interleave" "0"
|
||||
+pid1StartUnitWithStrace $testUnit
|
||||
+systemctlCheckNUMAProperties $testUnit "interleave" "0"
|
||||
+pid1StopUnit $testUnit
|
||||
+grep -P "set_mempolicy\(MPOL_INTERLEAVE, \[0x0*1\]" $straceLog
|
||||
+
|
||||
+echo "Unit file NUMAPolicy support - Preferred policy w/o mask"
|
||||
+writeTestUnitNUMAPolicy "preferred"
|
||||
+pid1StartUnitWithJournal $testUnit
|
||||
+systemctlCheckNUMAProperties $testUnit "preferred"
|
||||
+pid1StopUnit $testUnit
|
||||
+! grep "numa-test.service: Main process exited, code=exited, status=242/NUMA" $journalLog
|
||||
+
|
||||
+echo "Unit file NUMAPolicy support - Preferred policy w/ mask"
|
||||
+writeTestUnitNUMAPolicy "preferred" "0"
|
||||
+pid1StartUnitWithStrace $testUnit
|
||||
+systemctlCheckNUMAProperties $testUnit "preferred" "0"
|
||||
+pid1StopUnit $testUnit
|
||||
+grep -P "set_mempolicy\(MPOL_PREFERRED, \[0x0*1\]" $straceLog
|
||||
+
|
||||
+echo "Unit file NUMAPolicy support - Local policy w/o mask"
|
||||
+writeTestUnitNUMAPolicy "local"
|
||||
+pid1StartUnitWithStrace $testUnit
|
||||
+systemctlCheckNUMAProperties $testUnit "local"
|
||||
+pid1StopUnit $testUnit
|
||||
+grep "set_mempolicy(MPOL_LOCAL, NULL" $straceLog
|
||||
+
|
||||
+echo "Unit file NUMAPolicy support - Local policy w/ mask"
|
||||
+writeTestUnitNUMAPolicy "local" "0"
|
||||
+pid1StartUnitWithStrace $testUnit
|
||||
+systemctlCheckNUMAProperties $testUnit "local" "0"
|
||||
+pid1StopUnit $testUnit
|
||||
+# Maks must be ignored
|
||||
+grep "set_mempolicy(MPOL_LOCAL, NULL" $straceLog
|
||||
+
|
||||
+echo "systemd-run NUMAPolicy support"
|
||||
+runUnit='numa-systemd-run-test.service'
|
||||
+
|
||||
+systemd-run -p NUMAPolicy=default --unit $runUnit sleep 1000
|
||||
+systemctlCheckNUMAProperties $runUnit "default"
|
||||
+pid1StopUnit $runUnit
|
||||
+
|
||||
+systemd-run -p NUMAPolicy=default -p NUMAMask=0 --unit $runUnit sleep 1000
|
||||
+systemctlCheckNUMAProperties $runUnit "default" ""
|
||||
+pid1StopUnit $runUnit
|
||||
+
|
||||
+systemd-run -p NUMAPolicy=bind -p NUMAMask=0 --unit $runUnit sleep 1000
|
||||
+systemctlCheckNUMAProperties $runUnit "bind" "0"
|
||||
+pid1StopUnit $runUnit
|
||||
+
|
||||
+systemd-run -p NUMAPolicy=interleave -p NUMAMask=0 --unit $runUnit sleep 1000
|
||||
+systemctlCheckNUMAProperties $runUnit "interleave" "0"
|
||||
+pid1StopUnit $runUnit
|
||||
+
|
||||
+systemd-run -p NUMAPolicy=preferred -p NUMAMask=0 --unit $runUnit sleep 1000
|
||||
+systemctlCheckNUMAProperties $runUnit "preferred" "0"
|
||||
+pid1StopUnit $runUnit
|
||||
+
|
||||
+systemd-run -p NUMAPolicy=local --unit $runUnit sleep 1000
|
||||
+systemctlCheckNUMAProperties $runUnit "local"
|
||||
+pid1StopUnit $runUnit
|
||||
+
|
||||
+systemd-run -p NUMAPolicy=local -p NUMAMask=0 --unit $runUnit sleep 1000
|
||||
+systemctlCheckNUMAProperties $runUnit "local" ""
|
||||
+pid1StopUnit $runUnit
|
||||
+
|
||||
+# Cleanup
|
||||
+rm -rf $testDir
|
||||
+rm -rf $confDir
|
||||
+systemctl daemon-reload
|
||||
+
|
||||
+systemd-analyze log-level info
|
||||
+
|
||||
+echo OK > /testok
|
||||
+
|
||||
+exit 0
|
@ -0,0 +1,52 @@
|
||||
From b93a2617d49d9636801130d974995cabe6335b71 Mon Sep 17 00:00:00 2001
|
||||
From: Frantisek Sumsal <frantisek@sumsal.cz>
|
||||
Date: Mon, 1 Jul 2019 09:27:59 +0200
|
||||
Subject: [PATCH] test: replace `tail -f` with journal cursor which should
|
||||
be...
|
||||
|
||||
more reliable
|
||||
|
||||
(cherry picked from commit d0b2178f3e79f302702bd7140766eee03643f734)
|
||||
|
||||
Related: #1808940
|
||||
---
|
||||
test/TEST-36-NUMAPOLICY/testsuite.sh | 13 +++++++------
|
||||
1 file changed, 7 insertions(+), 6 deletions(-)
|
||||
|
||||
diff --git a/test/TEST-36-NUMAPOLICY/testsuite.sh b/test/TEST-36-NUMAPOLICY/testsuite.sh
|
||||
index e15087b137..306a96b517 100755
|
||||
--- a/test/TEST-36-NUMAPOLICY/testsuite.sh
|
||||
+++ b/test/TEST-36-NUMAPOLICY/testsuite.sh
|
||||
@@ -29,6 +29,9 @@ testUnitNUMAConf="$testUnitFile.d/numa.conf"
|
||||
journalSleep=5
|
||||
sleepAfterStart=1
|
||||
|
||||
+# Journal cursor for easier navigation
|
||||
+journalCursorFile="jounalCursorFile"
|
||||
+
|
||||
startStrace() {
|
||||
coproc strace -qq -p 1 -o $straceLog -e set_mempolicy -s 1024 $1
|
||||
}
|
||||
@@ -38,18 +41,16 @@ stopStrace() {
|
||||
}
|
||||
|
||||
startJournalctl() {
|
||||
- coproc journalctl -u init.scope -f > $journalLog
|
||||
+ # Save journal's cursor for later navigation
|
||||
+ journalctl --no-pager --cursor-file="$journalCursorFile" -n0 -ocat
|
||||
}
|
||||
|
||||
stopJournalctl() {
|
||||
- # Wait a few seconds until the messages get properly queued...
|
||||
- sleep $journalSleep
|
||||
- # ...and then force journald to write them to the backing storage
|
||||
- # Also, using journalctl --sync should be better than using SIGRTMIN+1, as
|
||||
+ # Using journalctl --sync should be better than using SIGRTMIN+1, as
|
||||
# the --sync wait until the synchronization is complete
|
||||
echo "Force journald to write all queued messages"
|
||||
journalctl --sync
|
||||
- kill -s TERM $COPROC_PID
|
||||
+ journalctl -u init.scope --cursor-file="$journalCursorFile" > "$journalLog"
|
||||
}
|
||||
|
||||
checkNUMA() {
|
@ -0,0 +1,58 @@
|
||||
From d6d43b81df76d571d57f83ceb050c8b4ac4701b8 Mon Sep 17 00:00:00 2001
|
||||
From: Frantisek Sumsal <frantisek@sumsal.cz>
|
||||
Date: Mon, 1 Jul 2019 13:08:26 +0200
|
||||
Subject: [PATCH] test: support MPOL_LOCAL matching in unpatched strace
|
||||
versions
|
||||
|
||||
The MPOL_LOCAL constant is not recognized in current strace versions.
|
||||
Let's match at least the numerical value of this constant until the
|
||||
strace patch is approved & merged.
|
||||
|
||||
(cherry picked from commit ac14396d027023e1be910327989cb422cb2f6724)
|
||||
|
||||
Related: #1808940
|
||||
---
|
||||
test/TEST-36-NUMAPOLICY/testsuite.sh | 12 ++++++++----
|
||||
1 file changed, 8 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/test/TEST-36-NUMAPOLICY/testsuite.sh b/test/TEST-36-NUMAPOLICY/testsuite.sh
|
||||
index 306a96b517..a4134bdeca 100755
|
||||
--- a/test/TEST-36-NUMAPOLICY/testsuite.sh
|
||||
+++ b/test/TEST-36-NUMAPOLICY/testsuite.sh
|
||||
@@ -173,12 +173,16 @@ echo "PID1 NUMAPolicy support - Local policy w/o mask"
|
||||
writePID1NUMAPolicy "local"
|
||||
pid1ReloadWithStrace
|
||||
# Kernel requires that nodemask argument is set to NULL when setting default policy
|
||||
-grep "set_mempolicy(MPOL_LOCAL, NULL" $straceLog
|
||||
+# The unpatched versions of strace don't recognize the MPOL_LOCAL constant and
|
||||
+# return a numerical constant instead (with a comment):
|
||||
+# set_mempolicy(0x4 /* MPOL_??? */, NULL, 0) = 0
|
||||
+# Let's cover this scenario as well
|
||||
+grep -E "set_mempolicy\((MPOL_LOCAL|0x4 [^,]*), NULL" $straceLog
|
||||
|
||||
echo "PID1 NUMAPolicy support - Local policy w/ mask"
|
||||
writePID1NUMAPolicy "local" "0"
|
||||
pid1ReloadWithStrace
|
||||
-grep "set_mempolicy(MPOL_LOCAL, NULL" $straceLog
|
||||
+grep -E "set_mempolicy\((MPOL_LOCAL|0x4 [^,]*), NULL" $straceLog
|
||||
|
||||
echo "Unit file NUMAPolicy support - Default policy w/o mask"
|
||||
writeTestUnitNUMAPolicy "default"
|
||||
@@ -240,7 +244,7 @@ writeTestUnitNUMAPolicy "local"
|
||||
pid1StartUnitWithStrace $testUnit
|
||||
systemctlCheckNUMAProperties $testUnit "local"
|
||||
pid1StopUnit $testUnit
|
||||
-grep "set_mempolicy(MPOL_LOCAL, NULL" $straceLog
|
||||
+grep -E "set_mempolicy\((MPOL_LOCAL|0x4 [^,]*), NULL" $straceLog
|
||||
|
||||
echo "Unit file NUMAPolicy support - Local policy w/ mask"
|
||||
writeTestUnitNUMAPolicy "local" "0"
|
||||
@@ -248,7 +252,7 @@ pid1StartUnitWithStrace $testUnit
|
||||
systemctlCheckNUMAProperties $testUnit "local" "0"
|
||||
pid1StopUnit $testUnit
|
||||
# Maks must be ignored
|
||||
-grep "set_mempolicy(MPOL_LOCAL, NULL" $straceLog
|
||||
+grep -E "set_mempolicy\((MPOL_LOCAL|0x4 [^,]*), NULL" $straceLog
|
||||
|
||||
echo "systemd-run NUMAPolicy support"
|
||||
runUnit='numa-systemd-run-test.service'
|
@ -0,0 +1,50 @@
|
||||
From 60813b55f9b5b44b14f38bbc1b8c0d2b30e3f6c7 Mon Sep 17 00:00:00 2001
|
||||
From: Frantisek Sumsal <frantisek@sumsal.cz>
|
||||
Date: Mon, 1 Jul 2019 19:53:45 +0200
|
||||
Subject: [PATCH] test: make sure the strace process is indeed dead
|
||||
|
||||
It may take a few moments for the strace process to properly terminate
|
||||
and write all logs to the backing storage
|
||||
|
||||
(cherry picked from commit 56425e54a2140f47b4560b51c5db08aa2de199a6)
|
||||
|
||||
Related: #1808940
|
||||
---
|
||||
test/TEST-36-NUMAPOLICY/test.sh | 2 +-
|
||||
test/TEST-36-NUMAPOLICY/testsuite.sh | 3 +++
|
||||
2 files changed, 4 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/test/TEST-36-NUMAPOLICY/test.sh b/test/TEST-36-NUMAPOLICY/test.sh
|
||||
index a0d8623e8e..f0a321e7a1 100755
|
||||
--- a/test/TEST-36-NUMAPOLICY/test.sh
|
||||
+++ b/test/TEST-36-NUMAPOLICY/test.sh
|
||||
@@ -16,7 +16,7 @@ test_setup() {
|
||||
eval $(udevadm info --export --query=env --name=${LOOPDEV}p2)
|
||||
|
||||
setup_basic_environment
|
||||
- inst_binary mktemp
|
||||
+ dracut_install mktemp
|
||||
|
||||
# mask some services that we do not want to run in these tests
|
||||
ln -fs /dev/null $initdir/etc/systemd/system/systemd-hwdb-update.service
|
||||
diff --git a/test/TEST-36-NUMAPOLICY/testsuite.sh b/test/TEST-36-NUMAPOLICY/testsuite.sh
|
||||
index a4134bdeca..daed8fcc1c 100755
|
||||
--- a/test/TEST-36-NUMAPOLICY/testsuite.sh
|
||||
+++ b/test/TEST-36-NUMAPOLICY/testsuite.sh
|
||||
@@ -38,6 +38,8 @@ startStrace() {
|
||||
|
||||
stopStrace() {
|
||||
kill -s TERM $COPROC_PID
|
||||
+ # Make sure the strace process is indeed dead
|
||||
+ while kill -0 $COPROC_PID 2>/dev/null; do sleep 0.1; done
|
||||
}
|
||||
|
||||
startJournalctl() {
|
||||
@@ -80,6 +82,7 @@ writeTestUnitNUMAPolicy() {
|
||||
pid1ReloadWithStrace() {
|
||||
startStrace
|
||||
systemctl daemon-reload
|
||||
+ sleep $sleepAfterStart
|
||||
stopStrace
|
||||
}
|
||||
|
@ -0,0 +1,36 @@
|
||||
From ad3e4a0f010c9497b01d89de54213af982f8afd2 Mon Sep 17 00:00:00 2001
|
||||
From: Frantisek Sumsal <frantisek@sumsal.cz>
|
||||
Date: Tue, 2 Jul 2019 09:52:45 +0200
|
||||
Subject: [PATCH] test: skip the test on systems without NUMA support
|
||||
|
||||
(cherry picked from commit b030847163e9bd63d3dd6eec6ac7f336411faba6)
|
||||
|
||||
Related: #1808940
|
||||
---
|
||||
test/TEST-36-NUMAPOLICY/testsuite.sh | 13 ++++++++++++-
|
||||
1 file changed, 12 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/test/TEST-36-NUMAPOLICY/testsuite.sh b/test/TEST-36-NUMAPOLICY/testsuite.sh
|
||||
index daed8fcc1c..4b715d305a 100755
|
||||
--- a/test/TEST-36-NUMAPOLICY/testsuite.sh
|
||||
+++ b/test/TEST-36-NUMAPOLICY/testsuite.sh
|
||||
@@ -123,7 +123,18 @@ systemctlCheckNUMAProperties() {
|
||||
fi
|
||||
}
|
||||
|
||||
-checkNUMA
|
||||
+if ! checkNUMA; then
|
||||
+ echo >&2 "NUMA is not supported on this machine, skipping the test"
|
||||
+
|
||||
+ # FIXME: add some sanity checks to verify systemd behaves correctly with
|
||||
+ # NUMA disabled together with NUMAPolicy= and NUMAMask=
|
||||
+
|
||||
+ systemd-analyze log-level info
|
||||
+ echo OK > /testok
|
||||
+
|
||||
+ exit 0
|
||||
+fi
|
||||
+
|
||||
writeTestUnit
|
||||
|
||||
# Create systemd config drop-in directory
|
30
SOURCES/0338-test-give-strace-some-time-to-initialize.patch
Normal file
30
SOURCES/0338-test-give-strace-some-time-to-initialize.patch
Normal file
@ -0,0 +1,30 @@
|
||||
From 66f6f6304d87b2fe0c4f91373c7d1b836de1b054 Mon Sep 17 00:00:00 2001
|
||||
From: Frantisek Sumsal <frantisek@sumsal.cz>
|
||||
Date: Tue, 23 Jul 2019 00:56:04 +0200
|
||||
Subject: [PATCH] test: give strace some time to initialize
|
||||
|
||||
The `coproc` implementation seems to be a little bit different in older
|
||||
bash versions, so the `strace` is sometimes started AFTER `systemctl
|
||||
daemon-reload`, which causes unexpected fails. Let's help it a little by
|
||||
sleeping for a bit.
|
||||
|
||||
(cherry picked from commit c7367d7cfdfdcec98f8659f0ed3f1d7b77123903)
|
||||
|
||||
Related: #1808940
|
||||
---
|
||||
test/TEST-36-NUMAPOLICY/testsuite.sh | 2 ++
|
||||
1 file changed, 2 insertions(+)
|
||||
|
||||
diff --git a/test/TEST-36-NUMAPOLICY/testsuite.sh b/test/TEST-36-NUMAPOLICY/testsuite.sh
|
||||
index 4b715d305a..1c8cf7e6b6 100755
|
||||
--- a/test/TEST-36-NUMAPOLICY/testsuite.sh
|
||||
+++ b/test/TEST-36-NUMAPOLICY/testsuite.sh
|
||||
@@ -34,6 +34,8 @@ journalCursorFile="jounalCursorFile"
|
||||
|
||||
startStrace() {
|
||||
coproc strace -qq -p 1 -o $straceLog -e set_mempolicy -s 1024 $1
|
||||
+ # Wait for strace to properly "initialize"
|
||||
+ sleep $sleepAfterStart
|
||||
}
|
||||
|
||||
stopStrace() {
|
@ -0,0 +1,391 @@
|
||||
From 8239ecf0b4b8bbe5b3c17964d230d13cee4d900a Mon Sep 17 00:00:00 2001
|
||||
From: Frantisek Sumsal <frantisek@sumsal.cz>
|
||||
Date: Mon, 5 Aug 2019 14:38:45 +0200
|
||||
Subject: [PATCH] test: add a simple sanity check for systems without NUMA
|
||||
support
|
||||
|
||||
(cherry picked from commit 92f8e978923f962a57d744c5f358520ac06f7892)
|
||||
|
||||
Related: #1808940
|
||||
---
|
||||
test/TEST-36-NUMAPOLICY/testsuite.sh | 350 ++++++++++++++-------------
|
||||
1 file changed, 180 insertions(+), 170 deletions(-)
|
||||
|
||||
diff --git a/test/TEST-36-NUMAPOLICY/testsuite.sh b/test/TEST-36-NUMAPOLICY/testsuite.sh
|
||||
index 1c8cf7e6b6..a5ac788178 100755
|
||||
--- a/test/TEST-36-NUMAPOLICY/testsuite.sh
|
||||
+++ b/test/TEST-36-NUMAPOLICY/testsuite.sh
|
||||
@@ -50,11 +50,12 @@ startJournalctl() {
|
||||
}
|
||||
|
||||
stopJournalctl() {
|
||||
+ local unit="${1:-init.scope}"
|
||||
# Using journalctl --sync should be better than using SIGRTMIN+1, as
|
||||
# the --sync wait until the synchronization is complete
|
||||
echo "Force journald to write all queued messages"
|
||||
journalctl --sync
|
||||
- journalctl -u init.scope --cursor-file="$journalCursorFile" > "$journalLog"
|
||||
+ journalctl -u $unit --cursor-file="$journalCursorFile" > "$journalLog"
|
||||
}
|
||||
|
||||
checkNUMA() {
|
||||
@@ -125,181 +126,190 @@ systemctlCheckNUMAProperties() {
|
||||
fi
|
||||
}
|
||||
|
||||
-if ! checkNUMA; then
|
||||
- echo >&2 "NUMA is not supported on this machine, skipping the test"
|
||||
-
|
||||
- # FIXME: add some sanity checks to verify systemd behaves correctly with
|
||||
- # NUMA disabled together with NUMAPolicy= and NUMAMask=
|
||||
-
|
||||
- systemd-analyze log-level info
|
||||
- echo OK > /testok
|
||||
-
|
||||
- exit 0
|
||||
-fi
|
||||
-
|
||||
writeTestUnit
|
||||
|
||||
# Create systemd config drop-in directory
|
||||
confDir="/etc/systemd/system.conf.d/"
|
||||
mkdir -p "$confDir"
|
||||
|
||||
-echo "PID1 NUMAPolicy support - Default policy w/o mask"
|
||||
-writePID1NUMAPolicy "default"
|
||||
-pid1ReloadWithStrace
|
||||
-# Kernel requires that nodemask argument is set to NULL when setting default policy
|
||||
-grep "set_mempolicy(MPOL_DEFAULT, NULL" $straceLog
|
||||
-
|
||||
-echo "PID1 NUMAPolicy support - Default policy w/ mask"
|
||||
-writePID1NUMAPolicy "default" "0"
|
||||
-pid1ReloadWithStrace
|
||||
-grep "set_mempolicy(MPOL_DEFAULT, NULL" $straceLog
|
||||
-
|
||||
-echo "PID1 NUMAPolicy support - Bind policy w/o mask"
|
||||
-writePID1NUMAPolicy "bind"
|
||||
-pid1ReloadWithJournal
|
||||
-grep "Failed to set NUMA memory policy: Invalid argument" $journalLog
|
||||
-
|
||||
-echo "PID1 NUMAPolicy support - Bind policy w/ mask"
|
||||
-writePID1NUMAPolicy "bind" "0"
|
||||
-pid1ReloadWithStrace
|
||||
-grep -P "set_mempolicy\(MPOL_BIND, \[0x0*1\]" $straceLog
|
||||
-
|
||||
-echo "PID1 NUMAPolicy support - Interleave policy w/o mask"
|
||||
-writePID1NUMAPolicy "interleave"
|
||||
-pid1ReloadWithJournal
|
||||
-grep "Failed to set NUMA memory policy: Invalid argument" $journalLog
|
||||
-
|
||||
-echo "PID1 NUMAPolicy support - Interleave policy w/ mask"
|
||||
-writePID1NUMAPolicy "interleave" "0"
|
||||
-pid1ReloadWithStrace
|
||||
-grep -P "set_mempolicy\(MPOL_INTERLEAVE, \[0x0*1\]" $straceLog
|
||||
-
|
||||
-echo "PID1 NUMAPolicy support - Preferred policy w/o mask"
|
||||
-writePID1NUMAPolicy "preferred"
|
||||
-pid1ReloadWithJournal
|
||||
-# Preferred policy with empty node mask is actually allowed and should reset allocation policy to default
|
||||
-! grep "Failed to set NUMA memory policy: Invalid argument" $journalLog
|
||||
-
|
||||
-echo "PID1 NUMAPolicy support - Preferred policy w/ mask"
|
||||
-writePID1NUMAPolicy "preferred" "0"
|
||||
-pid1ReloadWithStrace
|
||||
-grep -P "set_mempolicy\(MPOL_PREFERRED, \[0x0*1\]" $straceLog
|
||||
-
|
||||
-echo "PID1 NUMAPolicy support - Local policy w/o mask"
|
||||
-writePID1NUMAPolicy "local"
|
||||
-pid1ReloadWithStrace
|
||||
-# Kernel requires that nodemask argument is set to NULL when setting default policy
|
||||
-# The unpatched versions of strace don't recognize the MPOL_LOCAL constant and
|
||||
-# return a numerical constant instead (with a comment):
|
||||
-# set_mempolicy(0x4 /* MPOL_??? */, NULL, 0) = 0
|
||||
-# Let's cover this scenario as well
|
||||
-grep -E "set_mempolicy\((MPOL_LOCAL|0x4 [^,]*), NULL" $straceLog
|
||||
-
|
||||
-echo "PID1 NUMAPolicy support - Local policy w/ mask"
|
||||
-writePID1NUMAPolicy "local" "0"
|
||||
-pid1ReloadWithStrace
|
||||
-grep -E "set_mempolicy\((MPOL_LOCAL|0x4 [^,]*), NULL" $straceLog
|
||||
-
|
||||
-echo "Unit file NUMAPolicy support - Default policy w/o mask"
|
||||
-writeTestUnitNUMAPolicy "default"
|
||||
-pid1StartUnitWithStrace $testUnit
|
||||
-systemctlCheckNUMAProperties $testUnit "default"
|
||||
-pid1StopUnit $testUnit
|
||||
-grep "set_mempolicy(MPOL_DEFAULT, NULL" $straceLog
|
||||
-
|
||||
-echo "Unit file NUMAPolicy support - Default policy w/ mask"
|
||||
-writeTestUnitNUMAPolicy "default" "0"
|
||||
-pid1StartUnitWithStrace $testUnit
|
||||
-systemctlCheckNUMAProperties $testUnit "default" "0"
|
||||
-pid1StopUnit $testUnit
|
||||
-# Maks must be ignored
|
||||
-grep "set_mempolicy(MPOL_DEFAULT, NULL" $straceLog
|
||||
-
|
||||
-echo "Unit file NUMAPolicy support - Bind policy w/o mask"
|
||||
-writeTestUnitNUMAPolicy "bind"
|
||||
-pid1StartUnitWithJournal $testUnit
|
||||
-pid1StopUnit $testUnit
|
||||
-grep "numa-test.service: Main process exited, code=exited, status=242/NUMA" $journalLog
|
||||
-
|
||||
-echo "Unit file NUMAPolicy support - Bind policy w/ mask"
|
||||
-writeTestUnitNUMAPolicy "bind" "0"
|
||||
-pid1StartUnitWithStrace $testUnit
|
||||
-systemctlCheckNUMAProperties $testUnit "bind" "0"
|
||||
-pid1StopUnit $testUnit
|
||||
-grep -P "set_mempolicy\(MPOL_BIND, \[0x0*1\]" $straceLog
|
||||
-
|
||||
-echo "Unit file NUMAPolicy support - Interleave policy w/o mask"
|
||||
-writeTestUnitNUMAPolicy "interleave"
|
||||
-pid1StartUnitWithStrace $testUnit
|
||||
-pid1StopUnit $testUnit
|
||||
-grep "numa-test.service: Main process exited, code=exited, status=242/NUMA" $journalLog
|
||||
-
|
||||
-echo "Unit file NUMAPolicy support - Interleave policy w/ mask"
|
||||
-writeTestUnitNUMAPolicy "interleave" "0"
|
||||
-pid1StartUnitWithStrace $testUnit
|
||||
-systemctlCheckNUMAProperties $testUnit "interleave" "0"
|
||||
-pid1StopUnit $testUnit
|
||||
-grep -P "set_mempolicy\(MPOL_INTERLEAVE, \[0x0*1\]" $straceLog
|
||||
-
|
||||
-echo "Unit file NUMAPolicy support - Preferred policy w/o mask"
|
||||
-writeTestUnitNUMAPolicy "preferred"
|
||||
-pid1StartUnitWithJournal $testUnit
|
||||
-systemctlCheckNUMAProperties $testUnit "preferred"
|
||||
-pid1StopUnit $testUnit
|
||||
-! grep "numa-test.service: Main process exited, code=exited, status=242/NUMA" $journalLog
|
||||
-
|
||||
-echo "Unit file NUMAPolicy support - Preferred policy w/ mask"
|
||||
-writeTestUnitNUMAPolicy "preferred" "0"
|
||||
-pid1StartUnitWithStrace $testUnit
|
||||
-systemctlCheckNUMAProperties $testUnit "preferred" "0"
|
||||
-pid1StopUnit $testUnit
|
||||
-grep -P "set_mempolicy\(MPOL_PREFERRED, \[0x0*1\]" $straceLog
|
||||
-
|
||||
-echo "Unit file NUMAPolicy support - Local policy w/o mask"
|
||||
-writeTestUnitNUMAPolicy "local"
|
||||
-pid1StartUnitWithStrace $testUnit
|
||||
-systemctlCheckNUMAProperties $testUnit "local"
|
||||
-pid1StopUnit $testUnit
|
||||
-grep -E "set_mempolicy\((MPOL_LOCAL|0x4 [^,]*), NULL" $straceLog
|
||||
-
|
||||
-echo "Unit file NUMAPolicy support - Local policy w/ mask"
|
||||
-writeTestUnitNUMAPolicy "local" "0"
|
||||
-pid1StartUnitWithStrace $testUnit
|
||||
-systemctlCheckNUMAProperties $testUnit "local" "0"
|
||||
-pid1StopUnit $testUnit
|
||||
-# Maks must be ignored
|
||||
-grep -E "set_mempolicy\((MPOL_LOCAL|0x4 [^,]*), NULL" $straceLog
|
||||
-
|
||||
-echo "systemd-run NUMAPolicy support"
|
||||
-runUnit='numa-systemd-run-test.service'
|
||||
-
|
||||
-systemd-run -p NUMAPolicy=default --unit $runUnit sleep 1000
|
||||
-systemctlCheckNUMAProperties $runUnit "default"
|
||||
-pid1StopUnit $runUnit
|
||||
-
|
||||
-systemd-run -p NUMAPolicy=default -p NUMAMask=0 --unit $runUnit sleep 1000
|
||||
-systemctlCheckNUMAProperties $runUnit "default" ""
|
||||
-pid1StopUnit $runUnit
|
||||
-
|
||||
-systemd-run -p NUMAPolicy=bind -p NUMAMask=0 --unit $runUnit sleep 1000
|
||||
-systemctlCheckNUMAProperties $runUnit "bind" "0"
|
||||
-pid1StopUnit $runUnit
|
||||
-
|
||||
-systemd-run -p NUMAPolicy=interleave -p NUMAMask=0 --unit $runUnit sleep 1000
|
||||
-systemctlCheckNUMAProperties $runUnit "interleave" "0"
|
||||
-pid1StopUnit $runUnit
|
||||
-
|
||||
-systemd-run -p NUMAPolicy=preferred -p NUMAMask=0 --unit $runUnit sleep 1000
|
||||
-systemctlCheckNUMAProperties $runUnit "preferred" "0"
|
||||
-pid1StopUnit $runUnit
|
||||
-
|
||||
-systemd-run -p NUMAPolicy=local --unit $runUnit sleep 1000
|
||||
-systemctlCheckNUMAProperties $runUnit "local"
|
||||
-pid1StopUnit $runUnit
|
||||
-
|
||||
-systemd-run -p NUMAPolicy=local -p NUMAMask=0 --unit $runUnit sleep 1000
|
||||
-systemctlCheckNUMAProperties $runUnit "local" ""
|
||||
-pid1StopUnit $runUnit
|
||||
+if ! checkNUMA; then
|
||||
+ echo >&2 "NUMA is not supported on this machine, switching to a simple sanity check"
|
||||
+
|
||||
+ echo "PID1 NUMAPolicy=default && NUMAMask=0 check without NUMA support"
|
||||
+ writePID1NUMAPolicy "default" "0"
|
||||
+ startJournalctl
|
||||
+ systemctl daemon-reload
|
||||
+ stopJournalctl
|
||||
+ grep "NUMA support not available, ignoring" "$journalLog"
|
||||
+
|
||||
+ echo "systemd-run NUMAPolicy=default && NUMAMask=0 check without NUMA support"
|
||||
+ runUnit='numa-systemd-run-test.service'
|
||||
+ startJournalctl
|
||||
+ systemd-run -p NUMAPolicy=default -p NUMAMask=0 --unit $runUnit sleep 1000
|
||||
+ sleep $sleepAfterStart
|
||||
+ pid1StopUnit $runUnit
|
||||
+ stopJournalctl $runUnit
|
||||
+ grep "NUMA support not available, ignoring" "$journalLog"
|
||||
+
|
||||
+else
|
||||
+ echo "PID1 NUMAPolicy support - Default policy w/o mask"
|
||||
+ writePID1NUMAPolicy "default"
|
||||
+ pid1ReloadWithStrace
|
||||
+ # Kernel requires that nodemask argument is set to NULL when setting default policy
|
||||
+ grep "set_mempolicy(MPOL_DEFAULT, NULL" $straceLog
|
||||
+
|
||||
+ echo "PID1 NUMAPolicy support - Default policy w/ mask"
|
||||
+ writePID1NUMAPolicy "default" "0"
|
||||
+ pid1ReloadWithStrace
|
||||
+ grep "set_mempolicy(MPOL_DEFAULT, NULL" $straceLog
|
||||
+
|
||||
+ echo "PID1 NUMAPolicy support - Bind policy w/o mask"
|
||||
+ writePID1NUMAPolicy "bind"
|
||||
+ pid1ReloadWithJournal
|
||||
+ grep "Failed to set NUMA memory policy: Invalid argument" $journalLog
|
||||
+
|
||||
+ echo "PID1 NUMAPolicy support - Bind policy w/ mask"
|
||||
+ writePID1NUMAPolicy "bind" "0"
|
||||
+ pid1ReloadWithStrace
|
||||
+ grep -P "set_mempolicy\(MPOL_BIND, \[0x0*1\]" $straceLog
|
||||
+
|
||||
+ echo "PID1 NUMAPolicy support - Interleave policy w/o mask"
|
||||
+ writePID1NUMAPolicy "interleave"
|
||||
+ pid1ReloadWithJournal
|
||||
+ grep "Failed to set NUMA memory policy: Invalid argument" $journalLog
|
||||
+
|
||||
+ echo "PID1 NUMAPolicy support - Interleave policy w/ mask"
|
||||
+ writePID1NUMAPolicy "interleave" "0"
|
||||
+ pid1ReloadWithStrace
|
||||
+ grep -P "set_mempolicy\(MPOL_INTERLEAVE, \[0x0*1\]" $straceLog
|
||||
+
|
||||
+ echo "PID1 NUMAPolicy support - Preferred policy w/o mask"
|
||||
+ writePID1NUMAPolicy "preferred"
|
||||
+ pid1ReloadWithJournal
|
||||
+ # Preferred policy with empty node mask is actually allowed and should reset allocation policy to default
|
||||
+ ! grep "Failed to set NUMA memory policy: Invalid argument" $journalLog
|
||||
+
|
||||
+ echo "PID1 NUMAPolicy support - Preferred policy w/ mask"
|
||||
+ writePID1NUMAPolicy "preferred" "0"
|
||||
+ pid1ReloadWithStrace
|
||||
+ grep -P "set_mempolicy\(MPOL_PREFERRED, \[0x0*1\]" $straceLog
|
||||
+
|
||||
+ echo "PID1 NUMAPolicy support - Local policy w/o mask"
|
||||
+ writePID1NUMAPolicy "local"
|
||||
+ pid1ReloadWithStrace
|
||||
+ # Kernel requires that nodemask argument is set to NULL when setting default policy
|
||||
+ # The unpatched versions of strace don't recognize the MPOL_LOCAL constant and
|
||||
+ # return a numerical constant instead (with a comment):
|
||||
+ # set_mempolicy(0x4 /* MPOL_??? */, NULL, 0) = 0
|
||||
+ # Let's cover this scenario as well
|
||||
+ grep -E "set_mempolicy\((MPOL_LOCAL|0x4 [^,]*), NULL" $straceLog
|
||||
+
|
||||
+ echo "PID1 NUMAPolicy support - Local policy w/ mask"
|
||||
+ writePID1NUMAPolicy "local" "0"
|
||||
+ pid1ReloadWithStrace
|
||||
+ grep -E "set_mempolicy\((MPOL_LOCAL|0x4 [^,]*), NULL" $straceLog
|
||||
+
|
||||
+ echo "Unit file NUMAPolicy support - Default policy w/o mask"
|
||||
+ writeTestUnitNUMAPolicy "default"
|
||||
+ pid1StartUnitWithStrace $testUnit
|
||||
+ systemctlCheckNUMAProperties $testUnit "default"
|
||||
+ pid1StopUnit $testUnit
|
||||
+ grep "set_mempolicy(MPOL_DEFAULT, NULL" $straceLog
|
||||
+
|
||||
+ echo "Unit file NUMAPolicy support - Default policy w/ mask"
|
||||
+ writeTestUnitNUMAPolicy "default" "0"
|
||||
+ pid1StartUnitWithStrace $testUnit
|
||||
+ systemctlCheckNUMAProperties $testUnit "default" "0"
|
||||
+ pid1StopUnit $testUnit
|
||||
+ # Maks must be ignored
|
||||
+ grep "set_mempolicy(MPOL_DEFAULT, NULL" $straceLog
|
||||
+
|
||||
+ echo "Unit file NUMAPolicy support - Bind policy w/o mask"
|
||||
+ writeTestUnitNUMAPolicy "bind"
|
||||
+ pid1StartUnitWithJournal $testUnit
|
||||
+ pid1StopUnit $testUnit
|
||||
+ grep "numa-test.service: Main process exited, code=exited, status=242/NUMA" $journalLog
|
||||
+
|
||||
+ echo "Unit file NUMAPolicy support - Bind policy w/ mask"
|
||||
+ writeTestUnitNUMAPolicy "bind" "0"
|
||||
+ pid1StartUnitWithStrace $testUnit
|
||||
+ systemctlCheckNUMAProperties $testUnit "bind" "0"
|
||||
+ pid1StopUnit $testUnit
|
||||
+ grep -P "set_mempolicy\(MPOL_BIND, \[0x0*1\]" $straceLog
|
||||
+
|
||||
+ echo "Unit file NUMAPolicy support - Interleave policy w/o mask"
|
||||
+ writeTestUnitNUMAPolicy "interleave"
|
||||
+ pid1StartUnitWithStrace $testUnit
|
||||
+ pid1StopUnit $testUnit
|
||||
+ grep "numa-test.service: Main process exited, code=exited, status=242/NUMA" $journalLog
|
||||
+
|
||||
+ echo "Unit file NUMAPolicy support - Interleave policy w/ mask"
|
||||
+ writeTestUnitNUMAPolicy "interleave" "0"
|
||||
+ pid1StartUnitWithStrace $testUnit
|
||||
+ systemctlCheckNUMAProperties $testUnit "interleave" "0"
|
||||
+ pid1StopUnit $testUnit
|
||||
+ grep -P "set_mempolicy\(MPOL_INTERLEAVE, \[0x0*1\]" $straceLog
|
||||
+
|
||||
+ echo "Unit file NUMAPolicy support - Preferred policy w/o mask"
|
||||
+ writeTestUnitNUMAPolicy "preferred"
|
||||
+ pid1StartUnitWithJournal $testUnit
|
||||
+ systemctlCheckNUMAProperties $testUnit "preferred"
|
||||
+ pid1StopUnit $testUnit
|
||||
+ ! grep "numa-test.service: Main process exited, code=exited, status=242/NUMA" $journalLog
|
||||
+
|
||||
+ echo "Unit file NUMAPolicy support - Preferred policy w/ mask"
|
||||
+ writeTestUnitNUMAPolicy "preferred" "0"
|
||||
+ pid1StartUnitWithStrace $testUnit
|
||||
+ systemctlCheckNUMAProperties $testUnit "preferred" "0"
|
||||
+ pid1StopUnit $testUnit
|
||||
+ grep -P "set_mempolicy\(MPOL_PREFERRED, \[0x0*1\]" $straceLog
|
||||
+
|
||||
+ echo "Unit file NUMAPolicy support - Local policy w/o mask"
|
||||
+ writeTestUnitNUMAPolicy "local"
|
||||
+ pid1StartUnitWithStrace $testUnit
|
||||
+ systemctlCheckNUMAProperties $testUnit "local"
|
||||
+ pid1StopUnit $testUnit
|
||||
+ grep -E "set_mempolicy\((MPOL_LOCAL|0x4 [^,]*), NULL" $straceLog
|
||||
+
|
||||
+ echo "Unit file NUMAPolicy support - Local policy w/ mask"
|
||||
+ writeTestUnitNUMAPolicy "local" "0"
|
||||
+ pid1StartUnitWithStrace $testUnit
|
||||
+ systemctlCheckNUMAProperties $testUnit "local" "0"
|
||||
+ pid1StopUnit $testUnit
|
||||
+ # Maks must be ignored
|
||||
+ grep -E "set_mempolicy\((MPOL_LOCAL|0x4 [^,]*), NULL" $straceLog
|
||||
+
|
||||
+ echo "systemd-run NUMAPolicy support"
|
||||
+ runUnit='numa-systemd-run-test.service'
|
||||
+
|
||||
+ systemd-run -p NUMAPolicy=default --unit $runUnit sleep 1000
|
||||
+ systemctlCheckNUMAProperties $runUnit "default"
|
||||
+ pid1StopUnit $runUnit
|
||||
+
|
||||
+ systemd-run -p NUMAPolicy=default -p NUMAMask=0 --unit $runUnit sleep 1000
|
||||
+ systemctlCheckNUMAProperties $runUnit "default" ""
|
||||
+ pid1StopUnit $runUnit
|
||||
+
|
||||
+ systemd-run -p NUMAPolicy=bind -p NUMAMask=0 --unit $runUnit sleep 1000
|
||||
+ systemctlCheckNUMAProperties $runUnit "bind" "0"
|
||||
+ pid1StopUnit $runUnit
|
||||
+
|
||||
+ systemd-run -p NUMAPolicy=interleave -p NUMAMask=0 --unit $runUnit sleep 1000
|
||||
+ systemctlCheckNUMAProperties $runUnit "interleave" "0"
|
||||
+ pid1StopUnit $runUnit
|
||||
+
|
||||
+ systemd-run -p NUMAPolicy=preferred -p NUMAMask=0 --unit $runUnit sleep 1000
|
||||
+ systemctlCheckNUMAProperties $runUnit "preferred" "0"
|
||||
+ pid1StopUnit $runUnit
|
||||
+
|
||||
+ systemd-run -p NUMAPolicy=local --unit $runUnit sleep 1000
|
||||
+ systemctlCheckNUMAProperties $runUnit "local"
|
||||
+ pid1StopUnit $runUnit
|
||||
+
|
||||
+ systemd-run -p NUMAPolicy=local -p NUMAMask=0 --unit $runUnit sleep 1000
|
||||
+ systemctlCheckNUMAProperties $runUnit "local" ""
|
||||
+ pid1StopUnit $runUnit
|
||||
+fi
|
||||
|
||||
# Cleanup
|
||||
rm -rf $testDir
|
35
SOURCES/0340-test-drop-the-missed-exit-1-expression.patch
Normal file
35
SOURCES/0340-test-drop-the-missed-exit-1-expression.patch
Normal file
@ -0,0 +1,35 @@
|
||||
From 772f08f8255d7ab921c344ab4243249cbd1c37fc Mon Sep 17 00:00:00 2001
|
||||
From: Frantisek Sumsal <frantisek@sumsal.cz>
|
||||
Date: Sat, 10 Aug 2019 16:05:07 +0200
|
||||
Subject: [PATCH] test: drop the missed || exit 1 expression
|
||||
|
||||
...as we've already done in the rest of the testsuite, see
|
||||
cc469c3dfc398210f38f819d367e68646c71d8da
|
||||
|
||||
(cherry picked from commit 67c434b03f8a24f5350f017dfb4b2464406046db)
|
||||
|
||||
Related: #1808940
|
||||
---
|
||||
test/TEST-36-NUMAPOLICY/test.sh | 3 ++-
|
||||
1 file changed, 2 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/test/TEST-36-NUMAPOLICY/test.sh b/test/TEST-36-NUMAPOLICY/test.sh
|
||||
index f0a321e7a1..3b3b120423 100755
|
||||
--- a/test/TEST-36-NUMAPOLICY/test.sh
|
||||
+++ b/test/TEST-36-NUMAPOLICY/test.sh
|
||||
@@ -1,5 +1,6 @@
|
||||
#!/bin/bash
|
||||
set -e
|
||||
+
|
||||
TEST_DESCRIPTION="test MUMAPolicy= and NUMAMask= options"
|
||||
TEST_NO_NSPAWN=1
|
||||
QEMU_OPTIONS="-numa node,nodeid=0"
|
||||
@@ -41,7 +42,7 @@ EOF
|
||||
cp testsuite.sh $initdir/
|
||||
|
||||
setup_testsuite
|
||||
- ) || return 1
|
||||
+ )
|
||||
setup_nspawn_root
|
||||
|
||||
ddebug "umount $TESTDIR/root"
|
@ -0,0 +1,59 @@
|
||||
From 0bef8805c81eecfe3960bf00b6022837e4979198 Mon Sep 17 00:00:00 2001
|
||||
From: Frantisek Sumsal <fsumsal@redhat.com>
|
||||
Date: Tue, 3 Mar 2020 15:54:29 +0100
|
||||
Subject: [PATCH] test: replace cursor file with a plain cursor
|
||||
|
||||
systemd in RHEL 8 doesn't support the --cursor-file option, so let's
|
||||
fall back to a plain cursor string
|
||||
|
||||
Related: #1808940
|
||||
rhel-only
|
||||
---
|
||||
test/TEST-36-NUMAPOLICY/test.sh | 2 +-
|
||||
test/TEST-36-NUMAPOLICY/testsuite.sh | 6 +++---
|
||||
2 files changed, 4 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/test/TEST-36-NUMAPOLICY/test.sh b/test/TEST-36-NUMAPOLICY/test.sh
|
||||
index 3b3b120423..7cc909765b 100755
|
||||
--- a/test/TEST-36-NUMAPOLICY/test.sh
|
||||
+++ b/test/TEST-36-NUMAPOLICY/test.sh
|
||||
@@ -17,7 +17,7 @@ test_setup() {
|
||||
eval $(udevadm info --export --query=env --name=${LOOPDEV}p2)
|
||||
|
||||
setup_basic_environment
|
||||
- dracut_install mktemp
|
||||
+ dracut_install mktemp awk
|
||||
|
||||
# mask some services that we do not want to run in these tests
|
||||
ln -fs /dev/null $initdir/etc/systemd/system/systemd-hwdb-update.service
|
||||
diff --git a/test/TEST-36-NUMAPOLICY/testsuite.sh b/test/TEST-36-NUMAPOLICY/testsuite.sh
|
||||
index a5ac788178..bffac4ffe6 100755
|
||||
--- a/test/TEST-36-NUMAPOLICY/testsuite.sh
|
||||
+++ b/test/TEST-36-NUMAPOLICY/testsuite.sh
|
||||
@@ -30,7 +30,7 @@ journalSleep=5
|
||||
sleepAfterStart=1
|
||||
|
||||
# Journal cursor for easier navigation
|
||||
-journalCursorFile="jounalCursorFile"
|
||||
+journalCursor=""
|
||||
|
||||
startStrace() {
|
||||
coproc strace -qq -p 1 -o $straceLog -e set_mempolicy -s 1024 $1
|
||||
@@ -46,7 +46,7 @@ stopStrace() {
|
||||
|
||||
startJournalctl() {
|
||||
# Save journal's cursor for later navigation
|
||||
- journalctl --no-pager --cursor-file="$journalCursorFile" -n0 -ocat
|
||||
+ journalCursor="$(journalctl --no-pager --show-cursor -n0 -ocat | awk '{print $3}')"
|
||||
}
|
||||
|
||||
stopJournalctl() {
|
||||
@@ -55,7 +55,7 @@ stopJournalctl() {
|
||||
# the --sync wait until the synchronization is complete
|
||||
echo "Force journald to write all queued messages"
|
||||
journalctl --sync
|
||||
- journalctl -u $unit --cursor-file="$journalCursorFile" > "$journalLog"
|
||||
+ journalctl -u $unit --after-cursor="$journalCursor" > "$journalLog"
|
||||
}
|
||||
|
||||
checkNUMA() {
|
@ -0,0 +1,32 @@
|
||||
From ed282d8d84fa32aaef21994d92d1d3dbfa281094 Mon Sep 17 00:00:00 2001
|
||||
From: Ryan Gonzalez <kirbyfan64@users.noreply.github.com>
|
||||
Date: Fri, 22 Feb 2019 23:45:03 -0600
|
||||
Subject: [PATCH] cryptsetup: Treat key file errors as a failed password
|
||||
attempt
|
||||
|
||||
6f177c7dc092eb68762b4533d41b14244adb2a73 caused key file errors to immediately fail, which would make it hard to correct an issue due to e.g. a crypttab typo or a damaged key file.
|
||||
|
||||
Closes #11723.
|
||||
|
||||
(cherry picked from commit c20db3887569e0c0d9c0e2845c5286e7edf0133a)
|
||||
|
||||
Related: #1763155
|
||||
---
|
||||
src/cryptsetup/cryptsetup.c | 4 ++++
|
||||
1 file changed, 4 insertions(+)
|
||||
|
||||
diff --git a/src/cryptsetup/cryptsetup.c b/src/cryptsetup/cryptsetup.c
|
||||
index 33c215eaa1..11162eb722 100644
|
||||
--- a/src/cryptsetup/cryptsetup.c
|
||||
+++ b/src/cryptsetup/cryptsetup.c
|
||||
@@ -558,6 +558,10 @@ static int attach_luks_or_plain(struct crypt_device *cd,
|
||||
log_error_errno(r, "Failed to activate with key file '%s'. (Key data incorrect?)", key_file);
|
||||
return -EAGAIN; /* Log actual error, but return EAGAIN */
|
||||
}
|
||||
+ if (r == -EINVAL) {
|
||||
+ log_error_errno(r, "Failed to activate with key file '%s'. (Key file missing?)", key_file);
|
||||
+ return -EAGAIN; /* Log actual error, but return EAGAIN */
|
||||
+ }
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to activate with key file '%s': %m", key_file);
|
||||
} else {
|
@ -0,0 +1,79 @@
|
||||
From b89a1a9d19aa806feb984c8dba25116b5b5a52bc Mon Sep 17 00:00:00 2001
|
||||
From: HATAYAMA Daisuke <d.hatayama@fujitsu.com>
|
||||
Date: Wed, 24 Jul 2019 23:54:48 -0400
|
||||
Subject: [PATCH] swap: finish the secondary swap units' jobs if deactivation
|
||||
of the primary swap unit fails
|
||||
|
||||
Currently, if deactivation of the primary swap unit fails:
|
||||
|
||||
# LANG=C systemctl --no-pager stop dev-mapper-fedora\\x2dswap.swap
|
||||
Job for dev-mapper-fedora\x2dswap.swap failed.
|
||||
See "systemctl status "dev-mapper-fedora\\x2dswap.swap"" and "journalctl -xe" for details.
|
||||
|
||||
then there are still the running stop jobs for all the secondary swap units
|
||||
that follow the primary one:
|
||||
|
||||
# systemctl list-jobs
|
||||
JOB UNIT TYPE STATE
|
||||
3233 dev-disk-by\x2duuid-2dc8b9b1\x2da0a5\x2d44d8\x2d89c4\x2d6cdd26cd5ce0.swap stop running
|
||||
3232 dev-dm\x2d1.swap stop running
|
||||
3231 dev-disk-by\x2did-dm\x2duuid\x2dLVM\x2dyuXWpCCIurGzz2nkGCVnUFSi7GH6E3ZcQjkKLnF0Fil0RJmhoLN8fcOnDybWCMTj.swap stop running
|
||||
3230 dev-disk-by\x2did-dm\x2dname\x2dfedora\x2dswap.swap stop running
|
||||
3234 dev-fedora-swap.swap stop running
|
||||
|
||||
5 jobs listed.
|
||||
|
||||
This remains endlessly because their JobTimeoutUSec is infinity:
|
||||
|
||||
# LANG=C systemctl show -p JobTimeoutUSec dev-fedora-swap.swap
|
||||
JobTimeoutUSec=infinity
|
||||
|
||||
If this issue happens during system shutdown, the system shutdown appears to
|
||||
get hang and the system will be forcibly shutdown or rebooted 30 minutes later
|
||||
by the following configuration:
|
||||
|
||||
# grep -E "^JobTimeout" /usr/lib/systemd/system/reboot.target
|
||||
JobTimeoutSec=30min
|
||||
JobTimeoutAction=reboot-force
|
||||
|
||||
The scenario in the real world seems that there is some service unit with
|
||||
KillMode=none, processes whose memory is being swapped out are not killed
|
||||
during stop operation in the service unit and then swapoff command fails.
|
||||
|
||||
On the other hand, it works well in successful case of swapoff command because
|
||||
the secondary jobs monitor /proc/swaps file and can detect deletion of the
|
||||
corresponding swap file.
|
||||
|
||||
This commit fixes the issue by finishing the secondary swap units' jobs if
|
||||
deactivation of the primary swap unit fails.
|
||||
|
||||
Fixes: #11577
|
||||
(cherry picked from commit 9c1f969d40f84d5cc98d810bab8b24148b2d8928)
|
||||
|
||||
Resolves: #1749622
|
||||
---
|
||||
src/core/swap.c | 10 ++++++++--
|
||||
1 file changed, 8 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/src/core/swap.c b/src/core/swap.c
|
||||
index e717dbb54a..66a62d8a37 100644
|
||||
--- a/src/core/swap.c
|
||||
+++ b/src/core/swap.c
|
||||
@@ -682,9 +682,15 @@ static void swap_enter_active(Swap *s, SwapResult f) {
|
||||
static void swap_enter_dead_or_active(Swap *s, SwapResult f) {
|
||||
assert(s);
|
||||
|
||||
- if (s->from_proc_swaps)
|
||||
+ if (s->from_proc_swaps) {
|
||||
+ Swap *other;
|
||||
+
|
||||
swap_enter_active(s, f);
|
||||
- else
|
||||
+
|
||||
+ LIST_FOREACH_OTHERS(same_devnode, other, s)
|
||||
+ if (UNIT(other)->job)
|
||||
+ swap_enter_dead_or_active(other, f);
|
||||
+ } else
|
||||
swap_enter_dead(s, f);
|
||||
}
|
||||
|
@ -0,0 +1,41 @@
|
||||
From d9ae3222cfbd5d2a48e6dbade6617085cc76f1c1 Mon Sep 17 00:00:00 2001
|
||||
From: HATAYAMA Daisuke <d.hatayama@fujitsu.com>
|
||||
Date: Tue, 25 Feb 2020 13:35:50 -0500
|
||||
Subject: [PATCH] resolved: Recover missing PrivateTmp=yes and
|
||||
ProtectSystem=strict
|
||||
|
||||
Since the commit b61e8046ebcb28225423fc0073183d68d4c577c4,
|
||||
systemd-resolved.service often fails to start with the following message:
|
||||
|
||||
Failed at step NAMESPACE spawning /usr/bin/mount: Read-only file system
|
||||
|
||||
This is because dropping DynamicUser=yes dropped implicit PrivateTmp=yes and
|
||||
also implicit After=systemd-tmpfiles-setup.service, and thus
|
||||
systemd-resolved.service can start before systemd-remount-fs.service. As a
|
||||
result, mount operations associated with PrivateDevices= can be performed to
|
||||
still read-only filesystems.
|
||||
|
||||
To fix this issue, it's better to recover PrivateTmp=yes and
|
||||
ProtectSystem=strict just as the upstream commit
|
||||
62fb7e80fcc45a1530ed58a84980be8cfafa9b3e (Revert "resolve: enable DynamicUser=
|
||||
for systemd-resolved.service").
|
||||
|
||||
Resolves: #1810869
|
||||
---
|
||||
units/systemd-resolved.service.in | 2 ++
|
||||
1 file changed, 2 insertions(+)
|
||||
|
||||
diff --git a/units/systemd-resolved.service.in b/units/systemd-resolved.service.in
|
||||
index 6c2ad5ca86..aad1a53a5f 100644
|
||||
--- a/units/systemd-resolved.service.in
|
||||
+++ b/units/systemd-resolved.service.in
|
||||
@@ -28,7 +28,9 @@ WatchdogSec=3min
|
||||
User=systemd-resolve
|
||||
CapabilityBoundingSet=CAP_SETPCAP CAP_NET_RAW CAP_NET_BIND_SERVICE
|
||||
AmbientCapabilities=CAP_SETPCAP CAP_NET_RAW CAP_NET_BIND_SERVICE
|
||||
+PrivateTmp=yes
|
||||
PrivateDevices=yes
|
||||
+ProtectSystems=strict
|
||||
ProtectHome=yes
|
||||
ProtectControlGroups=yes
|
||||
ProtectKernelTunables=yes
|
@ -0,0 +1,30 @@
|
||||
From 448b34284c09469eaa2168291ccb34afc3e4cc1d Mon Sep 17 00:00:00 2001
|
||||
From: ven <2988994+hexiaowen@users.noreply.github.com>
|
||||
Date: Wed, 22 May 2019 14:24:28 +0800
|
||||
Subject: [PATCH] =?UTF-8?q?bus=5Fopen=20leak=20sd=5Fevent=5Fsource=20when?=
|
||||
=?UTF-8?q?=20udevadm=20trigger=E3=80=82?=
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
On my host, when executing the udevadm trigger, I only receive the change event, which causes memleak
|
||||
|
||||
(cherry picked from commit b2774a3ae692113e1f47a336a6c09bac9cfb49ad)
|
||||
|
||||
Resolves: #1798504
|
||||
---
|
||||
src/login/logind-button.c | 1 +
|
||||
1 file changed, 1 insertion(+)
|
||||
|
||||
diff --git a/src/login/logind-button.c b/src/login/logind-button.c
|
||||
index 0defa6b9ba..9944eb2316 100644
|
||||
--- a/src/login/logind-button.c
|
||||
+++ b/src/login/logind-button.c
|
||||
@@ -341,6 +341,7 @@ int button_open(Button *b) {
|
||||
|
||||
(void) button_set_mask(b);
|
||||
|
||||
+ b->io_event_source = sd_event_source_unref(b->io_event_source);
|
||||
r = sd_event_add_io(b->manager->event, &b->io_event_source, b->fd, EPOLLIN, button_dispatch, b);
|
||||
if (r < 0) {
|
||||
log_error_errno(r, "Failed to add button event: %m");
|
339
SOURCES/0346-core-rework-StopWhenUnneeded-logic.patch
Normal file
339
SOURCES/0346-core-rework-StopWhenUnneeded-logic.patch
Normal file
@ -0,0 +1,339 @@
|
||||
From 5458256264c97eee521caf07c705f549a0f0bd55 Mon Sep 17 00:00:00 2001
|
||||
From: Lennart Poettering <lennart@poettering.net>
|
||||
Date: Thu, 9 Aug 2018 16:26:27 +0200
|
||||
Subject: [PATCH] core: rework StopWhenUnneeded= logic
|
||||
|
||||
Previously, we'd act immediately on StopWhenUnneeded= when a unit state
|
||||
changes. With this rework we'll maintain a queue instead: whenever
|
||||
there's the chance that StopWhenUneeded= might have an effect we enqueue
|
||||
the unit, and process it later when we have nothing better to do.
|
||||
|
||||
This should make the implementation a bit more reliable, as the unit notify event
|
||||
cannot immediately enqueue tons of side-effect jobs that might
|
||||
contradict each other, but we do so only in a strictly ordered fashion,
|
||||
from the main event loop.
|
||||
|
||||
This slightly changes the check when to consider a unit "unneeded".
|
||||
Previously, we'd assume that a unit in "deactivating" state could also
|
||||
be cleaned up. With this new logic we'll only consider units unneeded
|
||||
that are fully up and have no job queued. This means that whenever
|
||||
there's something pending for a unit we won't clean it up.
|
||||
|
||||
(cherry picked from commit a3c1168ac293f16d9343d248795bb4c246aaff4a)
|
||||
|
||||
Resolves: #1798046
|
||||
---
|
||||
src/core/manager.c | 43 ++++++++++++++++
|
||||
src/core/manager.h | 3 ++
|
||||
src/core/unit.c | 122 +++++++++++++++++++++++++--------------------
|
||||
src/core/unit.h | 7 +++
|
||||
4 files changed, 120 insertions(+), 55 deletions(-)
|
||||
|
||||
diff --git a/src/core/manager.c b/src/core/manager.c
|
||||
index 0eae7d46fb..4c04896aaa 100644
|
||||
--- a/src/core/manager.c
|
||||
+++ b/src/core/manager.c
|
||||
@@ -1211,6 +1211,45 @@ static unsigned manager_dispatch_gc_job_queue(Manager *m) {
|
||||
return n;
|
||||
}
|
||||
|
||||
+static unsigned manager_dispatch_stop_when_unneeded_queue(Manager *m) {
|
||||
+ unsigned n = 0;
|
||||
+ Unit *u;
|
||||
+ int r;
|
||||
+
|
||||
+ assert(m);
|
||||
+
|
||||
+ while ((u = m->stop_when_unneeded_queue)) {
|
||||
+ _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
|
||||
+ assert(m->stop_when_unneeded_queue);
|
||||
+
|
||||
+ assert(u->in_stop_when_unneeded_queue);
|
||||
+ LIST_REMOVE(stop_when_unneeded_queue, m->stop_when_unneeded_queue, u);
|
||||
+ u->in_stop_when_unneeded_queue = false;
|
||||
+
|
||||
+ n++;
|
||||
+
|
||||
+ if (!unit_is_unneeded(u))
|
||||
+ continue;
|
||||
+
|
||||
+ log_unit_debug(u, "Unit is not needed anymore.");
|
||||
+
|
||||
+ /* If stopping a unit fails continuously we might enter a stop loop here, hence stop acting on the
|
||||
+ * service being unnecessary after a while. */
|
||||
+
|
||||
+ if (!ratelimit_below(&u->auto_stop_ratelimit)) {
|
||||
+ log_unit_warning(u, "Unit not needed anymore, but not stopping since we tried this too often recently.");
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
+ /* Ok, nobody needs us anymore. Sniff. Then let's commit suicide */
|
||||
+ r = manager_add_job(u->manager, JOB_STOP, u, JOB_FAIL, &error, NULL);
|
||||
+ if (r < 0)
|
||||
+ log_unit_warning_errno(u, r, "Failed to enqueue stop job, ignoring: %s", bus_error_message(&error, r));
|
||||
+ }
|
||||
+
|
||||
+ return n;
|
||||
+}
|
||||
+
|
||||
static void manager_clear_jobs_and_units(Manager *m) {
|
||||
Unit *u;
|
||||
|
||||
@@ -1228,6 +1267,7 @@ static void manager_clear_jobs_and_units(Manager *m) {
|
||||
assert(!m->cleanup_queue);
|
||||
assert(!m->gc_unit_queue);
|
||||
assert(!m->gc_job_queue);
|
||||
+ assert(!m->stop_when_unneeded_queue);
|
||||
|
||||
assert(hashmap_isempty(m->jobs));
|
||||
assert(hashmap_isempty(m->units));
|
||||
@@ -2824,6 +2864,9 @@ int manager_loop(Manager *m) {
|
||||
if (manager_dispatch_cgroup_realize_queue(m) > 0)
|
||||
continue;
|
||||
|
||||
+ if (manager_dispatch_stop_when_unneeded_queue(m) > 0)
|
||||
+ continue;
|
||||
+
|
||||
if (manager_dispatch_dbus_queue(m) > 0)
|
||||
continue;
|
||||
|
||||
diff --git a/src/core/manager.h b/src/core/manager.h
|
||||
index fa47952d24..40568d3c8b 100644
|
||||
--- a/src/core/manager.h
|
||||
+++ b/src/core/manager.h
|
||||
@@ -130,6 +130,9 @@ struct Manager {
|
||||
/* Target units whose default target dependencies haven't been set yet */
|
||||
LIST_HEAD(Unit, target_deps_queue);
|
||||
|
||||
+ /* Units that might be subject to StopWhenUnneeded= clean-up */
|
||||
+ LIST_HEAD(Unit, stop_when_unneeded_queue);
|
||||
+
|
||||
sd_event *event;
|
||||
|
||||
/* This maps PIDs we care about to units that are interested in. We allow multiple units to he interested in
|
||||
diff --git a/src/core/unit.c b/src/core/unit.c
|
||||
index e1f5e6f7bd..40f138d25c 100644
|
||||
--- a/src/core/unit.c
|
||||
+++ b/src/core/unit.c
|
||||
@@ -438,6 +438,22 @@ void unit_add_to_dbus_queue(Unit *u) {
|
||||
u->in_dbus_queue = true;
|
||||
}
|
||||
|
||||
+void unit_add_to_stop_when_unneeded_queue(Unit *u) {
|
||||
+ assert(u);
|
||||
+
|
||||
+ if (u->in_stop_when_unneeded_queue)
|
||||
+ return;
|
||||
+
|
||||
+ if (!u->stop_when_unneeded)
|
||||
+ return;
|
||||
+
|
||||
+ if (!UNIT_IS_ACTIVE_OR_RELOADING(unit_active_state(u)))
|
||||
+ return;
|
||||
+
|
||||
+ LIST_PREPEND(stop_when_unneeded_queue, u->manager->stop_when_unneeded_queue, u);
|
||||
+ u->in_stop_when_unneeded_queue = true;
|
||||
+}
|
||||
+
|
||||
static void bidi_set_free(Unit *u, Hashmap *h) {
|
||||
Unit *other;
|
||||
Iterator i;
|
||||
@@ -634,6 +650,9 @@ void unit_free(Unit *u) {
|
||||
if (u->in_target_deps_queue)
|
||||
LIST_REMOVE(target_deps_queue, u->manager->target_deps_queue, u);
|
||||
|
||||
+ if (u->in_stop_when_unneeded_queue)
|
||||
+ LIST_REMOVE(stop_when_unneeded_queue, u->manager->stop_when_unneeded_queue, u);
|
||||
+
|
||||
safe_close(u->ip_accounting_ingress_map_fd);
|
||||
safe_close(u->ip_accounting_egress_map_fd);
|
||||
|
||||
@@ -1950,55 +1969,71 @@ bool unit_can_reload(Unit *u) {
|
||||
return UNIT_VTABLE(u)->reload;
|
||||
}
|
||||
|
||||
-static void unit_check_unneeded(Unit *u) {
|
||||
-
|
||||
- _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
|
||||
-
|
||||
- static const UnitDependency needed_dependencies[] = {
|
||||
+bool unit_is_unneeded(Unit *u) {
|
||||
+ static const UnitDependency deps[] = {
|
||||
UNIT_REQUIRED_BY,
|
||||
UNIT_REQUISITE_OF,
|
||||
UNIT_WANTED_BY,
|
||||
UNIT_BOUND_BY,
|
||||
};
|
||||
-
|
||||
- unsigned j;
|
||||
- int r;
|
||||
+ size_t j;
|
||||
|
||||
assert(u);
|
||||
|
||||
- /* If this service shall be shut down when unneeded then do
|
||||
- * so. */
|
||||
-
|
||||
if (!u->stop_when_unneeded)
|
||||
- return;
|
||||
+ return false;
|
||||
|
||||
- if (!UNIT_IS_ACTIVE_OR_ACTIVATING(unit_active_state(u)))
|
||||
- return;
|
||||
+ /* Don't clean up while the unit is transitioning or is even inactive. */
|
||||
+ if (!UNIT_IS_ACTIVE_OR_RELOADING(unit_active_state(u)))
|
||||
+ return false;
|
||||
+ if (u->job)
|
||||
+ return false;
|
||||
|
||||
- for (j = 0; j < ELEMENTSOF(needed_dependencies); j++) {
|
||||
+ for (j = 0; j < ELEMENTSOF(deps); j++) {
|
||||
Unit *other;
|
||||
Iterator i;
|
||||
void *v;
|
||||
|
||||
- HASHMAP_FOREACH_KEY(v, other, u->dependencies[needed_dependencies[j]], i)
|
||||
- if (unit_active_or_pending(other) || unit_will_restart(other))
|
||||
- return;
|
||||
- }
|
||||
+ /* If a dependending unit has a job queued, or is active (or in transitioning), or is marked for
|
||||
+ * restart, then don't clean this one up. */
|
||||
|
||||
- /* If stopping a unit fails continuously we might enter a stop
|
||||
- * loop here, hence stop acting on the service being
|
||||
- * unnecessary after a while. */
|
||||
- if (!ratelimit_below(&u->auto_stop_ratelimit)) {
|
||||
- log_unit_warning(u, "Unit not needed anymore, but not stopping since we tried this too often recently.");
|
||||
- return;
|
||||
+ HASHMAP_FOREACH_KEY(v, other, u->dependencies[deps[j]], i) {
|
||||
+ if (u->job)
|
||||
+ return false;
|
||||
+
|
||||
+ if (!UNIT_IS_INACTIVE_OR_FAILED(unit_active_state(other)))
|
||||
+ return false;
|
||||
+
|
||||
+ if (unit_will_restart(other))
|
||||
+ return false;
|
||||
+ }
|
||||
}
|
||||
|
||||
- log_unit_info(u, "Unit not needed anymore. Stopping.");
|
||||
+ return true;
|
||||
+}
|
||||
|
||||
- /* Ok, nobody needs us anymore. Sniff. Then let's commit suicide */
|
||||
- r = manager_add_job(u->manager, JOB_STOP, u, JOB_FAIL, &error, NULL);
|
||||
- if (r < 0)
|
||||
- log_unit_warning_errno(u, r, "Failed to enqueue stop job, ignoring: %s", bus_error_message(&error, r));
|
||||
+static void check_unneeded_dependencies(Unit *u) {
|
||||
+
|
||||
+ static const UnitDependency deps[] = {
|
||||
+ UNIT_REQUIRES,
|
||||
+ UNIT_REQUISITE,
|
||||
+ UNIT_WANTS,
|
||||
+ UNIT_BINDS_TO,
|
||||
+ };
|
||||
+ size_t j;
|
||||
+
|
||||
+ assert(u);
|
||||
+
|
||||
+ /* Add all units this unit depends on to the queue that processes StopWhenUnneeded= behaviour. */
|
||||
+
|
||||
+ for (j = 0; j < ELEMENTSOF(deps); j++) {
|
||||
+ Unit *other;
|
||||
+ Iterator i;
|
||||
+ void *v;
|
||||
+
|
||||
+ HASHMAP_FOREACH_KEY(v, other, u->dependencies[deps[j]], i)
|
||||
+ unit_add_to_stop_when_unneeded_queue(other);
|
||||
+ }
|
||||
}
|
||||
|
||||
static void unit_check_binds_to(Unit *u) {
|
||||
@@ -2098,29 +2133,6 @@ static void retroactively_stop_dependencies(Unit *u) {
|
||||
manager_add_job(u->manager, JOB_STOP, other, JOB_REPLACE, NULL, NULL);
|
||||
}
|
||||
|
||||
-static void check_unneeded_dependencies(Unit *u) {
|
||||
- Unit *other;
|
||||
- Iterator i;
|
||||
- void *v;
|
||||
-
|
||||
- assert(u);
|
||||
- assert(UNIT_IS_INACTIVE_OR_DEACTIVATING(unit_active_state(u)));
|
||||
-
|
||||
- /* Garbage collect services that might not be needed anymore, if enabled */
|
||||
- HASHMAP_FOREACH_KEY(v, other, u->dependencies[UNIT_REQUIRES], i)
|
||||
- if (!UNIT_IS_INACTIVE_OR_DEACTIVATING(unit_active_state(other)))
|
||||
- unit_check_unneeded(other);
|
||||
- HASHMAP_FOREACH_KEY(v, other, u->dependencies[UNIT_WANTS], i)
|
||||
- if (!UNIT_IS_INACTIVE_OR_DEACTIVATING(unit_active_state(other)))
|
||||
- unit_check_unneeded(other);
|
||||
- HASHMAP_FOREACH_KEY(v, other, u->dependencies[UNIT_REQUISITE], i)
|
||||
- if (!UNIT_IS_INACTIVE_OR_DEACTIVATING(unit_active_state(other)))
|
||||
- unit_check_unneeded(other);
|
||||
- HASHMAP_FOREACH_KEY(v, other, u->dependencies[UNIT_BINDS_TO], i)
|
||||
- if (!UNIT_IS_INACTIVE_OR_DEACTIVATING(unit_active_state(other)))
|
||||
- unit_check_unneeded(other);
|
||||
-}
|
||||
-
|
||||
void unit_start_on_failure(Unit *u) {
|
||||
Unit *other;
|
||||
Iterator i;
|
||||
@@ -2423,7 +2435,7 @@ void unit_notify(Unit *u, UnitActiveState os, UnitActiveState ns, UnitNotifyFlag
|
||||
}
|
||||
|
||||
/* stop unneeded units regardless if going down was expected or not */
|
||||
- if (UNIT_IS_INACTIVE_OR_DEACTIVATING(ns))
|
||||
+ if (UNIT_IS_INACTIVE_OR_FAILED(ns))
|
||||
check_unneeded_dependencies(u);
|
||||
|
||||
if (ns != os && ns == UNIT_FAILED) {
|
||||
@@ -2483,7 +2495,7 @@ void unit_notify(Unit *u, UnitActiveState os, UnitActiveState ns, UnitNotifyFlag
|
||||
|
||||
if (!MANAGER_IS_RELOADING(u->manager)) {
|
||||
/* Maybe we finished startup and are now ready for being stopped because unneeded? */
|
||||
- unit_check_unneeded(u);
|
||||
+ unit_add_to_stop_when_unneeded_queue(u);
|
||||
|
||||
/* Maybe we finished startup, but something we needed has vanished? Let's die then. (This happens when
|
||||
* something BindsTo= to a Type=oneshot unit, as these units go directly from starting to inactive,
|
||||
diff --git a/src/core/unit.h b/src/core/unit.h
|
||||
index 99755823eb..595ee88d43 100644
|
||||
--- a/src/core/unit.h
|
||||
+++ b/src/core/unit.h
|
||||
@@ -212,6 +212,9 @@ typedef struct Unit {
|
||||
/* Target dependencies queue */
|
||||
LIST_FIELDS(Unit, target_deps_queue);
|
||||
|
||||
+ /* Queue of units with StopWhenUnneeded set that shell be checked for clean-up. */
|
||||
+ LIST_FIELDS(Unit, stop_when_unneeded_queue);
|
||||
+
|
||||
/* PIDs we keep an eye on. Note that a unit might have many
|
||||
* more, but these are the ones we care enough about to
|
||||
* process SIGCHLD for */
|
||||
@@ -322,6 +325,7 @@ typedef struct Unit {
|
||||
bool in_cgroup_realize_queue:1;
|
||||
bool in_cgroup_empty_queue:1;
|
||||
bool in_target_deps_queue:1;
|
||||
+ bool in_stop_when_unneeded_queue:1;
|
||||
|
||||
bool sent_dbus_new_signal:1;
|
||||
|
||||
@@ -615,6 +619,7 @@ void unit_add_to_dbus_queue(Unit *u);
|
||||
void unit_add_to_cleanup_queue(Unit *u);
|
||||
void unit_add_to_gc_queue(Unit *u);
|
||||
void unit_add_to_target_deps_queue(Unit *u);
|
||||
+void unit_add_to_stop_when_unneeded_queue(Unit *u);
|
||||
|
||||
int unit_merge(Unit *u, Unit *other);
|
||||
int unit_merge_by_name(Unit *u, const char *other);
|
||||
@@ -751,6 +756,8 @@ bool unit_type_supported(UnitType t);
|
||||
|
||||
bool unit_is_pristine(Unit *u);
|
||||
|
||||
+bool unit_is_unneeded(Unit *u);
|
||||
+
|
||||
pid_t unit_control_pid(Unit *u);
|
||||
pid_t unit_main_pid(Unit *u);
|
||||
|
@ -0,0 +1,81 @@
|
||||
From 6ecf0a945d6d4187995de7e79e3ed75f4827289a Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= <zbyszek@in.waw.pl>
|
||||
Date: Sun, 24 Nov 2019 14:14:43 +0100
|
||||
Subject: [PATCH] pid1: fix the names of AllowedCPUs= and AllowedMemoryNodes=
|
||||
|
||||
The original PR was submitted with CPUSetCpus and CPUSetMems, which was later
|
||||
changed to AllowedCPUs and AllowedMemmoryNodes everywhere (including the parser
|
||||
used by systemd-run), but not in the parser for unit files.
|
||||
|
||||
Since we already released -rc1, let's keep support for the old names. I think
|
||||
we can remove it in a release or two if anyone remembers to do that.
|
||||
|
||||
Fixes #14126. Follow-up for 047f5d63d7a1ab75073f8485e2f9b550d25b0772.
|
||||
|
||||
(cherry picked from commit 0b8d3075872a05e0449906d24421ce192f50c29f)
|
||||
|
||||
Related: #1818054
|
||||
---
|
||||
src/core/load-fragment-gperf.gperf.m4 | 4 ++--
|
||||
src/core/load-fragment.c | 4 ++--
|
||||
src/core/load-fragment.h | 4 ++--
|
||||
3 files changed, 6 insertions(+), 6 deletions(-)
|
||||
|
||||
diff --git a/src/core/load-fragment-gperf.gperf.m4 b/src/core/load-fragment-gperf.gperf.m4
|
||||
index ebb44df487..161c5a2c82 100644
|
||||
--- a/src/core/load-fragment-gperf.gperf.m4
|
||||
+++ b/src/core/load-fragment-gperf.gperf.m4
|
||||
@@ -161,14 +161,14 @@ $1.KillSignal, config_parse_signal, 0,
|
||||
)m4_dnl
|
||||
m4_define(`CGROUP_CONTEXT_CONFIG_ITEMS',
|
||||
`$1.Slice, config_parse_unit_slice, 0, 0
|
||||
+$1.AllowedCPUs, config_parse_allowed_cpus, 0, offsetof($1, cgroup_context)
|
||||
+$1.AllowedMemoryNodes, config_parse_allowed_mems, 0, offsetof($1, cgroup_context)
|
||||
$1.CPUAccounting, config_parse_bool, 0, offsetof($1, cgroup_context.cpu_accounting)
|
||||
$1.CPUWeight, config_parse_cg_weight, 0, offsetof($1, cgroup_context.cpu_weight)
|
||||
$1.StartupCPUWeight, config_parse_cg_weight, 0, offsetof($1, cgroup_context.startup_cpu_weight)
|
||||
$1.CPUShares, config_parse_cpu_shares, 0, offsetof($1, cgroup_context.cpu_shares)
|
||||
$1.StartupCPUShares, config_parse_cpu_shares, 0, offsetof($1, cgroup_context.startup_cpu_shares)
|
||||
$1.CPUQuota, config_parse_cpu_quota, 0, offsetof($1, cgroup_context)
|
||||
-$1.CPUSetCpus, config_parse_cpuset_cpus, 0, offsetof($1, cgroup_context)
|
||||
-$1.CPUSetMems, config_parse_cpuset_mems, 0, offsetof($1, cgroup_context)
|
||||
$1.MemoryAccounting, config_parse_bool, 0, offsetof($1, cgroup_context.memory_accounting)
|
||||
$1.MemoryLow, config_parse_memory_limit, 0, offsetof($1, cgroup_context)
|
||||
$1.MemoryHigh, config_parse_memory_limit, 0, offsetof($1, cgroup_context)
|
||||
diff --git a/src/core/load-fragment.c b/src/core/load-fragment.c
|
||||
index 6debf82401..2082166afb 100644
|
||||
--- a/src/core/load-fragment.c
|
||||
+++ b/src/core/load-fragment.c
|
||||
@@ -3011,7 +3011,7 @@ int config_parse_cpu_quota(
|
||||
return 0;
|
||||
}
|
||||
|
||||
-int config_parse_cpuset_cpus(
|
||||
+int config_parse_allowed_cpus(
|
||||
const char *unit,
|
||||
const char *filename,
|
||||
unsigned line,
|
||||
@@ -3030,7 +3030,7 @@ int config_parse_cpuset_cpus(
|
||||
return 0;
|
||||
}
|
||||
|
||||
-int config_parse_cpuset_mems(
|
||||
+int config_parse_allowed_mems(
|
||||
const char *unit,
|
||||
const char *filename,
|
||||
unsigned line,
|
||||
diff --git a/src/core/load-fragment.h b/src/core/load-fragment.h
|
||||
index 6612e1fb32..424fa478a7 100644
|
||||
--- a/src/core/load-fragment.h
|
||||
+++ b/src/core/load-fragment.h
|
||||
@@ -86,8 +86,8 @@ CONFIG_PARSER_PROTOTYPE(config_parse_set_status);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_namespace_path_strv);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_temporary_filesystems);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_cpu_quota);
|
||||
-CONFIG_PARSER_PROTOTYPE(config_parse_cpuset_cpus);
|
||||
-CONFIG_PARSER_PROTOTYPE(config_parse_cpuset_mems);
|
||||
+CONFIG_PARSER_PROTOTYPE(config_parse_allowed_cpus);
|
||||
+CONFIG_PARSER_PROTOTYPE(config_parse_allowed_mems);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_protect_home);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_protect_system);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_bus_name);
|
@ -0,0 +1,62 @@
|
||||
From ca843e40587fb87fe20bd0561b6ccb42aaafc4ab Mon Sep 17 00:00:00 2001
|
||||
From: Lennart Poettering <lennart@poettering.net>
|
||||
Date: Thu, 9 Jan 2020 17:30:31 +0100
|
||||
Subject: [PATCH] core: fix re-realization of cgroup siblings
|
||||
|
||||
This is a fix-up for eef85c4a3f8054d29383a176f6cebd1ef3a15b9a which
|
||||
broke this.
|
||||
|
||||
Tracked down by @w-simon
|
||||
|
||||
Fixes: #14453
|
||||
(cherry picked from commit 65f6b6bdcb500c576674b5838e4cc4c35e18bfde)
|
||||
|
||||
Related: #1818054
|
||||
---
|
||||
src/core/cgroup.c | 21 +++++++--------------
|
||||
1 file changed, 7 insertions(+), 14 deletions(-)
|
||||
|
||||
diff --git a/src/core/cgroup.c b/src/core/cgroup.c
|
||||
index 664d269483..3f7665b755 100644
|
||||
--- a/src/core/cgroup.c
|
||||
+++ b/src/core/cgroup.c
|
||||
@@ -1796,32 +1796,25 @@ unsigned manager_dispatch_cgroup_realize_queue(Manager *m) {
|
||||
static void unit_add_siblings_to_cgroup_realize_queue(Unit *u) {
|
||||
Unit *slice;
|
||||
|
||||
- /* This adds the siblings of the specified unit and the
|
||||
- * siblings of all parent units to the cgroup queue. (But
|
||||
- * neither the specified unit itself nor the parents.) */
|
||||
+ /* This adds the siblings of the specified unit and the siblings of all parent units to the cgroup
|
||||
+ * queue. (But neither the specified unit itself nor the parents.) */
|
||||
|
||||
while ((slice = UNIT_DEREF(u->slice))) {
|
||||
Iterator i;
|
||||
Unit *m;
|
||||
void *v;
|
||||
|
||||
- HASHMAP_FOREACH_KEY(v, m, u->dependencies[UNIT_BEFORE], i) {
|
||||
- if (m == u)
|
||||
- continue;
|
||||
-
|
||||
- /* Skip units that have a dependency on the slice
|
||||
- * but aren't actually in it. */
|
||||
+ HASHMAP_FOREACH_KEY(v, m, slice->dependencies[UNIT_BEFORE], i) {
|
||||
+ /* Skip units that have a dependency on the slice but aren't actually in it. */
|
||||
if (UNIT_DEREF(m->slice) != slice)
|
||||
continue;
|
||||
|
||||
- /* No point in doing cgroup application for units
|
||||
- * without active processes. */
|
||||
+ /* No point in doing cgroup application for units without active processes. */
|
||||
if (UNIT_IS_INACTIVE_OR_FAILED(unit_active_state(m)))
|
||||
continue;
|
||||
|
||||
- /* If the unit doesn't need any new controllers
|
||||
- * and has current ones realized, it doesn't need
|
||||
- * any changes. */
|
||||
+ /* If the unit doesn't need any new controllers and has current ones realized, it
|
||||
+ * doesn't need any changes. */
|
||||
if (unit_has_mask_realized(m,
|
||||
unit_get_target_mask(m),
|
||||
unit_get_enable_mask(m),
|
@ -0,0 +1,99 @@
|
||||
From 9fe3b9c7165afeedcf9f31959c436bcec233bb4d Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Michal=20Sekleta=CC=81r?= <msekleta@redhat.com>
|
||||
Date: Tue, 14 Apr 2020 16:16:45 +0200
|
||||
Subject: [PATCH] basic: use comma as separator in cpuset cgroup cpu ranges
|
||||
|
||||
This is a workaround for
|
||||
https://bugzilla.redhat.com/show_bug.cgi?id=1819152 and should be
|
||||
reverted in RHEL-8.3.
|
||||
|
||||
RHEL-only
|
||||
|
||||
Related: #1818054
|
||||
---
|
||||
src/basic/cpu-set-util.c | 45 ++++++++++++++++++++++++++++++++++++++++
|
||||
src/basic/cpu-set-util.h | 1 +
|
||||
src/core/cgroup.c | 2 +-
|
||||
3 files changed, 47 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/src/basic/cpu-set-util.c b/src/basic/cpu-set-util.c
|
||||
index 36cb017ae7..51752ad1a6 100644
|
||||
--- a/src/basic/cpu-set-util.c
|
||||
+++ b/src/basic/cpu-set-util.c
|
||||
@@ -86,6 +86,51 @@ char *cpu_set_to_range_string(const CPUSet *set) {
|
||||
return TAKE_PTR(str) ?: strdup("");
|
||||
}
|
||||
|
||||
+/* XXX(msekleta): this is the workaround for https://bugzilla.redhat.com/show_bug.cgi?id=1819152, remove in 8.3 */
|
||||
+char *cpu_set_to_range_string_kernel(const CPUSet *set) {
|
||||
+ unsigned range_start = 0, range_end;
|
||||
+ _cleanup_free_ char *str = NULL;
|
||||
+ size_t allocated = 0, len = 0;
|
||||
+ bool in_range = false;
|
||||
+ int r;
|
||||
+
|
||||
+ for (unsigned i = 0; i < set->allocated * 8; i++)
|
||||
+ if (CPU_ISSET_S(i, set->allocated, set->set)) {
|
||||
+ if (in_range)
|
||||
+ range_end++;
|
||||
+ else {
|
||||
+ range_start = range_end = i;
|
||||
+ in_range = true;
|
||||
+ }
|
||||
+ } else if (in_range) {
|
||||
+ in_range = false;
|
||||
+
|
||||
+ if (!GREEDY_REALLOC(str, allocated, len + 2 + 2 * DECIMAL_STR_MAX(unsigned)))
|
||||
+ return NULL;
|
||||
+
|
||||
+ if (range_end > range_start)
|
||||
+ r = sprintf(str + len, len > 0 ? ",%d-%d" : "%d-%d", range_start, range_end);
|
||||
+ else
|
||||
+ r = sprintf(str + len, len > 0 ? ",%d" : "%d", range_start);
|
||||
+ assert_se(r > 0);
|
||||
+ len += r;
|
||||
+ }
|
||||
+
|
||||
+ if (in_range) {
|
||||
+ if (!GREEDY_REALLOC(str, allocated, len + 2 + 2 * DECIMAL_STR_MAX(int)))
|
||||
+ return NULL;
|
||||
+
|
||||
+ if (range_end > range_start)
|
||||
+ r = sprintf(str + len, len > 0 ? ",%d-%d" : "%d-%d", range_start, range_end);
|
||||
+ else
|
||||
+ r = sprintf(str + len, len > 0 ? ",%d" : "%d", range_start);
|
||||
+ assert_se(r > 0);
|
||||
+ }
|
||||
+
|
||||
+ return TAKE_PTR(str) ?: strdup("");
|
||||
+}
|
||||
+
|
||||
+
|
||||
int cpu_set_realloc(CPUSet *cpu_set, unsigned ncpus) {
|
||||
size_t need;
|
||||
|
||||
diff --git a/src/basic/cpu-set-util.h b/src/basic/cpu-set-util.h
|
||||
index 295028cb54..8519a9b6c8 100644
|
||||
--- a/src/basic/cpu-set-util.h
|
||||
+++ b/src/basic/cpu-set-util.h
|
||||
@@ -27,6 +27,7 @@ int cpu_set_add_all(CPUSet *a, const CPUSet *b);
|
||||
|
||||
char* cpu_set_to_string(const CPUSet *a);
|
||||
char *cpu_set_to_range_string(const CPUSet *a);
|
||||
+char *cpu_set_to_range_string_kernel(const CPUSet *a);
|
||||
int cpu_set_realloc(CPUSet *cpu_set, unsigned ncpus);
|
||||
|
||||
int parse_cpu_set_full(
|
||||
diff --git a/src/core/cgroup.c b/src/core/cgroup.c
|
||||
index 3f7665b755..9e4c3c7dac 100644
|
||||
--- a/src/core/cgroup.c
|
||||
+++ b/src/core/cgroup.c
|
||||
@@ -557,7 +557,7 @@ static void cgroup_apply_unified_cpuset(Unit *u, CPUSet cpus, const char *name)
|
||||
_cleanup_free_ char *buf = NULL;
|
||||
int r;
|
||||
|
||||
- buf = cpu_set_to_range_string(&cpus);
|
||||
+ buf = cpu_set_to_range_string_kernel(&cpus);
|
||||
if (!buf)
|
||||
return;
|
||||
|
@ -0,0 +1,159 @@
|
||||
From 6e732b6e44ad8eb3e94c47459c64f0bc6ef2fcb0 Mon Sep 17 00:00:00 2001
|
||||
From: Anita Zhang <the.anitazha@gmail.com>
|
||||
Date: Sat, 25 Jan 2020 16:46:16 +0100
|
||||
Subject: [PATCH] core: transition to FINAL_SIGTERM state after ExecStopPost=
|
||||
|
||||
Fixes #14566
|
||||
|
||||
(cherry picked from commit c1566ef0d22ed786b9ecf4c476e53b8a91e67578)
|
||||
|
||||
Resolves: #1766479
|
||||
---
|
||||
src/core/service.c | 10 +++++
|
||||
test/TEST-47-ISSUE-14566/Makefile | 1 +
|
||||
test/TEST-47-ISSUE-14566/repro.sh | 5 +++
|
||||
test/TEST-47-ISSUE-14566/test.sh | 55 +++++++++++++++++++++++++++
|
||||
test/TEST-47-ISSUE-14566/testsuite.sh | 23 +++++++++++
|
||||
5 files changed, 94 insertions(+)
|
||||
create mode 120000 test/TEST-47-ISSUE-14566/Makefile
|
||||
create mode 100755 test/TEST-47-ISSUE-14566/repro.sh
|
||||
create mode 100755 test/TEST-47-ISSUE-14566/test.sh
|
||||
create mode 100755 test/TEST-47-ISSUE-14566/testsuite.sh
|
||||
|
||||
diff --git a/src/core/service.c b/src/core/service.c
|
||||
index b1ec52d220..5035dcacac 100644
|
||||
--- a/src/core/service.c
|
||||
+++ b/src/core/service.c
|
||||
@@ -3280,6 +3280,12 @@ static void service_sigchld_event(Unit *u, pid_t pid, int code, int status) {
|
||||
break;
|
||||
|
||||
case SERVICE_STOP_POST:
|
||||
+
|
||||
+ if (control_pid_good(s) <= 0)
|
||||
+ service_enter_signal(s, SERVICE_FINAL_SIGTERM, f);
|
||||
+
|
||||
+ break;
|
||||
+
|
||||
case SERVICE_FINAL_SIGTERM:
|
||||
case SERVICE_FINAL_SIGKILL:
|
||||
|
||||
@@ -3415,6 +3421,10 @@ static void service_sigchld_event(Unit *u, pid_t pid, int code, int status) {
|
||||
break;
|
||||
|
||||
case SERVICE_STOP_POST:
|
||||
+ if (main_pid_good(s) <= 0)
|
||||
+ service_enter_signal(s, SERVICE_FINAL_SIGTERM, f);
|
||||
+ break;
|
||||
+
|
||||
case SERVICE_FINAL_SIGTERM:
|
||||
case SERVICE_FINAL_SIGKILL:
|
||||
if (main_pid_good(s) <= 0)
|
||||
diff --git a/test/TEST-47-ISSUE-14566/Makefile b/test/TEST-47-ISSUE-14566/Makefile
|
||||
new file mode 120000
|
||||
index 0000000000..e9f93b1104
|
||||
--- /dev/null
|
||||
+++ b/test/TEST-47-ISSUE-14566/Makefile
|
||||
@@ -0,0 +1 @@
|
||||
+../TEST-01-BASIC/Makefile
|
||||
\ No newline at end of file
|
||||
diff --git a/test/TEST-47-ISSUE-14566/repro.sh b/test/TEST-47-ISSUE-14566/repro.sh
|
||||
new file mode 100755
|
||||
index 0000000000..5217602257
|
||||
--- /dev/null
|
||||
+++ b/test/TEST-47-ISSUE-14566/repro.sh
|
||||
@@ -0,0 +1,5 @@
|
||||
+#!/bin/bash
|
||||
+
|
||||
+sleep infinity &
|
||||
+echo $! > /leakedtestpid
|
||||
+wait $!
|
||||
diff --git a/test/TEST-47-ISSUE-14566/test.sh b/test/TEST-47-ISSUE-14566/test.sh
|
||||
new file mode 100755
|
||||
index 0000000000..0ce772164a
|
||||
--- /dev/null
|
||||
+++ b/test/TEST-47-ISSUE-14566/test.sh
|
||||
@@ -0,0 +1,55 @@
|
||||
+#!/bin/bash
|
||||
+set -e
|
||||
+TEST_DESCRIPTION="Test that KillMode=mixed does not leave left over proccesses with ExecStopPost="
|
||||
+. $TEST_BASE_DIR/test-functions
|
||||
+
|
||||
+test_setup() {
|
||||
+ create_empty_image
|
||||
+ mkdir -p $TESTDIR/root
|
||||
+ mount ${LOOPDEV}p1 $TESTDIR/root
|
||||
+
|
||||
+ (
|
||||
+ LOG_LEVEL=5
|
||||
+ eval $(udevadm info --export --query=env --name=${LOOPDEV}p2)
|
||||
+
|
||||
+ setup_basic_environment
|
||||
+
|
||||
+ # mask some services that we do not want to run in these tests
|
||||
+ ln -fs /dev/null $initdir/etc/systemd/system/systemd-hwdb-update.service
|
||||
+ ln -fs /dev/null $initdir/etc/systemd/system/systemd-journal-catalog-update.service
|
||||
+ ln -fs /dev/null $initdir/etc/systemd/system/systemd-networkd.service
|
||||
+ ln -fs /dev/null $initdir/etc/systemd/system/systemd-networkd.socket
|
||||
+ ln -fs /dev/null $initdir/etc/systemd/system/systemd-resolved.service
|
||||
+ ln -fs /dev/null $initdir/etc/systemd/system/systemd-machined.service
|
||||
+
|
||||
+ # setup the testsuite service
|
||||
+ cat >$initdir/etc/systemd/system/testsuite.service <<EOF
|
||||
+[Unit]
|
||||
+Description=Testsuite service
|
||||
+
|
||||
+[Service]
|
||||
+ExecStart=/testsuite.sh
|
||||
+Type=oneshot
|
||||
+EOF
|
||||
+ cat > $initdir/etc/systemd/system/issue_14566_test.service << EOF
|
||||
+[Unit]
|
||||
+Description=Issue 14566 Repro
|
||||
+
|
||||
+[Service]
|
||||
+ExecStart=/repro.sh
|
||||
+ExecStopPost=/bin/true
|
||||
+KillMode=mixed
|
||||
+EOF
|
||||
+
|
||||
+ cp testsuite.sh $initdir/
|
||||
+ cp repro.sh $initdir/
|
||||
+
|
||||
+ setup_testsuite
|
||||
+ )
|
||||
+ setup_nspawn_root
|
||||
+
|
||||
+ ddebug "umount $TESTDIR/root"
|
||||
+ umount $TESTDIR/root
|
||||
+}
|
||||
+
|
||||
+do_test "$@"
|
||||
diff --git a/test/TEST-47-ISSUE-14566/testsuite.sh b/test/TEST-47-ISSUE-14566/testsuite.sh
|
||||
new file mode 100755
|
||||
index 0000000000..d917cf52ff
|
||||
--- /dev/null
|
||||
+++ b/test/TEST-47-ISSUE-14566/testsuite.sh
|
||||
@@ -0,0 +1,23 @@
|
||||
+#!/bin/bash
|
||||
+set -ex
|
||||
+set -o pipefail
|
||||
+
|
||||
+systemd-analyze log-level debug
|
||||
+systemd-analyze log-target console
|
||||
+
|
||||
+systemctl start issue_14566_test
|
||||
+systemctl status issue_14566_test
|
||||
+
|
||||
+leaked_pid=$(cat /leakedtestpid)
|
||||
+
|
||||
+systemctl stop issue_14566_test
|
||||
+
|
||||
+# Leaked PID will still be around if we're buggy.
|
||||
+# I personally prefer to see 42.
|
||||
+ps -p "$leaked_pid" && exit 42
|
||||
+
|
||||
+systemd-analyze log-level info
|
||||
+
|
||||
+echo OK > /testok
|
||||
+
|
||||
+exit 0
|
@ -0,0 +1,75 @@
|
||||
From 45275461f4a5293f15191ec5cb3bb80219ef2474 Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Michal=20Sekleta=CC=81r?= <msekleta@redhat.com>
|
||||
Date: Tue, 4 Feb 2020 14:23:14 +0100
|
||||
Subject: [PATCH] sd-journal: close journal files that were deleted by journald
|
||||
before we've setup inotify watch
|
||||
|
||||
Fixes #14695
|
||||
|
||||
(cherry picked from commit 28ca867abdb20d0e4ac1901e2ed669cdb41ea3f6)
|
||||
|
||||
Related: #1796128
|
||||
---
|
||||
src/journal/journal-file.c | 2 +-
|
||||
src/journal/journal-file.h | 1 +
|
||||
src/journal/sd-journal.c | 15 +++++++++++++++
|
||||
3 files changed, 17 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/src/journal/journal-file.c b/src/journal/journal-file.c
|
||||
index 8249b11b23..7ab3c47fc9 100644
|
||||
--- a/src/journal/journal-file.c
|
||||
+++ b/src/journal/journal-file.c
|
||||
@@ -597,7 +597,7 @@ static int journal_file_verify_header(JournalFile *f) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
-static int journal_file_fstat(JournalFile *f) {
|
||||
+int journal_file_fstat(JournalFile *f) {
|
||||
int r;
|
||||
|
||||
assert(f);
|
||||
diff --git a/src/journal/journal-file.h b/src/journal/journal-file.h
|
||||
index 6a44fd39d2..6069b35234 100644
|
||||
--- a/src/journal/journal-file.h
|
||||
+++ b/src/journal/journal-file.h
|
||||
@@ -144,6 +144,7 @@ int journal_file_open(
|
||||
int journal_file_set_offline(JournalFile *f, bool wait);
|
||||
bool journal_file_is_offlining(JournalFile *f);
|
||||
JournalFile* journal_file_close(JournalFile *j);
|
||||
+int journal_file_fstat(JournalFile *f);
|
||||
DEFINE_TRIVIAL_CLEANUP_FUNC(JournalFile*, journal_file_close);
|
||||
|
||||
int journal_file_open_reliably(
|
||||
diff --git a/src/journal/sd-journal.c b/src/journal/sd-journal.c
|
||||
index 323300baec..c06255e273 100644
|
||||
--- a/src/journal/sd-journal.c
|
||||
+++ b/src/journal/sd-journal.c
|
||||
@@ -2584,6 +2584,8 @@ _public_ int sd_journal_wait(sd_journal *j, uint64_t timeout_usec) {
|
||||
assert_return(!journal_pid_changed(j), -ECHILD);
|
||||
|
||||
if (j->inotify_fd < 0) {
|
||||
+ Iterator i;
|
||||
+ JournalFile *f;
|
||||
|
||||
/* This is the first invocation, hence create the
|
||||
* inotify watch */
|
||||
@@ -2591,6 +2593,19 @@ _public_ int sd_journal_wait(sd_journal *j, uint64_t timeout_usec) {
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
+ /* Server might have done some vacuuming while we weren't watching.
|
||||
+ Get rid of the deleted files now so they don't stay around indefinitely. */
|
||||
+ ORDERED_HASHMAP_FOREACH(f, j->files, i) {
|
||||
+ r = journal_file_fstat(f);
|
||||
+ if (r < 0) {
|
||||
+ log_debug_errno(r,"Failed to fstat() journal file '%s' : %m", f->path);
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
+ if (f->last_stat.st_nlink <= 0)
|
||||
+ remove_file_real(j, f);
|
||||
+ }
|
||||
+
|
||||
/* The journal might have changed since the context
|
||||
* object was created and we weren't watching before,
|
||||
* hence don't wait for anything, and return
|
@ -0,0 +1,42 @@
|
||||
From 0f7ee0007b8267cc66b638a44da6ddd984ece412 Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Michal=20Sekleta=CC=81r?= <msekleta@redhat.com>
|
||||
Date: Fri, 27 Mar 2020 17:01:59 +0100
|
||||
Subject: [PATCH] sd-journal: remove the dead code and actually fix #14695
|
||||
|
||||
journal_file_fstat() returns an error if we call it on already unlinked
|
||||
journal file and hence we never reach remove_file_real() which is the
|
||||
entire point.
|
||||
|
||||
I must have made some mistake while testing the fix that got me thinking
|
||||
the issue is gone while opposite was true.
|
||||
|
||||
Fixes #14695
|
||||
|
||||
(cherry picked from commit 8581b9f9732d4c158bb5f773230a65ce77f2c292)
|
||||
|
||||
Resolves: #1796128
|
||||
---
|
||||
src/journal/sd-journal.c | 7 +++----
|
||||
1 file changed, 3 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/src/journal/sd-journal.c b/src/journal/sd-journal.c
|
||||
index c06255e273..4c502978de 100644
|
||||
--- a/src/journal/sd-journal.c
|
||||
+++ b/src/journal/sd-journal.c
|
||||
@@ -2597,13 +2597,12 @@ _public_ int sd_journal_wait(sd_journal *j, uint64_t timeout_usec) {
|
||||
Get rid of the deleted files now so they don't stay around indefinitely. */
|
||||
ORDERED_HASHMAP_FOREACH(f, j->files, i) {
|
||||
r = journal_file_fstat(f);
|
||||
- if (r < 0) {
|
||||
+ if (r == -EIDRM)
|
||||
+ remove_file_real(j, f);
|
||||
+ else if (r < 0) {
|
||||
log_debug_errno(r,"Failed to fstat() journal file '%s' : %m", f->path);
|
||||
continue;
|
||||
}
|
||||
-
|
||||
- if (f->last_stat.st_nlink <= 0)
|
||||
- remove_file_real(j, f);
|
||||
}
|
||||
|
||||
/* The journal might have changed since the context
|
@ -0,0 +1,43 @@
|
||||
From 38532765172a4e60624b9c24b8d081b34d9f7b86 Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= <zbyszek@in.waw.pl>
|
||||
Date: Tue, 13 Nov 2018 14:53:04 +0100
|
||||
Subject: [PATCH] udev: downgrade message when we fail to set inotify watch up
|
||||
|
||||
My logs are full of:
|
||||
|
||||
systemd-udevd[6586]: seq 13515 queued, 'add' 'block'
|
||||
systemd-udevd[6586]: seq 13516 queued, 'change' 'block'
|
||||
systemd-udevd[6586]: seq 13517 queued, 'change' 'block'
|
||||
systemd-udevd[6586]: seq 13518 queued, 'remove' 'bdi'
|
||||
systemd-udevd[6586]: seq 13519 queued, 'remove' 'block'
|
||||
systemd-udevd[9865]: seq 13514 processed
|
||||
systemd-udevd[9865]: seq 13515 running
|
||||
systemd-udevd[9865]: GROUP 6 /usr/lib/udev/rules.d/50-udev-default.rules:59
|
||||
systemd-udevd[9865]: IMPORT builtin 'blkid' /usr/lib/udev/rules.d/60-persistent-storage.rules:95
|
||||
systemd-udevd[9865]: IMPORT builtin 'blkid' fails: No such file or directory
|
||||
systemd-udevd[9865]: loop4: Failed to add device '/dev/loop4' to watch: No such file or directory
|
||||
(the last line is at error level).
|
||||
If we are too slow to set up a watch and the device is already gone by the time
|
||||
we try, this is not an error.
|
||||
|
||||
(cherry picked from commit 7fe0d0d5c0ad5aa3f069bb282868938d414d7ad1)
|
||||
|
||||
Resolves: #1808051
|
||||
---
|
||||
src/udev/udev-watch.c | 3 ++-
|
||||
1 file changed, 2 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/src/udev/udev-watch.c b/src/udev/udev-watch.c
|
||||
index 7864f57aa5..9c82196add 100644
|
||||
--- a/src/udev/udev-watch.c
|
||||
+++ b/src/udev/udev-watch.c
|
||||
@@ -87,7 +87,8 @@ void udev_watch_begin(struct udev *udev, struct udev_device *dev) {
|
||||
log_debug("adding watch on '%s'", udev_device_get_devnode(dev));
|
||||
wd = inotify_add_watch(inotify_fd, udev_device_get_devnode(dev), IN_CLOSE_WRITE);
|
||||
if (wd < 0) {
|
||||
- log_error_errno(errno, "inotify_add_watch(%d, %s, %o) failed: %m",
|
||||
+ log_full_errno(errno == ENOENT ? LOG_DEBUG : LOG_ERR,
|
||||
+ errno, "inotify_add_watch(%d, %s, %o) failed: %m",
|
||||
inotify_fd, udev_device_get_devnode(dev), IN_CLOSE_WRITE);
|
||||
return;
|
||||
}
|
@ -0,0 +1,195 @@
|
||||
From af20a66874296f71618819ebce9d4335b195728c Mon Sep 17 00:00:00 2001
|
||||
From: Lennart Poettering <lennart@poettering.net>
|
||||
Date: Wed, 22 Jan 2020 12:04:38 +0100
|
||||
Subject: [PATCH] logind: check PolicyKit before allowing VT switch
|
||||
|
||||
Let's lock this down a bit. Effectively nothing much changes, since the
|
||||
default PK policy will allow users on the VT to change VT. Only users
|
||||
with no local VT session won't be able to switch VTs.
|
||||
|
||||
(cherry picked from commit 4acf0cfd2f92edb94ad48d04f1ce6c9ab4e19d55)
|
||||
|
||||
Resolves: #1797679
|
||||
---
|
||||
src/login/logind-dbus.c | 16 +++++++
|
||||
src/login/logind-seat-dbus.c | 58 ++++++++++++++++++++++++-
|
||||
src/login/logind-session-dbus.c | 15 +++++++
|
||||
src/login/org.freedesktop.login1.policy | 10 +++++
|
||||
4 files changed, 98 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/src/login/logind-dbus.c b/src/login/logind-dbus.c
|
||||
index dca7f4a30f..3f122fcbd9 100644
|
||||
--- a/src/login/logind-dbus.c
|
||||
+++ b/src/login/logind-dbus.c
|
||||
@@ -913,6 +913,8 @@ static int method_activate_session(sd_bus_message *message, void *userdata, sd_b
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
+ /* PolicyKit is done by bus_session_method_activate() */
|
||||
+
|
||||
return bus_session_method_activate(message, session, error);
|
||||
}
|
||||
|
||||
@@ -944,6 +946,20 @@ static int method_activate_session_on_seat(sd_bus_message *message, void *userda
|
||||
if (session->seat != seat)
|
||||
return sd_bus_error_setf(error, BUS_ERROR_SESSION_NOT_ON_SEAT, "Session %s not on seat %s", session_name, seat_name);
|
||||
|
||||
+ r = bus_verify_polkit_async(
|
||||
+ message,
|
||||
+ CAP_SYS_ADMIN,
|
||||
+ "org.freedesktop.login1.chvt",
|
||||
+ NULL,
|
||||
+ false,
|
||||
+ UID_INVALID,
|
||||
+ &m->polkit_registry,
|
||||
+ error);
|
||||
+ if (r < 0)
|
||||
+ return r;
|
||||
+ if (r == 0)
|
||||
+ return 1; /* Will call us back */
|
||||
+
|
||||
r = session_activate(session);
|
||||
if (r < 0)
|
||||
return r;
|
||||
diff --git a/src/login/logind-seat-dbus.c b/src/login/logind-seat-dbus.c
|
||||
index c4d9b067c6..2e590a8f21 100644
|
||||
--- a/src/login/logind-seat-dbus.c
|
||||
+++ b/src/login/logind-seat-dbus.c
|
||||
@@ -174,6 +174,20 @@ static int method_activate_session(sd_bus_message *message, void *userdata, sd_b
|
||||
if (session->seat != s)
|
||||
return sd_bus_error_setf(error, BUS_ERROR_SESSION_NOT_ON_SEAT, "Session %s not on seat %s", name, s->id);
|
||||
|
||||
+ r = bus_verify_polkit_async(
|
||||
+ message,
|
||||
+ CAP_SYS_ADMIN,
|
||||
+ "org.freedesktop.login1.chvt",
|
||||
+ NULL,
|
||||
+ false,
|
||||
+ UID_INVALID,
|
||||
+ &s->manager->polkit_registry,
|
||||
+ error);
|
||||
+ if (r < 0)
|
||||
+ return r;
|
||||
+ if (r == 0)
|
||||
+ return 1; /* Will call us back */
|
||||
+
|
||||
r = session_activate(session);
|
||||
if (r < 0)
|
||||
return r;
|
||||
@@ -194,7 +208,21 @@ static int method_switch_to(sd_bus_message *message, void *userdata, sd_bus_erro
|
||||
return r;
|
||||
|
||||
if (to <= 0)
|
||||
- return -EINVAL;
|
||||
+ return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid virtual terminal");
|
||||
+
|
||||
+ r = bus_verify_polkit_async(
|
||||
+ message,
|
||||
+ CAP_SYS_ADMIN,
|
||||
+ "org.freedesktop.login1.chvt",
|
||||
+ NULL,
|
||||
+ false,
|
||||
+ UID_INVALID,
|
||||
+ &s->manager->polkit_registry,
|
||||
+ error);
|
||||
+ if (r < 0)
|
||||
+ return r;
|
||||
+ if (r == 0)
|
||||
+ return 1; /* Will call us back */
|
||||
|
||||
r = seat_switch_to(s, to);
|
||||
if (r < 0)
|
||||
@@ -210,6 +238,20 @@ static int method_switch_to_next(sd_bus_message *message, void *userdata, sd_bus
|
||||
assert(message);
|
||||
assert(s);
|
||||
|
||||
+ r = bus_verify_polkit_async(
|
||||
+ message,
|
||||
+ CAP_SYS_ADMIN,
|
||||
+ "org.freedesktop.login1.chvt",
|
||||
+ NULL,
|
||||
+ false,
|
||||
+ UID_INVALID,
|
||||
+ &s->manager->polkit_registry,
|
||||
+ error);
|
||||
+ if (r < 0)
|
||||
+ return r;
|
||||
+ if (r == 0)
|
||||
+ return 1; /* Will call us back */
|
||||
+
|
||||
r = seat_switch_to_next(s);
|
||||
if (r < 0)
|
||||
return r;
|
||||
@@ -224,6 +266,20 @@ static int method_switch_to_previous(sd_bus_message *message, void *userdata, sd
|
||||
assert(message);
|
||||
assert(s);
|
||||
|
||||
+ r = bus_verify_polkit_async(
|
||||
+ message,
|
||||
+ CAP_SYS_ADMIN,
|
||||
+ "org.freedesktop.login1.chvt",
|
||||
+ NULL,
|
||||
+ false,
|
||||
+ UID_INVALID,
|
||||
+ &s->manager->polkit_registry,
|
||||
+ error);
|
||||
+ if (r < 0)
|
||||
+ return r;
|
||||
+ if (r == 0)
|
||||
+ return 1; /* Will call us back */
|
||||
+
|
||||
r = seat_switch_to_previous(s);
|
||||
if (r < 0)
|
||||
return r;
|
||||
diff --git a/src/login/logind-session-dbus.c b/src/login/logind-session-dbus.c
|
||||
index 25c4981dc0..88a2d33dc8 100644
|
||||
--- a/src/login/logind-session-dbus.c
|
||||
+++ b/src/login/logind-session-dbus.c
|
||||
@@ -13,6 +13,7 @@
|
||||
#include "logind.h"
|
||||
#include "signal-util.h"
|
||||
#include "strv.h"
|
||||
+#include "user-util.h"
|
||||
#include "util.h"
|
||||
|
||||
static int property_get_user(
|
||||
@@ -182,6 +183,20 @@ int bus_session_method_activate(sd_bus_message *message, void *userdata, sd_bus_
|
||||
assert(message);
|
||||
assert(s);
|
||||
|
||||
+ r = bus_verify_polkit_async(
|
||||
+ message,
|
||||
+ CAP_SYS_ADMIN,
|
||||
+ "org.freedesktop.login1.chvt",
|
||||
+ NULL,
|
||||
+ false,
|
||||
+ UID_INVALID,
|
||||
+ &s->manager->polkit_registry,
|
||||
+ error);
|
||||
+ if (r < 0)
|
||||
+ return r;
|
||||
+ if (r == 0)
|
||||
+ return 1; /* Will call us back */
|
||||
+
|
||||
r = session_activate(s);
|
||||
if (r < 0)
|
||||
return r;
|
||||
diff --git a/src/login/org.freedesktop.login1.policy b/src/login/org.freedesktop.login1.policy
|
||||
index f1d1f956d3..83760e1580 100644
|
||||
--- a/src/login/org.freedesktop.login1.policy
|
||||
+++ b/src/login/org.freedesktop.login1.policy
|
||||
@@ -357,4 +357,14 @@
|
||||
</defaults>
|
||||
</action>
|
||||
|
||||
+ <action id="org.freedesktop.login1.chvt">
|
||||
+ <description gettext-domain="systemd">Change Session</description>
|
||||
+ <message gettext-domain="systemd">Authentication is required for changing the virtual terminal.</message>
|
||||
+ <defaults>
|
||||
+ <allow_any>auth_admin_keep</allow_any>
|
||||
+ <allow_inactive>auth_admin_keep</allow_inactive>
|
||||
+ <allow_active>yes</allow_active>
|
||||
+ </defaults>
|
||||
+ </action>
|
||||
+
|
||||
</policyconfig>
|
@ -0,0 +1,58 @@
|
||||
From 35e9e01b2879854a2adb8d571d0204990cad38d9 Mon Sep 17 00:00:00 2001
|
||||
From: Yu Watanabe <watanabe.yu+github@gmail.com>
|
||||
Date: Fri, 14 Sep 2018 13:25:02 +0900
|
||||
Subject: [PATCH] test: do not use global variable to pass error
|
||||
|
||||
(cherry picked from commit 0013fac248a15be3acce84c17a65e3ae0377294b)
|
||||
|
||||
Resolves: #1823767
|
||||
---
|
||||
test/TEST-21-SYSUSERS/test.sh | 1 +
|
||||
test/test-functions | 8 +++++---
|
||||
2 files changed, 6 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/test/TEST-21-SYSUSERS/test.sh b/test/TEST-21-SYSUSERS/test.sh
|
||||
index 73cbe10b69..b1049e720d 100755
|
||||
--- a/test/TEST-21-SYSUSERS/test.sh
|
||||
+++ b/test/TEST-21-SYSUSERS/test.sh
|
||||
@@ -15,6 +15,7 @@ prepare_testdir() {
|
||||
for i in $1.initial-{passwd,group,shadow}; do
|
||||
test -f $i && cp $i $TESTDIR/etc/${i#*.initial-}
|
||||
done
|
||||
+ return 0
|
||||
}
|
||||
|
||||
preprocess() {
|
||||
diff --git a/test/test-functions b/test/test-functions
|
||||
index fe25a501da..da83891f46 100644
|
||||
--- a/test/test-functions
|
||||
+++ b/test/test-functions
|
||||
@@ -449,7 +449,7 @@ EOF
|
||||
}
|
||||
|
||||
check_result_nspawn() {
|
||||
- ret=1
|
||||
+ local ret=1
|
||||
[[ -e $TESTDIR/$1/testok ]] && ret=0
|
||||
[[ -f $TESTDIR/$1/failed ]] && cp -a $TESTDIR/$1/failed $TESTDIR
|
||||
cp -a $TESTDIR/$1/var/log/journal $TESTDIR
|
||||
@@ -462,7 +462,7 @@ check_result_nspawn() {
|
||||
|
||||
# can be overridden in specific test
|
||||
check_result_qemu() {
|
||||
- ret=1
|
||||
+ local ret=1
|
||||
mkdir -p $TESTDIR/root
|
||||
mount ${LOOPDEV}p1 $TESTDIR/root
|
||||
[[ -e $TESTDIR/root/testok ]] && ret=0
|
||||
@@ -1527,7 +1527,9 @@ do_test() {
|
||||
case $1 in
|
||||
--run)
|
||||
echo "TEST RUN: $TEST_DESCRIPTION"
|
||||
- if test_run; then
|
||||
+ test_run
|
||||
+ ret=$?
|
||||
+ if (( $ret == 0 )); then
|
||||
echo "TEST RUN: $TEST_DESCRIPTION [OK]"
|
||||
else
|
||||
echo "TEST RUN: $TEST_DESCRIPTION [FAILED]"
|
25
SOURCES/0356-test-install-libraries-required-by-tests.patch
Normal file
25
SOURCES/0356-test-install-libraries-required-by-tests.patch
Normal file
@ -0,0 +1,25 @@
|
||||
From 98e4c0d39a83a325038d0b39715fc534c7613bef Mon Sep 17 00:00:00 2001
|
||||
From: Yu Watanabe <watanabe.yu+github@gmail.com>
|
||||
Date: Wed, 12 Sep 2018 18:19:45 +0900
|
||||
Subject: [PATCH] test: install libraries required by tests
|
||||
|
||||
(cherry picked from commit e3d3dada248c5f30e2978840ca1f0a03a4675b53)
|
||||
|
||||
Resolves: #1823767
|
||||
---
|
||||
test/test-functions | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/test/test-functions b/test/test-functions
|
||||
index da83891f46..f7ca3ad975 100644
|
||||
--- a/test/test-functions
|
||||
+++ b/test/test-functions
|
||||
@@ -420,7 +420,7 @@ get_ldpath() {
|
||||
|
||||
install_missing_libraries() {
|
||||
# install possible missing libraries
|
||||
- for i in $initdir{,/usr}/{sbin,bin}/* $initdir{,/usr}/lib/systemd/*; do
|
||||
+ for i in $initdir{,/usr}/{sbin,bin}/* $initdir{,/usr}/lib/systemd/{,tests/{,manual/,unsafe/}}*; do
|
||||
LD_LIBRARY_PATH=$(get_ldpath $i) inst_libs $i
|
||||
done
|
||||
}
|
32
SOURCES/0357-test-introduce-install_zoneinfo.patch
Normal file
32
SOURCES/0357-test-introduce-install_zoneinfo.patch
Normal file
@ -0,0 +1,32 @@
|
||||
From 73781e52f331f816924232f96c7bfc92ee763e70 Mon Sep 17 00:00:00 2001
|
||||
From: Yu Watanabe <watanabe.yu+github@gmail.com>
|
||||
Date: Wed, 12 Sep 2018 18:20:31 +0900
|
||||
Subject: [PATCH] test: introduce install_zoneinfo()
|
||||
|
||||
But it is not called by default.
|
||||
|
||||
(cherry picked from commit 7d10ec1cda8fed20c36b16d2387f529583645cda)
|
||||
|
||||
Resolves: #1823767
|
||||
---
|
||||
test/test-functions | 7 +++++++
|
||||
1 file changed, 7 insertions(+)
|
||||
|
||||
diff --git a/test/test-functions b/test/test-functions
|
||||
index f7ca3ad975..4d76ed1f82 100644
|
||||
--- a/test/test-functions
|
||||
+++ b/test/test-functions
|
||||
@@ -628,6 +628,13 @@ install_keymaps() {
|
||||
done
|
||||
}
|
||||
|
||||
+install_zoneinfo() {
|
||||
+ for i in /usr/share/zoneinfo/{,*/,*/*/}*; do
|
||||
+ [[ -f $i ]] || continue
|
||||
+ inst $i
|
||||
+ done
|
||||
+}
|
||||
+
|
||||
install_fonts() {
|
||||
for i in \
|
||||
/usr/lib/kbd/consolefonts/eurlatgr* \
|
@ -0,0 +1,151 @@
|
||||
From e39c4e6aee6c2ece5d9b51cc0e7a772016546f5a Mon Sep 17 00:00:00 2001
|
||||
From: Yu Watanabe <watanabe.yu+github@gmail.com>
|
||||
Date: Thu, 13 Sep 2018 03:01:42 +0900
|
||||
Subject: [PATCH] test: replace duplicated Makefile by symbolic link
|
||||
|
||||
(cherry picked from commit dd75c133d81f07c56c82ee4e7a80f391ffebd9ce)
|
||||
|
||||
Resolves: #1823767
|
||||
---
|
||||
test/TEST-17-UDEV-WANTS/Makefile | 5 +----
|
||||
test/TEST-18-FAILUREACTION/Makefile | 5 +----
|
||||
test/TEST-19-DELEGATE/Makefile | 5 +----
|
||||
test/TEST-20-MAINPIDGAMES/Makefile | 5 +----
|
||||
test/TEST-21-SYSUSERS/Makefile | 5 +----
|
||||
test/TEST-22-TMPFILES/Makefile | 5 +----
|
||||
test/TEST-23-TYPE-EXEC/Makefile | 5 +----
|
||||
7 files changed, 7 insertions(+), 28 deletions(-)
|
||||
mode change 100644 => 120000 test/TEST-17-UDEV-WANTS/Makefile
|
||||
mode change 100644 => 120000 test/TEST-18-FAILUREACTION/Makefile
|
||||
mode change 100644 => 120000 test/TEST-19-DELEGATE/Makefile
|
||||
mode change 100644 => 120000 test/TEST-20-MAINPIDGAMES/Makefile
|
||||
mode change 100644 => 120000 test/TEST-21-SYSUSERS/Makefile
|
||||
mode change 100644 => 120000 test/TEST-22-TMPFILES/Makefile
|
||||
mode change 100644 => 120000 test/TEST-23-TYPE-EXEC/Makefile
|
||||
|
||||
diff --git a/test/TEST-17-UDEV-WANTS/Makefile b/test/TEST-17-UDEV-WANTS/Makefile
|
||||
deleted file mode 100644
|
||||
index 34d7cc6cdf..0000000000
|
||||
--- a/test/TEST-17-UDEV-WANTS/Makefile
|
||||
+++ /dev/null
|
||||
@@ -1,4 +0,0 @@
|
||||
-BUILD_DIR=$(shell ../../tools/find-build-dir.sh)
|
||||
-
|
||||
-all setup clean run:
|
||||
- @basedir=../.. TEST_BASE_DIR=../ BUILD_DIR=$(BUILD_DIR) ./test.sh --$@
|
||||
diff --git a/test/TEST-17-UDEV-WANTS/Makefile b/test/TEST-17-UDEV-WANTS/Makefile
|
||||
new file mode 120000
|
||||
index 0000000000..e9f93b1104
|
||||
--- /dev/null
|
||||
+++ b/test/TEST-17-UDEV-WANTS/Makefile
|
||||
@@ -0,0 +1 @@
|
||||
+../TEST-01-BASIC/Makefile
|
||||
\ No newline at end of file
|
||||
diff --git a/test/TEST-18-FAILUREACTION/Makefile b/test/TEST-18-FAILUREACTION/Makefile
|
||||
deleted file mode 100644
|
||||
index 34d7cc6cdf..0000000000
|
||||
--- a/test/TEST-18-FAILUREACTION/Makefile
|
||||
+++ /dev/null
|
||||
@@ -1,4 +0,0 @@
|
||||
-BUILD_DIR=$(shell ../../tools/find-build-dir.sh)
|
||||
-
|
||||
-all setup clean run:
|
||||
- @basedir=../.. TEST_BASE_DIR=../ BUILD_DIR=$(BUILD_DIR) ./test.sh --$@
|
||||
diff --git a/test/TEST-18-FAILUREACTION/Makefile b/test/TEST-18-FAILUREACTION/Makefile
|
||||
new file mode 120000
|
||||
index 0000000000..e9f93b1104
|
||||
--- /dev/null
|
||||
+++ b/test/TEST-18-FAILUREACTION/Makefile
|
||||
@@ -0,0 +1 @@
|
||||
+../TEST-01-BASIC/Makefile
|
||||
\ No newline at end of file
|
||||
diff --git a/test/TEST-19-DELEGATE/Makefile b/test/TEST-19-DELEGATE/Makefile
|
||||
deleted file mode 100644
|
||||
index 34d7cc6cdf..0000000000
|
||||
--- a/test/TEST-19-DELEGATE/Makefile
|
||||
+++ /dev/null
|
||||
@@ -1,4 +0,0 @@
|
||||
-BUILD_DIR=$(shell ../../tools/find-build-dir.sh)
|
||||
-
|
||||
-all setup clean run:
|
||||
- @basedir=../.. TEST_BASE_DIR=../ BUILD_DIR=$(BUILD_DIR) ./test.sh --$@
|
||||
diff --git a/test/TEST-19-DELEGATE/Makefile b/test/TEST-19-DELEGATE/Makefile
|
||||
new file mode 120000
|
||||
index 0000000000..e9f93b1104
|
||||
--- /dev/null
|
||||
+++ b/test/TEST-19-DELEGATE/Makefile
|
||||
@@ -0,0 +1 @@
|
||||
+../TEST-01-BASIC/Makefile
|
||||
\ No newline at end of file
|
||||
diff --git a/test/TEST-20-MAINPIDGAMES/Makefile b/test/TEST-20-MAINPIDGAMES/Makefile
|
||||
deleted file mode 100644
|
||||
index 34d7cc6cdf..0000000000
|
||||
--- a/test/TEST-20-MAINPIDGAMES/Makefile
|
||||
+++ /dev/null
|
||||
@@ -1,4 +0,0 @@
|
||||
-BUILD_DIR=$(shell ../../tools/find-build-dir.sh)
|
||||
-
|
||||
-all setup clean run:
|
||||
- @basedir=../.. TEST_BASE_DIR=../ BUILD_DIR=$(BUILD_DIR) ./test.sh --$@
|
||||
diff --git a/test/TEST-20-MAINPIDGAMES/Makefile b/test/TEST-20-MAINPIDGAMES/Makefile
|
||||
new file mode 120000
|
||||
index 0000000000..e9f93b1104
|
||||
--- /dev/null
|
||||
+++ b/test/TEST-20-MAINPIDGAMES/Makefile
|
||||
@@ -0,0 +1 @@
|
||||
+../TEST-01-BASIC/Makefile
|
||||
\ No newline at end of file
|
||||
diff --git a/test/TEST-21-SYSUSERS/Makefile b/test/TEST-21-SYSUSERS/Makefile
|
||||
deleted file mode 100644
|
||||
index 34d7cc6cdf..0000000000
|
||||
--- a/test/TEST-21-SYSUSERS/Makefile
|
||||
+++ /dev/null
|
||||
@@ -1,4 +0,0 @@
|
||||
-BUILD_DIR=$(shell ../../tools/find-build-dir.sh)
|
||||
-
|
||||
-all setup clean run:
|
||||
- @basedir=../.. TEST_BASE_DIR=../ BUILD_DIR=$(BUILD_DIR) ./test.sh --$@
|
||||
diff --git a/test/TEST-21-SYSUSERS/Makefile b/test/TEST-21-SYSUSERS/Makefile
|
||||
new file mode 120000
|
||||
index 0000000000..e9f93b1104
|
||||
--- /dev/null
|
||||
+++ b/test/TEST-21-SYSUSERS/Makefile
|
||||
@@ -0,0 +1 @@
|
||||
+../TEST-01-BASIC/Makefile
|
||||
\ No newline at end of file
|
||||
diff --git a/test/TEST-22-TMPFILES/Makefile b/test/TEST-22-TMPFILES/Makefile
|
||||
deleted file mode 100644
|
||||
index 34d7cc6cdf..0000000000
|
||||
--- a/test/TEST-22-TMPFILES/Makefile
|
||||
+++ /dev/null
|
||||
@@ -1,4 +0,0 @@
|
||||
-BUILD_DIR=$(shell ../../tools/find-build-dir.sh)
|
||||
-
|
||||
-all setup clean run:
|
||||
- @basedir=../.. TEST_BASE_DIR=../ BUILD_DIR=$(BUILD_DIR) ./test.sh --$@
|
||||
diff --git a/test/TEST-22-TMPFILES/Makefile b/test/TEST-22-TMPFILES/Makefile
|
||||
new file mode 120000
|
||||
index 0000000000..e9f93b1104
|
||||
--- /dev/null
|
||||
+++ b/test/TEST-22-TMPFILES/Makefile
|
||||
@@ -0,0 +1 @@
|
||||
+../TEST-01-BASIC/Makefile
|
||||
\ No newline at end of file
|
||||
diff --git a/test/TEST-23-TYPE-EXEC/Makefile b/test/TEST-23-TYPE-EXEC/Makefile
|
||||
deleted file mode 100644
|
||||
index 34d7cc6cdf..0000000000
|
||||
--- a/test/TEST-23-TYPE-EXEC/Makefile
|
||||
+++ /dev/null
|
||||
@@ -1,4 +0,0 @@
|
||||
-BUILD_DIR=$(shell ../../tools/find-build-dir.sh)
|
||||
-
|
||||
-all setup clean run:
|
||||
- @basedir=../.. TEST_BASE_DIR=../ BUILD_DIR=$(BUILD_DIR) ./test.sh --$@
|
||||
diff --git a/test/TEST-23-TYPE-EXEC/Makefile b/test/TEST-23-TYPE-EXEC/Makefile
|
||||
new file mode 120000
|
||||
index 0000000000..e9f93b1104
|
||||
--- /dev/null
|
||||
+++ b/test/TEST-23-TYPE-EXEC/Makefile
|
||||
@@ -0,0 +1 @@
|
||||
+../TEST-01-BASIC/Makefile
|
||||
\ No newline at end of file
|
@ -0,0 +1,34 @@
|
||||
From 1599be6d3625700ded28108c0747b000448fa5dc Mon Sep 17 00:00:00 2001
|
||||
From: Yu Watanabe <watanabe.yu+github@gmail.com>
|
||||
Date: Wed, 19 Sep 2018 10:54:16 +0900
|
||||
Subject: [PATCH] test: add paths of keymaps in install_keymaps()
|
||||
|
||||
It seems that the paths of directories storing keymaps are changed.
|
||||
|
||||
(cherry picked from commit 83a7051ee1edbfe8cd2278477d23083beb385409)
|
||||
|
||||
Resolves: #1823767
|
||||
---
|
||||
test/test-functions | 6 +++++-
|
||||
1 file changed, 5 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/test/test-functions b/test/test-functions
|
||||
index 4d76ed1f82..546928c516 100644
|
||||
--- a/test/test-functions
|
||||
+++ b/test/test-functions
|
||||
@@ -619,10 +619,14 @@ install_pam() {
|
||||
}
|
||||
|
||||
install_keymaps() {
|
||||
+ # The first three paths may be deprecated.
|
||||
+ # It seems now the last two paths are used by many distributions.
|
||||
for i in \
|
||||
/usr/lib/kbd/keymaps/include/* \
|
||||
/usr/lib/kbd/keymaps/i386/include/* \
|
||||
- /usr/lib/kbd/keymaps/i386/qwerty/us.*; do
|
||||
+ /usr/lib/kbd/keymaps/i386/qwerty/us.* \
|
||||
+ /usr/lib/kbd/keymaps/legacy/include/* \
|
||||
+ /usr/lib/kbd/keymaps/legacy/i386/qwerty/us.*; do
|
||||
[[ -f $i ]] || continue
|
||||
inst $i
|
||||
done
|
@ -0,0 +1,33 @@
|
||||
From 8dbd01f7018947fd15d00c25b1aa0ffc72278cb6 Mon Sep 17 00:00:00 2001
|
||||
From: Yu Watanabe <watanabe.yu+github@gmail.com>
|
||||
Date: Wed, 19 Sep 2018 10:54:28 +0900
|
||||
Subject: [PATCH] test: make install_keymaps() optionally install more keymaps
|
||||
|
||||
(cherry picked from commit ad931fee506e1313e8a520ae0ecc1c8e275d9941)
|
||||
|
||||
Resolves: #1823767
|
||||
---
|
||||
test/test-functions | 10 ++++++++++
|
||||
1 file changed, 10 insertions(+)
|
||||
|
||||
diff --git a/test/test-functions b/test/test-functions
|
||||
index 546928c516..0938e6e826 100644
|
||||
--- a/test/test-functions
|
||||
+++ b/test/test-functions
|
||||
@@ -630,6 +630,16 @@ install_keymaps() {
|
||||
[[ -f $i ]] || continue
|
||||
inst $i
|
||||
done
|
||||
+
|
||||
+ # When it takes any argument, then install more keymaps.
|
||||
+ if [[ -n $1 ]]; then
|
||||
+ for i in \
|
||||
+ /usr/lib/kbd/keymaps/i386/*/* \
|
||||
+ /usr/lib/kbd/keymaps/legacy/i386/*/*; do
|
||||
+ [[ -f $i ]] || continue
|
||||
+ inst $i
|
||||
+ done
|
||||
+ fi
|
||||
}
|
||||
|
||||
install_zoneinfo() {
|
@ -0,0 +1,47 @@
|
||||
From 15ab55eca3d1f7feb86e55bdc147069f36d198eb Mon Sep 17 00:00:00 2001
|
||||
From: Yu Watanabe <watanabe.yu+github@gmail.com>
|
||||
Date: Fri, 14 Sep 2018 15:51:04 +0900
|
||||
Subject: [PATCH] test-fs-util: skip some tests when running in unprivileged
|
||||
container
|
||||
|
||||
(cherry picked from commit 9590065f37be040996f1c2b9a246b9952fdc0c0b)
|
||||
|
||||
Resolves: #1823767
|
||||
---
|
||||
src/test/test-fs-util.c | 9 ++++++++-
|
||||
1 file changed, 8 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/src/test/test-fs-util.c b/src/test/test-fs-util.c
|
||||
index 7b7990bb70..e3338ea440 100644
|
||||
--- a/src/test/test-fs-util.c
|
||||
+++ b/src/test/test-fs-util.c
|
||||
@@ -17,6 +17,7 @@
|
||||
#include "strv.h"
|
||||
#include "user-util.h"
|
||||
#include "util.h"
|
||||
+#include "virt.h"
|
||||
|
||||
static void test_chase_symlinks(void) {
|
||||
_cleanup_free_ char *result = NULL;
|
||||
@@ -468,6 +469,7 @@ static void test_touch_file(void) {
|
||||
struct stat st;
|
||||
const char *a;
|
||||
usec_t test_mtime;
|
||||
+ int r;
|
||||
|
||||
test_uid = geteuid() == 0 ? 65534 : getuid();
|
||||
test_gid = geteuid() == 0 ? 65534 : getgid();
|
||||
@@ -517,7 +519,12 @@ static void test_touch_file(void) {
|
||||
|
||||
if (geteuid() == 0) {
|
||||
a = strjoina(p, "/cdev");
|
||||
- assert_se(mknod(a, 0775 | S_IFCHR, makedev(0, 0)) >= 0);
|
||||
+ r = mknod(a, 0775 | S_IFCHR, makedev(0, 0));
|
||||
+ if (r < 0 && errno == EPERM && detect_container() > 0) {
|
||||
+ log_notice("Running in unprivileged container? Skipping remaining tests in %s", __func__);
|
||||
+ return;
|
||||
+ }
|
||||
+ assert_se(r >= 0);
|
||||
assert_se(touch_file(a, false, test_mtime, test_uid, test_gid, 0640) >= 0);
|
||||
assert_se(lstat(a, &st) >= 0);
|
||||
assert_se(st.st_uid == test_uid);
|
@ -0,0 +1,39 @@
|
||||
From b550cc33e762fa209b0740f1874f75ef780b8d90 Mon Sep 17 00:00:00 2001
|
||||
From: Yu Watanabe <watanabe.yu+github@gmail.com>
|
||||
Date: Thu, 20 Sep 2018 16:08:38 +0900
|
||||
Subject: [PATCH] test-process-util: skip several verifications when running in
|
||||
unprivileged container
|
||||
|
||||
(cherry picked from commit 767eab47501b06327a0e6030e5c54860a3fc427f)
|
||||
|
||||
Resolves: #1823767
|
||||
---
|
||||
src/test/test-process-util.c | 13 +++++++++----
|
||||
1 file changed, 9 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/src/test/test-process-util.c b/src/test/test-process-util.c
|
||||
index fd4d17408d..26e3247993 100644
|
||||
--- a/src/test/test-process-util.c
|
||||
+++ b/src/test/test-process-util.c
|
||||
@@ -394,12 +394,17 @@ static void test_rename_process_now(const char *p, int ret) {
|
||||
log_info("comm = <%s>", comm);
|
||||
assert_se(strneq(comm, p, TASK_COMM_LEN-1));
|
||||
|
||||
- assert_se(get_process_cmdline(0, 0, false, &cmdline) >= 0);
|
||||
+ r = get_process_cmdline(0, 0, false, &cmdline);
|
||||
+ assert_se(r >= 0);
|
||||
/* we cannot expect cmdline to be renamed properly without privileges */
|
||||
if (geteuid() == 0) {
|
||||
- log_info("cmdline = <%s>", cmdline);
|
||||
- assert_se(strneq(p, cmdline, STRLEN("test-process-util")));
|
||||
- assert_se(startswith(p, cmdline));
|
||||
+ if (r == 0 && detect_container() > 0)
|
||||
+ log_info("cmdline = <%s> (not verified, Running in unprivileged container?)", cmdline);
|
||||
+ else {
|
||||
+ log_info("cmdline = <%s>", cmdline);
|
||||
+ assert_se(strneq(p, cmdline, STRLEN("test-process-util")));
|
||||
+ assert_se(startswith(p, cmdline));
|
||||
+ }
|
||||
} else
|
||||
log_info("cmdline = <%s> (not verified)", cmdline);
|
||||
}
|
@ -0,0 +1,59 @@
|
||||
From a3a3d861496b8c0d061c6ba21278d0326c50f37d Mon Sep 17 00:00:00 2001
|
||||
From: Yu Watanabe <watanabe.yu+github@gmail.com>
|
||||
Date: Wed, 12 Sep 2018 18:18:33 +0900
|
||||
Subject: [PATCH] test-execute: also check python3 is installed or not
|
||||
|
||||
(cherry picked from commit 738c74d7b163ea18e3c68115c3ed8ceed166cbf7)
|
||||
|
||||
Resolves: #1823767
|
||||
---
|
||||
src/test/test-execute.c | 17 +++++++++++++++++
|
||||
1 file changed, 17 insertions(+)
|
||||
|
||||
diff --git a/src/test/test-execute.c b/src/test/test-execute.c
|
||||
index 6c22995b1e..af64427bc7 100644
|
||||
--- a/src/test/test-execute.c
|
||||
+++ b/src/test/test-execute.c
|
||||
@@ -317,6 +317,8 @@ static void test_exec_temporaryfilesystem(Manager *m) {
|
||||
|
||||
static void test_exec_systemcallfilter(Manager *m) {
|
||||
#if HAVE_SECCOMP
|
||||
+ int r;
|
||||
+
|
||||
if (!is_seccomp_available()) {
|
||||
log_notice("Seccomp not available, skipping %s", __func__);
|
||||
return;
|
||||
@@ -326,6 +328,13 @@ static void test_exec_systemcallfilter(Manager *m) {
|
||||
test(m, "exec-systemcallfilter-not-failing2.service", 0, CLD_EXITED);
|
||||
test(m, "exec-systemcallfilter-failing.service", SIGSYS, CLD_KILLED);
|
||||
test(m, "exec-systemcallfilter-failing2.service", SIGSYS, CLD_KILLED);
|
||||
+
|
||||
+ r = find_binary("python3", NULL);
|
||||
+ if (r < 0) {
|
||||
+ log_notice_errno(r, "Skipping remaining tests in %s, could not find python3 binary: %m", __func__);
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
test(m, "exec-systemcallfilter-with-errno-name.service", errno_from_name("EILSEQ"), CLD_EXITED);
|
||||
test(m, "exec-systemcallfilter-with-errno-number.service", 255, CLD_EXITED);
|
||||
#endif
|
||||
@@ -333,11 +342,19 @@ static void test_exec_systemcallfilter(Manager *m) {
|
||||
|
||||
static void test_exec_systemcallerrornumber(Manager *m) {
|
||||
#if HAVE_SECCOMP
|
||||
+ int r;
|
||||
+
|
||||
if (!is_seccomp_available()) {
|
||||
log_notice("Seccomp not available, skipping %s", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
+ r = find_binary("python3", NULL);
|
||||
+ if (r < 0) {
|
||||
+ log_notice_errno(r, "Skipping %s, could not find python3 binary: %m", __func__);
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
test(m, "exec-systemcallerrornumber-name.service", errno_from_name("EACCES"), CLD_EXITED);
|
||||
test(m, "exec-systemcallerrornumber-number.service", 255, CLD_EXITED);
|
||||
#endif
|
@ -0,0 +1,42 @@
|
||||
From fb66f2dbf1d228adc6f15edbbdf0ce53eb3be982 Mon Sep 17 00:00:00 2001
|
||||
From: Yu Watanabe <watanabe.yu+github@gmail.com>
|
||||
Date: Fri, 14 Sep 2018 15:47:42 +0900
|
||||
Subject: [PATCH] test-execute: skip several tests when running in container
|
||||
|
||||
(cherry picked from commit 642d1a6d6e98204ade25816bcc429cb67df92a29)
|
||||
|
||||
Resolves: #1823767
|
||||
---
|
||||
src/test/test-execute.c | 12 +++++++++++-
|
||||
1 file changed, 11 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/src/test/test-execute.c b/src/test/test-execute.c
|
||||
index af64427bc7..637ffe96bb 100644
|
||||
--- a/src/test/test-execute.c
|
||||
+++ b/src/test/test-execute.c
|
||||
@@ -616,14 +616,24 @@ static void test_exec_privatenetwork(Manager *m) {
|
||||
|
||||
static void test_exec_oomscoreadjust(Manager *m) {
|
||||
test(m, "exec-oomscoreadjust-positive.service", 0, CLD_EXITED);
|
||||
+
|
||||
+ if (detect_container() > 0) {
|
||||
+ log_notice("Testing in container, skipping remaining tests in %s", __func__);
|
||||
+ return;
|
||||
+ }
|
||||
test(m, "exec-oomscoreadjust-negative.service", 0, CLD_EXITED);
|
||||
}
|
||||
|
||||
static void test_exec_ioschedulingclass(Manager *m) {
|
||||
test(m, "exec-ioschedulingclass-none.service", 0, CLD_EXITED);
|
||||
test(m, "exec-ioschedulingclass-idle.service", 0, CLD_EXITED);
|
||||
- test(m, "exec-ioschedulingclass-realtime.service", 0, CLD_EXITED);
|
||||
test(m, "exec-ioschedulingclass-best-effort.service", 0, CLD_EXITED);
|
||||
+
|
||||
+ if (detect_container() > 0) {
|
||||
+ log_notice("Testing in container, skipping remaining tests in %s", __func__);
|
||||
+ return;
|
||||
+ }
|
||||
+ test(m, "exec-ioschedulingclass-realtime.service", 0, CLD_EXITED);
|
||||
}
|
||||
|
||||
static void test_exec_unsetenvironment(Manager *m) {
|
@ -0,0 +1,70 @@
|
||||
From b69552ccc0e33f713ae3a2baf1b0173cf221507d Mon Sep 17 00:00:00 2001
|
||||
From: Yu Watanabe <watanabe.yu+github@gmail.com>
|
||||
Date: Tue, 11 Sep 2018 09:17:22 +0900
|
||||
Subject: [PATCH] test: introduce test_is_running_from_builddir()
|
||||
|
||||
(cherry picked from commit 8cb10a4f4dabc508a04f76ea55f23ef517881b61)
|
||||
|
||||
Resolves: #1823767
|
||||
---
|
||||
src/shared/tests.c | 23 ++++++++++++++++++++---
|
||||
src/shared/tests.h | 1 +
|
||||
2 files changed, 21 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/src/shared/tests.c b/src/shared/tests.c
|
||||
index b10343650f..c77eb00924 100644
|
||||
--- a/src/shared/tests.c
|
||||
+++ b/src/shared/tests.c
|
||||
@@ -19,6 +19,24 @@ char* setup_fake_runtime_dir(void) {
|
||||
return p;
|
||||
}
|
||||
|
||||
+bool test_is_running_from_builddir(char **exedir) {
|
||||
+ _cleanup_free_ char *s = NULL;
|
||||
+ bool r;
|
||||
+
|
||||
+ /* Check if we're running from the builddir. Optionally, this returns
|
||||
+ * the path to the directory where the binary is located. */
|
||||
+
|
||||
+ assert_se(readlink_and_make_absolute("/proc/self/exe", &s) >= 0);
|
||||
+ r = path_startswith(s, ABS_BUILD_DIR);
|
||||
+
|
||||
+ if (exedir) {
|
||||
+ dirname(s);
|
||||
+ *exedir = TAKE_PTR(s);
|
||||
+ }
|
||||
+
|
||||
+ return r;
|
||||
+}
|
||||
+
|
||||
const char* get_testdata_dir(const char *suffix) {
|
||||
const char *env;
|
||||
/* convenience: caller does not need to free result */
|
||||
@@ -35,14 +53,13 @@ const char* get_testdata_dir(const char *suffix) {
|
||||
strncpy(testdir, env, sizeof(testdir) - 1);
|
||||
} else {
|
||||
_cleanup_free_ char *exedir = NULL;
|
||||
- assert_se(readlink_and_make_absolute("/proc/self/exe", &exedir) >= 0);
|
||||
|
||||
/* Check if we're running from the builddir. If so, use the compiled in path. */
|
||||
- if (path_startswith(exedir, ABS_BUILD_DIR))
|
||||
+ if (test_is_running_from_builddir(&exedir))
|
||||
assert_se(snprintf(testdir, sizeof(testdir), "%s/test", ABS_SRC_DIR) > 0);
|
||||
else
|
||||
/* Try relative path, according to the install-test layout */
|
||||
- assert_se(snprintf(testdir, sizeof(testdir), "%s/testdata", dirname(exedir)) > 0);
|
||||
+ assert_se(snprintf(testdir, sizeof(testdir), "%s/testdata", exedir) > 0);
|
||||
|
||||
/* test this without the suffix, as it may contain a glob */
|
||||
if (access(testdir, F_OK) < 0) {
|
||||
diff --git a/src/shared/tests.h b/src/shared/tests.h
|
||||
index cad21169f8..7f45c32d32 100644
|
||||
--- a/src/shared/tests.h
|
||||
+++ b/src/shared/tests.h
|
||||
@@ -2,5 +2,6 @@
|
||||
#pragma once
|
||||
|
||||
char* setup_fake_runtime_dir(void);
|
||||
+bool test_is_running_from_builddir(char **exedir);
|
||||
const char* get_testdata_dir(const char *suffix);
|
||||
void test_setup_logging(int level);
|
103
SOURCES/0366-test-make-test-catalog-relocatable.patch
Normal file
103
SOURCES/0366-test-make-test-catalog-relocatable.patch
Normal file
@ -0,0 +1,103 @@
|
||||
From ac476ab0ce970e4a269fee34a15e24f6b20962b7 Mon Sep 17 00:00:00 2001
|
||||
From: Yu Watanabe <watanabe.yu+github@gmail.com>
|
||||
Date: Tue, 11 Sep 2018 09:18:33 +0900
|
||||
Subject: [PATCH] test: make test-catalog relocatable
|
||||
|
||||
Fixes #10045.
|
||||
|
||||
(cherry picked from commit d9b6baa69968132d33e4ad8627c7fe0bd527c859)
|
||||
|
||||
Resolves: #1823767
|
||||
---
|
||||
catalog/meson.build | 1 -
|
||||
src/journal/test-catalog.c | 27 +++++++++++++++++++--------
|
||||
src/test/meson.build | 2 +-
|
||||
3 files changed, 20 insertions(+), 10 deletions(-)
|
||||
|
||||
diff --git a/catalog/meson.build b/catalog/meson.build
|
||||
index 1b13150894..3db8e390f2 100644
|
||||
--- a/catalog/meson.build
|
||||
+++ b/catalog/meson.build
|
||||
@@ -17,7 +17,6 @@ in_files = '''
|
||||
|
||||
support_url = get_option('support-url')
|
||||
support_sed = 's~%SUPPORT_URL%~@0@~'.format(support_url)
|
||||
-build_catalog_dir = meson.current_build_dir()
|
||||
|
||||
foreach file : in_files
|
||||
custom_target(
|
||||
diff --git a/src/journal/test-catalog.c b/src/journal/test-catalog.c
|
||||
index 8eae993780..0c4da29f31 100644
|
||||
--- a/src/journal/test-catalog.c
|
||||
+++ b/src/journal/test-catalog.c
|
||||
@@ -14,14 +14,13 @@
|
||||
#include "fileio.h"
|
||||
#include "log.h"
|
||||
#include "macro.h"
|
||||
+#include "path-util.h"
|
||||
#include "string-util.h"
|
||||
+#include "strv.h"
|
||||
+#include "tests.h"
|
||||
#include "util.h"
|
||||
|
||||
-static const char *catalog_dirs[] = {
|
||||
- CATALOG_DIR,
|
||||
- NULL,
|
||||
-};
|
||||
-
|
||||
+static char** catalog_dirs = NULL;
|
||||
static const char *no_catalog_dirs[] = {
|
||||
"/bin/hopefully/with/no/catalog",
|
||||
NULL
|
||||
@@ -167,8 +166,8 @@ static void test_catalog_update(const char *database) {
|
||||
assert_se(r == 0);
|
||||
|
||||
/* Make sure that we at least have some files loaded or the
|
||||
- catalog_list below will fail. */
|
||||
- r = catalog_update(database, NULL, catalog_dirs);
|
||||
+ * catalog_list below will fail. */
|
||||
+ r = catalog_update(database, NULL, (const char * const *) catalog_dirs);
|
||||
assert_se(r == 0);
|
||||
}
|
||||
|
||||
@@ -202,14 +201,26 @@ static void test_catalog_file_lang(void) {
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
_cleanup_(unlink_tempfilep) char database[] = "/tmp/test-catalog.XXXXXX";
|
||||
- _cleanup_free_ char *text = NULL;
|
||||
+ _cleanup_free_ char *text = NULL, *catalog_dir = NULL;
|
||||
int r;
|
||||
|
||||
setlocale(LC_ALL, "de_DE.UTF-8");
|
||||
|
||||
+ log_set_max_level(LOG_DEBUG);
|
||||
log_parse_environment();
|
||||
log_open();
|
||||
|
||||
+ /* If test-catalog is located at the build directory, then use catalogs in that.
|
||||
+ * If it is not, e.g. installed by systemd-tests package, then use installed catalogs. */
|
||||
+ if (test_is_running_from_builddir(NULL)) {
|
||||
+ assert_se(catalog_dir = path_join(NULL, ABS_BUILD_DIR, "catalog"));
|
||||
+ catalog_dirs = STRV_MAKE(catalog_dir);
|
||||
+ } else
|
||||
+ catalog_dirs = STRV_MAKE(CATALOG_DIR);
|
||||
+
|
||||
+ assert_se(access(catalog_dirs[0], F_OK) >= 0);
|
||||
+ log_notice("Using catalog directory '%s'", catalog_dirs[0]);
|
||||
+
|
||||
test_catalog_file_lang();
|
||||
|
||||
test_catalog_import_invalid();
|
||||
diff --git a/src/test/meson.build b/src/test/meson.build
|
||||
index 4259421f98..ead000e30c 100644
|
||||
--- a/src/test/meson.build
|
||||
+++ b/src/test/meson.build
|
||||
@@ -766,7 +766,7 @@ tests += [
|
||||
[threads,
|
||||
libxz,
|
||||
liblz4],
|
||||
- '', '', '-DCATALOG_DIR="@0@"'.format(build_catalog_dir)],
|
||||
+ '', '', '-DCATALOG_DIR="@0@"'.format(catalogdir)],
|
||||
|
||||
[['src/journal/test-compress.c'],
|
||||
[libjournal_core,
|
137
SOURCES/0367-test-parallelize-tasks-in-TEST-24-UNIT-TESTS.patch
Normal file
137
SOURCES/0367-test-parallelize-tasks-in-TEST-24-UNIT-TESTS.patch
Normal file
@ -0,0 +1,137 @@
|
||||
From 7ba4a6f5a02f6142d0e28fd475fd008532fb1083 Mon Sep 17 00:00:00 2001
|
||||
From: Frantisek Sumsal <frantisek@sumsal.cz>
|
||||
Date: Tue, 5 Mar 2019 13:50:28 +0100
|
||||
Subject: [PATCH] test: parallelize tasks in TEST-24-UNIT-TESTS
|
||||
|
||||
(cherry picked from commit 2f2a0454efd07644a4e0ccb3f00f1db2d7043391)
|
||||
|
||||
Related: #1823767
|
||||
---
|
||||
test/TEST-24-UNIT-TESTS/test.sh | 2 +
|
||||
test/TEST-24-UNIT-TESTS/testsuite.sh | 97 +++++++++++++++++++++-------
|
||||
2 files changed, 77 insertions(+), 22 deletions(-)
|
||||
|
||||
diff --git a/test/TEST-24-UNIT-TESTS/test.sh b/test/TEST-24-UNIT-TESTS/test.sh
|
||||
index 014ee52277..fc8c89fe0a 100755
|
||||
--- a/test/TEST-24-UNIT-TESTS/test.sh
|
||||
+++ b/test/TEST-24-UNIT-TESTS/test.sh
|
||||
@@ -78,6 +78,8 @@ test_setup() {
|
||||
setup_basic_environment
|
||||
install_keymaps yes
|
||||
install_zoneinfo
|
||||
+ # Install nproc to determine # of CPUs for correct parallelization
|
||||
+ inst_binary nproc
|
||||
|
||||
# setup the testsuite service
|
||||
cat >$initdir/etc/systemd/system/testsuite.service <<EOF
|
||||
diff --git a/test/TEST-24-UNIT-TESTS/testsuite.sh b/test/TEST-24-UNIT-TESTS/testsuite.sh
|
||||
index 7c0e495dbd..7c7a068556 100755
|
||||
--- a/test/TEST-24-UNIT-TESTS/testsuite.sh
|
||||
+++ b/test/TEST-24-UNIT-TESTS/testsuite.sh
|
||||
@@ -4,31 +4,84 @@
|
||||
#set -ex
|
||||
#set -o pipefail
|
||||
|
||||
-for i in /usr/lib/systemd/tests/test-*; do
|
||||
- if [[ ! -x $i ]]; then continue; fi
|
||||
- NAME=${i##*/}
|
||||
- echo "Running $NAME"
|
||||
- $i > /$NAME.log 2>&1
|
||||
- ret=$?
|
||||
- if (( $ret && $ret != 77 )); then
|
||||
- echo "$NAME failed with $ret"
|
||||
- echo $NAME >> /failed-tests
|
||||
- echo "--- $NAME begin ---" >> /failed
|
||||
- cat /$NAME.log >> /failed
|
||||
- echo "--- $NAME end ---" >> /failed
|
||||
- elif (( $ret == 77 )); then
|
||||
- echo "$NAME skipped"
|
||||
- echo $NAME >> /skipped-tests
|
||||
- echo "--- $NAME begin ---" >> /skipped
|
||||
- cat /$NAME.log >> /skipped
|
||||
- echo "--- $NAME end ---" >> /skipped
|
||||
+NPROC=$(nproc)
|
||||
+MAX_QUEUE_SIZE=${NPROC:-2}
|
||||
+IFS=$'\n' TEST_LIST=($(ls /usr/lib/systemd/tests/test-*))
|
||||
+
|
||||
+# Check & report test results
|
||||
+# Arguments:
|
||||
+# $1: test path
|
||||
+# $2: test exit code
|
||||
+function report_result() {
|
||||
+ if [[ $# -ne 2 ]]; then
|
||||
+ echo >&2 "check_result: missing arguments"
|
||||
+ exit 1
|
||||
+ fi
|
||||
+
|
||||
+ local name="${1##*/}"
|
||||
+ local ret=$2
|
||||
+
|
||||
+ if [[ $ret -ne 0 && $ret != 77 ]]; then
|
||||
+ echo "$name failed with $ret"
|
||||
+ echo "$name" >> /failed-tests
|
||||
+ {
|
||||
+ echo "--- $name begin ---"
|
||||
+ cat "/$name.log"
|
||||
+ echo "--- $name end ---"
|
||||
+ } >> /failed
|
||||
+ elif [[ $ret == 77 ]]; then
|
||||
+ echo "$name skipped"
|
||||
+ echo "$name" >> /skipped-tests
|
||||
+ {
|
||||
+ echo "--- $name begin ---"
|
||||
+ cat "/$name.log"
|
||||
+ echo "--- $name end ---"
|
||||
+ } >> /skipped
|
||||
else
|
||||
- echo "$NAME OK"
|
||||
- echo $NAME >> /testok
|
||||
+ echo "$name OK"
|
||||
+ echo "$name" >> /testok
|
||||
+ fi
|
||||
+
|
||||
+ systemd-cat echo "--- $name ---"
|
||||
+ systemd-cat cat "/$name.log"
|
||||
+}
|
||||
+
|
||||
+# Associative array for running tasks, where running[test-path]=PID
|
||||
+declare -A running=()
|
||||
+for task in "${TEST_LIST[@]}"; do
|
||||
+ # If there's MAX_QUEUE_SIZE running tasks, keep checking the running queue
|
||||
+ # until one of the tasks finishes, so we can replace it.
|
||||
+ while [[ ${#running[@]} -ge $MAX_QUEUE_SIZE ]]; do
|
||||
+ for key in "${!running[@]}"; do
|
||||
+ if ! kill -0 ${running[$key]} &>/dev/null; then
|
||||
+ # Task has finished, report its result and drop it from the queue
|
||||
+ wait ${running[$key]}
|
||||
+ ec=$?
|
||||
+ report_result "$key" $ec
|
||||
+ unset running["$key"]
|
||||
+ # Break from inner for loop and outer while loop to skip
|
||||
+ # the sleep below when we find a free slot in the queue
|
||||
+ break 2
|
||||
+ fi
|
||||
+ done
|
||||
+
|
||||
+ # Precisely* calculated constant to keep the spinlock from burning the CPU(s)
|
||||
+ sleep 0.01
|
||||
+ done
|
||||
+
|
||||
+ if [[ -x $task ]]; then
|
||||
+ log_file="/${task##*/}.log"
|
||||
+ $task &> "$log_file" &
|
||||
+ running[$task]=$!
|
||||
fi
|
||||
+done
|
||||
|
||||
- systemd-cat echo "--- $NAME ---"
|
||||
- systemd-cat cat /$NAME.log
|
||||
+# Wait for remaining running tasks
|
||||
+for key in "${!running[@]}"; do
|
||||
+ wait ${running[$key]}
|
||||
+ ec=$?
|
||||
+ report_result "$key" $ec
|
||||
+ unset running["$key"]
|
||||
done
|
||||
|
||||
exit 0
|
@ -0,0 +1,41 @@
|
||||
From fe6e09aa0931112e7e3750801858c66129c7a3a8 Mon Sep 17 00:00:00 2001
|
||||
From: Frantisek Sumsal <frantisek@sumsal.cz>
|
||||
Date: Tue, 5 Mar 2019 16:08:00 +0100
|
||||
Subject: [PATCH] test: try to determine QEMU_SMP dynamically
|
||||
|
||||
If the QEMU_SMP value has not been explicitly set, try to determine it
|
||||
from the number of online CPUs using the nproc utility. If this approach
|
||||
fails, fall back to the default value QEMU_SMP=1.
|
||||
|
||||
This change should significantly help when running integration tests
|
||||
under QEMU on multicore systems.
|
||||
|
||||
(cherry picked from commit 5bfb2a93a4a36bba0d24199553dcda6e560cbb75)
|
||||
|
||||
Related: #1823767
|
||||
---
|
||||
test/test-functions | 11 ++++++++++-
|
||||
1 file changed, 10 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/test/test-functions b/test/test-functions
|
||||
index 0938e6e826..3f1c327f3c 100644
|
||||
--- a/test/test-functions
|
||||
+++ b/test/test-functions
|
||||
@@ -120,7 +120,16 @@ run_qemu() {
|
||||
fi
|
||||
fi
|
||||
|
||||
- [ "$QEMU_SMP" ] || QEMU_SMP=1
|
||||
+ # If QEMU_SMP was not explicitly set, try to determine the value 'dynamically'
|
||||
+ # i.e. use the number of online CPUs on the host machine. If the nproc utility
|
||||
+ # is not installed or there's some other error when calling it, fall back
|
||||
+ # to the original value (QEMU_SMP=1).
|
||||
+ if ! [ "$QEMU_SMP" ]; then
|
||||
+ if ! QEMU_SMP=$(nproc); then
|
||||
+ dwarn "nproc utility is not installed, falling back to QEMU_SMP=1"
|
||||
+ QEMU_SMP=1
|
||||
+ fi
|
||||
+ fi
|
||||
|
||||
find_qemu_bin || return 1
|
||||
|
31
SOURCES/0369-test-store-coredumps-in-journal.patch
Normal file
31
SOURCES/0369-test-store-coredumps-in-journal.patch
Normal file
@ -0,0 +1,31 @@
|
||||
From 8df2d39a562416e1218e3ff191f3f3af1f9d4844 Mon Sep 17 00:00:00 2001
|
||||
From: Frantisek Sumsal <frantisek@sumsal.cz>
|
||||
Date: Tue, 13 Aug 2019 00:14:54 +0200
|
||||
Subject: [PATCH] test: store coredumps in journal
|
||||
|
||||
To make debugging much easier, especially for crashes in tests under
|
||||
QEMU, let's store the entire coredump bundle in the systemd journal,
|
||||
which is usually kept around by various CIs. Right now, we usually end
|
||||
up with a journal, but without the coredump itself, which is pretty
|
||||
useless.
|
||||
|
||||
(cherry picked from commit 215bffe1b8d7cb72fe9f72ed53682d52d5c2a9c5)
|
||||
|
||||
Related: #1823767
|
||||
---
|
||||
test/test-functions | 2 ++
|
||||
1 file changed, 2 insertions(+)
|
||||
|
||||
diff --git a/test/test-functions b/test/test-functions
|
||||
index 3f1c327f3c..7c4230b078 100644
|
||||
--- a/test/test-functions
|
||||
+++ b/test/test-functions
|
||||
@@ -420,6 +420,8 @@ install_systemd() {
|
||||
|
||||
# enable debug logging in PID1
|
||||
echo LogLevel=debug >> $initdir/etc/systemd/system.conf
|
||||
+ # store coredumps in journal
|
||||
+ echo Storage=journal >> $initdir/etc/systemd/coredump.conf
|
||||
}
|
||||
|
||||
get_ldpath() {
|
@ -0,0 +1,62 @@
|
||||
From 82156850f6642a363aa2ff06677ad089a460104e Mon Sep 17 00:00:00 2001
|
||||
From: Lennart Poettering <lennart@poettering.net>
|
||||
Date: Tue, 26 Nov 2019 09:46:00 +0100
|
||||
Subject: [PATCH] pid1: add new kernel cmdline arg systemd.cpu_affinity=
|
||||
|
||||
Let's allow configuration of the CPU affinity via the kernel cmdline,
|
||||
overriding CPUAffinity= in /etc/systemd/system.conf
|
||||
|
||||
Prompted by:
|
||||
|
||||
https://lists.freedesktop.org/archives/systemd-devel/2019-November/043754.html
|
||||
|
||||
(cherry picked from commit 68d58f38693e586b5ce5785274f8e42a79625196)
|
||||
|
||||
Resolves: #1812894
|
||||
---
|
||||
man/kernel-command-line.xml | 11 +++++++++++
|
||||
src/core/main.c | 9 +++++++++
|
||||
2 files changed, 20 insertions(+)
|
||||
|
||||
diff --git a/man/kernel-command-line.xml b/man/kernel-command-line.xml
|
||||
index 0545f9d84b..4d8cb4e50e 100644
|
||||
--- a/man/kernel-command-line.xml
|
||||
+++ b/man/kernel-command-line.xml
|
||||
@@ -366,6 +366,17 @@
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
+ <varlistentry>
|
||||
+ <term><varname>systemd.cpu_affinity=</varname></term>
|
||||
+
|
||||
+ <listitem>
|
||||
+ <para>Overrides the CPU affinity mask for the service manager and the default for all child
|
||||
+ processes it forks. This takes precedence over <varname>CPUAffinity=</varname>, see
|
||||
+ <citerefentry><refentrytitle>systemd-system.conf</refentrytitle><manvolnum>5</manvolnum></citerefentry>
|
||||
+ for details.</para>
|
||||
+ </listitem>
|
||||
+ </varlistentry>
|
||||
+
|
||||
<varlistentry>
|
||||
<term><varname>modules_load=</varname></term>
|
||||
<term><varname>rd.modules_load=</varname></term>
|
||||
diff --git a/src/core/main.c b/src/core/main.c
|
||||
index 45d09b1e11..9f238a8430 100644
|
||||
--- a/src/core/main.c
|
||||
+++ b/src/core/main.c
|
||||
@@ -472,6 +472,15 @@ static int parse_proc_cmdline_item(const char *key, const char *value, void *dat
|
||||
if (arg_default_timeout_start_usec <= 0)
|
||||
arg_default_timeout_start_usec = USEC_INFINITY;
|
||||
|
||||
+ } else if (proc_cmdline_key_streq(key, "systemd.cpu_affinity")) {
|
||||
+
|
||||
+ if (proc_cmdline_value_missing(key, value))
|
||||
+ return 0;
|
||||
+
|
||||
+ r = parse_cpu_set(value, &arg_cpu_affinity);
|
||||
+ if (r < 0)
|
||||
+ log_warning_errno(r, "Failed to parse CPU affinity mask '%s', ignoring: %m", value);
|
||||
+
|
||||
} else if (proc_cmdline_key_streq(key, "systemd.watchdog_device")) {
|
||||
|
||||
if (proc_cmdline_value_missing(key, value))
|
@ -0,0 +1,57 @@
|
||||
From f60e89ea4c38c11a9d0c1e642c0a78faa32aca56 Mon Sep 17 00:00:00 2001
|
||||
From: Joerg Steffens <joerg.steffens@bareos.com>
|
||||
Date: Tue, 21 Nov 2017 12:21:49 +0100
|
||||
Subject: [PATCH] udev-rules: make tape-changers also apprear in
|
||||
/dev/tape/by-path/
|
||||
|
||||
It is important to be able to access tape changer ("Medium Changers") by
|
||||
persistant name.
|
||||
While tape devices can be accessed via /dev/tape/by-id/ and
|
||||
/dev/tape/by-path/, tape-changers could only be accessed by
|
||||
/dev/tape/by-id/.
|
||||
However, in some cases, especially when accessing Amazon Webservice
|
||||
Storage Gateway VTLs (or accessing iSCSI VTLs in general?) this does not
|
||||
work, as all tape devices and the tape changer have the same ENV{ID_SERIAL}.
|
||||
The results is, that only the last device is available in
|
||||
/dev/tape/by-id/, as the former devices have been overwritten.
|
||||
|
||||
As this behavior is hard to change without breaking consistentcy,
|
||||
this additional device in /dev/tape/by-path/ can be used to access the medium changes.
|
||||
The tape devices can also be accessed by this path.
|
||||
|
||||
The content of the directory will now look like:
|
||||
|
||||
# SCSI tape device, rewind (unchanged)
|
||||
/dev/tape/by-path/$env{ID_PATH} -> ../../st*
|
||||
|
||||
# SCSI tape device, no-rewind (unchanged)
|
||||
/dev/tape/by-path/$env{ID_PATH}-nst -> ../../nst*
|
||||
|
||||
# SCSI tape changer device (newly added)
|
||||
/dev/tape/by-path/$env{ID_PATH}-changer -> ../../sg*
|
||||
|
||||
Tape devices and tape changer have different ID_PATHs.
|
||||
SCSI tape changer get the suffix "-changer"
|
||||
to make them better distinguishable from tape devices.
|
||||
|
||||
(cherry picked from commit 7f8ddf96a25162f06bd94a684cf700c128d18142)
|
||||
|
||||
Resolves: #1820112
|
||||
---
|
||||
rules/60-persistent-storage-tape.rules | 3 +++
|
||||
1 file changed, 3 insertions(+)
|
||||
|
||||
diff --git a/rules/60-persistent-storage-tape.rules b/rules/60-persistent-storage-tape.rules
|
||||
index b604864ee8..0575f308df 100644
|
||||
--- a/rules/60-persistent-storage-tape.rules
|
||||
+++ b/rules/60-persistent-storage-tape.rules
|
||||
@@ -9,6 +9,9 @@ ENV{UDEV_DISABLE_PERSISTENT_STORAGE_RULES_FLAG}=="1", GOTO="persistent_storage_t
|
||||
SUBSYSTEM=="scsi_generic", SUBSYSTEMS=="scsi", ATTRS{type}=="8", IMPORT{program}="scsi_id --sg-version=3 --export --whitelisted -d $devnode", \
|
||||
SYMLINK+="tape/by-id/scsi-$env{ID_SERIAL}"
|
||||
|
||||
+SUBSYSTEM=="scsi_generic", SUBSYSTEMS=="scsi", ATTRS{type}=="8", IMPORT{builtin}="path_id", \
|
||||
+ SYMLINK+="tape/by-path/$env{ID_PATH}-changer"
|
||||
+
|
||||
SUBSYSTEM!="scsi_tape", GOTO="persistent_storage_tape_end"
|
||||
|
||||
KERNEL=="st*[0-9]|nst*[0-9]", ATTRS{ieee1394_id}=="?*", ENV{ID_SERIAL}="$attr{ieee1394_id}", ENV{ID_BUS}="ieee1394"
|
@ -0,0 +1,75 @@
|
||||
From b8af9fd65b697e9bb77a32d1a6a70367814aaed5 Mon Sep 17 00:00:00 2001
|
||||
From: Lennart Poettering <lennart@poettering.net>
|
||||
Date: Mon, 1 Apr 2019 17:30:45 +0200
|
||||
Subject: [PATCH] man: be clearer that .timer time expressions need to be reset
|
||||
to override them
|
||||
|
||||
let's be clearer about the overriding concept for OnCalendar= settings.
|
||||
|
||||
Prompted by this thread:
|
||||
|
||||
https://lists.freedesktop.org/archives/systemd-devel/2019-March/042351.html
|
||||
(cherry picked from commit 58031d99c6320855b86f4890baa9165597e3d841)
|
||||
|
||||
Resolves: #1816908
|
||||
---
|
||||
man/systemd.timer.xml | 31 ++++++++++++++++++-------------
|
||||
1 file changed, 18 insertions(+), 13 deletions(-)
|
||||
|
||||
diff --git a/man/systemd.timer.xml b/man/systemd.timer.xml
|
||||
index 44b257c745..ebc1df89f1 100644
|
||||
--- a/man/systemd.timer.xml
|
||||
+++ b/man/systemd.timer.xml
|
||||
@@ -125,12 +125,12 @@
|
||||
to when the unit the timer is activating was last
|
||||
deactivated.</para>
|
||||
|
||||
- <para>Multiple directives may be combined of the same and of
|
||||
- different types. For example, by combining
|
||||
- <varname>OnBootSec=</varname> and
|
||||
- <varname>OnUnitActiveSec=</varname>, it is possible to define
|
||||
- a timer that elapses in regular intervals and activates a
|
||||
- specific service each time.</para>
|
||||
+ <para>Multiple directives may be combined of the same and of different types, in which case the timer
|
||||
+ unit will trigger whenever any of the specified timer expressions elapse. For example, by combining
|
||||
+ <varname>OnBootSec=</varname> and <varname>OnUnitActiveSec=</varname>, it is possible to define a
|
||||
+ timer that elapses in regular intervals and activates a specific service each time. Moreover, both
|
||||
+ monotonic time expressions and <varname>OnCalendar=</varname> calendar expressions may be combined in
|
||||
+ the same timer unit.</para>
|
||||
|
||||
<para>The arguments to the directives are time spans
|
||||
configured in seconds. Example: "OnBootSec=50" means 50s after
|
||||
@@ -145,13 +145,12 @@
|
||||
and the configured unit is started. This is not the case for
|
||||
timers defined in the other directives.</para>
|
||||
|
||||
- <para>These are monotonic timers, independent of wall-clock
|
||||
- time and timezones. If the computer is temporarily suspended,
|
||||
- the monotonic clock stops too.</para>
|
||||
+ <para>These are monotonic timers, independent of wall-clock time and timezones. If the computer is
|
||||
+ temporarily suspended, the monotonic clock pauses, too.</para>
|
||||
|
||||
- <para>If the empty string is assigned to any of these options,
|
||||
- the list of timers is reset, and all prior assignments will
|
||||
- have no effect.</para>
|
||||
+ <para>If the empty string is assigned to any of these options, the list of timers is reset (both
|
||||
+ monotonic timers and <varname>OnCalendar=</varname> timers, see below), and all prior assignments
|
||||
+ will have no effect.</para>
|
||||
|
||||
<para>Note that timers do not necessarily expire at the
|
||||
precise time configured with these settings, as they are
|
||||
@@ -175,7 +174,13 @@
|
||||
the <varname>AccuracySec=</varname> setting
|
||||
below.</para>
|
||||
|
||||
- <para>May be specified more than once.</para></listitem>
|
||||
+ <para>May be specified more than once, in which case the timer unit will trigger whenever any of the
|
||||
+ specified expressions elapse. Moreover calendar timers and monotonic timers (see above) may be
|
||||
+ combined within the same timer unit.</para>
|
||||
+
|
||||
+ <para>If the empty string is assigned to any of these options, the list of timers is reset (both
|
||||
+ <varname>OnCalendar=</varname> timers and monotonic timers, see above), and all prior assignments
|
||||
+ will have no effect.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
312
SOURCES/0373-Add-support-for-opening-files-for-appending.patch
Normal file
312
SOURCES/0373-Add-support-for-opening-files-for-appending.patch
Normal file
@ -0,0 +1,312 @@
|
||||
From 2808e53f785e9ca7fdab286678e784b661b4c185 Mon Sep 17 00:00:00 2001
|
||||
From: Zsolt Dollenstein <zsol.zsol@gmail.com>
|
||||
Date: Tue, 3 Jul 2018 12:22:29 -0700
|
||||
Subject: [PATCH] Add support for opening files for appending
|
||||
|
||||
Addresses part of #8983
|
||||
|
||||
(cherry picked from commit 566b7d23eb747e9c5a74e5647693077b52395fc5)
|
||||
|
||||
Resolves: #1809175
|
||||
---
|
||||
man/systemd.exec.xml | 16 ++++++----
|
||||
src/core/dbus-execute.c | 30 ++++++++++++++-----
|
||||
src/core/execute.c | 20 ++++++++++---
|
||||
src/core/execute.h | 1 +
|
||||
src/core/load-fragment.c | 11 +++++++
|
||||
src/core/main.c | 4 +--
|
||||
src/test/test-execute.c | 10 +++++++
|
||||
test/meson.build | 2 ++
|
||||
.../exec-standardoutput-append.service | 13 ++++++++
|
||||
.../exec-standardoutput-file.service | 13 ++++++++
|
||||
10 files changed, 101 insertions(+), 19 deletions(-)
|
||||
create mode 100644 test/test-execute/exec-standardoutput-append.service
|
||||
create mode 100644 test/test-execute/exec-standardoutput-file.service
|
||||
|
||||
diff --git a/man/systemd.exec.xml b/man/systemd.exec.xml
|
||||
index bdaed68162..e2a5ede968 100644
|
||||
--- a/man/systemd.exec.xml
|
||||
+++ b/man/systemd.exec.xml
|
||||
@@ -1792,8 +1792,8 @@ SystemCallErrorNumber=EPERM</programlisting>
|
||||
of <option>inherit</option>, <option>null</option>, <option>tty</option>, <option>journal</option>,
|
||||
<option>syslog</option>, <option>kmsg</option>, <option>journal+console</option>,
|
||||
<option>syslog+console</option>, <option>kmsg+console</option>,
|
||||
- <option>file:<replaceable>path</replaceable></option>, <option>socket</option> or
|
||||
- <option>fd:<replaceable>name</replaceable></option>.</para>
|
||||
+ <option>file:<replaceable>path</replaceable></option>, <option>append:<replaceable>path</replaceable></option>,
|
||||
+ <option>socket</option> or<option>fd:<replaceable>name</replaceable></option>.</para>
|
||||
|
||||
<para><option>inherit</option> duplicates the file descriptor of standard input for standard output.</para>
|
||||
|
||||
@@ -1824,11 +1824,17 @@ SystemCallErrorNumber=EPERM</programlisting>
|
||||
|
||||
<para>The <option>file:<replaceable>path</replaceable></option> option may be used to connect a specific file
|
||||
system object to standard output. The semantics are similar to the same option of
|
||||
- <varname>StandardInput=</varname>, see above. If standard input and output are directed to the same file path,
|
||||
- it is opened only once, for reading as well as writing and duplicated. This is particular useful when the
|
||||
- specified path refers to an <constant>AF_UNIX</constant> socket in the file system, as in that case only a
|
||||
+ <varname>StandardInput=</varname>, see above. If <replaceable>path</replaceable> refers to a regular file
|
||||
+ on the filesystem, it is opened (created if it doesn't exist yet) for writing at the beginning of the file,
|
||||
+ but without truncating it.
|
||||
+ If standard input and output are directed to the same file path, it is opened only once, for reading as well
|
||||
+ as writing and duplicated. This is particularly useful when the specified path refers to an
|
||||
+ <constant>AF_UNIX</constant> socket in the file system, as in that case only a
|
||||
single stream connection is created for both input and output.</para>
|
||||
|
||||
+ <para><option>append:<replaceable>path</replaceable></option> is similar to <option>file:<replaceable>path
|
||||
+ </replaceable></option> above, but it opens the file in append mode.</para>
|
||||
+
|
||||
<para><option>socket</option> connects standard output to a socket acquired via socket activation. The
|
||||
semantics are similar to the same option of <varname>StandardInput=</varname>, see above.</para>
|
||||
|
||||
diff --git a/src/core/dbus-execute.c b/src/core/dbus-execute.c
|
||||
index e7c0b893d1..f9527e56b2 100644
|
||||
--- a/src/core/dbus-execute.c
|
||||
+++ b/src/core/dbus-execute.c
|
||||
@@ -1772,7 +1772,10 @@ int bus_exec_context_set_transient_property(
|
||||
|
||||
return 1;
|
||||
|
||||
- } else if (STR_IN_SET(name, "StandardInputFile", "StandardOutputFile", "StandardErrorFile")) {
|
||||
+ } else if (STR_IN_SET(name,
|
||||
+ "StandardInputFile",
|
||||
+ "StandardOutputFile", "StandardOutputFileToCreate", "StandardOutputFileToAppend",
|
||||
+ "StandardErrorFile", "StandardErrorFileToCreate", "StandardErrorFileToAppend")) {
|
||||
const char *s;
|
||||
|
||||
r = sd_bus_message_read(message, "s", &s);
|
||||
@@ -1796,23 +1799,34 @@ int bus_exec_context_set_transient_property(
|
||||
c->std_input = EXEC_INPUT_FILE;
|
||||
unit_write_settingf(u, flags|UNIT_ESCAPE_SPECIFIERS, name, "StandardInput=file:%s", s);
|
||||
|
||||
- } else if (streq(name, "StandardOutputFile")) {
|
||||
+ } else if (STR_IN_SET(name, "StandardOutputFile", "StandardOutputFileToAppend")) {
|
||||
r = free_and_strdup(&c->stdio_file[STDOUT_FILENO], empty_to_null(s));
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
- c->std_output = EXEC_OUTPUT_FILE;
|
||||
- unit_write_settingf(u, flags|UNIT_ESCAPE_SPECIFIERS, name, "StandardOutput=file:%s", s);
|
||||
-
|
||||
+ if (streq(name, "StandardOutputFile")) {
|
||||
+ c->std_output = EXEC_OUTPUT_FILE;
|
||||
+ unit_write_settingf(u, flags|UNIT_ESCAPE_SPECIFIERS, name, "StandardOutput=file:%s", s);
|
||||
+ } else {
|
||||
+ assert(streq(name, "StandardOutputFileToAppend"));
|
||||
+ c->std_output = EXEC_OUTPUT_FILE_APPEND;
|
||||
+ unit_write_settingf(u, flags|UNIT_ESCAPE_SPECIFIERS, name, "StandardOutput=append:%s", s);
|
||||
+ }
|
||||
} else {
|
||||
- assert(streq(name, "StandardErrorFile"));
|
||||
+ assert(STR_IN_SET(name, "StandardErrorFile", "StandardErrorFileToAppend"));
|
||||
|
||||
r = free_and_strdup(&c->stdio_file[STDERR_FILENO], empty_to_null(s));
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
- c->std_error = EXEC_OUTPUT_FILE;
|
||||
- unit_write_settingf(u, flags|UNIT_ESCAPE_SPECIFIERS, name, "StandardError=file:%s", s);
|
||||
+ if (streq(name, "StandardErrorFile")) {
|
||||
+ c->std_error = EXEC_OUTPUT_FILE;
|
||||
+ unit_write_settingf(u, flags|UNIT_ESCAPE_SPECIFIERS, name, "StandardOutput=file:%s", s);
|
||||
+ } else {
|
||||
+ assert(streq(name, "StandardErrorFileToAppend"));
|
||||
+ c->std_error = EXEC_OUTPUT_FILE_APPEND;
|
||||
+ unit_write_settingf(u, flags|UNIT_ESCAPE_SPECIFIERS, name, "StandardOutput=append:%s", s);
|
||||
+ }
|
||||
}
|
||||
}
|
||||
|
||||
diff --git a/src/core/execute.c b/src/core/execute.c
|
||||
index f012023224..3c54ac1110 100644
|
||||
--- a/src/core/execute.c
|
||||
+++ b/src/core/execute.c
|
||||
@@ -89,6 +89,7 @@
|
||||
#include "strv.h"
|
||||
#include "syslog-util.h"
|
||||
#include "terminal-util.h"
|
||||
+#include "umask-util.h"
|
||||
#include "unit.h"
|
||||
#include "user-util.h"
|
||||
#include "util.h"
|
||||
@@ -675,9 +676,10 @@ static int setup_output(
|
||||
(void) fd_nonblock(named_iofds[fileno], false);
|
||||
return dup2(named_iofds[fileno], fileno) < 0 ? -errno : fileno;
|
||||
|
||||
- case EXEC_OUTPUT_FILE: {
|
||||
+ case EXEC_OUTPUT_FILE:
|
||||
+ case EXEC_OUTPUT_FILE_APPEND: {
|
||||
bool rw;
|
||||
- int fd;
|
||||
+ int fd, flags;
|
||||
|
||||
assert(context->stdio_file[fileno]);
|
||||
|
||||
@@ -687,11 +689,16 @@ static int setup_output(
|
||||
if (rw)
|
||||
return dup2(STDIN_FILENO, fileno) < 0 ? -errno : fileno;
|
||||
|
||||
- fd = acquire_path(context->stdio_file[fileno], O_WRONLY, 0666 & ~context->umask);
|
||||
+ flags = O_WRONLY;
|
||||
+ if (o == EXEC_OUTPUT_FILE_APPEND)
|
||||
+ flags |= O_APPEND;
|
||||
+
|
||||
+ fd = acquire_path(context->stdio_file[fileno], flags, 0666 & ~context->umask);
|
||||
+
|
||||
if (fd < 0)
|
||||
return fd;
|
||||
|
||||
- return move_fd(fd, fileno, false);
|
||||
+ return move_fd(fd, fileno, 0);
|
||||
}
|
||||
|
||||
default:
|
||||
@@ -4168,8 +4175,12 @@ void exec_context_dump(const ExecContext *c, FILE* f, const char *prefix) {
|
||||
fprintf(f, "%sStandardInputFile: %s\n", prefix, c->stdio_file[STDIN_FILENO]);
|
||||
if (c->std_output == EXEC_OUTPUT_FILE)
|
||||
fprintf(f, "%sStandardOutputFile: %s\n", prefix, c->stdio_file[STDOUT_FILENO]);
|
||||
+ if (c->std_output == EXEC_OUTPUT_FILE_APPEND)
|
||||
+ fprintf(f, "%sStandardOutputFileToAppend: %s\n", prefix, c->stdio_file[STDOUT_FILENO]);
|
||||
if (c->std_error == EXEC_OUTPUT_FILE)
|
||||
fprintf(f, "%sStandardErrorFile: %s\n", prefix, c->stdio_file[STDERR_FILENO]);
|
||||
+ if (c->std_error == EXEC_OUTPUT_FILE_APPEND)
|
||||
+ fprintf(f, "%sStandardErrorFileToAppend: %s\n", prefix, c->stdio_file[STDERR_FILENO]);
|
||||
|
||||
if (c->tty_path)
|
||||
fprintf(f,
|
||||
@@ -5111,6 +5122,7 @@ static const char* const exec_output_table[_EXEC_OUTPUT_MAX] = {
|
||||
[EXEC_OUTPUT_SOCKET] = "socket",
|
||||
[EXEC_OUTPUT_NAMED_FD] = "fd",
|
||||
[EXEC_OUTPUT_FILE] = "file",
|
||||
+ [EXEC_OUTPUT_FILE_APPEND] = "append",
|
||||
};
|
||||
|
||||
DEFINE_STRING_TABLE_LOOKUP(exec_output, ExecOutput);
|
||||
diff --git a/src/core/execute.h b/src/core/execute.h
|
||||
index 2266355962..86c1cee84c 100644
|
||||
--- a/src/core/execute.h
|
||||
+++ b/src/core/execute.h
|
||||
@@ -57,6 +57,7 @@ typedef enum ExecOutput {
|
||||
EXEC_OUTPUT_SOCKET,
|
||||
EXEC_OUTPUT_NAMED_FD,
|
||||
EXEC_OUTPUT_FILE,
|
||||
+ EXEC_OUTPUT_FILE_APPEND,
|
||||
_EXEC_OUTPUT_MAX,
|
||||
_EXEC_OUTPUT_INVALID = -1
|
||||
} ExecOutput;
|
||||
diff --git a/src/core/load-fragment.c b/src/core/load-fragment.c
|
||||
index 2082166afb..9b2724307d 100644
|
||||
--- a/src/core/load-fragment.c
|
||||
+++ b/src/core/load-fragment.c
|
||||
@@ -1016,6 +1016,17 @@ int config_parse_exec_output(
|
||||
|
||||
eo = EXEC_OUTPUT_FILE;
|
||||
|
||||
+ } else if ((n = startswith(rvalue, "append:"))) {
|
||||
+
|
||||
+ r = unit_full_printf(u, n, &resolved);
|
||||
+ if (r < 0)
|
||||
+ return log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve unit specifiers in %s: %m", n);
|
||||
+
|
||||
+ r = path_simplify_and_warn(resolved, PATH_CHECK_ABSOLUTE | PATH_CHECK_FATAL, unit, filename, line, lvalue);
|
||||
+ if (r < 0)
|
||||
+ return -ENOEXEC;
|
||||
+
|
||||
+ eo = EXEC_OUTPUT_FILE_APPEND;
|
||||
} else {
|
||||
eo = exec_output_from_string(rvalue);
|
||||
if (eo < 0) {
|
||||
diff --git a/src/core/main.c b/src/core/main.c
|
||||
index 9f238a8430..25536054b3 100644
|
||||
--- a/src/core/main.c
|
||||
+++ b/src/core/main.c
|
||||
@@ -620,8 +620,8 @@ static int config_parse_output_restricted(
|
||||
return 0;
|
||||
}
|
||||
|
||||
- if (IN_SET(t, EXEC_OUTPUT_SOCKET, EXEC_OUTPUT_NAMED_FD, EXEC_OUTPUT_FILE)) {
|
||||
- log_syntax(unit, LOG_ERR, filename, line, 0, "Standard output types socket, fd:, file: are not supported as defaults, ignoring: %s", rvalue);
|
||||
+ if (IN_SET(t, EXEC_OUTPUT_SOCKET, EXEC_OUTPUT_NAMED_FD, EXEC_OUTPUT_FILE, EXEC_OUTPUT_FILE_APPEND)) {
|
||||
+ log_syntax(unit, LOG_ERR, filename, line, 0, "Standard output types socket, fd:, file:, append: are not supported as defaults, ignoring: %s", rvalue);
|
||||
return 0;
|
||||
}
|
||||
|
||||
diff --git a/src/test/test-execute.c b/src/test/test-execute.c
|
||||
index 637ffe96bb..0f8dc883b1 100644
|
||||
--- a/src/test/test-execute.c
|
||||
+++ b/src/test/test-execute.c
|
||||
@@ -651,6 +651,14 @@ static void test_exec_standardinput(Manager *m) {
|
||||
test(m, "exec-standardinput-file.service", 0, CLD_EXITED);
|
||||
}
|
||||
|
||||
+static void test_exec_standardoutput(Manager *m) {
|
||||
+ test(m, "exec-standardoutput-file.service", 0, CLD_EXITED);
|
||||
+}
|
||||
+
|
||||
+static void test_exec_standardoutput_append(Manager *m) {
|
||||
+ test(m, "exec-standardoutput-append.service", 0, CLD_EXITED);
|
||||
+}
|
||||
+
|
||||
static int run_tests(UnitFileScope scope, const test_function_t *tests) {
|
||||
const test_function_t *test = NULL;
|
||||
_cleanup_(manager_freep) Manager *m = NULL;
|
||||
@@ -698,6 +706,8 @@ int main(int argc, char *argv[]) {
|
||||
test_exec_restrictnamespaces,
|
||||
test_exec_runtimedirectory,
|
||||
test_exec_standardinput,
|
||||
+ test_exec_standardoutput,
|
||||
+ test_exec_standardoutput_append,
|
||||
test_exec_supplementarygroups,
|
||||
test_exec_systemcallerrornumber,
|
||||
test_exec_systemcallfilter,
|
||||
diff --git a/test/meson.build b/test/meson.build
|
||||
index fb9f2cdb9b..4d1c51048c 100644
|
||||
--- a/test/meson.build
|
||||
+++ b/test/meson.build
|
||||
@@ -115,6 +115,8 @@ test_data_files = '''
|
||||
test-execute/exec-specifier@.service
|
||||
test-execute/exec-standardinput-data.service
|
||||
test-execute/exec-standardinput-file.service
|
||||
+ test-execute/exec-standardoutput-file.service
|
||||
+ test-execute/exec-standardoutput-append.service
|
||||
test-execute/exec-supplementarygroups-multiple-groups-default-group-user.service
|
||||
test-execute/exec-supplementarygroups-multiple-groups-withgid.service
|
||||
test-execute/exec-supplementarygroups-multiple-groups-withuid.service
|
||||
diff --git a/test/test-execute/exec-standardoutput-append.service b/test/test-execute/exec-standardoutput-append.service
|
||||
new file mode 100644
|
||||
index 0000000000..8983bb056b
|
||||
--- /dev/null
|
||||
+++ b/test/test-execute/exec-standardoutput-append.service
|
||||
@@ -0,0 +1,13 @@
|
||||
+[Unit]
|
||||
+Description=Test for StandardOutput=append:
|
||||
+
|
||||
+[Service]
|
||||
+ExecStartPre=sh -c 'printf "hello\n" > /tmp/test-exec-standardoutput-output'
|
||||
+ExecStartPre=sh -c 'printf "hello\nhello\n" > /tmp/test-exec-standardoutput-expected'
|
||||
+StandardInput=data
|
||||
+StandardInputText=hello
|
||||
+StandardOutput=append:/tmp/test-exec-standardoutput-output
|
||||
+StandardError=null
|
||||
+ExecStart=cat
|
||||
+ExecStart=cmp /tmp/test-exec-standardoutput-output /tmp/test-exec-standardoutput-expected
|
||||
+Type=oneshot
|
||||
diff --git a/test/test-execute/exec-standardoutput-file.service b/test/test-execute/exec-standardoutput-file.service
|
||||
new file mode 100644
|
||||
index 0000000000..71e2604b94
|
||||
--- /dev/null
|
||||
+++ b/test/test-execute/exec-standardoutput-file.service
|
||||
@@ -0,0 +1,13 @@
|
||||
+[Unit]
|
||||
+Description=Test for StandardOutput=file:
|
||||
+
|
||||
+[Service]
|
||||
+ExecStartPre=sh -c 'printf "nooo\nhello\n" > /tmp/test-exec-standardoutput-output'
|
||||
+ExecStartPre=sh -c 'printf "hello\nello\n" > /tmp/test-exec-standardoutput-expected'
|
||||
+StandardInput=data
|
||||
+StandardInputText=hello
|
||||
+StandardOutput=file:/tmp/test-exec-standardoutput-output
|
||||
+StandardError=null
|
||||
+ExecStart=cat
|
||||
+ExecStart=cmp /tmp/test-exec-standardoutput-expected /tmp/test-exec-standardoutput-output
|
||||
+Type=oneshot
|
@ -0,0 +1,36 @@
|
||||
From 8ee1465520ad49892a0a378626ef93abc03f4d4e Mon Sep 17 00:00:00 2001
|
||||
From: Lennart Poettering <lennart@poettering.net>
|
||||
Date: Tue, 5 Mar 2019 18:57:53 +0100
|
||||
Subject: [PATCH] nspawn: move payload to sub-cgroup first, then sync cgroup
|
||||
trees
|
||||
|
||||
if we sync the legacy and unified trees before moving to the right
|
||||
subcgroup then ultimately the cgroup paths in the hierarchies will be
|
||||
out-of-sync... Hence, let's move the payload first, and sync then.
|
||||
|
||||
Addresses: https://github.com/systemd/systemd/pull/9762#issuecomment-441187979
|
||||
(cherry picked from commit 27da7ef0d09e00eae821f3ef26e1a666fe7aa087)
|
||||
|
||||
Resolves: #1837094
|
||||
---
|
||||
src/nspawn/nspawn.c | 4 ++--
|
||||
1 file changed, 2 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/src/nspawn/nspawn.c b/src/nspawn/nspawn.c
|
||||
index 08255b5724..8cb7591f0e 100644
|
||||
--- a/src/nspawn/nspawn.c
|
||||
+++ b/src/nspawn/nspawn.c
|
||||
@@ -3960,11 +3960,11 @@ static int run(int master,
|
||||
} else if (arg_slice || arg_property)
|
||||
log_notice("Machine and scope registration turned off, --slice= and --property= settings will have no effect.");
|
||||
|
||||
- r = sync_cgroup(*pid, arg_unified_cgroup_hierarchy, arg_uid_shift);
|
||||
+ r = create_subcgroup(*pid, arg_keep_unit, arg_unified_cgroup_hierarchy);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
- r = create_subcgroup(*pid, arg_keep_unit, arg_unified_cgroup_hierarchy);
|
||||
+ r = sync_cgroup(*pid, arg_unified_cgroup_hierarchy, arg_uid_shift);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
@ -0,0 +1,31 @@
|
||||
From f4a34d97bd7e1564a51f590df591cb31a1a3f333 Mon Sep 17 00:00:00 2001
|
||||
From: Evgeny Vereshchagin <evvers@ya.ru>
|
||||
Date: Mon, 17 Sep 2018 07:12:38 +0000
|
||||
Subject: [PATCH] nspawn: chown() the legacy hierarchy when it's used in a
|
||||
container
|
||||
|
||||
This is a follow-up to 720f0a2f3c928cc9379501a52146be9fbb4d9be2.
|
||||
|
||||
Closes https://github.com/systemd/systemd/issues/10026
|
||||
Closes https://github.com/systemd/systemd/issues/9563
|
||||
|
||||
(cherry picked from commit 89f180201cd8c0f3ce5cb6e8dd7e2b3cbcf71527)
|
||||
|
||||
Resolves: 1837094
|
||||
---
|
||||
src/nspawn/nspawn-cgroup.c | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/src/nspawn/nspawn-cgroup.c b/src/nspawn/nspawn-cgroup.c
|
||||
index d8a39a6959..a231622e29 100644
|
||||
--- a/src/nspawn/nspawn-cgroup.c
|
||||
+++ b/src/nspawn/nspawn-cgroup.c
|
||||
@@ -55,7 +55,7 @@ int chown_cgroup(pid_t pid, CGroupUnified unified_requested, uid_t uid_shift) {
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to chown() cgroup %s: %m", fs);
|
||||
|
||||
- if (unified_requested == CGROUP_UNIFIED_SYSTEMD) {
|
||||
+ if (unified_requested == CGROUP_UNIFIED_SYSTEMD || (unified_requested == CGROUP_UNIFIED_NONE && cg_unified_controller(SYSTEMD_CGROUP_CONTROLLER) > 0)) {
|
||||
_cleanup_free_ char *lfs = NULL;
|
||||
/* Always propagate access rights from unified to legacy controller */
|
||||
|
@ -0,0 +1,354 @@
|
||||
From 883dfbff6e3e9763d21f9d029a824c63e016cfd9 Mon Sep 17 00:00:00 2001
|
||||
From: Lennart Poettering <lennart@poettering.net>
|
||||
Date: Tue, 13 Nov 2018 19:57:43 +0100
|
||||
Subject: [PATCH] core: move unit_status_emit_starting_stopping_reloading() and
|
||||
related calls to job.c
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
This call is only used by job.c and very specific to job handling.
|
||||
Moreover the very similar logic of job_emit_status_message() is already
|
||||
in job.c.
|
||||
|
||||
Hence, let's clean this up, and move both sets of functions to job.c,
|
||||
and rename them a bit so that they express precisely what they do:
|
||||
|
||||
1. unit_status_emit_starting_stopping_reloading() →
|
||||
job_emit_begin_status_message()
|
||||
2. job_emit_status_message() → job_emit_done_status_message()
|
||||
|
||||
The first call is after all what we call when we begin with the
|
||||
execution of a job, and the second call what we call when we are done
|
||||
wiht it.
|
||||
|
||||
Just some moving and renaming, not other changes, and hence no change in
|
||||
behaviour.
|
||||
|
||||
(cherry picked from commit 33a3fdd9781329379f74e11a7a2707816aad8c61)
|
||||
|
||||
Related: #1737283
|
||||
---
|
||||
src/core/job.c | 119 +++++++++++++++++++++++++++++++++++++++++-------
|
||||
src/core/unit.c | 86 ----------------------------------
|
||||
src/core/unit.h | 1 -
|
||||
3 files changed, 103 insertions(+), 103 deletions(-)
|
||||
|
||||
diff --git a/src/core/job.c b/src/core/job.c
|
||||
index 769ed6d603..561ea14682 100644
|
||||
--- a/src/core/job.c
|
||||
+++ b/src/core/job.c
|
||||
@@ -507,6 +507,93 @@ static void job_change_type(Job *j, JobType newtype) {
|
||||
j->type = newtype;
|
||||
}
|
||||
|
||||
+_pure_ static const char* job_get_begin_status_message_format(Unit *u, JobType t) {
|
||||
+ const char *format;
|
||||
+ const UnitStatusMessageFormats *format_table;
|
||||
+
|
||||
+ assert(u);
|
||||
+ assert(IN_SET(t, JOB_START, JOB_STOP, JOB_RELOAD));
|
||||
+
|
||||
+ if (t != JOB_RELOAD) {
|
||||
+ format_table = &UNIT_VTABLE(u)->status_message_formats;
|
||||
+ if (format_table) {
|
||||
+ format = format_table->starting_stopping[t == JOB_STOP];
|
||||
+ if (format)
|
||||
+ return format;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ /* Return generic strings */
|
||||
+ if (t == JOB_START)
|
||||
+ return "Starting %s.";
|
||||
+ else if (t == JOB_STOP)
|
||||
+ return "Stopping %s.";
|
||||
+ else
|
||||
+ return "Reloading %s.";
|
||||
+}
|
||||
+
|
||||
+static void job_print_begin_status_message(Unit *u, JobType t) {
|
||||
+ const char *format;
|
||||
+
|
||||
+ assert(u);
|
||||
+
|
||||
+ /* Reload status messages have traditionally not been printed to console. */
|
||||
+ if (!IN_SET(t, JOB_START, JOB_STOP))
|
||||
+ return;
|
||||
+
|
||||
+ format = job_get_begin_status_message_format(u, t);
|
||||
+
|
||||
+ DISABLE_WARNING_FORMAT_NONLITERAL;
|
||||
+ unit_status_printf(u, "", format);
|
||||
+ REENABLE_WARNING;
|
||||
+}
|
||||
+
|
||||
+static void job_log_begin_status_message(Unit *u, JobType t) {
|
||||
+ const char *format, *mid;
|
||||
+ char buf[LINE_MAX];
|
||||
+
|
||||
+ assert(u);
|
||||
+
|
||||
+ if (!IN_SET(t, JOB_START, JOB_STOP, JOB_RELOAD))
|
||||
+ return;
|
||||
+
|
||||
+ if (log_on_console())
|
||||
+ return;
|
||||
+
|
||||
+ /* We log status messages for all units and all operations. */
|
||||
+
|
||||
+ format = job_get_begin_status_message_format(u, t);
|
||||
+
|
||||
+ DISABLE_WARNING_FORMAT_NONLITERAL;
|
||||
+ (void) snprintf(buf, sizeof buf, format, unit_description(u));
|
||||
+ REENABLE_WARNING;
|
||||
+
|
||||
+ mid = t == JOB_START ? "MESSAGE_ID=" SD_MESSAGE_UNIT_STARTING_STR :
|
||||
+ t == JOB_STOP ? "MESSAGE_ID=" SD_MESSAGE_UNIT_STOPPING_STR :
|
||||
+ "MESSAGE_ID=" SD_MESSAGE_UNIT_RELOADING_STR;
|
||||
+
|
||||
+ /* Note that we deliberately use LOG_MESSAGE() instead of
|
||||
+ * LOG_UNIT_MESSAGE() here, since this is supposed to mimic
|
||||
+ * closely what is written to screen using the status output,
|
||||
+ * which is supposed the highest level, friendliest output
|
||||
+ * possible, which means we should avoid the low-level unit
|
||||
+ * name. */
|
||||
+ log_struct(LOG_INFO,
|
||||
+ LOG_MESSAGE("%s", buf),
|
||||
+ LOG_UNIT_ID(u),
|
||||
+ LOG_UNIT_INVOCATION_ID(u),
|
||||
+ mid);
|
||||
+}
|
||||
+
|
||||
+static void job_emit_begin_status_message(Unit *u, JobType t) {
|
||||
+ assert(u);
|
||||
+ assert(t >= 0);
|
||||
+ assert(t < _JOB_TYPE_MAX);
|
||||
+
|
||||
+ job_log_begin_status_message(u, t);
|
||||
+ job_print_begin_status_message(u, t);
|
||||
+}
|
||||
+
|
||||
static int job_perform_on_unit(Job **j) {
|
||||
uint32_t id;
|
||||
Manager *m;
|
||||
@@ -552,7 +639,7 @@ static int job_perform_on_unit(Job **j) {
|
||||
* actually did something. */
|
||||
*j = manager_get_job(m, id);
|
||||
if (*j && r > 0)
|
||||
- unit_status_emit_starting_stopping_reloading(u, t);
|
||||
+ job_emit_begin_status_message(u, t);
|
||||
|
||||
return r;
|
||||
}
|
||||
@@ -638,7 +725,7 @@ int job_run_and_invalidate(Job *j) {
|
||||
return r;
|
||||
}
|
||||
|
||||
-_pure_ static const char *job_get_status_message_format(Unit *u, JobType t, JobResult result) {
|
||||
+_pure_ static const char *job_get_done_status_message_format(Unit *u, JobType t, JobResult result) {
|
||||
|
||||
static const char *const generic_finished_start_job[_JOB_RESULT_MAX] = {
|
||||
[JOB_DONE] = "Started %s.",
|
||||
@@ -699,7 +786,7 @@ _pure_ static const char *job_get_status_message_format(Unit *u, JobType t, JobR
|
||||
|
||||
static const struct {
|
||||
const char *color, *word;
|
||||
-} job_print_status_messages [_JOB_RESULT_MAX] = {
|
||||
+} job_print_done_status_messages[_JOB_RESULT_MAX] = {
|
||||
[JOB_DONE] = { ANSI_OK_COLOR, " OK " },
|
||||
[JOB_TIMEOUT] = { ANSI_HIGHLIGHT_RED, " TIME " },
|
||||
[JOB_FAILED] = { ANSI_HIGHLIGHT_RED, "FAILED" },
|
||||
@@ -711,7 +798,7 @@ static const struct {
|
||||
[JOB_ONCE] = { ANSI_HIGHLIGHT_RED, " ONCE " },
|
||||
};
|
||||
|
||||
-static void job_print_status_message(Unit *u, JobType t, JobResult result) {
|
||||
+static void job_print_done_status_message(Unit *u, JobType t, JobResult result) {
|
||||
const char *format;
|
||||
const char *status;
|
||||
|
||||
@@ -723,19 +810,19 @@ static void job_print_status_message(Unit *u, JobType t, JobResult result) {
|
||||
if (t == JOB_RELOAD)
|
||||
return;
|
||||
|
||||
- if (!job_print_status_messages[result].word)
|
||||
+ if (!job_print_done_status_messages[result].word)
|
||||
return;
|
||||
|
||||
- format = job_get_status_message_format(u, t, result);
|
||||
+ format = job_get_done_status_message_format(u, t, result);
|
||||
if (!format)
|
||||
return;
|
||||
|
||||
if (log_get_show_color())
|
||||
- status = strjoina(job_print_status_messages[result].color,
|
||||
- job_print_status_messages[result].word,
|
||||
+ status = strjoina(job_print_done_status_messages[result].color,
|
||||
+ job_print_done_status_messages[result].word,
|
||||
ANSI_NORMAL);
|
||||
else
|
||||
- status = job_print_status_messages[result].word;
|
||||
+ status = job_print_done_status_messages[result].word;
|
||||
|
||||
if (result != JOB_DONE)
|
||||
manager_flip_auto_status(u->manager, true);
|
||||
@@ -752,7 +839,7 @@ static void job_print_status_message(Unit *u, JobType t, JobResult result) {
|
||||
}
|
||||
}
|
||||
|
||||
-static void job_log_status_message(Unit *u, JobType t, JobResult result) {
|
||||
+static void job_log_done_status_message(Unit *u, uint32_t job_id, JobType t, JobResult result) {
|
||||
const char *format, *mid;
|
||||
char buf[LINE_MAX];
|
||||
static const int job_result_log_level[_JOB_RESULT_MAX] = {
|
||||
@@ -775,10 +862,10 @@ static void job_log_status_message(Unit *u, JobType t, JobResult result) {
|
||||
|
||||
/* Skip printing if output goes to the console, and job_print_status_message()
|
||||
will actually print something to the console. */
|
||||
- if (log_on_console() && job_print_status_messages[result].word)
|
||||
+ if (log_on_console() && job_print_done_status_messages[result].word)
|
||||
return;
|
||||
|
||||
- format = job_get_status_message_format(u, t, result);
|
||||
+ format = job_get_done_status_message_format(u, t, result);
|
||||
if (!format)
|
||||
return;
|
||||
|
||||
@@ -827,15 +914,15 @@ static void job_log_status_message(Unit *u, JobType t, JobResult result) {
|
||||
mid);
|
||||
}
|
||||
|
||||
-static void job_emit_status_message(Unit *u, JobType t, JobResult result) {
|
||||
+static void job_emit_done_status_message(Unit *u, uint32_t job_id, JobType t, JobResult result) {
|
||||
assert(u);
|
||||
|
||||
/* No message if the job did not actually do anything due to failed condition. */
|
||||
if (t == JOB_START && result == JOB_DONE && !u->condition_result)
|
||||
return;
|
||||
|
||||
- job_log_status_message(u, t, result);
|
||||
- job_print_status_message(u, t, result);
|
||||
+ job_log_done_status_message(u, job_id, t, result);
|
||||
+ job_print_done_status_message(u, t, result);
|
||||
}
|
||||
|
||||
static void job_fail_dependencies(Unit *u, UnitDependency d) {
|
||||
@@ -890,7 +977,7 @@ int job_finish_and_invalidate(Job *j, JobResult result, bool recursive, bool alr
|
||||
|
||||
/* If this job did nothing to respective unit we don't log the status message */
|
||||
if (!already)
|
||||
- job_emit_status_message(u, t, result);
|
||||
+ job_emit_done_status_message(u, j->id, t, result);
|
||||
|
||||
/* Patch restart jobs so that they become normal start jobs */
|
||||
if (result == JOB_DONE && t == JOB_RESTART) {
|
||||
diff --git a/src/core/unit.c b/src/core/unit.c
|
||||
index 40f138d25c..f5e251123d 100644
|
||||
--- a/src/core/unit.c
|
||||
+++ b/src/core/unit.c
|
||||
@@ -1624,92 +1624,6 @@ void unit_status_printf(Unit *u, const char *status, const char *unit_status_msg
|
||||
REENABLE_WARNING;
|
||||
}
|
||||
|
||||
-_pure_ static const char* unit_get_status_message_format(Unit *u, JobType t) {
|
||||
- const char *format;
|
||||
- const UnitStatusMessageFormats *format_table;
|
||||
-
|
||||
- assert(u);
|
||||
- assert(IN_SET(t, JOB_START, JOB_STOP, JOB_RELOAD));
|
||||
-
|
||||
- if (t != JOB_RELOAD) {
|
||||
- format_table = &UNIT_VTABLE(u)->status_message_formats;
|
||||
- if (format_table) {
|
||||
- format = format_table->starting_stopping[t == JOB_STOP];
|
||||
- if (format)
|
||||
- return format;
|
||||
- }
|
||||
- }
|
||||
-
|
||||
- /* Return generic strings */
|
||||
- if (t == JOB_START)
|
||||
- return "Starting %s.";
|
||||
- else if (t == JOB_STOP)
|
||||
- return "Stopping %s.";
|
||||
- else
|
||||
- return "Reloading %s.";
|
||||
-}
|
||||
-
|
||||
-static void unit_status_print_starting_stopping(Unit *u, JobType t) {
|
||||
- const char *format;
|
||||
-
|
||||
- assert(u);
|
||||
-
|
||||
- /* Reload status messages have traditionally not been printed to console. */
|
||||
- if (!IN_SET(t, JOB_START, JOB_STOP))
|
||||
- return;
|
||||
-
|
||||
- format = unit_get_status_message_format(u, t);
|
||||
-
|
||||
- DISABLE_WARNING_FORMAT_NONLITERAL;
|
||||
- unit_status_printf(u, "", format);
|
||||
- REENABLE_WARNING;
|
||||
-}
|
||||
-
|
||||
-static void unit_status_log_starting_stopping_reloading(Unit *u, JobType t) {
|
||||
- const char *format, *mid;
|
||||
- char buf[LINE_MAX];
|
||||
-
|
||||
- assert(u);
|
||||
-
|
||||
- if (!IN_SET(t, JOB_START, JOB_STOP, JOB_RELOAD))
|
||||
- return;
|
||||
-
|
||||
- if (log_on_console())
|
||||
- return;
|
||||
-
|
||||
- /* We log status messages for all units and all operations. */
|
||||
-
|
||||
- format = unit_get_status_message_format(u, t);
|
||||
-
|
||||
- DISABLE_WARNING_FORMAT_NONLITERAL;
|
||||
- (void) snprintf(buf, sizeof buf, format, unit_description(u));
|
||||
- REENABLE_WARNING;
|
||||
-
|
||||
- mid = t == JOB_START ? "MESSAGE_ID=" SD_MESSAGE_UNIT_STARTING_STR :
|
||||
- t == JOB_STOP ? "MESSAGE_ID=" SD_MESSAGE_UNIT_STOPPING_STR :
|
||||
- "MESSAGE_ID=" SD_MESSAGE_UNIT_RELOADING_STR;
|
||||
-
|
||||
- /* Note that we deliberately use LOG_MESSAGE() instead of
|
||||
- * LOG_UNIT_MESSAGE() here, since this is supposed to mimic
|
||||
- * closely what is written to screen using the status output,
|
||||
- * which is supposed the highest level, friendliest output
|
||||
- * possible, which means we should avoid the low-level unit
|
||||
- * name. */
|
||||
- log_struct(LOG_INFO,
|
||||
- LOG_MESSAGE("%s", buf),
|
||||
- LOG_UNIT_ID(u),
|
||||
- LOG_UNIT_INVOCATION_ID(u),
|
||||
- mid);
|
||||
-}
|
||||
-
|
||||
-void unit_status_emit_starting_stopping_reloading(Unit *u, JobType t) {
|
||||
- assert(u);
|
||||
- assert(t >= 0);
|
||||
- assert(t < _JOB_TYPE_MAX);
|
||||
-
|
||||
- unit_status_log_starting_stopping_reloading(u, t);
|
||||
- unit_status_print_starting_stopping(u, t);
|
||||
-}
|
||||
|
||||
int unit_start_limit_test(Unit *u) {
|
||||
assert(u);
|
||||
diff --git a/src/core/unit.h b/src/core/unit.h
|
||||
index 595ee88d43..4d9539790a 100644
|
||||
--- a/src/core/unit.h
|
||||
+++ b/src/core/unit.h
|
||||
@@ -699,7 +699,6 @@ int unit_coldplug(Unit *u);
|
||||
void unit_catchup(Unit *u);
|
||||
|
||||
void unit_status_printf(Unit *u, const char *status, const char *unit_status_msg_format) _printf_(3, 0);
|
||||
-void unit_status_emit_starting_stopping_reloading(Unit *u, JobType t);
|
||||
|
||||
bool unit_need_daemon_reload(Unit *u);
|
||||
|
@ -0,0 +1,63 @@
|
||||
From 9c543783dbe560f4dafa4c2f276e03a4bce0389e Mon Sep 17 00:00:00 2001
|
||||
From: Lennart Poettering <lennart@poettering.net>
|
||||
Date: Wed, 14 Nov 2018 11:08:16 +0100
|
||||
Subject: [PATCH] job: when a job was skipped due to a failed condition, log
|
||||
about it
|
||||
|
||||
Previously we'd neither show console status output nor log output. Let's
|
||||
fix that, and still log something.
|
||||
|
||||
(cherry picked from commit 9a80f2f4533883d272e6a436512aa7e88cedc549)
|
||||
|
||||
Related: #1737283
|
||||
---
|
||||
src/core/job.c | 22 ++++++++++++++++++----
|
||||
1 file changed, 18 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/src/core/job.c b/src/core/job.c
|
||||
index 561ea14682..b9eee91cf3 100644
|
||||
--- a/src/core/job.c
|
||||
+++ b/src/core/job.c
|
||||
@@ -810,6 +810,10 @@ static void job_print_done_status_message(Unit *u, JobType t, JobResult result)
|
||||
if (t == JOB_RELOAD)
|
||||
return;
|
||||
|
||||
+ /* No message if the job did not actually do anything due to failed condition. */
|
||||
+ if (t == JOB_START && result == JOB_DONE && !u->condition_result)
|
||||
+ return;
|
||||
+
|
||||
if (!job_print_done_status_messages[result].word)
|
||||
return;
|
||||
|
||||
@@ -865,6 +869,20 @@ static void job_log_done_status_message(Unit *u, uint32_t job_id, JobType t, Job
|
||||
if (log_on_console() && job_print_done_status_messages[result].word)
|
||||
return;
|
||||
|
||||
+ /* Show condition check message if the job did not actually do anything due to failed condition. */
|
||||
+ if (t == JOB_START && result == JOB_DONE && !u->condition_result) {
|
||||
+ log_struct(LOG_INFO,
|
||||
+ "MESSAGE=Condition check resulted in %s being skipped.", unit_description(u),
|
||||
+ "JOB_ID=%" PRIu32, job_id,
|
||||
+ "JOB_TYPE=%s", job_type_to_string(t),
|
||||
+ "JOB_RESULT=%s", job_result_to_string(result),
|
||||
+ LOG_UNIT_ID(u),
|
||||
+ LOG_UNIT_INVOCATION_ID(u),
|
||||
+ "MESSAGE_ID=" SD_MESSAGE_UNIT_STARTED_STR);
|
||||
+
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
format = job_get_done_status_message_format(u, t, result);
|
||||
if (!format)
|
||||
return;
|
||||
@@ -917,10 +935,6 @@ static void job_log_done_status_message(Unit *u, uint32_t job_id, JobType t, Job
|
||||
static void job_emit_done_status_message(Unit *u, uint32_t job_id, JobType t, JobResult result) {
|
||||
assert(u);
|
||||
|
||||
- /* No message if the job did not actually do anything due to failed condition. */
|
||||
- if (t == JOB_START && result == JOB_DONE && !u->condition_result)
|
||||
- return;
|
||||
-
|
||||
job_log_done_status_message(u, job_id, t, result);
|
||||
job_print_done_status_message(u, t, result);
|
||||
}
|
@ -0,0 +1,169 @@
|
||||
From 81c3f90d41c973a18e157c1106926711815adc0e Mon Sep 17 00:00:00 2001
|
||||
From: Lennart Poettering <lennart@poettering.net>
|
||||
Date: Mon, 10 Dec 2018 20:56:57 +0100
|
||||
Subject: [PATCH] core: split out all logic that updates a Job on a unit's
|
||||
unit_notify() invocation
|
||||
|
||||
Just some refactoring, no change in behaviour.
|
||||
|
||||
(cherry picked from commit 16c74914d233ec93012d77e5f93cf90e42939669)
|
||||
|
||||
Related: #1737283
|
||||
---
|
||||
src/core/unit.c | 136 +++++++++++++++++++++++++-----------------------
|
||||
1 file changed, 71 insertions(+), 65 deletions(-)
|
||||
|
||||
diff --git a/src/core/unit.c b/src/core/unit.c
|
||||
index f5e251123d..a4865c1da5 100644
|
||||
--- a/src/core/unit.c
|
||||
+++ b/src/core/unit.c
|
||||
@@ -2225,6 +2225,73 @@ static void unit_update_on_console(Unit *u) {
|
||||
manager_unref_console(u->manager);
|
||||
}
|
||||
|
||||
+static bool unit_process_job(Job *j, UnitActiveState ns, UnitNotifyFlags flags) {
|
||||
+ bool unexpected = false;
|
||||
+
|
||||
+ assert(j);
|
||||
+
|
||||
+ if (j->state == JOB_WAITING)
|
||||
+
|
||||
+ /* So we reached a different state for this job. Let's see if we can run it now if it failed previously
|
||||
+ * due to EAGAIN. */
|
||||
+ job_add_to_run_queue(j);
|
||||
+
|
||||
+ /* Let's check whether the unit's new state constitutes a finished job, or maybe contradicts a running job and
|
||||
+ * hence needs to invalidate jobs. */
|
||||
+
|
||||
+ switch (j->type) {
|
||||
+
|
||||
+ case JOB_START:
|
||||
+ case JOB_VERIFY_ACTIVE:
|
||||
+
|
||||
+ if (UNIT_IS_ACTIVE_OR_RELOADING(ns))
|
||||
+ job_finish_and_invalidate(j, JOB_DONE, true, false);
|
||||
+ else if (j->state == JOB_RUNNING && ns != UNIT_ACTIVATING) {
|
||||
+ unexpected = true;
|
||||
+
|
||||
+ if (UNIT_IS_INACTIVE_OR_FAILED(ns))
|
||||
+ job_finish_and_invalidate(j, ns == UNIT_FAILED ? JOB_FAILED : JOB_DONE, true, false);
|
||||
+ }
|
||||
+
|
||||
+ break;
|
||||
+
|
||||
+ case JOB_RELOAD:
|
||||
+ case JOB_RELOAD_OR_START:
|
||||
+ case JOB_TRY_RELOAD:
|
||||
+
|
||||
+ if (j->state == JOB_RUNNING) {
|
||||
+ if (ns == UNIT_ACTIVE)
|
||||
+ job_finish_and_invalidate(j, (flags & UNIT_NOTIFY_RELOAD_FAILURE) ? JOB_FAILED : JOB_DONE, true, false);
|
||||
+ else if (!IN_SET(ns, UNIT_ACTIVATING, UNIT_RELOADING)) {
|
||||
+ unexpected = true;
|
||||
+
|
||||
+ if (UNIT_IS_INACTIVE_OR_FAILED(ns))
|
||||
+ job_finish_and_invalidate(j, ns == UNIT_FAILED ? JOB_FAILED : JOB_DONE, true, false);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ break;
|
||||
+
|
||||
+ case JOB_STOP:
|
||||
+ case JOB_RESTART:
|
||||
+ case JOB_TRY_RESTART:
|
||||
+
|
||||
+ if (UNIT_IS_INACTIVE_OR_FAILED(ns))
|
||||
+ job_finish_and_invalidate(j, JOB_DONE, true, false);
|
||||
+ else if (j->state == JOB_RUNNING && ns != UNIT_DEACTIVATING) {
|
||||
+ unexpected = true;
|
||||
+ job_finish_and_invalidate(j, JOB_FAILED, true, false);
|
||||
+ }
|
||||
+
|
||||
+ break;
|
||||
+
|
||||
+ default:
|
||||
+ assert_not_reached("Job type unknown");
|
||||
+ }
|
||||
+
|
||||
+ return unexpected;
|
||||
+}
|
||||
+
|
||||
void unit_notify(Unit *u, UnitActiveState os, UnitActiveState ns, UnitNotifyFlags flags) {
|
||||
bool unexpected;
|
||||
Manager *m;
|
||||
@@ -2265,71 +2332,10 @@ void unit_notify(Unit *u, UnitActiveState os, UnitActiveState ns, UnitNotifyFlag
|
||||
|
||||
unit_update_on_console(u);
|
||||
|
||||
- if (u->job) {
|
||||
- unexpected = false;
|
||||
-
|
||||
- if (u->job->state == JOB_WAITING)
|
||||
-
|
||||
- /* So we reached a different state for this
|
||||
- * job. Let's see if we can run it now if it
|
||||
- * failed previously due to EAGAIN. */
|
||||
- job_add_to_run_queue(u->job);
|
||||
-
|
||||
- /* Let's check whether this state change constitutes a
|
||||
- * finished job, or maybe contradicts a running job and
|
||||
- * hence needs to invalidate jobs. */
|
||||
-
|
||||
- switch (u->job->type) {
|
||||
-
|
||||
- case JOB_START:
|
||||
- case JOB_VERIFY_ACTIVE:
|
||||
-
|
||||
- if (UNIT_IS_ACTIVE_OR_RELOADING(ns))
|
||||
- job_finish_and_invalidate(u->job, JOB_DONE, true, false);
|
||||
- else if (u->job->state == JOB_RUNNING && ns != UNIT_ACTIVATING) {
|
||||
- unexpected = true;
|
||||
-
|
||||
- if (UNIT_IS_INACTIVE_OR_FAILED(ns))
|
||||
- job_finish_and_invalidate(u->job, ns == UNIT_FAILED ? JOB_FAILED : JOB_DONE, true, false);
|
||||
- }
|
||||
-
|
||||
- break;
|
||||
-
|
||||
- case JOB_RELOAD:
|
||||
- case JOB_RELOAD_OR_START:
|
||||
- case JOB_TRY_RELOAD:
|
||||
-
|
||||
- if (u->job->state == JOB_RUNNING) {
|
||||
- if (ns == UNIT_ACTIVE)
|
||||
- job_finish_and_invalidate(u->job, (flags & UNIT_NOTIFY_RELOAD_FAILURE) ? JOB_FAILED : JOB_DONE, true, false);
|
||||
- else if (!IN_SET(ns, UNIT_ACTIVATING, UNIT_RELOADING)) {
|
||||
- unexpected = true;
|
||||
-
|
||||
- if (UNIT_IS_INACTIVE_OR_FAILED(ns))
|
||||
- job_finish_and_invalidate(u->job, ns == UNIT_FAILED ? JOB_FAILED : JOB_DONE, true, false);
|
||||
- }
|
||||
- }
|
||||
-
|
||||
- break;
|
||||
-
|
||||
- case JOB_STOP:
|
||||
- case JOB_RESTART:
|
||||
- case JOB_TRY_RESTART:
|
||||
-
|
||||
- if (UNIT_IS_INACTIVE_OR_FAILED(ns))
|
||||
- job_finish_and_invalidate(u->job, JOB_DONE, true, false);
|
||||
- else if (u->job->state == JOB_RUNNING && ns != UNIT_DEACTIVATING) {
|
||||
- unexpected = true;
|
||||
- job_finish_and_invalidate(u->job, JOB_FAILED, true, false);
|
||||
- }
|
||||
-
|
||||
- break;
|
||||
-
|
||||
- default:
|
||||
- assert_not_reached("Job type unknown");
|
||||
- }
|
||||
-
|
||||
- } else
|
||||
+ /* Let's propagate state changes to the job */
|
||||
+ if (u->job)
|
||||
+ unexpected = unit_process_job(u->job, ns, flags);
|
||||
+ else
|
||||
unexpected = true;
|
||||
|
||||
if (!MANAGER_IS_RELOADING(m)) {
|
@ -0,0 +1,200 @@
|
||||
From d5245b46716cf53ce4d95966ea99499cf7aa209a Mon Sep 17 00:00:00 2001
|
||||
From: Lennart Poettering <lennart@poettering.net>
|
||||
Date: Tue, 13 Nov 2018 21:25:22 +0100
|
||||
Subject: [PATCH] core: make log messages about units entering a 'failed' state
|
||||
recognizable
|
||||
|
||||
Let's make this recognizable, and carry result information in a
|
||||
structure fashion.
|
||||
|
||||
(cherry picked from commit 7c047d7443347c109daf67023a01c118b5f361eb)
|
||||
|
||||
Related: #1737283
|
||||
---
|
||||
catalog/systemd.catalog.in | 7 +++++++
|
||||
src/core/automount.c | 2 +-
|
||||
src/core/mount.c | 2 +-
|
||||
src/core/path.c | 2 +-
|
||||
src/core/scope.c | 2 +-
|
||||
src/core/service.c | 2 +-
|
||||
src/core/socket.c | 2 +-
|
||||
src/core/swap.c | 2 +-
|
||||
src/core/timer.c | 2 +-
|
||||
src/core/unit.c | 12 ++++++++++++
|
||||
src/core/unit.h | 2 ++
|
||||
src/systemd/sd-messages.h | 4 ++++
|
||||
12 files changed, 33 insertions(+), 8 deletions(-)
|
||||
|
||||
diff --git a/catalog/systemd.catalog.in b/catalog/systemd.catalog.in
|
||||
index 49a45890f6..54a0f46921 100644
|
||||
--- a/catalog/systemd.catalog.in
|
||||
+++ b/catalog/systemd.catalog.in
|
||||
@@ -344,6 +344,13 @@ Support: %SUPPORT_URL%
|
||||
|
||||
The unit @UNIT@ completed and consumed the indicated resources.
|
||||
|
||||
+-- d9b373ed55a64feb8242e02dbe79a49c
|
||||
+Subject: Unit failed
|
||||
+Defined-By: systemd
|
||||
+Support: %SUPPORT_URL%
|
||||
+
|
||||
+The unit @UNIT@ has entered the 'failed' state with result '@UNIT_RESULT@'.
|
||||
+
|
||||
-- 50876a9db00f4c40bde1a2ad381c3a1b
|
||||
Subject: The system is configured in a way that might cause problems
|
||||
Defined-By: systemd
|
||||
diff --git a/src/core/automount.c b/src/core/automount.c
|
||||
index 1b96a52c00..c78562c549 100644
|
||||
--- a/src/core/automount.c
|
||||
+++ b/src/core/automount.c
|
||||
@@ -315,7 +315,7 @@ static void automount_enter_dead(Automount *a, AutomountResult f) {
|
||||
a->result = f;
|
||||
|
||||
if (a->result != AUTOMOUNT_SUCCESS)
|
||||
- log_unit_warning(UNIT(a), "Failed with result '%s'.", automount_result_to_string(a->result));
|
||||
+ unit_log_failure(UNIT(a), automount_result_to_string(a->result));
|
||||
|
||||
automount_set_state(a, a->result != AUTOMOUNT_SUCCESS ? AUTOMOUNT_FAILED : AUTOMOUNT_DEAD);
|
||||
}
|
||||
diff --git a/src/core/mount.c b/src/core/mount.c
|
||||
index 5878814b1b..3cd0e479e9 100644
|
||||
--- a/src/core/mount.c
|
||||
+++ b/src/core/mount.c
|
||||
@@ -797,7 +797,7 @@ static void mount_enter_dead(Mount *m, MountResult f) {
|
||||
m->result = f;
|
||||
|
||||
if (m->result != MOUNT_SUCCESS)
|
||||
- log_unit_warning(UNIT(m), "Failed with result '%s'.", mount_result_to_string(m->result));
|
||||
+ unit_log_failure(UNIT(m), mount_result_to_string(m->result));
|
||||
|
||||
mount_set_state(m, m->result != MOUNT_SUCCESS ? MOUNT_FAILED : MOUNT_DEAD);
|
||||
|
||||
diff --git a/src/core/path.c b/src/core/path.c
|
||||
index 5ef178a46b..f8b69e7804 100644
|
||||
--- a/src/core/path.c
|
||||
+++ b/src/core/path.c
|
||||
@@ -449,7 +449,7 @@ static void path_enter_dead(Path *p, PathResult f) {
|
||||
p->result = f;
|
||||
|
||||
if (p->result != PATH_SUCCESS)
|
||||
- log_unit_warning(UNIT(p), "Failed with result '%s'.", path_result_to_string(p->result));
|
||||
+ unit_log_failure(UNIT(p), path_result_to_string(p->result));
|
||||
|
||||
path_set_state(p, p->result != PATH_SUCCESS ? PATH_FAILED : PATH_DEAD);
|
||||
}
|
||||
diff --git a/src/core/scope.c b/src/core/scope.c
|
||||
index 751556fecf..79ecfd992f 100644
|
||||
--- a/src/core/scope.c
|
||||
+++ b/src/core/scope.c
|
||||
@@ -240,7 +240,7 @@ static void scope_enter_dead(Scope *s, ScopeResult f) {
|
||||
s->result = f;
|
||||
|
||||
if (s->result != SCOPE_SUCCESS)
|
||||
- log_unit_warning(UNIT(s), "Failed with result '%s'.", scope_result_to_string(s->result));
|
||||
+ unit_log_failure(UNIT(s), scope_result_to_string(s->result));
|
||||
|
||||
scope_set_state(s, s->result != SCOPE_SUCCESS ? SCOPE_FAILED : SCOPE_DEAD);
|
||||
}
|
||||
diff --git a/src/core/service.c b/src/core/service.c
|
||||
index 5035dcacac..efceb0614c 100644
|
||||
--- a/src/core/service.c
|
||||
+++ b/src/core/service.c
|
||||
@@ -1680,7 +1680,7 @@ static void service_enter_dead(Service *s, ServiceResult f, bool allow_restart)
|
||||
s->result = f;
|
||||
|
||||
if (s->result != SERVICE_SUCCESS)
|
||||
- log_unit_warning(UNIT(s), "Failed with result '%s'.", service_result_to_string(s->result));
|
||||
+ unit_log_failure(UNIT(s), service_result_to_string(s->result));
|
||||
|
||||
if (allow_restart && service_shall_restart(s))
|
||||
s->will_auto_restart = true;
|
||||
diff --git a/src/core/socket.c b/src/core/socket.c
|
||||
index b034549634..160f11765c 100644
|
||||
--- a/src/core/socket.c
|
||||
+++ b/src/core/socket.c
|
||||
@@ -1991,7 +1991,7 @@ static void socket_enter_dead(Socket *s, SocketResult f) {
|
||||
s->result = f;
|
||||
|
||||
if (s->result != SOCKET_SUCCESS)
|
||||
- log_unit_warning(UNIT(s), "Failed with result '%s'.", socket_result_to_string(s->result));
|
||||
+ unit_log_failure(UNIT(s), socket_result_to_string(s->result));
|
||||
|
||||
socket_set_state(s, s->result != SOCKET_SUCCESS ? SOCKET_FAILED : SOCKET_DEAD);
|
||||
|
||||
diff --git a/src/core/swap.c b/src/core/swap.c
|
||||
index 66a62d8a37..b5926d8644 100644
|
||||
--- a/src/core/swap.c
|
||||
+++ b/src/core/swap.c
|
||||
@@ -657,7 +657,7 @@ static void swap_enter_dead(Swap *s, SwapResult f) {
|
||||
s->result = f;
|
||||
|
||||
if (s->result != SWAP_SUCCESS)
|
||||
- log_unit_warning(UNIT(s), "Failed with result '%s'.", swap_result_to_string(s->result));
|
||||
+ unit_log_failure(UNIT(s), swap_result_to_string(s->result));
|
||||
|
||||
swap_set_state(s, s->result != SWAP_SUCCESS ? SWAP_FAILED : SWAP_DEAD);
|
||||
|
||||
diff --git a/src/core/timer.c b/src/core/timer.c
|
||||
index db202971d3..6ac310cbe0 100644
|
||||
--- a/src/core/timer.c
|
||||
+++ b/src/core/timer.c
|
||||
@@ -288,7 +288,7 @@ static void timer_enter_dead(Timer *t, TimerResult f) {
|
||||
t->result = f;
|
||||
|
||||
if (t->result != TIMER_SUCCESS)
|
||||
- log_unit_warning(UNIT(t), "Failed with result '%s'.", timer_result_to_string(t->result));
|
||||
+ unit_log_failure(UNIT(t), timer_result_to_string(t->result));
|
||||
|
||||
timer_set_state(t, t->result != TIMER_SUCCESS ? TIMER_FAILED : TIMER_DEAD);
|
||||
}
|
||||
diff --git a/src/core/unit.c b/src/core/unit.c
|
||||
index a4865c1da5..f55bddc00f 100644
|
||||
--- a/src/core/unit.c
|
||||
+++ b/src/core/unit.c
|
||||
@@ -5462,6 +5462,18 @@ int unit_pid_attachable(Unit *u, pid_t pid, sd_bus_error *error) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
+void unit_log_failure(Unit *u, const char *result) {
|
||||
+ assert(u);
|
||||
+ assert(result);
|
||||
+
|
||||
+ log_struct(LOG_WARNING,
|
||||
+ "MESSAGE_ID=" SD_MESSAGE_UNIT_FAILURE_RESULT_STR,
|
||||
+ LOG_UNIT_ID(u),
|
||||
+ LOG_UNIT_INVOCATION_ID(u),
|
||||
+ LOG_UNIT_MESSAGE(u, "Failed with result '%s'.", result),
|
||||
+ "UNIT_RESULT=%s", result);
|
||||
+}
|
||||
+
|
||||
static const char* const collect_mode_table[_COLLECT_MODE_MAX] = {
|
||||
[COLLECT_INACTIVE] = "inactive",
|
||||
[COLLECT_INACTIVE_OR_FAILED] = "inactive-or-failed",
|
||||
diff --git a/src/core/unit.h b/src/core/unit.h
|
||||
index 4d9539790a..9d226fb3e0 100644
|
||||
--- a/src/core/unit.h
|
||||
+++ b/src/core/unit.h
|
||||
@@ -804,6 +804,8 @@ const char *unit_label_path(Unit *u);
|
||||
|
||||
int unit_pid_attachable(Unit *unit, pid_t pid, sd_bus_error *error);
|
||||
|
||||
+void unit_log_failure(Unit *u, const char *result);
|
||||
+
|
||||
/* Macros which append UNIT= or USER_UNIT= to the message */
|
||||
|
||||
#define log_unit_full(unit, level, error, ...) \
|
||||
diff --git a/src/systemd/sd-messages.h b/src/systemd/sd-messages.h
|
||||
index 2adfe16062..846b28fc2b 100644
|
||||
--- a/src/systemd/sd-messages.h
|
||||
+++ b/src/systemd/sd-messages.h
|
||||
@@ -106,6 +106,10 @@ _SD_BEGIN_DECLARATIONS;
|
||||
#define SD_MESSAGE_UNIT_RESOURCES SD_ID128_MAKE(ae,8f,7b,86,6b,03,47,b9,af,31,fe,1c,80,b1,27,c0)
|
||||
#define SD_MESSAGE_UNIT_RESOURCES_STR SD_ID128_MAKE_STR(ae,8f,7b,86,6b,03,47,b9,af,31,fe,1c,80,b1,27,c0)
|
||||
|
||||
+#define SD_MESSAGE_UNIT_FAILURE_RESULT SD_ID128_MAKE(d9,b3,73,ed,55,a6,4f,eb,82,42,e0,2d,be,79,a4,9c)
|
||||
+#define SD_MESSAGE_UNIT_FAILURE_RESULT_STR \
|
||||
+ SD_ID128_MAKE_STR(d9,b3,73,ed,55,a6,4f,eb,82,42,e0,2d,be,79,a4,9c)
|
||||
+
|
||||
#define SD_MESSAGE_SPAWN_FAILED SD_ID128_MAKE(64,12,57,65,1c,1b,4e,c9,a8,62,4d,7a,40,a9,e1,e7)
|
||||
#define SD_MESSAGE_SPAWN_FAILED_STR SD_ID128_MAKE_STR(64,12,57,65,1c,1b,4e,c9,a8,62,4d,7a,40,a9,e1,e7)
|
||||
|
@ -0,0 +1,210 @@
|
||||
From 40c2b0a20ff133f2050642dc7230424ddcb2987b Mon Sep 17 00:00:00 2001
|
||||
From: Lennart Poettering <lennart@poettering.net>
|
||||
Date: Tue, 13 Nov 2018 23:28:09 +0100
|
||||
Subject: [PATCH] core: log a recognizable message when a unit succeeds, too
|
||||
|
||||
We already are doing it on failure, let's do it on success, too.
|
||||
|
||||
Fixes: #10265
|
||||
(cherry picked from commit 523ee2d41471bfb738f52d59de9b469301842644)
|
||||
|
||||
Related: #1737283
|
||||
---
|
||||
catalog/systemd.catalog.in | 7 +++++++
|
||||
src/core/automount.c | 4 +++-
|
||||
src/core/mount.c | 4 +++-
|
||||
src/core/path.c | 4 +++-
|
||||
src/core/scope.c | 4 +++-
|
||||
src/core/service.c | 4 +++-
|
||||
src/core/socket.c | 4 +++-
|
||||
src/core/swap.c | 4 +++-
|
||||
src/core/timer.c | 4 +++-
|
||||
src/core/unit.c | 10 ++++++++++
|
||||
src/core/unit.h | 1 +
|
||||
src/systemd/sd-messages.h | 2 ++
|
||||
12 files changed, 44 insertions(+), 8 deletions(-)
|
||||
|
||||
diff --git a/catalog/systemd.catalog.in b/catalog/systemd.catalog.in
|
||||
index 54a0f46921..2492ad2028 100644
|
||||
--- a/catalog/systemd.catalog.in
|
||||
+++ b/catalog/systemd.catalog.in
|
||||
@@ -344,6 +344,13 @@ Support: %SUPPORT_URL%
|
||||
|
||||
The unit @UNIT@ completed and consumed the indicated resources.
|
||||
|
||||
+-- 7ad2d189f7e94e70a38c781354912448
|
||||
+Subject: Unit succeeded
|
||||
+Defined-By: systemd
|
||||
+Support: %SUPPORT_URL%
|
||||
+
|
||||
+The unit @UNIT@ has successfully entered the 'dead' state.
|
||||
+
|
||||
-- d9b373ed55a64feb8242e02dbe79a49c
|
||||
Subject: Unit failed
|
||||
Defined-By: systemd
|
||||
diff --git a/src/core/automount.c b/src/core/automount.c
|
||||
index c78562c549..b1a155d8d4 100644
|
||||
--- a/src/core/automount.c
|
||||
+++ b/src/core/automount.c
|
||||
@@ -314,7 +314,9 @@ static void automount_enter_dead(Automount *a, AutomountResult f) {
|
||||
if (a->result == AUTOMOUNT_SUCCESS)
|
||||
a->result = f;
|
||||
|
||||
- if (a->result != AUTOMOUNT_SUCCESS)
|
||||
+ if (a->result == AUTOMOUNT_SUCCESS)
|
||||
+ unit_log_success(UNIT(a));
|
||||
+ else
|
||||
unit_log_failure(UNIT(a), automount_result_to_string(a->result));
|
||||
|
||||
automount_set_state(a, a->result != AUTOMOUNT_SUCCESS ? AUTOMOUNT_FAILED : AUTOMOUNT_DEAD);
|
||||
diff --git a/src/core/mount.c b/src/core/mount.c
|
||||
index 3cd0e479e9..30aaf5ae55 100644
|
||||
--- a/src/core/mount.c
|
||||
+++ b/src/core/mount.c
|
||||
@@ -796,7 +796,9 @@ static void mount_enter_dead(Mount *m, MountResult f) {
|
||||
if (m->result == MOUNT_SUCCESS)
|
||||
m->result = f;
|
||||
|
||||
- if (m->result != MOUNT_SUCCESS)
|
||||
+ if (m->result == MOUNT_SUCCESS)
|
||||
+ unit_log_success(UNIT(m));
|
||||
+ else
|
||||
unit_log_failure(UNIT(m), mount_result_to_string(m->result));
|
||||
|
||||
mount_set_state(m, m->result != MOUNT_SUCCESS ? MOUNT_FAILED : MOUNT_DEAD);
|
||||
diff --git a/src/core/path.c b/src/core/path.c
|
||||
index f8b69e7804..dda4a3036b 100644
|
||||
--- a/src/core/path.c
|
||||
+++ b/src/core/path.c
|
||||
@@ -448,7 +448,9 @@ static void path_enter_dead(Path *p, PathResult f) {
|
||||
if (p->result == PATH_SUCCESS)
|
||||
p->result = f;
|
||||
|
||||
- if (p->result != PATH_SUCCESS)
|
||||
+ if (p->result == PATH_SUCCESS)
|
||||
+ unit_log_success(UNIT(p));
|
||||
+ else
|
||||
unit_log_failure(UNIT(p), path_result_to_string(p->result));
|
||||
|
||||
path_set_state(p, p->result != PATH_SUCCESS ? PATH_FAILED : PATH_DEAD);
|
||||
diff --git a/src/core/scope.c b/src/core/scope.c
|
||||
index 79ecfd992f..a1a5363244 100644
|
||||
--- a/src/core/scope.c
|
||||
+++ b/src/core/scope.c
|
||||
@@ -239,7 +239,9 @@ static void scope_enter_dead(Scope *s, ScopeResult f) {
|
||||
if (s->result == SCOPE_SUCCESS)
|
||||
s->result = f;
|
||||
|
||||
- if (s->result != SCOPE_SUCCESS)
|
||||
+ if (s->result == SCOPE_SUCCESS)
|
||||
+ unit_log_success(UNIT(s));
|
||||
+ else
|
||||
unit_log_failure(UNIT(s), scope_result_to_string(s->result));
|
||||
|
||||
scope_set_state(s, s->result != SCOPE_SUCCESS ? SCOPE_FAILED : SCOPE_DEAD);
|
||||
diff --git a/src/core/service.c b/src/core/service.c
|
||||
index efceb0614c..2c31e70ef6 100644
|
||||
--- a/src/core/service.c
|
||||
+++ b/src/core/service.c
|
||||
@@ -1679,7 +1679,9 @@ static void service_enter_dead(Service *s, ServiceResult f, bool allow_restart)
|
||||
if (s->result == SERVICE_SUCCESS)
|
||||
s->result = f;
|
||||
|
||||
- if (s->result != SERVICE_SUCCESS)
|
||||
+ if (s->result == SERVICE_SUCCESS)
|
||||
+ unit_log_success(UNIT(s));
|
||||
+ else
|
||||
unit_log_failure(UNIT(s), service_result_to_string(s->result));
|
||||
|
||||
if (allow_restart && service_shall_restart(s))
|
||||
diff --git a/src/core/socket.c b/src/core/socket.c
|
||||
index 160f11765c..7c6d3dfad1 100644
|
||||
--- a/src/core/socket.c
|
||||
+++ b/src/core/socket.c
|
||||
@@ -1990,7 +1990,9 @@ static void socket_enter_dead(Socket *s, SocketResult f) {
|
||||
if (s->result == SOCKET_SUCCESS)
|
||||
s->result = f;
|
||||
|
||||
- if (s->result != SOCKET_SUCCESS)
|
||||
+ if (s->result == SOCKET_SUCCESS)
|
||||
+ unit_log_success(UNIT(s));
|
||||
+ else
|
||||
unit_log_failure(UNIT(s), socket_result_to_string(s->result));
|
||||
|
||||
socket_set_state(s, s->result != SOCKET_SUCCESS ? SOCKET_FAILED : SOCKET_DEAD);
|
||||
diff --git a/src/core/swap.c b/src/core/swap.c
|
||||
index b5926d8644..a8f127f660 100644
|
||||
--- a/src/core/swap.c
|
||||
+++ b/src/core/swap.c
|
||||
@@ -656,7 +656,9 @@ static void swap_enter_dead(Swap *s, SwapResult f) {
|
||||
if (s->result == SWAP_SUCCESS)
|
||||
s->result = f;
|
||||
|
||||
- if (s->result != SWAP_SUCCESS)
|
||||
+ if (s->result == SWAP_SUCCESS)
|
||||
+ unit_log_success(UNIT(s));
|
||||
+ else
|
||||
unit_log_failure(UNIT(s), swap_result_to_string(s->result));
|
||||
|
||||
swap_set_state(s, s->result != SWAP_SUCCESS ? SWAP_FAILED : SWAP_DEAD);
|
||||
diff --git a/src/core/timer.c b/src/core/timer.c
|
||||
index 6ac310cbe0..2876d54a59 100644
|
||||
--- a/src/core/timer.c
|
||||
+++ b/src/core/timer.c
|
||||
@@ -287,7 +287,9 @@ static void timer_enter_dead(Timer *t, TimerResult f) {
|
||||
if (t->result == TIMER_SUCCESS)
|
||||
t->result = f;
|
||||
|
||||
- if (t->result != TIMER_SUCCESS)
|
||||
+ if (t->result == TIMER_SUCCESS)
|
||||
+ unit_log_success(UNIT(t));
|
||||
+ else
|
||||
unit_log_failure(UNIT(t), timer_result_to_string(t->result));
|
||||
|
||||
timer_set_state(t, t->result != TIMER_SUCCESS ? TIMER_FAILED : TIMER_DEAD);
|
||||
diff --git a/src/core/unit.c b/src/core/unit.c
|
||||
index f55bddc00f..ccb0106719 100644
|
||||
--- a/src/core/unit.c
|
||||
+++ b/src/core/unit.c
|
||||
@@ -5462,6 +5462,16 @@ int unit_pid_attachable(Unit *u, pid_t pid, sd_bus_error *error) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
+void unit_log_success(Unit *u) {
|
||||
+ assert(u);
|
||||
+
|
||||
+ log_struct(LOG_INFO,
|
||||
+ "MESSAGE_ID=" SD_MESSAGE_UNIT_SUCCESS_STR,
|
||||
+ LOG_UNIT_ID(u),
|
||||
+ LOG_UNIT_INVOCATION_ID(u),
|
||||
+ LOG_UNIT_MESSAGE(u, "Succeeded."));
|
||||
+}
|
||||
+
|
||||
void unit_log_failure(Unit *u, const char *result) {
|
||||
assert(u);
|
||||
assert(result);
|
||||
diff --git a/src/core/unit.h b/src/core/unit.h
|
||||
index 9d226fb3e0..4ae1b38624 100644
|
||||
--- a/src/core/unit.h
|
||||
+++ b/src/core/unit.h
|
||||
@@ -804,6 +804,7 @@ const char *unit_label_path(Unit *u);
|
||||
|
||||
int unit_pid_attachable(Unit *unit, pid_t pid, sd_bus_error *error);
|
||||
|
||||
+void unit_log_success(Unit *u);
|
||||
void unit_log_failure(Unit *u, const char *result);
|
||||
|
||||
/* Macros which append UNIT= or USER_UNIT= to the message */
|
||||
diff --git a/src/systemd/sd-messages.h b/src/systemd/sd-messages.h
|
||||
index 846b28fc2b..e7ef81b597 100644
|
||||
--- a/src/systemd/sd-messages.h
|
||||
+++ b/src/systemd/sd-messages.h
|
||||
@@ -106,6 +106,8 @@ _SD_BEGIN_DECLARATIONS;
|
||||
#define SD_MESSAGE_UNIT_RESOURCES SD_ID128_MAKE(ae,8f,7b,86,6b,03,47,b9,af,31,fe,1c,80,b1,27,c0)
|
||||
#define SD_MESSAGE_UNIT_RESOURCES_STR SD_ID128_MAKE_STR(ae,8f,7b,86,6b,03,47,b9,af,31,fe,1c,80,b1,27,c0)
|
||||
|
||||
+#define SD_MESSAGE_UNIT_SUCCESS SD_ID128_MAKE(7a,d2,d1,89,f7,e9,4e,70,a3,8c,78,13,54,91,24,48)
|
||||
+#define SD_MESSAGE_UNIT_SUCCESS_STR SD_ID128_MAKE_STR(7a,d2,d1,89,f7,e9,4e,70,a3,8c,78,13,54,91,24,48)
|
||||
#define SD_MESSAGE_UNIT_FAILURE_RESULT SD_ID128_MAKE(d9,b3,73,ed,55,a6,4f,eb,82,42,e0,2d,be,79,a4,9c)
|
||||
#define SD_MESSAGE_UNIT_FAILURE_RESULT_STR \
|
||||
SD_ID128_MAKE_STR(d9,b3,73,ed,55,a6,4f,eb,82,42,e0,2d,be,79,a4,9c)
|
@ -0,0 +1,113 @@
|
||||
From 9a6fa8659e7c6b18c95754e6fa9417f03b6341df Mon Sep 17 00:00:00 2001
|
||||
From: Lennart Poettering <lennart@poettering.net>
|
||||
Date: Mon, 19 Nov 2018 14:48:28 +0100
|
||||
Subject: [PATCH] tests: always use the right vtable wrapper calls
|
||||
|
||||
Prompted by https://github.com/systemd/systemd/pull/10836#discussion_r234598868
|
||||
|
||||
(cherry picked from commit bd7989a3d90e5d97e09f1eef33d09b2469a79f4d)
|
||||
|
||||
Related: #1737283
|
||||
---
|
||||
src/test/test-execute.c | 2 +-
|
||||
src/test/test-path.c | 18 +++++++++---------
|
||||
2 files changed, 10 insertions(+), 10 deletions(-)
|
||||
|
||||
diff --git a/src/test/test-execute.c b/src/test/test-execute.c
|
||||
index 0f8dc883b1..d88de52d2a 100644
|
||||
--- a/src/test/test-execute.c
|
||||
+++ b/src/test/test-execute.c
|
||||
@@ -129,7 +129,7 @@ static void test(Manager *m, const char *unit_name, int status_expected, int cod
|
||||
assert_se(unit_name);
|
||||
|
||||
assert_se(manager_load_startable_unit_or_warn(m, unit_name, NULL, &unit) >= 0);
|
||||
- assert_se(UNIT_VTABLE(unit)->start(unit) >= 0);
|
||||
+ assert_se(unit_start(unit) >= 0);
|
||||
check(m, unit, status_expected, code_expected);
|
||||
}
|
||||
|
||||
diff --git a/src/test/test-path.c b/src/test/test-path.c
|
||||
index 209eb2e366..3a1469ae02 100644
|
||||
--- a/src/test/test-path.c
|
||||
+++ b/src/test/test-path.c
|
||||
@@ -106,7 +106,7 @@ static void check_stop_unlink(Manager *m, Unit *unit, const char *test_path, con
|
||||
}
|
||||
}
|
||||
|
||||
- assert_se(UNIT_VTABLE(unit)->stop(unit) >= 0);
|
||||
+ assert_se(unit_stop(unit) >= 0);
|
||||
(void) rm_rf(test_path, REMOVE_ROOT|REMOVE_PHYSICAL);
|
||||
}
|
||||
|
||||
@@ -117,7 +117,7 @@ static void test_path_exists(Manager *m) {
|
||||
assert_se(m);
|
||||
|
||||
assert_se(manager_load_startable_unit_or_warn(m, "path-exists.path", NULL, &unit) >= 0);
|
||||
- assert_se(UNIT_VTABLE(unit)->start(unit) >= 0);
|
||||
+ assert_se(unit_start(unit) >= 0);
|
||||
|
||||
assert_se(touch(test_path) >= 0);
|
||||
|
||||
@@ -130,7 +130,7 @@ static void test_path_existsglob(Manager *m) {
|
||||
|
||||
assert_se(m);
|
||||
assert_se(manager_load_startable_unit_or_warn(m, "path-existsglob.path", NULL, &unit) >= 0);
|
||||
- assert_se(UNIT_VTABLE(unit)->start(unit) >= 0);
|
||||
+ assert_se(unit_start(unit) >= 0);
|
||||
|
||||
assert_se(touch(test_path) >= 0);
|
||||
|
||||
@@ -147,7 +147,7 @@ static void test_path_changed(Manager *m) {
|
||||
assert_se(touch(test_path) >= 0);
|
||||
|
||||
assert_se(manager_load_startable_unit_or_warn(m, "path-changed.path", NULL, &unit) >= 0);
|
||||
- assert_se(UNIT_VTABLE(unit)->start(unit) >= 0);
|
||||
+ assert_se(unit_start(unit) >= 0);
|
||||
|
||||
f = fopen(test_path, "w");
|
||||
assert_se(f);
|
||||
@@ -166,7 +166,7 @@ static void test_path_modified(Manager *m) {
|
||||
assert_se(touch(test_path) >= 0);
|
||||
|
||||
assert_se(manager_load_startable_unit_or_warn(m, "path-modified.path", NULL, &unit) >= 0);
|
||||
- assert_se(UNIT_VTABLE(unit)->start(unit) >= 0);
|
||||
+ assert_se(unit_start(unit) >= 0);
|
||||
|
||||
f = fopen(test_path, "w");
|
||||
assert_se(f);
|
||||
@@ -182,7 +182,7 @@ static void test_path_unit(Manager *m) {
|
||||
assert_se(m);
|
||||
|
||||
assert_se(manager_load_startable_unit_or_warn(m, "path-unit.path", NULL, &unit) >= 0);
|
||||
- assert_se(UNIT_VTABLE(unit)->start(unit) >= 0);
|
||||
+ assert_se(unit_start(unit) >= 0);
|
||||
|
||||
assert_se(touch(test_path) >= 0);
|
||||
|
||||
@@ -198,7 +198,7 @@ static void test_path_directorynotempty(Manager *m) {
|
||||
assert_se(access(test_path, F_OK) < 0);
|
||||
|
||||
assert_se(manager_load_startable_unit_or_warn(m, "path-directorynotempty.path", NULL, &unit) >= 0);
|
||||
- assert_se(UNIT_VTABLE(unit)->start(unit) >= 0);
|
||||
+ assert_se(unit_start(unit) >= 0);
|
||||
|
||||
/* MakeDirectory default to no */
|
||||
assert_se(access(test_path, F_OK) < 0);
|
||||
@@ -219,7 +219,7 @@ static void test_path_makedirectory_directorymode(Manager *m) {
|
||||
assert_se(access(test_path, F_OK) < 0);
|
||||
|
||||
assert_se(manager_load_startable_unit_or_warn(m, "path-makedirectory.path", NULL, &unit) >= 0);
|
||||
- assert_se(UNIT_VTABLE(unit)->start(unit) >= 0);
|
||||
+ assert_se(unit_start(unit) >= 0);
|
||||
|
||||
/* Check if the directory has been created */
|
||||
assert_se(access(test_path, F_OK) >= 0);
|
||||
@@ -230,7 +230,7 @@ static void test_path_makedirectory_directorymode(Manager *m) {
|
||||
assert_se((s.st_mode & S_IRWXG) == 0040);
|
||||
assert_se((s.st_mode & S_IRWXO) == 0004);
|
||||
|
||||
- assert_se(UNIT_VTABLE(unit)->stop(unit) >= 0);
|
||||
+ assert_se(unit_stop(unit) >= 0);
|
||||
(void) rm_rf(test_path, REMOVE_ROOT|REMOVE_PHYSICAL);
|
||||
}
|
||||
|
@ -0,0 +1,153 @@
|
||||
From 9beae637a919326ddc072c4dd53cb66e80273c8f Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= <zbyszek@in.waw.pl>
|
||||
Date: Fri, 15 Mar 2019 13:42:55 +0100
|
||||
Subject: [PATCH] test-execute: allow filtering test cases by pattern
|
||||
|
||||
When debugging failure in one of the cases, it's annoying to have to wade
|
||||
through the output from all the other cases. Let's allow picking select
|
||||
cases.
|
||||
|
||||
(cherry picked from commit 9efb96315ae502dabeb94ab35816ea8955563b7a)
|
||||
|
||||
Related: #1737283
|
||||
---
|
||||
src/test/test-execute.c | 104 ++++++++++++++++++++++------------------
|
||||
1 file changed, 58 insertions(+), 46 deletions(-)
|
||||
|
||||
diff --git a/src/test/test-execute.c b/src/test/test-execute.c
|
||||
index d88de52d2a..d077674efc 100644
|
||||
--- a/src/test/test-execute.c
|
||||
+++ b/src/test/test-execute.c
|
||||
@@ -659,8 +659,15 @@ static void test_exec_standardoutput_append(Manager *m) {
|
||||
test(m, "exec-standardoutput-append.service", 0, CLD_EXITED);
|
||||
}
|
||||
|
||||
-static int run_tests(UnitFileScope scope, const test_function_t *tests) {
|
||||
- const test_function_t *test = NULL;
|
||||
+typedef struct test_entry {
|
||||
+ test_function_t f;
|
||||
+ const char *name;
|
||||
+} test_entry;
|
||||
+
|
||||
+#define entry(x) {x, #x}
|
||||
+
|
||||
+static int run_tests(UnitFileScope scope, const test_entry tests[], char **patterns) {
|
||||
+ const test_entry *test = NULL;
|
||||
_cleanup_(manager_freep) Manager *m = NULL;
|
||||
int r;
|
||||
|
||||
@@ -674,55 +681,60 @@ static int run_tests(UnitFileScope scope, const test_function_t *tests) {
|
||||
assert_se(r >= 0);
|
||||
assert_se(manager_startup(m, NULL, NULL) >= 0);
|
||||
|
||||
- for (test = tests; test && *test; test++)
|
||||
- (*test)(m);
|
||||
+ for (test = tests; test && test->f; test++)
|
||||
+ if (strv_fnmatch_or_empty(patterns, test->name, FNM_NOESCAPE))
|
||||
+ test->f(m);
|
||||
+ else
|
||||
+ log_info("Skipping %s because it does not match any pattern.", test->name);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
+
|
||||
int main(int argc, char *argv[]) {
|
||||
_cleanup_(rm_rf_physical_and_freep) char *runtime_dir = NULL;
|
||||
- static const test_function_t user_tests[] = {
|
||||
- test_exec_basic,
|
||||
- test_exec_ambientcapabilities,
|
||||
- test_exec_bindpaths,
|
||||
- test_exec_capabilityboundingset,
|
||||
- test_exec_cpuaffinity,
|
||||
- test_exec_environment,
|
||||
- test_exec_environmentfile,
|
||||
- test_exec_group,
|
||||
- test_exec_ignoresigpipe,
|
||||
- test_exec_inaccessiblepaths,
|
||||
- test_exec_ioschedulingclass,
|
||||
- test_exec_oomscoreadjust,
|
||||
- test_exec_passenvironment,
|
||||
- test_exec_personality,
|
||||
- test_exec_privatedevices,
|
||||
- test_exec_privatenetwork,
|
||||
- test_exec_privatetmp,
|
||||
- test_exec_protectkernelmodules,
|
||||
- test_exec_readonlypaths,
|
||||
- test_exec_readwritepaths,
|
||||
- test_exec_restrictnamespaces,
|
||||
- test_exec_runtimedirectory,
|
||||
- test_exec_standardinput,
|
||||
- test_exec_standardoutput,
|
||||
- test_exec_standardoutput_append,
|
||||
- test_exec_supplementarygroups,
|
||||
- test_exec_systemcallerrornumber,
|
||||
- test_exec_systemcallfilter,
|
||||
- test_exec_temporaryfilesystem,
|
||||
- test_exec_umask,
|
||||
- test_exec_unsetenvironment,
|
||||
- test_exec_user,
|
||||
- test_exec_workingdirectory,
|
||||
- NULL,
|
||||
+ _cleanup_free_ char *test_execute_path = NULL;
|
||||
+ static const test_entry user_tests[] = {
|
||||
+ entry(test_exec_basic),
|
||||
+ entry(test_exec_ambientcapabilities),
|
||||
+ entry(test_exec_bindpaths),
|
||||
+ entry(test_exec_capabilityboundingset),
|
||||
+ entry(test_exec_cpuaffinity),
|
||||
+ entry(test_exec_environment),
|
||||
+ entry(test_exec_environmentfile),
|
||||
+ entry(test_exec_group),
|
||||
+ entry(test_exec_ignoresigpipe),
|
||||
+ entry(test_exec_inaccessiblepaths),
|
||||
+ entry(test_exec_ioschedulingclass),
|
||||
+ entry(test_exec_oomscoreadjust),
|
||||
+ entry(test_exec_passenvironment),
|
||||
+ entry(test_exec_personality),
|
||||
+ entry(test_exec_privatedevices),
|
||||
+ entry(test_exec_privatenetwork),
|
||||
+ entry(test_exec_privatetmp),
|
||||
+ entry(test_exec_protectkernelmodules),
|
||||
+ entry(test_exec_readonlypaths),
|
||||
+ entry(test_exec_readwritepaths),
|
||||
+ entry(test_exec_restrictnamespaces),
|
||||
+ entry(test_exec_runtimedirectory),
|
||||
+ entry(test_exec_standardinput),
|
||||
+ entry(test_exec_standardoutput),
|
||||
+ entry(test_exec_standardoutput_append),
|
||||
+ entry(test_exec_supplementarygroups),
|
||||
+ entry(test_exec_systemcallerrornumber),
|
||||
+ entry(test_exec_systemcallfilter),
|
||||
+ entry(test_exec_temporaryfilesystem),
|
||||
+ entry(test_exec_umask),
|
||||
+ entry(test_exec_unsetenvironment),
|
||||
+ entry(test_exec_user),
|
||||
+ entry(test_exec_workingdirectory),
|
||||
+ {},
|
||||
};
|
||||
- static const test_function_t system_tests[] = {
|
||||
- test_exec_dynamicuser,
|
||||
- test_exec_specifier,
|
||||
- test_exec_systemcallfilter_system,
|
||||
- NULL,
|
||||
+ static const test_entry system_tests[] = {
|
||||
+ entry(test_exec_dynamicuser),
|
||||
+ entry(test_exec_specifier),
|
||||
+ entry(test_exec_systemcallfilter_system),
|
||||
+ {},
|
||||
};
|
||||
int r;
|
||||
|
||||
@@ -759,9 +771,9 @@ int main(int argc, char *argv[]) {
|
||||
assert_se(unsetenv("VAR2") == 0);
|
||||
assert_se(unsetenv("VAR3") == 0);
|
||||
|
||||
- r = run_tests(UNIT_FILE_USER, user_tests);
|
||||
+ r = run_tests(UNIT_FILE_USER, user_tests, argv + 1);
|
||||
if (r != 0)
|
||||
return r;
|
||||
|
||||
- return run_tests(UNIT_FILE_SYSTEM, system_tests);
|
||||
+ return run_tests(UNIT_FILE_SYSTEM, system_tests, argv + 1);
|
||||
}
|
568
SOURCES/0383-test-execute-provide-custom-failure-message.patch
Normal file
568
SOURCES/0383-test-execute-provide-custom-failure-message.patch
Normal file
@ -0,0 +1,568 @@
|
||||
From ad8f0b480799aa7e312dacbcb0c01a3a9e6aa6db Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= <zbyszek@in.waw.pl>
|
||||
Date: Tue, 26 Mar 2019 11:38:55 +0100
|
||||
Subject: [PATCH] test-execute: provide custom failure message
|
||||
|
||||
test_exec_ambientcapabilities: exec-ambientcapabilities-nobody.service: exit status 0, expected 1
|
||||
|
||||
Sometimes we get just the last line, for example from the failure summary,
|
||||
so make it as useful as possible.
|
||||
|
||||
(cherry picked from commit 6aed6a11577b108b9a39f26aeae5e45d98f20c90)
|
||||
|
||||
Related: #1737283
|
||||
---
|
||||
src/test/test-execute.c | 236 +++++++++++++++++++++-------------------
|
||||
1 file changed, 123 insertions(+), 113 deletions(-)
|
||||
|
||||
diff --git a/src/test/test-execute.c b/src/test/test-execute.c
|
||||
index d077674efc..e42d0d30a8 100644
|
||||
--- a/src/test/test-execute.c
|
||||
+++ b/src/test/test-execute.c
|
||||
@@ -30,7 +30,7 @@
|
||||
|
||||
typedef void (*test_function_t)(Manager *m);
|
||||
|
||||
-static void check(Manager *m, Unit *unit, int status_expected, int code_expected) {
|
||||
+static void check(const char *func, Manager *m, Unit *unit, int status_expected, int code_expected) {
|
||||
Service *service = NULL;
|
||||
usec_t ts;
|
||||
usec_t timeout = 2 * USEC_PER_MINUTE;
|
||||
@@ -56,8 +56,18 @@ static void check(Manager *m, Unit *unit, int status_expected, int code_expected
|
||||
}
|
||||
}
|
||||
exec_status_dump(&service->main_exec_status, stdout, "\t");
|
||||
- assert_se(service->main_exec_status.status == status_expected);
|
||||
- assert_se(service->main_exec_status.code == code_expected);
|
||||
+ if (service->main_exec_status.status != status_expected) {
|
||||
+ log_error("%s: %s: exit status %d, expected %d",
|
||||
+ func, unit->id,
|
||||
+ service->main_exec_status.status, status_expected);
|
||||
+ abort();
|
||||
+ }
|
||||
+ if (service->main_exec_status.code != code_expected) {
|
||||
+ log_error("%s: %s: exit code %d, expected %d",
|
||||
+ func, unit->id,
|
||||
+ service->main_exec_status.code, code_expected);
|
||||
+ abort();
|
||||
+ }
|
||||
}
|
||||
|
||||
static bool check_nobody_user_and_group(void) {
|
||||
@@ -123,21 +133,21 @@ static bool is_inaccessible_available(void) {
|
||||
return true;
|
||||
}
|
||||
|
||||
-static void test(Manager *m, const char *unit_name, int status_expected, int code_expected) {
|
||||
+static void test(const char *func, Manager *m, const char *unit_name, int status_expected, int code_expected) {
|
||||
Unit *unit;
|
||||
|
||||
assert_se(unit_name);
|
||||
|
||||
assert_se(manager_load_startable_unit_or_warn(m, unit_name, NULL, &unit) >= 0);
|
||||
assert_se(unit_start(unit) >= 0);
|
||||
- check(m, unit, status_expected, code_expected);
|
||||
+ check(func, m, unit, status_expected, code_expected);
|
||||
}
|
||||
|
||||
static void test_exec_bindpaths(Manager *m) {
|
||||
assert_se(mkdir_p("/tmp/test-exec-bindpaths", 0755) >= 0);
|
||||
assert_se(mkdir_p("/tmp/test-exec-bindreadonlypaths", 0755) >= 0);
|
||||
|
||||
- test(m, "exec-bindpaths.service", 0, CLD_EXITED);
|
||||
+ test(__func__, m, "exec-bindpaths.service", 0, CLD_EXITED);
|
||||
|
||||
(void) rm_rf("/tmp/test-exec-bindpaths", REMOVE_ROOT|REMOVE_PHYSICAL);
|
||||
(void) rm_rf("/tmp/test-exec-bindreadonlypaths", REMOVE_ROOT|REMOVE_PHYSICAL);
|
||||
@@ -154,8 +164,8 @@ static void test_exec_cpuaffinity(Manager *m) {
|
||||
return;
|
||||
}
|
||||
|
||||
- test(m, "exec-cpuaffinity1.service", 0, CLD_EXITED);
|
||||
- test(m, "exec-cpuaffinity2.service", 0, CLD_EXITED);
|
||||
+ test(__func__, m, "exec-cpuaffinity1.service", 0, CLD_EXITED);
|
||||
+ test(__func__, m, "exec-cpuaffinity2.service", 0, CLD_EXITED);
|
||||
|
||||
if (!CPU_ISSET_S(1, c.allocated, c.set) ||
|
||||
!CPU_ISSET_S(2, c.allocated, c.set)) {
|
||||
@@ -163,52 +173,52 @@ static void test_exec_cpuaffinity(Manager *m) {
|
||||
return;
|
||||
}
|
||||
|
||||
- test(m, "exec-cpuaffinity3.service", 0, CLD_EXITED);
|
||||
+ test(__func__, m, "exec-cpuaffinity3.service", 0, CLD_EXITED);
|
||||
}
|
||||
|
||||
static void test_exec_workingdirectory(Manager *m) {
|
||||
assert_se(mkdir_p("/tmp/test-exec_workingdirectory", 0755) >= 0);
|
||||
|
||||
- test(m, "exec-workingdirectory.service", 0, CLD_EXITED);
|
||||
- test(m, "exec-workingdirectory-trailing-dot.service", 0, CLD_EXITED);
|
||||
+ test(__func__, m, "exec-workingdirectory.service", 0, CLD_EXITED);
|
||||
+ test(__func__, m, "exec-workingdirectory-trailing-dot.service", 0, CLD_EXITED);
|
||||
|
||||
(void) rm_rf("/tmp/test-exec_workingdirectory", REMOVE_ROOT|REMOVE_PHYSICAL);
|
||||
}
|
||||
|
||||
static void test_exec_personality(Manager *m) {
|
||||
#if defined(__x86_64__)
|
||||
- test(m, "exec-personality-x86-64.service", 0, CLD_EXITED);
|
||||
+ test(__func__, m, "exec-personality-x86-64.service", 0, CLD_EXITED);
|
||||
|
||||
#elif defined(__s390__)
|
||||
- test(m, "exec-personality-s390.service", 0, CLD_EXITED);
|
||||
+ test(__func__, m, "exec-personality-s390.service", 0, CLD_EXITED);
|
||||
|
||||
#elif defined(__powerpc64__)
|
||||
# if __BYTE_ORDER == __BIG_ENDIAN
|
||||
- test(m, "exec-personality-ppc64.service", 0, CLD_EXITED);
|
||||
+ test(__func__, m, "exec-personality-ppc64.service", 0, CLD_EXITED);
|
||||
# else
|
||||
- test(m, "exec-personality-ppc64le.service", 0, CLD_EXITED);
|
||||
+ test(__func__, m, "exec-personality-ppc64le.service", 0, CLD_EXITED);
|
||||
# endif
|
||||
|
||||
#elif defined(__aarch64__)
|
||||
- test(m, "exec-personality-aarch64.service", 0, CLD_EXITED);
|
||||
+ test(__func__, m, "exec-personality-aarch64.service", 0, CLD_EXITED);
|
||||
|
||||
#elif defined(__i386__)
|
||||
- test(m, "exec-personality-x86.service", 0, CLD_EXITED);
|
||||
+ test(__func__, m, "exec-personality-x86.service", 0, CLD_EXITED);
|
||||
#else
|
||||
log_notice("Unknown personality, skipping %s", __func__);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void test_exec_ignoresigpipe(Manager *m) {
|
||||
- test(m, "exec-ignoresigpipe-yes.service", 0, CLD_EXITED);
|
||||
- test(m, "exec-ignoresigpipe-no.service", SIGPIPE, CLD_KILLED);
|
||||
+ test(__func__, m, "exec-ignoresigpipe-yes.service", 0, CLD_EXITED);
|
||||
+ test(__func__, m, "exec-ignoresigpipe-no.service", SIGPIPE, CLD_KILLED);
|
||||
}
|
||||
|
||||
static void test_exec_privatetmp(Manager *m) {
|
||||
assert_se(touch("/tmp/test-exec_privatetmp") >= 0);
|
||||
|
||||
- test(m, "exec-privatetmp-yes.service", 0, CLD_EXITED);
|
||||
- test(m, "exec-privatetmp-no.service", 0, CLD_EXITED);
|
||||
+ test(__func__, m, "exec-privatetmp-yes.service", 0, CLD_EXITED);
|
||||
+ test(__func__, m, "exec-privatetmp-no.service", 0, CLD_EXITED);
|
||||
|
||||
unlink("/tmp/test-exec_privatetmp");
|
||||
}
|
||||
@@ -225,9 +235,9 @@ static void test_exec_privatedevices(Manager *m) {
|
||||
return;
|
||||
}
|
||||
|
||||
- test(m, "exec-privatedevices-yes.service", 0, CLD_EXITED);
|
||||
- test(m, "exec-privatedevices-no.service", 0, CLD_EXITED);
|
||||
- test(m, "exec-privatedevices-disabled-by-prefix.service", 0, CLD_EXITED);
|
||||
+ test(__func__, m, "exec-privatedevices-yes.service", 0, CLD_EXITED);
|
||||
+ test(__func__, m, "exec-privatedevices-no.service", 0, CLD_EXITED);
|
||||
+ test(__func__, m, "exec-privatedevices-disabled-by-prefix.service", 0, CLD_EXITED);
|
||||
|
||||
/* We use capsh to test if the capabilities are
|
||||
* properly set, so be sure that it exists */
|
||||
@@ -237,10 +247,10 @@ static void test_exec_privatedevices(Manager *m) {
|
||||
return;
|
||||
}
|
||||
|
||||
- test(m, "exec-privatedevices-yes-capability-mknod.service", 0, CLD_EXITED);
|
||||
- test(m, "exec-privatedevices-no-capability-mknod.service", 0, CLD_EXITED);
|
||||
- test(m, "exec-privatedevices-yes-capability-sys-rawio.service", 0, CLD_EXITED);
|
||||
- test(m, "exec-privatedevices-no-capability-sys-rawio.service", 0, CLD_EXITED);
|
||||
+ test(__func__, m, "exec-privatedevices-yes-capability-mknod.service", 0, CLD_EXITED);
|
||||
+ test(__func__, m, "exec-privatedevices-no-capability-mknod.service", 0, CLD_EXITED);
|
||||
+ test(__func__, m, "exec-privatedevices-yes-capability-sys-rawio.service", 0, CLD_EXITED);
|
||||
+ test(__func__, m, "exec-privatedevices-no-capability-sys-rawio.service", 0, CLD_EXITED);
|
||||
}
|
||||
|
||||
static void test_exec_protectkernelmodules(Manager *m) {
|
||||
@@ -261,23 +271,23 @@ static void test_exec_protectkernelmodules(Manager *m) {
|
||||
return;
|
||||
}
|
||||
|
||||
- test(m, "exec-protectkernelmodules-no-capabilities.service", 0, CLD_EXITED);
|
||||
- test(m, "exec-protectkernelmodules-yes-capabilities.service", 0, CLD_EXITED);
|
||||
- test(m, "exec-protectkernelmodules-yes-mount-propagation.service", 0, CLD_EXITED);
|
||||
+ test(__func__, m, "exec-protectkernelmodules-no-capabilities.service", 0, CLD_EXITED);
|
||||
+ test(__func__, m, "exec-protectkernelmodules-yes-capabilities.service", 0, CLD_EXITED);
|
||||
+ test(__func__, m, "exec-protectkernelmodules-yes-mount-propagation.service", 0, CLD_EXITED);
|
||||
}
|
||||
|
||||
static void test_exec_readonlypaths(Manager *m) {
|
||||
|
||||
- test(m, "exec-readonlypaths-simple.service", 0, CLD_EXITED);
|
||||
+ test(__func__, m, "exec-readonlypaths-simple.service", 0, CLD_EXITED);
|
||||
|
||||
if (path_is_read_only_fs("/var") > 0) {
|
||||
log_notice("Directory /var is readonly, skipping remaining tests in %s", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
- test(m, "exec-readonlypaths.service", 0, CLD_EXITED);
|
||||
- test(m, "exec-readonlypaths-mount-propagation.service", 0, CLD_EXITED);
|
||||
- test(m, "exec-readonlypaths-with-bindpaths.service", 0, CLD_EXITED);
|
||||
+ test(__func__, m, "exec-readonlypaths.service", 0, CLD_EXITED);
|
||||
+ test(__func__, m, "exec-readonlypaths-mount-propagation.service", 0, CLD_EXITED);
|
||||
+ test(__func__, m, "exec-readonlypaths-with-bindpaths.service", 0, CLD_EXITED);
|
||||
}
|
||||
|
||||
static void test_exec_readwritepaths(Manager *m) {
|
||||
@@ -287,7 +297,7 @@ static void test_exec_readwritepaths(Manager *m) {
|
||||
return;
|
||||
}
|
||||
|
||||
- test(m, "exec-readwritepaths-mount-propagation.service", 0, CLD_EXITED);
|
||||
+ test(__func__, m, "exec-readwritepaths-mount-propagation.service", 0, CLD_EXITED);
|
||||
}
|
||||
|
||||
static void test_exec_inaccessiblepaths(Manager *m) {
|
||||
@@ -297,22 +307,22 @@ static void test_exec_inaccessiblepaths(Manager *m) {
|
||||
return;
|
||||
}
|
||||
|
||||
- test(m, "exec-inaccessiblepaths-proc.service", 0, CLD_EXITED);
|
||||
+ test(__func__, m, "exec-inaccessiblepaths-proc.service", 0, CLD_EXITED);
|
||||
|
||||
if (path_is_read_only_fs("/") > 0) {
|
||||
log_notice("Root directory is readonly, skipping remaining tests in %s", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
- test(m, "exec-inaccessiblepaths-mount-propagation.service", 0, CLD_EXITED);
|
||||
+ test(__func__, m, "exec-inaccessiblepaths-mount-propagation.service", 0, CLD_EXITED);
|
||||
}
|
||||
|
||||
static void test_exec_temporaryfilesystem(Manager *m) {
|
||||
|
||||
- test(m, "exec-temporaryfilesystem-options.service", 0, CLD_EXITED);
|
||||
- test(m, "exec-temporaryfilesystem-ro.service", 0, CLD_EXITED);
|
||||
- test(m, "exec-temporaryfilesystem-rw.service", 0, CLD_EXITED);
|
||||
- test(m, "exec-temporaryfilesystem-usr.service", 0, CLD_EXITED);
|
||||
+ test(__func__, m, "exec-temporaryfilesystem-options.service", 0, CLD_EXITED);
|
||||
+ test(__func__, m, "exec-temporaryfilesystem-ro.service", 0, CLD_EXITED);
|
||||
+ test(__func__, m, "exec-temporaryfilesystem-rw.service", 0, CLD_EXITED);
|
||||
+ test(__func__, m, "exec-temporaryfilesystem-usr.service", 0, CLD_EXITED);
|
||||
}
|
||||
|
||||
static void test_exec_systemcallfilter(Manager *m) {
|
||||
@@ -324,10 +334,10 @@ static void test_exec_systemcallfilter(Manager *m) {
|
||||
return;
|
||||
}
|
||||
|
||||
- test(m, "exec-systemcallfilter-not-failing.service", 0, CLD_EXITED);
|
||||
- test(m, "exec-systemcallfilter-not-failing2.service", 0, CLD_EXITED);
|
||||
- test(m, "exec-systemcallfilter-failing.service", SIGSYS, CLD_KILLED);
|
||||
- test(m, "exec-systemcallfilter-failing2.service", SIGSYS, CLD_KILLED);
|
||||
+ test(__func__, m, "exec-systemcallfilter-not-failing.service", 0, CLD_EXITED);
|
||||
+ test(__func__, m, "exec-systemcallfilter-not-failing2.service", 0, CLD_EXITED);
|
||||
+ test(__func__, m, "exec-systemcallfilter-failing.service", SIGSYS, CLD_KILLED);
|
||||
+ test(__func__, m, "exec-systemcallfilter-failing2.service", SIGSYS, CLD_KILLED);
|
||||
|
||||
r = find_binary("python3", NULL);
|
||||
if (r < 0) {
|
||||
@@ -335,8 +345,8 @@ static void test_exec_systemcallfilter(Manager *m) {
|
||||
return;
|
||||
}
|
||||
|
||||
- test(m, "exec-systemcallfilter-with-errno-name.service", errno_from_name("EILSEQ"), CLD_EXITED);
|
||||
- test(m, "exec-systemcallfilter-with-errno-number.service", 255, CLD_EXITED);
|
||||
+ test(__func__, m, "exec-systemcallfilter-with-errno-name.service", errno_from_name("EILSEQ"), CLD_EXITED);
|
||||
+ test(__func__, m, "exec-systemcallfilter-with-errno-number.service", 255, CLD_EXITED);
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -355,8 +365,8 @@ static void test_exec_systemcallerrornumber(Manager *m) {
|
||||
return;
|
||||
}
|
||||
|
||||
- test(m, "exec-systemcallerrornumber-name.service", errno_from_name("EACCES"), CLD_EXITED);
|
||||
- test(m, "exec-systemcallerrornumber-number.service", 255, CLD_EXITED);
|
||||
+ test(__func__, m, "exec-systemcallerrornumber-name.service", errno_from_name("EACCES"), CLD_EXITED);
|
||||
+ test(__func__, m, "exec-systemcallerrornumber-number.service", 255, CLD_EXITED);
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -367,13 +377,13 @@ static void test_exec_restrictnamespaces(Manager *m) {
|
||||
return;
|
||||
}
|
||||
|
||||
- test(m, "exec-restrictnamespaces-no.service", 0, CLD_EXITED);
|
||||
- test(m, "exec-restrictnamespaces-yes.service", 1, CLD_EXITED);
|
||||
- test(m, "exec-restrictnamespaces-mnt.service", 0, CLD_EXITED);
|
||||
- test(m, "exec-restrictnamespaces-mnt-blacklist.service", 1, CLD_EXITED);
|
||||
- test(m, "exec-restrictnamespaces-merge-and.service", 0, CLD_EXITED);
|
||||
- test(m, "exec-restrictnamespaces-merge-or.service", 0, CLD_EXITED);
|
||||
- test(m, "exec-restrictnamespaces-merge-all.service", 0, CLD_EXITED);
|
||||
+ test(__func__, m, "exec-restrictnamespaces-no.service", 0, CLD_EXITED);
|
||||
+ test(__func__, m, "exec-restrictnamespaces-yes.service", 1, CLD_EXITED);
|
||||
+ test(__func__, m, "exec-restrictnamespaces-mnt.service", 0, CLD_EXITED);
|
||||
+ test(__func__, m, "exec-restrictnamespaces-mnt-blacklist.service", 1, CLD_EXITED);
|
||||
+ test(__func__, m, "exec-restrictnamespaces-merge-and.service", 0, CLD_EXITED);
|
||||
+ test(__func__, m, "exec-restrictnamespaces-merge-or.service", 0, CLD_EXITED);
|
||||
+ test(__func__, m, "exec-restrictnamespaces-merge-all.service", 0, CLD_EXITED);
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -384,7 +394,7 @@ static void test_exec_systemcallfilter_system(Manager *m) {
|
||||
return;
|
||||
}
|
||||
|
||||
- test(m, "exec-systemcallfilter-system-user.service", 0, CLD_EXITED);
|
||||
+ test(__func__, m, "exec-systemcallfilter-system-user.service", 0, CLD_EXITED);
|
||||
|
||||
if (!check_nobody_user_and_group()) {
|
||||
log_notice("nobody user/group is not synthesized or may conflict to other entries, skipping remaining tests in %s", __func__);
|
||||
@@ -396,12 +406,12 @@ static void test_exec_systemcallfilter_system(Manager *m) {
|
||||
return;
|
||||
}
|
||||
|
||||
- test(m, "exec-systemcallfilter-system-user-" NOBODY_USER_NAME ".service", 0, CLD_EXITED);
|
||||
+ test(__func__, m, "exec-systemcallfilter-system-user-" NOBODY_USER_NAME ".service", 0, CLD_EXITED);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void test_exec_user(Manager *m) {
|
||||
- test(m, "exec-user.service", 0, CLD_EXITED);
|
||||
+ test(__func__, m, "exec-user.service", 0, CLD_EXITED);
|
||||
|
||||
if (!check_nobody_user_and_group()) {
|
||||
log_notice("nobody user/group is not synthesized or may conflict to other entries, skipping remaining tests in %s", __func__);
|
||||
@@ -413,11 +423,11 @@ static void test_exec_user(Manager *m) {
|
||||
return;
|
||||
}
|
||||
|
||||
- test(m, "exec-user-" NOBODY_USER_NAME ".service", 0, CLD_EXITED);
|
||||
+ test(__func__, m, "exec-user-" NOBODY_USER_NAME ".service", 0, CLD_EXITED);
|
||||
}
|
||||
|
||||
static void test_exec_group(Manager *m) {
|
||||
- test(m, "exec-group.service", 0, CLD_EXITED);
|
||||
+ test(__func__, m, "exec-group.service", 0, CLD_EXITED);
|
||||
|
||||
if (!check_nobody_user_and_group()) {
|
||||
log_notice("nobody user/group is not synthesized or may conflict to other entries, skipping remaining tests in %s", __func__);
|
||||
@@ -429,31 +439,31 @@ static void test_exec_group(Manager *m) {
|
||||
return;
|
||||
}
|
||||
|
||||
- test(m, "exec-group-" NOBODY_GROUP_NAME ".service", 0, CLD_EXITED);
|
||||
+ test(__func__, m, "exec-group-" NOBODY_GROUP_NAME ".service", 0, CLD_EXITED);
|
||||
}
|
||||
|
||||
static void test_exec_supplementarygroups(Manager *m) {
|
||||
- test(m, "exec-supplementarygroups.service", 0, CLD_EXITED);
|
||||
- test(m, "exec-supplementarygroups-single-group.service", 0, CLD_EXITED);
|
||||
- test(m, "exec-supplementarygroups-single-group-user.service", 0, CLD_EXITED);
|
||||
- test(m, "exec-supplementarygroups-multiple-groups-default-group-user.service", 0, CLD_EXITED);
|
||||
- test(m, "exec-supplementarygroups-multiple-groups-withgid.service", 0, CLD_EXITED);
|
||||
- test(m, "exec-supplementarygroups-multiple-groups-withuid.service", 0, CLD_EXITED);
|
||||
+ test(__func__, m, "exec-supplementarygroups.service", 0, CLD_EXITED);
|
||||
+ test(__func__, m, "exec-supplementarygroups-single-group.service", 0, CLD_EXITED);
|
||||
+ test(__func__, m, "exec-supplementarygroups-single-group-user.service", 0, CLD_EXITED);
|
||||
+ test(__func__, m, "exec-supplementarygroups-multiple-groups-default-group-user.service", 0, CLD_EXITED);
|
||||
+ test(__func__, m, "exec-supplementarygroups-multiple-groups-withgid.service", 0, CLD_EXITED);
|
||||
+ test(__func__, m, "exec-supplementarygroups-multiple-groups-withuid.service", 0, CLD_EXITED);
|
||||
}
|
||||
|
||||
static void test_exec_dynamicuser(Manager *m) {
|
||||
- test(m, "exec-dynamicuser-fixeduser.service", 0, CLD_EXITED);
|
||||
- test(m, "exec-dynamicuser-fixeduser-one-supplementarygroup.service", 0, CLD_EXITED);
|
||||
- test(m, "exec-dynamicuser-supplementarygroups.service", 0, CLD_EXITED);
|
||||
- test(m, "exec-dynamicuser-statedir.service", 0, CLD_EXITED);
|
||||
+ test(__func__, m, "exec-dynamicuser-fixeduser.service", 0, CLD_EXITED);
|
||||
+ test(__func__, m, "exec-dynamicuser-fixeduser-one-supplementarygroup.service", 0, CLD_EXITED);
|
||||
+ test(__func__, m, "exec-dynamicuser-supplementarygroups.service", 0, CLD_EXITED);
|
||||
+ test(__func__, m, "exec-dynamicuser-statedir.service", 0, CLD_EXITED);
|
||||
|
||||
(void) rm_rf("/var/lib/test-dynamicuser-migrate", REMOVE_ROOT|REMOVE_PHYSICAL);
|
||||
(void) rm_rf("/var/lib/test-dynamicuser-migrate2", REMOVE_ROOT|REMOVE_PHYSICAL);
|
||||
(void) rm_rf("/var/lib/private/test-dynamicuser-migrate", REMOVE_ROOT|REMOVE_PHYSICAL);
|
||||
(void) rm_rf("/var/lib/private/test-dynamicuser-migrate2", REMOVE_ROOT|REMOVE_PHYSICAL);
|
||||
|
||||
- test(m, "exec-dynamicuser-statedir-migrate-step1.service", 0, CLD_EXITED);
|
||||
- test(m, "exec-dynamicuser-statedir-migrate-step2.service", 0, CLD_EXITED);
|
||||
+ test(__func__, m, "exec-dynamicuser-statedir-migrate-step1.service", 0, CLD_EXITED);
|
||||
+ test(__func__, m, "exec-dynamicuser-statedir-migrate-step2.service", 0, CLD_EXITED);
|
||||
|
||||
(void) rm_rf("/var/lib/test-dynamicuser-migrate", REMOVE_ROOT|REMOVE_PHYSICAL);
|
||||
(void) rm_rf("/var/lib/test-dynamicuser-migrate2", REMOVE_ROOT|REMOVE_PHYSICAL);
|
||||
@@ -462,9 +472,9 @@ static void test_exec_dynamicuser(Manager *m) {
|
||||
}
|
||||
|
||||
static void test_exec_environment(Manager *m) {
|
||||
- test(m, "exec-environment.service", 0, CLD_EXITED);
|
||||
- test(m, "exec-environment-multiple.service", 0, CLD_EXITED);
|
||||
- test(m, "exec-environment-empty.service", 0, CLD_EXITED);
|
||||
+ test(__func__, m, "exec-environment.service", 0, CLD_EXITED);
|
||||
+ test(__func__, m, "exec-environment-multiple.service", 0, CLD_EXITED);
|
||||
+ test(__func__, m, "exec-environment-empty.service", 0, CLD_EXITED);
|
||||
}
|
||||
|
||||
static void test_exec_environmentfile(Manager *m) {
|
||||
@@ -484,7 +494,7 @@ static void test_exec_environmentfile(Manager *m) {
|
||||
r = write_string_file("/tmp/test-exec_environmentfile.conf", e, WRITE_STRING_FILE_CREATE);
|
||||
assert_se(r == 0);
|
||||
|
||||
- test(m, "exec-environmentfile.service", 0, CLD_EXITED);
|
||||
+ test(__func__, m, "exec-environmentfile.service", 0, CLD_EXITED);
|
||||
|
||||
(void) unlink("/tmp/test-exec_environmentfile.conf");
|
||||
}
|
||||
@@ -506,26 +516,26 @@ static void test_exec_passenvironment(Manager *m) {
|
||||
assert_se(setenv("VAR3", "$word 5 6", 1) == 0);
|
||||
assert_se(setenv("VAR4", "new\nline", 1) == 0);
|
||||
assert_se(setenv("VAR5", "passwordwithbackslashes", 1) == 0);
|
||||
- test(m, "exec-passenvironment.service", 0, CLD_EXITED);
|
||||
- test(m, "exec-passenvironment-repeated.service", 0, CLD_EXITED);
|
||||
- test(m, "exec-passenvironment-empty.service", 0, CLD_EXITED);
|
||||
+ test(__func__, m, "exec-passenvironment.service", 0, CLD_EXITED);
|
||||
+ test(__func__, m, "exec-passenvironment-repeated.service", 0, CLD_EXITED);
|
||||
+ test(__func__, m, "exec-passenvironment-empty.service", 0, CLD_EXITED);
|
||||
assert_se(unsetenv("VAR1") == 0);
|
||||
assert_se(unsetenv("VAR2") == 0);
|
||||
assert_se(unsetenv("VAR3") == 0);
|
||||
assert_se(unsetenv("VAR4") == 0);
|
||||
assert_se(unsetenv("VAR5") == 0);
|
||||
- test(m, "exec-passenvironment-absent.service", 0, CLD_EXITED);
|
||||
+ test(__func__, m, "exec-passenvironment-absent.service", 0, CLD_EXITED);
|
||||
}
|
||||
|
||||
static void test_exec_umask(Manager *m) {
|
||||
- test(m, "exec-umask-default.service", 0, CLD_EXITED);
|
||||
- test(m, "exec-umask-0177.service", 0, CLD_EXITED);
|
||||
+ test(__func__, m, "exec-umask-default.service", 0, CLD_EXITED);
|
||||
+ test(__func__, m, "exec-umask-0177.service", 0, CLD_EXITED);
|
||||
}
|
||||
|
||||
static void test_exec_runtimedirectory(Manager *m) {
|
||||
- test(m, "exec-runtimedirectory.service", 0, CLD_EXITED);
|
||||
- test(m, "exec-runtimedirectory-mode.service", 0, CLD_EXITED);
|
||||
- test(m, "exec-runtimedirectory-owner.service", 0, CLD_EXITED);
|
||||
+ test(__func__, m, "exec-runtimedirectory.service", 0, CLD_EXITED);
|
||||
+ test(__func__, m, "exec-runtimedirectory-mode.service", 0, CLD_EXITED);
|
||||
+ test(__func__, m, "exec-runtimedirectory-owner.service", 0, CLD_EXITED);
|
||||
|
||||
if (!check_nobody_user_and_group()) {
|
||||
log_notice("nobody user/group is not synthesized or may conflict to other entries, skipping remaining tests in %s", __func__);
|
||||
@@ -537,7 +547,7 @@ static void test_exec_runtimedirectory(Manager *m) {
|
||||
return;
|
||||
}
|
||||
|
||||
- test(m, "exec-runtimedirectory-owner-" NOBODY_GROUP_NAME ".service", 0, CLD_EXITED);
|
||||
+ test(__func__, m, "exec-runtimedirectory-owner-" NOBODY_GROUP_NAME ".service", 0, CLD_EXITED);
|
||||
}
|
||||
|
||||
static void test_exec_capabilityboundingset(Manager *m) {
|
||||
@@ -556,14 +566,14 @@ static void test_exec_capabilityboundingset(Manager *m) {
|
||||
return;
|
||||
}
|
||||
|
||||
- test(m, "exec-capabilityboundingset-simple.service", 0, CLD_EXITED);
|
||||
- test(m, "exec-capabilityboundingset-reset.service", 0, CLD_EXITED);
|
||||
- test(m, "exec-capabilityboundingset-merge.service", 0, CLD_EXITED);
|
||||
- test(m, "exec-capabilityboundingset-invert.service", 0, CLD_EXITED);
|
||||
+ test(__func__, m, "exec-capabilityboundingset-simple.service", 0, CLD_EXITED);
|
||||
+ test(__func__, m, "exec-capabilityboundingset-reset.service", 0, CLD_EXITED);
|
||||
+ test(__func__, m, "exec-capabilityboundingset-merge.service", 0, CLD_EXITED);
|
||||
+ test(__func__, m, "exec-capabilityboundingset-invert.service", 0, CLD_EXITED);
|
||||
}
|
||||
|
||||
static void test_exec_basic(Manager *m) {
|
||||
- test(m, "exec-basic.service", 0, CLD_EXITED);
|
||||
+ test(__func__, m, "exec-basic.service", 0, CLD_EXITED);
|
||||
}
|
||||
|
||||
static void test_exec_ambientcapabilities(Manager *m) {
|
||||
@@ -585,8 +595,8 @@ static void test_exec_ambientcapabilities(Manager *m) {
|
||||
return;
|
||||
}
|
||||
|
||||
- test(m, "exec-ambientcapabilities.service", 0, CLD_EXITED);
|
||||
- test(m, "exec-ambientcapabilities-merge.service", 0, CLD_EXITED);
|
||||
+ test(__func__, m, "exec-ambientcapabilities.service", 0, CLD_EXITED);
|
||||
+ test(__func__, m, "exec-ambientcapabilities-merge.service", 0, CLD_EXITED);
|
||||
|
||||
if (!check_nobody_user_and_group()) {
|
||||
log_notice("nobody user/group is not synthesized or may conflict to other entries, skipping remaining tests in %s", __func__);
|
||||
@@ -598,8 +608,8 @@ static void test_exec_ambientcapabilities(Manager *m) {
|
||||
return;
|
||||
}
|
||||
|
||||
- test(m, "exec-ambientcapabilities-" NOBODY_USER_NAME ".service", 0, CLD_EXITED);
|
||||
- test(m, "exec-ambientcapabilities-merge-" NOBODY_USER_NAME ".service", 0, CLD_EXITED);
|
||||
+ test(__func__, m, "exec-ambientcapabilities-" NOBODY_USER_NAME ".service", 0, CLD_EXITED);
|
||||
+ test(__func__, m, "exec-ambientcapabilities-merge-" NOBODY_USER_NAME ".service", 0, CLD_EXITED);
|
||||
}
|
||||
|
||||
static void test_exec_privatenetwork(Manager *m) {
|
||||
@@ -611,52 +621,52 @@ static void test_exec_privatenetwork(Manager *m) {
|
||||
return;
|
||||
}
|
||||
|
||||
- test(m, "exec-privatenetwork-yes.service", 0, CLD_EXITED);
|
||||
+ test(__func__, m, "exec-privatenetwork-yes.service", 0, CLD_EXITED);
|
||||
}
|
||||
|
||||
static void test_exec_oomscoreadjust(Manager *m) {
|
||||
- test(m, "exec-oomscoreadjust-positive.service", 0, CLD_EXITED);
|
||||
+ test(__func__, m, "exec-oomscoreadjust-positive.service", 0, CLD_EXITED);
|
||||
|
||||
if (detect_container() > 0) {
|
||||
log_notice("Testing in container, skipping remaining tests in %s", __func__);
|
||||
return;
|
||||
}
|
||||
- test(m, "exec-oomscoreadjust-negative.service", 0, CLD_EXITED);
|
||||
+ test(__func__, m, "exec-oomscoreadjust-negative.service", 0, CLD_EXITED);
|
||||
}
|
||||
|
||||
static void test_exec_ioschedulingclass(Manager *m) {
|
||||
- test(m, "exec-ioschedulingclass-none.service", 0, CLD_EXITED);
|
||||
- test(m, "exec-ioschedulingclass-idle.service", 0, CLD_EXITED);
|
||||
- test(m, "exec-ioschedulingclass-best-effort.service", 0, CLD_EXITED);
|
||||
+ test(__func__, m, "exec-ioschedulingclass-none.service", 0, CLD_EXITED);
|
||||
+ test(__func__, m, "exec-ioschedulingclass-idle.service", 0, CLD_EXITED);
|
||||
+ test(__func__, m, "exec-ioschedulingclass-best-effort.service", 0, CLD_EXITED);
|
||||
|
||||
if (detect_container() > 0) {
|
||||
log_notice("Testing in container, skipping remaining tests in %s", __func__);
|
||||
return;
|
||||
}
|
||||
- test(m, "exec-ioschedulingclass-realtime.service", 0, CLD_EXITED);
|
||||
+ test(__func__, m, "exec-ioschedulingclass-realtime.service", 0, CLD_EXITED);
|
||||
}
|
||||
|
||||
static void test_exec_unsetenvironment(Manager *m) {
|
||||
- test(m, "exec-unsetenvironment.service", 0, CLD_EXITED);
|
||||
+ test(__func__, m, "exec-unsetenvironment.service", 0, CLD_EXITED);
|
||||
}
|
||||
|
||||
static void test_exec_specifier(Manager *m) {
|
||||
- test(m, "exec-specifier.service", 0, CLD_EXITED);
|
||||
- test(m, "exec-specifier@foo-bar.service", 0, CLD_EXITED);
|
||||
- test(m, "exec-specifier-interpolation.service", 0, CLD_EXITED);
|
||||
+ test(__func__, m, "exec-specifier.service", 0, CLD_EXITED);
|
||||
+ test(__func__, m, "exec-specifier@foo-bar.service", 0, CLD_EXITED);
|
||||
+ test(__func__, m, "exec-specifier-interpolation.service", 0, CLD_EXITED);
|
||||
}
|
||||
|
||||
static void test_exec_standardinput(Manager *m) {
|
||||
- test(m, "exec-standardinput-data.service", 0, CLD_EXITED);
|
||||
- test(m, "exec-standardinput-file.service", 0, CLD_EXITED);
|
||||
+ test(__func__, m, "exec-standardinput-data.service", 0, CLD_EXITED);
|
||||
+ test(__func__, m, "exec-standardinput-file.service", 0, CLD_EXITED);
|
||||
}
|
||||
|
||||
static void test_exec_standardoutput(Manager *m) {
|
||||
- test(m, "exec-standardoutput-file.service", 0, CLD_EXITED);
|
||||
+ test(__func__, m, "exec-standardoutput-file.service", 0, CLD_EXITED);
|
||||
}
|
||||
|
||||
static void test_exec_standardoutput_append(Manager *m) {
|
||||
- test(m, "exec-standardoutput-append.service", 0, CLD_EXITED);
|
||||
+ test(__func__, m, "exec-standardoutput-append.service", 0, CLD_EXITED);
|
||||
}
|
||||
|
||||
typedef struct test_entry {
|
738
SOURCES/0384-core-ExecCondition-for-services.patch
Normal file
738
SOURCES/0384-core-ExecCondition-for-services.patch
Normal file
@ -0,0 +1,738 @@
|
||||
From ab9c835796a27f0fbaee75a90f0311ec456941d8 Mon Sep 17 00:00:00 2001
|
||||
From: Anita Zhang <the.anitazha@gmail.com>
|
||||
Date: Fri, 28 Jun 2019 17:02:30 -0700
|
||||
Subject: [PATCH] core: ExecCondition= for services
|
||||
|
||||
Closes #10596
|
||||
|
||||
(cherry picked from commit 31cd5f63ce86a0784c4ef869c4d323a11ff14adc)
|
||||
|
||||
Resolves: #1737283
|
||||
---
|
||||
TODO | 2 -
|
||||
catalog/systemd.catalog.in | 7 ++
|
||||
doc/TRANSIENT-SETTINGS.md | 1 +
|
||||
man/systemd.service.xml | 20 ++++
|
||||
src/basic/unit-def.c | 1 +
|
||||
src/basic/unit-def.h | 1 +
|
||||
src/core/dbus-service.c | 1 +
|
||||
src/core/job.c | 3 +-
|
||||
src/core/job.h | 2 +-
|
||||
src/core/load-fragment-gperf.gperf.m4 | 1 +
|
||||
src/core/service.c | 93 ++++++++++++++++---
|
||||
src/core/service.h | 2 +
|
||||
src/core/unit.c | 25 ++++-
|
||||
src/core/unit.h | 4 +
|
||||
src/shared/bus-unit-util.c | 2 +-
|
||||
src/systemd/sd-messages.h | 2 +
|
||||
src/test/test-execute.c | 50 +++++++++-
|
||||
test/fuzz/fuzz-unit-file/directives.service | 1 +
|
||||
test/meson.build | 2 +
|
||||
.../exec-condition-failed.service | 11 +++
|
||||
test/test-execute/exec-condition-skip.service | 15 +++
|
||||
21 files changed, 222 insertions(+), 24 deletions(-)
|
||||
create mode 100644 test/test-execute/exec-condition-failed.service
|
||||
create mode 100644 test/test-execute/exec-condition-skip.service
|
||||
|
||||
diff --git a/TODO b/TODO
|
||||
index ff1008accf..8f78000089 100644
|
||||
--- a/TODO
|
||||
+++ b/TODO
|
||||
@@ -626,8 +626,6 @@ Features:
|
||||
|
||||
* merge unit_kill_common() and unit_kill_context()
|
||||
|
||||
-* introduce ExecCondition= in services
|
||||
-
|
||||
* EFI:
|
||||
- honor language efi variables for default language selection (if there are any?)
|
||||
- honor timezone efi variables for default timezone selection (if there are any?)
|
||||
diff --git a/catalog/systemd.catalog.in b/catalog/systemd.catalog.in
|
||||
index 2492ad2028..dc44414f9d 100644
|
||||
--- a/catalog/systemd.catalog.in
|
||||
+++ b/catalog/systemd.catalog.in
|
||||
@@ -358,6 +358,13 @@ Support: %SUPPORT_URL%
|
||||
|
||||
The unit @UNIT@ has entered the 'failed' state with result '@UNIT_RESULT@'.
|
||||
|
||||
+-- 0e4284a0caca4bfc81c0bb6786972673
|
||||
+Subject: Unit skipped
|
||||
+Defined-By: systemd
|
||||
+Support: %SUPPORT_URL%
|
||||
+
|
||||
+The unit @UNIT@ was skipped and has entered the 'dead' state with result '@UNIT_RESULT@'.
|
||||
+
|
||||
-- 50876a9db00f4c40bde1a2ad381c3a1b
|
||||
Subject: The system is configured in a way that might cause problems
|
||||
Defined-By: systemd
|
||||
diff --git a/doc/TRANSIENT-SETTINGS.md b/doc/TRANSIENT-SETTINGS.md
|
||||
index 0b2ad66dcb..23fe84e4d1 100644
|
||||
--- a/doc/TRANSIENT-SETTINGS.md
|
||||
+++ b/doc/TRANSIENT-SETTINGS.md
|
||||
@@ -267,6 +267,7 @@ Most service unit settings are available for transient units.
|
||||
|
||||
```
|
||||
✓ PIDFile=
|
||||
+✓ ExecCondition=
|
||||
✓ ExecStartPre=
|
||||
✓ ExecStart=
|
||||
✓ ExecStartPost=
|
||||
diff --git a/man/systemd.service.xml b/man/systemd.service.xml
|
||||
index 315b80e704..54586d1948 100644
|
||||
--- a/man/systemd.service.xml
|
||||
+++ b/man/systemd.service.xml
|
||||
@@ -414,6 +414,26 @@
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
+ <varlistentry>
|
||||
+ <term><varname>ExecCondition=</varname></term>
|
||||
+ <listitem><para>Optional commands that are executed before the command(s) in <varname>ExecStartPre=</varname>.
|
||||
+ Syntax is the same as for <varname>ExecStart=</varname>, except that multiple command lines are allowed and the
|
||||
+ commands are executed one after the other, serially.</para>
|
||||
+
|
||||
+ <para>The behavior is like an <varname>ExecStartPre=</varname> and condition check hybrid: when an
|
||||
+ <varname>ExecCondition=</varname> command exits with exit code 1 through 254 (inclusive), the remaining
|
||||
+ commands are skipped and the unit is <emphasis>not</emphasis> marked as failed. However, if an
|
||||
+ <varname>ExecCondition=</varname> command exits with 255 or abnormally (e.g. timeout, killed by a
|
||||
+ signal, etc.), the unit will be considered failed (and remaining commands will be skipped). Exit code of 0 or
|
||||
+ those matching <varname>SuccessExitStatus=</varname> will continue execution to the next command(s).</para>
|
||||
+
|
||||
+ <para>The same recommendations about not running long-running processes in <varname>ExecStartPre=</varname>
|
||||
+ also applies to <varname>ExecCondition=</varname>. <varname>ExecCondition=</varname> will also run the commands
|
||||
+ in <varname>ExecStopPost=</varname>, as part of stopping the service, in the case of any non-zero or abnormal
|
||||
+ exits, like the ones described above.</para>
|
||||
+ </listitem>
|
||||
+ </varlistentry>
|
||||
+
|
||||
<varlistentry>
|
||||
<term><varname>ExecReload=</varname></term>
|
||||
<listitem><para>Commands to execute to trigger a configuration
|
||||
diff --git a/src/basic/unit-def.c b/src/basic/unit-def.c
|
||||
index ac6a9b37e8..46593f6e65 100644
|
||||
--- a/src/basic/unit-def.c
|
||||
+++ b/src/basic/unit-def.c
|
||||
@@ -162,6 +162,7 @@ DEFINE_STRING_TABLE_LOOKUP(scope_state, ScopeState);
|
||||
|
||||
static const char* const service_state_table[_SERVICE_STATE_MAX] = {
|
||||
[SERVICE_DEAD] = "dead",
|
||||
+ [SERVICE_CONDITION] = "condition",
|
||||
[SERVICE_START_PRE] = "start-pre",
|
||||
[SERVICE_START] = "start",
|
||||
[SERVICE_START_POST] = "start-post",
|
||||
diff --git a/src/basic/unit-def.h b/src/basic/unit-def.h
|
||||
index d7e2d74669..db397a31ed 100644
|
||||
--- a/src/basic/unit-def.h
|
||||
+++ b/src/basic/unit-def.h
|
||||
@@ -101,6 +101,7 @@ typedef enum ScopeState {
|
||||
|
||||
typedef enum ServiceState {
|
||||
SERVICE_DEAD,
|
||||
+ SERVICE_CONDITION,
|
||||
SERVICE_START_PRE,
|
||||
SERVICE_START,
|
||||
SERVICE_START_POST,
|
||||
diff --git a/src/core/dbus-service.c b/src/core/dbus-service.c
|
||||
index 1b4c98c7d2..5f768a77c8 100644
|
||||
--- a/src/core/dbus-service.c
|
||||
+++ b/src/core/dbus-service.c
|
||||
@@ -127,6 +127,7 @@ const sd_bus_vtable bus_service_vtable[] = {
|
||||
SD_BUS_PROPERTY("NRestarts", "u", bus_property_get_unsigned, offsetof(Service, n_restarts), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
|
||||
|
||||
BUS_EXEC_STATUS_VTABLE("ExecMain", offsetof(Service, main_exec_status), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
|
||||
+ BUS_EXEC_COMMAND_LIST_VTABLE("ExecCondition", offsetof(Service, exec_command[SERVICE_EXEC_CONDITION]), SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION),
|
||||
BUS_EXEC_COMMAND_LIST_VTABLE("ExecStartPre", offsetof(Service, exec_command[SERVICE_EXEC_START_PRE]), SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION),
|
||||
BUS_EXEC_COMMAND_LIST_VTABLE("ExecStart", offsetof(Service, exec_command[SERVICE_EXEC_START]), SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION),
|
||||
BUS_EXEC_COMMAND_LIST_VTABLE("ExecStartPost", offsetof(Service, exec_command[SERVICE_EXEC_START_POST]), SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION),
|
||||
diff --git a/src/core/job.c b/src/core/job.c
|
||||
index b9eee91cf3..870ec0a387 100644
|
||||
--- a/src/core/job.c
|
||||
+++ b/src/core/job.c
|
||||
@@ -870,7 +870,8 @@ static void job_log_done_status_message(Unit *u, uint32_t job_id, JobType t, Job
|
||||
return;
|
||||
|
||||
/* Show condition check message if the job did not actually do anything due to failed condition. */
|
||||
- if (t == JOB_START && result == JOB_DONE && !u->condition_result) {
|
||||
+ if ((t == JOB_START && result == JOB_DONE && !u->condition_result) ||
|
||||
+ (t == JOB_START && result == JOB_SKIPPED)) {
|
||||
log_struct(LOG_INFO,
|
||||
"MESSAGE=Condition check resulted in %s being skipped.", unit_description(u),
|
||||
"JOB_ID=%" PRIu32, job_id,
|
||||
diff --git a/src/core/job.h b/src/core/job.h
|
||||
index 2f5f3f3989..189fea20ca 100644
|
||||
--- a/src/core/job.h
|
||||
+++ b/src/core/job.h
|
||||
@@ -85,7 +85,7 @@ enum JobResult {
|
||||
JOB_TIMEOUT, /* Job timeout elapsed */
|
||||
JOB_FAILED, /* Job failed */
|
||||
JOB_DEPENDENCY, /* A required dependency job did not result in JOB_DONE */
|
||||
- JOB_SKIPPED, /* Negative result of JOB_VERIFY_ACTIVE */
|
||||
+ JOB_SKIPPED, /* Negative result of JOB_VERIFY_ACTIVE or skip due to ExecCondition= */
|
||||
JOB_INVALID, /* JOB_RELOAD of inactive unit */
|
||||
JOB_ASSERT, /* Couldn't start a unit, because an assert didn't hold */
|
||||
JOB_UNSUPPORTED, /* Couldn't start a unit, because the unit type is not supported on the system */
|
||||
diff --git a/src/core/load-fragment-gperf.gperf.m4 b/src/core/load-fragment-gperf.gperf.m4
|
||||
index 161c5a2c82..8883818ff2 100644
|
||||
--- a/src/core/load-fragment-gperf.gperf.m4
|
||||
+++ b/src/core/load-fragment-gperf.gperf.m4
|
||||
@@ -291,6 +291,7 @@ Unit.AssertNull, config_parse_unit_condition_null, 0,
|
||||
Unit.CollectMode, config_parse_collect_mode, 0, offsetof(Unit, collect_mode)
|
||||
m4_dnl
|
||||
Service.PIDFile, config_parse_unit_path_printf, 0, offsetof(Service, pid_file)
|
||||
+Service.ExecCondition, config_parse_exec, SERVICE_EXEC_CONDITION, offsetof(Service, exec_command)
|
||||
Service.ExecStartPre, config_parse_exec, SERVICE_EXEC_START_PRE, offsetof(Service, exec_command)
|
||||
Service.ExecStart, config_parse_exec, SERVICE_EXEC_START, offsetof(Service, exec_command)
|
||||
Service.ExecStartPost, config_parse_exec, SERVICE_EXEC_START_POST, offsetof(Service, exec_command)
|
||||
diff --git a/src/core/service.c b/src/core/service.c
|
||||
index 2c31e70ef6..92be4280f6 100644
|
||||
--- a/src/core/service.c
|
||||
+++ b/src/core/service.c
|
||||
@@ -41,6 +41,7 @@
|
||||
|
||||
static const UnitActiveState state_translation_table[_SERVICE_STATE_MAX] = {
|
||||
[SERVICE_DEAD] = UNIT_INACTIVE,
|
||||
+ [SERVICE_CONDITION] = UNIT_ACTIVATING,
|
||||
[SERVICE_START_PRE] = UNIT_ACTIVATING,
|
||||
[SERVICE_START] = UNIT_ACTIVATING,
|
||||
[SERVICE_START_POST] = UNIT_ACTIVATING,
|
||||
@@ -62,6 +63,7 @@ static const UnitActiveState state_translation_table[_SERVICE_STATE_MAX] = {
|
||||
* consider idle jobs active as soon as we start working on them */
|
||||
static const UnitActiveState state_translation_table_idle[_SERVICE_STATE_MAX] = {
|
||||
[SERVICE_DEAD] = UNIT_INACTIVE,
|
||||
+ [SERVICE_CONDITION] = UNIT_ACTIVE,
|
||||
[SERVICE_START_PRE] = UNIT_ACTIVE,
|
||||
[SERVICE_START] = UNIT_ACTIVE,
|
||||
[SERVICE_START_POST] = UNIT_ACTIVE,
|
||||
@@ -1024,7 +1026,7 @@ static void service_set_state(Service *s, ServiceState state) {
|
||||
service_unwatch_pid_file(s);
|
||||
|
||||
if (!IN_SET(state,
|
||||
- SERVICE_START_PRE, SERVICE_START, SERVICE_START_POST,
|
||||
+ SERVICE_CONDITION, SERVICE_START_PRE, SERVICE_START, SERVICE_START_POST,
|
||||
SERVICE_RUNNING,
|
||||
SERVICE_RELOAD,
|
||||
SERVICE_STOP, SERVICE_STOP_SIGABRT, SERVICE_STOP_SIGTERM, SERVICE_STOP_SIGKILL, SERVICE_STOP_POST,
|
||||
@@ -1042,7 +1044,7 @@ static void service_set_state(Service *s, ServiceState state) {
|
||||
}
|
||||
|
||||
if (!IN_SET(state,
|
||||
- SERVICE_START_PRE, SERVICE_START, SERVICE_START_POST,
|
||||
+ SERVICE_CONDITION, SERVICE_START_PRE, SERVICE_START, SERVICE_START_POST,
|
||||
SERVICE_RELOAD,
|
||||
SERVICE_STOP, SERVICE_STOP_SIGABRT, SERVICE_STOP_SIGTERM, SERVICE_STOP_SIGKILL, SERVICE_STOP_POST,
|
||||
SERVICE_FINAL_SIGTERM, SERVICE_FINAL_SIGKILL)) {
|
||||
@@ -1057,7 +1059,7 @@ static void service_set_state(Service *s, ServiceState state) {
|
||||
}
|
||||
|
||||
if (!IN_SET(state,
|
||||
- SERVICE_START_PRE, SERVICE_START, SERVICE_START_POST,
|
||||
+ SERVICE_CONDITION, SERVICE_START_PRE, SERVICE_START, SERVICE_START_POST,
|
||||
SERVICE_RUNNING, SERVICE_RELOAD,
|
||||
SERVICE_STOP, SERVICE_STOP_SIGABRT, SERVICE_STOP_SIGTERM, SERVICE_STOP_SIGKILL, SERVICE_STOP_POST,
|
||||
SERVICE_FINAL_SIGTERM, SERVICE_FINAL_SIGKILL) &&
|
||||
@@ -1080,7 +1082,8 @@ static void service_set_state(Service *s, ServiceState state) {
|
||||
|
||||
unit_notify(UNIT(s), table[old_state], table[state],
|
||||
(s->reload_result == SERVICE_SUCCESS ? 0 : UNIT_NOTIFY_RELOAD_FAILURE) |
|
||||
- (s->will_auto_restart ? UNIT_NOTIFY_WILL_AUTO_RESTART : 0));
|
||||
+ (s->will_auto_restart ? UNIT_NOTIFY_WILL_AUTO_RESTART : 0) |
|
||||
+ (s->result == SERVICE_SKIP_CONDITION ? UNIT_NOTIFY_SKIP_CONDITION : 0));
|
||||
}
|
||||
|
||||
static usec_t service_coldplug_timeout(Service *s) {
|
||||
@@ -1088,6 +1091,7 @@ static usec_t service_coldplug_timeout(Service *s) {
|
||||
|
||||
switch (s->deserialized_state) {
|
||||
|
||||
+ case SERVICE_CONDITION:
|
||||
case SERVICE_START_PRE:
|
||||
case SERVICE_START:
|
||||
case SERVICE_START_POST:
|
||||
@@ -1143,7 +1147,7 @@ static int service_coldplug(Unit *u) {
|
||||
if (s->control_pid > 0 &&
|
||||
pid_is_unwaited(s->control_pid) &&
|
||||
IN_SET(s->deserialized_state,
|
||||
- SERVICE_START_PRE, SERVICE_START, SERVICE_START_POST,
|
||||
+ SERVICE_CONDITION, SERVICE_START_PRE, SERVICE_START, SERVICE_START_POST,
|
||||
SERVICE_RELOAD,
|
||||
SERVICE_STOP, SERVICE_STOP_SIGABRT, SERVICE_STOP_SIGTERM, SERVICE_STOP_SIGKILL, SERVICE_STOP_POST,
|
||||
SERVICE_FINAL_SIGTERM, SERVICE_FINAL_SIGKILL)) {
|
||||
@@ -1667,6 +1671,7 @@ static bool service_will_restart(Unit *u) {
|
||||
}
|
||||
|
||||
static void service_enter_dead(Service *s, ServiceResult f, bool allow_restart) {
|
||||
+ ServiceState end_state;
|
||||
int r;
|
||||
|
||||
assert(s);
|
||||
@@ -1679,10 +1684,16 @@ static void service_enter_dead(Service *s, ServiceResult f, bool allow_restart)
|
||||
if (s->result == SERVICE_SUCCESS)
|
||||
s->result = f;
|
||||
|
||||
- if (s->result == SERVICE_SUCCESS)
|
||||
+ if (s->result == SERVICE_SUCCESS) {
|
||||
unit_log_success(UNIT(s));
|
||||
- else
|
||||
+ end_state = SERVICE_DEAD;
|
||||
+ } else if (s->result == SERVICE_SKIP_CONDITION) {
|
||||
+ unit_log_skip(UNIT(s), service_result_to_string(s->result));
|
||||
+ end_state = SERVICE_DEAD;
|
||||
+ } else {
|
||||
unit_log_failure(UNIT(s), service_result_to_string(s->result));
|
||||
+ end_state = SERVICE_FAILED;
|
||||
+ }
|
||||
|
||||
if (allow_restart && service_shall_restart(s))
|
||||
s->will_auto_restart = true;
|
||||
@@ -1691,7 +1702,7 @@ static void service_enter_dead(Service *s, ServiceResult f, bool allow_restart)
|
||||
* SERVICE_FAILED/SERVICE_DEAD before entering into SERVICE_AUTO_RESTART. */
|
||||
s->n_keep_fd_store ++;
|
||||
|
||||
- service_set_state(s, s->result != SERVICE_SUCCESS ? SERVICE_FAILED : SERVICE_DEAD);
|
||||
+ service_set_state(s, end_state);
|
||||
|
||||
if (s->will_auto_restart) {
|
||||
s->will_auto_restart = false;
|
||||
@@ -2110,6 +2121,40 @@ fail:
|
||||
service_enter_dead(s, SERVICE_FAILURE_RESOURCES, true);
|
||||
}
|
||||
|
||||
+static void service_enter_condition(Service *s) {
|
||||
+ int r;
|
||||
+
|
||||
+ assert(s);
|
||||
+
|
||||
+ service_unwatch_control_pid(s);
|
||||
+
|
||||
+ s->control_command = s->exec_command[SERVICE_EXEC_CONDITION];
|
||||
+ if (s->control_command) {
|
||||
+
|
||||
+ unit_warn_leftover_processes(UNIT(s));
|
||||
+
|
||||
+ s->control_command_id = SERVICE_EXEC_CONDITION;
|
||||
+
|
||||
+ r = service_spawn(s,
|
||||
+ s->control_command,
|
||||
+ s->timeout_start_usec,
|
||||
+ EXEC_APPLY_SANDBOXING|EXEC_APPLY_CHROOT|EXEC_IS_CONTROL|EXEC_APPLY_TTY_STDIN,
|
||||
+ &s->control_pid);
|
||||
+
|
||||
+ if (r < 0)
|
||||
+ goto fail;
|
||||
+
|
||||
+ service_set_state(s, SERVICE_CONDITION);
|
||||
+ } else
|
||||
+ service_enter_start_pre(s);
|
||||
+
|
||||
+ return;
|
||||
+
|
||||
+fail:
|
||||
+ log_unit_warning_errno(UNIT(s), r, "Failed to run 'exec-condition' task: %m");
|
||||
+ service_enter_dead(s, SERVICE_FAILURE_RESOURCES, true);
|
||||
+}
|
||||
+
|
||||
static void service_enter_restart(Service *s) {
|
||||
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
|
||||
int r;
|
||||
@@ -2222,7 +2267,7 @@ static void service_run_next_control(Service *s) {
|
||||
s->control_command = s->control_command->command_next;
|
||||
service_unwatch_control_pid(s);
|
||||
|
||||
- if (IN_SET(s->state, SERVICE_START_PRE, SERVICE_START, SERVICE_START_POST, SERVICE_RUNNING, SERVICE_RELOAD))
|
||||
+ if (IN_SET(s->state, SERVICE_CONDITION, SERVICE_START_PRE, SERVICE_START, SERVICE_START_POST, SERVICE_RUNNING, SERVICE_RELOAD))
|
||||
timeout = s->timeout_start_usec;
|
||||
else
|
||||
timeout = s->timeout_stop_usec;
|
||||
@@ -2231,7 +2276,7 @@ static void service_run_next_control(Service *s) {
|
||||
s->control_command,
|
||||
timeout,
|
||||
EXEC_APPLY_SANDBOXING|EXEC_APPLY_CHROOT|EXEC_IS_CONTROL|
|
||||
- (IN_SET(s->control_command_id, SERVICE_EXEC_START_PRE, SERVICE_EXEC_STOP_POST) ? EXEC_APPLY_TTY_STDIN : 0)|
|
||||
+ (IN_SET(s->control_command_id, SERVICE_EXEC_CONDITION, SERVICE_EXEC_START_PRE, SERVICE_EXEC_STOP_POST) ? EXEC_APPLY_TTY_STDIN : 0)|
|
||||
(IN_SET(s->control_command_id, SERVICE_EXEC_STOP, SERVICE_EXEC_STOP_POST) ? EXEC_SETENV_RESULT : 0),
|
||||
&s->control_pid);
|
||||
if (r < 0)
|
||||
@@ -2242,7 +2287,7 @@ static void service_run_next_control(Service *s) {
|
||||
fail:
|
||||
log_unit_warning_errno(UNIT(s), r, "Failed to run next control task: %m");
|
||||
|
||||
- if (IN_SET(s->state, SERVICE_START_PRE, SERVICE_START_POST, SERVICE_STOP))
|
||||
+ if (IN_SET(s->state, SERVICE_CONDITION, SERVICE_START_PRE, SERVICE_START_POST, SERVICE_STOP))
|
||||
service_enter_signal(s, SERVICE_STOP_SIGTERM, SERVICE_FAILURE_RESOURCES);
|
||||
else if (s->state == SERVICE_STOP_POST)
|
||||
service_enter_dead(s, SERVICE_FAILURE_RESOURCES, true);
|
||||
@@ -2296,7 +2341,7 @@ static int service_start(Unit *u) {
|
||||
return -EAGAIN;
|
||||
|
||||
/* Already on it! */
|
||||
- if (IN_SET(s->state, SERVICE_START_PRE, SERVICE_START, SERVICE_START_POST))
|
||||
+ if (IN_SET(s->state, SERVICE_CONDITION, SERVICE_START_PRE, SERVICE_START, SERVICE_START_POST))
|
||||
return 0;
|
||||
|
||||
/* A service that will be restarted must be stopped first to
|
||||
@@ -2344,7 +2389,9 @@ static int service_start(Unit *u) {
|
||||
s->flush_n_restarts = false;
|
||||
}
|
||||
|
||||
- service_enter_start_pre(s);
|
||||
+ u->reset_accounting = true;
|
||||
+
|
||||
+ service_enter_condition(s);
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -2370,7 +2417,7 @@ static int service_stop(Unit *u) {
|
||||
|
||||
/* If there's already something running we go directly into
|
||||
* kill mode. */
|
||||
- if (IN_SET(s->state, SERVICE_START_PRE, SERVICE_START, SERVICE_START_POST, SERVICE_RELOAD)) {
|
||||
+ if (IN_SET(s->state, SERVICE_CONDITION, SERVICE_START_PRE, SERVICE_START, SERVICE_START_POST, SERVICE_RELOAD)) {
|
||||
service_enter_signal(s, SERVICE_STOP_SIGTERM, SERVICE_SUCCESS);
|
||||
return 0;
|
||||
}
|
||||
@@ -3303,6 +3350,10 @@ static void service_sigchld_event(Unit *u, pid_t pid, int code, int status) {
|
||||
} else if (s->control_pid == pid) {
|
||||
s->control_pid = 0;
|
||||
|
||||
+ /* ExecCondition= calls that exit with (0, 254] should invoke skip-like behavior instead of failing */
|
||||
+ if (f == SERVICE_FAILURE_EXIT_CODE && s->state == SERVICE_CONDITION && status < 255)
|
||||
+ f = SERVICE_SKIP_CONDITION;
|
||||
+
|
||||
if (s->control_command) {
|
||||
exec_status_exit(&s->control_command->exec_status, &s->exec_context, pid, code, status);
|
||||
|
||||
@@ -3338,6 +3389,13 @@ static void service_sigchld_event(Unit *u, pid_t pid, int code, int status) {
|
||||
|
||||
switch (s->state) {
|
||||
|
||||
+ case SERVICE_CONDITION:
|
||||
+ if (f == SERVICE_SUCCESS)
|
||||
+ service_enter_start_pre(s);
|
||||
+ else
|
||||
+ service_enter_signal(s, SERVICE_STOP_SIGTERM, f);
|
||||
+ break;
|
||||
+
|
||||
case SERVICE_START_PRE:
|
||||
if (f == SERVICE_SUCCESS)
|
||||
service_enter_start(s);
|
||||
@@ -3462,9 +3520,10 @@ static int service_dispatch_timer(sd_event_source *source, usec_t usec, void *us
|
||||
|
||||
switch (s->state) {
|
||||
|
||||
+ case SERVICE_CONDITION:
|
||||
case SERVICE_START_PRE:
|
||||
case SERVICE_START:
|
||||
- log_unit_warning(UNIT(s), "%s operation timed out. Terminating.", s->state == SERVICE_START ? "Start" : "Start-pre");
|
||||
+ log_unit_warning(UNIT(s), "%s operation timed out. Terminating.", service_state_to_string(s->state));
|
||||
service_enter_signal(s, SERVICE_STOP_SIGTERM, SERVICE_FAILURE_TIMEOUT);
|
||||
break;
|
||||
|
||||
@@ -3975,6 +4034,7 @@ static bool service_needs_console(Unit *u) {
|
||||
return false;
|
||||
|
||||
return IN_SET(s->state,
|
||||
+ SERVICE_CONDITION,
|
||||
SERVICE_START_PRE,
|
||||
SERVICE_START,
|
||||
SERVICE_START_POST,
|
||||
@@ -4014,6 +4074,7 @@ static const char* const service_type_table[_SERVICE_TYPE_MAX] = {
|
||||
DEFINE_STRING_TABLE_LOOKUP(service_type, ServiceType);
|
||||
|
||||
static const char* const service_exec_command_table[_SERVICE_EXEC_COMMAND_MAX] = {
|
||||
+ [SERVICE_EXEC_CONDITION] = "ExecCondition",
|
||||
[SERVICE_EXEC_START_PRE] = "ExecStartPre",
|
||||
[SERVICE_EXEC_START] = "ExecStart",
|
||||
[SERVICE_EXEC_START_POST] = "ExecStartPost",
|
||||
@@ -4043,6 +4104,7 @@ static const char* const service_result_table[_SERVICE_RESULT_MAX] = {
|
||||
[SERVICE_FAILURE_CORE_DUMP] = "core-dump",
|
||||
[SERVICE_FAILURE_WATCHDOG] = "watchdog",
|
||||
[SERVICE_FAILURE_START_LIMIT_HIT] = "start-limit-hit",
|
||||
+ [SERVICE_SKIP_CONDITION] = "exec-condition",
|
||||
};
|
||||
|
||||
DEFINE_STRING_TABLE_LOOKUP(service_result, ServiceResult);
|
||||
@@ -4118,6 +4180,7 @@ const UnitVTable service_vtable = {
|
||||
.finished_start_job = {
|
||||
[JOB_DONE] = "Started %s.",
|
||||
[JOB_FAILED] = "Failed to start %s.",
|
||||
+ [JOB_SKIPPED] = "Skipped %s.",
|
||||
},
|
||||
.finished_stop_job = {
|
||||
[JOB_DONE] = "Stopped %s.",
|
||||
diff --git a/src/core/service.h b/src/core/service.h
|
||||
index 1206e3cdda..62b78cadf1 100644
|
||||
--- a/src/core/service.h
|
||||
+++ b/src/core/service.h
|
||||
@@ -36,6 +36,7 @@ typedef enum ServiceType {
|
||||
} ServiceType;
|
||||
|
||||
typedef enum ServiceExecCommand {
|
||||
+ SERVICE_EXEC_CONDITION,
|
||||
SERVICE_EXEC_START_PRE,
|
||||
SERVICE_EXEC_START,
|
||||
SERVICE_EXEC_START_POST,
|
||||
@@ -67,6 +68,7 @@ typedef enum ServiceResult {
|
||||
SERVICE_FAILURE_CORE_DUMP,
|
||||
SERVICE_FAILURE_WATCHDOG,
|
||||
SERVICE_FAILURE_START_LIMIT_HIT,
|
||||
+ SERVICE_SKIP_CONDITION,
|
||||
_SERVICE_RESULT_MAX,
|
||||
_SERVICE_RESULT_INVALID = -1
|
||||
} ServiceResult;
|
||||
diff --git a/src/core/unit.c b/src/core/unit.c
|
||||
index ccb0106719..61799bf9e3 100644
|
||||
--- a/src/core/unit.c
|
||||
+++ b/src/core/unit.c
|
||||
@@ -2227,6 +2227,7 @@ static void unit_update_on_console(Unit *u) {
|
||||
|
||||
static bool unit_process_job(Job *j, UnitActiveState ns, UnitNotifyFlags flags) {
|
||||
bool unexpected = false;
|
||||
+ JobResult result;
|
||||
|
||||
assert(j);
|
||||
|
||||
@@ -2249,8 +2250,16 @@ static bool unit_process_job(Job *j, UnitActiveState ns, UnitNotifyFlags flags)
|
||||
else if (j->state == JOB_RUNNING && ns != UNIT_ACTIVATING) {
|
||||
unexpected = true;
|
||||
|
||||
- if (UNIT_IS_INACTIVE_OR_FAILED(ns))
|
||||
- job_finish_and_invalidate(j, ns == UNIT_FAILED ? JOB_FAILED : JOB_DONE, true, false);
|
||||
+ if (UNIT_IS_INACTIVE_OR_FAILED(ns)) {
|
||||
+ if (ns == UNIT_FAILED)
|
||||
+ result = JOB_FAILED;
|
||||
+ else if (FLAGS_SET(flags, UNIT_NOTIFY_SKIP_CONDITION))
|
||||
+ result = JOB_SKIPPED;
|
||||
+ else
|
||||
+ result = JOB_DONE;
|
||||
+
|
||||
+ job_finish_and_invalidate(j, result, true, false);
|
||||
+ }
|
||||
}
|
||||
|
||||
break;
|
||||
@@ -5484,6 +5493,18 @@ void unit_log_failure(Unit *u, const char *result) {
|
||||
"UNIT_RESULT=%s", result);
|
||||
}
|
||||
|
||||
+void unit_log_skip(Unit *u, const char *result) {
|
||||
+ assert(u);
|
||||
+ assert(result);
|
||||
+
|
||||
+ log_struct(LOG_INFO,
|
||||
+ "MESSAGE_ID=" SD_MESSAGE_UNIT_SKIPPED_STR,
|
||||
+ LOG_UNIT_ID(u),
|
||||
+ LOG_UNIT_INVOCATION_ID(u),
|
||||
+ LOG_UNIT_MESSAGE(u, "Skipped due to '%s'.", result),
|
||||
+ "UNIT_RESULT=%s", result);
|
||||
+}
|
||||
+
|
||||
static const char* const collect_mode_table[_COLLECT_MODE_MAX] = {
|
||||
[COLLECT_INACTIVE] = "inactive",
|
||||
[COLLECT_INACTIVE_OR_FAILED] = "inactive-or-failed",
|
||||
diff --git a/src/core/unit.h b/src/core/unit.h
|
||||
index 4ae1b38624..39179f5fd4 100644
|
||||
--- a/src/core/unit.h
|
||||
+++ b/src/core/unit.h
|
||||
@@ -658,6 +658,7 @@ int unit_kill_common(Unit *u, KillWho who, int signo, pid_t main_pid, pid_t cont
|
||||
typedef enum UnitNotifyFlags {
|
||||
UNIT_NOTIFY_RELOAD_FAILURE = 1 << 0,
|
||||
UNIT_NOTIFY_WILL_AUTO_RESTART = 1 << 1,
|
||||
+ UNIT_NOTIFY_SKIP_CONDITION = 1 << 2,
|
||||
} UnitNotifyFlags;
|
||||
|
||||
void unit_notify(Unit *u, UnitActiveState os, UnitActiveState ns, UnitNotifyFlags flags);
|
||||
@@ -806,6 +807,9 @@ int unit_pid_attachable(Unit *unit, pid_t pid, sd_bus_error *error);
|
||||
|
||||
void unit_log_success(Unit *u);
|
||||
void unit_log_failure(Unit *u, const char *result);
|
||||
+/* unit_log_skip is for cases like ExecCondition= where a unit is considered "done"
|
||||
+ * after some execution, rather than succeeded or failed. */
|
||||
+void unit_log_skip(Unit *u, const char *result);
|
||||
|
||||
/* Macros which append UNIT= or USER_UNIT= to the message */
|
||||
|
||||
diff --git a/src/shared/bus-unit-util.c b/src/shared/bus-unit-util.c
|
||||
index 8f3b463c6b..e0b2cfb170 100644
|
||||
--- a/src/shared/bus-unit-util.c
|
||||
+++ b/src/shared/bus-unit-util.c
|
||||
@@ -1334,7 +1334,7 @@ static int bus_append_service_property(sd_bus_message *m, const char *field, con
|
||||
return bus_append_safe_atou(m, field, eq);
|
||||
|
||||
if (STR_IN_SET(field,
|
||||
- "ExecStartPre", "ExecStart", "ExecStartPost",
|
||||
+ "ExecCondition", "ExecStartPre", "ExecStart", "ExecStartPost",
|
||||
"ExecReload", "ExecStop", "ExecStopPost"))
|
||||
|
||||
return bus_append_exec_command(m, field, eq);
|
||||
diff --git a/src/systemd/sd-messages.h b/src/systemd/sd-messages.h
|
||||
index e7ef81b597..bdd4fd3974 100644
|
||||
--- a/src/systemd/sd-messages.h
|
||||
+++ b/src/systemd/sd-messages.h
|
||||
@@ -111,6 +111,8 @@ _SD_BEGIN_DECLARATIONS;
|
||||
#define SD_MESSAGE_UNIT_FAILURE_RESULT SD_ID128_MAKE(d9,b3,73,ed,55,a6,4f,eb,82,42,e0,2d,be,79,a4,9c)
|
||||
#define SD_MESSAGE_UNIT_FAILURE_RESULT_STR \
|
||||
SD_ID128_MAKE_STR(d9,b3,73,ed,55,a6,4f,eb,82,42,e0,2d,be,79,a4,9c)
|
||||
+#define SD_MESSAGE_UNIT_SKIPPED SD_ID128_MAKE(0e,42,84,a0,ca,ca,4b,fc,81,c0,bb,67,86,97,26,73)
|
||||
+#define SD_MESSAGE_UNIT_SKIPPED_STR SD_ID128_MAKE_STR(0e,42,84,a0,ca,ca,4b,fc,81,c0,bb,67,86,97,26,73)
|
||||
|
||||
#define SD_MESSAGE_SPAWN_FAILED SD_ID128_MAKE(64,12,57,65,1c,1b,4e,c9,a8,62,4d,7a,40,a9,e1,e7)
|
||||
#define SD_MESSAGE_SPAWN_FAILED_STR SD_ID128_MAKE_STR(64,12,57,65,1c,1b,4e,c9,a8,62,4d,7a,40,a9,e1,e7)
|
||||
diff --git a/src/test/test-execute.c b/src/test/test-execute.c
|
||||
index e42d0d30a8..882e866ea9 100644
|
||||
--- a/src/test/test-execute.c
|
||||
+++ b/src/test/test-execute.c
|
||||
@@ -30,7 +30,7 @@
|
||||
|
||||
typedef void (*test_function_t)(Manager *m);
|
||||
|
||||
-static void check(const char *func, Manager *m, Unit *unit, int status_expected, int code_expected) {
|
||||
+static void wait_for_service_finish(Manager *m, Unit *unit) {
|
||||
Service *service = NULL;
|
||||
usec_t ts;
|
||||
usec_t timeout = 2 * USEC_PER_MINUTE;
|
||||
@@ -55,6 +55,17 @@ static void check(const char *func, Manager *m, Unit *unit, int status_expected,
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
+}
|
||||
+
|
||||
+static void check_main_result(const char *func, Manager *m, Unit *unit, int status_expected, int code_expected) {
|
||||
+ Service *service = NULL;
|
||||
+
|
||||
+ assert_se(m);
|
||||
+ assert_se(unit);
|
||||
+
|
||||
+ wait_for_service_finish(m, unit);
|
||||
+
|
||||
+ service = SERVICE(unit);
|
||||
exec_status_dump(&service->main_exec_status, stdout, "\t");
|
||||
if (service->main_exec_status.status != status_expected) {
|
||||
log_error("%s: %s: exit status %d, expected %d",
|
||||
@@ -70,6 +81,25 @@ static void check(const char *func, Manager *m, Unit *unit, int status_expected,
|
||||
}
|
||||
}
|
||||
|
||||
+static void check_service_result(const char *func, Manager *m, Unit *unit, ServiceResult result_expected) {
|
||||
+ Service *service = NULL;
|
||||
+
|
||||
+ assert_se(m);
|
||||
+ assert_se(unit);
|
||||
+
|
||||
+ wait_for_service_finish(m, unit);
|
||||
+
|
||||
+ service = SERVICE(unit);
|
||||
+
|
||||
+ if (service->result != result_expected) {
|
||||
+ log_error("%s: %s: service end result %s, expected %s",
|
||||
+ func, unit->id,
|
||||
+ service_result_to_string(service->result),
|
||||
+ service_result_to_string(result_expected));
|
||||
+ abort();
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
static bool check_nobody_user_and_group(void) {
|
||||
static int cache = -1;
|
||||
struct passwd *p;
|
||||
@@ -140,7 +170,17 @@ static void test(const char *func, Manager *m, const char *unit_name, int status
|
||||
|
||||
assert_se(manager_load_startable_unit_or_warn(m, unit_name, NULL, &unit) >= 0);
|
||||
assert_se(unit_start(unit) >= 0);
|
||||
- check(func, m, unit, status_expected, code_expected);
|
||||
+ check_main_result(func, m, unit, status_expected, code_expected);
|
||||
+}
|
||||
+
|
||||
+static void test_service(const char *func, Manager *m, const char *unit_name, ServiceResult result_expected) {
|
||||
+ Unit *unit;
|
||||
+
|
||||
+ assert_se(unit_name);
|
||||
+
|
||||
+ assert_se(manager_load_startable_unit_or_warn(m, unit_name, NULL, &unit) >= 0);
|
||||
+ assert_se(unit_start(unit) >= 0);
|
||||
+ check_service_result(func, m, unit, result_expected);
|
||||
}
|
||||
|
||||
static void test_exec_bindpaths(Manager *m) {
|
||||
@@ -669,6 +709,11 @@ static void test_exec_standardoutput_append(Manager *m) {
|
||||
test(__func__, m, "exec-standardoutput-append.service", 0, CLD_EXITED);
|
||||
}
|
||||
|
||||
+static void test_exec_condition(Manager *m) {
|
||||
+ test_service(__func__, m, "exec-condition-failed.service", SERVICE_FAILURE_EXIT_CODE);
|
||||
+ test_service(__func__, m, "exec-condition-skip.service", SERVICE_SKIP_CONDITION);
|
||||
+}
|
||||
+
|
||||
typedef struct test_entry {
|
||||
test_function_t f;
|
||||
const char *name;
|
||||
@@ -709,6 +754,7 @@ int main(int argc, char *argv[]) {
|
||||
entry(test_exec_ambientcapabilities),
|
||||
entry(test_exec_bindpaths),
|
||||
entry(test_exec_capabilityboundingset),
|
||||
+ entry(test_exec_condition),
|
||||
entry(test_exec_cpuaffinity),
|
||||
entry(test_exec_environment),
|
||||
entry(test_exec_environmentfile),
|
||||
diff --git a/test/fuzz/fuzz-unit-file/directives.service b/test/fuzz/fuzz-unit-file/directives.service
|
||||
index eab1820e20..9d0530df72 100644
|
||||
--- a/test/fuzz/fuzz-unit-file/directives.service
|
||||
+++ b/test/fuzz/fuzz-unit-file/directives.service
|
||||
@@ -83,6 +83,7 @@ DirectoryNotEmpty=
|
||||
Documentation=
|
||||
DynamicUser=
|
||||
ExecReload=
|
||||
+ExecCondition=
|
||||
ExecStart=
|
||||
ExecStartPost=
|
||||
ExecStartPre=
|
||||
diff --git a/test/meson.build b/test/meson.build
|
||||
index 4d1c51048c..070731c4a9 100644
|
||||
--- a/test/meson.build
|
||||
+++ b/test/meson.build
|
||||
@@ -42,6 +42,8 @@ test_data_files = '''
|
||||
test-execute/exec-capabilityboundingset-merge.service
|
||||
test-execute/exec-capabilityboundingset-reset.service
|
||||
test-execute/exec-capabilityboundingset-simple.service
|
||||
+ test-execute/exec-condition-failed.service
|
||||
+ test-execute/exec-condition-skip.service
|
||||
test-execute/exec-cpuaffinity1.service
|
||||
test-execute/exec-cpuaffinity2.service
|
||||
test-execute/exec-cpuaffinity3.service
|
||||
diff --git a/test/test-execute/exec-condition-failed.service b/test/test-execute/exec-condition-failed.service
|
||||
new file mode 100644
|
||||
index 0000000000..4a406dc17f
|
||||
--- /dev/null
|
||||
+++ b/test/test-execute/exec-condition-failed.service
|
||||
@@ -0,0 +1,11 @@
|
||||
+[Unit]
|
||||
+Description=Test for exec condition that fails the unit
|
||||
+
|
||||
+[Service]
|
||||
+Type=oneshot
|
||||
+
|
||||
+# exit 255 will fail the unit
|
||||
+ExecCondition=/bin/sh -c 'exit 255'
|
||||
+
|
||||
+# This should not get run
|
||||
+ExecStart=/bin/sh -c 'true'
|
||||
diff --git a/test/test-execute/exec-condition-skip.service b/test/test-execute/exec-condition-skip.service
|
||||
new file mode 100644
|
||||
index 0000000000..9450e8442a
|
||||
--- /dev/null
|
||||
+++ b/test/test-execute/exec-condition-skip.service
|
||||
@@ -0,0 +1,15 @@
|
||||
+[Unit]
|
||||
+Description=Test for exec condition that triggers skipping
|
||||
+
|
||||
+[Service]
|
||||
+Type=oneshot
|
||||
+
|
||||
+# exit codes [1, 254] will result in skipping the rest of execution
|
||||
+ExecCondition=/bin/sh -c 'exit 0'
|
||||
+ExecCondition=/bin/sh -c 'exit 254'
|
||||
+
|
||||
+# This would normally fail the unit but will not get run due to the skip above
|
||||
+ExecCondition=/bin/sh -c 'exit 255'
|
||||
+
|
||||
+# This should not get run
|
||||
+ExecStart=/bin/sh -c 'true'
|
75
SOURCES/0385-Drop-support-for-lz4-1.3.0.patch
Normal file
75
SOURCES/0385-Drop-support-for-lz4-1.3.0.patch
Normal file
@ -0,0 +1,75 @@
|
||||
From 09c96d5ef3f2b0bc4e5f1cf69e9b66248e325509 Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= <zbyszek@in.waw.pl>
|
||||
Date: Mon, 29 Oct 2018 18:32:51 +0100
|
||||
Subject: [PATCH] Drop support for lz4 < 1.3.0
|
||||
|
||||
lz4-r130 was released on May 29th, 2015. Let's drop the work-around for older
|
||||
versions. In particular, we won't test any new code against those ancient
|
||||
releases, so we shouldn't pretend they are supported.
|
||||
|
||||
(cherry picked from commit e0a1d4b049e6991919a0eacd5d96f7f39dc6ddd1)
|
||||
Resolves: #1843871
|
||||
---
|
||||
README | 2 +-
|
||||
meson.build | 1 +
|
||||
src/journal/compress.c | 4 ----
|
||||
src/journal/test-compress.c | 4 ----
|
||||
4 files changed, 2 insertions(+), 9 deletions(-)
|
||||
|
||||
diff --git a/README b/README
|
||||
index 7d06e04800..859152fbde 100644
|
||||
--- a/README
|
||||
+++ b/README
|
||||
@@ -148,7 +148,7 @@ REQUIREMENTS:
|
||||
libacl (optional)
|
||||
libselinux (optional)
|
||||
liblzma (optional)
|
||||
- liblz4 >= 119 (optional)
|
||||
+ liblz4 >= 1.3.0 / 130 (optional)
|
||||
libgcrypt (optional)
|
||||
libqrencode (optional)
|
||||
libmicrohttpd (optional)
|
||||
diff --git a/meson.build b/meson.build
|
||||
index 70811c29cf..c8ae1e15bd 100644
|
||||
--- a/meson.build
|
||||
+++ b/meson.build
|
||||
@@ -1076,6 +1076,7 @@ conf.set10('HAVE_XZ', have)
|
||||
want_lz4 = get_option('lz4')
|
||||
if want_lz4 != 'false' and not fuzzer_build
|
||||
liblz4 = dependency('liblz4',
|
||||
+ version : '>= 1.3.0',
|
||||
required : want_lz4 == 'true')
|
||||
have = liblz4.found()
|
||||
else
|
||||
diff --git a/src/journal/compress.c b/src/journal/compress.c
|
||||
index 6baf15c8ff..a4a5e63840 100644
|
||||
--- a/src/journal/compress.c
|
||||
+++ b/src/journal/compress.c
|
||||
@@ -95,11 +95,7 @@ int compress_blob_lz4(const void *src, uint64_t src_size,
|
||||
if (src_size < 9)
|
||||
return -ENOBUFS;
|
||||
|
||||
-#if LZ4_VERSION_NUMBER >= 10700
|
||||
r = LZ4_compress_default(src, (char*)dst + 8, src_size, (int) dst_alloc_size - 8);
|
||||
-#else
|
||||
- r = LZ4_compress_limitedOutput(src, (char*)dst + 8, src_size, (int) dst_alloc_size - 8);
|
||||
-#endif
|
||||
if (r <= 0)
|
||||
return -ENOBUFS;
|
||||
|
||||
diff --git a/src/journal/test-compress.c b/src/journal/test-compress.c
|
||||
index 791c6fdffb..eb3dc3eb6b 100644
|
||||
--- a/src/journal/test-compress.c
|
||||
+++ b/src/journal/test-compress.c
|
||||
@@ -207,11 +207,7 @@ static void test_lz4_decompress_partial(void) {
|
||||
memset(huge, 'x', HUGE_SIZE);
|
||||
memcpy(huge, "HUGE=", 5);
|
||||
|
||||
-#if LZ4_VERSION_NUMBER >= 10700
|
||||
r = LZ4_compress_default(huge, buf, HUGE_SIZE, buf_size);
|
||||
-#else
|
||||
- r = LZ4_compress_limitedOutput(huge, buf, HUGE_SIZE, buf_size);
|
||||
-#endif
|
||||
assert_se(r >= 0);
|
||||
compressed = r;
|
||||
log_info("Compressed %i → %zu", HUGE_SIZE, compressed);
|
@ -0,0 +1,72 @@
|
||||
From fc1e6209f622ff96c24259a50d98ca6f57a55426 Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= <zbyszek@in.waw.pl>
|
||||
Date: Mon, 29 Oct 2018 22:21:28 +0100
|
||||
Subject: [PATCH] test-compress: add test for short decompress_startswith calls
|
||||
|
||||
I thought this might fail with lz4 < 1.8.3, but it seems that because of
|
||||
greedy_realloc, we always use a buffer that is large enough, and it always
|
||||
passes.
|
||||
|
||||
(cherry picked from commit ba17efce44e6a1e139c1671205e9a6ed3824af1b)
|
||||
Resolves: #1843871
|
||||
---
|
||||
src/journal/test-compress.c | 32 ++++++++++++++++++++++++++++++++
|
||||
1 file changed, 32 insertions(+)
|
||||
|
||||
diff --git a/src/journal/test-compress.c b/src/journal/test-compress.c
|
||||
index eb3dc3eb6b..65cd3fbfeb 100644
|
||||
--- a/src/journal/test-compress.c
|
||||
+++ b/src/journal/test-compress.c
|
||||
@@ -131,6 +131,32 @@ static void test_decompress_startswith(int compression,
|
||||
assert_se(r > 0);
|
||||
}
|
||||
|
||||
+static void test_decompress_startswith_short(int compression,
|
||||
+ compress_blob_t compress,
|
||||
+ decompress_sw_t decompress_sw) {
|
||||
+
|
||||
+#define TEXT "HUGE=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
|
||||
+
|
||||
+ char buf[1024];
|
||||
+ size_t i, csize;
|
||||
+ int r;
|
||||
+
|
||||
+ log_info("/* %s with %s */", __func__, object_compressed_to_string(compression));
|
||||
+
|
||||
+ r = compress(TEXT, sizeof TEXT, buf, sizeof buf, &csize);
|
||||
+ assert_se(r == 0);
|
||||
+
|
||||
+ for (i = 1; i < strlen(TEXT); i++) {
|
||||
+ size_t alloc_size = i;
|
||||
+ _cleanup_free_ void *buf2 = NULL;
|
||||
+
|
||||
+ assert_se(buf2 = malloc(i));
|
||||
+
|
||||
+ assert_se(decompress_sw(buf, csize, &buf2, &alloc_size, TEXT, i, TEXT[i]) == 1);
|
||||
+ assert_se(decompress_sw(buf, csize, &buf2, &alloc_size, TEXT, i, 'y') == 0);
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
static void test_compress_stream(int compression,
|
||||
const char* cat,
|
||||
compress_stream_t compress,
|
||||
@@ -271,6 +297,9 @@ int main(int argc, char *argv[]) {
|
||||
|
||||
test_compress_stream(OBJECT_COMPRESSED_XZ, "xzcat",
|
||||
compress_stream_xz, decompress_stream_xz, srcfile);
|
||||
+
|
||||
+ test_decompress_startswith_short(OBJECT_COMPRESSED_XZ, compress_blob_xz, decompress_startswith_xz);
|
||||
+
|
||||
#else
|
||||
log_info("/* XZ test skipped */");
|
||||
#endif
|
||||
@@ -295,6 +324,9 @@ int main(int argc, char *argv[]) {
|
||||
compress_stream_lz4, decompress_stream_lz4, srcfile);
|
||||
|
||||
test_lz4_decompress_partial();
|
||||
+
|
||||
+ test_decompress_startswith_short(OBJECT_COMPRESSED_LZ4, compress_blob_lz4, decompress_startswith_lz4);
|
||||
+
|
||||
#else
|
||||
log_info("/* LZ4 test skipped */");
|
||||
#endif
|
@ -0,0 +1,180 @@
|
||||
From 696d56fc75e72f47e4d3232a2140fac10b6b44de Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= <zbyszek@in.waw.pl>
|
||||
Date: Mon, 29 Oct 2018 14:55:33 +0100
|
||||
Subject: [PATCH] journal: adapt for new improved LZ4_decompress_safe_partial()
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
With lz4 1.8.3, this function can now decompress partial results into a smaller
|
||||
buffer. The release news don't say anything interesting, but the test case that
|
||||
was previously failing now works OK.
|
||||
|
||||
Fixes #10259.
|
||||
|
||||
A test is added. It shows that with *older* lz4, a partial decompression can
|
||||
occur with the returned size smaller then the requested number of bytes _and_
|
||||
smaller then the size of the compressed data:
|
||||
|
||||
(lz4-libs-1.8.2-1.fc29.x86_64)
|
||||
Compressed 4194304 → 16464
|
||||
Decompressed → 4194304
|
||||
Decompressed partial 12/4194304 → 4194304
|
||||
Decompressed partial 1/1 → -2 (bad)
|
||||
Decompressed partial 2/2 → -2 (bad)
|
||||
Decompressed partial 3/3 → -2 (bad)
|
||||
Decompressed partial 4/4 → -2 (bad)
|
||||
Decompressed partial 5/5 → -2 (bad)
|
||||
Decompressed partial 6/6 → 6 (good)
|
||||
Decompressed partial 7/7 → 6 (good)
|
||||
Decompressed partial 8/8 → 6 (good)
|
||||
Decompressed partial 9/9 → 6 (good)
|
||||
Decompressed partial 10/10 → 6 (good)
|
||||
Decompressed partial 11/11 → 6 (good)
|
||||
Decompressed partial 12/12 → 6 (good)
|
||||
Decompressed partial 13/13 → 6 (good)
|
||||
Decompressed partial 14/14 → 6 (good)
|
||||
Decompressed partial 15/15 → 6 (good)
|
||||
Decompressed partial 16/16 → 6 (good)
|
||||
Decompressed partial 17/17 → 6 (good)
|
||||
Decompressed partial 18/18 → -16459 (bad)
|
||||
|
||||
(lz4-libs-1.8.3-1.fc29.x86_64)
|
||||
Compressed 4194304 → 16464
|
||||
Decompressed → 4194304
|
||||
Decompressed partial 12/4194304 → 12
|
||||
Decompressed partial 1/1 → 1 (good)
|
||||
Decompressed partial 2/2 → 2 (good)
|
||||
Decompressed partial 3/3 → 3 (good)
|
||||
Decompressed partial 4/4 → 4 (good)
|
||||
...
|
||||
|
||||
If we got such a short "successful" decompression in decompress_startswith() as
|
||||
implemented before this patch, we could be confused and return a false negative
|
||||
result. But it turns out that this only occurs with small output buffer
|
||||
sizes. We use greedy_realloc() to manager the buffer, so it is always at least
|
||||
64 bytes. I couldn't hit a case where decompress_startswith() would actually
|
||||
return a bogus result. But since the lack of proof is not conclusive, the code
|
||||
for *older* lz4 is changed too, just to be safe. We cannot rule out that on a
|
||||
different architecture or with some unlucky compressed string we could hit this
|
||||
corner case.
|
||||
|
||||
The fallback code is guarded by a version check. The check uses a function not
|
||||
the compile-time define, because there was no soversion bump in lz4 or new
|
||||
symbols, and we could be compiled against a newer lz4 and linked at runtime
|
||||
with an older one. (This happens routinely e.g. when somebody upgrades a subset
|
||||
of distro packages.)
|
||||
|
||||
(cherry picked from commit e41ef6fd0027d3619dc1cf062100b2d224d0ee7e)
|
||||
Resolves: #1843871
|
||||
---
|
||||
src/journal/compress.c | 39 ++++++++++++++++++++++++-------------
|
||||
src/journal/test-compress.c | 21 ++++++++++----------
|
||||
2 files changed, 37 insertions(+), 23 deletions(-)
|
||||
|
||||
diff --git a/src/journal/compress.c b/src/journal/compress.c
|
||||
index a4a5e63840..e95ce2bcaa 100644
|
||||
--- a/src/journal/compress.c
|
||||
+++ b/src/journal/compress.c
|
||||
@@ -290,7 +290,6 @@ int decompress_startswith_lz4(const void *src, uint64_t src_size,
|
||||
* prefix */
|
||||
|
||||
int r;
|
||||
- size_t size;
|
||||
|
||||
assert(src);
|
||||
assert(src_size > 0);
|
||||
@@ -307,23 +306,37 @@ int decompress_startswith_lz4(const void *src, uint64_t src_size,
|
||||
|
||||
r = LZ4_decompress_safe_partial((char*)src + 8, *buffer, src_size - 8,
|
||||
prefix_len + 1, *buffer_size);
|
||||
- if (r >= 0)
|
||||
- size = (unsigned) r;
|
||||
- else {
|
||||
- /* lz4 always tries to decode full "sequence", so in
|
||||
- * pathological cases might need to decompress the
|
||||
- * full field. */
|
||||
+ /* One lz4 < 1.8.3, we might get "failure" (r < 0), or "success" where
|
||||
+ * just a part of the buffer is decompressed. But if we get a smaller
|
||||
+ * amount of bytes than requested, we don't know whether there isn't enough
|
||||
+ * data to fill the requested size or whether we just got a partial answer.
|
||||
+ */
|
||||
+ if (r < 0 || (size_t) r < prefix_len + 1) {
|
||||
+ size_t size;
|
||||
+
|
||||
+ if (LZ4_versionNumber() >= 10803)
|
||||
+ /* We trust that the newer lz4 decompresses the number of bytes we
|
||||
+ * requested if available in the compressed string. */
|
||||
+ return 0;
|
||||
+
|
||||
+ if (r > 0)
|
||||
+ /* Compare what we have first, in case of mismatch we can
|
||||
+ * shortcut the full comparison. */
|
||||
+ if (memcmp(*buffer, prefix, r) != 0)
|
||||
+ return 0;
|
||||
+
|
||||
+ /* Before version 1.8.3, lz4 always tries to decode full a "sequence",
|
||||
+ * so in pathological cases might need to decompress the full field. */
|
||||
r = decompress_blob_lz4(src, src_size, buffer, buffer_size, &size, 0);
|
||||
if (r < 0)
|
||||
return r;
|
||||
- }
|
||||
|
||||
- if (size >= prefix_len + 1)
|
||||
- return memcmp(*buffer, prefix, prefix_len) == 0 &&
|
||||
- ((const uint8_t*) *buffer)[prefix_len] == extra;
|
||||
- else
|
||||
- return 0;
|
||||
+ if (size < prefix_len + 1)
|
||||
+ return 0;
|
||||
+ }
|
||||
|
||||
+ return memcmp(*buffer, prefix, prefix_len) == 0 &&
|
||||
+ ((const uint8_t*) *buffer)[prefix_len] == extra;
|
||||
#else
|
||||
return -EPROTONOSUPPORT;
|
||||
#endif
|
||||
diff --git a/src/journal/test-compress.c b/src/journal/test-compress.c
|
||||
index 65cd3fbfeb..f60c4ae3d7 100644
|
||||
--- a/src/journal/test-compress.c
|
||||
+++ b/src/journal/test-compress.c
|
||||
@@ -223,13 +223,13 @@ static void test_compress_stream(int compression,
|
||||
|
||||
#if HAVE_LZ4
|
||||
static void test_lz4_decompress_partial(void) {
|
||||
- char buf[20000];
|
||||
+ char buf[20000], buf2[100];
|
||||
size_t buf_size = sizeof(buf), compressed;
|
||||
int r;
|
||||
_cleanup_free_ char *huge = NULL;
|
||||
|
||||
#define HUGE_SIZE (4096*1024)
|
||||
- huge = malloc(HUGE_SIZE);
|
||||
+ assert_se(huge = malloc(HUGE_SIZE));
|
||||
memset(huge, 'x', HUGE_SIZE);
|
||||
memcpy(huge, "HUGE=", 5);
|
||||
|
||||
@@ -248,14 +248,15 @@ static void test_lz4_decompress_partial(void) {
|
||||
assert_se(r >= 0);
|
||||
log_info("Decompressed partial %i/%i → %i", 12, HUGE_SIZE, r);
|
||||
|
||||
- /* We expect this to fail, because that's how current lz4 works. If this
|
||||
- * call succeeds, then lz4 has been fixed, and we need to change our code.
|
||||
- */
|
||||
- r = LZ4_decompress_safe_partial(buf, huge,
|
||||
- compressed,
|
||||
- 12, HUGE_SIZE-1);
|
||||
- assert_se(r < 0);
|
||||
- log_info("Decompressed partial %i/%i → %i", 12, HUGE_SIZE-1, r);
|
||||
+ for (size_t size = 1; size < sizeof(buf2); size++) {
|
||||
+ /* This failed in older lz4s but works in newer ones. */
|
||||
+ r = LZ4_decompress_safe_partial(buf, buf2, compressed, size, size);
|
||||
+ log_info("Decompressed partial %zu/%zu → %i (%s)", size, size, r,
|
||||
+ r < 0 ? "bad" : "good");
|
||||
+ if (r >= 0 && LZ4_versionNumber() >= 10803)
|
||||
+ /* lz4 <= 1.8.2 should fail that test, let's only check for newer ones */
|
||||
+ assert_se(memcmp(buf2, huge, r) == 0);
|
||||
+ }
|
||||
}
|
||||
#endif
|
||||
|
@ -0,0 +1,118 @@
|
||||
From 242273e1afd456e86ebc48d7d601cb28297f8efb Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= <zbyszek@in.waw.pl>
|
||||
Date: Tue, 30 Oct 2018 09:02:26 +0100
|
||||
Subject: [PATCH] fuzz-compress: add fuzzer for compression and decompression
|
||||
|
||||
(cherry picked from commit 029427043b2e0523a21f54374f872b23cf744350)
|
||||
Resolves: #1843871
|
||||
---
|
||||
src/fuzz/fuzz-compress.c | 80 ++++++++++++++++++++++++++++++++++++++++
|
||||
src/fuzz/meson.build | 7 +++-
|
||||
2 files changed, 86 insertions(+), 1 deletion(-)
|
||||
create mode 100644 src/fuzz/fuzz-compress.c
|
||||
|
||||
diff --git a/src/fuzz/fuzz-compress.c b/src/fuzz/fuzz-compress.c
|
||||
new file mode 100644
|
||||
index 0000000000..9c5dfc92c0
|
||||
--- /dev/null
|
||||
+++ b/src/fuzz/fuzz-compress.c
|
||||
@@ -0,0 +1,80 @@
|
||||
+/* SPDX-License-Identifier: LGPL-2.1+ */
|
||||
+
|
||||
+#include <errno.h>
|
||||
+
|
||||
+#include "alloc-util.h"
|
||||
+#include "compress.h"
|
||||
+#include "fuzz.h"
|
||||
+
|
||||
+static int compress(int alg,
|
||||
+ const void *src, uint64_t src_size,
|
||||
+ void *dst, size_t dst_alloc_size, size_t *dst_size) {
|
||||
+
|
||||
+ if (alg == OBJECT_COMPRESSED_LZ4)
|
||||
+ return compress_blob_lz4(src, src_size, dst, dst_alloc_size, dst_size);
|
||||
+ if (alg == OBJECT_COMPRESSED_XZ)
|
||||
+ return compress_blob_xz(src, src_size, dst, dst_alloc_size, dst_size);
|
||||
+ return -EOPNOTSUPP;
|
||||
+}
|
||||
+
|
||||
+typedef struct header {
|
||||
+ uint32_t alg:2; /* We have only two compression algorithms so far, but we might add
|
||||
+ * more in the future. Let's make this a bit wider so our fuzzer
|
||||
+ * cases remain stable in the future. */
|
||||
+ uint32_t sw_len;
|
||||
+ uint32_t sw_alloc;
|
||||
+ uint32_t reserved[3]; /* Extra space to keep fuzz cases stable in case we need to
|
||||
+ * add stuff in the future. */
|
||||
+ uint8_t data[];
|
||||
+} header;
|
||||
+
|
||||
+int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
|
||||
+ _cleanup_free_ void *buf = NULL, *buf2 = NULL;
|
||||
+ int r;
|
||||
+
|
||||
+ if (size < offsetof(header, data) + 1)
|
||||
+ return 0;
|
||||
+
|
||||
+ const header *h = (struct header*) data;
|
||||
+ const size_t data_len = size - offsetof(header, data);
|
||||
+
|
||||
+ int alg = h->alg;
|
||||
+
|
||||
+ /* We don't want to fill the logs with messages about parse errors.
|
||||
+ * Disable most logging if not running standalone */
|
||||
+ if (!getenv("SYSTEMD_LOG_LEVEL"))
|
||||
+ log_set_max_level(LOG_CRIT);
|
||||
+
|
||||
+ log_info("Using compression %s, data size=%zu",
|
||||
+ object_compressed_to_string(alg) ?: "(none)",
|
||||
+ data_len);
|
||||
+
|
||||
+ buf = malloc(MAX(size, 128u)); /* Make the buffer a bit larger for very small data */
|
||||
+ if (!buf) {
|
||||
+ log_oom();
|
||||
+ return 0;
|
||||
+ }
|
||||
+
|
||||
+ size_t csize;
|
||||
+ r = compress(alg, h->data, data_len, buf, size, &csize);
|
||||
+ if (r < 0) {
|
||||
+ log_error_errno(r, "Compression failed: %m");
|
||||
+ return 0;
|
||||
+ }
|
||||
+
|
||||
+ log_debug("Compressed %zu bytes to → %zu bytes", data_len, csize);
|
||||
+
|
||||
+ size_t sw_alloc = MAX(h->sw_alloc, 1u);
|
||||
+ buf2 = malloc(sw_alloc);
|
||||
+ if (!buf) {
|
||||
+ log_oom();
|
||||
+ return 0;
|
||||
+ }
|
||||
+
|
||||
+ size_t sw_len = MIN(data_len - 1, h->sw_len);
|
||||
+
|
||||
+ r = decompress_startswith(alg, buf, csize, &buf2, &sw_alloc, h->data, sw_len, h->data[sw_len]);
|
||||
+ assert_se(r > 0);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
diff --git a/src/fuzz/meson.build b/src/fuzz/meson.build
|
||||
index 5315d2771c..b8d5979d3c 100644
|
||||
--- a/src/fuzz/meson.build
|
||||
+++ b/src/fuzz/meson.build
|
||||
@@ -73,8 +73,13 @@ fuzzers += [
|
||||
[libsystemd_journal_remote,
|
||||
libshared],
|
||||
[]],
|
||||
+
|
||||
[['src/fuzz/fuzz-fido-id-desc.c',
|
||||
'src/udev/fido_id/fido_id_desc.c'],
|
||||
[],
|
||||
- []]
|
||||
+ []],
|
||||
+
|
||||
+ [['src/fuzz/fuzz-compress.c'],
|
||||
+ [libshared],
|
||||
+ []],
|
||||
]
|
35
SOURCES/0389-seccomp-fix-__NR__sysctl-usage.patch
Normal file
35
SOURCES/0389-seccomp-fix-__NR__sysctl-usage.patch
Normal file
@ -0,0 +1,35 @@
|
||||
From 65a066aae68744e889c114cee56dff5b48d872df Mon Sep 17 00:00:00 2001
|
||||
From: Jan Synacek <jsynacek@redhat.com>
|
||||
Date: Thu, 4 Jun 2020 16:55:52 +0200
|
||||
Subject: [PATCH] seccomp: fix __NR__sysctl usage
|
||||
|
||||
Loosely based on
|
||||
https://github.com/systemd/systemd/pull/14032 and
|
||||
https://github.com/systemd/systemd/pull/14268.
|
||||
|
||||
Related: #1843871
|
||||
---
|
||||
src/test/test-seccomp.c | 4 ++--
|
||||
1 file changed, 2 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/src/test/test-seccomp.c b/src/test/test-seccomp.c
|
||||
index 4021a06e0e..009a2e1922 100644
|
||||
--- a/src/test/test-seccomp.c
|
||||
+++ b/src/test/test-seccomp.c
|
||||
@@ -237,14 +237,14 @@ static void test_protect_sysctl(void) {
|
||||
assert_se(pid >= 0);
|
||||
|
||||
if (pid == 0) {
|
||||
-#if __NR__sysctl > 0
|
||||
+#if defined __NR__sysctl && __NR__sysctl >= 0
|
||||
assert_se(syscall(__NR__sysctl, NULL) < 0);
|
||||
assert_se(errno == EFAULT);
|
||||
#endif
|
||||
|
||||
assert_se(seccomp_protect_sysctl() >= 0);
|
||||
|
||||
-#if __NR__sysctl > 0
|
||||
+#if defined __NR__sysctl && __NR__sysctl >= 0
|
||||
assert_se(syscall(__NR__sysctl, 0, 0, 0) < 0);
|
||||
assert_se(errno == EPERM);
|
||||
#endif
|
@ -0,0 +1,174 @@
|
||||
From 3569b29eb8b082229dd97b8aae60bbe4d2f96ef5 Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= <zbyszek@in.waw.pl>
|
||||
Date: Wed, 19 Dec 2018 23:05:48 +0100
|
||||
Subject: [PATCH] tmpfiles: fix crash with NULL in arg_root and other fixes and
|
||||
tests
|
||||
|
||||
The function to replacement paths into the configuration file list was borked.
|
||||
Apart from the crash with empty root prefix, it would incorrectly handle the
|
||||
case where root *was* set, and the replacement file was supposed to override
|
||||
an existing file.
|
||||
|
||||
prefix_root is used instead of path_join because prefix_root removes duplicate
|
||||
slashes (when --root=dir/ is used).
|
||||
|
||||
A test is added.
|
||||
|
||||
Fixes #11124.
|
||||
|
||||
(cherry picked from commit 082bb1c59bd4300bcdc08488c94109680cfadf57)
|
||||
|
||||
Resolves: #1836024
|
||||
---
|
||||
src/basic/conf-files.c | 21 ++++++++-----
|
||||
src/test/test-conf-files.c | 61 +++++++++++++++++++++++++++++++++++++-
|
||||
2 files changed, 73 insertions(+), 9 deletions(-)
|
||||
|
||||
diff --git a/src/basic/conf-files.c b/src/basic/conf-files.c
|
||||
index d6ef0e941e..5ca83091c9 100644
|
||||
--- a/src/basic/conf-files.c
|
||||
+++ b/src/basic/conf-files.c
|
||||
@@ -204,14 +204,17 @@ int conf_files_insert(char ***strv, const char *root, char **dirs, const char *p
|
||||
if (c == 0) {
|
||||
char **dir;
|
||||
|
||||
- /* Oh, we found our spot and it already contains something. */
|
||||
+ /* Oh, there already is an entry with a matching name (the last component). */
|
||||
+
|
||||
STRV_FOREACH(dir, dirs) {
|
||||
+ _cleanup_free_ char *rdir = NULL;
|
||||
char *p1, *p2;
|
||||
|
||||
- p1 = path_startswith((*strv)[i], root);
|
||||
- if (p1)
|
||||
- /* Skip "/" in *dir, because p1 is without "/" too */
|
||||
- p1 = path_startswith(p1, *dir + 1);
|
||||
+ rdir = prefix_root(root, *dir);
|
||||
+ if (!rdir)
|
||||
+ return -ENOMEM;
|
||||
+
|
||||
+ p1 = path_startswith((*strv)[i], rdir);
|
||||
if (p1)
|
||||
/* Existing entry with higher priority
|
||||
* or same priority, no need to do anything. */
|
||||
@@ -220,7 +223,8 @@ int conf_files_insert(char ***strv, const char *root, char **dirs, const char *p
|
||||
p2 = path_startswith(path, *dir);
|
||||
if (p2) {
|
||||
/* Our new entry has higher priority */
|
||||
- t = path_join(root, path, NULL);
|
||||
+
|
||||
+ t = prefix_root(root, path);
|
||||
if (!t)
|
||||
return log_oom();
|
||||
|
||||
@@ -236,7 +240,8 @@ int conf_files_insert(char ***strv, const char *root, char **dirs, const char *p
|
||||
/* … we are not there yet, let's continue */
|
||||
}
|
||||
|
||||
- t = path_join(root, path, NULL);
|
||||
+ /* The new file has lower priority than all the existing entries */
|
||||
+ t = prefix_root(root, path);
|
||||
if (!t)
|
||||
return log_oom();
|
||||
|
||||
@@ -322,7 +327,7 @@ int conf_files_list_with_replacement(
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to extend config file list: %m");
|
||||
|
||||
- p = path_join(root, replacement, NULL);
|
||||
+ p = prefix_root(root, replacement);
|
||||
if (!p)
|
||||
return log_oom();
|
||||
}
|
||||
diff --git a/src/test/test-conf-files.c b/src/test/test-conf-files.c
|
||||
index 2ec2dfc261..5789767161 100644
|
||||
--- a/src/test/test-conf-files.c
|
||||
+++ b/src/test/test-conf-files.c
|
||||
@@ -13,6 +13,7 @@
|
||||
#include "macro.h"
|
||||
#include "mkdir.h"
|
||||
#include "parse-util.h"
|
||||
+#include "path-util.h"
|
||||
#include "rm-rf.h"
|
||||
#include "string-util.h"
|
||||
#include "strv.h"
|
||||
@@ -42,7 +43,7 @@ static void test_conf_files_list(bool use_root) {
|
||||
_cleanup_strv_free_ char **found_files = NULL, **found_files2 = NULL;
|
||||
const char *root_dir, *search_1, *search_2, *expect_a, *expect_b, *expect_c, *mask;
|
||||
|
||||
- log_debug("/* %s */", __func__);
|
||||
+ log_debug("/* %s(%s) */", __func__, yes_no(use_root));
|
||||
|
||||
setup_test_dir(tmp_dir,
|
||||
"/dir1/a.conf",
|
||||
@@ -92,6 +93,60 @@ static void test_conf_files_list(bool use_root) {
|
||||
assert_se(rm_rf(tmp_dir, REMOVE_ROOT|REMOVE_PHYSICAL) == 0);
|
||||
}
|
||||
|
||||
+static void test_conf_files_insert(const char *root) {
|
||||
+ _cleanup_strv_free_ char **s = NULL;
|
||||
+
|
||||
+ log_info("/* %s root=%s */", __func__, strempty(root));
|
||||
+
|
||||
+ char **dirs = STRV_MAKE("/dir1", "/dir2", "/dir3");
|
||||
+
|
||||
+ _cleanup_free_ const char
|
||||
+ *foo1 = prefix_root(root, "/dir1/foo.conf"),
|
||||
+ *foo2 = prefix_root(root, "/dir2/foo.conf"),
|
||||
+ *bar2 = prefix_root(root, "/dir2/bar.conf"),
|
||||
+ *zzz3 = prefix_root(root, "/dir3/zzz.conf"),
|
||||
+ *whatever = prefix_root(root, "/whatever.conf");
|
||||
+
|
||||
+ assert_se(conf_files_insert(&s, root, dirs, "/dir2/foo.conf") == 0);
|
||||
+ assert_se(strv_equal(s, STRV_MAKE(foo2)));
|
||||
+
|
||||
+ /* The same file again, https://github.com/systemd/systemd/issues/11124 */
|
||||
+ assert_se(conf_files_insert(&s, root, dirs, "/dir2/foo.conf") == 0);
|
||||
+ assert_se(strv_equal(s, STRV_MAKE(foo2)));
|
||||
+
|
||||
+ /* Lower priority → new entry is ignored */
|
||||
+ assert_se(conf_files_insert(&s, root, dirs, "/dir3/foo.conf") == 0);
|
||||
+ assert_se(strv_equal(s, STRV_MAKE(foo2)));
|
||||
+
|
||||
+ /* Higher priority → new entry replaces */
|
||||
+ assert_se(conf_files_insert(&s, root, dirs, "/dir1/foo.conf") == 0);
|
||||
+ assert_se(strv_equal(s, STRV_MAKE(foo1)));
|
||||
+
|
||||
+ /* Earlier basename */
|
||||
+ assert_se(conf_files_insert(&s, root, dirs, "/dir2/bar.conf") == 0);
|
||||
+ assert_se(strv_equal(s, STRV_MAKE(bar2, foo1)));
|
||||
+
|
||||
+ /* Later basename */
|
||||
+ assert_se(conf_files_insert(&s, root, dirs, "/dir3/zzz.conf") == 0);
|
||||
+ assert_se(strv_equal(s, STRV_MAKE(bar2, foo1, zzz3)));
|
||||
+
|
||||
+ /* All lower priority → all ignored */
|
||||
+ assert_se(conf_files_insert(&s, root, dirs, "/dir3/zzz.conf") == 0);
|
||||
+ assert_se(conf_files_insert(&s, root, dirs, "/dir2/bar.conf") == 0);
|
||||
+ assert_se(conf_files_insert(&s, root, dirs, "/dir3/bar.conf") == 0);
|
||||
+ assert_se(conf_files_insert(&s, root, dirs, "/dir2/foo.conf") == 0);
|
||||
+ assert_se(strv_equal(s, STRV_MAKE(bar2, foo1, zzz3)));
|
||||
+
|
||||
+ /* Two entries that don't match any of the directories, but match basename */
|
||||
+ assert_se(conf_files_insert(&s, root, dirs, "/dir4/zzz.conf") == 0);
|
||||
+ assert_se(conf_files_insert(&s, root, dirs, "/zzz.conf") == 0);
|
||||
+ assert_se(strv_equal(s, STRV_MAKE(bar2, foo1, zzz3)));
|
||||
+
|
||||
+ /* An entry that doesn't match any of the directories, no match at all */
|
||||
+ assert_se(conf_files_insert(&s, root, dirs, "/whatever.conf") == 0);
|
||||
+ assert_se(strv_equal(s, STRV_MAKE(bar2, foo1, whatever, zzz3)));
|
||||
+}
|
||||
+
|
||||
int main(int argc, char **argv) {
|
||||
log_set_max_level(LOG_DEBUG);
|
||||
log_parse_environment();
|
||||
@@ -99,5 +154,9 @@ int main(int argc, char **argv) {
|
||||
|
||||
test_conf_files_list(false);
|
||||
test_conf_files_list(true);
|
||||
+ test_conf_files_insert(NULL);
|
||||
+ test_conf_files_insert("/root");
|
||||
+ test_conf_files_insert("/root/");
|
||||
+
|
||||
return 0;
|
||||
}
|
@ -0,0 +1,85 @@
|
||||
From d8ae33a302f01601e9e98b4aca3516e93c634a54 Mon Sep 17 00:00:00 2001
|
||||
From: Andreas Henriksson <andreas@fatal.se>
|
||||
Date: Sun, 14 Oct 2018 14:53:09 +0200
|
||||
Subject: [PATCH] sulogin-shell: Use force if SYSTEMD_SULOGIN_FORCE set
|
||||
|
||||
When the root account is locked sulogin will either inform you of
|
||||
this and not allow you in or if --force is used it will hand
|
||||
you passwordless root (if using a recent enough version of util-linux).
|
||||
|
||||
Not being allowed a shell is ofcourse inconvenient, but at the same
|
||||
time handing out passwordless root unconditionally is probably not
|
||||
a good idea everywhere.
|
||||
|
||||
This patch thus allows to control which behaviour you want by
|
||||
setting the SYSTEMD_SULOGIN_FORCE environment variable to true
|
||||
or false to control the behaviour, eg. via adding this to
|
||||
'systemctl edit rescue.service' (or emergency.service):
|
||||
|
||||
[Service]
|
||||
Environment=SYSTEMD_SULOGIN_FORCE=1
|
||||
|
||||
Distributions who used locked root accounts and want the passwordless
|
||||
behaviour could thus simply drop in the override file in
|
||||
/etc/systemd/system/rescue.service.d/override.conf
|
||||
|
||||
Fixes: #7115
|
||||
Addresses: https://bugs.debian.org/802211
|
||||
(cherry picked from commit 33eb44fe4a8d7971b5614bc4c2d90f8d91cce66c)
|
||||
|
||||
Resolves: #1625929
|
||||
---
|
||||
doc/ENVIRONMENT.md | 6 ++++++
|
||||
src/sulogin-shell/sulogin-shell.c | 11 ++++++++++-
|
||||
2 files changed, 16 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/doc/ENVIRONMENT.md b/doc/ENVIRONMENT.md
|
||||
index 1e648be640..39a36a52cc 100644
|
||||
--- a/doc/ENVIRONMENT.md
|
||||
+++ b/doc/ENVIRONMENT.md
|
||||
@@ -101,3 +101,9 @@ systemd-timedated:
|
||||
NTP client services. If set, `timedatectl set-ntp on` enables and starts the
|
||||
first existing unit listed in the environment variable, and
|
||||
`timedatectl set-ntp off` disables and stops all listed units.
|
||||
+
|
||||
+systemd-sulogin-shell:
|
||||
+
|
||||
+* `$SYSTEMD_SULOGIN_FORCE=1` — This skips asking for the root password if the
|
||||
+ root password is not available (such as when the root account is locked).
|
||||
+ See `sulogin(8)` for more details.
|
||||
diff --git a/src/sulogin-shell/sulogin-shell.c b/src/sulogin-shell/sulogin-shell.c
|
||||
index 5db3592d6f..a1ea2333de 100644
|
||||
--- a/src/sulogin-shell/sulogin-shell.c
|
||||
+++ b/src/sulogin-shell/sulogin-shell.c
|
||||
@@ -9,6 +9,7 @@
|
||||
#include "bus-util.h"
|
||||
#include "bus-error.h"
|
||||
#include "def.h"
|
||||
+#include "env-util.h"
|
||||
#include "log.h"
|
||||
#include "process-util.h"
|
||||
#include "sd-bus.h"
|
||||
@@ -89,7 +90,11 @@ static void print_mode(const char* mode) {
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
- static const char* const sulogin_cmdline[] = {SULOGIN, NULL};
|
||||
+ const char* sulogin_cmdline[] = {
|
||||
+ SULOGIN,
|
||||
+ NULL, /* --force */
|
||||
+ NULL
|
||||
+ };
|
||||
_cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
|
||||
int r;
|
||||
|
||||
@@ -99,6 +104,10 @@ int main(int argc, char *argv[]) {
|
||||
|
||||
print_mode(argc > 1 ? argv[1] : "");
|
||||
|
||||
+ if (getenv_bool("SYSTEMD_SULOGIN_FORCE") > 0)
|
||||
+ /* allows passwordless logins if root account is locked. */
|
||||
+ sulogin_cmdline[1] = "--force";
|
||||
+
|
||||
(void) fork_wait(sulogin_cmdline);
|
||||
|
||||
r = bus_connect_system_systemd(&bus);
|
@ -0,0 +1,62 @@
|
||||
From 9b7aa39e7db5a6446d3c034741e64cda1a9dd200 Mon Sep 17 00:00:00 2001
|
||||
From: Filipe Brandenburger <filbranden@google.com>
|
||||
Date: Mon, 25 Jun 2018 18:07:48 -0700
|
||||
Subject: [PATCH] resolvconf: fixes for the compatibility interface
|
||||
|
||||
Also use compat_main() when called as `resolvconf`, since the interface
|
||||
is closer to that of `systemd-resolve`.
|
||||
|
||||
Use a heap allocated string to set arg_ifname, since a stack allocated
|
||||
one would be lost after the function returns. (This last one broke the
|
||||
case where an interface name was suffixed with a dot, such as in
|
||||
`resolvconf -a tap0.dhcp`.)
|
||||
|
||||
Tested:
|
||||
$ build/resolvconf -a nonexistent.abc </etc/resolv.conf
|
||||
Unknown interface 'nonexistent': No such device
|
||||
|
||||
Fixes #9423.
|
||||
|
||||
(cherry picked from commit 5a01b3f35d7b6182c78b6973db8d99bdabd4f9c3)
|
||||
|
||||
Resolves: #1835594
|
||||
---
|
||||
src/resolve/resolvconf-compat.c | 4 +++-
|
||||
src/resolve/resolvectl.c | 2 +-
|
||||
2 files changed, 4 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/src/resolve/resolvconf-compat.c b/src/resolve/resolvconf-compat.c
|
||||
index d7e68003e6..0723458945 100644
|
||||
--- a/src/resolve/resolvconf-compat.c
|
||||
+++ b/src/resolve/resolvconf-compat.c
|
||||
@@ -53,6 +53,8 @@ static int parse_nameserver(const char *string) {
|
||||
|
||||
if (strv_push(&arg_set_dns, word) < 0)
|
||||
return log_oom();
|
||||
+
|
||||
+ word = NULL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
@@ -202,7 +204,7 @@ int resolvconf_parse_argv(int argc, char *argv[]) {
|
||||
|
||||
dot = strchr(argv[optind], '.');
|
||||
if (dot) {
|
||||
- iface = strndupa(argv[optind], dot - argv[optind]);
|
||||
+ iface = strndup(argv[optind], dot - argv[optind]);
|
||||
log_debug("Ignoring protocol specifier '%s'.", dot + 1);
|
||||
} else
|
||||
iface = argv[optind];
|
||||
diff --git a/src/resolve/resolvectl.c b/src/resolve/resolvectl.c
|
||||
index cf1ec323a4..355e5c62b1 100644
|
||||
--- a/src/resolve/resolvectl.c
|
||||
+++ b/src/resolve/resolvectl.c
|
||||
@@ -3090,7 +3090,7 @@ int main(int argc, char **argv) {
|
||||
goto finish;
|
||||
}
|
||||
|
||||
- if (streq(program_invocation_short_name, "systemd-resolve"))
|
||||
+ if (STR_IN_SET(program_invocation_short_name, "systemd-resolve", "resolvconf"))
|
||||
r = compat_main(argc, argv, bus);
|
||||
else
|
||||
r = native_main(argc, argv, bus);
|
26
SOURCES/0393-mount-don-t-add-Requires-for-tmp.mount.patch
Normal file
26
SOURCES/0393-mount-don-t-add-Requires-for-tmp.mount.patch
Normal file
@ -0,0 +1,26 @@
|
||||
From 56bc690688957abe24d434b7ede16cbe0f2d1233 Mon Sep 17 00:00:00 2001
|
||||
From: David Tardon <dtardon@redhat.com>
|
||||
Date: Tue, 17 Mar 2020 10:49:44 +0100
|
||||
Subject: [PATCH] mount: don't add Requires for tmp.mount
|
||||
|
||||
This is a follow-up to #1619292.
|
||||
|
||||
rhel-only
|
||||
Resolves: #1748840
|
||||
---
|
||||
src/core/mount.c | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/src/core/mount.c b/src/core/mount.c
|
||||
index 30aaf5ae55..2746372db2 100644
|
||||
--- a/src/core/mount.c
|
||||
+++ b/src/core/mount.c
|
||||
@@ -305,7 +305,7 @@ static int mount_add_mount_dependencies(Mount *m) {
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
- if (UNIT(m)->fragment_path) {
|
||||
+ if (UNIT(m)->fragment_path && !streq(UNIT(m)->id, "tmp.mount")) {
|
||||
/* If we have fragment configuration, then make this dependency required */
|
||||
r = unit_add_dependency(other, UNIT_REQUIRES, UNIT(m), true, UNIT_DEPENDENCY_PATH);
|
||||
if (r < 0)
|
55
SOURCES/0394-core-coldplug-possible-nop_job.patch
Normal file
55
SOURCES/0394-core-coldplug-possible-nop_job.patch
Normal file
@ -0,0 +1,55 @@
|
||||
From 4a1405998671caaaad5b24d4cef309c05175b1c1 Mon Sep 17 00:00:00 2001
|
||||
From: ypf791 <ypf791@gmail.com>
|
||||
Date: Fri, 19 Jul 2019 18:28:04 +0800
|
||||
Subject: [PATCH] core: coldplug possible nop_job
|
||||
|
||||
When a unit in a state INACTIVE or DEACTIVATING, JobType JOB_TRY_RESTART or
|
||||
JOB_TRY_RELOAD will be collapsed to JOB_NOP. And use u->nop_job instead
|
||||
of u->job.
|
||||
|
||||
If a JOB_NOP job is going on with a waiting state, a parallel daemon-reload
|
||||
just install it during deserialization. Without a coldplug, the job will
|
||||
not be in m->run_queue, which results in a hung try-restart or
|
||||
try-reload process.
|
||||
|
||||
Reproduce:
|
||||
|
||||
run systemctl try-restart test.servcie (inactive) repeatly in a terminal.
|
||||
run systemctl daemon-reload repeatly in other terminals.
|
||||
|
||||
After successful reproduce, systemctl list-jobs will list the hang job.
|
||||
|
||||
Upsteam:
|
||||
systemd/systemd#13124
|
||||
|
||||
(cherry picked from commit b49e14d5f3081dfcd363d8199a14c0924ae9152f)
|
||||
|
||||
Resolves: #1829798
|
||||
---
|
||||
src/core/unit.c | 6 ++++--
|
||||
1 file changed, 4 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/src/core/unit.c b/src/core/unit.c
|
||||
index 61799bf9e3..f57260727f 100644
|
||||
--- a/src/core/unit.c
|
||||
+++ b/src/core/unit.c
|
||||
@@ -3696,6 +3696,7 @@ int unit_add_node_dependency(Unit *u, const char *what, bool wants, UnitDependen
|
||||
int unit_coldplug(Unit *u) {
|
||||
int r = 0, q;
|
||||
char **i;
|
||||
+ Job *uj;
|
||||
|
||||
assert(u);
|
||||
|
||||
@@ -3718,8 +3719,9 @@ int unit_coldplug(Unit *u) {
|
||||
r = q;
|
||||
}
|
||||
|
||||
- if (u->job) {
|
||||
- q = job_coldplug(u->job);
|
||||
+ uj = u->job ?: u->nop_job;
|
||||
+ if (uj) {
|
||||
+ q = job_coldplug(uj);
|
||||
if (q < 0 && r >= 0)
|
||||
r = q;
|
||||
}
|
584
SOURCES/0395-core-add-IODeviceLatencyTargetSec.patch
Normal file
584
SOURCES/0395-core-add-IODeviceLatencyTargetSec.patch
Normal file
@ -0,0 +1,584 @@
|
||||
From 2240e7955d64260e94dd52a3ab9855d267c2af89 Mon Sep 17 00:00:00 2001
|
||||
From: Tejun Heo <tj@kernel.org>
|
||||
Date: Wed, 13 Jun 2018 14:16:35 -0700
|
||||
Subject: [PATCH] core: add IODeviceLatencyTargetSec
|
||||
|
||||
This adds support for the following proposed latency based IO control
|
||||
mechanism.
|
||||
|
||||
https://lkml.org/lkml/2018/6/5/428
|
||||
|
||||
(cherry picked from commit 6ae4283cb14c4e4a895f4bbba703804e4128c86c)
|
||||
|
||||
Resolves: #1831519
|
||||
---
|
||||
man/systemd.resource-control.xml | 29 +++++--
|
||||
src/core/cgroup.c | 56 +++++++++++--
|
||||
src/core/cgroup.h | 9 +++
|
||||
src/core/dbus-cgroup.c | 111 ++++++++++++++++++++++++++
|
||||
src/core/load-fragment-gperf.gperf.m4 | 1 +
|
||||
src/core/load-fragment.c | 72 +++++++++++++++++
|
||||
src/core/load-fragment.h | 1 +
|
||||
src/shared/bus-unit-util.c | 31 +++++++
|
||||
src/systemctl/systemctl.c | 22 +++++
|
||||
9 files changed, 320 insertions(+), 12 deletions(-)
|
||||
|
||||
diff --git a/man/systemd.resource-control.xml b/man/systemd.resource-control.xml
|
||||
index 4329742e94..b0064bf98f 100644
|
||||
--- a/man/systemd.resource-control.xml
|
||||
+++ b/man/systemd.resource-control.xml
|
||||
@@ -417,11 +417,11 @@
|
||||
<listitem>
|
||||
<para>Set the per-device overall block I/O weight for the executed processes, if the unified control group
|
||||
hierarchy is used on the system. Takes a space-separated pair of a file path and a weight value to specify
|
||||
- the device specific weight value, between 1 and 10000. (Example: "/dev/sda 1000"). The file path may be
|
||||
- specified as path to a block device node or as any other file, in which case the backing block device of the
|
||||
- file system of the file is determined. This controls the <literal>io.weight</literal> control group
|
||||
- attribute, which defaults to 100. Use this option multiple times to set weights for multiple devices. For
|
||||
- details about this control group attribute, see <ulink
|
||||
+ the device specific weight value, between 1 and 10000. (Example: <literal>/dev/sda 1000</literal>). The file
|
||||
+ path may be specified as path to a block device node or as any other file, in which case the backing block
|
||||
+ device of the file system of the file is determined. This controls the <literal>io.weight</literal> control
|
||||
+ group attribute, which defaults to 100. Use this option multiple times to set weights for multiple devices.
|
||||
+ For details about this control group attribute, see <ulink
|
||||
url="https://www.kernel.org/doc/Documentation/cgroup-v2.txt">cgroup-v2.txt</ulink>.</para>
|
||||
|
||||
<para>Implies <literal>IOAccounting=true</literal>.</para>
|
||||
@@ -482,6 +482,25 @@
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
+ <varlistentry>
|
||||
+ <term><varname>IODeviceLatencyTargetSec=<replaceable>device</replaceable> <replaceable>target</replaceable></varname></term>
|
||||
+
|
||||
+ <listitem>
|
||||
+ <para>Set the per-device average target I/O latency for the executed processes, if the unified control group
|
||||
+ hierarchy is used on the system. Takes a file path and a timespan separated by a space to specify
|
||||
+ the device specific latency target. (Example: "/dev/sda 25ms"). The file path may be specified
|
||||
+ as path to a block device node or as any other file, in which case the backing block device of the file
|
||||
+ system of the file is determined. This controls the <literal>io.latency</literal> control group
|
||||
+ attribute. Use this option multiple times to set latency target for multiple devices. For details about this
|
||||
+ control group attribute, see <ulink
|
||||
+ url="https://www.kernel.org/doc/Documentation/cgroup-v2.txt">cgroup-v2.txt</ulink>.</para>
|
||||
+
|
||||
+ <para>Implies <literal>IOAccounting=true</literal>.</para>
|
||||
+
|
||||
+ <para>These settings are supported only if the unified control group hierarchy is used.</para>
|
||||
+ </listitem>
|
||||
+ </varlistentry>
|
||||
+
|
||||
<varlistentry>
|
||||
<term><varname>IPAccounting=</varname></term>
|
||||
|
||||
diff --git a/src/core/cgroup.c b/src/core/cgroup.c
|
||||
index 9e4c3c7dac..ad8219bd79 100644
|
||||
--- a/src/core/cgroup.c
|
||||
+++ b/src/core/cgroup.c
|
||||
@@ -114,6 +114,15 @@ void cgroup_context_free_io_device_weight(CGroupContext *c, CGroupIODeviceWeight
|
||||
free(w);
|
||||
}
|
||||
|
||||
+void cgroup_context_free_io_device_latency(CGroupContext *c, CGroupIODeviceLatency *l) {
|
||||
+ assert(c);
|
||||
+ assert(l);
|
||||
+
|
||||
+ LIST_REMOVE(device_latencies, c->io_device_latencies, l);
|
||||
+ free(l->path);
|
||||
+ free(l);
|
||||
+}
|
||||
+
|
||||
void cgroup_context_free_io_device_limit(CGroupContext *c, CGroupIODeviceLimit *l) {
|
||||
assert(c);
|
||||
assert(l);
|
||||
@@ -147,6 +156,9 @@ void cgroup_context_done(CGroupContext *c) {
|
||||
while (c->io_device_weights)
|
||||
cgroup_context_free_io_device_weight(c, c->io_device_weights);
|
||||
|
||||
+ while (c->io_device_latencies)
|
||||
+ cgroup_context_free_io_device_latency(c, c->io_device_latencies);
|
||||
+
|
||||
while (c->io_device_limits)
|
||||
cgroup_context_free_io_device_limit(c, c->io_device_limits);
|
||||
|
||||
@@ -171,6 +183,7 @@ void cgroup_context_dump(CGroupContext *c, FILE* f, const char *prefix) {
|
||||
_cleanup_free_ char *cpuset_mems = NULL;
|
||||
CGroupIODeviceLimit *il;
|
||||
CGroupIODeviceWeight *iw;
|
||||
+ CGroupIODeviceLatency *l;
|
||||
CGroupBlockIODeviceBandwidth *b;
|
||||
CGroupBlockIODeviceWeight *w;
|
||||
CGroupDeviceAllow *a;
|
||||
@@ -256,11 +269,18 @@ void cgroup_context_dump(CGroupContext *c, FILE* f, const char *prefix) {
|
||||
|
||||
LIST_FOREACH(device_weights, iw, c->io_device_weights)
|
||||
fprintf(f,
|
||||
- "%sIODeviceWeight=%s %" PRIu64,
|
||||
+ "%sIODeviceWeight=%s %" PRIu64 "\n",
|
||||
prefix,
|
||||
iw->path,
|
||||
iw->weight);
|
||||
|
||||
+ LIST_FOREACH(device_latencies, l, c->io_device_latencies)
|
||||
+ fprintf(f,
|
||||
+ "%sIODeviceLatencyTargetSec=%s %s\n",
|
||||
+ prefix,
|
||||
+ l->path,
|
||||
+ format_timespan(u, sizeof(u), l->target_usec, 1));
|
||||
+
|
||||
LIST_FOREACH(device_limits, il, c->io_device_limits) {
|
||||
char buf[FORMAT_BYTES_MAX];
|
||||
CGroupIOLimitType type;
|
||||
@@ -573,6 +593,7 @@ static bool cgroup_context_has_io_config(CGroupContext *c) {
|
||||
c->io_weight != CGROUP_WEIGHT_INVALID ||
|
||||
c->startup_io_weight != CGROUP_WEIGHT_INVALID ||
|
||||
c->io_device_weights ||
|
||||
+ c->io_device_latencies ||
|
||||
c->io_device_limits;
|
||||
}
|
||||
|
||||
@@ -646,6 +667,26 @@ static void cgroup_apply_blkio_device_weight(Unit *u, const char *dev_path, uint
|
||||
"Failed to set blkio.weight_device: %m");
|
||||
}
|
||||
|
||||
+static void cgroup_apply_io_device_latency(Unit *u, const char *dev_path, usec_t target) {
|
||||
+ char buf[DECIMAL_STR_MAX(dev_t)*2+2+7+DECIMAL_STR_MAX(uint64_t)+1];
|
||||
+ dev_t dev;
|
||||
+ int r;
|
||||
+
|
||||
+ r = lookup_block_device(dev_path, &dev);
|
||||
+ if (r < 0)
|
||||
+ return;
|
||||
+
|
||||
+ if (target != USEC_INFINITY)
|
||||
+ xsprintf(buf, "%u:%u target=%" PRIu64 "\n", major(dev), minor(dev), target);
|
||||
+ else
|
||||
+ xsprintf(buf, "%u:%u target=max\n", major(dev), minor(dev));
|
||||
+
|
||||
+ r = cg_set_attribute("io", u->cgroup_path, "io.latency", buf);
|
||||
+ if (r < 0)
|
||||
+ log_unit_full(u, IN_SET(r, -ENOENT, -EROFS, -EACCES) ? LOG_DEBUG : LOG_WARNING, r,
|
||||
+ "Failed to set io.latency on cgroup %s: %m", u->cgroup_path);
|
||||
+}
|
||||
+
|
||||
static void cgroup_apply_io_device_limit(Unit *u, const char *dev_path, uint64_t *limits) {
|
||||
char limit_bufs[_CGROUP_IO_LIMIT_TYPE_MAX][DECIMAL_STR_MAX(uint64_t)];
|
||||
char buf[DECIMAL_STR_MAX(dev_t)*2+2+(6+DECIMAL_STR_MAX(uint64_t)+1)*4];
|
||||
@@ -827,13 +868,11 @@ static void cgroup_context_apply(
|
||||
if (has_io) {
|
||||
CGroupIODeviceWeight *w;
|
||||
|
||||
- /* FIXME: no way to reset this list */
|
||||
LIST_FOREACH(device_weights, w, c->io_device_weights)
|
||||
cgroup_apply_io_device_weight(u, w->path, w->weight);
|
||||
} else if (has_blockio) {
|
||||
CGroupBlockIODeviceWeight *w;
|
||||
|
||||
- /* FIXME: no way to reset this list */
|
||||
LIST_FOREACH(device_weights, w, c->blockio_device_weights) {
|
||||
weight = cgroup_weight_blkio_to_io(w->weight);
|
||||
|
||||
@@ -843,9 +882,15 @@ static void cgroup_context_apply(
|
||||
cgroup_apply_io_device_weight(u, w->path, weight);
|
||||
}
|
||||
}
|
||||
+
|
||||
+ if (has_io) {
|
||||
+ CGroupIODeviceLatency *l;
|
||||
+
|
||||
+ LIST_FOREACH(device_latencies, l, c->io_device_latencies)
|
||||
+ cgroup_apply_io_device_latency(u, l->path, l->target_usec);
|
||||
+ }
|
||||
}
|
||||
|
||||
- /* Apply limits and free ones without config. */
|
||||
if (has_io) {
|
||||
CGroupIODeviceLimit *l;
|
||||
|
||||
@@ -902,7 +947,6 @@ static void cgroup_context_apply(
|
||||
if (has_io) {
|
||||
CGroupIODeviceWeight *w;
|
||||
|
||||
- /* FIXME: no way to reset this list */
|
||||
LIST_FOREACH(device_weights, w, c->io_device_weights) {
|
||||
weight = cgroup_weight_io_to_blkio(w->weight);
|
||||
|
||||
@@ -914,13 +958,11 @@ static void cgroup_context_apply(
|
||||
} else if (has_blockio) {
|
||||
CGroupBlockIODeviceWeight *w;
|
||||
|
||||
- /* FIXME: no way to reset this list */
|
||||
LIST_FOREACH(device_weights, w, c->blockio_device_weights)
|
||||
cgroup_apply_blkio_device_weight(u, w->path, w->weight);
|
||||
}
|
||||
}
|
||||
|
||||
- /* Apply limits and free ones without config. */
|
||||
if (has_io) {
|
||||
CGroupIODeviceLimit *l;
|
||||
|
||||
diff --git a/src/core/cgroup.h b/src/core/cgroup.h
|
||||
index da10575394..f7365b4c46 100644
|
||||
--- a/src/core/cgroup.h
|
||||
+++ b/src/core/cgroup.h
|
||||
@@ -13,6 +13,7 @@ typedef struct CGroupContext CGroupContext;
|
||||
typedef struct CGroupDeviceAllow CGroupDeviceAllow;
|
||||
typedef struct CGroupIODeviceWeight CGroupIODeviceWeight;
|
||||
typedef struct CGroupIODeviceLimit CGroupIODeviceLimit;
|
||||
+typedef struct CGroupIODeviceLatency CGroupIODeviceLatency;
|
||||
typedef struct CGroupBlockIODeviceWeight CGroupBlockIODeviceWeight;
|
||||
typedef struct CGroupBlockIODeviceBandwidth CGroupBlockIODeviceBandwidth;
|
||||
|
||||
@@ -52,6 +53,12 @@ struct CGroupIODeviceLimit {
|
||||
uint64_t limits[_CGROUP_IO_LIMIT_TYPE_MAX];
|
||||
};
|
||||
|
||||
+struct CGroupIODeviceLatency {
|
||||
+ LIST_FIELDS(CGroupIODeviceLatency, device_latencies);
|
||||
+ char *path;
|
||||
+ usec_t target_usec;
|
||||
+};
|
||||
+
|
||||
struct CGroupBlockIODeviceWeight {
|
||||
LIST_FIELDS(CGroupBlockIODeviceWeight, device_weights);
|
||||
char *path;
|
||||
@@ -85,6 +92,7 @@ struct CGroupContext {
|
||||
uint64_t startup_io_weight;
|
||||
LIST_HEAD(CGroupIODeviceWeight, io_device_weights);
|
||||
LIST_HEAD(CGroupIODeviceLimit, io_device_limits);
|
||||
+ LIST_HEAD(CGroupIODeviceLatency, io_device_latencies);
|
||||
|
||||
uint64_t memory_low;
|
||||
uint64_t memory_high;
|
||||
@@ -137,6 +145,7 @@ CGroupMask cgroup_context_get_mask(CGroupContext *c);
|
||||
void cgroup_context_free_device_allow(CGroupContext *c, CGroupDeviceAllow *a);
|
||||
void cgroup_context_free_io_device_weight(CGroupContext *c, CGroupIODeviceWeight *w);
|
||||
void cgroup_context_free_io_device_limit(CGroupContext *c, CGroupIODeviceLimit *l);
|
||||
+void cgroup_context_free_io_device_latency(CGroupContext *c, CGroupIODeviceLatency *l);
|
||||
void cgroup_context_free_blockio_device_weight(CGroupContext *c, CGroupBlockIODeviceWeight *w);
|
||||
void cgroup_context_free_blockio_device_bandwidth(CGroupContext *c, CGroupBlockIODeviceBandwidth *b);
|
||||
|
||||
diff --git a/src/core/dbus-cgroup.c b/src/core/dbus-cgroup.c
|
||||
index 30d4e83932..a1d3014d61 100644
|
||||
--- a/src/core/dbus-cgroup.c
|
||||
+++ b/src/core/dbus-cgroup.c
|
||||
@@ -140,6 +140,36 @@ static int property_get_io_device_limits(
|
||||
return sd_bus_message_close_container(reply);
|
||||
}
|
||||
|
||||
+static int property_get_io_device_latency(
|
||||
+ sd_bus *bus,
|
||||
+ const char *path,
|
||||
+ const char *interface,
|
||||
+ const char *property,
|
||||
+ sd_bus_message *reply,
|
||||
+ void *userdata,
|
||||
+ sd_bus_error *error) {
|
||||
+
|
||||
+ CGroupContext *c = userdata;
|
||||
+ CGroupIODeviceLatency *l;
|
||||
+ int r;
|
||||
+
|
||||
+ assert(bus);
|
||||
+ assert(reply);
|
||||
+ assert(c);
|
||||
+
|
||||
+ r = sd_bus_message_open_container(reply, 'a', "(st)");
|
||||
+ if (r < 0)
|
||||
+ return r;
|
||||
+
|
||||
+ LIST_FOREACH(device_latencies, l, c->io_device_latencies) {
|
||||
+ r = sd_bus_message_append(reply, "(st)", l->path, l->target_usec);
|
||||
+ if (r < 0)
|
||||
+ return r;
|
||||
+ }
|
||||
+
|
||||
+ return sd_bus_message_close_container(reply);
|
||||
+}
|
||||
+
|
||||
static int property_get_blockio_device_weight(
|
||||
sd_bus *bus,
|
||||
const char *path,
|
||||
@@ -314,6 +344,7 @@ const sd_bus_vtable bus_cgroup_vtable[] = {
|
||||
SD_BUS_PROPERTY("IOWriteBandwidthMax", "a(st)", property_get_io_device_limits, 0, 0),
|
||||
SD_BUS_PROPERTY("IOReadIOPSMax", "a(st)", property_get_io_device_limits, 0, 0),
|
||||
SD_BUS_PROPERTY("IOWriteIOPSMax", "a(st)", property_get_io_device_limits, 0, 0),
|
||||
+ SD_BUS_PROPERTY("IODeviceLatencyTargetUSec", "a(st)", property_get_io_device_latency, 0, 0),
|
||||
SD_BUS_PROPERTY("BlockIOAccounting", "b", bus_property_get_bool, offsetof(CGroupContext, blockio_accounting), 0),
|
||||
SD_BUS_PROPERTY("BlockIOWeight", "t", NULL, offsetof(CGroupContext, blockio_weight), 0),
|
||||
SD_BUS_PROPERTY("StartupBlockIOWeight", "t", NULL, offsetof(CGroupContext, startup_blockio_weight), 0),
|
||||
@@ -898,6 +929,86 @@ int bus_cgroup_set_property(
|
||||
|
||||
return 1;
|
||||
|
||||
+ } else if (streq(name, "IODeviceLatencyTargetUSec")) {
|
||||
+ const char *path;
|
||||
+ uint64_t target;
|
||||
+ unsigned n = 0;
|
||||
+
|
||||
+ r = sd_bus_message_enter_container(message, 'a', "(st)");
|
||||
+ if (r < 0)
|
||||
+ return r;
|
||||
+
|
||||
+ while ((r = sd_bus_message_read(message, "(st)", &path, &target)) > 0) {
|
||||
+
|
||||
+ if (!path_is_normalized(path))
|
||||
+ return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Path '%s' specified in %s= is not normalized.", name, path);
|
||||
+
|
||||
+ if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
|
||||
+ CGroupIODeviceLatency *a = NULL, *b;
|
||||
+
|
||||
+ LIST_FOREACH(device_latencies, b, c->io_device_latencies) {
|
||||
+ if (path_equal(b->path, path)) {
|
||||
+ a = b;
|
||||
+ break;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ if (!a) {
|
||||
+ a = new0(CGroupIODeviceLatency, 1);
|
||||
+ if (!a)
|
||||
+ return -ENOMEM;
|
||||
+
|
||||
+ a->path = strdup(path);
|
||||
+ if (!a->path) {
|
||||
+ free(a);
|
||||
+ return -ENOMEM;
|
||||
+ }
|
||||
+ LIST_PREPEND(device_latencies, c->io_device_latencies, a);
|
||||
+ }
|
||||
+
|
||||
+ a->target_usec = target;
|
||||
+ }
|
||||
+
|
||||
+ n++;
|
||||
+ }
|
||||
+
|
||||
+ r = sd_bus_message_exit_container(message);
|
||||
+ if (r < 0)
|
||||
+ return r;
|
||||
+
|
||||
+ if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
|
||||
+ _cleanup_free_ char *buf = NULL;
|
||||
+ _cleanup_fclose_ FILE *f = NULL;
|
||||
+ char ts[FORMAT_TIMESPAN_MAX];
|
||||
+ CGroupIODeviceLatency *a;
|
||||
+ size_t size = 0;
|
||||
+
|
||||
+ if (n == 0) {
|
||||
+ while (c->io_device_latencies)
|
||||
+ cgroup_context_free_io_device_latency(c, c->io_device_latencies);
|
||||
+ }
|
||||
+
|
||||
+ unit_invalidate_cgroup(u, CGROUP_MASK_IO);
|
||||
+
|
||||
+ f = open_memstream(&buf, &size);
|
||||
+ if (!f)
|
||||
+ return -ENOMEM;
|
||||
+
|
||||
+ (void) __fsetlocking(f, FSETLOCKING_BYCALLER);
|
||||
+
|
||||
+ fputs("IODeviceLatencyTargetSec=\n", f);
|
||||
+ LIST_FOREACH(device_latencies, a, c->io_device_latencies)
|
||||
+ fprintf(f, "IODeviceLatencyTargetSec=%s %s\n",
|
||||
+ a->path, format_timespan(ts, sizeof(ts), a->target_usec, 1));
|
||||
+
|
||||
+ r = fflush_and_check(f);
|
||||
+ if (r < 0)
|
||||
+ return r;
|
||||
+ unit_write_setting(u, flags, name, buf);
|
||||
+ }
|
||||
+
|
||||
+ return 1;
|
||||
+
|
||||
} else if (STR_IN_SET(name, "BlockIOReadBandwidth", "BlockIOWriteBandwidth")) {
|
||||
const char *path;
|
||||
bool read = true;
|
||||
diff --git a/src/core/load-fragment-gperf.gperf.m4 b/src/core/load-fragment-gperf.gperf.m4
|
||||
index 8883818ff2..23879c001f 100644
|
||||
--- a/src/core/load-fragment-gperf.gperf.m4
|
||||
+++ b/src/core/load-fragment-gperf.gperf.m4
|
||||
@@ -185,6 +185,7 @@ $1.IOReadBandwidthMax, config_parse_io_limit, 0,
|
||||
$1.IOWriteBandwidthMax, config_parse_io_limit, 0, offsetof($1, cgroup_context)
|
||||
$1.IOReadIOPSMax, config_parse_io_limit, 0, offsetof($1, cgroup_context)
|
||||
$1.IOWriteIOPSMax, config_parse_io_limit, 0, offsetof($1, cgroup_context)
|
||||
+$1.IODeviceLatencyTargetSec, config_parse_io_device_latency, 0, offsetof($1, cgroup_context)
|
||||
$1.BlockIOAccounting, config_parse_bool, 0, offsetof($1, cgroup_context.blockio_accounting)
|
||||
$1.BlockIOWeight, config_parse_blockio_weight, 0, offsetof($1, cgroup_context.blockio_weight)
|
||||
$1.StartupBlockIOWeight, config_parse_blockio_weight, 0, offsetof($1, cgroup_context.startup_blockio_weight)
|
||||
diff --git a/src/core/load-fragment.c b/src/core/load-fragment.c
|
||||
index 9b2724307d..1e22013b75 100644
|
||||
--- a/src/core/load-fragment.c
|
||||
+++ b/src/core/load-fragment.c
|
||||
@@ -3383,6 +3383,77 @@ int config_parse_io_device_weight(
|
||||
return 0;
|
||||
}
|
||||
|
||||
+int config_parse_io_device_latency(
|
||||
+ const char *unit,
|
||||
+ const char *filename,
|
||||
+ unsigned line,
|
||||
+ const char *section,
|
||||
+ unsigned section_line,
|
||||
+ const char *lvalue,
|
||||
+ int ltype,
|
||||
+ const char *rvalue,
|
||||
+ void *data,
|
||||
+ void *userdata) {
|
||||
+
|
||||
+ _cleanup_free_ char *path = NULL, *resolved = NULL;
|
||||
+ CGroupIODeviceLatency *l;
|
||||
+ CGroupContext *c = data;
|
||||
+ const char *p = rvalue;
|
||||
+ usec_t usec;
|
||||
+ int r;
|
||||
+
|
||||
+ assert(filename);
|
||||
+ assert(lvalue);
|
||||
+ assert(rvalue);
|
||||
+
|
||||
+ if (isempty(rvalue)) {
|
||||
+ while (c->io_device_latencies)
|
||||
+ cgroup_context_free_io_device_latency(c, c->io_device_latencies);
|
||||
+
|
||||
+ return 0;
|
||||
+ }
|
||||
+
|
||||
+ r = extract_first_word(&p, &path, NULL, EXTRACT_QUOTES);
|
||||
+ if (r == -ENOMEM)
|
||||
+ return log_oom();
|
||||
+ if (r < 0) {
|
||||
+ log_syntax(unit, LOG_WARNING, filename, line, r,
|
||||
+ "Invalid syntax, ignoring: %s", rvalue);
|
||||
+ return 0;
|
||||
+ }
|
||||
+ if (r == 0 || isempty(p)) {
|
||||
+ log_syntax(unit, LOG_WARNING, filename, line, 0,
|
||||
+ "Failed to extract device path and latency from '%s', ignoring.", rvalue);
|
||||
+ return 0;
|
||||
+ }
|
||||
+
|
||||
+ r = unit_full_printf(userdata, path, &resolved);
|
||||
+ if (r < 0) {
|
||||
+ log_syntax(unit, LOG_WARNING, filename, line, r,
|
||||
+ "Failed to resolve unit specifiers in '%s', ignoring: %m", path);
|
||||
+ return 0;
|
||||
+ }
|
||||
+
|
||||
+ r = path_simplify_and_warn(resolved, 0, unit, filename, line, lvalue);
|
||||
+ if (r < 0)
|
||||
+ return 0;
|
||||
+
|
||||
+ if (parse_sec(p, &usec) < 0) {
|
||||
+ log_syntax(unit, LOG_ERR, filename, line, 0, "Failed to parse timer value, ignoring: %s", p);
|
||||
+ return 0;
|
||||
+ }
|
||||
+
|
||||
+ l = new0(CGroupIODeviceLatency, 1);
|
||||
+ if (!l)
|
||||
+ return log_oom();
|
||||
+
|
||||
+ l->path = TAKE_PTR(resolved);
|
||||
+ l->target_usec = usec;
|
||||
+
|
||||
+ LIST_PREPEND(device_latencies, c->io_device_latencies, l);
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
int config_parse_io_limit(
|
||||
const char *unit,
|
||||
const char *filename,
|
||||
@@ -4572,6 +4643,7 @@ void unit_dump_config_items(FILE *f) {
|
||||
{ config_parse_device_policy, "POLICY" },
|
||||
{ config_parse_io_limit, "LIMIT" },
|
||||
{ config_parse_io_device_weight, "DEVICEWEIGHT" },
|
||||
+ { config_parse_io_device_latency, "DEVICELATENCY" },
|
||||
{ config_parse_blockio_bandwidth, "BANDWIDTH" },
|
||||
{ config_parse_blockio_weight, "WEIGHT" },
|
||||
{ config_parse_blockio_device_weight, "DEVICEWEIGHT" },
|
||||
diff --git a/src/core/load-fragment.h b/src/core/load-fragment.h
|
||||
index 424fa478a7..65a94d53cc 100644
|
||||
--- a/src/core/load-fragment.h
|
||||
+++ b/src/core/load-fragment.h
|
||||
@@ -68,6 +68,7 @@ CONFIG_PARSER_PROTOTYPE(config_parse_tasks_max);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_delegate);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_device_policy);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_device_allow);
|
||||
+CONFIG_PARSER_PROTOTYPE(config_parse_io_device_latency);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_io_device_weight);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_io_limit);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_blockio_weight);
|
||||
diff --git a/src/shared/bus-unit-util.c b/src/shared/bus-unit-util.c
|
||||
index e0b2cfb170..3c1ecf2027 100644
|
||||
--- a/src/shared/bus-unit-util.c
|
||||
+++ b/src/shared/bus-unit-util.c
|
||||
@@ -566,6 +566,37 @@ static int bus_append_cgroup_property(sd_bus_message *m, const char *field, cons
|
||||
return 1;
|
||||
}
|
||||
|
||||
+ if (streq(field, "IODeviceLatencyTargetSec")) {
|
||||
+ const char *field_usec = "IODeviceLatencyTargetUSec";
|
||||
+
|
||||
+ if (isempty(eq))
|
||||
+ r = sd_bus_message_append(m, "(sv)", field_usec, "a(st)", USEC_INFINITY);
|
||||
+ else {
|
||||
+ const char *path, *target, *e;
|
||||
+ usec_t usec;
|
||||
+
|
||||
+ e = strchr(eq, ' ');
|
||||
+ if (!e) {
|
||||
+ log_error("Failed to parse %s value %s.", field, eq);
|
||||
+ return -EINVAL;
|
||||
+ }
|
||||
+
|
||||
+ path = strndupa(eq, e - eq);
|
||||
+ target = e+1;
|
||||
+
|
||||
+ r = parse_sec(target, &usec);
|
||||
+ if (r < 0)
|
||||
+ return log_error_errno(r, "Failed to parse %s value %s: %m", field, target);
|
||||
+
|
||||
+ r = sd_bus_message_append(m, "(sv)", field_usec, "a(st)", 1, path, usec);
|
||||
+ }
|
||||
+
|
||||
+ if (r < 0)
|
||||
+ return bus_log_create_error(r);
|
||||
+
|
||||
+ return 1;
|
||||
+ }
|
||||
+
|
||||
if (STR_IN_SET(field, "IPAddressAllow", "IPAddressDeny")) {
|
||||
unsigned char prefixlen;
|
||||
union in_addr_union prefix = {};
|
||||
diff --git a/src/systemctl/systemctl.c b/src/systemctl/systemctl.c
|
||||
index a3074bc5e3..559e49f104 100644
|
||||
--- a/src/systemctl/systemctl.c
|
||||
+++ b/src/systemctl/systemctl.c
|
||||
@@ -4875,6 +4875,28 @@ static int print_property(const char *name, sd_bus_message *m, bool value, bool
|
||||
|
||||
return 1;
|
||||
|
||||
+ } else if (contents[0] == SD_BUS_TYPE_STRUCT_BEGIN &&
|
||||
+ streq(name, "IODeviceLatencyTargetUSec")) {
|
||||
+ char ts[FORMAT_TIMESPAN_MAX];
|
||||
+ const char *path;
|
||||
+ uint64_t target;
|
||||
+
|
||||
+ r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(st)");
|
||||
+ if (r < 0)
|
||||
+ return bus_log_parse_error(r);
|
||||
+
|
||||
+ while ((r = sd_bus_message_read(m, "(st)", &path, &target)) > 0)
|
||||
+ print_prop(name, "%s %s", strna(path),
|
||||
+ format_timespan(ts, sizeof(ts), target, 1));
|
||||
+ if (r < 0)
|
||||
+ return bus_log_parse_error(r);
|
||||
+
|
||||
+ r = sd_bus_message_exit_container(m);
|
||||
+ if (r < 0)
|
||||
+ return bus_log_parse_error(r);
|
||||
+
|
||||
+ return 1;
|
||||
+
|
||||
} else if (contents[0] == SD_BUS_TYPE_BYTE && streq(name, "StandardInputData")) {
|
||||
_cleanup_free_ char *h = NULL;
|
||||
const void *p;
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user