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?= <zbyszek@in.waw.pl>
+Date: Mon, 15 Oct 2018 22:41:49 +0200
+Subject: [PATCH] catalog: fix name of variable
+
+All the messages would (literally) say "The start-up result is RESULT."
+because @RESULT@ was not defined.
+
+Fixes https://bugzilla.redhat.com/show_bug.cgi?id=1639482
+and the first part of #8005.
+
+Fixup for 646cc98dc81c4d0edbc1b57e7bca0f474b47e270.
+
+(cherry picked from commit 65d51875c2a7b27b61de090f1bd6311b0cef2016)
+
+Resolves: #1677768
+---
+ catalog/systemd.be.catalog.in       | 6 +++---
+ catalog/systemd.be@latin.catalog.in | 6 +++---
+ catalog/systemd.bg.catalog.in       | 6 +++---
+ catalog/systemd.catalog.in          | 6 +++---
+ catalog/systemd.da.catalog.in       | 6 +++---
+ catalog/systemd.fr.catalog.in       | 6 +++---
+ catalog/systemd.hr.catalog.in       | 6 +++---
+ catalog/systemd.hu.catalog.in       | 6 +++---
+ catalog/systemd.it.catalog.in       | 6 +++---
+ catalog/systemd.ko.catalog.in       | 6 +++---
+ catalog/systemd.pl.catalog.in       | 6 +++---
+ catalog/systemd.pt_BR.catalog.in    | 6 +++---
+ catalog/systemd.ru.catalog.in       | 6 +++---
+ catalog/systemd.sr.catalog.in       | 6 +++---
+ catalog/systemd.zh_CN.catalog.in    | 6 +++---
+ catalog/systemd.zh_TW.catalog.in    | 6 +++---
+ 16 files changed, 48 insertions(+), 48 deletions(-)
+
+diff --git a/catalog/systemd.be.catalog.in b/catalog/systemd.be.catalog.in
+index 5011ea268d..2c59898683 100644
+--- a/catalog/systemd.be.catalog.in
++++ b/catalog/systemd.be.catalog.in
+@@ -175,7 +175,7 @@ Support: %SUPPORT_URL%
+ 
+ Працэс запуску юніта @UNIT@ завершаны.
+ 
+-Вынік: @RESULT@.
++Вынік: @JOB_RESULT@.
+ 
+ -- de5b426a63be47a7b6ac3eaac82e2f6f
+ Subject: Юніт @UNIT@ спыняецца
+@@ -198,7 +198,7 @@ Support: %SUPPORT_URL%
+ 
+ Збой юніта @UNIT@.
+ 
+-Вынік: @RESULT@.
++Вынік: @JOB_RESULT@.
+ 
+ -- d34d037fff1847e6ae669a370e694725
+ Subject: Юніт @UNIT@ перачытвае сваю канфігурацыю
+@@ -214,7 +214,7 @@ Support: %SUPPORT_URL%
+ 
+ Юніт @UNIT@ перачытаў сваю канфігурацыю.
+ 
+-Вынік: @RESULT@.
++Вынік: @JOB_RESULT@.
+ 
+ -- 641257651c1b4ec9a8624d7a40a9e1e7
+ Subject: Працэс @EXECUTABLE@ не можа быць выкананы
+diff --git a/catalog/systemd.be@latin.catalog.in b/catalog/systemd.be@latin.catalog.in
+index 6a8b092669..1d024fea12 100644
+--- a/catalog/systemd.be@latin.catalog.in
++++ b/catalog/systemd.be@latin.catalog.in
+@@ -178,7 +178,7 @@ Support: %SUPPORT_URL%
+ 
+ Praces zapusku junita @UNIT@ zavieršany.
+ 
+-Vynik: @RESULT@.
++Vynik: @JOB_RESULT@.
+ 
+ -- de5b426a63be47a7b6ac3eaac82e2f6f
+ Subject: Junit @UNIT@ spyniajecca
+@@ -201,7 +201,7 @@ Support: %SUPPORT_URL%
+ 
+ Zboj junita @UNIT@.
+ 
+-Vynik: @RESULT@.
++Vynik: @JOB_RESULT@.
+ 
+ -- d34d037fff1847e6ae669a370e694725
+ Subject: Junit @UNIT@ pieračytvaje svaju kanfihuracyju
+@@ -217,7 +217,7 @@ Support: %SUPPORT_URL%
+ 
+ Junit @UNIT@ pieračytaŭ svaju kanfihuracyju.
+ 
+-Vynik: @RESULT@.
++Vynik: @JOB_RESULT@.
+ 
+ -- 641257651c1b4ec9a8624d7a40a9e1e7
+ Subject: Praces @EXECUTABLE@ nie moža być vykanany
+diff --git a/catalog/systemd.bg.catalog.in b/catalog/systemd.bg.catalog.in
+index 64d616f381..41f7b21bce 100644
+--- a/catalog/systemd.bg.catalog.in
++++ b/catalog/systemd.bg.catalog.in
+@@ -178,7 +178,7 @@ Support: %SUPPORT_URL%
+ 
+ Стартирането на модул „@UNIT@“ завърши.
+ 
+-Резултатът е: @RESULT@
++Резултатът е: @JOB_RESULT@
+ 
+ -- de5b426a63be47a7b6ac3eaac82e2f6f
+ Subject: Модул „@UNIT@“ се спира
+@@ -201,7 +201,7 @@ Support: %SUPPORT_URL%
+ 
+ Модулът „@UNIT@“ не успя да стартира.
+ 
+-Резултатът е: @RESULT@
++Резултатът е: @JOB_RESULT@
+ 
+ -- d34d037fff1847e6ae669a370e694725
+ Subject: Модулът „@UNIT@“ започна презареждане на настройките си
+@@ -217,7 +217,7 @@ Support: %SUPPORT_URL%
+ 
+ Модулът „@UNIT@“ завърши презареждането на настройките си.
+ 
+-Резултатът e: @RESULT@
++Резултатът e: @JOB_RESULT@
+ 
+ -- 641257651c1b4ec9a8624d7a40a9e1e7
+ Subject: Програмата „@EXECUTABLE@“ не успя да се стартира
+diff --git a/catalog/systemd.catalog.in b/catalog/systemd.catalog.in
+index 8234e387cf..49a45890f6 100644
+--- a/catalog/systemd.catalog.in
++++ b/catalog/systemd.catalog.in
+@@ -202,7 +202,7 @@ Support: %SUPPORT_URL%
+ 
+ Unit @UNIT@ has finished starting up.
+ 
+-The start-up result is @RESULT@.
++The start-up result is @JOB_RESULT@.
+ 
+ -- de5b426a63be47a7b6ac3eaac82e2f6f
+ Subject: Unit @UNIT@ has begun shutting down
+@@ -225,7 +225,7 @@ Support: %SUPPORT_URL%
+ 
+ Unit @UNIT@ has failed.
+ 
+-The result is @RESULT@.
++The result is @JOB_RESULT@.
+ 
+ -- d34d037fff1847e6ae669a370e694725
+ Subject: Unit @UNIT@ has begun reloading its configuration
+@@ -241,7 +241,7 @@ Support: %SUPPORT_URL%
+ 
+ Unit @UNIT@ has finished reloading its configuration
+ 
+-The result is @RESULT@.
++The result is @JOB_RESULT@.
+ 
+ -- 641257651c1b4ec9a8624d7a40a9e1e7
+ Subject: Process @EXECUTABLE@ could not be executed
+diff --git a/catalog/systemd.da.catalog.in b/catalog/systemd.da.catalog.in
+index 4e2bec8a0f..aecfafa05f 100644
+--- a/catalog/systemd.da.catalog.in
++++ b/catalog/systemd.da.catalog.in
+@@ -159,7 +159,7 @@ Support: %SUPPORT_URL%
+ 
+ Enhed @UNIT@ er færdig med at starte op.
+ 
+-Resultat for opstart er @RESULT@.
++Resultat for opstart er @JOB_RESULT@.
+ 
+ -- de5b426a63be47a7b6ac3eaac82e2f6f
+ Subject: Enhed @UNIT@ har påbegyndt nedlukning
+@@ -182,7 +182,7 @@ Support: %SUPPORT_URL%
+ 
+ Enhed @UNIT@ har fejlet.
+ 
+-Resultatet er @RESULT@
++Resultatet er @JOB_RESULT@
+ 
+ -- d34d037fff1847e6ae669a370e694725
+ Subject: Enhed @UNIT@ har påbegyndt genindlæsning af sin konfiguration
+@@ -198,7 +198,7 @@ Support: %SUPPORT_URL%
+ 
+ Enhed @UNIT@ er færdig med at genindlæse sin konfiguration
+ 
+-Resultatet er: @RESULT@.
++Resultatet er: @JOB_RESULT@.
+ 
+ -- 641257651c1b4ec9a8624d7a40a9e1e7
+ Subject: Process @EXECUTABLE@ kunne ikke eksekveres
+diff --git a/catalog/systemd.fr.catalog.in b/catalog/systemd.fr.catalog.in
+index 156b1a37dc..13edd083cb 100644
+--- a/catalog/systemd.fr.catalog.in
++++ b/catalog/systemd.fr.catalog.in
+@@ -191,7 +191,7 @@ Subject: L'unité (unit) @UNIT@ a terminé son démarrage
+ Defined-By: systemd
+ Support: %SUPPORT_URL%
+ 
+-L'unité (unit) @UNIT@ a terminé son démarrage, avec le résultat @RESULT@.
++L'unité (unit) @UNIT@ a terminé son démarrage, avec le résultat @JOB_RESULT@.
+ 
+ -- de5b426a63be47a7b6ac3eaac82e2f6f
+ Subject: L'unité (unit) @UNIT@ a commencé à s'arrêter
+@@ -212,7 +212,7 @@ Subject: L'unité (unit) @UNIT@ a échoué
+ Defined-By: systemd
+ Support: %SUPPORT_URL%
+ 
+-L'unité (unit) @UNIT@ a échoué, avec le résultat @RESULT@.
++L'unité (unit) @UNIT@ a échoué, avec le résultat @JOB_RESULT@.
+ 
+ -- d34d037fff1847e6ae669a370e694725
+ Subject: L'unité (unit) @UNIT@ a commencé à recharger sa configuration
+@@ -227,7 +227,7 @@ Defined-By: systemd
+ Support: %SUPPORT_URL%
+ 
+ L'unité (unit) @UNIT@ a terminé de recharger configuration,
+-avec le résultat @RESULT@.
++avec le résultat @JOB_RESULT@.
+ 
+ -- 641257651c1b4ec9a8624d7a40a9e1e7
+ Subject: Le processus @EXECUTABLE@ n'a pas pu être exécuté
+diff --git a/catalog/systemd.hr.catalog.in b/catalog/systemd.hr.catalog.in
+index c4808b4c7d..4526ae2a8c 100644
+--- a/catalog/systemd.hr.catalog.in
++++ b/catalog/systemd.hr.catalog.in
+@@ -173,7 +173,7 @@ Support: %SUPPORT_URL%
+ 
+ Jedinica @UNIT@ je završila pokretanje.
+ 
+-Rezultat pokretanja je @RESULT@.
++Rezultat pokretanja je @JOB_RESULT@.
+ 
+ -- de5b426a63be47a7b6ac3eaac82e2f6f
+ Subject: Jedinica @UNIT@ je započela isključivanje
+@@ -196,7 +196,7 @@ Support: %SUPPORT_URL%
+ 
+ Jedinica @UNIT@ nije uspjela.
+ 
+-Rezultat je @RESULT@.
++Rezultat je @JOB_RESULT@.
+ 
+ -- d34d037fff1847e6ae669a370e694725
+ Subject: Jedinica @UNIT@ je započela ponovno učitavati podešavanja
+@@ -212,7 +212,7 @@ Support: %SUPPORT_URL%
+ 
+ Jedinica @UNIT@ je završila ponovno učitavati podešavanja
+ 
+-Rezultat je @RESULT@.
++Rezultat je @JOB_RESULT@.
+ 
+ -- 641257651c1b4ec9a8624d7a40a9e1e7
+ Subject: Proces @EXECUTABLE@ se ne može pokrenuti
+diff --git a/catalog/systemd.hu.catalog.in b/catalog/systemd.hu.catalog.in
+index 6c6d7e7934..5565b80b2a 100644
+--- a/catalog/systemd.hu.catalog.in
++++ b/catalog/systemd.hu.catalog.in
+@@ -161,7 +161,7 @@ Support: %SUPPORT_URL%
+ 
+ A(z) @UNIT@ egység befejezte az indulást
+ 
+-Az indítás eredménye: @RESULT@.
++Az indítás eredménye: @JOB_RESULT@.
+ 
+ -- de5b426a63be47a7b6ac3eaac82e2f6f
+ Subject: A(z) @UNIT@ egység megkezdte a leállást
+@@ -184,7 +184,7 @@ Support: %SUPPORT_URL%
+ 
+ A(z) @UNIT@ egység hibát jelzett.
+ 
+-Az eredmény: @RESULT@.
++Az eredmény: @JOB_RESULT@.
+ 
+ -- d34d037fff1847e6ae669a370e694725
+ Subject: A(z) @UNIT@ egység megkezdte a beállításainak újratöltését
+@@ -200,7 +200,7 @@ Support: %SUPPORT_URL%
+ 
+ A(z) @UNIT@ egység befejezte a beállításainak újratöltését.
+ 
+-Az eredmény: @RESULT@.
++Az eredmény: @JOB_RESULT@.
+ 
+ -- 641257651c1b4ec9a8624d7a40a9e1e7
+ Subject: A folyamat végrehajtása sikertelen: @EXECUTABLE@
+diff --git a/catalog/systemd.it.catalog.in b/catalog/systemd.it.catalog.in
+index 4fd1f2a933..8ce4fa5d92 100644
+--- a/catalog/systemd.it.catalog.in
++++ b/catalog/systemd.it.catalog.in
+@@ -191,7 +191,7 @@ Support: %SUPPORT_URL%
+ 
+ L'unità @UNIT@ ha terminato la fase di avvio.
+ 
+-La fase di avvio è @RESULT@.
++La fase di avvio è @JOB_RESULT@.
+ 
+ -- de5b426a63be47a7b6ac3eaac82e2f6f
+ Subject: L'unità @UNIT@ inizia la fase di spegnimento
+@@ -214,7 +214,7 @@ Support: %SUPPORT_URL%
+ 
+ L'unità @UNIT@ è fallita.
+ 
+-Il risultato è @RESULT@.
++Il risultato è @JOB_RESULT@.
+ 
+ -- d34d037fff1847e6ae669a370e694725
+ Subject: L'unità @UNIT@ inizia a caricare la propria configurazione
+@@ -230,7 +230,7 @@ Support: %SUPPORT_URL%
+ 
+ L'unità @UNIT@ è terminata ricaricando la propria configurazione
+ 
+-Il risultato è @RESULT@.
++Il risultato è @JOB_RESULT@.
+ 
+ -- 641257651c1b4ec9a8624d7a40a9e1e7
+ Subject: Il processo @EXECUTABLE@ non può essere eseguito
+diff --git a/catalog/systemd.ko.catalog.in b/catalog/systemd.ko.catalog.in
+index fc0faad02c..59fbde8b62 100644
+--- a/catalog/systemd.ko.catalog.in
++++ b/catalog/systemd.ko.catalog.in
+@@ -182,7 +182,7 @@ Support: %SUPPORT_URL%
+ 
+ @UNIT@ 유닛 시동을 마쳤습니다.
+ 
+-시동 결과는 @RESULT@ 입니다.
++시동 결과는 @JOB_RESULT@ 입니다.
+ 
+ -- de5b426a63be47a7b6ac3eaac82e2f6f
+ Subject: @UNIT@ 유닛 끝내기 동작 시작
+@@ -205,7 +205,7 @@ Support: %SUPPORT_URL%
+ 
+ @UNIT@ 유닛 동작에 실패했습니다.
+ 
+-결과는 @RESULT@ 입니다.
++결과는 @JOB_RESULT@ 입니다.
+ 
+ -- d34d037fff1847e6ae669a370e694725
+ Subject: @UNIT@ 유닛 설정 다시 읽기 시작
+@@ -221,7 +221,7 @@ Support: %SUPPORT_URL%
+ 
+ @UNIT@ 유닛의 설정 다시 읽기 동작을 끝냈습니다.
+ 
+-결과는 @RESULT@ 입니다.
++결과는 @JOB_RESULT@ 입니다.
+ 
+ -- 641257651c1b4ec9a8624d7a40a9e1e7
+ Subject: @EXECUTABLE@ 프로세스 시작할 수 없음
+diff --git a/catalog/systemd.pl.catalog.in b/catalog/systemd.pl.catalog.in
+index 998894bd0a..b73f56ca11 100644
+--- a/catalog/systemd.pl.catalog.in
++++ b/catalog/systemd.pl.catalog.in
+@@ -201,7 +201,7 @@ Support: %SUPPORT_URL%
+ 
+ Jednostka @UNIT@ ukończyła uruchamianie.
+ 
+-Wynik uruchamiania: @RESULT@.
++Wynik uruchamiania: @JOB_RESULT@.
+ 
+ -- de5b426a63be47a7b6ac3eaac82e2f6f
+ Subject: Rozpoczęto wyłączanie jednostki @UNIT@
+@@ -224,7 +224,7 @@ Support: %SUPPORT_URL%
+ 
+ Jednostka @UNIT@ się nie powiodła.
+ 
+-Wynik: @RESULT@.
++Wynik: @JOB_RESULT@.
+ 
+ -- d34d037fff1847e6ae669a370e694725
+ Subject: Rozpoczęto ponowne wczytywanie konfiguracji jednostki @UNIT@
+@@ -240,7 +240,7 @@ Support: %SUPPORT_URL%
+ 
+ Jednostka @UNIT@ ukończyła ponowne wczytywanie swojej konfiguracji.
+ 
+-Wynik: @RESULT@.
++Wynik: @JOB_RESULT@.
+ 
+ -- 641257651c1b4ec9a8624d7a40a9e1e7
+ Subject: Nie można wykonać procesu @EXECUTABLE@
+diff --git a/catalog/systemd.pt_BR.catalog.in b/catalog/systemd.pt_BR.catalog.in
+index db1cb03198..edaefb7164 100644
+--- a/catalog/systemd.pt_BR.catalog.in
++++ b/catalog/systemd.pt_BR.catalog.in
+@@ -162,7 +162,7 @@ Support: %SUPPORT_URL%
+ 
+ A unidade @UNIT@ concluiu a inicialização.
+ 
+-The start-up result is @RESULT@.
++The start-up result is @JOB_RESULT@.
+ 
+ -- de5b426a63be47a7b6ac3eaac82e2f6f
+ Subject: Unidade @UNIT@ sendo desligado
+@@ -185,7 +185,7 @@ Support: %SUPPORT_URL%
+ 
+ A unidade @UNIT@ falhou.
+ 
+-O resultado é @RESULT@.
++O resultado é @JOB_RESULT@.
+ 
+ -- d34d037fff1847e6ae669a370e694725
+ Subject: Unidade @UNIT@ iniciou recarregamento de sua configuração
+@@ -201,7 +201,7 @@ Support: %SUPPORT_URL%
+ 
+ A unidade @UNIT@ concluiu o recarregamento de sua configuração.
+ 
+-O resultado é @RESULT@.
++O resultado é @JOB_RESULT@.
+ 
+ -- 641257651c1b4ec9a8624d7a40a9e1e7
+ Subject: Processo @EXECUTABLE@ não pôde ser executado
+diff --git a/catalog/systemd.ru.catalog.in b/catalog/systemd.ru.catalog.in
+index 645edaa922..ccdc685037 100644
+--- a/catalog/systemd.ru.catalog.in
++++ b/catalog/systemd.ru.catalog.in
+@@ -227,7 +227,7 @@ Support: %SUPPORT_URL%
+ 
+ Процесс запуска юнита @UNIT@ был завершен.
+ 
+-Результат: @RESULT@.
++Результат: @JOB_RESULT@.
+ 
+ # Subject: Unit @UNIT@ has begun shutting down
+ -- de5b426a63be47a7b6ac3eaac82e2f6f
+@@ -253,7 +253,7 @@ Support: %SUPPORT_URL%
+ 
+ Произошел сбой юнита @UNIT@.
+ 
+-Результат: @RESULT@.
++Результат: @JOB_RESULT@.
+ 
+ # Subject: Unit @UNIT@ has begun with reloading its configuration
+ -- d34d037fff1847e6ae669a370e694725
+@@ -271,7 +271,7 @@ Support: %SUPPORT_URL%
+ 
+ Юнит @UNIT@ завершил процесс перечитывания своей конфигурации.
+ 
+-Результат: @RESULT@.
++Результат: @JOB_RESULT@.
+ 
+ # Subject: Process @EXECUTABLE@ could not be executed
+ -- 641257651c1b4ec9a8624d7a40a9e1e7
+diff --git a/catalog/systemd.sr.catalog.in b/catalog/systemd.sr.catalog.in
+index f5746715a4..7cb6546d43 100644
+--- a/catalog/systemd.sr.catalog.in
++++ b/catalog/systemd.sr.catalog.in
+@@ -158,7 +158,7 @@ Support: %SUPPORT_URL%
+ 
+ Јединица @UNIT@ је завршила са покретањем.
+ 
+-Исход покретања је @RESULT@.
++Исход покретања је @JOB_RESULT@.
+ 
+ -- de5b426a63be47a7b6ac3eaac82e2f6f
+ Subject: Јединица @UNIT@ је почела са гашењем
+@@ -181,7 +181,7 @@ Support: %SUPPORT_URL%
+ 
+ Јединица @UNIT@ је пукла.
+ 
+-Исход је @RESULT@.
++Исход је @JOB_RESULT@.
+ 
+ -- d34d037fff1847e6ae669a370e694725
+ Subject: Јединица @UNIT@ је почела са поновним учитавањем свог подешавања
+@@ -197,7 +197,7 @@ Support: %SUPPORT_URL%
+ 
+ Јединица @UNIT@ је завршила са поновним учитавањем свог подешавања
+ 
+-Исход је @RESULT@.
++Исход је @JOB_RESULT@.
+ 
+ -- 641257651c1b4ec9a8624d7a40a9e1e7
+ Subject: Процес @EXECUTABLE@ није могао бити извршен
+diff --git a/catalog/systemd.zh_CN.catalog.in b/catalog/systemd.zh_CN.catalog.in
+index fa58448acf..d6ac2592b8 100644
+--- a/catalog/systemd.zh_CN.catalog.in
++++ b/catalog/systemd.zh_CN.catalog.in
+@@ -156,7 +156,7 @@ Support: %SUPPORT_URL%
+ 
+ @UNIT@ 单元已结束启动。
+ 
+-启动结果为“@RESULT@”。
++启动结果为“@JOB_RESULT@”。
+ 
+ -- de5b426a63be47a7b6ac3eaac82e2f6f
+ Subject: @UNIT@ 单元已开始停止操作
+@@ -179,7 +179,7 @@ Support: %SUPPORT_URL%
+ 
+ @UNIT@ 单元已失败。
+ 
+-结果为“@RESULT@”。
++结果为“@JOB_RESULT@”。
+ 
+ -- d34d037fff1847e6ae669a370e694725
+ Subject: @UNIT@ 单元已开始重新载入其配置
+@@ -195,7 +195,7 @@ Support: %SUPPORT_URL%
+ 
+ @UNIT@ 单元已结束配置重载入操作。
+ 
+-结果为“@RESULT@”。
++结果为“@JOB_RESULT@”。
+ 
+ -- 641257651c1b4ec9a8624d7a40a9e1e7
+ Subject: 进程 @EXECUTABLE@ 无法执行
+diff --git a/catalog/systemd.zh_TW.catalog.in b/catalog/systemd.zh_TW.catalog.in
+index 17bd2bc9af..a468c2f6bf 100644
+--- a/catalog/systemd.zh_TW.catalog.in
++++ b/catalog/systemd.zh_TW.catalog.in
+@@ -160,7 +160,7 @@ Support: %SUPPORT_URL%
+ 
+ 單位 @UNIT@ 啟動已結束。
+ 
+-啟動結果為 @RESULT@。
++啟動結果為 @JOB_RESULT@。
+ 
+ -- de5b426a63be47a7b6ac3eaac82e2f6f
+ Subject: 單位 @UNIT@ 已開始關閉
+@@ -183,7 +183,7 @@ Support: %SUPPORT_URL%
+ 
+ 單位 @UNIT@ 已失敗。
+ 
+-結果為 @RESULT@。
++結果為 @JOB_RESULT@。
+ 
+ -- d34d037fff1847e6ae669a370e694725
+ Subject: 單位 @UNIT@ 已開始重新載入其設定
+@@ -199,7 +199,7 @@ Support: %SUPPORT_URL%
+ 
+ 單位 @UNIT@ 已結束重新載入其設定
+ 
+-結果為 @RESULT@。
++結果為 @JOB_RESULT@。
+ 
+ -- 641257651c1b4ec9a8624d7a40a9e1e7
+ Subject: 行程 @EXECUTABLE@ 無法執行
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.</para></listitem>
+       </varlistentry>
+ 
++      <varlistentry>
++        <term><option>keyfile-timeout=</option></term>
++
++        <listitem><para> Specifies the timeout for the device on
++        which the key file resides and falls back to a password if
++        it could not be mounted. See
++        <citerefentry><refentrytitle>systemd-cryptsetup-generator</refentrytitle><manvolnum>8</manvolnum></citerefentry>
++        for key files on external devices.
++        </para></listitem>
++      </varlistentry>
++
+       <varlistentry>
+         <term><option>luks</option></term>
+ 
+@@ -417,7 +428,8 @@
+       <programlisting>luks       UUID=2505567a-9e27-4efe-a4d5-15ad146c258b
+ swap       /dev/sda7       /dev/urandom       swap
+ truecrypt  /dev/sda2       /etc/container_password  tcrypt
+-hidden     /mnt/tc_hidden  /dev/null    tcrypt-hidden,tcrypt-keyfile=/etc/keyfile</programlisting>
++hidden     /mnt/tc_hidden  /dev/null    tcrypt-hidden,tcrypt-keyfile=/etc/keyfile
++external   /dev/sda3       keyfile:LABEL=keydev keyfile-timeout=10s</programlisting>
+     </example>
+   </refsect1>
+ 
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?= <zbyszek@in.waw.pl>
+Date: Thu, 1 Aug 2019 08:13:13 +0200
+Subject: [PATCH] cryptsetup: use unabbrieviated variable names
+
+Now that "ret_" has been added to the output variables, we can name
+the internal variables without artificial abbrevs.
+
+(cherry picked from commit 5d2100dc4c32abbce4109e75cbfbbef6e1b2b7b1)
+
+Related: #1763155
+---
+ src/cryptsetup/cryptsetup-generator.c | 26 +++++++++++++-------------
+ 1 file changed, 13 insertions(+), 13 deletions(-)
+
+diff --git a/src/cryptsetup/cryptsetup-generator.c b/src/cryptsetup/cryptsetup-generator.c
+index 1e8e3ba00d..7b234e37be 100644
+--- a/src/cryptsetup/cryptsetup-generator.c
++++ b/src/cryptsetup/cryptsetup-generator.c
+@@ -40,30 +40,30 @@ static Hashmap *arg_disks = NULL;
+ static char *arg_default_options = NULL;
+ static char *arg_default_keyfile = NULL;
+ 
+-static int split_keyspec(const char *keyspec, char **keyfile, char **keydev) {
+-        _cleanup_free_ char *kfile = NULL, *kdev = NULL;
+-        char *c;
++static int split_keyspec(const char *keyspec, char **ret_keyfile, char **ret_keydev) {
++        _cleanup_free_ char *keyfile = NULL, *keydev = NULL;
++        const char *c;
+ 
+         assert(keyspec);
+-        assert(keyfile);
+-        assert(keydev);
++        assert(ret_keyfile);
++        assert(ret_keydev);
+ 
+         c = strrchr(keyspec, ':');
+         if (c) {
+-                kfile = strndup(keyspec, c-keyspec);
+-                kdev = strdup(c + 1);
+-                if (!*kfile || !*kdev)
++                keyfile = strndup(keyspec, c-keyspec);
++                keydev = strdup(c + 1);
++                if (!keyfile || !keydev)
+                         return log_oom();
+         } else {
+                 /* No keydev specified */
+-                kfile = strdup(keyspec);
+-                kdev = NULL;
+-                if (!*kfile)
++                keyfile = strdup(keyspec);
++                keydev = NULL;
++                if (!keyfile)
+                         return log_oom();
+         }
+ 
+-        *keyfile = TAKE_PTR(kfile);
+-        *keydev = TAKE_PTR(kdev);
++        *ret_keyfile = TAKE_PTR(keyfile);
++        *ret_keydev = TAKE_PTR(keydev);
+ 
+         return 0;
+ }
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?= <zbyszek@in.waw.pl>
+Date: Thu, 1 Aug 2019 08:15:43 +0200
+Subject: [PATCH] cryptsetup: don't assert on variable which is optional
+
+https://github.com/systemd/systemd/commit/50d2eba27b9bfc77ef6b40e5721713846815418b#commitcomment-34519739
+
+In add_crypttab_devices() split_keyspec is called on the keyfile argument,
+which may be NULL.
+
+(cherry picked from commit fef716b28be6e866b8afe995805d5ebe2af6bbfa)
+
+Related: #1763155
+---
+ src/cryptsetup/cryptsetup-generator.c | 6 +++++-
+ 1 file changed, 5 insertions(+), 1 deletion(-)
+
+diff --git a/src/cryptsetup/cryptsetup-generator.c b/src/cryptsetup/cryptsetup-generator.c
+index 7b234e37be..a09983b576 100644
+--- a/src/cryptsetup/cryptsetup-generator.c
++++ b/src/cryptsetup/cryptsetup-generator.c
+@@ -44,10 +44,14 @@ static int split_keyspec(const char *keyspec, char **ret_keyfile, char **ret_key
+         _cleanup_free_ char *keyfile = NULL, *keydev = NULL;
+         const char *c;
+ 
+-        assert(keyspec);
+         assert(ret_keyfile);
+         assert(ret_keydev);
+ 
++        if (!keyspec) {
++                *ret_keyfile = *ret_keydev = NULL;
++                return 0;
++        }
++
+         c = strrchr(keyspec, ':');
+         if (c) {
+                 keyfile = strndup(keyspec, c-keyspec);
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?= <zbyszek@in.waw.pl>
+Date: Wed, 13 Nov 2019 10:32:30 +0100
+Subject: [PATCH] cryptsetup-generator: guess whether the keyfile argument is
+ two items or one
+
+Fixes #13615.
+
+See the inline comment for documentation.
+
+(cherry picked from commit 32c6237a7c2e697d2fc4f3403319db16858fb8e3)
+
+Related: #1763155
+---
+ src/cryptsetup/cryptsetup-generator.c | 45 ++++++++++++++++++---------
+ 1 file changed, 30 insertions(+), 15 deletions(-)
+
+diff --git a/src/cryptsetup/cryptsetup-generator.c b/src/cryptsetup/cryptsetup-generator.c
+index a09983b576..4117930925 100644
+--- a/src/cryptsetup/cryptsetup-generator.c
++++ b/src/cryptsetup/cryptsetup-generator.c
+@@ -54,17 +54,36 @@ static int split_keyspec(const char *keyspec, char **ret_keyfile, char **ret_key
+ 
+         c = strrchr(keyspec, ':');
+         if (c) {
+-                keyfile = strndup(keyspec, c-keyspec);
+-                keydev = strdup(c + 1);
+-                if (!keyfile || !keydev)
++                /* The keydev part has to be either an absolute path to device node (/dev/something,
++                 * /dev/foo/something, or even possibly /dev/foo/something:part), or a fstab device
++                 * specification starting with LABEL= or similar. The keyfile part has the same syntax.
++                 *
++                 * Let's try to guess if the second part looks like a keydev specification, or just part of a
++                 * filename with a colon. fstab_node_to_udev_node() will convert the fstab device syntax to
++                 * an absolute path. If we didn't get an absolute path, assume that it is just part of the
++                 * first keyfile argument. */
++
++                keydev = fstab_node_to_udev_node(c + 1);
++                if (!keydev)
+                         return log_oom();
+-        } else {
++
++                if (path_is_absolute(keydev))
++                        keyfile = strndup(keyspec, c-keyspec);
++                else {
++                        log_debug("Keyspec argument contains a colon, but \"%s\" doesn't look like a device specification.\n"
++                                  "Assuming that \"%s\" is a single device specification.",
++                                  c + 1, keyspec);
++                        keydev = mfree(keydev);
++                        c = NULL;
++                }
++        }
++
++        if (!c)
+                 /* No keydev specified */
+                 keyfile = strdup(keyspec);
+-                keydev = NULL;
+-                if (!keyfile)
+-                        return log_oom();
+-        }
++
++        if (!keyfile)
++                return log_oom();
+ 
+         *ret_keyfile = TAKE_PTR(keyfile);
+         *ret_keydev = TAKE_PTR(keydev);
+@@ -73,7 +92,7 @@ static int split_keyspec(const char *keyspec, char **ret_keyfile, char **ret_key
+ }
+ 
+ static int generate_keydev_mount(const char *name, const char *keydev, const char *keydev_timeout, bool canfail, char **unit, char **mount) {
+-        _cleanup_free_ char *u = NULL, *what = NULL, *where = NULL, *name_escaped = NULL, *device_unit = NULL;
++        _cleanup_free_ char *u = NULL, *where = NULL, *name_escaped = NULL, *device_unit = NULL;
+         _cleanup_fclose_ FILE *f = NULL;
+         int r;
+         usec_t timeout_us;
+@@ -111,22 +130,18 @@ static int generate_keydev_mount(const char *name, const char *keydev, const cha
+         if (r < 0)
+                 return r;
+ 
+-        what = fstab_node_to_udev_node(keydev);
+-        if (!what)
+-                return -ENOMEM;
+-
+         fprintf(f,
+                 "[Unit]\n"
+                 "DefaultDependencies=no\n\n"
+                 "[Mount]\n"
+                 "What=%s\n"
+                 "Where=%s\n"
+-                "Options=ro%s\n", what, where, canfail ? ",nofail" : "");
++                "Options=ro%s\n", keydev, where, canfail ? ",nofail" : "");
+ 
+         if (keydev_timeout) {
+                 r = parse_sec_fix_0(keydev_timeout, &timeout_us);
+                 if (r >= 0) {
+-                        r = unit_name_from_path(what, ".device", &device_unit);
++                        r = unit_name_from_path(keydev, ".device", &device_unit);
+                         if (r < 0)
+                                 return log_error_errno(r, "Failed to generate unit name: %m");
+ 
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 <medhefgo@web.de>
+Date: Mon, 25 Jun 2018 20:33:31 +0200
+Subject: [PATCH] crypt-util: Translate libcryptsetup log level instead of
+ using log_debug()
+
+This makes sure that errors reported by libcryptsetup are shown to the
+user instead of getting swallowed up by log_debug().
+
+(cherry picked from commit aa2cc005d77890b07e8c579f25e1333ff8ba8dac)
+
+Resolves: #1776408
+---
+ src/basic/crypt-util.c | 20 +++++++++++++++++++-
+ 1 file changed, 19 insertions(+), 1 deletion(-)
+
+diff --git a/src/basic/crypt-util.c b/src/basic/crypt-util.c
+index b181ba3ba0..20bdc5489e 100644
+--- a/src/basic/crypt-util.c
++++ b/src/basic/crypt-util.c
+@@ -5,6 +5,24 @@
+ #include "log.h"
+ 
+ void cryptsetup_log_glue(int level, const char *msg, void *usrptr) {
+-        log_debug("%s", msg);
++        switch (level) {
++        case CRYPT_LOG_NORMAL:
++                level = LOG_NOTICE;
++                break;
++        case CRYPT_LOG_ERROR:
++                level = LOG_ERR;
++                break;
++        case CRYPT_LOG_VERBOSE:
++                level = LOG_INFO;
++                break;
++        case CRYPT_LOG_DEBUG:
++                level = LOG_DEBUG;
++                break;
++        default:
++                log_error("Unknown libcryptsetup log level: %d", level);
++                level = LOG_ERR;
++        }
++
++        log_full(level, "%s", msg);
+ }
+ #endif
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 <lennart@poettering.net>
+Date: Mon, 21 Jan 2019 20:13:11 +0100
+Subject: [PATCH] cryptsetup: add some commenting about EAGAIN generation
+
+(cherry picked from commit b7a0fead10959b03a1fa642a5ae7aca3a6a3dee9)
+
+Related: #1776408
+---
+ src/cryptsetup/cryptsetup.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/src/cryptsetup/cryptsetup.c b/src/cryptsetup/cryptsetup.c
+index 0881aea915..f2b2557497 100644
+--- a/src/cryptsetup/cryptsetup.c
++++ b/src/cryptsetup/cryptsetup.c
+@@ -455,7 +455,7 @@ static int attach_tcrypt(
+                 r = read_one_line_file(key_file, &passphrase);
+                 if (r < 0) {
+                         log_error_errno(r, "Failed to read password file '%s': %m", key_file);
+-                        return -EAGAIN;
++                        return -EAGAIN; /* log with the actual error, but return EAGAIN */
+                 }
+ 
+                 params.passphrase = passphrase;
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 <lennart@poettering.net>
+Date: Mon, 21 Jan 2019 20:19:57 +0100
+Subject: [PATCH] cryptsetup: downgrade a log message we ignore
+
+(cherry picked from commit 44ce4255147ab308c1f13580147c693204c322e8)
+
+Related: #1776408
+---
+ src/cryptsetup/cryptsetup.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/src/cryptsetup/cryptsetup.c b/src/cryptsetup/cryptsetup.c
+index f2b2557497..53fe04a73f 100644
+--- a/src/cryptsetup/cryptsetup.c
++++ b/src/cryptsetup/cryptsetup.c
+@@ -621,7 +621,7 @@ int main(int argc, char *argv[]) {
+                     !streq(argv[4], "none")) {
+ 
+                         if (!path_is_absolute(argv[4]))
+-                                log_error("Password file path '%s' is not absolute. Ignoring.", argv[4]);
++                                log_warning("Password file path '%s' is not absolute. Ignoring.", argv[4]);
+                         else
+                                 key_file = argv[4];
+                 }
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 <lennart@poettering.net>
+Date: Mon, 21 Jan 2019 20:20:35 +0100
+Subject: [PATCH] cryptsetup: rework how we log about activation failures
+
+First of all let's always log where the errors happen, and not in an
+upper stackframe, in all cases. Previously we'd do this somethis one way
+and sometimes another, which resulted in sometimes duplicate logging and
+sometimes none.
+
+When we cannot activate something due to bad password the kernel gives
+us EPERM. Let's uniformly return this EAGAIN, so tha the next password
+is tried. (previously this was done in most cases but not in all)
+
+When we get EPERM let's also explicitly indicate that this probably
+means the password is simply wrong.
+
+Fixes: #11498
+(cherry picked from commit 6f177c7dc092eb68762b4533d41b14244adb2a73)
+
+Related: #1776408
+---
+ src/cryptsetup/cryptsetup.c | 36 ++++++++++++++++++++++--------------
+ 1 file changed, 22 insertions(+), 14 deletions(-)
+
+diff --git a/src/cryptsetup/cryptsetup.c b/src/cryptsetup/cryptsetup.c
+index 53fe04a73f..33c215eaa1 100644
+--- a/src/cryptsetup/cryptsetup.c
++++ b/src/cryptsetup/cryptsetup.c
+@@ -469,10 +469,15 @@ static int attach_tcrypt(
+                         log_error("Failed to activate using password file '%s'.", key_file);
+                         return -EAGAIN;
+                 }
+-                return r;
++
++                return log_error_errno(r, "Failed to load tcrypt superblock on device %s: %m", crypt_get_device_name(cd));
+         }
+ 
+-        return crypt_activate_by_volume_key(cd, name, NULL, 0, flags);
++        r = crypt_activate_by_volume_key(cd, name, NULL, 0, flags);
++        if (r < 0)
++                return log_error_errno(r, "Failed to activate tcrypt device %s: %m", crypt_get_device_name(cd));
++
++        return 0;
+ }
+ 
+ static int attach_luks_or_plain(struct crypt_device *cd,
+@@ -549,22 +554,30 @@ static int attach_luks_or_plain(struct crypt_device *cd,
+ 
+         if (key_file) {
+                 r = crypt_activate_by_keyfile_offset(cd, name, arg_key_slot, key_file, arg_keyfile_size, arg_keyfile_offset, flags);
+-                if (r < 0) {
+-                        log_error_errno(r, "Failed to activate with key file '%s': %m", key_file);
+-                        return -EAGAIN;
++                if (r == -EPERM) {
++                        log_error_errno(r, "Failed to activate with key file '%s'. (Key data incorrect?)", key_file);
++                        return -EAGAIN; /* Log actual error, but return EAGAIN */
+                 }
++                if (r < 0)
++                        return log_error_errno(r, "Failed to activate with key file '%s': %m", key_file);
+         } else {
+                 char **p;
+ 
++                r = -EINVAL;
+                 STRV_FOREACH(p, passwords) {
+                         if (pass_volume_key)
+                                 r = crypt_activate_by_volume_key(cd, name, *p, arg_key_size, flags);
+                         else
+                                 r = crypt_activate_by_passphrase(cd, name, arg_key_slot, *p, strlen(*p), flags);
+-
+                         if (r >= 0)
+                                 break;
+                 }
++                if (r == -EPERM) {
++                        log_error_errno(r, "Failed to activate with specified passphrase. (Passphrase incorrect?)");
++                        return -EAGAIN; /* log actual error, but return EAGAIN */
++                }
++                if (r < 0)
++                        return log_error_errno(r, "Failed to activate with specified passphrase: %m");
+         }
+ 
+         return r;
+@@ -726,16 +739,11 @@ int main(int argc, char *argv[]) {
+                                                          flags);
+                         if (r >= 0)
+                                 break;
+-                        if (r == -EAGAIN) {
+-                                key_file = NULL;
+-                                continue;
+-                        }
+-                        if (r != -EPERM) {
+-                                log_error_errno(r, "Failed to activate: %m");
++                        if (r != -EAGAIN)
+                                 goto finish;
+-                        }
+ 
+-                        log_warning("Invalid passphrase.");
++                        /* Passphrase not correct? Let's try again! */
++                        key_file = NULL;
+                 }
+ 
+                 if (arg_tries != 0 && tries >= arg_tries) {
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 <jsynacek@redhat.com>
+Date: Wed, 18 Dec 2019 09:41:29 +0100
+Subject: [PATCH] rules: reintroduce 60-alias-kmsg.rules
+
+Resolves:#1739353
+rhel-only
+---
+ rules/60-alias-kmsg.rules | 10 ++++++++++
+ rules/meson.build         |  1 +
+ 2 files changed, 11 insertions(+)
+ create mode 100644 rules/60-alias-kmsg.rules
+
+diff --git a/rules/60-alias-kmsg.rules b/rules/60-alias-kmsg.rules
+new file mode 100644
+index 0000000000..9c7236a730
+--- /dev/null
++++ b/rules/60-alias-kmsg.rules
+@@ -0,0 +1,10 @@
++SUBSYSTEM!="block", GOTO="log_end"
++KERNEL=="loop*|ram*", GOTO="log_end"
++ACTION=="remove", GOTO="log_end"
++ENV{DM_UDEV_DISABLE_OTHER_RULES_FLAG}=="1", GOTO="log_end"
++ENV{DM_UDEV_DISABLE_DISK_RULES_FLAG}=="1", GOTO="log_end"
++
++IMPORT{cmdline}="udev.alias"
++ENV{udev.alias}=="1", RUN+="/bin/sh -c 'echo udev-alias: $name \($links\) > /dev/kmsg'"
++
++LABEL="log_end"
+diff --git a/rules/meson.build b/rules/meson.build
+index 6363f8bf2e..7b5b2472de 100644
+--- a/rules/meson.build
++++ b/rules/meson.build
+@@ -3,6 +3,7 @@
+ rules = files('''
+         40-redhat.rules
+         40-elevator.rules
++        60-alias-kmsg.rules
+         60-block.rules
+         60-cdrom_id.rules
+         60-drm.rules
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 <lennart@poettering.net>
+Date: Thu, 17 Jan 2019 18:13:03 +0100
+Subject: [PATCH] sd-bus: make rqueue/wqueue sizes of type size_t
+
+Let's do this like we usually do and size arrays with size_t.
+
+We already do this for the "allocated" counter correctly, and externally
+we expose the queue sizes as uint64_t anyway, hence there's really no
+point in usigned "unsigned" internally.
+
+(cherry picked from commit 143d4e045a798ccc87889b2a8a60d7fbe44be441)
+Related: CVE-2020-1712
+---
+ src/libsystemd/sd-bus/bus-internal.h | 4 ++--
+ src/libsystemd/sd-bus/sd-bus.c       | 2 +-
+ 2 files changed, 3 insertions(+), 3 deletions(-)
+
+diff --git a/src/libsystemd/sd-bus/bus-internal.h b/src/libsystemd/sd-bus/bus-internal.h
+index 5d773b14c4..06bd7862cb 100644
+--- a/src/libsystemd/sd-bus/bus-internal.h
++++ b/src/libsystemd/sd-bus/bus-internal.h
+@@ -221,11 +221,11 @@ struct sd_bus {
+         size_t rbuffer_size;
+ 
+         sd_bus_message **rqueue;
+-        unsigned rqueue_size;
++        size_t rqueue_size;
+         size_t rqueue_allocated;
+ 
+         sd_bus_message **wqueue;
+-        unsigned wqueue_size;
++        size_t wqueue_size;
+         size_t windex;
+         size_t wqueue_allocated;
+ 
+diff --git a/src/libsystemd/sd-bus/sd-bus.c b/src/libsystemd/sd-bus/sd-bus.c
+index 1c9e967ae0..64026f7ee1 100644
+--- a/src/libsystemd/sd-bus/sd-bus.c
++++ b/src/libsystemd/sd-bus/sd-bus.c
+@@ -2080,7 +2080,7 @@ _public_ int sd_bus_call(
+         _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = sd_bus_message_ref(_m);
+         usec_t timeout;
+         uint64_t cookie;
+-        unsigned i;
++        size_t i;
+         int r;
+ 
+         bus_assert_return(m, -EINVAL, error);
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 <lennart@poettering.net>
+Date: Thu, 17 Jan 2019 18:14:17 +0100
+Subject: [PATCH] sd-bus: reorder bus ref and bus message ref handling
+
+Let's always place handling of these references together, so that all
+reference counting during allocation is at a single place.
+
+(cherry picked from commit e593b6a87a335267e5f7238b14683b7f840a01a3)
+Related: CVE-2020-1712
+---
+ src/libsystemd/sd-bus/bus-message.c | 5 +++--
+ 1 file changed, 3 insertions(+), 2 deletions(-)
+
+diff --git a/src/libsystemd/sd-bus/bus-message.c b/src/libsystemd/sd-bus/bus-message.c
+index 19cb2b9a97..e9cdf46c91 100644
+--- a/src/libsystemd/sd-bus/bus-message.c
++++ b/src/libsystemd/sd-bus/bus-message.c
+@@ -461,7 +461,6 @@ int bus_message_from_header(
+         if (!m)
+                 return -ENOMEM;
+ 
+-        m->n_ref = 1;
+         m->sealed = true;
+         m->header = header;
+         m->header_accessible = header_accessible;
+@@ -515,7 +514,9 @@ int bus_message_from_header(
+                 m->creds.mask |= SD_BUS_CREDS_SELINUX_CONTEXT;
+         }
+ 
++        m->n_ref = 1;
+         m->bus = sd_bus_ref(bus);
++
+         *ret = TAKE_PTR(m);
+ 
+         return 0;
+@@ -588,13 +589,13 @@ _public_ int sd_bus_message_new(
+                 return -ENOMEM;
+ 
+         t->n_ref = 1;
++        t->bus = sd_bus_ref(bus);
+         t->header = (struct bus_header*) ((uint8_t*) t + ALIGN(sizeof(struct sd_bus_message)));
+         t->header->endian = BUS_NATIVE_ENDIAN;
+         t->header->type = type;
+         t->header->version = bus->message_version;
+         t->allow_fds = bus->can_fds || !IN_SET(bus->state, BUS_HELLO, BUS_RUNNING);
+         t->root_container.need_offsets = BUS_MESSAGE_IS_GVARIANT(t);
+-        t->bus = sd_bus_ref(bus);
+ 
+         if (bus->allow_interactive_authorization)
+                 t->header->flags |= BUS_MESSAGE_ALLOW_INTERACTIVE_AUTHORIZATION;
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 <lennart@poettering.net>
+Date: Thu, 17 Jan 2019 18:15:37 +0100
+Subject: [PATCH] sd-bus: make sure dispatch_rqueue() initializes return
+ parameter on all types of success
+
+Let's make sure our own code follows coding style and initializes all
+return values on all types of success (and leaves it uninitialized in
+all types of failure).
+
+(cherry picked from commit c0bc4ec5cc17ac61773d1e9362b0ffa8382c1ff1)
+Related: CVE-2020-1712
+---
+ src/libsystemd/sd-bus/sd-bus.c | 4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+diff --git a/src/libsystemd/sd-bus/sd-bus.c b/src/libsystemd/sd-bus/sd-bus.c
+index 64026f7ee1..55b008cc9f 100644
+--- a/src/libsystemd/sd-bus/sd-bus.c
++++ b/src/libsystemd/sd-bus/sd-bus.c
+@@ -1814,8 +1814,10 @@ static int dispatch_rqueue(sd_bus *bus, bool hint_priority, int64_t priority, sd
+                 r = bus_read_message(bus, hint_priority, priority);
+                 if (r < 0)
+                         return r;
+-                if (r == 0)
++                if (r == 0) {
++                        *m = NULL;
+                         return ret;
++                }
+ 
+                 ret = 1;
+         }
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 <lennart@poettering.net>
+Date: Thu, 17 Jan 2019 18:18:18 +0100
+Subject: [PATCH] sd-bus: drop two inappropriate empty lines
+
+(cherry picked from commit 39feb2ce417e54cf9746e64b5dfd610cef6ac440)
+Related: CVE-2020-1712
+---
+ src/libsystemd/sd-bus/sd-bus.c | 2 --
+ 1 file changed, 2 deletions(-)
+
+diff --git a/src/libsystemd/sd-bus/sd-bus.c b/src/libsystemd/sd-bus/sd-bus.c
+index 55b008cc9f..01060d105c 100644
+--- a/src/libsystemd/sd-bus/sd-bus.c
++++ b/src/libsystemd/sd-bus/sd-bus.c
+@@ -2634,7 +2634,6 @@ static int process_builtin(sd_bus *bus, sd_bus_message *m) {
+                                 SD_BUS_ERROR_UNKNOWN_METHOD,
+                                  "Unknown method '%s' on interface '%s'.", m->member, m->interface);
+         }
+-
+         if (r < 0)
+                 return r;
+ 
+@@ -2758,7 +2757,6 @@ static int process_running(sd_bus *bus, bool hint_priority, int64_t priority, sd
+                         return r;
+ 
+                 *ret = TAKE_PTR(m);
+-
+                 return 1;
+         }
+ 
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 <lennart@poettering.net>
+Date: Thu, 17 Jan 2019 21:06:30 +0100
+Subject: [PATCH] sd-bus: initialize mutex after we allocated the wqueue
+
+That way the mutex doesn't have to be destroyed when we exit early due
+to OOM.
+
+(cherry picked from commit 2fe9a10d7695c4c3a748969a0d1662c624e50e5e)
+Related: CVE-2020-1712
+---
+ src/libsystemd/sd-bus/sd-bus.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/src/libsystemd/sd-bus/sd-bus.c b/src/libsystemd/sd-bus/sd-bus.c
+index 01060d105c..e49d58137d 100644
+--- a/src/libsystemd/sd-bus/sd-bus.c
++++ b/src/libsystemd/sd-bus/sd-bus.c
+@@ -248,12 +248,12 @@ _public_ int sd_bus_new(sd_bus **ret) {
+         b->original_pid = getpid_cached();
+         b->n_groups = (size_t) -1;
+ 
+-        assert_se(pthread_mutex_init(&b->memfd_cache_mutex, NULL) == 0);
+-
+         /* We guarantee that wqueue always has space for at least one entry */
+         if (!GREEDY_REALLOC(b->wqueue, b->wqueue_allocated, 1))
+                 return -ENOMEM;
+ 
++        assert_se(pthread_mutex_init(&b->memfd_cache_mutex, NULL) == 0);
++
+         *ret = TAKE_PTR(b);
+         return 0;
+ }
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 <lennart@poettering.net>
+Date: Thu, 17 Jan 2019 21:07:42 +0100
+Subject: [PATCH] sd-bus: always go through sd_bus_unref() to free messages
+
+Don't try to be smart, don't bypass the ref counting logic if there's no
+real reason to.
+
+This matters if we want to tweak the ref counting logic later.
+
+(cherry picked from commit b41812d1e308de03c879cfca490105216d528c4b)
+Related: CVE-2020-1712
+---
+ src/libsystemd/sd-bus/bus-message.c | 12 +++++-------
+ 1 file changed, 5 insertions(+), 7 deletions(-)
+
+diff --git a/src/libsystemd/sd-bus/bus-message.c b/src/libsystemd/sd-bus/bus-message.c
+index e9cdf46c91..306b6d6816 100644
+--- a/src/libsystemd/sd-bus/bus-message.c
++++ b/src/libsystemd/sd-bus/bus-message.c
+@@ -138,8 +138,6 @@ static sd_bus_message* message_free(sd_bus_message *m) {
+         return mfree(m);
+ }
+ 
+-DEFINE_TRIVIAL_CLEANUP_FUNC(sd_bus_message*, message_free);
+-
+ static void *message_extend_fields(sd_bus_message *m, size_t align, size_t sz, bool add_offset) {
+         void *op, *np;
+         size_t old_size, new_size, start;
+@@ -531,7 +529,7 @@ int bus_message_from_malloc(
+                 const char *label,
+                 sd_bus_message **ret) {
+ 
+-        _cleanup_(message_freep) sd_bus_message *m = NULL;
++        _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
+         size_t sz;
+         int r;
+ 
+@@ -651,7 +649,7 @@ _public_ int sd_bus_message_new_method_call(
+                 const char *interface,
+                 const char *member) {
+ 
+-        _cleanup_(message_freep) sd_bus_message *t = NULL;
++        _cleanup_(sd_bus_message_unrefp) sd_bus_message *t = NULL;
+         int r;
+ 
+         assert_return(bus, -ENOTCONN);
+@@ -696,7 +694,7 @@ static int message_new_reply(
+                 uint8_t type,
+                 sd_bus_message **m) {
+ 
+-        _cleanup_(message_freep) sd_bus_message *t = NULL;
++        _cleanup_(sd_bus_message_unrefp) sd_bus_message *t = NULL;
+         uint64_t cookie;
+         int r;
+ 
+@@ -747,7 +745,7 @@ _public_ int sd_bus_message_new_method_error(
+                 sd_bus_message **m,
+                 const sd_bus_error *e) {
+ 
+-        _cleanup_(message_freep) sd_bus_message *t = NULL;
++        _cleanup_(sd_bus_message_unrefp) sd_bus_message *t = NULL;
+         int r;
+ 
+         assert_return(sd_bus_error_is_set(e), -EINVAL);
+@@ -850,7 +848,7 @@ int bus_message_new_synthetic_error(
+                 const sd_bus_error *e,
+                 sd_bus_message **m) {
+ 
+-        _cleanup_(message_freep) sd_bus_message *t = NULL;
++        _cleanup_(sd_bus_message_unrefp) sd_bus_message *t = NULL;
+         int r;
+ 
+         assert(bus);
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 <lennart@poettering.net>
+Date: Thu, 17 Jan 2019 18:18:54 +0100
+Subject: [PATCH] bus-message: introduce two kinds of references to bus
+ messages
+
+Before this commit bus messages had a single reference count: when it
+reached zero the message would be freed. This simple approach meant a
+cyclic dependency was typically seen: a message that was enqueued in a
+bus connection object would reference the bus connection object but also
+itself be referenced by the bus connection object. So far out strategy
+to avoid cases like this was: make sure to process the bus connection
+regularly so that messages don#t stay queued, and at exit flush/close
+the connection so that the message queued would be emptied, and thus the
+cyclic dependencies resolved. Im many cases this isn't done properly
+however.
+
+With this change, let's address the issue more systematically: let's
+break the reference cycle. Specifically, there are now two types of
+references to a bus message:
+
+1. A regular one, which keeps both the message and the bus object it is
+   associated with pinned.
+
+2. A "queue" reference, which is weaker: it pins the message, but not
+   the bus object it is associated with.
+
+The idea is then that regular user handling uses regular references, but
+when a message is enqueued on its connection, then this takes a "queue"
+reference instead. This then means that a queued message doesn't imply
+the connection itself remains pinned, only regular references to the
+connection or a message associated with it do. Thus, if we end up in the
+situation where a user allocates a bus and a message and enqueues the
+latter in the former and drops all refs to both, then this will detect
+this case and free both.
+
+Note that this scheme isn't perfect, it only covers references between
+messages and the busses they are associated with. If OTOH a bus message
+is enqueued on a different bus than it is associated with cyclic deps
+cannot be recognized with this simple algorithm, and thus if you enqueue
+a message associated with a bus A on a bus B, and another message
+associated with bus B on a bus A, a cyclic ref will be in effect and not
+be discovered. However, given that this is an exotic case (though one
+that happens, consider systemd-bus-stdio-bridge), it should be OK not to
+cover with this, and people have to explicit flush all queues on exit in
+that case.
+
+Note that this commit only establishes the separate reference counters
+per message. A follow-up commit will start making use of this from the
+bus connection object.
+
+(cherry picked from commit 1b3f9dd759ca0ea215e7b89f8ce66d1b724497b9)
+Related: CVE-2020-1712
+---
+ src/libsystemd/sd-bus/bus-message.c | 60 ++++++++++++++++++++++++++---
+ src/libsystemd/sd-bus/bus-message.h | 14 ++++++-
+ 2 files changed, 68 insertions(+), 6 deletions(-)
+
+diff --git a/src/libsystemd/sd-bus/bus-message.c b/src/libsystemd/sd-bus/bus-message.c
+index 306b6d6816..7fe8929f82 100644
+--- a/src/libsystemd/sd-bus/bus-message.c
++++ b/src/libsystemd/sd-bus/bus-message.c
+@@ -120,7 +120,8 @@ static sd_bus_message* message_free(sd_bus_message *m) {
+ 
+         message_reset_parts(m);
+ 
+-        sd_bus_unref(m->bus);
++        /* Note that we don't unref m->bus here. That's already done by sd_bus_message_unref() as each user
++         * reference to the bus message also is considered a reference to the bus connection itself. */
+ 
+         if (m->free_fds) {
+                 close_many(m->fds, m->n_fds);
+@@ -893,27 +894,76 @@ int bus_message_new_synthetic_error(
+ }
+ 
+ _public_ sd_bus_message* sd_bus_message_ref(sd_bus_message *m) {
+-
+         if (!m)
+                 return NULL;
+ 
+-        assert(m->n_ref > 0);
++        /* We are fine if this message so far was either explicitly reffed or not reffed but queued into at
++         * least one bus connection object. */
++        assert(m->n_ref > 0 || m->n_queued > 0);
++
+         m->n_ref++;
+ 
++        /* Each user reference to a bus message shall also be considered a ref on the bus */
++        sd_bus_ref(m->bus);
+         return m;
+ }
+ 
+ _public_ sd_bus_message* sd_bus_message_unref(sd_bus_message *m) {
+-
+         if (!m)
+                 return NULL;
+ 
+         assert(m->n_ref > 0);
++
++        sd_bus_unref(m->bus); /* Each regular ref is also a ref on the bus connection. Let's hence drop it
++                               * here. Note we have to do this before decrementing our own n_ref here, since
++                               * otherwise, if this message is currently queued sd_bus_unref() might call
++                               * bus_message_unref_queued() for this which might then destroy the message
++                               * while we are still processing it. */
+         m->n_ref--;
+ 
+-        if (m->n_ref > 0)
++        if (m->n_ref > 0 || m->n_queued > 0)
+                 return NULL;
+ 
++        /* Unset the bus field if neither the user has a reference nor this message is queued. We are careful
++         * to reset the field only after the last reference to the bus is dropped, after all we might keep
++         * multiple references to the bus, once for each reference kept on outselves. */
++        m->bus = NULL;
++
++        return message_free(m);
++}
++
++sd_bus_message* bus_message_ref_queued(sd_bus_message *m, sd_bus *bus) {
++        if (!m)
++                return NULL;
++
++        /* If this is a different bus than the message is associated with, then implicitly turn this into a
++         * regular reference. This means that you can create a memory leak by enqueuing a message generated
++         * on one bus onto another at the same time as enqueueing a message from the second one on the first,
++         * as we'll not detect the cyclic references there. */
++        if (bus != m->bus)
++                return sd_bus_message_ref(m);
++
++        assert(m->n_ref > 0 || m->n_queued > 0);
++        m->n_queued++;
++
++        return m;
++}
++
++sd_bus_message* bus_message_unref_queued(sd_bus_message *m, sd_bus *bus) {
++        if (!m)
++                return NULL;
++
++        if (bus != m->bus)
++                return sd_bus_message_unref(m);
++
++        assert(m->n_queued > 0);
++        m->n_queued--;
++
++        if (m->n_ref > 0 || m->n_queued > 0)
++                return NULL;
++
++        m->bus = NULL;
++
+         return message_free(m);
+ }
+ 
+diff --git a/src/libsystemd/sd-bus/bus-message.h b/src/libsystemd/sd-bus/bus-message.h
+index 97f6060e30..ded88005e2 100644
+--- a/src/libsystemd/sd-bus/bus-message.h
++++ b/src/libsystemd/sd-bus/bus-message.h
+@@ -51,7 +51,16 @@ struct bus_body_part {
+ };
+ 
+ struct sd_bus_message {
+-        unsigned n_ref;
++        /* Caveat: a message can be referenced in two different ways: the main (user-facing) way will also
++         * pin the bus connection object the message is associated with. The secondary way ("queued") is used
++         * when a message is in the read or write queues of the bus connection object, which will not pin the
++         * bus connection object. This is necessary so that we don't have to have a pair of cyclic references
++         * between a message that is queued and its connection: as soon as a message is only referenced by
++         * the connection (by means of being queued) and the connection itself has no other references it
++         * will be freed. */
++
++        unsigned n_ref;     /* Counter of references that pin the connection */
++        unsigned n_queued;  /* Counter of references that do not pin the connection */
+ 
+         sd_bus *bus;
+ 
+@@ -216,3 +225,6 @@ int bus_message_append_sender(sd_bus_message *m, const char *sender);
+ 
+ void bus_message_set_sender_driver(sd_bus *bus, sd_bus_message *m);
+ void bus_message_set_sender_local(sd_bus *bus, sd_bus_message *m);
++
++sd_bus_message* bus_message_ref_queued(sd_bus_message *m, sd_bus *bus);
++sd_bus_message* bus_message_unref_queued(sd_bus_message *m, sd_bus *bus);
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 <jsynacek@redhat.com>
+Date: Fri, 31 Jan 2020 11:34:45 +0100
+Subject: [PATCH] sd-bus: introduce API for re-enqueuing incoming messages
+
+When authorizing via PolicyKit we want to process incoming method calls
+twice: once to process and figure out that we need PK authentication,
+and a second time after we aquired PK authentication to actually execute
+the operation. With this new call sd_bus_enqueue_for_read() we have a
+way to put an incoming message back into the read queue for this
+purpose.
+
+This might have other uses too, for example debugging.
+Related: CVE-2020-1712
+---
+ src/libsystemd/libsystemd.sym  |  1 +
+ src/libsystemd/sd-bus/sd-bus.c | 24 ++++++++++++++++++++++++
+ src/systemd/sd-bus.h           |  1 +
+ 3 files changed, 26 insertions(+)
+
+diff --git a/src/libsystemd/libsystemd.sym b/src/libsystemd/libsystemd.sym
+index 1eec17db50..e9972593a6 100644
+--- a/src/libsystemd/libsystemd.sym
++++ b/src/libsystemd/libsystemd.sym
+@@ -569,4 +569,5 @@ global:
+         sd_event_source_get_inotify_mask;
+         sd_event_source_set_destroy_callback;
+         sd_event_source_get_destroy_callback;
++        sd_bus_enqueue_for_read;
+ } LIBSYSTEMD_238;
+diff --git a/src/libsystemd/sd-bus/sd-bus.c b/src/libsystemd/sd-bus/sd-bus.c
+index e49d58137d..68ad6cbe89 100644
+--- a/src/libsystemd/sd-bus/sd-bus.c
++++ b/src/libsystemd/sd-bus/sd-bus.c
+@@ -4120,3 +4120,27 @@ _public_ int sd_bus_get_n_queued_write(sd_bus *bus, uint64_t *ret) {
+         *ret = bus->wqueue_size;
+         return 0;
+ }
++
++_public_ int sd_bus_enqueue_for_read(sd_bus *bus, sd_bus_message *m) {
++        int r;
++
++        assert_return(bus, -EINVAL);
++        assert_return(bus = bus_resolve(bus), -ENOPKG);
++        assert_return(m, -EINVAL);
++        assert_return(m->sealed, -EINVAL);
++        assert_return(!bus_pid_changed(bus), -ECHILD);
++
++        if (!BUS_IS_OPEN(bus->state))
++                return -ENOTCONN;
++
++        /* Re-enqeue a message for reading. This is primarily useful for PolicyKit-style authentication,
++         * where we want accept a message, then determine we need to interactively authenticate the user, and
++         * when we have that process the message again. */
++
++        r = bus_rqueue_make_room(bus);
++        if (r < 0)
++                return r;
++
++        bus->rqueue[bus->rqueue_size++] = bus_message_ref_queued(m, bus);
++        return 0;
++}
+diff --git a/src/systemd/sd-bus.h b/src/systemd/sd-bus.h
+index 54c4b1ca83..9ba757b13d 100644
+--- a/src/systemd/sd-bus.h
++++ b/src/systemd/sd-bus.h
+@@ -193,6 +193,7 @@ int sd_bus_process(sd_bus *bus, sd_bus_message **r);
+ int sd_bus_process_priority(sd_bus *bus, int64_t max_priority, sd_bus_message **r);
+ int sd_bus_wait(sd_bus *bus, uint64_t timeout_usec);
+ int sd_bus_flush(sd_bus *bus);
++int sd_bus_enqueue_for_read(sd_bus *bus, sd_bus_message *m);
+ 
+ sd_bus_slot* sd_bus_get_current_slot(sd_bus *bus);
+ sd_bus_message* sd_bus_get_current_message(sd_bus *bus);
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?= <zbyszek@in.waw.pl>
+Date: Wed, 8 May 2019 14:39:57 +0200
+Subject: [PATCH] sd-event: add sd_event_source_disable_unref() helper
+
+(cherry picked from commit afd15bbb4b6414b9356799c63029e36642dae8e4)
+Related: CVE-2020-1712
+---
+ man/rules/meson.build              |  4 +++-
+ man/sd_event_source_unref.xml      | 30 +++++++++++++++++++-----------
+ src/libsystemd/libsystemd.sym      |  1 +
+ src/libsystemd/sd-event/sd-event.c |  6 ++++++
+ src/systemd/sd-event.h             |  1 +
+ 5 files changed, 30 insertions(+), 12 deletions(-)
+
+diff --git a/man/rules/meson.build b/man/rules/meson.build
+index 989d11c9b9..7ae94ea265 100644
+--- a/man/rules/meson.build
++++ b/man/rules/meson.build
+@@ -340,7 +340,9 @@ manpages = [
+  ['sd_event_source_set_userdata', '3', ['sd_event_source_get_userdata'], ''],
+  ['sd_event_source_unref',
+   '3',
+-  ['sd_event_source_ref', 'sd_event_source_unrefp'],
++  ['sd_event_source_disable_unref',
++   'sd_event_source_ref',
++   'sd_event_source_unrefp'],
+   ''],
+  ['sd_event_wait',
+   '3',
+diff --git a/man/sd_event_source_unref.xml b/man/sd_event_source_unref.xml
+index d1b83c57aa..af8fed33f2 100644
+--- a/man/sd_event_source_unref.xml
++++ b/man/sd_event_source_unref.xml
+@@ -22,6 +22,7 @@
+     <refname>sd_event_source_unref</refname>
+     <refname>sd_event_source_unrefp</refname>
+     <refname>sd_event_source_ref</refname>
++    <refname>sd_event_source_disable_unref</refname>
+ 
+     <refpurpose>Increase or decrease event source reference counters</refpurpose>
+   </refnamediv>
+@@ -45,6 +46,10 @@
+         <paramdef>sd_event_source *<parameter>source</parameter></paramdef>
+       </funcprototype>
+ 
++      <funcprototype>
++        <funcdef>sd_event_source* <function>sd_event_source_disable_unref</function></funcdef>
++        <paramdef>sd_event_source *<parameter>source</parameter></paramdef>
++      </funcprototype>
+     </funcsynopsis>
+   </refsynopsisdiv>
+ 
+@@ -80,23 +85,26 @@
+     the passed event source object is
+     <constant>NULL</constant>.</para>
+ 
+-    <para>Note that event source objects stay alive and may be
+-    dispatched as long as they have a reference counter greater than
+-    zero. In order to drop a reference of an event source and make
+-    sure the associated event source handler function is not called
+-    anymore it is recommended to combine a call of
++    <para>Note that event source objects stay alive and may be dispatched as long as they have a reference
++    counter greater than zero. In order to drop a reference of an event source and make sure the associated
++    event source handler function is not called anymore it is recommended to combine a call of
+     <function>sd_event_source_unref()</function> with a prior call to
+-    <function>sd_event_source_set_enabled()</function> with
+-    <constant>SD_EVENT_OFF</constant>.</para>
++    <function>sd_event_source_set_enabled()</function> with <constant>SD_EVENT_OFF</constant> or call
++    <function>sd_event_source_disable_unref()</function>, see below.</para>
++
++    <para><function>sd_event_source_disable_unref()</function> combines a call to
++    <function>sd_event_source_set_enabled()</function> with <constant>SD_EVENT_OFF</constant> with
++    <function>sd_event_source_unref()</function>. This ensures that the source is disabled before the local
++    reference to it is lost. The <parameter>source</parameter> parameter is allowed to be
++    <constant>NULL</constant>.</para>
+   </refsect1>
+ 
+   <refsect1>
+     <title>Return Value</title>
+ 
+-    <para><function>sd_event_source_unref()</function> always returns
+-    <constant>NULL</constant>.
+-    <function>sd_event_source_ref()</function> always returns the
+-    event source object passed in.</para>
++    <para><function>sd_event_source_unref()</function> and
++    <function>sd_event_source_disable_unref()</function> always return <constant>NULL</constant>.
++    <function>sd_event_source_ref()</function> always returns the event source object passed in.</para>
+   </refsect1>
+ 
+   <xi:include href="libsystemd-pkgconfig.xml" />
+diff --git a/src/libsystemd/libsystemd.sym b/src/libsystemd/libsystemd.sym
+index e9972593a6..778e88a16c 100644
+--- a/src/libsystemd/libsystemd.sym
++++ b/src/libsystemd/libsystemd.sym
+@@ -570,4 +570,5 @@ global:
+         sd_event_source_set_destroy_callback;
+         sd_event_source_get_destroy_callback;
+         sd_bus_enqueue_for_read;
++        sd_event_source_disable_unref;
+ } LIBSYSTEMD_238;
+diff --git a/src/libsystemd/sd-event/sd-event.c b/src/libsystemd/sd-event/sd-event.c
+index d53b9a7026..0d3bf5cbb6 100644
+--- a/src/libsystemd/sd-event/sd-event.c
++++ b/src/libsystemd/sd-event/sd-event.c
+@@ -580,6 +580,12 @@ _public_ sd_event* sd_event_unref(sd_event *e) {
+         return NULL;
+ }
+ 
++_public_ sd_event_source* sd_event_source_disable_unref(sd_event_source *s) {
++        if (s)
++                (void) sd_event_source_set_enabled(s, SD_EVENT_OFF);
++        return sd_event_source_unref(s);
++}
++
+ static bool event_pid_changed(sd_event *e) {
+         assert(e);
+ 
+diff --git a/src/systemd/sd-event.h b/src/systemd/sd-event.h
+index 7fcae4ac49..9876be01c6 100644
+--- a/src/systemd/sd-event.h
++++ b/src/systemd/sd-event.h
+@@ -113,6 +113,7 @@ int sd_event_get_iteration(sd_event *e, uint64_t *ret);
+ 
+ sd_event_source* sd_event_source_ref(sd_event_source *s);
+ sd_event_source* sd_event_source_unref(sd_event_source *s);
++sd_event_source* sd_event_source_disable_unref(sd_event_source *s);
+ 
+ sd_event *sd_event_source_get_event(sd_event_source *s);
+ void* sd_event_source_get_userdata(sd_event_source *s);
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 <jsynacek@redhat.com>
+Date: Fri, 31 Jan 2020 15:17:25 +0100
+Subject: [PATCH] polkit: when authorizing via PK let's re-resolve
+ callback/userdata instead of caching it
+
+Previously, when doing an async PK query we'd store the original
+callback/userdata pair and call it again after the PK request is
+complete. This is problematic, since PK queries might be slow and in the
+meantime the userdata might be released and re-acquired. Let's avoid
+this by always traversing through the message handlers so that we always
+re-resolve the callback and userdata pair and thus can be sure it's
+up-to-date and properly valid.
+
+Resolves: CVE-2020-1712
+---
+ src/shared/bus-util.c | 74 +++++++++++++++++++++++++++++--------------
+ 1 file changed, 50 insertions(+), 24 deletions(-)
+
+diff --git a/src/shared/bus-util.c b/src/shared/bus-util.c
+index 2d908eb45c..5ed68429be 100644
+--- a/src/shared/bus-util.c
++++ b/src/shared/bus-util.c
+@@ -319,10 +319,10 @@ int bus_test_polkit(
+ 
+ typedef struct AsyncPolkitQuery {
+         sd_bus_message *request, *reply;
+-        sd_bus_message_handler_t callback;
+-        void *userdata;
+         sd_bus_slot *slot;
++
+         Hashmap *registry;
++        sd_event_source *defer_event_source;
+ } AsyncPolkitQuery;
+ 
+ static void async_polkit_query_free(AsyncPolkitQuery *q) {
+@@ -338,9 +338,22 @@ static void async_polkit_query_free(AsyncPolkitQuery *q) {
+         sd_bus_message_unref(q->request);
+         sd_bus_message_unref(q->reply);
+ 
++        sd_event_source_disable_unref(q->defer_event_source);
+         free(q);
+ }
+ 
++static int async_polkit_defer(sd_event_source *s, void *userdata) {
++        AsyncPolkitQuery *q = userdata;
++
++        assert(s);
++
++        /* This is called as idle event source after we processed the async polkit reply, hopefully after the
++         * method call we re-enqueued has been properly processed. */
++
++        async_polkit_query_free(q);
++        return 0;
++}
++
+ static int async_polkit_callback(sd_bus_message *reply, void *userdata, sd_bus_error *error) {
+         _cleanup_(sd_bus_error_free) sd_bus_error error_buffer = SD_BUS_ERROR_NULL;
+         AsyncPolkitQuery *q = userdata;
+@@ -349,19 +362,45 @@ static int async_polkit_callback(sd_bus_message *reply, void *userdata, sd_bus_e
+         assert(reply);
+         assert(q);
+ 
++        assert(q->slot);
+         q->slot = sd_bus_slot_unref(q->slot);
++
++        assert(!q->reply);
+         q->reply = sd_bus_message_ref(reply);
+ 
++        /* Now, let's dispatch the original message a second time be re-enqueing. This will then traverse the
++         * whole message processing again, and thus re-validating and re-retrieving the "userdata" field
++         * again.
++         *
++         * We install an idle event loop event to clean-up the PolicyKit request data when we are idle again,
++         * i.e. after the second time the message is processed is complete. */
++
++        assert(!q->defer_event_source);
++        r = sd_event_add_defer(sd_bus_get_event(sd_bus_message_get_bus(reply)), &q->defer_event_source, async_polkit_defer, q);
++        if (r < 0)
++                goto fail;
++
++        r = sd_event_source_set_priority(q->defer_event_source, SD_EVENT_PRIORITY_IDLE);
++        if (r < 0)
++                goto fail;
++
++        r = sd_event_source_set_enabled(q->defer_event_source, SD_EVENT_ONESHOT);
++        if (r < 0)
++                goto fail;
++
+         r = sd_bus_message_rewind(q->request, true);
+-        if (r < 0) {
+-                r = sd_bus_reply_method_errno(q->request, r, NULL);
+-                goto finish;
+-        }
++        if (r < 0)
++                goto fail;
+ 
+-        r = q->callback(q->request, q->userdata, &error_buffer);
+-        r = bus_maybe_reply_error(q->request, r, &error_buffer);
++        r = sd_bus_enqueue_for_read(sd_bus_message_get_bus(q->request), q->request);
++        if (r < 0)
++                goto fail;
+ 
+-finish:
++        return 1;
++
++fail:
++        log_debug_errno(r, "Processing asynchronous PolicyKit reply failed, ignoring: %m");
++        (void) sd_bus_reply_method_errno(q->request, r, NULL);
+         async_polkit_query_free(q);
+ 
+         return r;
+@@ -382,11 +421,9 @@ int bus_verify_polkit_async(
+ #if ENABLE_POLKIT
+         _cleanup_(sd_bus_message_unrefp) sd_bus_message *pk = NULL;
+         AsyncPolkitQuery *q;
+-        const char *sender, **k, **v;
+-        sd_bus_message_handler_t callback;
+-        void *userdata;
+         int c;
+ #endif
++        const char *sender, **k, **v;
+         int r;
+ 
+         assert(call);
+@@ -444,20 +481,11 @@ int bus_verify_polkit_async(
+         else if (r > 0)
+                 return 1;
+ 
+-#if ENABLE_POLKIT
+-        if (sd_bus_get_current_message(call->bus) != call)
+-                return -EINVAL;
+-
+-        callback = sd_bus_get_current_handler(call->bus);
+-        if (!callback)
+-                return -EINVAL;
+-
+-        userdata = sd_bus_get_current_userdata(call->bus);
+-
+         sender = sd_bus_message_get_sender(call);
+         if (!sender)
+                 return -EBADMSG;
+ 
++#if ENABLE_POLKIT
+         c = sd_bus_message_get_allow_interactive_authorization(call);
+         if (c < 0)
+                 return c;
+@@ -509,8 +537,6 @@ int bus_verify_polkit_async(
+                 return -ENOMEM;
+ 
+         q->request = sd_bus_message_ref(call);
+-        q->callback = callback;
+-        q->userdata = userdata;
+ 
+         r = hashmap_put(*registry, call, q);
+         if (r < 0) {
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?= <msekleta@redhat.com>
+Date: Mon, 6 Jan 2020 12:30:58 +0100
+Subject: [PATCH] sysctl: let's by default increase the numeric PID range from
+ 2^16 to 2^22
+
+This should PID collisions a tiny bit less likely, and thus improve
+security and robustness.
+
+2^22 isn't particularly a lot either, but it's the current kernel
+limitation.
+
+Bumping this limit was suggested by Linus himself:
+
+https://lwn.net/ml/linux-kernel/CAHk-=wiZ40LVjnXSi9iHLE_-ZBsWFGCgdmNiYZUXn1-V5YBg2g@mail.gmail.com/
+
+Let's experiment with this in systemd upstream first. Downstreams and
+users can after all still comment this easily.
+
+Besides compat concern the most often heard issue with such high PIDs is
+usability, since they are potentially hard to type. I am not entirely sure though
+whether 4194304 (as largest new PID) is that much worse to type or to
+copy than 65563.
+
+This should also simplify management of per system tasks limits as by
+this move the sysctl /proc/sys/kernel/threads-max becomes the primary
+knob to control how many processes to have in parallel.
+
+Resolves: #1744214
+---
+ sysctl.d/50-pid-max.conf | 17 +++++++++++++++++
+ sysctl.d/meson.build     |  1 +
+ 2 files changed, 18 insertions(+)
+ create mode 100644 sysctl.d/50-pid-max.conf
+
+diff --git a/sysctl.d/50-pid-max.conf b/sysctl.d/50-pid-max.conf
+new file mode 100644
+index 0000000000..3a8393d185
+--- /dev/null
++++ b/sysctl.d/50-pid-max.conf
+@@ -0,0 +1,17 @@
++#  This file is part of systemd.
++#
++#  systemd is free software; you can redistribute it and/or modify it
++#  under the terms of the GNU Lesser General Public License as published by
++#  the Free Software Foundation; either version 2.1 of the License, or
++#  (at your option) any later version.
++
++# See sysctl.d(5) and core(5) for documentation.
++
++# To override settings in this file, create a local file in /etc
++# (e.g. /etc/sysctl.d/90-override.conf), and put any assignments
++# there.
++
++# Bump the numeric PID range to its maximum of 2^22 (from the in-kernel default
++# of 2^16), to make PID collisions less likely.
++kernel.pid_max = 4194304
++
+diff --git a/sysctl.d/meson.build b/sysctl.d/meson.build
+index 64f6ce942e..a95957ad7d 100644
+--- a/sysctl.d/meson.build
++++ b/sysctl.d/meson.build
+@@ -2,6 +2,7 @@
+ 
+ install_data(
+         '50-default.conf',
++        '50-pid-max.conf',
+         install_dir : sysctldir)
+ 
+ in_files = []
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 <watanabe.yu+github@gmail.com>
+Date: Tue, 28 May 2019 12:40:17 +0900
+Subject: [PATCH] journal: do not trigger assertion when journal_file_close()
+ get NULL
+
+We generally expect destructors to not complain if a NULL argument is passed.
+
+Closes #12400.
+
+(cherry picked from commit c377a6f3ad3d9bed4ce7e873e8e9ec6b1650c57d)
+Resolves: #1788085
+---
+ src/journal/journal-file.c    | 3 ++-
+ src/journal/journald-server.c | 7 ++-----
+ 2 files changed, 4 insertions(+), 6 deletions(-)
+
+diff --git a/src/journal/journal-file.c b/src/journal/journal-file.c
+index efc3ee052b..8249b11b23 100644
+--- a/src/journal/journal-file.c
++++ b/src/journal/journal-file.c
+@@ -335,7 +335,8 @@ bool journal_file_is_offlining(JournalFile *f) {
+ }
+ 
+ JournalFile* journal_file_close(JournalFile *f) {
+-        assert(f);
++        if (!f)
++                return NULL;
+ 
+ #if HAVE_GCRYPT
+         /* Write the final tag */
+diff --git a/src/journal/journald-server.c b/src/journal/journald-server.c
+index 6aecb67d6c..6250eab831 100644
+--- a/src/journal/journald-server.c
++++ b/src/journal/journald-server.c
+@@ -1906,11 +1906,8 @@ void server_done(Server *s) {
+ 
+         client_context_flush_all(s);
+ 
+-        if (s->system_journal)
+-                (void) journal_file_close(s->system_journal);
+-
+-        if (s->runtime_journal)
+-                (void) journal_file_close(s->runtime_journal);
++        (void) journal_file_close(s->system_journal);
++        (void) journal_file_close(s->runtime_journal);
+ 
+         ordered_hashmap_free_with_destructor(s->user_journals, journal_file_close);
+ 
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 <watanabe.yu+github@gmail.com>
+Date: Tue, 28 May 2019 18:07:01 +0900
+Subject: [PATCH] journal: use cleanup attribute at one more place
+
+(cherry picked from commit 627df1dc42b68a74b0882b06366d1185b1a34332)
+
+Conflicts:
+	src/journal/journald-server.c
+
+Related: #1788085
+---
+ src/journal/journal-file.h    | 1 +
+ src/journal/journald-server.c | 9 ++++-----
+ 2 files changed, 5 insertions(+), 5 deletions(-)
+
+diff --git a/src/journal/journal-file.h b/src/journal/journal-file.h
+index cd8a48a364..6a44fd39d2 100644
+--- a/src/journal/journal-file.h
++++ b/src/journal/journal-file.h
+@@ -144,6 +144,7 @@ int journal_file_open(
+ int journal_file_set_offline(JournalFile *f, bool wait);
+ bool journal_file_is_offlining(JournalFile *f);
+ JournalFile* journal_file_close(JournalFile *j);
++DEFINE_TRIVIAL_CLEANUP_FUNC(JournalFile*, journal_file_close);
+ 
+ int journal_file_open_reliably(
+                 const char *fname,
+diff --git a/src/journal/journald-server.c b/src/journal/journald-server.c
+index 6250eab831..7632e2d9d0 100644
+--- a/src/journal/journald-server.c
++++ b/src/journal/journald-server.c
+@@ -253,8 +253,9 @@ static int open_journal(
+                 bool seal,
+                 JournalMetrics *metrics,
+                 JournalFile **ret) {
++
++        _cleanup_(journal_file_closep) JournalFile *f = NULL;
+         int r;
+-        JournalFile *f;
+ 
+         assert(s);
+         assert(fname);
+@@ -271,12 +272,10 @@ static int open_journal(
+                 return r;
+ 
+         r = journal_file_enable_post_change_timer(f, s->event, POST_CHANGE_TIMER_INTERVAL_USEC);
+-        if (r < 0) {
+-                (void) journal_file_close(f);
++        if (r < 0)
+                 return r;
+-        }
+ 
+-        *ret = f;
++        *ret = TAKE_PTR(f);
+         return r;
+ }
+ 
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 <lennart@poettering.net>
+Date: Thu, 17 Jan 2019 18:31:59 +0100
+Subject: [PATCH] sd-bus: use "queue" message references for managing r/w
+ message queues in connection objects
+
+Let's make use of the new concept the previous commit added.
+
+See: #4846
+(cherry picked from commit c1757a70eac0382c4837a3833d683919f6a48ed7)
+Related: CVE-2020-1712
+---
+ src/libsystemd/sd-bus/bus-socket.c |  6 ++-
+ src/libsystemd/sd-bus/sd-bus.c     | 60 ++++++++++++++----------------
+ 2 files changed, 32 insertions(+), 34 deletions(-)
+
+diff --git a/src/libsystemd/sd-bus/bus-socket.c b/src/libsystemd/sd-bus/bus-socket.c
+index 17cfa8e1fd..4a72795d2b 100644
+--- a/src/libsystemd/sd-bus/bus-socket.c
++++ b/src/libsystemd/sd-bus/bus-socket.c
+@@ -1116,8 +1116,10 @@ static int bus_socket_make_message(sd_bus *bus, size_t size) {
+         bus->fds = NULL;
+         bus->n_fds = 0;
+ 
+-        if (t)
+-                bus->rqueue[bus->rqueue_size++] = t;
++        if (t) {
++                bus->rqueue[bus->rqueue_size++] = bus_message_ref_queued(t, bus);
++                sd_bus_message_unref(t);
++        }
+ 
+         return 1;
+ }
+diff --git a/src/libsystemd/sd-bus/sd-bus.c b/src/libsystemd/sd-bus/sd-bus.c
+index 68ad6cbe89..a3509f7e89 100644
+--- a/src/libsystemd/sd-bus/sd-bus.c
++++ b/src/libsystemd/sd-bus/sd-bus.c
+@@ -148,13 +148,13 @@ static void bus_reset_queues(sd_bus *b) {
+         assert(b);
+ 
+         while (b->rqueue_size > 0)
+-                sd_bus_message_unref(b->rqueue[--b->rqueue_size]);
++                bus_message_unref_queued(b->rqueue[--b->rqueue_size], b);
+ 
+         b->rqueue = mfree(b->rqueue);
+         b->rqueue_allocated = 0;
+ 
+         while (b->wqueue_size > 0)
+-                sd_bus_message_unref(b->wqueue[--b->wqueue_size]);
++                bus_message_unref_queued(b->wqueue[--b->wqueue_size], b);
+ 
+         b->wqueue = mfree(b->wqueue);
+         b->wqueue_allocated = 0;
+@@ -493,7 +493,7 @@ static int synthesize_connected_signal(sd_bus *bus) {
+ 
+         /* Insert at the very front */
+         memmove(bus->rqueue + 1, bus->rqueue, sizeof(sd_bus_message*) * bus->rqueue_size);
+-        bus->rqueue[0] = TAKE_PTR(m);
++        bus->rqueue[0] = bus_message_ref_queued(m, bus);
+         bus->rqueue_size++;
+ 
+         return 0;
+@@ -1760,7 +1760,7 @@ static int dispatch_wqueue(sd_bus *bus) {
+                          * anyway. */
+ 
+                         bus->wqueue_size--;
+-                        sd_bus_message_unref(bus->wqueue[0]);
++                        bus_message_unref_queued(bus->wqueue[0], bus);
+                         memmove(bus->wqueue, bus->wqueue + 1, sizeof(sd_bus_message*) * bus->wqueue_size);
+                         bus->windex = 0;
+ 
+@@ -1789,6 +1789,15 @@ int bus_rqueue_make_room(sd_bus *bus) {
+         return 0;
+ }
+ 
++static void rqueue_drop_one(sd_bus *bus, size_t i) {
++        assert(bus);
++        assert(i < bus->rqueue_size);
++
++        bus_message_unref_queued(bus->rqueue[i], bus);
++        memmove(bus->rqueue + i, bus->rqueue + i + 1, sizeof(sd_bus_message*) * (bus->rqueue_size - i - 1));
++        bus->rqueue_size--;
++}
++
+ static int dispatch_rqueue(sd_bus *bus, bool hint_priority, int64_t priority, sd_bus_message **m) {
+         int r, ret = 0;
+ 
+@@ -1803,10 +1812,8 @@ static int dispatch_rqueue(sd_bus *bus, bool hint_priority, int64_t priority, sd
+         for (;;) {
+                 if (bus->rqueue_size > 0) {
+                         /* Dispatch a queued message */
+-
+-                        *m = bus->rqueue[0];
+-                        bus->rqueue_size--;
+-                        memmove(bus->rqueue, bus->rqueue + 1, sizeof(sd_bus_message*) * bus->rqueue_size);
++                        *m = sd_bus_message_ref(bus->rqueue[0]);
++                        rqueue_drop_one(bus, 0);
+                         return 1;
+                 }
+ 
+@@ -1884,7 +1891,7 @@ _public_ int sd_bus_send(sd_bus *bus, sd_bus_message *_m, uint64_t *cookie) {
+                          * of the wqueue array is always allocated so
+                          * that we always can remember how much was
+                          * written. */
+-                        bus->wqueue[0] = sd_bus_message_ref(m);
++                        bus->wqueue[0] = bus_message_ref_queued(m, bus);
+                         bus->wqueue_size = 1;
+                         bus->windex = idx;
+                 }
+@@ -1898,7 +1905,7 @@ _public_ int sd_bus_send(sd_bus *bus, sd_bus_message *_m, uint64_t *cookie) {
+                 if (!GREEDY_REALLOC(bus->wqueue, bus->wqueue_allocated, bus->wqueue_size + 1))
+                         return -ENOMEM;
+ 
+-                bus->wqueue[bus->wqueue_size++] = sd_bus_message_ref(m);
++                bus->wqueue[bus->wqueue_size++] = bus_message_ref_queued(m, bus);
+         }
+ 
+ finish:
+@@ -2124,37 +2131,30 @@ _public_ int sd_bus_call(
+                 usec_t left;
+ 
+                 while (i < bus->rqueue_size) {
+-                        sd_bus_message *incoming = NULL;
++                        _cleanup_(sd_bus_message_unrefp) sd_bus_message *incoming = NULL;
+ 
+-                        incoming = bus->rqueue[i];
++                        incoming = sd_bus_message_ref(bus->rqueue[i]);
+ 
+                         if (incoming->reply_cookie == cookie) {
+                                 /* Found a match! */
+ 
+-                                memmove(bus->rqueue + i, bus->rqueue + i + 1, sizeof(sd_bus_message*) * (bus->rqueue_size - i - 1));
+-                                bus->rqueue_size--;
++                                rqueue_drop_one(bus, i);
+                                 log_debug_bus_message(incoming);
+ 
+                                 if (incoming->header->type == SD_BUS_MESSAGE_METHOD_RETURN) {
+ 
+                                         if (incoming->n_fds <= 0 || bus->accept_fd) {
+                                                 if (reply)
+-                                                        *reply = incoming;
+-                                                else
+-                                                        sd_bus_message_unref(incoming);
++                                                        *reply = TAKE_PTR(incoming);
+ 
+                                                 return 1;
+                                         }
+ 
+-                                        r = sd_bus_error_setf(error, SD_BUS_ERROR_INCONSISTENT_MESSAGE, "Reply message contained file descriptors which I couldn't accept. Sorry.");
+-                                        sd_bus_message_unref(incoming);
+-                                        return r;
++                                        return sd_bus_error_setf(error, SD_BUS_ERROR_INCONSISTENT_MESSAGE, "Reply message contained file descriptors which I couldn't accept. Sorry.");
+ 
+-                                } else if (incoming->header->type == SD_BUS_MESSAGE_METHOD_ERROR) {
+-                                        r = sd_bus_error_copy(error, &incoming->error);
+-                                        sd_bus_message_unref(incoming);
+-                                        return r;
+-                                } else {
++                                } else if (incoming->header->type == SD_BUS_MESSAGE_METHOD_ERROR)
++                                        return sd_bus_error_copy(error, &incoming->error);
++                                else {
+                                         r = -EIO;
+                                         goto fail;
+                                 }
+@@ -2164,15 +2164,11 @@ _public_ int sd_bus_call(
+                                    incoming->sender &&
+                                    streq(bus->unique_name, incoming->sender)) {
+ 
+-                                memmove(bus->rqueue + i, bus->rqueue + i + 1, sizeof(sd_bus_message*) * (bus->rqueue_size - i - 1));
+-                                bus->rqueue_size--;
++                                rqueue_drop_one(bus, i);
+ 
+-                                /* Our own message? Somebody is trying
+-                                 * to send its own client a message,
+-                                 * let's not dead-lock, let's fail
+-                                 * immediately. */
++                                /* Our own message? Somebody is trying to send its own client a message,
++                                 * let's not dead-lock, let's fail immediately. */
+ 
+-                                sd_bus_message_unref(incoming);
+                                 r = -ELOOP;
+                                 goto fail;
+                         }
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 <jsynacek@redhat.com>
+Date: Wed, 12 Feb 2020 12:58:54 +0100
+Subject: [PATCH] pid1: make sure to restore correct default values for some
+ rlimits
+
+Commit fb39af4ce42d7ef9af63009f271f404038703704 forgot to restore the default
+rlimit values (RLIMIT_NOFILE and RLIMIT_MEMLOCK) while PID1 is reloading.
+
+This patch extracts the code in charge of initializing the default values for
+those rlimits in order to create dedicated functions, which take care of their
+initialization.
+
+These functions are then called in parse_configuration() so we make sure that
+the default values for these rlimits get restored every time PID1 is reloading
+its configuration.
+
+(cherry picked from commit a9fd4cd1206832a61aaf61fff583bb133e6cb965)
+Resolves: #1789930
+---
+ src/core/main.c | 135 +++++++++++++++++++++++++++++++++++++-----------
+ 1 file changed, 106 insertions(+), 29 deletions(-)
+
+diff --git a/src/core/main.c b/src/core/main.c
+index c83249a8dc..b8c1e567ad 100644
+--- a/src/core/main.c
++++ b/src/core/main.c
+@@ -136,7 +136,8 @@ static EmergencyAction arg_cad_burst_action;
+ static CPUSet arg_cpu_affinity;
+ static NUMAPolicy arg_numa_policy;
+ 
+-static int parse_configuration(void);
++static int parse_configuration(const struct rlimit *saved_rlimit_nofile,
++                               const struct rlimit *saved_rlimit_memlock);
+ 
+ _noreturn_ static void freeze_or_reboot(void) {
+ 
+@@ -1149,25 +1150,6 @@ static int prepare_reexecute(Manager *m, FILE **_f, FDSet **_fds, bool switching
+ static int bump_rlimit_nofile(struct rlimit *saved_rlimit) {
+         int r, nr;
+ 
+-        assert(saved_rlimit);
+-
+-        /* Save the original RLIMIT_NOFILE so that we can reset it
+-         * later when transitioning from the initrd to the main
+-         * systemd or suchlike. */
+-        if (getrlimit(RLIMIT_NOFILE, saved_rlimit) < 0)
+-                return log_warning_errno(errno, "Reading RLIMIT_NOFILE failed, ignoring: %m");
+-
+-        /* Make sure forked processes get the default kernel setting */
+-        if (!arg_default_rlimit[RLIMIT_NOFILE]) {
+-                struct rlimit *rl;
+-
+-                rl = newdup(struct rlimit, saved_rlimit, 1);
+-                if (!rl)
+-                        return log_oom();
+-
+-                arg_default_rlimit[RLIMIT_NOFILE] = rl;
+-        }
+-
+         /* Bump up the resource limit for ourselves substantially, all the way to the maximum the kernel allows */
+         nr = read_nr_open();
+         r = setrlimit_closest(RLIMIT_NOFILE, &RLIMIT_MAKE_CONST(nr));
+@@ -1180,16 +1162,12 @@ static int bump_rlimit_nofile(struct rlimit *saved_rlimit) {
+ static int bump_rlimit_memlock(struct rlimit *saved_rlimit) {
+         int r;
+ 
+-        assert(saved_rlimit);
+         assert(getuid() == 0);
+ 
+         /* BPF_MAP_TYPE_LPM_TRIE bpf maps are charged against RLIMIT_MEMLOCK, even though we have CAP_IPC_LOCK which
+          * should normally disable such checks. We need them to implement IPAccessAllow= and IPAccessDeny=, hence let's
+          * bump the value high enough for the root user. */
+ 
+-        if (getrlimit(RLIMIT_MEMLOCK, saved_rlimit) < 0)
+-                return log_warning_errno(errno, "Reading RLIMIT_MEMLOCK failed, ignoring: %m");
+-
+         r = setrlimit_closest(RLIMIT_MEMLOCK, &RLIMIT_MAKE_CONST(1024ULL*1024ULL*16ULL));
+         if (r < 0)
+                 return log_warning_errno(r, "Setting RLIMIT_MEMLOCK failed, ignoring: %m");
+@@ -1651,6 +1629,8 @@ static void do_reexecute(
+ 
+ static int invoke_main_loop(
+                 Manager *m,
++                const struct rlimit *saved_rlimit_nofile,
++                const struct rlimit *saved_rlimit_memlock,
+                 bool *ret_reexecute,
+                 int *ret_retval,                   /* Return parameters relevant for shutting down */
+                 const char **ret_shutdown_verb,    /* … */
+@@ -1662,6 +1642,8 @@ static int invoke_main_loop(
+         int r;
+ 
+         assert(m);
++        assert(saved_rlimit_nofile);
++        assert(saved_rlimit_memlock);
+         assert(ret_reexecute);
+         assert(ret_retval);
+         assert(ret_shutdown_verb);
+@@ -1691,7 +1673,7 @@ static int invoke_main_loop(
+                         saved_log_level = m->log_level_overridden ? log_get_max_level() : -1;
+                         saved_log_target = m->log_target_overridden ? log_get_target() : _LOG_TARGET_INVALID;
+ 
+-                        (void) parse_configuration();
++                        (void) parse_configuration(saved_rlimit_nofile, saved_rlimit_memlock);
+ 
+                         set_manager_defaults(m);
+ 
+@@ -1983,6 +1965,80 @@ static int do_queue_default_job(
+         return 0;
+ }
+ 
++static void save_rlimits(struct rlimit *saved_rlimit_nofile,
++                         struct rlimit *saved_rlimit_memlock) {
++
++        assert(saved_rlimit_nofile);
++        assert(saved_rlimit_memlock);
++
++        if (getrlimit(RLIMIT_NOFILE, saved_rlimit_nofile) < 0)
++                log_warning_errno(errno, "Reading RLIMIT_NOFILE failed, ignoring: %m");
++
++        if (getrlimit(RLIMIT_MEMLOCK, saved_rlimit_memlock) < 0)
++                log_warning_errno(errno, "Reading RLIMIT_MEMLOCK failed, ignoring: %m");
++}
++
++static void fallback_rlimit_nofile(const struct rlimit *saved_rlimit_nofile) {
++        struct rlimit *rl;
++
++        if (arg_default_rlimit[RLIMIT_NOFILE])
++                return;
++
++        /* Make sure forked processes get limits based on the original kernel setting */
++
++        rl = newdup(struct rlimit, saved_rlimit_nofile, 1);
++        if (!rl) {
++                log_oom();
++                return;
++        }
++
++        /* Bump the hard limit for system services to a substantially higher value. The default
++         * hard limit current kernels set is pretty low (4K), mostly for historical
++         * reasons. According to kernel developers, the fd handling in recent kernels has been
++         * optimized substantially enough, so that we can bump the limit now, without paying too
++         * high a price in memory or performance. Note however that we only bump the hard limit,
++         * not the soft limit. That's because select() works the way it works, and chokes on fds
++         * >= 1024. If we'd bump the soft limit globally, it might accidentally happen to
++         * unexpecting programs that they get fds higher than what they can process using
++         * select(). By only bumping the hard limit but leaving the low limit as it is we avoid
++         * this pitfall:  programs that are written by folks aware of the select() problem in mind
++         * (and thus use poll()/epoll instead of select(), the way everybody should) can
++         * explicitly opt into high fds by bumping their soft limit beyond 1024, to the hard limit
++         * we pass. */
++        if (arg_system) {
++                int nr;
++
++                /* Get the underlying absolute limit the kernel enforces */
++                nr = read_nr_open();
++
++                rl->rlim_max = MIN((rlim_t) nr, MAX(rl->rlim_max, (rlim_t) HIGH_RLIMIT_NOFILE));
++        }
++
++        /* If for some reason we were invoked with a soft limit above 1024 (which should never
++         * happen!, but who knows what we get passed in from pam_limit when invoked as --user
++         * instance), then lower what we pass on to not confuse our children */
++        rl->rlim_cur = MIN(rl->rlim_cur, (rlim_t) FD_SETSIZE);
++
++        arg_default_rlimit[RLIMIT_NOFILE] = rl;
++}
++
++static void fallback_rlimit_memlock(const struct rlimit *saved_rlimit_memlock) {
++        struct rlimit *rl;
++
++        /* Pass the original value down to invoked processes */
++
++        if (arg_default_rlimit[RLIMIT_MEMLOCK])
++                return;
++
++        rl = newdup(struct rlimit, saved_rlimit_memlock, 1);
++        if (!rl) {
++                log_oom();
++                return;
++        }
++
++        arg_default_rlimit[RLIMIT_MEMLOCK] = rl;
++}
++
+ static void reset_arguments(void) {
+         /* Frees/resets arg_* variables, with a few exceptions commented below. */
+ 
+@@ -2040,9 +2096,13 @@ static void reset_arguments(void) {
+         numa_policy_reset(&arg_numa_policy);
+ }
+ 
+-static int parse_configuration(void) {
++static int parse_configuration(const struct rlimit *saved_rlimit_nofile,
++                               const struct rlimit *saved_rlimit_memlock) {
+         int r;
+ 
++        assert(saved_rlimit_nofile);
++        assert(saved_rlimit_memlock);
++
+         arg_default_tasks_max = system_tasks_max_scale(DEFAULT_TASKS_MAX_PERCENTAGE, 100U);
+ 
+         /* Assign configuration defaults */
+@@ -2058,18 +2118,29 @@ static int parse_configuration(void) {
+                         log_warning_errno(r, "Failed to parse kernel command line, ignoring: %m");
+         }
+ 
++        /* Initialize some default rlimits for services if they haven't been configured */
++        fallback_rlimit_nofile(saved_rlimit_nofile);
++        fallback_rlimit_memlock(saved_rlimit_memlock);
++
+         /* Note that this also parses bits from the kernel command line, including "debug". */
+         log_parse_environment();
+ 
+         return 0;
+ }
+ 
+-static int load_configuration(int argc, char **argv, const char **ret_error_message) {
++static int load_configuration(
++                int argc,
++                char **argv,
++                const struct rlimit *saved_rlimit_nofile,
++                const struct rlimit *saved_rlimit_memlock,
++                const char **ret_error_message) {
+         int r;
+ 
++        assert(saved_rlimit_nofile);
++        assert(saved_rlimit_memlock);
+         assert(ret_error_message);
+ 
+-        (void) parse_configuration();
++        (void) parse_configuration(saved_rlimit_nofile, saved_rlimit_memlock);
+ 
+         r = parse_argv(argc, argv);
+         if (r < 0) {
+@@ -2403,11 +2474,15 @@ int main(int argc, char *argv[]) {
+                 }
+         }
+ 
++        /* Save the original RLIMIT_NOFILE/RLIMIT_MEMLOCK so that we can reset it later when
++         * transitioning from the initrd to the main systemd or suchlike. */
++        save_rlimits(&saved_rlimit_nofile, &saved_rlimit_memlock);
++
+         /* Reset all signal handlers. */
+         (void) reset_all_signal_handlers();
+         (void) ignore_signals(SIGNALS_IGNORE, -1);
+ 
+-        r = load_configuration(argc, argv, &error_message);
++        r = load_configuration(argc, argv, &saved_rlimit_nofile, &saved_rlimit_memlock, &error_message);
+         if (r < 0)
+                 goto finish;
+ 
+@@ -2522,6 +2597,8 @@ int main(int argc, char *argv[]) {
+         }
+ 
+         (void) invoke_main_loop(m,
++                                &saved_rlimit_nofile,
++                                &saved_rlimit_memlock,
+                                 &reexecute,
+                                 &retval,
+                                 &shutdown_verb,
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 <lennart@poettering.net>
+Date: Thu, 11 Oct 2018 18:31:11 +0200
+Subject: [PATCH] main: introduce a define HIGH_RLIMIT_MEMLOCK similar to
+ HIGH_RLIMIT_NOFILE
+
+(cherry picked from commit c8884aceefc85245b9bdfb626e2daf27521259bd)
+Related: #1789930
+---
+ src/basic/def.h | 3 +++
+ src/core/main.c | 2 +-
+ 2 files changed, 4 insertions(+), 1 deletion(-)
+
+diff --git a/src/basic/def.h b/src/basic/def.h
+index 4d515c11b6..65ad659999 100644
+--- a/src/basic/def.h
++++ b/src/basic/def.h
+@@ -75,3 +75,6 @@
+                 _CONF_PATHS_SPLIT_USR(n))
+ 
+ #define LONG_LINE_MAX (1U*1024U*1024U)
++
++#define HIGH_RLIMIT_NOFILE (256*1024)
++#define HIGH_RLIMIT_MEMLOCK (1024ULL*1024ULL*64ULL)
+diff --git a/src/core/main.c b/src/core/main.c
+index b8c1e567ad..d6550ea161 100644
+--- a/src/core/main.c
++++ b/src/core/main.c
+@@ -1168,7 +1168,7 @@ static int bump_rlimit_memlock(struct rlimit *saved_rlimit) {
+          * should normally disable such checks. We need them to implement IPAccessAllow= and IPAccessDeny=, hence let's
+          * bump the value high enough for the root user. */
+ 
+-        r = setrlimit_closest(RLIMIT_MEMLOCK, &RLIMIT_MAKE_CONST(1024ULL*1024ULL*16ULL));
++        r = setrlimit_closest(RLIMIT_MEMLOCK, &RLIMIT_MAKE_CONST(HIGH_RLIMIT_MEMLOCK));
+         if (r < 0)
+                 return log_warning_errno(r, "Setting RLIMIT_MEMLOCK failed, ignoring: %m");
+ 
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 <lennart@poettering.net>
+Date: Wed, 20 Mar 2019 19:00:28 +0100
+Subject: [PATCH] seccomp: introduce seccomp_restrict_suid_sgid() for blocking
+ chmod() for suid/sgid files
+
+(cherry picked from commit 3c27973b13724ede05a06a5d346a569794cda433)
+Related: #1687512
+---
+ src/shared/seccomp-util.c | 132 ++++++++++++++++++++++++++++++++++++++
+ src/shared/seccomp-util.h |   1 +
+ 2 files changed, 133 insertions(+)
+
+diff --git a/src/shared/seccomp-util.c b/src/shared/seccomp-util.c
+index 92910acf0e..fd46b9f88d 100644
+--- a/src/shared/seccomp-util.c
++++ b/src/shared/seccomp-util.c
+@@ -1,12 +1,14 @@
+ /* SPDX-License-Identifier: LGPL-2.1+ */
+ 
+ #include <errno.h>
++#include <fcntl.h>
+ #include <linux/seccomp.h>
+ #include <seccomp.h>
+ #include <stddef.h>
+ #include <sys/mman.h>
+ #include <sys/prctl.h>
+ #include <sys/shm.h>
++#include <sys/stat.h>
+ 
+ #include "af-list.h"
+ #include "alloc-util.h"
+@@ -1747,3 +1749,133 @@ int seccomp_lock_personality(unsigned long personality) {
+ 
+         return 0;
+ }
++
++int seccomp_restrict_suid_sgid(void) {
++        uint32_t arch;
++        int r;
++
++        SECCOMP_FOREACH_LOCAL_ARCH(arch) {
++                _cleanup_(seccomp_releasep) scmp_filter_ctx seccomp = NULL;
++
++                r = seccomp_init_for_arch(&seccomp, arch, SCMP_ACT_ALLOW);
++                if (r < 0)
++                        return r;
++
++                /* Checks the mode_t parameter of the following system calls:
++                 *
++                 *       → chmod() + fchmod() + fchmodat()
++                 *       → open() + creat() + openat()
++                 *       → mkdir() + mkdirat()
++                 *       → mknod() + mknodat()
++                 */
++
++                for (unsigned bit = 0; bit < 2; bit ++) {
++                        /* Block S_ISUID in the first iteration, S_ISGID in the second */
++                        mode_t m = bit == 0 ? S_ISUID : S_ISGID;
++
++                        r = seccomp_rule_add_exact(
++                                        seccomp,
++                                        SCMP_ACT_ERRNO(EPERM),
++                                        SCMP_SYS(chmod),
++                                        1,
++                                        SCMP_A1(SCMP_CMP_MASKED_EQ, m, m));
++                        if (r < 0)
++                                break;
++
++                        r = seccomp_rule_add_exact(
++                                        seccomp,
++                                        SCMP_ACT_ERRNO(EPERM),
++                                        SCMP_SYS(fchmod),
++                                        1,
++                                        SCMP_A1(SCMP_CMP_MASKED_EQ, m, m));
++                        if (r < 0)
++                                break;
++
++                        r = seccomp_rule_add_exact(
++                                        seccomp,
++                                        SCMP_ACT_ERRNO(EPERM),
++                                        SCMP_SYS(fchmodat),
++                                        1,
++                                        SCMP_A2(SCMP_CMP_MASKED_EQ, m, m));
++                        if (r < 0)
++                                break;
++
++                        r = seccomp_rule_add_exact(
++                                        seccomp,
++                                        SCMP_ACT_ERRNO(EPERM),
++                                        SCMP_SYS(mkdir),
++                                        1,
++                                        SCMP_A1(SCMP_CMP_MASKED_EQ, m, m));
++                        if (r < 0)
++                                break;
++
++                        r = seccomp_rule_add_exact(
++                                        seccomp,
++                                        SCMP_ACT_ERRNO(EPERM),
++                                        SCMP_SYS(mkdirat),
++                                        1,
++                                        SCMP_A2(SCMP_CMP_MASKED_EQ, m, m));
++                        if (r < 0)
++                                break;
++
++                        r = seccomp_rule_add_exact(
++                                        seccomp,
++                                        SCMP_ACT_ERRNO(EPERM),
++                                        SCMP_SYS(mknod),
++                                        1,
++                                        SCMP_A1(SCMP_CMP_MASKED_EQ, m, m));
++                        if (r < 0)
++                                break;
++
++                        r = seccomp_rule_add_exact(
++                                        seccomp,
++                                        SCMP_ACT_ERRNO(EPERM),
++                                        SCMP_SYS(mknodat),
++                                        1,
++                                        SCMP_A2(SCMP_CMP_MASKED_EQ, m, m));
++                        if (r < 0)
++                                break;
++
++                        r = seccomp_rule_add_exact(
++                                        seccomp,
++                                        SCMP_ACT_ERRNO(EPERM),
++                                        SCMP_SYS(open),
++                                        2,
++                                        SCMP_A1(SCMP_CMP_MASKED_EQ, O_CREAT, O_CREAT),
++                                        SCMP_A2(SCMP_CMP_MASKED_EQ, m, m));
++                        if (r < 0)
++                                break;
++
++                        r = seccomp_rule_add_exact(
++                                        seccomp,
++                                        SCMP_ACT_ERRNO(EPERM),
++                                        SCMP_SYS(openat),
++                                        2,
++                                        SCMP_A2(SCMP_CMP_MASKED_EQ, O_CREAT, O_CREAT),
++                                        SCMP_A3(SCMP_CMP_MASKED_EQ, m, m));
++                        if (r < 0)
++                                break;
++
++                        r = seccomp_rule_add_exact(
++                                        seccomp,
++                                        SCMP_ACT_ERRNO(EPERM),
++                                        SCMP_SYS(creat),
++                                        1,
++                                        SCMP_A1(SCMP_CMP_MASKED_EQ, m, m));
++                        if (r < 0)
++                                break;
++                }
++                if (r < 0) {
++                        log_debug_errno(r, "Failed to add suid/sgid rule for architecture %s, skipping: %m", seccomp_arch_to_string(arch));
++                        continue;
++                }
++
++                r = seccomp_load(seccomp);
++                if (IN_SET(r, -EPERM, -EACCES))
++                        return r;
++                if (r < 0)
++                        log_debug_errno(r, "Failed to apply suid/sgid restrictions for architecture %s, skipping: %m", seccomp_arch_to_string(arch));
++        }
++
++        return 0;
++}
+diff --git a/src/shared/seccomp-util.h b/src/shared/seccomp-util.h
+index d8a36c4e21..602f092255 100644
+--- a/src/shared/seccomp-util.h
++++ b/src/shared/seccomp-util.h
+@@ -85,6 +85,7 @@ int seccomp_restrict_address_families(Set *address_families, bool whitelist);
+ int seccomp_restrict_realtime(void);
+ int seccomp_memory_deny_write_execute(void);
+ int seccomp_lock_personality(unsigned long personality);
++int seccomp_restrict_suid_sgid(void);
+ 
+ extern const uint32_t seccomp_local_archs[];
+ 
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 <jsynacek@redhat.com>
+Date: Tue, 12 Nov 2019 13:27:49 +0100
+Subject: [PATCH] test: add test case for restrict_suid_sgid()
+
+(cherry picked from commit 167fc10cb352b04d442c9010dab4f8dc24219749)
+Related: #1687512
+---
+ src/test/test-seccomp.c | 226 ++++++++++++++++++++++++++++++++++++++++
+ 1 file changed, 226 insertions(+)
+
+diff --git a/src/test/test-seccomp.c b/src/test/test-seccomp.c
+index d177515ac7..4021a06e0e 100644
+--- a/src/test/test-seccomp.c
++++ b/src/test/test-seccomp.c
+@@ -17,9 +17,11 @@
+ #include "nsflags.h"
+ #include "process-util.h"
+ #include "raw-clone.h"
++#include "rm-rf.h"
+ #include "seccomp-util.h"
+ #include "set.h"
+ #include "string-util.h"
++#include "umask-util.h"
+ #include "util.h"
+ #include "virt.h"
+ 
+@@ -666,6 +668,229 @@ static void test_filter_sets_ordered(void) {
+         }
+ }
+ 
++static int mkostemp_safe(char *pattern) {
++        _unused_ _cleanup_umask_ mode_t u = umask(0077);
++        int fd;
++
++        assert(pattern);
++
++        fd = mkostemp(pattern, O_CLOEXEC);
++        if (fd < 0)
++                return -errno;
++
++        return fd;
++}
++
++static int real_open(const char *path, int flags, mode_t mode) {
++        /* glibc internally calls openat() when open() is requested. Let's hence define our own wrapper for
++         * testing purposes that calls the real syscall, on architectures where SYS_open is defined. On
++         * other architectures, let's just fall back to the glibc call. */
++
++#ifdef SYS_open
++        return (int) syscall(SYS_open, path, flags, mode);
++#else
++        return open(path, flags, mode);
++#endif
++}
++
++static void test_restrict_suid_sgid(void) {
++        pid_t pid;
++
++        log_info("/* %s */", __func__);
++
++        if (!is_seccomp_available()) {
++                log_notice("Seccomp not available, skipping %s", __func__);
++                return;
++        }
++        if (geteuid() != 0) {
++                log_notice("Not root, skipping %s", __func__);
++                return;
++        }
++
++        pid = fork();
++        assert_se(pid >= 0);
++
++        if (pid == 0) {
++                char path[] = "/tmp/suidsgidXXXXXX", dir[] = "/tmp/suidsgiddirXXXXXX";
++                int fd = -1, k = -1;
++                const char *z;
++
++                fd = mkostemp_safe(path);
++                assert_se(fd >= 0);
++
++                assert_se(mkdtemp(dir));
++                z = strjoina(dir, "/test");
++
++                assert_se(chmod(path, 0755 | S_ISUID) >= 0);
++                assert_se(chmod(path, 0755 | S_ISGID) >= 0);
++                assert_se(chmod(path, 0755 | S_ISGID | S_ISUID) >= 0);
++                assert_se(chmod(path, 0755) >= 0);
++
++                assert_se(fchmod(fd, 0755 | S_ISUID) >= 0);
++                assert_se(fchmod(fd, 0755 | S_ISGID) >= 0);
++                assert_se(fchmod(fd, 0755 | S_ISGID | S_ISUID) >= 0);
++                assert_se(fchmod(fd, 0755) >= 0);
++
++                assert_se(fchmodat(AT_FDCWD, path, 0755 | S_ISUID, 0) >= 0);
++                assert_se(fchmodat(AT_FDCWD, path, 0755 | S_ISGID, 0) >= 0);
++                assert_se(fchmodat(AT_FDCWD, path, 0755 | S_ISGID | S_ISUID, 0) >= 0);
++                assert_se(fchmodat(AT_FDCWD, path, 0755, 0) >= 0);
++
++                k = real_open(z, O_CREAT|O_RDWR|O_CLOEXEC|O_EXCL, 0644 | S_ISUID);
++                k = safe_close(k);
++                assert_se(unlink(z) >= 0);
++
++                k = real_open(z, O_CREAT|O_RDWR|O_CLOEXEC|O_EXCL, 0644 | S_ISGID);
++                k = safe_close(k);
++                assert_se(unlink(z) >= 0);
++
++                k = real_open(z, O_CREAT|O_RDWR|O_CLOEXEC|O_EXCL, 0644 | S_ISUID | S_ISGID);
++                k = safe_close(k);
++                assert_se(unlink(z) >= 0);
++
++                k = real_open(z, O_CREAT|O_RDWR|O_CLOEXEC|O_EXCL, 0644);
++                k = safe_close(k);
++                assert_se(unlink(z) >= 0);
++
++                k = creat(z, 0644 | S_ISUID);
++                k = safe_close(k);
++                assert_se(unlink(z) >= 0);
++
++                k = creat(z, 0644 | S_ISGID);
++                k = safe_close(k);
++                assert_se(unlink(z) >= 0);
++
++                k = creat(z, 0644 | S_ISUID | S_ISGID);
++                k = safe_close(k);
++                assert_se(unlink(z) >= 0);
++
++                k = creat(z, 0644);
++                k = safe_close(k);
++                assert_se(unlink(z) >= 0);
++
++                k = openat(AT_FDCWD, z, O_CREAT|O_RDWR|O_CLOEXEC|O_EXCL, 0644 | S_ISUID);
++                k = safe_close(k);
++                assert_se(unlink(z) >= 0);
++
++                k = openat(AT_FDCWD, z, O_CREAT|O_RDWR|O_CLOEXEC|O_EXCL, 0644 | S_ISGID);
++                k = safe_close(k);
++                assert_se(unlink(z) >= 0);
++
++                k = openat(AT_FDCWD, z, O_CREAT|O_RDWR|O_CLOEXEC|O_EXCL, 0644 | S_ISUID | S_ISGID);
++                k = safe_close(k);
++                assert_se(unlink(z) >= 0);
++
++                k = openat(AT_FDCWD, z, O_CREAT|O_RDWR|O_CLOEXEC|O_EXCL, 0644);
++                k = safe_close(k);
++                assert_se(unlink(z) >= 0);
++
++                assert_se(mkdir(z, 0755 | S_ISUID) >= 0);
++                assert_se(rmdir(z) >= 0);
++                assert_se(mkdir(z, 0755 | S_ISGID) >= 0);
++                assert_se(rmdir(z) >= 0);
++                assert_se(mkdir(z, 0755 | S_ISUID | S_ISGID) >= 0);
++                assert_se(rmdir(z) >= 0);
++                assert_se(mkdir(z, 0755) >= 0);
++                assert_se(rmdir(z) >= 0);
++
++                assert_se(mkdirat(AT_FDCWD, z, 0755 | S_ISUID) >= 0);
++                assert_se(rmdir(z) >= 0);
++                assert_se(mkdirat(AT_FDCWD, z, 0755 | S_ISGID) >= 0);
++                assert_se(rmdir(z) >= 0);
++                assert_se(mkdirat(AT_FDCWD, z, 0755 | S_ISUID | S_ISGID) >= 0);
++                assert_se(rmdir(z) >= 0);
++                assert_se(mkdirat(AT_FDCWD, z, 0755) >= 0);
++                assert_se(rmdir(z) >= 0);
++
++                assert_se(mknod(z, S_IFREG | 0755 | S_ISUID, 0) >= 0);
++                assert_se(unlink(z) >= 0);
++                assert_se(mknod(z, S_IFREG | 0755 | S_ISGID, 0) >= 0);
++                assert_se(unlink(z) >= 0);
++                assert_se(mknod(z, S_IFREG | 0755 | S_ISUID | S_ISGID, 0) >= 0);
++                assert_se(unlink(z) >= 0);
++                assert_se(mknod(z, S_IFREG | 0755, 0) >= 0);
++                assert_se(unlink(z) >= 0);
++
++                assert_se(mknodat(AT_FDCWD, z, S_IFREG | 0755 | S_ISUID, 0) >= 0);
++                assert_se(unlink(z) >= 0);
++                assert_se(mknodat(AT_FDCWD, z, S_IFREG | 0755 | S_ISGID, 0) >= 0);
++                assert_se(unlink(z) >= 0);
++                assert_se(mknodat(AT_FDCWD, z, S_IFREG | 0755 | S_ISUID | S_ISGID, 0) >= 0);
++                assert_se(unlink(z) >= 0);
++                assert_se(mknodat(AT_FDCWD, z, S_IFREG | 0755, 0) >= 0);
++                assert_se(unlink(z) >= 0);
++
++                assert_se(seccomp_restrict_suid_sgid() >= 0);
++
++                assert_se(chmod(path, 0775 | S_ISUID) < 0 && errno == EPERM);
++                assert_se(chmod(path, 0775 | S_ISGID) < 0  && errno == EPERM);
++                assert_se(chmod(path, 0775 | S_ISGID | S_ISUID) < 0  && errno == EPERM);
++                assert_se(chmod(path, 0775) >= 0);
++
++                assert_se(fchmod(fd, 0775 | S_ISUID) < 0 && errno == EPERM);
++                assert_se(fchmod(fd, 0775 | S_ISGID) < 0  && errno == EPERM);
++                assert_se(fchmod(fd, 0775 | S_ISGID | S_ISUID) < 0  && errno == EPERM);
++                assert_se(fchmod(fd, 0775) >= 0);
++
++                assert_se(fchmodat(AT_FDCWD, path, 0755 | S_ISUID, 0) < 0 && errno == EPERM);
++                assert_se(fchmodat(AT_FDCWD, path, 0755 | S_ISGID, 0) < 0 && errno == EPERM);
++                assert_se(fchmodat(AT_FDCWD, path, 0755 | S_ISGID | S_ISUID, 0) < 0 && errno == EPERM);
++                assert_se(fchmodat(AT_FDCWD, path, 0755, 0) >= 0);
++
++                assert_se(real_open(z, O_CREAT|O_RDWR|O_CLOEXEC|O_EXCL, 0644 | S_ISUID) < 0 && errno == EPERM);
++                assert_se(real_open(z, O_CREAT|O_RDWR|O_CLOEXEC|O_EXCL, 0644 | S_ISGID) < 0 && errno == EPERM);
++                assert_se(real_open(z, O_CREAT|O_RDWR|O_CLOEXEC|O_EXCL, 0644 | S_ISUID | S_ISGID) < 0 && errno == EPERM);
++                k = real_open(z, O_CREAT|O_RDWR|O_CLOEXEC|O_EXCL, 0644);
++                k = safe_close(k);
++                assert_se(unlink(z) >= 0);
++
++                assert_se(creat(z, 0644 | S_ISUID) < 0 && errno == EPERM);
++                assert_se(creat(z, 0644 | S_ISGID) < 0 && errno == EPERM);
++                assert_se(creat(z, 0644 | S_ISUID | S_ISGID) < 0 && errno == EPERM);
++                k = creat(z, 0644);
++                k = safe_close(k);
++                assert_se(unlink(z) >= 0);
++
++                assert_se(openat(AT_FDCWD, z, O_CREAT|O_RDWR|O_CLOEXEC|O_EXCL, 0644 | S_ISUID) < 0 && errno == EPERM);
++                assert_se(openat(AT_FDCWD, z, O_CREAT|O_RDWR|O_CLOEXEC|O_EXCL, 0644 | S_ISGID) < 0 && errno == EPERM);
++                assert_se(openat(AT_FDCWD, z, O_CREAT|O_RDWR|O_CLOEXEC|O_EXCL, 0644 | S_ISUID | S_ISGID) < 0 && errno == EPERM);
++                k = openat(AT_FDCWD, z, O_CREAT|O_RDWR|O_CLOEXEC|O_EXCL, 0644);
++                k = safe_close(k);
++                assert_se(unlink(z) >= 0);
++
++                assert_se(mkdir(z, 0755 | S_ISUID) < 0 && errno == EPERM);
++                assert_se(mkdir(z, 0755 | S_ISGID) < 0 && errno == EPERM);
++                assert_se(mkdir(z, 0755 | S_ISUID | S_ISGID) < 0 && errno == EPERM);
++                assert_se(mkdir(z, 0755) >= 0);
++                assert_se(rmdir(z) >= 0);
++
++                assert_se(mkdirat(AT_FDCWD, z, 0755 | S_ISUID) < 0 && errno == EPERM);
++                assert_se(mkdirat(AT_FDCWD, z, 0755 | S_ISGID) < 0 && errno == EPERM);
++                assert_se(mkdirat(AT_FDCWD, z, 0755 | S_ISUID | S_ISGID) < 0 && errno == EPERM);
++                assert_se(mkdirat(AT_FDCWD, z, 0755) >= 0);
++                assert_se(rmdir(z) >= 0);
++
++                assert_se(mknod(z, S_IFREG | 0755 | S_ISUID, 0) < 0 && errno == EPERM);
++                assert_se(mknod(z, S_IFREG | 0755 | S_ISGID, 0) < 0 && errno == EPERM);
++                assert_se(mknod(z, S_IFREG | 0755 | S_ISUID | S_ISGID, 0) < 0 && errno == EPERM);
++                assert_se(mknod(z, S_IFREG | 0755, 0) >= 0);
++                assert_se(unlink(z) >= 0);
++
++                assert_se(mknodat(AT_FDCWD, z, S_IFREG | 0755 | S_ISUID, 0) < 0 && errno == EPERM);
++                assert_se(mknodat(AT_FDCWD, z, S_IFREG | 0755 | S_ISGID, 0) < 0 && errno == EPERM);
++                assert_se(mknodat(AT_FDCWD, z, S_IFREG | 0755 | S_ISUID | S_ISGID, 0) < 0 && errno == EPERM);
++                assert_se(mknodat(AT_FDCWD, z, S_IFREG | 0755, 0) >= 0);
++                assert_se(unlink(z) >= 0);
++
++                assert_se(unlink(path) >= 0);
++                assert_se(rm_rf(dir, REMOVE_ROOT|REMOVE_PHYSICAL) >= 0);
++
++                _exit(EXIT_SUCCESS);
++        }
++
++        assert_se(wait_for_terminate_and_check("suidsgidseccomp", pid, WAIT_LOG) == EXIT_SUCCESS);
++}
++
+ int main(int argc, char *argv[]) {
+ 
+         log_set_max_level(LOG_DEBUG);
+@@ -684,6 +909,7 @@ int main(int argc, char *argv[]) {
+         test_load_syscall_filter_set_raw();
+         test_lock_personality();
+         test_filter_sets_ordered();
++        test_restrict_suid_sgid();
+ 
+         return 0;
+ }
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 <lennart@poettering.net>
+Date: Wed, 20 Mar 2019 19:09:09 +0100
+Subject: [PATCH] core: expose SUID/SGID restriction as new unit setting
+ RestrictSUIDSGID=
+
+(cherry picked from commit f69567cbe26d09eac9d387c0be0fc32c65a83ada)
+Related: #1687512
+---
+ src/core/dbus-execute.c                     |  4 ++++
+ src/core/execute.c                          | 22 +++++++++++++++++++++
+ src/core/execute.h                          |  1 +
+ src/core/load-fragment-gperf.gperf.m4       |  2 ++
+ src/shared/bus-unit-util.c                  |  2 +-
+ test/fuzz/fuzz-unit-file/directives.service |  1 +
+ 6 files changed, 31 insertions(+), 1 deletion(-)
+
+diff --git a/src/core/dbus-execute.c b/src/core/dbus-execute.c
+index 198f149210..e7c0b893d1 100644
+--- a/src/core/dbus-execute.c
++++ b/src/core/dbus-execute.c
+@@ -815,6 +815,7 @@ const sd_bus_vtable bus_exec_vtable[] = {
+         SD_BUS_PROPERTY("ConfigurationDirectory", "as", NULL, offsetof(ExecContext, directories[EXEC_DIRECTORY_CONFIGURATION].paths), SD_BUS_VTABLE_PROPERTY_CONST),
+         SD_BUS_PROPERTY("MemoryDenyWriteExecute", "b", bus_property_get_bool, offsetof(ExecContext, memory_deny_write_execute), SD_BUS_VTABLE_PROPERTY_CONST),
+         SD_BUS_PROPERTY("RestrictRealtime", "b", bus_property_get_bool, offsetof(ExecContext, restrict_realtime), SD_BUS_VTABLE_PROPERTY_CONST),
++        SD_BUS_PROPERTY("RestrictSUIDSGID", "b", bus_property_get_bool, offsetof(ExecContext, restrict_suid_sgid), SD_BUS_VTABLE_PROPERTY_CONST),
+         SD_BUS_PROPERTY("RestrictNamespaces", "t", bus_property_get_ulong, offsetof(ExecContext, restrict_namespaces), SD_BUS_VTABLE_PROPERTY_CONST),
+         SD_BUS_PROPERTY("BindPaths", "a(ssbt)", property_get_bind_paths, 0, SD_BUS_VTABLE_PROPERTY_CONST),
+         SD_BUS_PROPERTY("BindReadOnlyPaths", "a(ssbt)", property_get_bind_paths, 0, SD_BUS_VTABLE_PROPERTY_CONST),
+@@ -1179,6 +1180,9 @@ int bus_exec_context_set_transient_property(
+         if (streq(name, "RestrictRealtime"))
+                 return bus_set_transient_bool(u, name, &c->restrict_realtime, message, flags, error);
+ 
++        if (streq(name, "RestrictSUIDSGID"))
++                return bus_set_transient_bool(u, name, &c->restrict_suid_sgid, message, flags, error);
++
+         if (streq(name, "DynamicUser"))
+                 return bus_set_transient_bool(u, name, &c->dynamic_user, message, flags, error);
+ 
+diff --git a/src/core/execute.c b/src/core/execute.c
+index 56aa89e1ec..f012023224 100644
+--- a/src/core/execute.c
++++ b/src/core/execute.c
+@@ -1366,6 +1366,7 @@ static bool context_has_no_new_privileges(const ExecContext *c) {
+         return context_has_address_families(c) ||
+                 c->memory_deny_write_execute ||
+                 c->restrict_realtime ||
++                c->restrict_suid_sgid ||
+                 exec_context_restrict_namespaces_set(c) ||
+                 c->protect_kernel_tunables ||
+                 c->protect_kernel_modules ||
+@@ -1470,6 +1471,19 @@ static int apply_restrict_realtime(const Unit* u, const ExecContext *c) {
+         return seccomp_restrict_realtime();
+ }
+ 
++static int apply_restrict_suid_sgid(const Unit* u, const ExecContext *c) {
++        assert(u);
++        assert(c);
++
++        if (!c->restrict_suid_sgid)
++                return 0;
++
++        if (skip_seccomp_unavailable(u, "RestrictSUIDSGID="))
++                return 0;
++
++        return seccomp_restrict_suid_sgid();
++}
++
+ static int apply_protect_sysctl(const Unit *u, const ExecContext *c) {
+         assert(u);
+         assert(c);
+@@ -3404,6 +3418,12 @@ static int exec_child(
+                         return log_unit_error_errno(unit, r, "Failed to apply realtime restrictions: %m");
+                 }
+ 
++                r = apply_restrict_suid_sgid(unit, context);
++                if (r < 0) {
++                        *exit_status = EXIT_SECCOMP;
++                        return log_unit_error_errno(unit, r, "Failed to apply SUID/SGID restrictions: %m");
++                }
++
+                 r = apply_restrict_namespaces(unit, context);
+                 if (r < 0) {
+                         *exit_status = EXIT_SECCOMP;
+@@ -4023,6 +4043,7 @@ void exec_context_dump(const ExecContext *c, FILE* f, const char *prefix) {
+                 "%sIgnoreSIGPIPE: %s\n"
+                 "%sMemoryDenyWriteExecute: %s\n"
+                 "%sRestrictRealtime: %s\n"
++                "%sRestrictSUIDSGID: %s\n"
+                 "%sKeyringMode: %s\n",
+                 prefix, c->umask,
+                 prefix, c->working_directory ? c->working_directory : "/",
+@@ -4041,6 +4062,7 @@ void exec_context_dump(const ExecContext *c, FILE* f, const char *prefix) {
+                 prefix, yes_no(c->ignore_sigpipe),
+                 prefix, yes_no(c->memory_deny_write_execute),
+                 prefix, yes_no(c->restrict_realtime),
++                prefix, yes_no(c->restrict_suid_sgid),
+                 prefix, exec_keyring_mode_to_string(c->keyring_mode));
+ 
+         if (c->root_image)
+diff --git a/src/core/execute.h b/src/core/execute.h
+index b2eb55f8f5..2266355962 100644
+--- a/src/core/execute.h
++++ b/src/core/execute.h
+@@ -245,6 +245,7 @@ struct ExecContext {
+          * that the autofs logic detects that it belongs to us and we
+          * don't enter a trigger loop. */
+         bool same_pgrp;
++        bool restrict_suid_sgid;
+ 
+         unsigned long personality;
+         bool lock_personality;
+diff --git a/src/core/load-fragment-gperf.gperf.m4 b/src/core/load-fragment-gperf.gperf.m4
+index cdf4d14c4e..49e938d0ce 100644
+--- a/src/core/load-fragment-gperf.gperf.m4
++++ b/src/core/load-fragment-gperf.gperf.m4
+@@ -76,6 +76,7 @@ $1.SystemCallErrorNumber,        config_parse_syscall_errno,         0,
+ $1.MemoryDenyWriteExecute,       config_parse_bool,                  0,                             offsetof($1, exec_context.memory_deny_write_execute)
+ $1.RestrictNamespaces,           config_parse_restrict_namespaces,   0,                             offsetof($1, exec_context)
+ $1.RestrictRealtime,             config_parse_bool,                  0,                             offsetof($1, exec_context.restrict_realtime)
++$1.RestrictSUIDSGID,             config_parse_bool,                  0,                             offsetof($1, exec_context.restrict_suid_sgid)
+ $1.RestrictAddressFamilies,      config_parse_address_families,      0,                             offsetof($1, exec_context)
+ $1.LockPersonality,              config_parse_bool,                  0,                             offsetof($1, exec_context.lock_personality)',
+ `$1.SystemCallFilter,            config_parse_warn_compat,           DISABLED_CONFIGURATION,        0
+@@ -84,6 +85,7 @@ $1.SystemCallErrorNumber,        config_parse_warn_compat,           DISABLED_CO
+ $1.MemoryDenyWriteExecute,       config_parse_warn_compat,           DISABLED_CONFIGURATION,        0
+ $1.RestrictNamespaces,           config_parse_warn_compat,           DISABLED_CONFIGURATION,        0
+ $1.RestrictRealtime,             config_parse_warn_compat,           DISABLED_CONFIGURATION,        0
++$1.RestrictSUIDSGID,             config_parse_warn_compat,           DISABLED_CONFIGURATION         0
+ $1.RestrictAddressFamilies,      config_parse_warn_compat,           DISABLED_CONFIGURATION,        0
+ $1.LockPersonality,              config_parse_warn_compat,           DISABLED_CONFIGURATION,        0')
+ $1.LimitCPU,                     config_parse_rlimit,                RLIMIT_CPU,                    offsetof($1, exec_context.rlimit)
+diff --git a/src/shared/bus-unit-util.c b/src/shared/bus-unit-util.c
+index 055edd6e22..3c42e97b7a 100644
+--- a/src/shared/bus-unit-util.c
++++ b/src/shared/bus-unit-util.c
+@@ -697,7 +697,7 @@ static int bus_append_execute_property(sd_bus_message *m, const char *field, con
+                        "PrivateMounts", "NoNewPrivileges", "SyslogLevelPrefix",
+                        "MemoryDenyWriteExecute", "RestrictRealtime", "DynamicUser", "RemoveIPC",
+                        "ProtectKernelTunables", "ProtectKernelModules", "ProtectControlGroups",
+-                       "MountAPIVFS", "CPUSchedulingResetOnFork", "LockPersonality"))
++                       "MountAPIVFS", "CPUSchedulingResetOnFork", "LockPersonality" "RestrictSUIDSGID"))
+ 
+                 return bus_append_parse_boolean(m, field, eq);
+ 
+diff --git a/test/fuzz/fuzz-unit-file/directives.service b/test/fuzz/fuzz-unit-file/directives.service
+index d8d1fc68b8..eab1820e20 100644
+--- a/test/fuzz/fuzz-unit-file/directives.service
++++ b/test/fuzz/fuzz-unit-file/directives.service
+@@ -849,6 +849,7 @@ ReserveVT=
+ RestrictAddressFamilies=
+ RestrictNamespaces=
+ RestrictRealtime=
++RestrictSUIDSGID=
+ RuntimeDirectory=
+ RuntimeDirectoryMode=
+ RuntimeDirectoryPreserve=
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 <lennart@poettering.net>
+Date: Wed, 20 Mar 2019 19:20:35 +0100
+Subject: [PATCH] analyze: check for RestrictSUIDSGID= in "systemd-analyze
+ security"
+
+And let's give it a heigh weight, since it pretty much can be used for
+bad things only.
+
+(cherry picked from commit 9d880b70ba5c6ca83c82952f4c90e86e56c7b70c)
+Related: #1687512
+---
+ src/analyze/analyze-security.c | 12 ++++++++++++
+ 1 file changed, 12 insertions(+)
+
+diff --git a/src/analyze/analyze-security.c b/src/analyze/analyze-security.c
+index eec040d5c3..969101c57b 100644
+--- a/src/analyze/analyze-security.c
++++ b/src/analyze/analyze-security.c
+@@ -69,6 +69,7 @@ struct security_info {
+ 
+         uint64_t restrict_namespaces;
+         bool restrict_realtime;
++        bool restrict_suid_sgid;
+ 
+         char *root_directory;
+         char *root_image;
+@@ -1130,6 +1131,16 @@ static const struct security_assessor security_assessor_table[] = {
+                 .assess = assess_bool,
+                 .offset = offsetof(struct security_info, restrict_realtime),
+         },
++        {
++                .id = "RestrictSUIDSGID=",
++                .url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#RestrictSUIDSGID=",
++                .description_good = "SUID/SGID file creation by service is restricted",
++                .description_bad = "Service may create SUID/SGID files",
++                .weight = 1000,
++                .range = 1,
++                .assess = assess_bool,
++                .offset = offsetof(struct security_info, restrict_suid_sgid),
++        },
+         {
+                 .id = "RestrictNamespaces=~CLONE_NEWUSER",
+                 .url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#RestrictNamespaces=",
+@@ -1862,6 +1873,7 @@ static int acquire_security_info(sd_bus *bus, const char *name, struct security_
+                 { "RestrictAddressFamilies", "(bas)",   property_read_restrict_address_families, 0                                                         },
+                 { "RestrictNamespaces",      "t",       NULL,                                    offsetof(struct security_info, restrict_namespaces)       },
+                 { "RestrictRealtime",        "b",       NULL,                                    offsetof(struct security_info, restrict_realtime)         },
++                { "RestrictSUIDSGID",        "b",       NULL,                                    offsetof(struct security_info, restrict_suid_sgid)        },
+                 { "RootDirectory",           "s",       NULL,                                    offsetof(struct security_info, root_directory)            },
+                 { "RootImage",               "s",       NULL,                                    offsetof(struct security_info, root_image)                },
+                 { "SupplementaryGroups",     "as",      NULL,                                    offsetof(struct security_info, supplementary_groups)      },
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 <lennart@poettering.net>
+Date: Wed, 20 Mar 2019 19:45:32 +0100
+Subject: [PATCH] man: document the new RestrictSUIDSGID= setting
+
+(cherry picked from commit 7445db6eb70e8d5989f481d0c5a08ace7047ae5b)
+Related: #1687512
+---
+ doc/TRANSIENT-SETTINGS.md |  1 +
+ man/systemd.exec.xml      | 41 +++++++++++++++++++++++++++------------
+ 2 files changed, 30 insertions(+), 12 deletions(-)
+
+diff --git a/doc/TRANSIENT-SETTINGS.md b/doc/TRANSIENT-SETTINGS.md
+index 0ea444b133..c2b5c0dcce 100644
+--- a/doc/TRANSIENT-SETTINGS.md
++++ b/doc/TRANSIENT-SETTINGS.md
+@@ -149,6 +149,7 @@ All execution-related settings are available for transient units.
+ ✓ MemoryDenyWriteExecute=
+ ✓ RestrictNamespaces=
+ ✓ RestrictRealtime=
++✓ RestrictSUIDSGID=
+ ✓ RestrictAddressFamilies=
+ ✓ LockPersonality=
+ ✓ LimitCPU=
+diff --git a/man/systemd.exec.xml b/man/systemd.exec.xml
+index 87fb8b34f4..45ed1864f8 100644
+--- a/man/systemd.exec.xml
++++ b/man/systemd.exec.xml
+@@ -348,18 +348,19 @@ CapabilityBoundingSet=~CAP_B CAP_C</programlisting>
+       <varlistentry>
+         <term><varname>NoNewPrivileges=</varname></term>
+ 
+-        <listitem><para>Takes a boolean argument. If true, ensures that the service process and all its children can
+-        never gain new privileges through <function>execve()</function> (e.g. via setuid or setgid bits, or filesystem
+-        capabilities). This is the simplest and most effective way to ensure that a process and its children can never
+-        elevate privileges again. Defaults to false, but certain settings override this and ignore the value of this
+-        setting.  This is the case when <varname>SystemCallFilter=</varname>,
+-        <varname>SystemCallArchitectures=</varname>, <varname>RestrictAddressFamilies=</varname>,
+-        <varname>RestrictNamespaces=</varname>, <varname>PrivateDevices=</varname>,
+-        <varname>ProtectKernelTunables=</varname>, <varname>ProtectKernelModules=</varname>,
+-        <varname>MemoryDenyWriteExecute=</varname>, <varname>RestrictRealtime=</varname>, or
+-        <varname>LockPersonality=</varname> are specified. Note that even if this setting is overridden by them,
+-        <command>systemctl show</command> shows the original value of this setting. Also see
+-        <ulink url="https://www.kernel.org/doc/html/latest/userspace-api/no_new_privs.html">No New Privileges
++        <listitem><para>Takes a boolean argument. If true, ensures that the service process and all its
++        children can never gain new privileges through <function>execve()</function> (e.g. via setuid or
++        setgid bits, or filesystem capabilities). This is the simplest and most effective way to ensure that
++        a process and its children can never elevate privileges again. Defaults to false, but certain
++        settings override this and ignore the value of this setting.  This is the case when
++        <varname>SystemCallFilter=</varname>, <varname>SystemCallArchitectures=</varname>,
++        <varname>RestrictAddressFamilies=</varname>, <varname>RestrictNamespaces=</varname>,
++        <varname>PrivateDevices=</varname>, <varname>ProtectKernelTunables=</varname>,
++        <varname>ProtectKernelModules=</varname>, <varname>MemoryDenyWriteExecute=</varname>,
++        <varname>RestrictRealtime=</varname>, <varname>RestrictSUIDSGID=</varname> or
++        <varname>LockPersonality=</varname> are specified. Note that even if this setting is overridden by
++        them, <command>systemctl show</command> shows the original value of this setting. Also see <ulink
++        url="https://www.kernel.org/doc/html/latest/userspace-api/no_new_privs.html">No New Privileges
+         Flag</ulink>.  </para></listitem>
+       </varlistentry>
+ 
+@@ -1274,6 +1275,22 @@ RestrictNamespaces=~cgroup net</programlisting>
+         that actually require them. Defaults to off.</para></listitem>
+       </varlistentry>
+ 
++      <varlistentry>
++        <term><varname>RestrictSUIDSGID=</varname></term>
++
++        <listitem><para>Takes a boolean argument. If set, any attempts to set the set-user-ID (SUID) or
++        set-group-ID (SGID) bits on files or directories will be denied (for details on these bits see
++        <citerefentry
++        project='man-pages'><refentrytitle>inode</refentrytitle><manvolnum>7</manvolnum></citerefentry>). If
++        running in user mode, or in system mode, but without the <constant>CAP_SYS_ADMIN</constant>
++        capability (e.g. setting <varname>User=</varname>), <varname>NoNewPrivileges=yes</varname> is
++        implied. As the SUID/SGID bits are mechanisms to elevate privileges, and allows users to acquire the
++        identity of other users, it is recommended to restrict creation of SUID/SGID files to the few
++        programs that actually require them. Note that this restricts marking of any type of file system
++        object with these bits, including both regular files and directories (where the SGID is a different
++        meaning than for files, see documentation). Defaults to off.</para></listitem>
++      </varlistentry>
++
+       <varlistentry>
+         <term><varname>RemoveIPC=</varname></term>
+ 
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 <lennart@poettering.net>
+Date: Wed, 20 Mar 2019 19:52:20 +0100
+Subject: [PATCH] units: turn on RestrictSUIDSGID= in most of our long-running
+ daemons
+
+(cherry picked from commit 62aa29247c3d74bcec0607c347f2be23cd90675d)
+Related: #1687512
+---
+ units/systemd-coredump@.service.in      | 1 +
+ units/systemd-hostnamed.service.in      | 1 +
+ units/systemd-journal-remote.service.in | 1 +
+ units/systemd-journald.service.in       | 1 +
+ units/systemd-localed.service.in        | 1 +
+ units/systemd-logind.service.in         | 1 +
+ units/systemd-networkd.service.in       | 1 +
+ units/systemd-resolved.service.in       | 1 +
+ units/systemd-timedated.service.in      | 1 +
+ units/systemd-timesyncd.service.in      | 1 +
+ units/systemd-udevd.service.in          | 3 ++-
+ 11 files changed, 12 insertions(+), 1 deletion(-)
+
+diff --git a/units/systemd-coredump@.service.in b/units/systemd-coredump@.service.in
+index 68a68a5055..d69ebd8b24 100644
+--- a/units/systemd-coredump@.service.in
++++ b/units/systemd-coredump@.service.in
+@@ -33,6 +33,7 @@ MemoryDenyWriteExecute=yes
+ RestrictRealtime=yes
+ RestrictNamespaces=yes
+ RestrictAddressFamilies=AF_UNIX
++RestrictSUIDSGID=yes
+ SystemCallFilter=@system-service
+ SystemCallErrorNumber=EPERM
+ SystemCallArchitectures=native
+diff --git a/units/systemd-hostnamed.service.in b/units/systemd-hostnamed.service.in
+index 4e5470dd29..97d4e142bc 100644
+--- a/units/systemd-hostnamed.service.in
++++ b/units/systemd-hostnamed.service.in
+@@ -29,6 +29,7 @@ MemoryDenyWriteExecute=yes
+ RestrictRealtime=yes
+ RestrictNamespaces=yes
+ RestrictAddressFamilies=AF_UNIX
++RestrictSUIDSGID=yes
+ SystemCallFilter=@system-service sethostname
+ SystemCallErrorNumber=EPERM
+ SystemCallArchitectures=native
+diff --git a/units/systemd-journal-remote.service.in b/units/systemd-journal-remote.service.in
+index a94265f215..3c914f5a40 100644
+--- a/units/systemd-journal-remote.service.in
++++ b/units/systemd-journal-remote.service.in
+@@ -28,6 +28,7 @@ MemoryDenyWriteExecute=yes
+ RestrictRealtime=yes
+ RestrictNamespaces=yes
+ RestrictAddressFamilies=AF_UNIX AF_INET AF_INET6
++RestrictSUIDSGID=yes
+ SystemCallArchitectures=native
+ LockPersonality=yes
+ LogsDirectory=journal/remote
+diff --git a/units/systemd-journald.service.in b/units/systemd-journald.service.in
+index e109b25792..ab9ec35ff8 100644
+--- a/units/systemd-journald.service.in
++++ b/units/systemd-journald.service.in
+@@ -21,6 +21,7 @@ Sockets=systemd-journald.socket systemd-journald-dev-log.socket
+ ExecStart=@rootlibexecdir@/systemd-journald
+ Restart=always
+ RestartSec=0
++RestrictSUIDSGID=yes
+ StandardOutput=null
+ WatchdogSec=3min
+ FileDescriptorStoreMax=4224
+diff --git a/units/systemd-localed.service.in b/units/systemd-localed.service.in
+index ce043db154..b87d60e9eb 100644
+--- a/units/systemd-localed.service.in
++++ b/units/systemd-localed.service.in
+@@ -29,6 +29,7 @@ MemoryDenyWriteExecute=yes
+ RestrictRealtime=yes
+ RestrictNamespaces=yes
+ RestrictAddressFamilies=AF_UNIX
++RestrictSUIDSGID=yes
+ SystemCallFilter=@system-service
+ SystemCallErrorNumber=EPERM
+ SystemCallArchitectures=native
+diff --git a/units/systemd-logind.service.in b/units/systemd-logind.service.in
+index 6953fac55b..086338e03b 100644
+--- a/units/systemd-logind.service.in
++++ b/units/systemd-logind.service.in
+@@ -30,6 +30,7 @@ MemoryDenyWriteExecute=yes
+ RestrictRealtime=yes
+ RestrictNamespaces=yes
+ RestrictAddressFamilies=AF_UNIX AF_NETLINK
++RestrictSUIDSGID=yes
+ SystemCallFilter=@system-service
+ SystemCallErrorNumber=EPERM
+ SystemCallArchitectures=native
+diff --git a/units/systemd-networkd.service.in b/units/systemd-networkd.service.in
+index 371ab3a9cf..a0f34ac738 100644
+--- a/units/systemd-networkd.service.in
++++ b/units/systemd-networkd.service.in
+@@ -39,6 +39,7 @@ SystemCallFilter=@system-service
+ SystemCallErrorNumber=EPERM
+ SystemCallArchitectures=native
+ LockPersonality=yes
++RestrictSUIDSGID=yes
+ RuntimeDirectory=systemd/netif
+ RuntimeDirectoryPreserve=yes
+ 
+diff --git a/units/systemd-resolved.service.in b/units/systemd-resolved.service.in
+index aaed406ab2..6c2ad5ca86 100644
+--- a/units/systemd-resolved.service.in
++++ b/units/systemd-resolved.service.in
+@@ -41,6 +41,7 @@ SystemCallFilter=@system-service
+ SystemCallErrorNumber=EPERM
+ SystemCallArchitectures=native
+ LockPersonality=yes
++RestrictSUIDSGID=yes
+ RuntimeDirectory=systemd/resolve
+ RuntimeDirectoryPreserve=yes
+ 
+diff --git a/units/systemd-timedated.service.in b/units/systemd-timedated.service.in
+index 662b39557a..1da2bc4bb0 100644
+--- a/units/systemd-timedated.service.in
++++ b/units/systemd-timedated.service.in
+@@ -27,6 +27,7 @@ MemoryDenyWriteExecute=yes
+ RestrictRealtime=yes
+ RestrictNamespaces=yes
+ RestrictAddressFamilies=AF_UNIX
++RestrictSUIDSGID=yes
+ SystemCallFilter=@system-service @clock
+ SystemCallErrorNumber=EPERM
+ SystemCallArchitectures=native
+diff --git a/units/systemd-timesyncd.service.in b/units/systemd-timesyncd.service.in
+index 4a490b6e16..c2b9551726 100644
+--- a/units/systemd-timesyncd.service.in
++++ b/units/systemd-timesyncd.service.in
+@@ -37,6 +37,7 @@ MemoryDenyWriteExecute=yes
+ RestrictRealtime=yes
+ RestrictNamespaces=yes
+ RestrictAddressFamilies=AF_UNIX AF_INET AF_INET6
++RestrictSUIDSGID=yes
+ RuntimeDirectory=systemd/timesync
+ SystemCallFilter=@system-service @clock
+ SystemCallErrorNumber=EPERM
+diff --git a/units/systemd-udevd.service.in b/units/systemd-udevd.service.in
+index fd9ead3bb8..970cf0f290 100644
+--- a/units/systemd-udevd.service.in
++++ b/units/systemd-udevd.service.in
+@@ -27,8 +27,9 @@ WatchdogSec=3min
+ TasksMax=infinity
+ PrivateMounts=yes
+ MemoryDenyWriteExecute=yes
+-RestrictRealtime=yes
+ RestrictAddressFamilies=AF_UNIX AF_NETLINK AF_INET AF_INET6
++RestrictRealtime=yes
++RestrictSUIDSGID=yes
+ SystemCallFilter=@system-service @module @raw-io
+ SystemCallErrorNumber=EPERM
+ SystemCallArchitectures=native
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 <lennart@poettering.net>
+Date: Wed, 20 Mar 2019 20:19:38 +0100
+Subject: [PATCH] core: imply NNP and SUID/SGID restriction for DynamicUser=yes
+ service
+
+Let's be safe, rather than sorry. This way DynamicUser=yes services can
+neither take benefit of, nor create SUID/SGID binaries.
+
+Given that DynamicUser= is a recent addition only we should be able to
+get away with turning this on, even though this is strictly speaking a
+binary compatibility breakage.
+
+(cherry picked from commit bf65b7e0c9fc215897b676ab9a7c9d1c688143ba)
+Resolves: #1687512
+---
+ man/systemd.exec.xml | 16 ++++++++++------
+ src/core/unit.c      | 10 ++++++++--
+ 2 files changed, 18 insertions(+), 8 deletions(-)
+
+diff --git a/man/systemd.exec.xml b/man/systemd.exec.xml
+index 45ed1864f8..bdaed68162 100644
+--- a/man/systemd.exec.xml
++++ b/man/systemd.exec.xml
+@@ -229,7 +229,9 @@
+         created by the executed processes is bound to the runtime of the service, and hence the lifetime of the dynamic
+         user/group. Since <filename>/tmp</filename> and <filename>/var/tmp</filename> are usually the only
+         world-writable directories on a system this ensures that a unit making use of dynamic user/group allocation
+-        cannot leave files around after unit termination. Moreover <varname>ProtectSystem=strict</varname> and
++        cannot leave files around after unit termination. Furthermore <varname>NoNewPrivileges=</varname> and
++        <varname>RestrictSUIDSGID=</varname> are implicitly enabled to ensure that processes invoked cannot take benefit
++        or create SUID/SGID files or directories. Moreover <varname>ProtectSystem=strict</varname> and
+         <varname>ProtectHome=read-only</varname> are implied, thus prohibiting the service to write to arbitrary file
+         system locations. In order to allow the service to write to certain directories, they have to be whitelisted
+         using <varname>ReadWritePaths=</varname>, but care must be taken so that UID/GID recycling doesn't create
+@@ -357,11 +359,12 @@ CapabilityBoundingSet=~CAP_B CAP_C</programlisting>
+         <varname>RestrictAddressFamilies=</varname>, <varname>RestrictNamespaces=</varname>,
+         <varname>PrivateDevices=</varname>, <varname>ProtectKernelTunables=</varname>,
+         <varname>ProtectKernelModules=</varname>, <varname>MemoryDenyWriteExecute=</varname>,
+-        <varname>RestrictRealtime=</varname>, <varname>RestrictSUIDSGID=</varname> or
+-        <varname>LockPersonality=</varname> are specified. Note that even if this setting is overridden by
+-        them, <command>systemctl show</command> shows the original value of this setting. Also see <ulink
++        <varname>RestrictRealtime=</varname>, <varname>RestrictSUIDSGID=</varname>,
++        <varname>DynamicUser=</varname> or <varname>LockPersonality=</varname> are specified. Note that even
++        if this setting is overridden by them, <command>systemctl show</command> shows the original value of
++        this setting. Also see <ulink
+         url="https://www.kernel.org/doc/html/latest/userspace-api/no_new_privs.html">No New Privileges
+-        Flag</ulink>.  </para></listitem>
++        Flag</ulink>.</para></listitem>
+       </varlistentry>
+ 
+       <varlistentry>
+@@ -1288,7 +1291,8 @@ RestrictNamespaces=~cgroup net</programlisting>
+         identity of other users, it is recommended to restrict creation of SUID/SGID files to the few
+         programs that actually require them. Note that this restricts marking of any type of file system
+         object with these bits, including both regular files and directories (where the SGID is a different
+-        meaning than for files, see documentation). Defaults to off.</para></listitem>
++        meaning than for files, see documentation). This option is implied if <varname>DynamicUser=</varname>
++        is enabled. Defaults to off.</para></listitem>
+       </varlistentry>
+ 
+       <varlistentry>
+diff --git a/src/core/unit.c b/src/core/unit.c
+index 115739f4c6..e1f5e6f7bd 100644
+--- a/src/core/unit.c
++++ b/src/core/unit.c
+@@ -4161,14 +4161,20 @@ int unit_patch_contexts(Unit *u) {
+                                         return -ENOMEM;
+                         }
+ 
+-                        /* If the dynamic user option is on, let's make sure that the unit can't leave its UID/GID
+-                         * around in the file system or on IPC objects. Hence enforce a strict sandbox. */
++                        /* If the dynamic user option is on, let's make sure that the unit can't leave its
++                         * UID/GID around in the file system or on IPC objects. Hence enforce a strict
++                         * sandbox. */
+ 
+                         ec->private_tmp = true;
+                         ec->remove_ipc = true;
+                         ec->protect_system = PROTECT_SYSTEM_STRICT;
+                         if (ec->protect_home == PROTECT_HOME_NO)
+                                 ec->protect_home = PROTECT_HOME_READ_ONLY;
++
++                        /* Make sure this service can neither benefit from SUID/SGID binaries nor create
++                         * them. */
++                        ec->no_new_privileges = true;
++                        ec->restrict_suid_sgid = true;
+                 }
+         }
+ 
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 <phrdina@redhat.com>
+Date: Mon, 29 Jul 2019 17:50:05 +0200
+Subject: [PATCH] cgroup: introduce support for cgroup v2 CPUSET controller
+
+Introduce support for configuring cpus and mems for processes using
+cgroup v2 CPUSET controller.  This allows users to limit which cpus
+and memory NUMA nodes can be used by processes to better utilize
+system resources.
+
+The cgroup v2 interfaces to control it are cpuset.cpus and cpuset.mems
+where the requested configuration is written.  However, it doesn't mean
+that the requested configuration will be actually used as parent cgroup
+may limit the cpus or mems as well.  In order to reflect the real
+configuration cgroup v2 provides read-only files cpuset.cpus.effective
+and cpuset.mems.effective which are exported to users as well.
+
+(cherry picked from commit 047f5d63d7a1ab75073f8485e2f9b550d25b0772)
+
+Related: #1724617
+---
+ doc/TRANSIENT-SETTINGS.md             |  2 +
+ man/systemd.resource-control.xml      | 30 +++++++++++++
+ src/basic/cgroup-util.c               |  1 +
+ src/basic/cgroup-util.h               |  2 +
+ src/core/cgroup.c                     | 63 +++++++++++++++++++++++++++
+ src/core/cgroup.h                     |  5 +++
+ src/core/dbus-cgroup.c                | 59 +++++++++++++++++++++++++
+ src/core/dbus-unit.c                  | 48 ++++++++++++++++++++
+ src/core/load-fragment-gperf.gperf.m4 |  2 +
+ src/core/load-fragment.c              | 38 ++++++++++++++++
+ src/core/load-fragment.h              |  2 +
+ src/shared/bus-unit-util.c            | 16 +++++++
+ src/systemctl/systemctl.c             |  2 +-
+ src/test/test-cgroup-mask.c           |  3 +-
+ 14 files changed, 271 insertions(+), 2 deletions(-)
+
+diff --git a/doc/TRANSIENT-SETTINGS.md b/doc/TRANSIENT-SETTINGS.md
+index c2b5c0dcce..0b2ad66dcb 100644
+--- a/doc/TRANSIENT-SETTINGS.md
++++ b/doc/TRANSIENT-SETTINGS.md
+@@ -218,6 +218,8 @@ All cgroup/resource control settings are available for transient units
+ ✓ CPUShares=
+ ✓ StartupCPUShares=
+ ✓ CPUQuota=
++✓ AllowedCPUs=
++✓ AllowedMemoryNodes=
+ ✓ MemoryAccounting=
+ ✓ MemoryLow=
+ ✓ MemoryHigh=
+diff --git a/man/systemd.resource-control.xml b/man/systemd.resource-control.xml
+index 370c110592..4329742e94 100644
+--- a/man/systemd.resource-control.xml
++++ b/man/systemd.resource-control.xml
+@@ -201,6 +201,36 @@
+         </listitem>
+       </varlistentry>
+ 
++      <varlistentry>
++        <term><varname>AllowedCPUs=</varname></term>
++
++        <listitem>
++          <para>Restrict processes to be executed on specific CPUs. Takes a list of CPU indices or ranges separated by either
++          whitespace or commas. CPU ranges are specified by the lower and upper CPU indices separated by a dash.</para>
++
++          <para>Setting <varname>AllowedCPUs=</varname> doesn't guarantee that all of the CPUs will be used by the processes
++          as it may be limited by parent units. The effective configuration is reported as <varname>EffectiveCPUs=</varname>.</para>
++
++          <para>This setting is supported only with the unified control group hierarchy.</para>
++        </listitem>
++      </varlistentry>
++
++      <varlistentry>
++        <term><varname>AllowedMemoryNodes=</varname></term>
++
++        <listitem>
++          <para>Restrict processes to be executed on specific memory NUMA nodes. Takes a list of memory NUMA nodes indices
++          or ranges separated by either whitespace or commas. Memory NUMA nodes ranges are specified by the lower and upper
++          CPU indices separated by a dash.</para>
++
++          <para>Setting <varname>AllowedMemoryNodes=</varname> doesn't guarantee that all of the memory NUMA nodes will
++          be used by the processes as it may be limited by parent units. The effective configuration is reported as
++          <varname>EffectiveMemoryNodes=</varname>.</para>
++
++          <para>This setting is supported only with the unified control group hierarchy.</para>
++        </listitem>
++      </varlistentry>
++
+       <varlistentry>
+         <term><varname>MemoryAccounting=</varname></term>
+ 
+diff --git a/src/basic/cgroup-util.c b/src/basic/cgroup-util.c
+index 038ece4b06..6f47c3aacb 100644
+--- a/src/basic/cgroup-util.c
++++ b/src/basic/cgroup-util.c
+@@ -2763,6 +2763,7 @@ bool fd_is_cgroup_fs(int fd) {
+ static const char *cgroup_controller_table[_CGROUP_CONTROLLER_MAX] = {
+         [CGROUP_CONTROLLER_CPU] = "cpu",
+         [CGROUP_CONTROLLER_CPUACCT] = "cpuacct",
++        [CGROUP_CONTROLLER_CPUSET] = "cpuset",
+         [CGROUP_CONTROLLER_IO] = "io",
+         [CGROUP_CONTROLLER_BLKIO] = "blkio",
+         [CGROUP_CONTROLLER_MEMORY] = "memory",
+diff --git a/src/basic/cgroup-util.h b/src/basic/cgroup-util.h
+index 26e3ae0404..b414600dca 100644
+--- a/src/basic/cgroup-util.h
++++ b/src/basic/cgroup-util.h
+@@ -21,6 +21,7 @@
+ typedef enum CGroupController {
+         CGROUP_CONTROLLER_CPU,
+         CGROUP_CONTROLLER_CPUACCT,    /* v1 only */
++        CGROUP_CONTROLLER_CPUSET,     /* v2 only */
+         CGROUP_CONTROLLER_IO,         /* v2 only */
+         CGROUP_CONTROLLER_BLKIO,      /* v1 only */
+         CGROUP_CONTROLLER_MEMORY,
+@@ -36,6 +37,7 @@ typedef enum CGroupController {
+ typedef enum CGroupMask {
+         CGROUP_MASK_CPU = CGROUP_CONTROLLER_TO_MASK(CGROUP_CONTROLLER_CPU),
+         CGROUP_MASK_CPUACCT = CGROUP_CONTROLLER_TO_MASK(CGROUP_CONTROLLER_CPUACCT),
++        CGROUP_MASK_CPUSET = CGROUP_CONTROLLER_TO_MASK(CGROUP_CONTROLLER_CPUSET),
+         CGROUP_MASK_IO = CGROUP_CONTROLLER_TO_MASK(CGROUP_CONTROLLER_IO),
+         CGROUP_MASK_BLKIO = CGROUP_CONTROLLER_TO_MASK(CGROUP_CONTROLLER_BLKIO),
+         CGROUP_MASK_MEMORY = CGROUP_CONTROLLER_TO_MASK(CGROUP_CONTROLLER_MEMORY),
+diff --git a/src/core/cgroup.c b/src/core/cgroup.c
+index 76eafdc082..664d269483 100644
+--- a/src/core/cgroup.c
++++ b/src/core/cgroup.c
+@@ -161,9 +161,14 @@ void cgroup_context_done(CGroupContext *c) {
+ 
+         c->ip_address_allow = ip_address_access_free_all(c->ip_address_allow);
+         c->ip_address_deny = ip_address_access_free_all(c->ip_address_deny);
++
++        cpu_set_reset(&c->cpuset_cpus);
++        cpu_set_reset(&c->cpuset_mems);
+ }
+ 
+ void cgroup_context_dump(CGroupContext *c, FILE* f, const char *prefix) {
++        _cleanup_free_ char *cpuset_cpus = NULL;
++        _cleanup_free_ char *cpuset_mems = NULL;
+         CGroupIODeviceLimit *il;
+         CGroupIODeviceWeight *iw;
+         CGroupBlockIODeviceBandwidth *b;
+@@ -177,6 +182,9 @@ void cgroup_context_dump(CGroupContext *c, FILE* f, const char *prefix) {
+ 
+         prefix = strempty(prefix);
+ 
++        cpuset_cpus = cpu_set_to_range_string(&c->cpuset_cpus);
++        cpuset_mems = cpu_set_to_range_string(&c->cpuset_mems);
++
+         fprintf(f,
+                 "%sCPUAccounting=%s\n"
+                 "%sIOAccounting=%s\n"
+@@ -189,6 +197,8 @@ void cgroup_context_dump(CGroupContext *c, FILE* f, const char *prefix) {
+                 "%sCPUShares=%" PRIu64 "\n"
+                 "%sStartupCPUShares=%" PRIu64 "\n"
+                 "%sCPUQuotaPerSecSec=%s\n"
++                "%sAllowedCPUs=%s\n"
++                "%sAllowedMemoryNodes=%s\n"
+                 "%sIOWeight=%" PRIu64 "\n"
+                 "%sStartupIOWeight=%" PRIu64 "\n"
+                 "%sBlockIOWeight=%" PRIu64 "\n"
+@@ -212,6 +222,8 @@ void cgroup_context_dump(CGroupContext *c, FILE* f, const char *prefix) {
+                 prefix, c->cpu_shares,
+                 prefix, c->startup_cpu_shares,
+                 prefix, format_timespan(u, sizeof(u), c->cpu_quota_per_sec_usec, 1),
++                prefix, cpuset_cpus,
++                prefix, cpuset_mems,
+                 prefix, c->io_weight,
+                 prefix, c->startup_io_weight,
+                 prefix, c->blockio_weight,
+@@ -541,6 +553,21 @@ static uint64_t cgroup_cpu_weight_to_shares(uint64_t weight) {
+                      CGROUP_CPU_SHARES_MIN, CGROUP_CPU_SHARES_MAX);
+ }
+ 
++static void cgroup_apply_unified_cpuset(Unit *u, CPUSet cpus, const char *name) {
++        _cleanup_free_ char *buf = NULL;
++        int r;
++
++        buf = cpu_set_to_range_string(&cpus);
++        if (!buf)
++            return;
++
++        r = cg_set_attribute("cpuset", u->cgroup_path, name, buf);
++        if (r < 0)
++                log_unit_full(u, IN_SET(r, -ENOENT, -EROFS, -EACCES) ? LOG_DEBUG : LOG_WARNING, r,
++                              "Failed to set %s: %m", name);
++
++}
++
+ static bool cgroup_context_has_io_config(CGroupContext *c) {
+         return c->io_accounting ||
+                 c->io_weight != CGROUP_WEIGHT_INVALID ||
+@@ -766,6 +793,11 @@ static void cgroup_context_apply(
+                 }
+         }
+ 
++        if ((apply_mask & CGROUP_MASK_CPUSET) && !is_root) {
++                cgroup_apply_unified_cpuset(u, c->cpuset_cpus, "cpuset.cpus");
++                cgroup_apply_unified_cpuset(u, c->cpuset_mems, "cpuset.mems");
++        }
++
+         if (apply_mask & CGROUP_MASK_IO) {
+                 bool has_io = cgroup_context_has_io_config(c);
+                 bool has_blockio = cgroup_context_has_blockio_config(c);
+@@ -1068,6 +1100,9 @@ CGroupMask cgroup_context_get_mask(CGroupContext *c) {
+             c->cpu_quota_per_sec_usec != USEC_INFINITY)
+                 mask |= CGROUP_MASK_CPUACCT | CGROUP_MASK_CPU;
+ 
++        if (c->cpuset_cpus.set || c->cpuset_mems.set)
++                mask |= CGROUP_MASK_CPUSET;
++
+         if (cgroup_context_has_io_config(c) || cgroup_context_has_blockio_config(c))
+                 mask |= CGROUP_MASK_IO | CGROUP_MASK_BLKIO;
+ 
+@@ -2697,4 +2732,32 @@ static const char* const cgroup_device_policy_table[_CGROUP_DEVICE_POLICY_MAX] =
+         [CGROUP_STRICT] = "strict",
+ };
+ 
++int unit_get_cpuset(Unit *u, CPUSet *cpus, const char *name) {
++        _cleanup_free_ char *v = NULL;
++        int r;
++
++        assert(u);
++        assert(cpus);
++
++        if (!u->cgroup_path)
++                return -ENODATA;
++
++        if ((u->cgroup_realized_mask & CGROUP_MASK_CPUSET) == 0)
++                return -ENODATA;
++
++        r = cg_all_unified();
++        if (r < 0)
++                return r;
++        if (r == 0)
++                return -ENODATA;
++        if (r > 0)
++                r = cg_get_attribute("cpuset", u->cgroup_path, name, &v);
++        if (r == -ENOENT)
++                return -ENODATA;
++        if (r < 0)
++                return r;
++
++        return parse_cpu_set_full(v, cpus, false, NULL, NULL, 0, NULL);
++}
++
+ DEFINE_STRING_TABLE_LOOKUP(cgroup_device_policy, CGroupDevicePolicy);
+diff --git a/src/core/cgroup.h b/src/core/cgroup.h
+index 2d2ff6fc3c..da10575394 100644
+--- a/src/core/cgroup.h
++++ b/src/core/cgroup.h
+@@ -4,6 +4,7 @@
+ #include <stdbool.h>
+ 
+ #include "cgroup-util.h"
++#include "cpu-set-util.h"
+ #include "ip-address-access.h"
+ #include "list.h"
+ #include "time-util.h"
+@@ -77,6 +78,9 @@ struct CGroupContext {
+         uint64_t startup_cpu_weight;
+         usec_t cpu_quota_per_sec_usec;
+ 
++        CPUSet cpuset_cpus;
++        CPUSet cpuset_mems;
++
+         uint64_t io_weight;
+         uint64_t startup_io_weight;
+         LIST_HEAD(CGroupIODeviceWeight, io_device_weights);
+@@ -205,3 +209,4 @@ const char* cgroup_device_policy_to_string(CGroupDevicePolicy i) _const_;
+ CGroupDevicePolicy cgroup_device_policy_from_string(const char *s) _pure_;
+ 
+ bool unit_cgroup_delegate(Unit *u);
++int unit_get_cpuset(Unit *u, CPUSet *cpus, const char *name);
+diff --git a/src/core/dbus-cgroup.c b/src/core/dbus-cgroup.c
+index 540bc77aed..30d4e83932 100644
+--- a/src/core/dbus-cgroup.c
++++ b/src/core/dbus-cgroup.c
+@@ -53,6 +53,27 @@ static int property_get_delegate_controllers(
+         return sd_bus_message_close_container(reply);
+ }
+ 
++static int property_get_cpuset(
++                sd_bus *bus,
++                const char *path,
++                const char *interface,
++                const char *property,
++                sd_bus_message *reply,
++                void *userdata,
++                sd_bus_error *error) {
++
++        CPUSet *cpus = userdata;
++        _cleanup_free_ uint8_t *array = NULL;
++        size_t allocated;
++
++        assert(bus);
++        assert(reply);
++        assert(cpus);
++
++        (void) cpu_set_to_dbus(cpus, &array, &allocated);
++        return sd_bus_message_append_array(reply, 'y', array, allocated);
++}
++
+ static int property_get_io_device_weight(
+                 sd_bus *bus,
+                 const char *path,
+@@ -283,6 +304,8 @@ const sd_bus_vtable bus_cgroup_vtable[] = {
+         SD_BUS_PROPERTY("CPUShares", "t", NULL, offsetof(CGroupContext, cpu_shares), 0),
+         SD_BUS_PROPERTY("StartupCPUShares", "t", NULL, offsetof(CGroupContext, startup_cpu_shares), 0),
+         SD_BUS_PROPERTY("CPUQuotaPerSecUSec", "t", bus_property_get_usec, offsetof(CGroupContext, cpu_quota_per_sec_usec), 0),
++        SD_BUS_PROPERTY("AllowedCPUs", "ay", property_get_cpuset, offsetof(CGroupContext, cpuset_cpus), 0),
++        SD_BUS_PROPERTY("AllowedMemoryNodes", "ay", property_get_cpuset, offsetof(CGroupContext, cpuset_mems), 0),
+         SD_BUS_PROPERTY("IOAccounting", "b", bus_property_get_bool, offsetof(CGroupContext, io_accounting), 0),
+         SD_BUS_PROPERTY("IOWeight", "t", NULL, offsetof(CGroupContext, io_weight), 0),
+         SD_BUS_PROPERTY("StartupIOWeight", "t", NULL, offsetof(CGroupContext, startup_io_weight), 0),
+@@ -671,6 +694,42 @@ int bus_cgroup_set_property(
+ 
+                 return 1;
+ 
++        } else if (STR_IN_SET(name, "AllowedCPUs", "AllowedMemoryNodes")) {
++                const void *a;
++                size_t n;
++                _cleanup_(cpu_set_reset) CPUSet new_set = {};
++
++                r = sd_bus_message_read_array(message, 'y', &a, &n);
++                if (r < 0)
++                        return r;
++
++                r = cpu_set_from_dbus(a, n, &new_set);
++                if (r < 0)
++                        return r;
++
++                if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
++                        _cleanup_free_ char *setstr = NULL;
++                        _cleanup_free_ char *data = NULL;
++                        CPUSet *set;
++
++                        setstr = cpu_set_to_range_string(&new_set);
++
++                        if (streq(name, "AllowedCPUs"))
++                                set = &c->cpuset_cpus;
++                        else
++                                set = &c->cpuset_mems;
++
++                        if (asprintf(&data, "%s=%s", name, setstr) < 0)
++                                return -ENOMEM;
++
++                        cpu_set_reset(set);
++                        cpu_set_add_all(set, &new_set);
++                        unit_invalidate_cgroup(u, CGROUP_MASK_CPUSET);
++                        unit_write_setting(u, flags, name, data);
++                }
++
++                return 1;
++
+         } else if ((iol_type = cgroup_io_limit_type_from_string(name)) >= 0) {
+                 const char *path;
+                 unsigned n = 0;
+diff --git a/src/core/dbus-unit.c b/src/core/dbus-unit.c
+index c5bca10979..aa15e47754 100644
+--- a/src/core/dbus-unit.c
++++ b/src/core/dbus-unit.c
+@@ -752,6 +752,52 @@ static int property_get_cpu_usage(
+         return sd_bus_message_append(reply, "t", ns);
+ }
+ 
++static int property_get_cpuset_cpus(
++                sd_bus *bus,
++                const char *path,
++                const char *interface,
++                const char *property,
++                sd_bus_message *reply,
++                void *userdata,
++                sd_bus_error *error) {
++
++        Unit *u = userdata;
++        _cleanup_(cpu_set_reset) CPUSet cpus = {};
++        _cleanup_free_ uint8_t *array = NULL;
++        size_t allocated;
++
++        assert(bus);
++        assert(reply);
++        assert(u);
++
++        (void) unit_get_cpuset(u, &cpus, "cpuset.cpus.effective");
++        (void) cpu_set_to_dbus(&cpus, &array, &allocated);
++        return sd_bus_message_append_array(reply, 'y', array, allocated);
++}
++
++static int property_get_cpuset_mems(
++                sd_bus *bus,
++                const char *path,
++                const char *interface,
++                const char *property,
++                sd_bus_message *reply,
++                void *userdata,
++                sd_bus_error *error) {
++
++        Unit *u = userdata;
++        _cleanup_(cpu_set_reset) CPUSet mems = {};
++        _cleanup_free_ uint8_t *array = NULL;
++        size_t allocated;
++
++        assert(bus);
++        assert(reply);
++        assert(u);
++
++        (void) unit_get_cpuset(u, &mems, "cpuset.mems.effective");
++        (void) cpu_set_to_dbus(&mems, &array, &allocated);
++        return sd_bus_message_append_array(reply, 'y', array, allocated);
++}
++
+ static int property_get_cgroup(
+                 sd_bus *bus,
+                 const char *path,
+@@ -1074,6 +1120,8 @@ const sd_bus_vtable bus_unit_cgroup_vtable[] = {
+         SD_BUS_PROPERTY("ControlGroup", "s", property_get_cgroup, 0, 0),
+         SD_BUS_PROPERTY("MemoryCurrent", "t", property_get_current_memory, 0, 0),
+         SD_BUS_PROPERTY("CPUUsageNSec", "t", property_get_cpu_usage, 0, 0),
++        SD_BUS_PROPERTY("EffectiveCPUs", "ay", property_get_cpuset_cpus, 0, 0),
++        SD_BUS_PROPERTY("EffectiveMemoryNodes", "ay", property_get_cpuset_mems, 0, 0),
+         SD_BUS_PROPERTY("TasksCurrent", "t", property_get_current_tasks, 0, 0),
+         SD_BUS_PROPERTY("IPIngressBytes", "t", property_get_ip_counter, 0, 0),
+         SD_BUS_PROPERTY("IPIngressPackets", "t", property_get_ip_counter, 0, 0),
+diff --git a/src/core/load-fragment-gperf.gperf.m4 b/src/core/load-fragment-gperf.gperf.m4
+index 49e938d0ce..ebb44df487 100644
+--- a/src/core/load-fragment-gperf.gperf.m4
++++ b/src/core/load-fragment-gperf.gperf.m4
+@@ -167,6 +167,8 @@ $1.StartupCPUWeight,             config_parse_cg_weight,             0,
+ $1.CPUShares,                    config_parse_cpu_shares,            0,                             offsetof($1, cgroup_context.cpu_shares)
+ $1.StartupCPUShares,             config_parse_cpu_shares,            0,                             offsetof($1, cgroup_context.startup_cpu_shares)
+ $1.CPUQuota,                     config_parse_cpu_quota,             0,                             offsetof($1, cgroup_context)
++$1.CPUSetCpus,                   config_parse_cpuset_cpus,           0,                             offsetof($1, cgroup_context)
++$1.CPUSetMems,                   config_parse_cpuset_mems,           0,                             offsetof($1, cgroup_context)
+ $1.MemoryAccounting,             config_parse_bool,                  0,                             offsetof($1, cgroup_context.memory_accounting)
+ $1.MemoryLow,                    config_parse_memory_limit,          0,                             offsetof($1, cgroup_context)
+ $1.MemoryHigh,                   config_parse_memory_limit,          0,                             offsetof($1, cgroup_context)
+diff --git a/src/core/load-fragment.c b/src/core/load-fragment.c
+index 35dd595098..6debf82401 100644
+--- a/src/core/load-fragment.c
++++ b/src/core/load-fragment.c
+@@ -3011,6 +3011,44 @@ int config_parse_cpu_quota(
+         return 0;
+ }
+ 
++int config_parse_cpuset_cpus(
++                const char *unit,
++                const char *filename,
++                unsigned line,
++                const char *section,
++                unsigned section_line,
++                const char *lvalue,
++                int ltype,
++                const char *rvalue,
++                void *data,
++                void *userdata) {
++
++        CGroupContext *c = data;
++
++        (void) parse_cpu_set_extend(rvalue, &c->cpuset_cpus, true, unit, filename, line, lvalue);
++
++        return 0;
++}
++
++int config_parse_cpuset_mems(
++                const char *unit,
++                const char *filename,
++                unsigned line,
++                const char *section,
++                unsigned section_line,
++                const char *lvalue,
++                int ltype,
++                const char *rvalue,
++                void *data,
++                void *userdata) {
++
++        CGroupContext *c = data;
++
++        (void) parse_cpu_set_extend(rvalue, &c->cpuset_mems, true, unit, filename, line, lvalue);
++
++        return 0;
++}
++
+ int config_parse_memory_limit(
+                 const char *unit,
+                 const char *filename,
+diff --git a/src/core/load-fragment.h b/src/core/load-fragment.h
+index f2ca1b8ee7..6612e1fb32 100644
+--- a/src/core/load-fragment.h
++++ b/src/core/load-fragment.h
+@@ -86,6 +86,8 @@ CONFIG_PARSER_PROTOTYPE(config_parse_set_status);
+ CONFIG_PARSER_PROTOTYPE(config_parse_namespace_path_strv);
+ CONFIG_PARSER_PROTOTYPE(config_parse_temporary_filesystems);
+ CONFIG_PARSER_PROTOTYPE(config_parse_cpu_quota);
++CONFIG_PARSER_PROTOTYPE(config_parse_cpuset_cpus);
++CONFIG_PARSER_PROTOTYPE(config_parse_cpuset_mems);
+ CONFIG_PARSER_PROTOTYPE(config_parse_protect_home);
+ CONFIG_PARSER_PROTOTYPE(config_parse_protect_system);
+ CONFIG_PARSER_PROTOTYPE(config_parse_bus_name);
+diff --git a/src/shared/bus-unit-util.c b/src/shared/bus-unit-util.c
+index 3c42e97b7a..8f3b463c6b 100644
+--- a/src/shared/bus-unit-util.c
++++ b/src/shared/bus-unit-util.c
+@@ -396,6 +396,22 @@ static int bus_append_cgroup_property(sd_bus_message *m, const char *field, cons
+ 
+                 return bus_append_cg_cpu_shares_parse(m, field, eq);
+ 
++        if (STR_IN_SET(field, "AllowedCPUs", "AllowedMemoryNodes")) {
++                _cleanup_(cpu_set_reset) CPUSet cpuset = {};
++                _cleanup_free_ uint8_t *array = NULL;
++                size_t allocated;
++
++                r = parse_cpu_set(eq, &cpuset);
++                if (r < 0)
++                        return log_error_errno(r, "Failed to parse %s value: %s", field, eq);
++
++                r = cpu_set_to_dbus(&cpuset, &array, &allocated);
++                if (r < 0)
++                        return log_error_errno(r, "Failed to serialize CPUSet: %m");
++
++                return bus_append_byte_array(m, field, array, allocated);
++        }
++
+         if (STR_IN_SET(field, "BlockIOWeight", "StartupBlockIOWeight"))
+ 
+                 return bus_append_cg_blkio_weight_parse(m, field, eq);
+diff --git a/src/systemctl/systemctl.c b/src/systemctl/systemctl.c
+index 7274921e6d..a3074bc5e3 100644
+--- a/src/systemctl/systemctl.c
++++ b/src/systemctl/systemctl.c
+@@ -4892,7 +4892,7 @@ static int print_property(const char *name, sd_bus_message *m, bool value, bool
+                         print_prop(name, "%s", h);
+ 
+                         return 1;
+-                } else if (contents[0] == SD_BUS_TYPE_BYTE && STR_IN_SET(name, "CPUAffinity", "NUMAMask")) {
++                } else if (contents[0] == SD_BUS_TYPE_BYTE && STR_IN_SET(name, "CPUAffinity", "NUMAMask", "AllowedCPUs", "AllowedMemoryNodes", "EffectiveCPUs", "EffectiveMemoryNodes")) {
+                         _cleanup_free_ char *affinity = NULL;
+                         _cleanup_(cpu_set_reset) CPUSet set = {};
+                         const void *a;
+diff --git a/src/test/test-cgroup-mask.c b/src/test/test-cgroup-mask.c
+index d65959edf1..93c3f5d856 100644
+--- a/src/test/test-cgroup-mask.c
++++ b/src/test/test-cgroup-mask.c
+@@ -104,9 +104,10 @@ static void test_cg_mask_to_string_one(CGroupMask mask, const char *t) {
+ 
+ static void test_cg_mask_to_string(void) {
+         test_cg_mask_to_string_one(0, NULL);
+-        test_cg_mask_to_string_one(_CGROUP_MASK_ALL, "cpu cpuacct io blkio memory devices pids");
++        test_cg_mask_to_string_one(_CGROUP_MASK_ALL, "cpu cpuacct cpuset io blkio memory devices pids");
+         test_cg_mask_to_string_one(CGROUP_MASK_CPU, "cpu");
+         test_cg_mask_to_string_one(CGROUP_MASK_CPUACCT, "cpuacct");
++        test_cg_mask_to_string_one(CGROUP_MASK_CPUSET, "cpuset");
+         test_cg_mask_to_string_one(CGROUP_MASK_IO, "io");
+         test_cg_mask_to_string_one(CGROUP_MASK_BLKIO, "blkio");
+         test_cg_mask_to_string_one(CGROUP_MASK_MEMORY, "memory");
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 <fbui@suse.com>
+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?= <msekleta@redhat.com>
+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 <frantisek@sumsal.cz>
+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 <<EOF
++[Unit]
++Description=Testsuite service
++
++[Service]
++ExecStart=/bin/bash -x /testsuite.sh
++Type=oneshot
++StandardOutput=tty
++StandardError=tty
++NotifyAccess=all
++EOF
++        cp testsuite.sh $initdir/
++
++        setup_testsuite
++    ) || return 1
++    setup_nspawn_root
++
++    ddebug "umount $TESTDIR/root"
++    umount $TESTDIR/root
++}
++
++do_test "$@"
+diff --git a/test/TEST-36-NUMAPOLICY/testsuite.sh b/test/TEST-36-NUMAPOLICY/testsuite.sh
+new file mode 100755
+index 0000000000..e15087b137
+--- /dev/null
++++ b/test/TEST-36-NUMAPOLICY/testsuite.sh
+@@ -0,0 +1,292 @@
++#!/bin/bash
++set -ex
++set -o pipefail
++
++at_exit() {
++    if [ $? -ne 0 ]; then
++        # We're exiting with a non-zero EC, let's dump test artifacts
++        # for easier debugging
++        [ -f "$straceLog" ] && cat "$straceLog"
++        [ -f "$journalLog" ] && cat "$journalLog"
++    fi
++}
++
++trap at_exit EXIT
++
++systemd-analyze log-level debug
++systemd-analyze log-target journal
++
++# Log files
++straceLog='strace.log'
++journalLog='journal.log'
++
++# Systemd config files
++testUnit='numa-test.service'
++testUnitFile="/etc/systemd/system/$testUnit"
++testUnitNUMAConf="$testUnitFile.d/numa.conf"
++
++# Sleep constants (we should probably figure out something better but nothing comes to mind)
++journalSleep=5
++sleepAfterStart=1
++
++startStrace() {
++    coproc strace -qq -p 1 -o $straceLog -e set_mempolicy -s 1024 $1
++}
++
++stopStrace() {
++    kill -s TERM $COPROC_PID
++}
++
++startJournalctl() {
++    coproc journalctl -u init.scope -f > $journalLog
++}
++
++stopJournalctl() {
++    # Wait a few seconds until the messages get properly queued...
++    sleep $journalSleep
++    # ...and then force journald to write them to the backing storage
++    # Also, using journalctl --sync should be better than using SIGRTMIN+1, as
++    # the --sync wait until the synchronization is complete
++    echo "Force journald to write all queued messages"
++    journalctl --sync
++    kill -s TERM $COPROC_PID
++}
++
++checkNUMA() {
++    # NUMA enabled system should have at least NUMA node0
++    test -e /sys/devices/system/node/node0
++}
++
++writePID1NUMAPolicy() {
++    echo [Manager] > $confDir/numa.conf
++    echo NUMAPolicy=$1 >> $confDir/numa.conf
++    echo NUMAMask=$2>> $confDir/numa.conf
++}
++
++writeTestUnit() {
++    echo [Service] > $testUnitFile
++    echo ExecStart=/bin/sleep 3600 >> $testUnitFile
++    mkdir -p $testUnitFile.d/
++}
++
++writeTestUnitNUMAPolicy() {
++    echo [Service] > $testUnitNUMAConf
++    echo NUMAPolicy=$1 >> $testUnitNUMAConf
++    echo NUMAMask=$2>> $testUnitNUMAConf
++    systemctl daemon-reload
++}
++
++pid1ReloadWithStrace() {
++    startStrace
++    systemctl daemon-reload
++    stopStrace
++}
++
++pid1ReloadWithJournal() {
++    startJournalctl
++    systemctl daemon-reload
++    stopJournalctl
++}
++
++pid1StartUnitWithStrace() {
++    startStrace '-f'
++    systemctl start $1
++    sleep $sleepAfterStart
++    stopStrace
++}
++
++pid1StartUnitWithJournal() {
++    startJournalctl
++    systemctl start $1
++    sleep $sleepAfterStart
++    stopJournalctl
++}
++
++pid1StopUnit() {
++    systemctl stop $1
++}
++
++systemctlCheckNUMAProperties() {
++    local LOGFILE="$(mktemp)"
++    systemctl show -p NUMAPolicy $1 > "$LOGFILE"
++    grep "NUMAPolicy=$2" "$LOGFILE"
++
++    > "$LOGFILE"
++
++    if [ -n $3 ]; then
++        systemctl show -p NUMAMask $1 > "$LOGFILE"
++        grep "NUMAMask=$3" "$LOGFILE"
++    fi
++}
++
++checkNUMA
++writeTestUnit
++
++# Create systemd config drop-in directory
++confDir="/etc/systemd/system.conf.d/"
++mkdir -p "$confDir"
++
++echo "PID1 NUMAPolicy support - Default policy w/o mask"
++writePID1NUMAPolicy "default"
++pid1ReloadWithStrace
++# Kernel requires that nodemask argument is set to NULL when setting default policy
++grep "set_mempolicy(MPOL_DEFAULT, NULL" $straceLog
++
++echo "PID1 NUMAPolicy support - Default policy w/ mask"
++writePID1NUMAPolicy "default" "0"
++pid1ReloadWithStrace
++grep "set_mempolicy(MPOL_DEFAULT, NULL" $straceLog
++
++echo "PID1 NUMAPolicy support - Bind policy w/o mask"
++writePID1NUMAPolicy "bind"
++pid1ReloadWithJournal
++grep "Failed to set NUMA memory policy: Invalid argument" $journalLog
++
++echo "PID1 NUMAPolicy support - Bind policy w/ mask"
++writePID1NUMAPolicy "bind" "0"
++pid1ReloadWithStrace
++grep -P "set_mempolicy\(MPOL_BIND, \[0x0*1\]" $straceLog
++
++echo "PID1 NUMAPolicy support - Interleave policy w/o mask"
++writePID1NUMAPolicy "interleave"
++pid1ReloadWithJournal
++grep "Failed to set NUMA memory policy: Invalid argument" $journalLog
++
++echo "PID1 NUMAPolicy support - Interleave policy w/ mask"
++writePID1NUMAPolicy "interleave" "0"
++pid1ReloadWithStrace
++grep -P "set_mempolicy\(MPOL_INTERLEAVE, \[0x0*1\]" $straceLog
++
++echo "PID1 NUMAPolicy support - Preferred policy w/o mask"
++writePID1NUMAPolicy "preferred"
++pid1ReloadWithJournal
++# Preferred policy with empty node mask is actually allowed and should reset allocation policy to default
++! grep "Failed to set NUMA memory policy: Invalid argument" $journalLog
++
++echo "PID1 NUMAPolicy support - Preferred policy w/ mask"
++writePID1NUMAPolicy "preferred" "0"
++pid1ReloadWithStrace
++grep -P "set_mempolicy\(MPOL_PREFERRED, \[0x0*1\]" $straceLog
++
++echo "PID1 NUMAPolicy support - Local policy w/o mask"
++writePID1NUMAPolicy "local"
++pid1ReloadWithStrace
++# Kernel requires that nodemask argument is set to NULL when setting default policy
++grep "set_mempolicy(MPOL_LOCAL, NULL" $straceLog
++
++echo "PID1 NUMAPolicy support - Local policy w/ mask"
++writePID1NUMAPolicy "local" "0"
++pid1ReloadWithStrace
++grep "set_mempolicy(MPOL_LOCAL, NULL" $straceLog
++
++echo "Unit file NUMAPolicy support - Default policy w/o mask"
++writeTestUnitNUMAPolicy "default"
++pid1StartUnitWithStrace $testUnit
++systemctlCheckNUMAProperties $testUnit "default"
++pid1StopUnit $testUnit
++grep "set_mempolicy(MPOL_DEFAULT, NULL" $straceLog
++
++echo "Unit file NUMAPolicy support - Default policy w/ mask"
++writeTestUnitNUMAPolicy "default" "0"
++pid1StartUnitWithStrace $testUnit
++systemctlCheckNUMAProperties $testUnit "default" "0"
++pid1StopUnit $testUnit
++# Maks must be ignored
++grep "set_mempolicy(MPOL_DEFAULT, NULL" $straceLog
++
++echo "Unit file NUMAPolicy support - Bind policy w/o mask"
++writeTestUnitNUMAPolicy "bind"
++pid1StartUnitWithJournal $testUnit
++pid1StopUnit $testUnit
++grep "numa-test.service: Main process exited, code=exited, status=242/NUMA" $journalLog
++
++echo "Unit file NUMAPolicy support - Bind policy w/ mask"
++writeTestUnitNUMAPolicy "bind" "0"
++pid1StartUnitWithStrace $testUnit
++systemctlCheckNUMAProperties $testUnit "bind" "0"
++pid1StopUnit $testUnit
++grep -P "set_mempolicy\(MPOL_BIND, \[0x0*1\]" $straceLog
++
++echo "Unit file NUMAPolicy support - Interleave policy w/o mask"
++writeTestUnitNUMAPolicy "interleave"
++pid1StartUnitWithStrace $testUnit
++pid1StopUnit $testUnit
++grep "numa-test.service: Main process exited, code=exited, status=242/NUMA" $journalLog
++
++echo "Unit file NUMAPolicy support - Interleave policy w/ mask"
++writeTestUnitNUMAPolicy "interleave" "0"
++pid1StartUnitWithStrace $testUnit
++systemctlCheckNUMAProperties $testUnit "interleave" "0"
++pid1StopUnit $testUnit
++grep -P "set_mempolicy\(MPOL_INTERLEAVE, \[0x0*1\]" $straceLog
++
++echo "Unit file NUMAPolicy support - Preferred policy w/o mask"
++writeTestUnitNUMAPolicy "preferred"
++pid1StartUnitWithJournal $testUnit
++systemctlCheckNUMAProperties $testUnit "preferred"
++pid1StopUnit $testUnit
++! grep "numa-test.service: Main process exited, code=exited, status=242/NUMA" $journalLog
++
++echo "Unit file NUMAPolicy support - Preferred policy w/ mask"
++writeTestUnitNUMAPolicy "preferred" "0"
++pid1StartUnitWithStrace $testUnit
++systemctlCheckNUMAProperties $testUnit "preferred" "0"
++pid1StopUnit $testUnit
++grep -P "set_mempolicy\(MPOL_PREFERRED, \[0x0*1\]" $straceLog
++
++echo "Unit file NUMAPolicy support - Local policy w/o mask"
++writeTestUnitNUMAPolicy "local"
++pid1StartUnitWithStrace $testUnit
++systemctlCheckNUMAProperties $testUnit "local"
++pid1StopUnit $testUnit
++grep "set_mempolicy(MPOL_LOCAL, NULL" $straceLog
++
++echo "Unit file NUMAPolicy support - Local policy w/ mask"
++writeTestUnitNUMAPolicy "local" "0"
++pid1StartUnitWithStrace $testUnit
++systemctlCheckNUMAProperties $testUnit "local" "0"
++pid1StopUnit $testUnit
++# Maks must be ignored
++grep "set_mempolicy(MPOL_LOCAL, NULL" $straceLog
++
++echo "systemd-run NUMAPolicy support"
++runUnit='numa-systemd-run-test.service'
++
++systemd-run -p NUMAPolicy=default --unit $runUnit sleep 1000
++systemctlCheckNUMAProperties $runUnit "default"
++pid1StopUnit $runUnit
++
++systemd-run -p NUMAPolicy=default -p NUMAMask=0 --unit $runUnit sleep 1000
++systemctlCheckNUMAProperties $runUnit "default" ""
++pid1StopUnit $runUnit
++
++systemd-run -p NUMAPolicy=bind -p NUMAMask=0 --unit $runUnit sleep 1000
++systemctlCheckNUMAProperties $runUnit "bind" "0"
++pid1StopUnit $runUnit
++
++systemd-run -p NUMAPolicy=interleave -p NUMAMask=0 --unit $runUnit sleep 1000
++systemctlCheckNUMAProperties $runUnit "interleave" "0"
++pid1StopUnit $runUnit
++
++systemd-run -p NUMAPolicy=preferred -p NUMAMask=0 --unit $runUnit sleep 1000
++systemctlCheckNUMAProperties $runUnit "preferred" "0"
++pid1StopUnit $runUnit
++
++systemd-run -p NUMAPolicy=local --unit $runUnit sleep 1000
++systemctlCheckNUMAProperties $runUnit "local"
++pid1StopUnit $runUnit
++
++systemd-run -p NUMAPolicy=local -p NUMAMask=0 --unit $runUnit sleep 1000
++systemctlCheckNUMAProperties $runUnit "local" ""
++pid1StopUnit $runUnit
++
++# Cleanup
++rm -rf $testDir
++rm -rf $confDir
++systemctl daemon-reload
++
++systemd-analyze log-level info
++
++echo OK > /testok
++
++exit 0
+-- 
+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 <frantisek@sumsal.cz>
+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 <frantisek@sumsal.cz>
+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 <frantisek@sumsal.cz>
+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 <frantisek@sumsal.cz>
+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 <frantisek@sumsal.cz>
+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 <frantisek@sumsal.cz>
+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 <frantisek@sumsal.cz>
+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 <fsumsal@redhat.com>
+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 <kirbyfan64@users.noreply.github.com>
+Date: Fri, 22 Feb 2019 23:45:03 -0600
+Subject: [PATCH] cryptsetup: Treat key file errors as a failed password
+ attempt
+
+6f177c7dc092eb68762b4533d41b14244adb2a73 caused key file errors to immediately fail, which would make it hard to correct an issue due to e.g. a crypttab typo or a damaged key file.
+
+Closes #11723.
+
+(cherry picked from commit c20db3887569e0c0d9c0e2845c5286e7edf0133a)
+
+Related: #1763155
+---
+ src/cryptsetup/cryptsetup.c | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+diff --git a/src/cryptsetup/cryptsetup.c b/src/cryptsetup/cryptsetup.c
+index 33c215eaa1..11162eb722 100644
+--- a/src/cryptsetup/cryptsetup.c
++++ b/src/cryptsetup/cryptsetup.c
+@@ -558,6 +558,10 @@ static int attach_luks_or_plain(struct crypt_device *cd,
+                         log_error_errno(r, "Failed to activate with key file '%s'. (Key data incorrect?)", key_file);
+                         return -EAGAIN; /* Log actual error, but return EAGAIN */
+                 }
++                if (r == -EINVAL) {
++                        log_error_errno(r, "Failed to activate with key file '%s'. (Key file missing?)", key_file);
++                        return -EAGAIN; /* Log actual error, but return EAGAIN */
++                }
+                 if (r < 0)
+                         return log_error_errno(r, "Failed to activate with key file '%s': %m", key_file);
+         } else {
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 <systemd-maint@redhat.com> - 239-29
+- cryptsetup: Treat key file errors as a failed password attempt (#1763155)
+
+* Wed Mar 11 2020 systemd maintenance team <systemd-maint@redhat.com> - 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 <systemd-maint@redhat.com> - 239-27
+- cgroup: introduce support for cgroup v2 CPUSET controller (#1724617)
+
+* Wed Feb 19 2020 systemd maintenance team <systemd-maint@redhat.com> - 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 <systemd-maint@redhat.com> - 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 <systemd-maint@redhat.com> - 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 <systemd-maint@redhat.com> - 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 <systemd-maint@redhat.com> - 239-22
+- spec: don't ship /var/log/README
+- spec: provide systemd-rpm-macros
+
 * Mon Dec 09 2019 systemd maintenance team <systemd-maint@redhat.com> - 239-21
 - test-cpu-set-util: fix comparison for allocation size (#1734787)
 - test-cpu-set-util: fix allocation size check on i386 (#1734787)