diff --git a/.systemd.metadata b/.systemd.metadata index 18c2ceb..a883c33 100644 --- a/.systemd.metadata +++ b/.systemd.metadata @@ -1 +1 @@ -8803baa484cbe36680463c8c5e6febeff074b8e7 SOURCES/systemd-239.tar.gz +8803baa484cbe36680463c8c5e6febeff074b8e7 SOURCES/systemd-239.tar.gz diff --git a/SOURCES/0296-catalog-fix-name-of-variable.patch b/SOURCES/0296-catalog-fix-name-of-variable.patch new file mode 100644 index 0000000..1e752eb --- /dev/null +++ b/SOURCES/0296-catalog-fix-name-of-variable.patch @@ -0,0 +1,531 @@ +From c3513c7bcc27210c89edad1740e1190e693df86f Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= +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@ 無法執行 diff --git a/SOURCES/0297-cryptsetup-add-keyfile-timeout-to-allow-a-keydev-tim.patch b/SOURCES/0297-cryptsetup-add-keyfile-timeout-to-allow-a-keydev-tim.patch new file mode 100644 index 0000000..8e99e2f --- /dev/null +++ b/SOURCES/0297-cryptsetup-add-keyfile-timeout-to-allow-a-keydev-tim.patch @@ -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="))) { diff --git a/SOURCES/0298-cryptsetup-add-documentation-for-keyfile-timeout.patch b/SOURCES/0298-cryptsetup-add-documentation-for-keyfile-timeout.patch new file mode 100644 index 0000000..c43658a --- /dev/null +++ b/SOURCES/0298-cryptsetup-add-documentation-for-keyfile-timeout.patch @@ -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. + + ++ ++ ++ ++ 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 ++ systemd-cryptsetup-generator8 ++ for key files on external devices. ++ ++ ++ + + + +@@ -417,7 +428,8 @@ + 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 ++hidden /mnt/tc_hidden /dev/null tcrypt-hidden,tcrypt-keyfile=/etc/keyfile ++external /dev/sda3 keyfile:LABEL=keydev keyfile-timeout=10s + + + diff --git a/SOURCES/0299-cryptsetup-use-unabbrieviated-variable-names.patch b/SOURCES/0299-cryptsetup-use-unabbrieviated-variable-names.patch new file mode 100644 index 0000000..be86edd --- /dev/null +++ b/SOURCES/0299-cryptsetup-use-unabbrieviated-variable-names.patch @@ -0,0 +1,63 @@ +From 0577d8378645c1ecd909b74403cefe31ed569398 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= +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; + } diff --git a/SOURCES/0300-cryptsetup-don-t-assert-on-variable-which-is-optiona.patch b/SOURCES/0300-cryptsetup-don-t-assert-on-variable-which-is-optiona.patch new file mode 100644 index 0000000..7154dca --- /dev/null +++ b/SOURCES/0300-cryptsetup-don-t-assert-on-variable-which-is-optiona.patch @@ -0,0 +1,37 @@ +From 5cdb2b0b2a0f8f89f97053b0633b8419506d4e28 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= +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); diff --git a/SOURCES/0301-cryptsetup-generator-guess-whether-the-keyfile-argum.patch b/SOURCES/0301-cryptsetup-generator-guess-whether-the-keyfile-argum.patch new file mode 100644 index 0000000..0f394ac --- /dev/null +++ b/SOURCES/0301-cryptsetup-generator-guess-whether-the-keyfile-argum.patch @@ -0,0 +1,100 @@ +From 9040e15cd3cba546b47aeae0ea133afa1a6ad292 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= +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"); + diff --git a/SOURCES/0302-crypt-util-Translate-libcryptsetup-log-level-instead.patch b/SOURCES/0302-crypt-util-Translate-libcryptsetup-log-level-instead.patch new file mode 100644 index 0000000..f7c2454 --- /dev/null +++ b/SOURCES/0302-crypt-util-Translate-libcryptsetup-log-level-instead.patch @@ -0,0 +1,46 @@ +From 05e184dea3f0182e5787812adfd52b68cff9418d Mon Sep 17 00:00:00 2001 +From: Jan Janssen +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 diff --git a/SOURCES/0303-cryptsetup-add-some-commenting-about-EAGAIN-generati.patch b/SOURCES/0303-cryptsetup-add-some-commenting-about-EAGAIN-generati.patch new file mode 100644 index 0000000..e8f6f83 --- /dev/null +++ b/SOURCES/0303-cryptsetup-add-some-commenting-about-EAGAIN-generati.patch @@ -0,0 +1,25 @@ +From ea0c4c31f6dff7d01e585bd8d5f962b373844544 Mon Sep 17 00:00:00 2001 +From: Lennart Poettering +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; diff --git a/SOURCES/0304-cryptsetup-downgrade-a-log-message-we-ignore.patch b/SOURCES/0304-cryptsetup-downgrade-a-log-message-we-ignore.patch new file mode 100644 index 0000000..cd853ee --- /dev/null +++ b/SOURCES/0304-cryptsetup-downgrade-a-log-message-we-ignore.patch @@ -0,0 +1,25 @@ +From 3bbacfb22a9266769a41dee6f8f594fbeb6287fc Mon Sep 17 00:00:00 2001 +From: Lennart Poettering +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]; + } diff --git a/SOURCES/0305-cryptsetup-rework-how-we-log-about-activation-failur.patch b/SOURCES/0305-cryptsetup-rework-how-we-log-about-activation-failur.patch new file mode 100644 index 0000000..5b357c3 --- /dev/null +++ b/SOURCES/0305-cryptsetup-rework-how-we-log-about-activation-failur.patch @@ -0,0 +1,102 @@ +From 966ecf0011a02c7823083a7868b8589fdf850be8 Mon Sep 17 00:00:00 2001 +From: Lennart Poettering +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) { diff --git a/SOURCES/0306-rules-reintroduce-60-alias-kmsg.rules.patch b/SOURCES/0306-rules-reintroduce-60-alias-kmsg.rules.patch new file mode 100644 index 0000000..2451c00 --- /dev/null +++ b/SOURCES/0306-rules-reintroduce-60-alias-kmsg.rules.patch @@ -0,0 +1,41 @@ +From b7f9d757dd6f276203b8b04f0c0ba1c61bcf8937 Mon Sep 17 00:00:00 2001 +From: Jan Synacek +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 diff --git a/SOURCES/0307-sd-bus-make-rqueue-wqueue-sizes-of-type-size_t.patch b/SOURCES/0307-sd-bus-make-rqueue-wqueue-sizes-of-type-size_t.patch new file mode 100644 index 0000000..65374a7 --- /dev/null +++ b/SOURCES/0307-sd-bus-make-rqueue-wqueue-sizes-of-type-size_t.patch @@ -0,0 +1,49 @@ +From 1d8e642b0b67f07b0bf469c25126b878380bae6a Mon Sep 17 00:00:00 2001 +From: Lennart Poettering +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); diff --git a/SOURCES/0308-sd-bus-reorder-bus-ref-and-bus-message-ref-handling.patch b/SOURCES/0308-sd-bus-reorder-bus-ref-and-bus-message-ref-handling.patch new file mode 100644 index 0000000..89004d8 --- /dev/null +++ b/SOURCES/0308-sd-bus-reorder-bus-ref-and-bus-message-ref-handling.patch @@ -0,0 +1,51 @@ +From 9c23ceef0a08ffdf4aed7a96ec440e1b110568ac Mon Sep 17 00:00:00 2001 +From: Lennart Poettering +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; diff --git a/SOURCES/0309-sd-bus-make-sure-dispatch_rqueue-initializes-return-.patch b/SOURCES/0309-sd-bus-make-sure-dispatch_rqueue-initializes-return-.patch new file mode 100644 index 0000000..9c7b804 --- /dev/null +++ b/SOURCES/0309-sd-bus-make-sure-dispatch_rqueue-initializes-return-.patch @@ -0,0 +1,32 @@ +From 19a9c67b79ebb9a65bc2aec8d8f2799262ef0cb2 Mon Sep 17 00:00:00 2001 +From: Lennart Poettering +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; + } diff --git a/SOURCES/0310-sd-bus-drop-two-inappropriate-empty-lines.patch b/SOURCES/0310-sd-bus-drop-two-inappropriate-empty-lines.patch new file mode 100644 index 0000000..da2330b --- /dev/null +++ b/SOURCES/0310-sd-bus-drop-two-inappropriate-empty-lines.patch @@ -0,0 +1,31 @@ +From 7e9944795e3f0046857379a5f878b365597ed373 Mon Sep 17 00:00:00 2001 +From: Lennart Poettering +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; + } + diff --git a/SOURCES/0311-sd-bus-initialize-mutex-after-we-allocated-the-wqueu.patch b/SOURCES/0311-sd-bus-initialize-mutex-after-we-allocated-the-wqueu.patch new file mode 100644 index 0000000..d91eb20 --- /dev/null +++ b/SOURCES/0311-sd-bus-initialize-mutex-after-we-allocated-the-wqueu.patch @@ -0,0 +1,33 @@ +From 247d4f826ab189c4dfc4706aaa94782342655218 Mon Sep 17 00:00:00 2001 +From: Lennart Poettering +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; + } diff --git a/SOURCES/0312-sd-bus-always-go-through-sd_bus_unref-to-free-messag.patch b/SOURCES/0312-sd-bus-always-go-through-sd_bus_unref-to-free-messag.patch new file mode 100644 index 0000000..4e2883a --- /dev/null +++ b/SOURCES/0312-sd-bus-always-go-through-sd_bus_unref-to-free-messag.patch @@ -0,0 +1,74 @@ +From 6180d5ee908c9c742f816c6922c229aefd533117 Mon Sep 17 00:00:00 2001 +From: Lennart Poettering +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); diff --git a/SOURCES/0313-bus-message-introduce-two-kinds-of-references-to-bus.patch b/SOURCES/0313-bus-message-introduce-two-kinds-of-references-to-bus.patch new file mode 100644 index 0000000..7eb554d --- /dev/null +++ b/SOURCES/0313-bus-message-introduce-two-kinds-of-references-to-bus.patch @@ -0,0 +1,182 @@ +From bc2d7df4fc21e9e54413169d5aad21616314d65e Mon Sep 17 00:00:00 2001 +From: Lennart Poettering +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); diff --git a/SOURCES/0314-sd-bus-introduce-API-for-re-enqueuing-incoming-messa.patch b/SOURCES/0314-sd-bus-introduce-API-for-re-enqueuing-incoming-messa.patch new file mode 100644 index 0000000..fdafc3d --- /dev/null +++ b/SOURCES/0314-sd-bus-introduce-API-for-re-enqueuing-incoming-messa.patch @@ -0,0 +1,74 @@ +From 8efdae75ddf035c8c04983820f8d8cf767cc17b1 Mon Sep 17 00:00:00 2001 +From: Jan Synacek +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); diff --git a/SOURCES/0315-sd-event-add-sd_event_source_disable_unref-helper.patch b/SOURCES/0315-sd-event-add-sd_event_source_disable_unref-helper.patch new file mode 100644 index 0000000..1748190 --- /dev/null +++ b/SOURCES/0315-sd-event-add-sd_event_source_disable_unref-helper.patch @@ -0,0 +1,130 @@ +From 73b87f8c73af714a32e7b56b217cd4e4f46a5ea7 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= +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 @@ + sd_event_source_unref + sd_event_source_unrefp + sd_event_source_ref ++ sd_event_source_disable_unref + + Increase or decrease event source reference counters + +@@ -45,6 +46,10 @@ + sd_event_source *source + + ++ ++ sd_event_source* sd_event_source_disable_unref ++ sd_event_source *source ++ + + + +@@ -80,23 +85,26 @@ + the passed event source object is + NULL. + +- 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 ++ 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 + sd_event_source_unref() with a prior call to +- sd_event_source_set_enabled() with +- SD_EVENT_OFF. ++ sd_event_source_set_enabled() with SD_EVENT_OFF or call ++ sd_event_source_disable_unref(), see below. ++ ++ sd_event_source_disable_unref() combines a call to ++ sd_event_source_set_enabled() with SD_EVENT_OFF with ++ sd_event_source_unref(). This ensures that the source is disabled before the local ++ reference to it is lost. The source parameter is allowed to be ++ NULL. + + + + Return Value + +- sd_event_source_unref() always returns +- NULL. +- sd_event_source_ref() always returns the +- event source object passed in. ++ sd_event_source_unref() and ++ sd_event_source_disable_unref() always return NULL. ++ sd_event_source_ref() always returns the event source object passed in. + + + +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); diff --git a/SOURCES/0316-polkit-when-authorizing-via-PK-let-s-re-resolve-call.patch b/SOURCES/0316-polkit-when-authorizing-via-PK-let-s-re-resolve-call.patch new file mode 100644 index 0000000..da3d850 --- /dev/null +++ b/SOURCES/0316-polkit-when-authorizing-via-PK-let-s-re-resolve-call.patch @@ -0,0 +1,156 @@ +From 2ec3c78b1d1ba907cd888aac3cdc3a86c03cda90 Mon Sep 17 00:00:00 2001 +From: Jan Synacek +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) { diff --git a/SOURCES/0317-sysctl-let-s-by-default-increase-the-numeric-PID-ran.patch b/SOURCES/0317-sysctl-let-s-by-default-increase-the-numeric-PID-ran.patch new file mode 100644 index 0000000..d7523ce --- /dev/null +++ b/SOURCES/0317-sysctl-let-s-by-default-increase-the-numeric-PID-ran.patch @@ -0,0 +1,70 @@ +From b9be2c6b48227642ba85c5a741f121cc99655904 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Michal=20Sekleta=CC=81r?= +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 = [] diff --git a/SOURCES/0318-journal-do-not-trigger-assertion-when-journal_file_c.patch b/SOURCES/0318-journal-do-not-trigger-assertion-when-journal_file_c.patch new file mode 100644 index 0000000..9ebc71d --- /dev/null +++ b/SOURCES/0318-journal-do-not-trigger-assertion-when-journal_file_c.patch @@ -0,0 +1,49 @@ +From dc4c3a5aa35a5e88adcf210471d9460262c8c0d9 Mon Sep 17 00:00:00 2001 +From: Yu Watanabe +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); + diff --git a/SOURCES/0319-journal-use-cleanup-attribute-at-one-more-place.patch b/SOURCES/0319-journal-use-cleanup-attribute-at-one-more-place.patch new file mode 100644 index 0000000..9ca0d60 --- /dev/null +++ b/SOURCES/0319-journal-use-cleanup-attribute-at-one-more-place.patch @@ -0,0 +1,58 @@ +From ceacf935ac9f59bc08b5901f70f227958a2bcf52 Mon Sep 17 00:00:00 2001 +From: Yu Watanabe +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; + } + diff --git a/SOURCES/0320-sd-bus-use-queue-message-references-for-managing-r-w.patch b/SOURCES/0320-sd-bus-use-queue-message-references-for-managing-r-w.patch new file mode 100644 index 0000000..f8ff1d5 --- /dev/null +++ b/SOURCES/0320-sd-bus-use-queue-message-references-for-managing-r-w.patch @@ -0,0 +1,183 @@ +From 781a055c17400e953bb7929434fe7a2e6517d5e8 Mon Sep 17 00:00:00 2001 +From: Lennart Poettering +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; + } diff --git a/SOURCES/0321-pid1-make-sure-to-restore-correct-default-values-for.patch b/SOURCES/0321-pid1-make-sure-to-restore-correct-default-values-for.patch new file mode 100644 index 0000000..2ca5b14 --- /dev/null +++ b/SOURCES/0321-pid1-make-sure-to-restore-correct-default-values-for.patch @@ -0,0 +1,261 @@ +From 77a273e02c1c811485d13ddca0f844512aed2cff Mon Sep 17 00:00:00 2001 +From: Jan Synacek +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, diff --git a/SOURCES/0322-main-introduce-a-define-HIGH_RLIMIT_MEMLOCK-similar-.patch b/SOURCES/0322-main-introduce-a-define-HIGH_RLIMIT_MEMLOCK-similar-.patch new file mode 100644 index 0000000..72ec11c --- /dev/null +++ b/SOURCES/0322-main-introduce-a-define-HIGH_RLIMIT_MEMLOCK-similar-.patch @@ -0,0 +1,37 @@ +From 0528a880ddf797a42b2de274e5c7bd2d9896c991 Mon Sep 17 00:00:00 2001 +From: Lennart Poettering +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"); + diff --git a/SOURCES/0323-seccomp-introduce-seccomp_restrict_suid_sgid-for-blo.patch b/SOURCES/0323-seccomp-introduce-seccomp_restrict_suid_sgid-for-blo.patch new file mode 100644 index 0000000..d63169b --- /dev/null +++ b/SOURCES/0323-seccomp-introduce-seccomp_restrict_suid_sgid-for-blo.patch @@ -0,0 +1,178 @@ +From 5a62c0daff82e8343d24f98e1761d27bf8015782 Mon Sep 17 00:00:00 2001 +From: Lennart Poettering +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 ++#include + #include + #include + #include + #include + #include + #include ++#include + + #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[]; + diff --git a/SOURCES/0324-test-add-test-case-for-restrict_suid_sgid.patch b/SOURCES/0324-test-add-test-case-for-restrict_suid_sgid.patch new file mode 100644 index 0000000..c04084f --- /dev/null +++ b/SOURCES/0324-test-add-test-case-for-restrict_suid_sgid.patch @@ -0,0 +1,265 @@ +From b39697a80ad388e2063c54e56333882f4307c1a1 Mon Sep 17 00:00:00 2001 +From: Jan Synacek +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; + } diff --git a/SOURCES/0325-core-expose-SUID-SGID-restriction-as-new-unit-settin.patch b/SOURCES/0325-core-expose-SUID-SGID-restriction-as-new-unit-settin.patch new file mode 100644 index 0000000..7d8d98a --- /dev/null +++ b/SOURCES/0325-core-expose-SUID-SGID-restriction-as-new-unit-settin.patch @@ -0,0 +1,157 @@ +From f79283a86531e3bbf0854b5f126b7b291fadfb43 Mon Sep 17 00:00:00 2001 +From: Lennart Poettering +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= diff --git a/SOURCES/0326-analyze-check-for-RestrictSUIDSGID-in-systemd-analyz.patch b/SOURCES/0326-analyze-check-for-RestrictSUIDSGID-in-systemd-analyz.patch new file mode 100644 index 0000000..ffdc4bf --- /dev/null +++ b/SOURCES/0326-analyze-check-for-RestrictSUIDSGID-in-systemd-analyz.patch @@ -0,0 +1,52 @@ +From 3d338556760632b9c8b646a719d56e02e3ad2088 Mon Sep 17 00:00:00 2001 +From: Lennart Poettering +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) }, diff --git a/SOURCES/0327-man-document-the-new-RestrictSUIDSGID-setting.patch b/SOURCES/0327-man-document-the-new-RestrictSUIDSGID-setting.patch new file mode 100644 index 0000000..f362587 --- /dev/null +++ b/SOURCES/0327-man-document-the-new-RestrictSUIDSGID-setting.patch @@ -0,0 +1,83 @@ +From 797ebaa8240aefc39de3d1713468b221c83ed3f5 Mon Sep 17 00:00:00 2001 +From: Lennart Poettering +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 + + NoNewPrivileges= + +- Takes a boolean argument. If true, ensures that the service process and all its children can +- never gain new privileges through execve() (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 SystemCallFilter=, +- SystemCallArchitectures=, RestrictAddressFamilies=, +- RestrictNamespaces=, PrivateDevices=, +- ProtectKernelTunables=, ProtectKernelModules=, +- MemoryDenyWriteExecute=, RestrictRealtime=, or +- LockPersonality= are specified. Note that even if this setting is overridden by them, +- systemctl show shows the original value of this setting. Also see +- No New Privileges ++ Takes a boolean argument. If true, ensures that the service process and all its ++ children can never gain new privileges through execve() (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 ++ SystemCallFilter=, SystemCallArchitectures=, ++ RestrictAddressFamilies=, RestrictNamespaces=, ++ PrivateDevices=, ProtectKernelTunables=, ++ ProtectKernelModules=, MemoryDenyWriteExecute=, ++ RestrictRealtime=, RestrictSUIDSGID= or ++ LockPersonality= are specified. Note that even if this setting is overridden by ++ them, systemctl show shows the original value of this setting. Also see No New Privileges + Flag. + + +@@ -1274,6 +1275,22 @@ RestrictNamespaces=~cgroup net + that actually require them. Defaults to off. + + ++ ++ RestrictSUIDSGID= ++ ++ 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 ++ inode7). If ++ running in user mode, or in system mode, but without the CAP_SYS_ADMIN ++ capability (e.g. setting User=), NoNewPrivileges=yes 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. ++ ++ + + RemoveIPC= + diff --git a/SOURCES/0328-units-turn-on-RestrictSUIDSGID-in-most-of-our-long-r.patch b/SOURCES/0328-units-turn-on-RestrictSUIDSGID-in-most-of-our-long-r.patch new file mode 100644 index 0000000..8a9917f --- /dev/null +++ b/SOURCES/0328-units-turn-on-RestrictSUIDSGID-in-most-of-our-long-r.patch @@ -0,0 +1,157 @@ +From b0573f1a6f8022aed4954d5ca19cc037d25cd5e7 Mon Sep 17 00:00:00 2001 +From: Lennart Poettering +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 diff --git a/SOURCES/0329-core-imply-NNP-and-SUID-SGID-restriction-for-Dynamic.patch b/SOURCES/0329-core-imply-NNP-and-SUID-SGID-restriction-for-Dynamic.patch new file mode 100644 index 0000000..df4279c --- /dev/null +++ b/SOURCES/0329-core-imply-NNP-and-SUID-SGID-restriction-for-Dynamic.patch @@ -0,0 +1,89 @@ +From 11f5677752f9b78239214b3064e5a2c3712d71b1 Mon Sep 17 00:00:00 2001 +From: Lennart Poettering +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 /tmp and /var/tmp 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 ProtectSystem=strict and ++ cannot leave files around after unit termination. Furthermore NoNewPrivileges= and ++ RestrictSUIDSGID= are implicitly enabled to ensure that processes invoked cannot take benefit ++ or create SUID/SGID files or directories. Moreover ProtectSystem=strict and + ProtectHome=read-only 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 ReadWritePaths=, but care must be taken so that UID/GID recycling doesn't create +@@ -357,11 +359,12 @@ CapabilityBoundingSet=~CAP_B CAP_C + RestrictAddressFamilies=, RestrictNamespaces=, + PrivateDevices=, ProtectKernelTunables=, + ProtectKernelModules=, MemoryDenyWriteExecute=, +- RestrictRealtime=, RestrictSUIDSGID= or +- LockPersonality= are specified. Note that even if this setting is overridden by +- them, systemctl show shows the original value of this setting. Also see RestrictRealtime=, RestrictSUIDSGID=, ++ DynamicUser= or LockPersonality= are specified. Note that even ++ if this setting is overridden by them, systemctl show shows the original value of ++ this setting. Also see No New Privileges +- Flag. ++ Flag. + + + +@@ -1288,7 +1291,8 @@ RestrictNamespaces=~cgroup net + 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. ++ meaning than for files, see documentation). This option is implied if DynamicUser= ++ is enabled. Defaults to off. + + + +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; + } + } + diff --git a/SOURCES/0330-cgroup-introduce-support-for-cgroup-v2-CPUSET-contro.patch b/SOURCES/0330-cgroup-introduce-support-for-cgroup-v2-CPUSET-contro.patch new file mode 100644 index 0000000..d8d2f87 --- /dev/null +++ b/SOURCES/0330-cgroup-introduce-support-for-cgroup-v2-CPUSET-contro.patch @@ -0,0 +1,555 @@ +From b55c9b8e717d1967e6aa16c1e2646fc81d899ab7 Mon Sep 17 00:00:00 2001 +From: Pavel Hrdina +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 @@ + + + ++ ++ AllowedCPUs= ++ ++ ++ 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. ++ ++ Setting AllowedCPUs= 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 EffectiveCPUs=. ++ ++ This setting is supported only with the unified control group hierarchy. ++ ++ ++ ++ ++ AllowedMemoryNodes= ++ ++ ++ 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. ++ ++ Setting AllowedMemoryNodes= 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 ++ EffectiveMemoryNodes=. ++ ++ This setting is supported only with the unified control group hierarchy. ++ ++ ++ + + MemoryAccounting= + +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 + + #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"); diff --git a/SOURCES/0331-pid1-fix-DefaultTasksMax-initialization.patch b/SOURCES/0331-pid1-fix-DefaultTasksMax-initialization.patch new file mode 100644 index 0000000..9c89a62 --- /dev/null +++ b/SOURCES/0331-pid1-fix-DefaultTasksMax-initialization.patch @@ -0,0 +1,41 @@ +From e809564cfa5af01a26075682d49f81a987c41dd8 Mon Sep 17 00:00:00 2001 +From: Franck Bui +Date: Wed, 2 Oct 2019 11:58:16 +0200 +Subject: [PATCH 331/341] 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(); + +-- +2.21.1 + diff --git a/SOURCES/0332-cgroup-make-sure-that-cpuset-is-supported-on-cgroup-.patch b/SOURCES/0332-cgroup-make-sure-that-cpuset-is-supported-on-cgroup-.patch new file mode 100644 index 0000000..2596a8e --- /dev/null +++ b/SOURCES/0332-cgroup-make-sure-that-cpuset-is-supported-on-cgroup-.patch @@ -0,0 +1,43 @@ +From 5fc2d94fbf8271bb340e834f832af5d890c267bf Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Michal=20Sekleta=CC=81r?= +Date: Tue, 3 Mar 2020 11:45:00 +0100 +Subject: [PATCH 332/341] 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); +-- +2.21.1 + diff --git a/SOURCES/0333-test-introduce-TEST-36-NUMAPOLICY.patch b/SOURCES/0333-test-introduce-TEST-36-NUMAPOLICY.patch new file mode 100644 index 0000000..2e1b42a --- /dev/null +++ b/SOURCES/0333-test-introduce-TEST-36-NUMAPOLICY.patch @@ -0,0 +1,383 @@ +From 90dda340e4adeb1126639a849d4f31ae327fdc4b Mon Sep 17 00:00:00 2001 +From: Frantisek Sumsal +Date: Tue, 25 Jun 2019 23:01:40 +0200 +Subject: [PATCH 333/341] 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 < $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 +-- +2.21.1 + diff --git a/SOURCES/0334-test-replace-tail-f-with-journal-cursor-which-should.patch b/SOURCES/0334-test-replace-tail-f-with-journal-cursor-which-should.patch new file mode 100644 index 0000000..8254d16 --- /dev/null +++ b/SOURCES/0334-test-replace-tail-f-with-journal-cursor-which-should.patch @@ -0,0 +1,55 @@ +From b93a2617d49d9636801130d974995cabe6335b71 Mon Sep 17 00:00:00 2001 +From: Frantisek Sumsal +Date: Mon, 1 Jul 2019 09:27:59 +0200 +Subject: [PATCH 334/341] 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() { +-- +2.21.1 + diff --git a/SOURCES/0335-test-support-MPOL_LOCAL-matching-in-unpatched-strace.patch b/SOURCES/0335-test-support-MPOL_LOCAL-matching-in-unpatched-strace.patch new file mode 100644 index 0000000..8d293d9 --- /dev/null +++ b/SOURCES/0335-test-support-MPOL_LOCAL-matching-in-unpatched-strace.patch @@ -0,0 +1,61 @@ +From d6d43b81df76d571d57f83ceb050c8b4ac4701b8 Mon Sep 17 00:00:00 2001 +From: Frantisek Sumsal +Date: Mon, 1 Jul 2019 13:08:26 +0200 +Subject: [PATCH 335/341] 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' +-- +2.21.1 + diff --git a/SOURCES/0336-test-make-sure-the-strace-process-is-indeed-dead.patch b/SOURCES/0336-test-make-sure-the-strace-process-is-indeed-dead.patch new file mode 100644 index 0000000..55d9b4f --- /dev/null +++ b/SOURCES/0336-test-make-sure-the-strace-process-is-indeed-dead.patch @@ -0,0 +1,53 @@ +From 60813b55f9b5b44b14f38bbc1b8c0d2b30e3f6c7 Mon Sep 17 00:00:00 2001 +From: Frantisek Sumsal +Date: Mon, 1 Jul 2019 19:53:45 +0200 +Subject: [PATCH 336/341] 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 + } + +-- +2.21.1 + diff --git a/SOURCES/0337-test-skip-the-test-on-systems-without-NUMA-support.patch b/SOURCES/0337-test-skip-the-test-on-systems-without-NUMA-support.patch new file mode 100644 index 0000000..2680709 --- /dev/null +++ b/SOURCES/0337-test-skip-the-test-on-systems-without-NUMA-support.patch @@ -0,0 +1,39 @@ +From ad3e4a0f010c9497b01d89de54213af982f8afd2 Mon Sep 17 00:00:00 2001 +From: Frantisek Sumsal +Date: Tue, 2 Jul 2019 09:52:45 +0200 +Subject: [PATCH 337/341] 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 +-- +2.21.1 + diff --git a/SOURCES/0338-test-give-strace-some-time-to-initialize.patch b/SOURCES/0338-test-give-strace-some-time-to-initialize.patch new file mode 100644 index 0000000..5d68666 --- /dev/null +++ b/SOURCES/0338-test-give-strace-some-time-to-initialize.patch @@ -0,0 +1,33 @@ +From 66f6f6304d87b2fe0c4f91373c7d1b836de1b054 Mon Sep 17 00:00:00 2001 +From: Frantisek Sumsal +Date: Tue, 23 Jul 2019 00:56:04 +0200 +Subject: [PATCH 338/341] 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() { +-- +2.21.1 + diff --git a/SOURCES/0339-test-add-a-simple-sanity-check-for-systems-without-N.patch b/SOURCES/0339-test-add-a-simple-sanity-check-for-systems-without-N.patch new file mode 100644 index 0000000..10d52aa --- /dev/null +++ b/SOURCES/0339-test-add-a-simple-sanity-check-for-systems-without-N.patch @@ -0,0 +1,394 @@ +From 8239ecf0b4b8bbe5b3c17964d230d13cee4d900a Mon Sep 17 00:00:00 2001 +From: Frantisek Sumsal +Date: Mon, 5 Aug 2019 14:38:45 +0200 +Subject: [PATCH 339/341] 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 +-- +2.21.1 + diff --git a/SOURCES/0340-test-drop-the-missed-exit-1-expression.patch b/SOURCES/0340-test-drop-the-missed-exit-1-expression.patch new file mode 100644 index 0000000..d0df520 --- /dev/null +++ b/SOURCES/0340-test-drop-the-missed-exit-1-expression.patch @@ -0,0 +1,38 @@ +From 772f08f8255d7ab921c344ab4243249cbd1c37fc Mon Sep 17 00:00:00 2001 +From: Frantisek Sumsal +Date: Sat, 10 Aug 2019 16:05:07 +0200 +Subject: [PATCH 340/341] 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" +-- +2.21.1 + diff --git a/SOURCES/0341-test-replace-cursor-file-with-a-plain-cursor.patch b/SOURCES/0341-test-replace-cursor-file-with-a-plain-cursor.patch new file mode 100644 index 0000000..f3b1f25 --- /dev/null +++ b/SOURCES/0341-test-replace-cursor-file-with-a-plain-cursor.patch @@ -0,0 +1,62 @@ +From 0bef8805c81eecfe3960bf00b6022837e4979198 Mon Sep 17 00:00:00 2001 +From: Frantisek Sumsal +Date: Tue, 3 Mar 2020 15:54:29 +0100 +Subject: [PATCH 341/341] 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() { +-- +2.21.1 + diff --git a/SOURCES/0342-cryptsetup-Treat-key-file-errors-as-a-failed-passwor.patch b/SOURCES/0342-cryptsetup-Treat-key-file-errors-as-a-failed-passwor.patch new file mode 100644 index 0000000..4fee429 --- /dev/null +++ b/SOURCES/0342-cryptsetup-Treat-key-file-errors-as-a-failed-passwor.patch @@ -0,0 +1,32 @@ +From ed282d8d84fa32aaef21994d92d1d3dbfa281094 Mon Sep 17 00:00:00 2001 +From: Ryan Gonzalez +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 { diff --git a/SPECS/systemd.spec b/SPECS/systemd.spec index e6a8d07..1c03e7a 100644 --- a/SPECS/systemd.spec +++ b/SPECS/systemd.spec @@ -13,7 +13,7 @@ Name: systemd Url: http://www.freedesktop.org/wiki/Software/systemd Version: 239 -Release: 21%{?dist} +Release: 29%{?dist} # For a breakdown of the licensing, see README License: LGPLv2+ and MIT and GPLv2+ Summary: System and Service Manager @@ -345,6 +345,53 @@ Patch0292: 0292-core-job-fix-breakage-of-ordering-dependencies-by-sy.patch Patch0293: 0293-debug-generator-enable-custom-systemd.debug_shell-tt.patch Patch0294: 0294-test-cpu-set-util-fix-comparison-for-allocation-size.patch Patch0295: 0295-test-cpu-set-util-fix-allocation-size-check-on-i386.patch +Patch0296: 0296-catalog-fix-name-of-variable.patch +Patch0297: 0297-cryptsetup-add-keyfile-timeout-to-allow-a-keydev-tim.patch +Patch0298: 0298-cryptsetup-add-documentation-for-keyfile-timeout.patch +Patch0299: 0299-cryptsetup-use-unabbrieviated-variable-names.patch +Patch0300: 0300-cryptsetup-don-t-assert-on-variable-which-is-optiona.patch +Patch0301: 0301-cryptsetup-generator-guess-whether-the-keyfile-argum.patch +Patch0302: 0302-crypt-util-Translate-libcryptsetup-log-level-instead.patch +Patch0303: 0303-cryptsetup-add-some-commenting-about-EAGAIN-generati.patch +Patch0304: 0304-cryptsetup-downgrade-a-log-message-we-ignore.patch +Patch0305: 0305-cryptsetup-rework-how-we-log-about-activation-failur.patch +Patch0306: 0306-rules-reintroduce-60-alias-kmsg.rules.patch +Patch0307: 0307-sd-bus-make-rqueue-wqueue-sizes-of-type-size_t.patch +Patch0308: 0308-sd-bus-reorder-bus-ref-and-bus-message-ref-handling.patch +Patch0309: 0309-sd-bus-make-sure-dispatch_rqueue-initializes-return-.patch +Patch0310: 0310-sd-bus-drop-two-inappropriate-empty-lines.patch +Patch0311: 0311-sd-bus-initialize-mutex-after-we-allocated-the-wqueu.patch +Patch0312: 0312-sd-bus-always-go-through-sd_bus_unref-to-free-messag.patch +Patch0313: 0313-bus-message-introduce-two-kinds-of-references-to-bus.patch +Patch0314: 0314-sd-bus-introduce-API-for-re-enqueuing-incoming-messa.patch +Patch0315: 0315-sd-event-add-sd_event_source_disable_unref-helper.patch +Patch0316: 0316-polkit-when-authorizing-via-PK-let-s-re-resolve-call.patch +Patch0317: 0317-sysctl-let-s-by-default-increase-the-numeric-PID-ran.patch +Patch0318: 0318-journal-do-not-trigger-assertion-when-journal_file_c.patch +Patch0319: 0319-journal-use-cleanup-attribute-at-one-more-place.patch +Patch0320: 0320-sd-bus-use-queue-message-references-for-managing-r-w.patch +Patch0321: 0321-pid1-make-sure-to-restore-correct-default-values-for.patch +Patch0322: 0322-main-introduce-a-define-HIGH_RLIMIT_MEMLOCK-similar-.patch +Patch0323: 0323-seccomp-introduce-seccomp_restrict_suid_sgid-for-blo.patch +Patch0324: 0324-test-add-test-case-for-restrict_suid_sgid.patch +Patch0325: 0325-core-expose-SUID-SGID-restriction-as-new-unit-settin.patch +Patch0326: 0326-analyze-check-for-RestrictSUIDSGID-in-systemd-analyz.patch +Patch0327: 0327-man-document-the-new-RestrictSUIDSGID-setting.patch +Patch0328: 0328-units-turn-on-RestrictSUIDSGID-in-most-of-our-long-r.patch +Patch0329: 0329-core-imply-NNP-and-SUID-SGID-restriction-for-Dynamic.patch +Patch0330: 0330-cgroup-introduce-support-for-cgroup-v2-CPUSET-contro.patch +Patch0331: 0331-pid1-fix-DefaultTasksMax-initialization.patch +Patch0332: 0332-cgroup-make-sure-that-cpuset-is-supported-on-cgroup-.patch +Patch0333: 0333-test-introduce-TEST-36-NUMAPOLICY.patch +Patch0334: 0334-test-replace-tail-f-with-journal-cursor-which-should.patch +Patch0335: 0335-test-support-MPOL_LOCAL-matching-in-unpatched-strace.patch +Patch0336: 0336-test-make-sure-the-strace-process-is-indeed-dead.patch +Patch0337: 0337-test-skip-the-test-on-systems-without-NUMA-support.patch +Patch0338: 0338-test-give-strace-some-time-to-initialize.patch +Patch0339: 0339-test-add-a-simple-sanity-check-for-systems-without-N.patch +Patch0340: 0340-test-drop-the-missed-exit-1-expression.patch +Patch0341: 0341-test-replace-cursor-file-with-a-plain-cursor.patch +Patch0342: 0342-cryptsetup-Treat-key-file-errors-as-a-failed-passwor.patch %ifarch %{ix86} x86_64 aarch64 @@ -412,6 +459,7 @@ Provides: /bin/systemctl Provides: /sbin/shutdown Provides: syslog Provides: systemd-units = %{version}-%{release} +Provides: systemd-rpm-macros = %{version}-%{release} Obsoletes: system-setup-keyboard < 0.9 Provides: system-setup-keyboard = 0.9 # systemd-sysv-convert was removed in f20: https://fedorahosted.org/fpc/ticket/308 @@ -606,6 +654,10 @@ CONFIGURE_OPTS=( -Ddefault-hierarchy=legacy ) +# Don't ship /var/log/README. The relationship between journal and syslog should be documented +# in the official documentation. +sed -ie "/subdir('doc\/var-log')/d" meson.build + %meson "${CONFIGURE_OPTS[@]}" %meson_build @@ -964,6 +1016,71 @@ fi %files tests -f .file-list-tests %changelog +* Mon Mar 23 2020 systemd maintenance team - 239-29 +- cryptsetup: Treat key file errors as a failed password attempt (#1763155) + +* Wed Mar 11 2020 systemd maintenance team - 239-28 +- pid1: fix DefaultTasksMax initialization (#1809037) +- cgroup: make sure that cpuset is supported on cgroup v2 and disabled with v1 (#1808940) +- test: introduce TEST-36-NUMAPOLICY (#1808940) +- test: replace `tail -f` with journal cursor which should be more reliable (#1808940) +- test: support MPOL_LOCAL matching in unpatched strace versions (#1808940) +- test: make sure the strace process is indeed dead (#1808940) +- test: skip the test on systems without NUMA support (#1808940) +- test: give strace some time to initialize (#1808940) +- test: add a simple sanity check for systems without NUMA support (#1808940) +- test: drop the missed || exit 1 expression (#1808940) +- test: replace cursor file with a plain cursor (#1808940) + +* Fri Feb 21 2020 systemd maintenance team - 239-27 +- cgroup: introduce support for cgroup v2 CPUSET controller (#1724617) + +* Wed Feb 19 2020 systemd maintenance team - 239-26 +- seccomp: introduce seccomp_restrict_suid_sgid() for blocking chmod() for suid/sgid files (#1687512) +- test: add test case for restrict_suid_sgid() (#1687512) +- core: expose SUID/SGID restriction as new unit setting RestrictSUIDSGID= (#1687512) +- analyze: check for RestrictSUIDSGID= in "systemd-analyze security" (#1687512) +- man: document the new RestrictSUIDSGID= setting (#1687512) +- units: turn on RestrictSUIDSGID= in most of our long-running daemons (#1687512) +- core: imply NNP and SUID/SGID restriction for DynamicUser=yes service (#1687512) + +* Mon Feb 17 2020 systemd maintenance team - 239-25 +- sd-bus: use "queue" message references for managing r/w message queues in connection objects (CVE-2020-1712) +- pid1: make sure to restore correct default values for some rlimits (#1789930) +- main: introduce a define HIGH_RLIMIT_MEMLOCK similar to HIGH_RLIMIT_NOFILE (#1789930) + +* Thu Feb 13 2020 systemd maintenance team - 239-24 +- rules: reintroduce 60-alias-kmsg.rules (#1739353) +- sd-bus: make rqueue/wqueue sizes of type size_t (CVE-2020-1712) +- sd-bus: reorder bus ref and bus message ref handling (CVE-2020-1712) +- sd-bus: make sure dispatch_rqueue() initializes return parameter on all types of success (CVE-2020-1712) +- sd-bus: drop two inappropriate empty lines (CVE-2020-1712) +- sd-bus: initialize mutex after we allocated the wqueue (CVE-2020-1712) +- sd-bus: always go through sd_bus_unref() to free messages (CVE-2020-1712) +- bus-message: introduce two kinds of references to bus messages (CVE-2020-1712) +- sd-bus: introduce API for re-enqueuing incoming messages (CVE-2020-1712) +- sd-event: add sd_event_source_disable_unref() helper (CVE-2020-1712) +- polkit: when authorizing via PK let's re-resolve callback/userdata instead of caching it (CVE-2020-1712) +- sysctl: let's by default increase the numeric PID range from 2^16 to 2^22 (#1744214) +- journal: do not trigger assertion when journal_file_close() get NULL (#1788085) +- journal: use cleanup attribute at one more place (#1788085) + +* Mon Jan 13 2020 systemd maintenance team - 239-23 +- catalog: fix name of variable (#1677768) +- cryptsetup: add keyfile-timeout to allow a keydev timeout and allow to fallback to a password if it fails. (#1763155) +- cryptsetup: add documentation for keyfile-timeout (#1763155) +- cryptsetup: use unabbrieviated variable names (#1763155) +- cryptsetup: don't assert on variable which is optional (#1763155) +- cryptsetup-generator: guess whether the keyfile argument is two items or one (#1763155) +- crypt-util: Translate libcryptsetup log level instead of using log_debug() (#1776408) +- cryptsetup: add some commenting about EAGAIN generation (#1776408) +- cryptsetup: downgrade a log message we ignore (#1776408) +- cryptsetup: rework how we log about activation failures (#1776408) + +* Tue Dec 17 2019 systemd maintenance team - 239-22 +- spec: don't ship /var/log/README +- spec: provide systemd-rpm-macros + * Mon Dec 09 2019 systemd maintenance team - 239-21 - test-cpu-set-util: fix comparison for allocation size (#1734787) - test-cpu-set-util: fix allocation size check on i386 (#1734787)