Submitted By: DJ Lucas Date: 2018-11-04 Initial Package Version: 239 Upstream Status: Committed Origin: https://github.com/systemd/systemd-stable/ Description: 2018-10-28 patch set - Includes many backported patches for the current stable version of systemd. Fixes security and usability issues discovered since release. diff -Naurp systemd-239-orig/catalog/systemd.be.catalog.in systemd-239/catalog/systemd.be.catalog.in --- systemd-239-orig/catalog/systemd.be.catalog.in 2018-06-22 06:11:49.000000000 -0500 +++ systemd-239/catalog/systemd.be.catalog.in 2018-11-04 08:49:10.176692740 -0600 @@ -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 -Naurp systemd-239-orig/catalog/systemd.be@latin.catalog.in systemd-239/catalog/systemd.be@latin.catalog.in --- systemd-239-orig/catalog/systemd.be@latin.catalog.in 2018-06-22 06:11:49.000000000 -0500 +++ systemd-239/catalog/systemd.be@latin.catalog.in 2018-11-04 08:49:10.176692740 -0600 @@ -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 -Naurp systemd-239-orig/catalog/systemd.bg.catalog.in systemd-239/catalog/systemd.bg.catalog.in --- systemd-239-orig/catalog/systemd.bg.catalog.in 2018-06-22 06:11:49.000000000 -0500 +++ systemd-239/catalog/systemd.bg.catalog.in 2018-11-04 08:49:10.176692740 -0600 @@ -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 -Naurp systemd-239-orig/catalog/systemd.catalog.in systemd-239/catalog/systemd.catalog.in --- systemd-239-orig/catalog/systemd.catalog.in 2018-06-22 06:11:49.000000000 -0500 +++ systemd-239/catalog/systemd.catalog.in 2018-11-04 08:49:10.176692740 -0600 @@ -201,7 +201,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 @@ -224,7 +224,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 @@ -240,7 +240,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 -Naurp systemd-239-orig/catalog/systemd.da.catalog.in systemd-239/catalog/systemd.da.catalog.in --- systemd-239-orig/catalog/systemd.da.catalog.in 2018-06-22 06:11:49.000000000 -0500 +++ systemd-239/catalog/systemd.da.catalog.in 2018-11-04 08:49:10.176692740 -0600 @@ -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 -Naurp systemd-239-orig/catalog/systemd.fr.catalog.in systemd-239/catalog/systemd.fr.catalog.in --- systemd-239-orig/catalog/systemd.fr.catalog.in 2018-06-22 06:11:49.000000000 -0500 +++ systemd-239/catalog/systemd.fr.catalog.in 2018-11-04 08:49:10.176692740 -0600 @@ -191,7 +191,7 @@ Subject: L'unité (unit) @UNIT@ a termin 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 -Naurp systemd-239-orig/catalog/systemd.hr.catalog.in systemd-239/catalog/systemd.hr.catalog.in --- systemd-239-orig/catalog/systemd.hr.catalog.in 2018-06-22 06:11:49.000000000 -0500 +++ systemd-239/catalog/systemd.hr.catalog.in 2018-11-04 08:49:10.176692740 -0600 @@ -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 -Naurp systemd-239-orig/catalog/systemd.hu.catalog.in systemd-239/catalog/systemd.hu.catalog.in --- systemd-239-orig/catalog/systemd.hu.catalog.in 2018-06-22 06:11:49.000000000 -0500 +++ systemd-239/catalog/systemd.hu.catalog.in 2018-11-04 08:49:10.176692740 -0600 @@ -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 -Naurp systemd-239-orig/catalog/systemd.it.catalog.in systemd-239/catalog/systemd.it.catalog.in --- systemd-239-orig/catalog/systemd.it.catalog.in 2018-06-22 06:11:49.000000000 -0500 +++ systemd-239/catalog/systemd.it.catalog.in 2018-11-04 08:49:10.176692740 -0600 @@ -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 -Naurp systemd-239-orig/catalog/systemd.ko.catalog.in systemd-239/catalog/systemd.ko.catalog.in --- systemd-239-orig/catalog/systemd.ko.catalog.in 2018-06-22 06:11:49.000000000 -0500 +++ systemd-239/catalog/systemd.ko.catalog.in 2018-11-04 08:49:10.176692740 -0600 @@ -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 -Naurp systemd-239-orig/catalog/systemd.pl.catalog.in systemd-239/catalog/systemd.pl.catalog.in --- systemd-239-orig/catalog/systemd.pl.catalog.in 2018-06-22 06:11:49.000000000 -0500 +++ systemd-239/catalog/systemd.pl.catalog.in 2018-11-04 08:49:10.177692739 -0600 @@ -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 -Naurp systemd-239-orig/catalog/systemd.pt_BR.catalog.in systemd-239/catalog/systemd.pt_BR.catalog.in --- systemd-239-orig/catalog/systemd.pt_BR.catalog.in 2018-06-22 06:11:49.000000000 -0500 +++ systemd-239/catalog/systemd.pt_BR.catalog.in 2018-11-04 08:49:10.177692739 -0600 @@ -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 -Naurp systemd-239-orig/catalog/systemd.ru.catalog.in systemd-239/catalog/systemd.ru.catalog.in --- systemd-239-orig/catalog/systemd.ru.catalog.in 2018-06-22 06:11:49.000000000 -0500 +++ systemd-239/catalog/systemd.ru.catalog.in 2018-11-04 08:49:10.177692739 -0600 @@ -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 -Naurp systemd-239-orig/catalog/systemd.sr.catalog.in systemd-239/catalog/systemd.sr.catalog.in --- systemd-239-orig/catalog/systemd.sr.catalog.in 2018-06-22 06:11:49.000000000 -0500 +++ systemd-239/catalog/systemd.sr.catalog.in 2018-11-04 08:49:10.177692739 -0600 @@ -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 -Naurp systemd-239-orig/catalog/systemd.zh_CN.catalog.in systemd-239/catalog/systemd.zh_CN.catalog.in --- systemd-239-orig/catalog/systemd.zh_CN.catalog.in 2018-06-22 06:11:49.000000000 -0500 +++ systemd-239/catalog/systemd.zh_CN.catalog.in 2018-11-04 08:49:10.177692739 -0600 @@ -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 -Naurp systemd-239-orig/catalog/systemd.zh_TW.catalog.in systemd-239/catalog/systemd.zh_TW.catalog.in --- systemd-239-orig/catalog/systemd.zh_TW.catalog.in 2018-06-22 06:11:49.000000000 -0500 +++ systemd-239/catalog/systemd.zh_TW.catalog.in 2018-11-04 08:49:10.177692739 -0600 @@ -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 -Naurp systemd-239-orig/doc/ENVIRONMENT.md systemd-239/doc/ENVIRONMENT.md --- systemd-239-orig/doc/ENVIRONMENT.md 2018-06-22 06:11:49.000000000 -0500 +++ systemd-239/doc/ENVIRONMENT.md 2018-11-04 08:49:10.177692739 -0600 @@ -37,6 +37,13 @@ All tools: useful for debugging, in order to test generators and other code against specific kernel command lines. +* `$SYSTEMD_IN_INITRD` — takes a boolean. If set, overrides initrd detection. + This is useful for debugging and testing initrd-only programs in the main + system. + +* `$SYSTEMD_MEMPOOL=0` — if set the internal memory caching logic employed by + hash tables is turned off, and libc malloc() is used for all allocations. + systemctl: * `$SYSTEMCTL_FORCE_BUS=1` — if set, do not connect to PID1's private D-Bus diff -Naurp systemd-239-orig/hwdb/60-evdev.hwdb systemd-239/hwdb/60-evdev.hwdb --- systemd-239-orig/hwdb/60-evdev.hwdb 2018-06-22 06:11:49.000000000 -0500 +++ systemd-239/hwdb/60-evdev.hwdb 2018-11-04 08:49:10.180692738 -0600 @@ -265,7 +265,7 @@ evdev:name:SynPS/2 Synaptics TouchPad:dm EVDEV_ABS_36=1029:4916:78 # HP Spectre -evdev:name:SynPS/2 Synaptics TouchPad:dmi:i*svnHP:pnHPSpectreNotebook* +evdev:name:SynPS/2 Synaptics TouchPad:dmi:*svnHP:pnHPSpectreNotebook* EVDEV_ABS_00=1205:5691:47 EVDEV_ABS_01=1083:4808:65 EVDEV_ABS_35=1205:5691:47 diff -Naurp systemd-239-orig/man/coredumpctl.xml systemd-239/man/coredumpctl.xml --- systemd-239-orig/man/coredumpctl.xml 2018-06-22 06:11:49.000000000 -0500 +++ systemd-239/man/coredumpctl.xml 2018-11-04 08:49:10.184692736 -0600 @@ -210,7 +210,8 @@ info - Show detailed information about core dumps + Show detailed information about the last core dump + or core dumps matching specified characteristics captured in the journal. diff -Naurp systemd-239-orig/man/logind.conf.xml systemd-239/man/logind.conf.xml --- systemd-239-orig/man/logind.conf.xml 2018-06-22 06:11:49.000000000 -0500 +++ systemd-239/man/logind.conf.xml 2018-11-04 08:49:10.184692736 -0600 @@ -185,6 +185,17 @@ + UserStopDelaySec= + + Specifies how long to keep the user record and per-user service + user@.service around for a user after they logged out fully. If set to zero, the per-user + service is terminated immediately when the last session of the user has ended. If this option is configured to + non-zero rapid logout/login cycles are sped up, as the user's service manager is not constantly restarted. If + set to infinity the per-user service for a user is never terminated again after first login, + and continues to run until system shutdown. Defaults to 10s. + + + HandlePowerKey= HandleSuspendKey= HandleHibernateKey= diff -Naurp systemd-239-orig/man/meson.build systemd-239/man/meson.build --- systemd-239-orig/man/meson.build 2018-06-22 06:11:49.000000000 -0500 +++ systemd-239/man/meson.build 2018-11-04 08:49:10.185692736 -0600 @@ -166,7 +166,8 @@ foreach tuple : want_man or want_html ? html_pages += [p3] endforeach -# cannot use run_target until https://github.com/mesonbuild/meson/issues/1644 is resolved +# Cannot use run_target because those targets are used in depends +# Also see https://github.com/mesonbuild/meson/issues/368. man = custom_target( 'man', output : 'man', diff -Naurp systemd-239-orig/man/os-release.xml systemd-239/man/os-release.xml --- systemd-239-orig/man/os-release.xml 2018-06-22 06:11:49.000000000 -0500 +++ systemd-239/man/os-release.xml 2018-11-04 08:49:10.185692736 -0600 @@ -218,14 +218,18 @@ HOME_URL= + DOCUMENTATION_URL= SUPPORT_URL= BUG_REPORT_URL= PRIVACY_POLICY_URL= - Links to resources on the Internet related the - operating system. HOME_URL= should refer to - the homepage of the operating system, or alternatively some - homepage of the specific version of the operating system. + Links to resources on the Internet related to + the operating system. + HOME_URL= should refer to the homepage of + the operating system, or alternatively some homepage of the + specific version of the operating system. + DOCUMENTATION_URL= should refer to the main + documentation page for this operating system. SUPPORT_URL= should refer to the main support page for the operating system, if there is any. This is primarily intended for operating systems which vendors @@ -302,6 +306,22 @@ + + LOGO= + + + A string, specifying the name of an icon as defined by + freedesktop.org Icon Theme Specification. This can be + used by graphical applications to display an operating + system's or distributor's logo. This field is optional and + may not necessarily be implemented on all systems. + Examples: + LOGO=fedora-logo, + LOGO=distributor-logo-opensuse + + + If you are reading this file from C code or a shell script diff -Naurp systemd-239-orig/man/resolved.conf.xml systemd-239/man/resolved.conf.xml --- systemd-239-orig/man/resolved.conf.xml 2018-06-22 06:11:49.000000000 -0500 +++ systemd-239/man/resolved.conf.xml 2018-11-04 08:49:10.185692736 -0600 @@ -91,7 +91,7 @@ Takes a boolean argument or resolve. Controls Link-Local Multicast Name Resolution support (RFC 4794) on + url="https://tools.ietf.org/html/rfc4795">RFC 4795) on the local host. If true, enables full LLMNR responder and resolver support. If false, disables both. If set to resolve, only resolution support is enabled, diff -Naurp systemd-239-orig/man/rules/meson.build systemd-239/man/rules/meson.build --- systemd-239-orig/man/rules/meson.build 2018-06-22 06:11:49.000000000 -0500 +++ systemd-239/man/rules/meson.build 2018-11-04 08:49:10.185692736 -0600 @@ -820,6 +820,7 @@ manpages = [ ''], ['udev_new', '3', ['udev_ref', 'udev_unref'], ''], ['udevadm', '8', [], ''], + ['user@.service', '5', ['user-runtime-dir@.service'], ''], ['vconsole.conf', '5', [], 'ENABLE_VCONSOLE'] ] # Really, do not edit. diff -Naurp systemd-239-orig/man/sd_bus_error.xml systemd-239/man/sd_bus_error.xml --- systemd-239-orig/man/sd_bus_error.xml 2018-06-22 06:11:49.000000000 -0500 +++ systemd-239/man/sd_bus_error.xml 2018-11-04 08:49:10.185692736 -0600 @@ -148,7 +148,7 @@ should have both fields initialized to NULL. Set an error structure to SD_BUS_ERROR_NULL in order to reset both fields to NULL. When no longer necessary, resources - held by the sd_bus_errorstructure should + held by the sd_bus_error structure should be destroyed with sd_bus_error_free(). sd_bus_error_set() sets an error diff -Naurp systemd-239-orig/man/sd_journal_stream_fd.xml systemd-239/man/sd_journal_stream_fd.xml --- systemd-239-orig/man/sd_journal_stream_fd.xml 2018-06-22 06:11:49.000000000 -0500 +++ systemd-239/man/sd_journal_stream_fd.xml 2018-11-04 08:49:10.186692735 -0600 @@ -49,7 +49,7 @@ sd_journal_stream_fd() takes a short program identifier string as first argument, which will be written - to the journal as _SYSLOG_IDENTIFIER= field for each log entry + to the journal as SYSLOG_IDENTIFIER= field for each log entry (see systemd.journal-fields7 for more information). The second argument shall be the default diff -Naurp systemd-239-orig/man/systemctl.xml systemd-239/man/systemctl.xml --- systemd-239-orig/man/systemctl.xml 2018-06-22 06:11:49.000000000 -0500 +++ systemd-239/man/systemctl.xml 2018-11-04 08:49:10.186692735 -0600 @@ -655,7 +655,7 @@ - list-units PATTERN + list-units PATTERN List units that systemd currently has in memory. This includes units that are @@ -703,7 +703,7 @@ To show all installed unit files use 'sy - list-sockets PATTERN + list-sockets PATTERN List socket units currently in memory, ordered by listening address. If one or more @@ -726,7 +726,7 @@ kobject-uevent 1 systemd-udevd-kernel.so - list-timers PATTERN + list-timers PATTERN List timer units currently in memory, ordered by the time they elapse next. If one or more @@ -803,7 +803,7 @@ Sun 2017-02-26 20:57:49 EST 2h 3min lef Note that restarting a unit with this command does not necessarily flush out all of the unit's resources before it is started again. For example, the per-service file descriptor storage facility (see - FileDescriptoreStoreMax= in + FileDescriptorStoreMax= in systemd.service5) will remain intact as long as the unit has a job pending, and is only cleared when the unit is fully stopped and no jobs are pending anymore. If it is intended that the file descriptor store is flushed out, too, during a @@ -1098,7 +1098,7 @@ Jan 12 10:46:45 example.com bluetoothd[8 - list-unit-files PATTERN… + list-unit-files PATTERN… List unit files installed on the system, in combination with their enablement state (as reported by @@ -1477,7 +1477,7 @@ Jan 12 10:46:45 example.com bluetoothd[8 - list-machines PATTERN + list-machines PATTERN List the host and all running local containers with @@ -1779,7 +1779,7 @@ Jan 12 10:46:45 example.com bluetoothd[8 - reboot arg + reboot arg Shut down and reboot the system. This is mostly equivalent to systemctl start reboot.target @@ -1819,7 +1819,7 @@ Jan 12 10:46:45 example.com bluetoothd[8 - exit EXIT_CODE + exit EXIT_CODE Ask the service manager to quit. This is only supported for user service managers (i.e. in @@ -1833,7 +1833,7 @@ Jan 12 10:46:45 example.com bluetoothd[8 - switch-root ROOT INIT + switch-root ROOT INIT Switches to a different root directory and executes a new system manager process below it. This is diff -Naurp systemd-239-orig/man/systemd.exec.xml systemd-239/man/systemd.exec.xml --- systemd-239-orig/man/systemd.exec.xml 2018-06-22 06:11:49.000000000 -0500 +++ systemd-239/man/systemd.exec.xml 2018-11-04 08:49:10.187692735 -0600 @@ -81,6 +81,9 @@ Paths + The following settings may be used to change a service's view of the filesystem. Please note that the paths + must be absolute and must not contain a .. path component. + @@ -1311,10 +1314,7 @@ RestrictNamespaces=~cgroup netPrivateMounts= above) will implicitly disable mount and unmount propagation from the unit's processes towards the host by changing the propagation setting of all mount points in the unit's file system namepace to first. Setting this option to - does not reestablish propagation in that case. Conversely, if this option is set, but - no other file system namespace setting is used, then new file system namespaces will be created for the unit's - processes and this propagation flag will be applied right away to all mounts within it, without the - intermediary application of . + does not reestablish propagation in that case. If not set – but file system namespaces are enabled through another file system namespace unit setting – mount propagation is used, but — as mentioned — as is applied diff -Naurp systemd-239-orig/man/systemd-hibernate-resume-generator.xml systemd-239/man/systemd-hibernate-resume-generator.xml --- systemd-239-orig/man/systemd-hibernate-resume-generator.xml 2018-06-22 06:11:49.000000000 -0500 +++ systemd-239/man/systemd-hibernate-resume-generator.xml 2018-11-04 08:49:10.187692735 -0600 @@ -28,11 +28,13 @@ Description - systemd-hibernate-resume-generator is a - generator that instantiates + systemd-hibernate-resume-generator is a + generator that initiates the procedure to resume the system from hibernation. + It instantiates the systemd-hibernate-resume@.service8 unit according to the value of parameter - specified on the kernel command line. + specified on the kernel command line, which will instruct the kernel + to resume the system from the hibernation image on that device. @@ -54,6 +56,12 @@ supported. + + noresume + + Do not try to resume from hibernation. If this parameter is + present, resume= is ignored. + diff -Naurp systemd-239-orig/man/systemd.mount.xml systemd-239/man/systemd.mount.xml --- systemd-239-orig/man/systemd.mount.xml 2018-06-22 06:11:49.000000000 -0500 +++ systemd-239/man/systemd.mount.xml 2018-11-04 08:49:10.188692734 -0600 @@ -370,12 +370,10 @@ - With , this mount will - be only wanted, not required, by - local-fs.target or - remote-fs.target. This means that the - boot will continue even if this mount point is not mounted - successfully. + With , this mount will be only wanted, not required, by + local-fs.target or remote-fs.target. Moreover the mount unit is not + ordered before these target units. This means that the boot will continue without waiting for the mount unit + and regardless whether the mount point can be mounted successfully. diff -Naurp systemd-239-orig/man/systemd.netdev.xml systemd-239/man/systemd.netdev.xml --- systemd-239-orig/man/systemd.netdev.xml 2018-06-22 06:11:49.000000000 -0500 +++ systemd-239/man/systemd.netdev.xml 2018-11-04 08:49:10.188692734 -0600 @@ -1003,7 +1003,7 @@ (see wg8). This option is mandatory to use WireGuard. Note that because this information is secret, you may want to set - the permissions of the .netdev file to be owned by root:systemd-networkd + the permissions of the .netdev file to be owned by root:systemd-network with a 0640 file mode. diff -Naurp systemd-239-orig/man/systemd.network.xml systemd-239/man/systemd.network.xml --- systemd-239-orig/man/systemd.network.xml 2018-06-22 06:11:49.000000000 -0500 +++ systemd-239/man/systemd.network.xml 2018-11-04 08:49:10.188692734 -0600 @@ -1069,7 +1069,7 @@ Protocol= - The Protocol identifier for the route. Takes a number between 0 and 255 or the special values + The protocol identifier for the route. Takes a number between 0 and 255 or the special values kernel, boot and static. Defaults to static. @@ -1159,6 +1159,7 @@ When true, the interface maximum transmission unit from the DHCP server will be used on the current link. + If MTUBytes= is set, then this setting is ignored. Defaults to false. diff -Naurp systemd-239-orig/man/systemd.nspawn.xml systemd-239/man/systemd.nspawn.xml --- systemd-239-orig/man/systemd.nspawn.xml 2018-06-22 06:11:49.000000000 -0500 +++ systemd-239/man/systemd.nspawn.xml 2018-11-04 08:49:10.188692734 -0600 @@ -340,7 +340,7 @@ Timezone= Configures how /etc/localtime in the container shall be handled. This is - equivalent to the command line switch, and takes the same argument. See + equivalent to the command line switch, and takes the same argument. See systemd-nspawn1 for details. diff -Naurp systemd-239-orig/man/systemd.service.xml systemd-239/man/systemd.service.xml --- systemd-239-orig/man/systemd.service.xml 2018-06-22 06:11:49.000000000 -0500 +++ systemd-239/man/systemd.service.xml 2018-11-04 08:49:10.188692734 -0600 @@ -318,7 +318,7 @@ - - If the executable path is prefixed with -, an exit code of the command normally considered a failure (i.e. non-zero exit status or abnormal exit due to signal) is ignored and considered success. + If the executable path is prefixed with -, an exit code of the command normally considered a failure (i.e. non-zero exit status or abnormal exit due to signal) is recorded, but has no further effect and is considered equivalent to success. diff -Naurp systemd-239-orig/man/systemd-sleep.conf.xml systemd-239/man/systemd-sleep.conf.xml --- systemd-239-orig/man/systemd-sleep.conf.xml 2018-06-22 06:11:49.000000000 -0500 +++ systemd-239/man/systemd-sleep.conf.xml 2018-11-04 08:49:10.187692735 -0600 @@ -114,6 +114,24 @@ + AllowSuspend= + AllowHibernation= + AllowSuspendThenHibernate= + AllowHybridSleep= + + By default any power-saving mode is advertised if possible (i.e. + the kernel supports that mode, the necessary resources are available). Those + switches can be used to disable specific modes. + + If AllowHibernation=no or AllowSuspend=no is + used, this implies AllowSuspendThenHibernate=no and + AllowHybridSleep=no, since those methods use both suspend and hibernation + internally. AllowSuspendThenHibernate=yes and + AllowHybridSleep=yes can be used to override and enable those specific + modes. + + + SuspendMode= HibernateMode= HybridSleepMode= diff -Naurp systemd-239-orig/man/systemd.special.xml systemd-239/man/systemd.special.xml --- systemd-239-orig/man/systemd.special.xml 2018-06-22 06:11:49.000000000 -0500 +++ systemd-239/man/systemd.special.xml 2018-11-04 08:49:10.188692734 -0600 @@ -1052,7 +1052,8 @@ PartOf=graphical-session.target systemd.target5, systemd.slice5, bootup7, - systemd-fstab-generator8 + systemd-fstab-generator8, + user@.service5 diff -Naurp systemd-239-orig/man/systemd-system.conf.xml systemd-239/man/systemd-system.conf.xml --- systemd-239-orig/man/systemd-system.conf.xml 2018-06-22 06:11:49.000000000 -0500 +++ systemd-239/man/systemd-system.conf.xml 2018-11-04 08:49:10.187692735 -0600 @@ -322,15 +322,16 @@ DefaultBlockIOAccounting= DefaultMemoryAccounting= DefaultTasksAccounting= + DefaultIOAccounting= DefaultIPAccounting= Configure the default resource accounting settings, as configured per-unit by CPUAccounting=, BlockIOAccounting=, MemoryAccounting=, - TasksAccounting= and IPAccounting=. See + TasksAccounting=, IOAccounting= and IPAccounting=. See systemd.resource-control5 for details on the per-unit settings. DefaultTasksAccounting= defaults to on, DefaultMemoryAccounting= to &MEMORY_ACCOUNTING_DEFAULT;, - the other three settings to off. + the other four settings to off. diff -Naurp systemd-239-orig/man/systemd.timer.xml systemd-239/man/systemd.timer.xml --- systemd-239-orig/man/systemd.timer.xml 2018-06-22 06:11:49.000000000 -0500 +++ systemd-239/man/systemd.timer.xml 2018-11-04 08:49:10.188692734 -0600 @@ -213,7 +213,7 @@ distributed amount of time between 0 and the specified time value. Defaults to 0, indicating that no randomized delay shall be applied. Each timer unit will determine this delay - randomly each time it is started, and the delay will simply be + randomly before each iteration, and the delay will simply be added on top of the next determined elapsing time. This is useful to stretch dispatching of similarly configured timer events over a certain amount time, to avoid that they all fire diff -Naurp systemd-239-orig/man/systemd.time.xml systemd-239/man/systemd.time.xml --- systemd-239-orig/man/systemd.time.xml 2018-06-22 06:11:49.000000000 -0500 +++ systemd-239/man/systemd.time.xml 2018-11-04 08:49:10.188692734 -0600 @@ -50,7 +50,7 @@ understood: - usec, us + usec, us, µs msec, ms seconds, second, sec, s minutes, minute, min, m diff -Naurp systemd-239-orig/man/user@.service.xml systemd-239/man/user@.service.xml --- systemd-239-orig/man/user@.service.xml 1969-12-31 18:00:00.000000000 -0600 +++ systemd-239/man/user@.service.xml 2018-11-04 08:49:10.188692734 -0600 @@ -0,0 +1,190 @@ + + + + + + + user@.service + systemd + + + + user@.service + 5 + + + + user@.service + user-runtime-dir@.service + System units to manager user processes + + + + user@UID.service + user-runtime-dir@UID.service + user-UID.slice + + + + Description + + The + systemd1 + system manager (PID 1) starts user manager instances as + user@UID.service, where the user's numerical UID + is used as the instance identifier. Each systemd --user instance manages a + hierarchy of its own units. See + systemd1 for + a discussion of systemd units and + systemd.special1 + for a list of units that form the basis of the unit hierarchies of system and user units. + + user@UID.service is accompanied by the + system unit user-runtime-dir@UID.service, which + creates the user's runtime directory + /run/user/UID, and then removes it when this + unit is stopped. + + User processes may be started by the user@.service instance, in which + case they will be part of that unit in the system hierarchy. They may also be started elsewhere, + for example by + sshd8 or a + display manager like gdm, in which case they form a .scope unit (see + systemd.scope5). + Both user@UID.service and the scope units are + collected under a user-UID.slice. + + Individual user-UID.slice slices are + collected under user.slice, see + systemd.special8. + + + + + Controlling resources for logged-in users + + Options that control resources available to logged-in users can be configured at a few + different levels. As described in the previous section, user.slice contains + processes of all users, so any resource limits on that slice apply to all users together. The + usual way to configure them would be through drop-ins, e.g. /etc/systemd/system/user.slice.d/resources.conf. + + + The processes of a single user are collected under + user-UID.slice. Resource limits for that user + can be configured through drop-ins for that unit, e.g. /etc/systemd/system/user-1000.slice.d/resources.conf. If the limits + should apply to all users instead, they may be configured through drop-ins for the truncated + unit name, user-.slice. For example, configuration in /etc/systemd/system/user-.slice.d/resources.conf is included in all + user-UID.slice units, see + systemd.unit5 + for a discussion of the drop-in mechanism. + + When a user logs in and a .scope unit is created for the session (see previous section), + the creation of the scope may be managed through + pam_systemd8. + This PAM module communicates with + systemd-logind8 + to create the session scope and provide access to hardware resources. Resource limits for the + scope may be configured through the PAM module configuration, see + pam_systemd8. + Configuring them through the normal unit configuration is also possible, but since + the name of the slice unit is generally unpredictable, this is less useful. + + In general any resources that apply to units may be set for + user@UID.service and the slice + units discussed above, see + systemd.resource-control5 + for an overview. + + + + Examples + + Hierarchy of control groups with two logged in users + + $ systemd-cgls +Control group /: +-.slice +├─user.slice +│ ├─user-1000.slice +│ │ ├─user@1000.service +│ │ │ ├─pulseaudio.service +│ │ │ │ └─2386 /usr/bin/pulseaudio --daemonize=no +│ │ │ └─gnome-terminal-server.service +│ │ │ └─init.scope +│ │ │ ├─ 4127 /usr/libexec/gnome-terminal-server +│ │ │ └─ 4198 zsh +│ │ … +│ │ └─session-4.scope +│ │ ├─ 1264 gdm-session-worker [pam/gdm-password] +│ │ ├─ 2339 /usr/bin/gnome-shell +│ │ … +│ │ ├─session-19.scope +│ │ ├─6497 sshd: zbyszek [priv] +│ │ ├─6502 sshd: zbyszek@pts/6 +│ │ ├─6509 -zsh +│ │ └─6602 systemd-cgls --no-pager +│ … +│ └─user-1001.slice +│ ├─session-20.scope +│ │ ├─6675 sshd: guest [priv] +│ │ ├─6708 sshd: guest@pts/6 +│ │ └─6717 -bash +│ └─user@1001.service +│ ├─init.scope +│ │ ├─6680 /usr/lib/systemd/systemd --user +│ │ └─6688 (sd-pam) +│ └─sleep.service +│ └─6706 /usr/bin/sleep 30 +… + User with UID 1000 is logged in using gdm (session-4.scope) and + ssh1 + (session-19.scope), and also has a user manager instance + running (user@1000.service). User with UID 1001 is logged + in using ssh (session-20.scope) and + also has a user manager instance running (user@1001.service). Those are all (leaf) system units, and form + part of the slice hierarchy, with user-1000.slice and + user-1001.slice below user.slice. User units are visible below the + user@.service instances (pulseaudio.service, gnome-terminal-server.service, init.scope, sleep.service). + + + + + Default user resource limits + + $ systemctl cat user-1000.slice +# /usr/lib/systemd/system/user-.slice.d/10-defaults.conf +# … +[Unit] +Description=User Slice of UID %j +After=systemd-user-sessions.service + +[Slice] +TasksMax=33% + The user-UID.slice units by default don't + have a unit file. The resource limits are set through a drop-in, which can be easily replaced + or extended following standard drop-in mechanisms discussed in the first section. + + + + + See Also + + systemd1, + systemd.service5, + systemd.slice5, + systemd.resource-control5, + systemd.exec5, + systemd.special7, + pam8 + + + diff -Naurp systemd-239-orig/meson.build systemd-239/meson.build --- systemd-239-orig/meson.build 2018-06-22 06:11:49.000000000 -0500 +++ systemd-239/meson.build 2018-11-04 08:49:10.176692740 -0600 @@ -370,6 +370,10 @@ foreach arg : ['unused-parameter', 'unused-result', 'format-signedness', 'error=nonnull', # work-around for gcc 7.1 turning this on on its own + + # Disable -Wmaybe-uninitialized, since it's noisy on gcc 8 with + # optimizations enabled, producing essentially false positives. + 'maybe-uninitialized', ] if cc.has_argument('-W' + arg) add_project_arguments('-Wno-' + arg, language : 'c') @@ -421,7 +425,6 @@ decl_headers = ''' #include #include #include -#include #include ''' # FIXME: key_serial_t is only defined in keyutils.h, this is bound to fail @@ -435,10 +438,24 @@ foreach decl : ['char16_t', ] # We get -1 if the size cannot be determined - have = cc.sizeof(decl, prefix : decl_headers) > 0 + have = cc.sizeof(decl, prefix : decl_headers, args : '-D_GNU_SOURCE') > 0 + + if decl == 'struct statx' + if have + want_linux_stat_h = false + else + have = cc.sizeof(decl, + prefix : decl_headers + '#include ', + args : '-D_GNU_SOURCE') > 0 + want_linux_stat_h = have + endif + endif + conf.set10('HAVE_' + decl.underscorify().to_upper(), have) endforeach +conf.set10('WANT_LINUX_STAT_H', want_linux_stat_h) + foreach decl : [['IFLA_INET6_ADDR_GEN_MODE', 'linux/if_link.h'], ['IN6_ADDR_GEN_MODE_STABLE_PRIVACY', 'linux/if_link.h'], ['IFLA_VRF_TABLE', 'linux/if_link.h'], @@ -678,41 +695,43 @@ substs.set('containeruidbasemax', contai nobody_user = get_option('nobody-user') nobody_group = get_option('nobody-group') -getent_result = run_command('getent', 'passwd', '65534') -if getent_result.returncode() == 0 - name = getent_result.stdout().split(':')[0] - if name != nobody_user - warning('\n' + - 'The local user with the UID 65534 does not match the configured user name "@0@" of the nobody user (its name is @1@).\n'.format(nobody_user, name) + - 'Your build will result in an user table setup that is incompatible with the local system.') - endif -endif -id_result = run_command('id', '-u', nobody_user) -if id_result.returncode() == 0 - id = id_result.stdout().to_int() - if id != 65534 - warning('\n' + - 'The local user with the configured user name "@0@" of the nobody user does not have UID 65534 (it has @1@).\n'.format(nobody_user, id) + - 'Your build will result in an user table setup that is incompatible with the local system.') +if not meson.is_cross_build() + getent_result = run_command('getent', 'passwd', '65534') + if getent_result.returncode() == 0 + name = getent_result.stdout().split(':')[0] + if name != nobody_user + warning('\n' + + 'The local user with the UID 65534 does not match the configured user name "@0@" of the nobody user (its name is @1@).\n'.format(nobody_user, name) + + 'Your build will result in an user table setup that is incompatible with the local system.') + endif + endif + id_result = run_command('id', '-u', nobody_user) + if id_result.returncode() == 0 + id = id_result.stdout().to_int() + if id != 65534 + warning('\n' + + 'The local user with the configured user name "@0@" of the nobody user does not have UID 65534 (it has @1@).\n'.format(nobody_user, id) + + 'Your build will result in an user table setup that is incompatible with the local system.') + endif endif -endif -getent_result = run_command('getent', 'group', '65534') -if getent_result.returncode() == 0 - name = getent_result.stdout().split(':')[0] - if name != nobody_group - warning('\n' + - 'The local group with the GID 65534 does not match the configured group name "@0@" of the nobody group (its name is @1@).\n'.format(nobody_group, name) + - 'Your build will result in an group table setup that is incompatible with the local system.') - endif -endif -id_result = run_command('id', '-g', nobody_group) -if id_result.returncode() == 0 - id = id_result.stdout().to_int() - if id != 65534 - warning('\n' + - 'The local group with the configured group name "@0@" of the nobody group does not have UID 65534 (it has @1@).\n'.format(nobody_group, id) + - 'Your build will result in an group table setup that is incompatible with the local system.') + getent_result = run_command('getent', 'group', '65534') + if getent_result.returncode() == 0 + name = getent_result.stdout().split(':')[0] + if name != nobody_group + warning('\n' + + 'The local group with the GID 65534 does not match the configured group name "@0@" of the nobody group (its name is @1@).\n'.format(nobody_group, name) + + 'Your build will result in an group table setup that is incompatible with the local system.') + endif + endif + id_result = run_command('id', '-g', nobody_group) + if id_result.returncode() == 0 + id = id_result.stdout().to_int() + if id != 65534 + warning('\n' + + 'The local group with the configured group name "@0@" of the nobody group does not have UID 65534 (it has @1@).\n'.format(nobody_group, id) + + 'Your build will result in an group table setup that is incompatible with the local system.') + endif endif endif if nobody_user != nobody_group and not (nobody_user == 'nobody' and nobody_group == 'nogroup') @@ -741,7 +760,9 @@ substs.set('USERS_GID', users_gid) conf.set10('ENABLE_ADM_GROUP', get_option('adm-group')) conf.set10('ENABLE_WHEEL_GROUP', get_option('wheel-group')) -substs.set('DEV_KVM_MODE', get_option('dev-kvm-mode')) +dev_kvm_mode = get_option('dev-kvm-mode') +substs.set('DEV_KVM_MODE', dev_kvm_mode) +conf.set10('DEV_KVM_UACCESS', dev_kvm_mode != '0666') substs.set('GROUP_RENDER_MODE', get_option('group-render-mode')) kill_user_processes = get_option('default-kill-user-processes') @@ -764,7 +785,7 @@ substs.set('DEBUGTTY', get_option('debug enable_debug_hashmap = false enable_debug_mmap_cache = false -foreach name : get_option('debug') +foreach name : get_option('debug-extra') if name == 'hashmap' enable_debug_hashmap = true elif name == 'mmap-cache' @@ -1137,7 +1158,7 @@ substs.set('DEFAULT_DNSSEC_MODE', defaul dns_over_tls = get_option('dns-over-tls') if dns_over_tls != 'false' - have = conf.get('HAVE_GNUTLS') == 1 + have = libgnutls != [] and libgnutls.version().version_compare('>=3.5.3') if dns_over_tls == 'true' and not have error('DNS-over-TLS support was requested, but dependencies are not available') endif @@ -1162,7 +1183,6 @@ want_importd = get_option('importd') if want_importd != 'false' have = (conf.get('HAVE_LIBCURL') == 1 and conf.get('HAVE_ZLIB') == 1 and - conf.get('HAVE_BZIP2') == 1 and conf.get('HAVE_XZ') == 1 and conf.get('HAVE_GCRYPT') == 1) if want_importd == 'true' and not have @@ -1319,7 +1339,7 @@ libjournal_core = static_library( libsystemd_sym_path = '@0@/@1@'.format(meson.current_source_dir(), libsystemd_sym) libsystemd = shared_library( 'systemd', - 'src/systemd/sd-id128.h', # pick a header file at random to work around old meson bug + disable_mempool_c, version : libsystemd_version, include_directories : includes, link_args : ['-shared', @@ -1345,6 +1365,7 @@ install_libsystemd_static = static_libra journal_client_sources, basic_sources, basic_gcrypt_sources, + disable_mempool_c, include_directories : includes, build_by_default : static_libsystemd != 'false', install : static_libsystemd != 'false', @@ -1401,6 +1422,7 @@ subdir('test') test_dlopen = executable( 'test-dlopen', test_dlopen_c, + disable_mempool_c, include_directories : includes, link_with : [libbasic], dependencies : [libdl]) @@ -1420,6 +1442,7 @@ foreach tuple : [['myhostname', 'ENABLE_ nss = shared_library( 'nss_' + module, 'src/nss-@0@/nss-@0@.c'.format(module), + disable_mempool_c, version : '2', include_directories : includes, # Note that we link NSS modules with '-z nodelete' so that mempools never get orphaned @@ -1688,15 +1711,15 @@ if conf.get('ENABLE_LOGIND') == 1 test_dlopen, args : [pam_systemd.full_path()]) # path to dlopen must include a slash endif -endif -executable('systemd-user-runtime-dir', - user_runtime_dir_sources, - include_directories : includes, - link_with : [libshared, liblogind_core], - install_rpath : rootlibexecdir, - install : true, - install_dir : rootlibexecdir) + executable('systemd-user-runtime-dir', + user_runtime_dir_sources, + include_directories : includes, + link_with : [libshared], + install_rpath : rootlibexecdir, + install : true, + install_dir : rootlibexecdir) +endif if conf.get('HAVE_PAM') == 1 executable('systemd-user-sessions', @@ -2686,12 +2709,9 @@ subdir('shell-completion/zsh') subdir('doc/sysvinit') subdir('doc/var-log') -# FIXME: figure out if the warning is true: -# https://github.com/mesonbuild/meson/wiki/Reference-manual#install_subdir install_subdir('factory/etc', install_dir : factorydir) - install_data('xorg/50-systemd-user.sh', install_dir : xinitrcdir) install_data('modprobe.d/systemd.conf', @@ -2890,6 +2910,10 @@ alt_time_epoch = run_command('date', '-I status += [ 'time epoch: @0@ (@1@)'.format(time_epoch, alt_time_epoch)] +status += [ + 'static libsystemd: @0@'.format(get_option('static-libsystemd')), + 'static libudev: @0@'.format(get_option('static-libudev'))] + # TODO: # CFLAGS: ${OUR_CFLAGS} ${CFLAGS} # CPPFLAGS: ${OUR_CPPFLAGS} ${CPPFLAGS} @@ -2985,6 +3009,8 @@ foreach tuple : [ ['debug hashmap'], ['debug mmap cache'], ['valgrind', conf.get('VALGRIND') == 1], + ['link-udev-shared', get_option('link-udev-shared')], + ['link-systemctl-shared', get_option('link-systemctl-shared')], ] if tuple.length() >= 2 diff -Naurp systemd-239-orig/meson_options.txt systemd-239/meson_options.txt --- systemd-239-orig/meson_options.txt 2018-06-22 06:11:49.000000000 -0500 +++ systemd-239/meson_options.txt 2018-11-04 08:49:10.176692740 -0600 @@ -46,7 +46,7 @@ option('debug-shell', type : 'string', v description : 'path to debug shell binary') option('debug-tty', type : 'string', value : '/dev/tty9', description : 'specify the tty device for debug shell') -option('debug', type : 'array', choices : ['hashmap', 'mmap-cache'], value : [], +option('debug-extra', type : 'array', choices : ['hashmap', 'mmap-cache'], value : [], description : 'enable extra debugging') option('memory-accounting-default', type : 'boolean', description : 'enable MemoryAccounting= by default') @@ -278,9 +278,9 @@ option('dbus', type : 'combo', choices : option('gnu-efi', type : 'combo', choices : ['auto', 'true', 'false'], description : 'gnu-efi support for sd-boot') -option('efi-cc', type : 'string', value : 'gcc', +option('efi-cc', type : 'string', description : 'the compiler to use for EFI modules') -option('efi-ld', type : 'string', value : 'ld', +option('efi-ld', type : 'string', description : 'the linker to use for EFI modules') option('efi-libdir', type : 'string', description : 'path to the EFI lib directory') diff -Naurp systemd-239-orig/README systemd-239/README --- systemd-239-orig/README 2018-06-22 06:11:49.000000000 -0500 +++ systemd-239/README 2018-11-04 08:49:10.176692740 -0600 @@ -154,6 +154,7 @@ REQUIREMENTS: libmicrohttpd (optional) libpython (optional) libidn2 or libidn (optional) + gnutls >= 3.1.4 (optional, >= 3.5.3 is necessary to support DNS-over-TLS) elfutils >= 158 (optional) polkit (optional) pkg-config diff -Naurp systemd-239-orig/shell-completion/bash/journalctl systemd-239/shell-completion/bash/journalctl --- systemd-239-orig/shell-completion/bash/journalctl 2018-06-22 06:11:49.000000000 -0500 +++ systemd-239/shell-completion/bash/journalctl 2018-11-04 08:49:10.190692734 -0600 @@ -46,9 +46,9 @@ _journalctl() { --flush --rotate --sync --no-hostname -N --fields' [ARG]='-b --boot -D --directory --file -F --field -t --identifier -M --machine -o --output -u --unit --user-unit -p --priority - --root' + --root --case-sensitive' [ARGUNKNOWN]='-c --cursor --interval -n --lines -S --since -U --until - --after-cursor --verify-key + --after-cursor --verify-key -g --grep --vacuum-size --vacuum-time --vacuum-files --output-fields' ) @@ -86,6 +86,9 @@ _journalctl() { --identifier|-t) comps=$(journalctl -F 'SYSLOG_IDENTIFIER' 2>/dev/null) ;; + --case-sensitive) + comps='yes no' + ;; *) return 0 ;; diff -Naurp systemd-239-orig/src/analyze/analyze.c systemd-239/src/analyze/analyze.c --- systemd-239-orig/src/analyze/analyze.c 2018-06-22 06:11:49.000000000 -0500 +++ systemd-239/src/analyze/analyze.c 2018-11-04 08:49:10.190692734 -0600 @@ -653,12 +653,13 @@ static int analyze_plot(int argc, char * if (text_width > text_start && text_width + text_start > width) width = text_width + text_start; - if (u->deactivated > u->activating && u->deactivated <= boot->finish_time - && u->activated == 0 && u->deactivating == 0) + if (u->deactivated > u->activating && + u->deactivated <= boot->finish_time && + u->activated == 0 && u->deactivating == 0) u->activated = u->deactivating = u->deactivated; if (u->activated < u->activating || u->activated > boot->finish_time) u->activated = boot->finish_time; - if (u->deactivating < u->activated || u->activated > boot->finish_time) + if (u->deactivating < u->activated || u->deactivating > boot->finish_time) u->deactivating = boot->finish_time; if (u->deactivated < u->deactivating || u->deactivated > boot->finish_time) u->deactivated = boot->finish_time; @@ -890,11 +891,8 @@ static int list_dependencies_one(sd_bus STRV_FOREACH(c, deps) { times = hashmap_get(unit_times_hashmap, *c); if (times_in_range(times, boot) && - (times->activated >= service_longest - || service_longest == 0)) { + times->activated >= service_longest) service_longest = times->activated; - break; - } } if (service_longest == 0) diff -Naurp systemd-239-orig/src/basic/alloc-util.h systemd-239/src/basic/alloc-util.h --- systemd-239-orig/src/basic/alloc-util.h 2018-06-22 06:11:49.000000000 -0500 +++ systemd-239/src/basic/alloc-util.h 2018-11-04 08:49:10.191692733 -0600 @@ -46,6 +46,21 @@ static inline void *mfree(void *memory) void* memdup(const void *p, size_t l) _alloc_(2); void* memdup_suffix0(const void *p, size_t l) _alloc_(2); +#define memdupa(p, l) \ + ({ \ + void *_q_; \ + _q_ = alloca(l); \ + memcpy(_q_, p, l); \ + }) + +#define memdupa_suffix0(p, l) \ + ({ \ + void *_q_; \ + _q_ = alloca(l + 1); \ + ((uint8_t*) _q_)[l] = 0; \ + memcpy(_q_, p, l); \ + }) + static inline void freep(void *p) { free(*(void**) p); } diff -Naurp systemd-239-orig/src/basic/btrfs-util.c systemd-239/src/basic/btrfs-util.c --- systemd-239-orig/src/basic/btrfs-util.c 2018-06-22 06:11:49.000000000 -0500 +++ systemd-239/src/basic/btrfs-util.c 2018-11-04 08:49:10.191692733 -0600 @@ -866,7 +866,7 @@ int btrfs_subvol_set_subtree_quota_limit int btrfs_resize_loopback_fd(int fd, uint64_t new_size, bool grow_only) { struct btrfs_ioctl_vol_args args = {}; - char p[SYS_BLOCK_PATH_MAX("/loop/backing_file")]; + char p[SYS_BLOCK_PATH_MAX("/loop/backing_file")], q[DEV_NUM_PATH_MAX]; _cleanup_free_ char *backing = NULL; _cleanup_close_ int loop_fd = -1, backing_fd = -1; struct stat st; @@ -911,8 +911,8 @@ int btrfs_resize_loopback_fd(int fd, uin if (grow_only && new_size < (uint64_t) st.st_size) return -EINVAL; - xsprintf_sys_block_path(p, NULL, dev); - loop_fd = open(p, O_RDWR|O_CLOEXEC|O_NOCTTY); + xsprintf_dev_num_path(q, "block", dev); + loop_fd = open(q, O_RDWR|O_CLOEXEC|O_NOCTTY); if (loop_fd < 0) return -errno; diff -Naurp systemd-239-orig/src/basic/env-util.h systemd-239/src/basic/env-util.h --- systemd-239-orig/src/basic/env-util.h 2018-06-22 06:11:49.000000000 -0500 +++ systemd-239/src/basic/env-util.h 2018-11-04 08:49:10.191692733 -0600 @@ -4,6 +4,7 @@ #include #include #include +#include #include "macro.h" diff -Naurp systemd-239-orig/src/basic/exec-util.c systemd-239/src/basic/exec-util.c --- systemd-239-orig/src/basic/exec-util.c 2018-06-22 06:11:49.000000000 -0500 +++ systemd-239/src/basic/exec-util.c 2018-11-04 08:49:10.192692732 -0600 @@ -71,11 +71,12 @@ static int do_execute( gather_stdout_callback_t const callbacks[_STDOUT_CONSUME_MAX], void* const callback_args[_STDOUT_CONSUME_MAX], int output_fd, - char *argv[]) { + char *argv[], + char *envp[]) { _cleanup_hashmap_free_free_ Hashmap *pids = NULL; _cleanup_strv_free_ char **paths = NULL; - char **path; + char **path, **e; int r; /* We fork this all off from a child process so that we can somewhat cleanly make @@ -86,7 +87,7 @@ static int do_execute( r = conf_files_list_strv(&paths, NULL, NULL, CONF_FILES_EXECUTABLE|CONF_FILES_REGULAR|CONF_FILES_FILTER_MASKED, (const char* const*) directories); if (r < 0) - return r; + return log_error_errno(r, "Failed to enumerate executables: %m"); if (!callbacks) { pids = hashmap_new(NULL); @@ -100,6 +101,10 @@ static int do_execute( if (timeout != USEC_INFINITY) alarm(DIV_ROUND_UP(timeout, USEC_PER_SEC)); + STRV_FOREACH(e, envp) + if (putenv(*e) != 0) + return log_error_errno(errno, "Failed to set environment variable: %m"); + STRV_FOREACH(path, paths) { _cleanup_free_ char *t = NULL; _cleanup_close_ int fd = -1; @@ -166,7 +171,8 @@ int execute_directories( usec_t timeout, gather_stdout_callback_t const callbacks[_STDOUT_CONSUME_MAX], void* const callback_args[_STDOUT_CONSUME_MAX], - char *argv[]) { + char *argv[], + char *envp[]) { char **dirs = (char**) directories; _cleanup_close_ int fd = -1; @@ -197,7 +203,7 @@ int execute_directories( if (r < 0) return r; if (r == 0) { - r = do_execute(dirs, timeout, callbacks, callback_args, fd, argv); + r = do_execute(dirs, timeout, callbacks, callback_args, fd, argv, envp); _exit(r < 0 ? EXIT_FAILURE : EXIT_SUCCESS); } diff -Naurp systemd-239-orig/src/basic/exec-util.h systemd-239/src/basic/exec-util.h --- systemd-239-orig/src/basic/exec-util.h 2018-06-22 06:11:49.000000000 -0500 +++ systemd-239/src/basic/exec-util.h 2018-11-04 08:49:10.192692732 -0600 @@ -18,6 +18,7 @@ int execute_directories( usec_t timeout, gather_stdout_callback_t const callbacks[_STDOUT_CONSUME_MAX], void* const callback_args[_STDOUT_CONSUME_MAX], - char *argv[]); + char *argv[], + char *envp[]); extern const gather_stdout_callback_t gather_environment[_STDOUT_CONSUME_MAX]; diff -Naurp systemd-239-orig/src/basic/fd-util.c systemd-239/src/basic/fd-util.c --- systemd-239-orig/src/basic/fd-util.c 2018-06-22 06:11:49.000000000 -0500 +++ systemd-239/src/basic/fd-util.c 2018-11-04 08:49:10.192692732 -0600 @@ -353,22 +353,22 @@ bool fdname_is_valid(const char *s) { } int fd_get_path(int fd, char **ret) { - _cleanup_close_ int dir = -1; - char fdname[DECIMAL_STR_MAX(int)]; + char procfs_path[STRLEN("/proc/self/fd/") + DECIMAL_STR_MAX(int)]; int r; - dir = open("/proc/self/fd/", O_CLOEXEC | O_DIRECTORY | O_PATH); - if (dir < 0) - /* /proc is not available or not set up properly, we're most likely - * in some chroot environment. */ - return errno == ENOENT ? -EOPNOTSUPP : -errno; + xsprintf(procfs_path, "/proc/self/fd/%i", fd); + r = readlink_malloc(procfs_path, ret); + if (r == -ENOENT) { + /* ENOENT can mean two things: that the fd does not exist or that /proc is not mounted. Let's make + * things debuggable and distuingish the two. */ - xsprintf(fdname, "%i", fd); + if (access("/proc/self/fd/", F_OK) < 0) + /* /proc is not available or not set up properly, we're most likely in some chroot + * environment. */ + return errno == ENOENT ? -EOPNOTSUPP : -errno; - r = readlinkat_malloc(dir, fdname, ret); - if (r == -ENOENT) - /* If the file doesn't exist the fd is invalid */ - return -EBADF; + return -EBADF; /* The directory exists, hence it's the fd that doesn't. */ + } return r; } diff -Naurp systemd-239-orig/src/basic/fd-util.h systemd-239/src/basic/fd-util.h --- systemd-239-orig/src/basic/fd-util.h 2018-06-22 06:11:49.000000000 -0500 +++ systemd-239/src/basic/fd-util.h 2018-11-04 08:49:10.192692732 -0600 @@ -78,8 +78,12 @@ int acquire_data_fd(const void *data, si int fd_duplicate_data_fd(int fd); /* Hint: ENETUNREACH happens if we try to connect to "non-existing" special IP addresses, such as ::5 */ -#define ERRNO_IS_DISCONNECT(r) \ - IN_SET(r, ENOTCONN, ECONNRESET, ECONNREFUSED, ECONNABORTED, EPIPE, ENETUNREACH) +/* The kernel sends e.g., EHOSTUNREACH or ENONET to userspace in some ICMP error cases. + * See the icmp_err_convert[] in net/ipv4/icmp.c in the kernel sources */ +#define ERRNO_IS_DISCONNECT(r) \ + IN_SET(r, \ + ENOTCONN, ECONNRESET, ECONNREFUSED, ECONNABORTED, EPIPE, \ + ENETUNREACH, EHOSTUNREACH, ENOPROTOOPT, EHOSTDOWN, ENONET) /* Resource exhaustion, could be our fault or general system trouble */ #define ERRNO_IS_RESOURCE(r) \ diff -Naurp systemd-239-orig/src/basic/fileio.c systemd-239/src/basic/fileio.c --- systemd-239-orig/src/basic/fileio.c 2018-06-22 06:11:49.000000000 -0500 +++ systemd-239/src/basic/fileio.c 2018-11-04 08:49:10.192692732 -0600 @@ -1488,6 +1488,7 @@ int open_serialization_fd(const char *id } int link_tmpfile(int fd, const char *path, const char *target) { + int r; assert(fd >= 0); assert(target); @@ -1500,8 +1501,9 @@ int link_tmpfile(int fd, const char *pat * operation currently (renameat2() does), and there is no nice way to emulate this. */ if (path) { - if (rename_noreplace(AT_FDCWD, path, AT_FDCWD, target) < 0) - return -errno; + r = rename_noreplace(AT_FDCWD, path, AT_FDCWD, target); + if (r < 0) + return r; } else { char proc_fd_path[STRLEN("/proc/self/fd/") + DECIMAL_STR_MAX(fd) + 1]; diff -Naurp systemd-239-orig/src/basic/format-table.c systemd-239/src/basic/format-table.c --- systemd-239-orig/src/basic/format-table.c 2018-06-22 06:11:49.000000000 -0500 +++ systemd-239/src/basic/format-table.c 2018-11-04 08:49:10.192692732 -0600 @@ -36,7 +36,7 @@ that. The first row is always the header row. If header display is turned off we simply skip outputting the first row. Also, when sorting rows we always leave the first row where it is, as the header shouldn't move. - - Note because there's no row and no column object some properties that might be approproate as row/column properties + - Note because there's no row and no column object some properties that might be appropriate as row/column properties are exposed as cell properties instead. For example, the "weight" of a column (which is used to determine where to add/remove space preferable when expanding/compressing tables horizontally) is actually made the "weight" of a cell. Given that we usually need it per-column though we will calculate the average across every cell of the column @@ -73,11 +73,11 @@ typedef struct TableData { } TableData; static size_t TABLE_CELL_TO_INDEX(TableCell *cell) { - unsigned i; + size_t i; assert(cell); - i = PTR_TO_UINT(cell); + i = PTR_TO_SIZE(cell); assert(i > 0); return i-1; @@ -85,7 +85,7 @@ static size_t TABLE_CELL_TO_INDEX(TableC static TableCell* TABLE_INDEX_TO_CELL(size_t index) { assert(index != (size_t) -1); - return UINT_TO_PTR((unsigned) (index + 1)); + return SIZE_TO_PTR(index + 1); } struct Table { @@ -1134,14 +1134,12 @@ int table_print(Table *t, FILE *f) { assert(weight_sum >= column_weight[j]); weight_sum -= column_weight[j]; - if (restart) + if (restart && !finalize) break; } - if (finalize) { - assert(!restart); + if (finalize) break; - } if (!restart) finalize = true; diff -Naurp systemd-239-orig/src/basic/fs-util.c systemd-239/src/basic/fs-util.c --- systemd-239-orig/src/basic/fs-util.c 2018-06-22 06:11:49.000000000 -0500 +++ systemd-239/src/basic/fs-util.c 2018-11-04 08:49:10.192692732 -0600 @@ -129,7 +129,7 @@ int rename_noreplace(int olddirfd, const } int readlinkat_malloc(int fd, const char *p, char **ret) { - size_t l = 100; + size_t l = FILENAME_MAX+1; int r; assert(p); diff -Naurp systemd-239-orig/src/basic/hashmap.c systemd-239/src/basic/hashmap.c --- systemd-239-orig/src/basic/hashmap.c 2018-06-22 06:11:49.000000000 -0500 +++ systemd-239/src/basic/hashmap.c 2018-11-04 08:49:10.192692732 -0600 @@ -6,8 +6,8 @@ #include #include "alloc-util.h" -#include "hashmap.h" #include "fileio.h" +#include "hashmap.h" #include "macro.h" #include "mempool.h" #include "process-util.h" @@ -769,17 +769,16 @@ static void reset_direct_storage(Hashmap static struct HashmapBase *hashmap_base_new(const struct hash_ops *hash_ops, enum HashmapType type HASHMAP_DEBUG_PARAMS) { HashmapBase *h; const struct hashmap_type_info *hi = &hashmap_type_info[type]; - bool use_pool; - - use_pool = is_main_thread(); + bool up; - h = use_pool ? mempool_alloc0_tile(hi->mempool) : malloc0(hi->head_size); + up = mempool_enabled(); + h = up ? mempool_alloc0_tile(hi->mempool) : malloc0(hi->head_size); if (!h) return NULL; h->type = type; - h->from_pool = use_pool; + h->from_pool = up; h->hash_ops = hash_ops ? hash_ops : &trivial_hash_ops; if (type == HASHMAP_TYPE_ORDERED) { @@ -857,9 +856,11 @@ static void hashmap_free_no_clear(Hashma assert_se(pthread_mutex_unlock(&hashmap_debug_list_mutex) == 0); #endif - if (h->from_pool) + if (h->from_pool) { + /* Ensure that the object didn't get migrated between threads. */ + assert_se(is_main_thread()); mempool_free_tile(hashmap_type_info[h->type].mempool, h); - else + } else free(h); } diff -Naurp systemd-239-orig/src/basic/hexdecoct.c systemd-239/src/basic/hexdecoct.c --- systemd-239-orig/src/basic/hexdecoct.c 2018-06-22 06:11:49.000000000 -0500 +++ systemd-239/src/basic/hexdecoct.c 2018-11-04 08:49:10.192692732 -0600 @@ -592,8 +592,7 @@ static int base64_append_width( _cleanup_free_ char *x = NULL; char *t, *s; - ssize_t slen, len, avail; - int line, lines; + ssize_t len, slen, avail, line, lines; len = base64mem(p, l, &x); if (len <= 0) @@ -602,6 +601,9 @@ static int base64_append_width( lines = DIV_ROUND_UP(len, width); slen = strlen_ptr(sep); + if (lines > (SSIZE_MAX - plen - 1 - slen) / (indent + width + 1)) + return -ENOMEM; + t = realloc(*prefix, plen + 1 + slen + (indent + width + 1) * lines); if (!t) return -ENOMEM; diff -Naurp systemd-239-orig/src/basic/mempool.c systemd-239/src/basic/mempool.c --- systemd-239-orig/src/basic/mempool.c 2018-06-22 06:11:49.000000000 -0500 +++ systemd-239/src/basic/mempool.c 2018-11-04 08:49:10.192692732 -0600 @@ -3,8 +3,10 @@ #include #include +#include "env-util.h" #include "macro.h" #include "mempool.h" +#include "process-util.h" #include "util.h" struct pool { @@ -70,8 +72,21 @@ void mempool_free_tile(struct mempool *m mp->freelist = p; } -#if VALGRIND +bool mempool_enabled(void) { + static int b = -1; + + if (!is_main_thread()) + return false; + if (!mempool_use_allowed) + b = false; + if (b < 0) + b = getenv_bool("SYSTEMD_MEMPOOL") != 0; + + return b; +} + +#if VALGRIND void mempool_drop(struct mempool *mp) { struct pool *p = mp->first_pool; while (p) { @@ -81,5 +96,4 @@ void mempool_drop(struct mempool *mp) { p = n; } } - #endif diff -Naurp systemd-239-orig/src/basic/mempool.h systemd-239/src/basic/mempool.h --- systemd-239-orig/src/basic/mempool.h 2018-06-22 06:11:49.000000000 -0500 +++ systemd-239/src/basic/mempool.h 2018-11-04 08:49:10.192692732 -0600 @@ -1,7 +1,7 @@ /* SPDX-License-Identifier: LGPL-2.1+ */ #pragma once - +#include #include struct pool; @@ -23,6 +23,9 @@ static struct mempool pool_name = { \ .at_least = alloc_at_least, \ } +extern const bool mempool_use_allowed; +bool mempool_enabled(void); + #if VALGRIND void mempool_drop(struct mempool *mp); #endif diff -Naurp systemd-239-orig/src/basic/meson.build systemd-239/src/basic/meson.build --- systemd-239-orig/src/basic/meson.build 2018-06-22 06:11:49.000000000 -0500 +++ systemd-239/src/basic/meson.build 2018-11-04 08:49:10.192692732 -0600 @@ -121,7 +121,6 @@ basic_sources = files(''' mkdir-label.c mkdir.c mkdir.h - module-util.h mount-util.c mount-util.h nss-util.h diff -Naurp systemd-239-orig/src/basic/missing.h systemd-239/src/basic/missing.h --- systemd-239-orig/src/basic/missing.h 2018-06-22 06:11:49.000000000 -0500 +++ systemd-239/src/basic/missing.h 2018-11-04 08:49:10.192692732 -0600 @@ -15,7 +15,6 @@ #include #include #include -#include #include #include #include @@ -25,6 +24,10 @@ #include #include +#if WANT_LINUX_STAT_H +#include +#endif + #if HAVE_AUDIT #include #endif diff -Naurp systemd-239-orig/src/basic/module-util.h systemd-239/src/basic/module-util.h --- systemd-239-orig/src/basic/module-util.h 2018-06-22 06:11:49.000000000 -0500 +++ systemd-239/src/basic/module-util.h 1969-12-31 18:00:00.000000000 -0600 @@ -1,10 +0,0 @@ -/* SPDX-License-Identifier: LGPL-2.1+ */ -#pragma once - -#include - -#include "macro.h" - -DEFINE_TRIVIAL_CLEANUP_FUNC(struct kmod_ctx*, kmod_unref); -DEFINE_TRIVIAL_CLEANUP_FUNC(struct kmod_module*, kmod_module_unref); -DEFINE_TRIVIAL_CLEANUP_FUNC(struct kmod_list*, kmod_module_unref_list); diff -Naurp systemd-239-orig/src/basic/parse-util.c systemd-239/src/basic/parse-util.c --- systemd-239-orig/src/basic/parse-util.c 2018-06-22 06:11:49.000000000 -0500 +++ systemd-239/src/basic/parse-util.c 2018-11-04 08:49:10.193692732 -0600 @@ -637,6 +637,8 @@ int parse_permille_unbounded(const char r = safe_atoi(n, &v); if (r < 0) return r; + if (v < 0) + return -ERANGE; } else { pc = endswith(p, "%"); if (!pc) @@ -657,15 +659,14 @@ int parse_permille_unbounded(const char r = safe_atoi(n, &v); if (r < 0) return r; + if (v < 0) + return -ERANGE; if (v > (INT_MAX - q) / 10) return -ERANGE; v = v * 10 + q; } - if (v < 0) - return -ERANGE; - return v; } diff -Naurp systemd-239-orig/src/basic/proc-cmdline.c systemd-239/src/basic/proc-cmdline.c --- systemd-239-orig/src/basic/proc-cmdline.c 2018-06-22 06:11:49.000000000 -0500 +++ systemd-239/src/basic/proc-cmdline.c 2018-11-04 08:49:10.193692732 -0600 @@ -39,18 +39,12 @@ int proc_cmdline(char **ret) { return read_one_line_file("/proc/cmdline", ret); } -int proc_cmdline_parse(proc_cmdline_parse_t parse_item, void *data, unsigned flags) { - - _cleanup_free_ char *line = NULL; +int proc_cmdline_parse_given(const char *line, proc_cmdline_parse_t parse_item, void *data, unsigned flags) { const char *p; int r; assert(parse_item); - r = proc_cmdline(&line); - if (r < 0) - return r; - p = line; for (;;) { _cleanup_free_ char *word = NULL; @@ -86,6 +80,19 @@ int proc_cmdline_parse(proc_cmdline_pars return 0; } +int proc_cmdline_parse(proc_cmdline_parse_t parse_item, void *data, unsigned flags) { + _cleanup_free_ char *line = NULL; + int r; + + assert(parse_item); + + r = proc_cmdline(&line); + if (r < 0) + return r; + + return proc_cmdline_parse_given(line, parse_item, data, flags); +} + static bool relaxed_equal_char(char a, char b) { return a == b || diff -Naurp systemd-239-orig/src/basic/proc-cmdline.h systemd-239/src/basic/proc-cmdline.h --- systemd-239-orig/src/basic/proc-cmdline.h 2018-06-22 06:11:49.000000000 -0500 +++ systemd-239/src/basic/proc-cmdline.h 2018-11-04 08:49:10.193692732 -0600 @@ -14,6 +14,7 @@ typedef int (*proc_cmdline_parse_t)(cons int proc_cmdline(char **ret); +int proc_cmdline_parse_given(const char *line, proc_cmdline_parse_t parse_item, void *data, unsigned flags); int proc_cmdline_parse(const proc_cmdline_parse_t parse, void *userdata, unsigned flags); int proc_cmdline_get_key(const char *parameter, unsigned flags, char **value); diff -Naurp systemd-239-orig/src/basic/process-util.c systemd-239/src/basic/process-util.c --- systemd-239-orig/src/basic/process-util.c 2018-06-22 06:11:49.000000000 -0500 +++ systemd-239/src/basic/process-util.c 2018-11-04 08:49:10.193692732 -0600 @@ -336,15 +336,33 @@ int rename_process(const char name[]) { /* Now, let's tell the kernel about this new memory */ if (prctl(PR_SET_MM, PR_SET_MM_ARG_START, (unsigned long) nn, 0, 0) < 0) { - log_debug_errno(errno, "PR_SET_MM_ARG_START failed, proceeding without: %m"); - (void) munmap(nn, nn_size); - goto use_saved_argv; - } + /* HACK: prctl() API is kind of dumb on this point. The existing end address may already be + * below the desired start address, in which case the kernel may have kicked this back due + * to a range-check failure (see linux/kernel/sys.c:validate_prctl_map() to see this in + * action). The proper solution would be to have a prctl() API that could set both start+end + * simultaneously, or at least let us query the existing address to anticipate this condition + * and respond accordingly. For now, we can only guess at the cause of this failure and try + * a workaround--which will briefly expand the arg space to something potentially huge before + * resizing it to what we want. */ + log_debug_errno(errno, "PR_SET_MM_ARG_START failed, attempting PR_SET_MM_ARG_END hack: %m"); + + if (prctl(PR_SET_MM, PR_SET_MM_ARG_END, (unsigned long) nn + l + 1, 0, 0) < 0) { + log_debug_errno(errno, "PR_SET_MM_ARG_END hack failed, proceeding without: %m"); + (void) munmap(nn, nn_size); + goto use_saved_argv; + } - /* And update the end pointer to the new end, too. If this fails, we don't really know what to do, it's - * pretty unlikely that we can rollback, hence we'll just accept the failure, and continue. */ - if (prctl(PR_SET_MM, PR_SET_MM_ARG_END, (unsigned long) nn + l + 1, 0, 0) < 0) - log_debug_errno(errno, "PR_SET_MM_ARG_END failed, proceeding without: %m"); + if (prctl(PR_SET_MM, PR_SET_MM_ARG_START, (unsigned long) nn, 0, 0) < 0) { + log_debug_errno(errno, "PR_SET_MM_ARG_START still failed, proceeding without: %m"); + goto use_saved_argv; + } + } else { + /* And update the end pointer to the new end, too. If this fails, we don't really know what + * to do, it's pretty unlikely that we can rollback, hence we'll just accept the failure, + * and continue. */ + if (prctl(PR_SET_MM, PR_SET_MM_ARG_END, (unsigned long) nn + l + 1, 0, 0) < 0) + log_debug_errno(errno, "PR_SET_MM_ARG_END failed, proceeding without: %m"); + } if (mm) (void) munmap(mm, mm_size); diff -Naurp systemd-239-orig/src/basic/process-util.h systemd-239/src/basic/process-util.h --- systemd-239-orig/src/basic/process-util.h 2018-06-22 06:11:49.000000000 -0500 +++ systemd-239/src/basic/process-util.h 2018-11-04 08:49:10.193692732 -0600 @@ -134,13 +134,6 @@ static inline bool pid_is_valid(pid_t p) return p > 0; } -static inline int sched_policy_to_string_alloc_with_check(int n, char **s) { - if (!sched_policy_is_valid(n)) - return -EINVAL; - - return sched_policy_to_string_alloc(n, s); -} - int ioprio_parse_priority(const char *s, int *ret); pid_t getpid_cached(void); diff -Naurp systemd-239-orig/src/basic/raw-clone.h systemd-239/src/basic/raw-clone.h --- systemd-239-orig/src/basic/raw-clone.h 2018-06-22 06:11:49.000000000 -0500 +++ systemd-239/src/basic/raw-clone.h 2018-11-04 08:49:10.193692732 -0600 @@ -60,7 +60,7 @@ static inline pid_t raw_clone(unsigned l "mov %%o0, %1" : "=r"(in_child), "=r"(child_pid), "=r"(error) : "i"(__NR_clone), "r"(flags) : - "%o1", "%o0", "%g1" "cc" ); + "%o1", "%o0", "%g1", "cc" ); if (error) { errno = child_pid; diff -Naurp systemd-239-orig/src/basic/sigbus.c systemd-239/src/basic/sigbus.c --- systemd-239-orig/src/basic/sigbus.c 2018-06-22 06:11:49.000000000 -0500 +++ systemd-239/src/basic/sigbus.c 2018-11-04 08:49:10.193692732 -0600 @@ -113,6 +113,10 @@ void sigbus_install(void) { .sa_flags = SA_SIGINFO, }; + /* make sure that sysconf() is not called from a signal handler because + * it is not guaranteed to be async-signal-safe since POSIX.1-2008 */ + (void) page_size(); + n_installed++; if (n_installed == 1) diff -Naurp systemd-239-orig/src/basic/socket-util.c systemd-239/src/basic/socket-util.c --- systemd-239-orig/src/basic/socket-util.c 2018-06-22 06:11:49.000000000 -0500 +++ systemd-239/src/basic/socket-util.c 2018-11-04 08:49:10.193692732 -0600 @@ -50,7 +50,8 @@ static const char* const socket_address_ DEFINE_STRING_TABLE_LOOKUP(socket_address_type, int); int socket_address_parse(SocketAddress *a, const char *s) { - char *e, *n; + _cleanup_free_ char *n = NULL; + char *e; int r; assert(a); @@ -68,7 +69,9 @@ int socket_address_parse(SocketAddress * if (!e) return -EINVAL; - n = strndupa(s+1, e-s-1); + n = strndup(s+1, e-s-1); + if (!n) + return -ENOMEM; errno = 0; if (inet_pton(AF_INET6, n, &a->sockaddr.in6.sin6_addr) <= 0) @@ -125,7 +128,10 @@ int socket_address_parse(SocketAddress * if (r < 0) return r; - n = strndupa(cid_start, e - cid_start); + n = strndup(cid_start, e - cid_start); + if (!n) + return -ENOMEM; + if (!isempty(n)) { r = safe_atou(n, &a->sockaddr.vm.svm_cid); if (r < 0) @@ -146,7 +152,9 @@ int socket_address_parse(SocketAddress * if (r < 0) return r; - n = strndupa(s, e-s); + n = strndup(s, e-s); + if (!n) + return -ENOMEM; /* IPv4 in w.x.y.z:p notation? */ r = inet_pton(AF_INET, n, &a->sockaddr.in.sin_addr); @@ -739,21 +747,6 @@ int socknameinfo_pretty(union sockaddr_u return 0; } -int socket_address_unlink(SocketAddress *a) { - assert(a); - - if (socket_address_family(a) != AF_UNIX) - return 0; - - if (a->sockaddr.un.sun_path[0] == 0) - return 0; - - if (unlink(a->sockaddr.un.sun_path) < 0) - return -errno; - - return 1; -} - static const char* const netlink_family_table[] = { [NETLINK_ROUTE] = "route", [NETLINK_FIREWALL] = "firewall", @@ -827,8 +820,8 @@ int fd_inc_sndbuf(int fd, size_t n) { /* If we have the privileges we will ignore the kernel limit. */ value = (int) n; - if (setsockopt(fd, SOL_SOCKET, SO_SNDBUFFORCE, &value, sizeof(value)) < 0) - if (setsockopt(fd, SOL_SOCKET, SO_SNDBUF, &value, sizeof(value)) < 0) + if (setsockopt(fd, SOL_SOCKET, SO_SNDBUF, &value, sizeof(value)) < 0) + if (setsockopt(fd, SOL_SOCKET, SO_SNDBUFFORCE, &value, sizeof(value)) < 0) return -errno; return 1; @@ -845,8 +838,8 @@ int fd_inc_rcvbuf(int fd, size_t n) { /* If we have the privileges we will ignore the kernel limit. */ value = (int) n; - if (setsockopt(fd, SOL_SOCKET, SO_RCVBUFFORCE, &value, sizeof(value)) < 0) - if (setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &value, sizeof(value)) < 0) + if (setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &value, sizeof(value)) < 0) + if (setsockopt(fd, SOL_SOCKET, SO_RCVBUFFORCE, &value, sizeof(value)) < 0) return -errno; return 1; } @@ -1181,3 +1174,27 @@ int socket_ioctl_fd(void) { return fd; } + +int sockaddr_un_unlink(const struct sockaddr_un *sa) { + const char *p, * nul; + + assert(sa); + + if (sa->sun_family != AF_UNIX) + return -EPROTOTYPE; + + if (sa->sun_path[0] == 0) /* Nothing to do for abstract sockets */ + return 0; + + /* The path in .sun_path is not necessarily NUL terminated. Let's fix that. */ + nul = memchr(sa->sun_path, 0, sizeof(sa->sun_path)); + if (nul) + p = sa->sun_path; + else + p = memdupa_suffix0(sa->sun_path, sizeof(sa->sun_path)); + + if (unlink(p) < 0) + return -errno; + + return 1; +} diff -Naurp systemd-239-orig/src/basic/socket-util.h systemd-239/src/basic/socket-util.h --- systemd-239-orig/src/basic/socket-util.h 2018-06-22 06:11:49.000000000 -0500 +++ systemd-239/src/basic/socket-util.h 2018-11-04 08:49:10.193692732 -0600 @@ -71,7 +71,12 @@ int socket_address_parse_and_warn(Socket int socket_address_parse_netlink(SocketAddress *a, const char *s); int socket_address_print(const SocketAddress *a, char **p); int socket_address_verify(const SocketAddress *a) _pure_; -int socket_address_unlink(SocketAddress *a); + +int sockaddr_un_unlink(const struct sockaddr_un *sa); + +static inline int socket_address_unlink(const SocketAddress *a) { + return socket_address_family(a) == AF_UNIX ? sockaddr_un_unlink(&a->sockaddr.un) : 0; +} bool socket_address_can_accept(const SocketAddress *a) _pure_; diff -Naurp systemd-239-orig/src/basic/string-util.c systemd-239/src/basic/string-util.c --- systemd-239-orig/src/basic/string-util.c 2018-06-22 06:11:49.000000000 -0500 +++ systemd-239/src/basic/string-util.c 2018-11-04 08:49:10.193692732 -0600 @@ -1004,7 +1004,7 @@ int free_and_strdup(char **p, const char assert(p); - /* Replaces a string pointer with an strdup()ed new string, + /* Replaces a string pointer with a strdup()ed new string, * possibly freeing the old one. */ if (streq_ptr(*p, s)) @@ -1023,6 +1023,32 @@ int free_and_strdup(char **p, const char return 1; } +int free_and_strndup(char **p, const char *s, size_t l) { + char *t; + + assert(p); + assert(s || l == 0); + + /* Replaces a string pointer with a strndup()ed new string, + * freeing the old one. */ + + if (!*p && !s) + return 0; + + if (*p && s && strneq(*p, s, l) && (l > strlen(*p) || (*p)[l] == '\0')) + return 0; + + if (s) { + t = strndup(s, l); + if (!t) + return -ENOMEM; + } else + t = NULL; + + free_and_replace(*p, t); + return 1; +} + #if !HAVE_EXPLICIT_BZERO /* * Pointer to memset is volatile so that compiler must de-reference diff -Naurp systemd-239-orig/src/basic/string-util.h systemd-239/src/basic/string-util.h --- systemd-239-orig/src/basic/string-util.h 2018-06-22 06:11:49.000000000 -0500 +++ systemd-239/src/basic/string-util.h 2018-11-04 08:49:10.193692732 -0600 @@ -176,6 +176,7 @@ char *strrep(const char *s, unsigned n); int split_pair(const char *s, const char *sep, char **l, char **r); int free_and_strdup(char **p, const char *s); +int free_and_strndup(char **p, const char *s, size_t l); /* Normal memmem() requires haystack to be nonnull, which is annoying for zero-length buffers */ static inline void *memmem_safe(const void *haystack, size_t haystacklen, const void *needle, size_t needlelen) { @@ -228,3 +229,25 @@ static inline void *memory_startswith(co return (uint8_t*) p + n; } + +/* Like startswith_no_case(), but operates on arbitrary memory blocks. + * It works only for ASCII strings. + */ +static inline void *memory_startswith_no_case(const void *p, size_t sz, const char *token) { + size_t n, i; + + assert(token); + + n = strlen(token); + if (sz < n) + return NULL; + + assert(p); + + for (i = 0; i < n; i++) { + if (ascii_tolower(((char *)p)[i]) != ascii_tolower(token[i])) + return NULL; + } + + return (uint8_t*) p + n; +} diff -Naurp systemd-239-orig/src/basic/terminal-util.c systemd-239/src/basic/terminal-util.c --- systemd-239-orig/src/basic/terminal-util.c 2018-06-22 06:11:49.000000000 -0500 +++ systemd-239/src/basic/terminal-util.c 2018-11-04 08:49:10.193692732 -0600 @@ -819,11 +819,11 @@ unsigned columns(void) { if (e) (void) safe_atoi(e, &c); - if (c <= 0) + if (c <= 0 || c > USHRT_MAX) { c = fd_columns(STDOUT_FILENO); - - if (c <= 0) - c = 80; + if (c <= 0) + c = 80; + } cached_columns = c; return cached_columns; @@ -853,11 +853,11 @@ unsigned lines(void) { if (e) (void) safe_atoi(e, &l); - if (l <= 0) + if (l <= 0 || l > USHRT_MAX) { l = fd_lines(STDOUT_FILENO); - - if (l <= 0) - l = 24; + if (l <= 0) + l = 24; + } cached_lines = l; return cached_lines; diff -Naurp systemd-239-orig/src/basic/time-util.c systemd-239/src/basic/time-util.c --- systemd-239-orig/src/basic/time-util.c 2018-06-22 06:11:49.000000000 -0500 +++ systemd-239/src/basic/time-util.c 2018-11-04 08:49:10.194692732 -0600 @@ -1058,18 +1058,19 @@ int parse_sec(const char *t, usec_t *use return parse_time(t, usec, USEC_PER_SEC); } -int parse_sec_fix_0(const char *t, usec_t *usec) { - assert(t); - assert(usec); +int parse_sec_fix_0(const char *t, usec_t *ret) { + usec_t k; + int r; - t += strspn(t, WHITESPACE); + assert(t); + assert(ret); - if (streq(t, "0")) { - *usec = USEC_INFINITY; - return 0; - } + r = parse_sec(t, &k); + if (r < 0) + return r; - return parse_sec(t, usec); + *ret = k == 0 ? USEC_INFINITY : k; + return r; } int parse_nsec(const char *t, nsec_t *nsec) { diff -Naurp systemd-239-orig/src/basic/user-util.h systemd-239/src/basic/user-util.h --- systemd-239-orig/src/basic/user-util.h 2018-06-22 06:11:49.000000000 -0500 +++ systemd-239/src/basic/user-util.h 2018-11-04 08:49:10.194692732 -0600 @@ -102,7 +102,7 @@ int fgetgrent_sane(FILE *stream, struct int putpwent_sane(const struct passwd *pw, FILE *stream); int putspent_sane(const struct spwd *sp, FILE *stream); int putgrent_sane(const struct group *gr, FILE *stream); -#ifdef ENABLE_GSHADOW +#if ENABLE_GSHADOW int fgetsgent_sane(FILE *stream, struct sgrp **sg); int putsgent_sane(const struct sgrp *sg, FILE *stream); #endif diff -Naurp systemd-239-orig/src/basic/util.c systemd-239/src/basic/util.c --- systemd-239-orig/src/basic/util.c 2018-06-22 06:11:49.000000000 -0500 +++ systemd-239/src/basic/util.c 2018-11-04 08:49:10.194692732 -0600 @@ -23,6 +23,7 @@ #include "def.h" #include "device-nodes.h" #include "dirent-util.h" +#include "env-util.h" #include "fd-util.h" #include "fileio.h" #include "format-util.h" @@ -131,6 +132,7 @@ int prot_from_flags(int flags) { bool in_initrd(void) { struct statfs s; + int r; if (saved_in_initrd >= 0) return saved_in_initrd; @@ -145,9 +147,16 @@ bool in_initrd(void) { * emptying when transititioning to the main systemd. */ - saved_in_initrd = access("/etc/initrd-release", F_OK) >= 0 && - statfs("/", &s) >= 0 && - is_temporary_fs(&s); + r = getenv_bool_secure("SYSTEMD_IN_INITRD"); + if (r < 0 && r != -ENXIO) + log_debug_errno(r, "Failed to parse $SYSTEMD_IN_INITRD, ignoring: %m"); + + if (r >= 0) + saved_in_initrd = r > 0; + else + saved_in_initrd = access("/etc/initrd-release", F_OK) >= 0 && + statfs("/", &s) >= 0 && + is_temporary_fs(&s); return saved_in_initrd; } diff -Naurp systemd-239-orig/src/basic/virt.c systemd-239/src/basic/virt.c --- systemd-239-orig/src/basic/virt.c 2018-06-22 06:11:49.000000000 -0500 +++ systemd-239/src/basic/virt.c 2018-11-04 08:49:10.194692732 -0600 @@ -11,6 +11,7 @@ #include "alloc-util.h" #include "dirent-util.h" +#include "def.h" #include "env-util.h" #include "fd-util.h" #include "fileio.h" @@ -259,21 +260,38 @@ static int detect_vm_hypervisor(void) { } static int detect_vm_uml(void) { - _cleanup_free_ char *cpuinfo_contents = NULL; + _cleanup_fclose_ FILE *f = NULL; int r; /* Detect User-Mode Linux by reading /proc/cpuinfo */ - r = read_full_file("/proc/cpuinfo", &cpuinfo_contents, NULL); - if (r == -ENOENT) { - log_debug("/proc/cpuinfo not found, assuming no UML virtualization."); - return VIRTUALIZATION_NONE; + f = fopen("/proc/cpuinfo", "re"); + if (!f) { + if (errno == ENOENT) { + log_debug("/proc/cpuinfo not found, assuming no UML virtualization."); + return VIRTUALIZATION_NONE; + } + return -errno; } - if (r < 0) - return r; - if (strstr(cpuinfo_contents, "\nvendor_id\t: User Mode Linux\n")) { - log_debug("UML virtualization found in /proc/cpuinfo"); - return VIRTUALIZATION_UML; + for (;;) { + _cleanup_free_ char *line = NULL; + const char *t; + + r = read_line(f, LONG_LINE_MAX, &line); + if (r < 0) + return r; + if (r == 0) + break; + + t = startswith(line, "vendor_id\t: "); + if (t) { + if (startswith(t, "User Mode Linux")) { + log_debug("UML virtualization found in /proc/cpuinfo"); + return VIRTUALIZATION_UML; + } + + break; + } } log_debug("UML virtualization not found in /proc/cpuinfo."); diff -Naurp systemd-239-orig/src/basic/xattr-util.c systemd-239/src/basic/xattr-util.c --- systemd-239-orig/src/basic/xattr-util.c 2018-06-22 06:11:49.000000000 -0500 +++ systemd-239/src/basic/xattr-util.c 2018-11-04 08:49:10.194692732 -0600 @@ -2,7 +2,6 @@ #include #include -#include #include #include #include diff -Naurp systemd-239-orig/src/boot/bootctl.c systemd-239/src/boot/bootctl.c --- systemd-239-orig/src/boot/bootctl.c 2018-06-22 06:11:49.000000000 -0500 +++ systemd-239/src/boot/bootctl.c 2018-11-04 08:49:10.194692732 -0600 @@ -1032,6 +1032,8 @@ static int verb_list(int argc, char *arg ansi_highlight_green(), n == (unsigned) config.default_entry ? " (default)" : "", ansi_normal()); + if (e->id) + printf(" id: %s\n", e->id); if (e->version) printf(" version: %s\n", e->version); if (e->machine_id) diff -Naurp systemd-239-orig/src/boot/efi/console.h systemd-239/src/boot/efi/console.h --- systemd-239-orig/src/boot/efi/console.h 2018-06-22 06:11:49.000000000 -0500 +++ systemd-239/src/boot/efi/console.h 2018-11-04 08:49:10.194692732 -0600 @@ -14,7 +14,7 @@ #define EFI_CONTROL_PRESSED (EFI_RIGHT_CONTROL_PRESSED|EFI_LEFT_CONTROL_PRESSED) #define EFI_ALT_PRESSED (EFI_RIGHT_ALT_PRESSED|EFI_LEFT_ALT_PRESSED) -#define KEYPRESS(keys, scan, uni) ((((UINT64)keys) << 32) | ((scan) << 16) | (uni)) +#define KEYPRESS(keys, scan, uni) ((((UINT64)keys) << 32) | (((UINT64)scan) << 16) | (uni)) #define KEYCHAR(k) ((k) & 0xffff) #define CHAR_CTRL(c) ((c) - 'a' + 1) diff -Naurp systemd-239-orig/src/boot/efi/meson.build systemd-239/src/boot/efi/meson.build --- systemd-239-orig/src/boot/efi/meson.build 2018-06-22 06:11:49.000000000 -0500 +++ systemd-239/src/boot/efi/meson.build 2018-11-04 08:49:10.194692732 -0600 @@ -34,7 +34,13 @@ stub_sources = ''' if conf.get('ENABLE_EFI') == 1 and get_option('gnu-efi') != 'false' efi_cc = get_option('efi-cc') + if efi_cc == '' + efi_cc = ' '.join(cc.cmd_array()) + endif efi_ld = get_option('efi-ld') + if efi_ld == '' + efi_ld = find_program('ld', required: true) + endif efi_incdir = get_option('efi-includedir') gnu_efi_path_arch = '' diff -Naurp systemd-239-orig/src/boot/efi/splash.c systemd-239/src/boot/efi/splash.c --- systemd-239-orig/src/boot/efi/splash.c 2018-06-22 06:11:49.000000000 -0500 +++ systemd-239/src/boot/efi/splash.c 2018-11-04 08:49:10.194692732 -0600 @@ -283,7 +283,7 @@ EFI_STATUS graphics_splash(UINT8 *conten GraphicsOutput->Mode->Info->VerticalResolution, 0); /* EFI buffer */ - blt_size = dib->x * dib->y * sizeof(EFI_GRAPHICS_OUTPUT_BLT_PIXEL); + blt_size = sizeof(EFI_GRAPHICS_OUTPUT_BLT_PIXEL) * dib->x * dib->y; blt = AllocatePool(blt_size); if (!blt) return EFI_OUT_OF_RESOURCES; diff -Naurp systemd-239-orig/src/boot/efi/stub.c systemd-239/src/boot/efi/stub.c --- systemd-239-orig/src/boot/efi/stub.c 2018-06-22 06:11:49.000000000 -0500 +++ systemd-239/src/boot/efi/stub.c 2018-11-04 08:49:10.194692732 -0600 @@ -69,7 +69,7 @@ EFI_STATUS efi_main(EFI_HANDLE image, EF cmdline_len = szs[0]; /* if we are not in secure boot mode, accept a custom command line and replace the built-in one */ - if (!secure && loaded_image->LoadOptionsSize > 0 && *(CHAR16 *)loaded_image->LoadOptions != 0) { + if (!secure && loaded_image->LoadOptionsSize > 0 && *(CHAR16 *)loaded_image->LoadOptions > 0x1F) { CHAR16 *options; CHAR8 *line; UINTN i; diff -Naurp systemd-239-orig/src/core/automount.c systemd-239/src/core/automount.c --- systemd-239-orig/src/core/automount.c 2018-06-22 06:11:49.000000000 -0500 +++ systemd-239/src/core/automount.c 2018-11-04 08:49:10.195692731 -0600 @@ -882,12 +882,13 @@ static int automount_deserialize_item(Un a->result = f; } else if (streq(key, "dev-id")) { - unsigned d; + unsigned long d; - if (safe_atou(value, &d) < 0) + if (safe_atolu(value, &d) < 0) log_unit_debug(u, "Failed to parse dev-id value: %s", value); else - a->dev_id = (unsigned) d; + a->dev_id = (dev_t) d; + } else if (streq(key, "token")) { unsigned token; diff -Naurp systemd-239-orig/src/core/chown-recursive.c systemd-239/src/core/chown-recursive.c --- systemd-239-orig/src/core/chown-recursive.c 2018-06-22 06:11:49.000000000 -0500 +++ systemd-239/src/core/chown-recursive.c 2018-11-04 08:49:10.195692731 -0600 @@ -1,17 +1,21 @@ /* SPDX-License-Identifier: LGPL-2.1+ */ -#include -#include #include +#include +#include +#include -#include "user-util.h" -#include "macro.h" -#include "fd-util.h" -#include "dirent-util.h" #include "chown-recursive.h" +#include "dirent-util.h" +#include "fd-util.h" +#include "macro.h" +#include "stdio-util.h" +#include "strv.h" +#include "user-util.h" -static int chown_one(int fd, const char *name, const struct stat *st, uid_t uid, gid_t gid) { - int r; +static int chown_one(int fd, const struct stat *st, uid_t uid, gid_t gid) { + char procfs_path[STRLEN("/proc/self/fd/") + DECIMAL_STR_MAX(int) + 1]; + const char *n; assert(fd >= 0); assert(st); @@ -20,98 +24,95 @@ static int chown_one(int fd, const char (!gid_is_valid(gid) || st->st_gid == gid)) return 0; - if (name) - r = fchownat(fd, name, uid, gid, AT_SYMLINK_NOFOLLOW); - else - r = fchown(fd, uid, gid); - if (r < 0) - return -errno; + /* We change ownership through the /proc/self/fd/%i path, so that we have a stable reference that works with + * O_PATH. (Note: fchown() and fchmod() do not work with O_PATH, the kernel refuses that. */ + xsprintf(procfs_path, "/proc/self/fd/%i", fd); + + /* Drop any ACL if there is one */ + FOREACH_STRING(n, "system.posix_acl_access", "system.posix_acl_default") + if (removexattr(procfs_path, n) < 0) + if (!IN_SET(errno, ENODATA, EOPNOTSUPP, ENOSYS, ENOTTY)) + return -errno; - /* The linux kernel alters the mode in some cases of chown(). Let's undo this. */ - if (name) { - if (!S_ISLNK(st->st_mode)) - r = fchmodat(fd, name, st->st_mode, 0); - else /* There's currently no AT_SYMLINK_NOFOLLOW for fchmodat() */ - r = 0; - } else - r = fchmod(fd, st->st_mode); - if (r < 0) + if (chown(procfs_path, uid, gid) < 0) return -errno; + /* The linux kernel alters the mode in some cases of chown(), as well when we change ACLs. Let's undo this. We + * do this only for non-symlinks however. That's because for symlinks the access mode is ignored anyway and + * because on some kernels/file systems trying to change the access mode will succeed but has no effect while + * on others it actively fails. */ + if (!S_ISLNK(st->st_mode)) + if (chmod(procfs_path, st->st_mode & 07777) < 0) + return -errno; + return 1; } static int chown_recursive_internal(int fd, const struct stat *st, uid_t uid, gid_t gid) { + _cleanup_closedir_ DIR *d = NULL; bool changed = false; + struct dirent *de; int r; assert(fd >= 0); assert(st); - if (S_ISDIR(st->st_mode)) { - _cleanup_closedir_ DIR *d = NULL; - struct dirent *de; - - d = fdopendir(fd); - if (!d) { - r = -errno; - goto finish; - } - fd = -1; - - FOREACH_DIRENT_ALL(de, d, r = -errno; goto finish) { - struct stat fst; - - if (dot_or_dot_dot(de->d_name)) - continue; + d = fdopendir(fd); + if (!d) { + safe_close(fd); + return -errno; + } - if (fstatat(dirfd(d), de->d_name, &fst, AT_SYMLINK_NOFOLLOW) < 0) { - r = -errno; - goto finish; - } - - if (S_ISDIR(fst.st_mode)) { - int subdir_fd; - - subdir_fd = openat(dirfd(d), de->d_name, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|O_NOFOLLOW|O_NOATIME); - if (subdir_fd < 0) { - r = -errno; - goto finish; - } - - r = chown_recursive_internal(subdir_fd, &fst, uid, gid); - if (r < 0) - goto finish; - if (r > 0) - changed = true; - } else { - r = chown_one(dirfd(d), de->d_name, &fst, uid, gid); - if (r < 0) - goto finish; - if (r > 0) - changed = true; - } + FOREACH_DIRENT_ALL(de, d, return -errno) { + _cleanup_close_ int path_fd = -1; + struct stat fst; + + if (dot_or_dot_dot(de->d_name)) + continue; + + /* Let's pin the child inode we want to fix now with an O_PATH fd, so that it cannot be swapped out + * while we manipulate it. */ + path_fd = openat(dirfd(d), de->d_name, O_PATH|O_CLOEXEC|O_NOFOLLOW); + if (path_fd < 0) + return -errno; + + if (fstat(path_fd, &fst) < 0) + return -errno; + + if (S_ISDIR(fst.st_mode)) { + int subdir_fd; + + /* Convert it to a "real" (i.e. non-O_PATH) fd now */ + subdir_fd = fd_reopen(path_fd, O_RDONLY|O_CLOEXEC|O_NOATIME); + if (subdir_fd < 0) + return subdir_fd; + + r = chown_recursive_internal(subdir_fd, &fst, uid, gid); /* takes possession of subdir_fd even on failure */ + if (r < 0) + return r; + if (r > 0) + changed = true; + } else { + r = chown_one(path_fd, &fst, uid, gid); + if (r < 0) + return r; + if (r > 0) + changed = true; } + } - r = chown_one(dirfd(d), NULL, st, uid, gid); - } else - r = chown_one(fd, NULL, st, uid, gid); + r = chown_one(dirfd(d), st, uid, gid); if (r < 0) - goto finish; + return r; - r = r > 0 || changed; - -finish: - safe_close(fd); - return r; + return r > 0 || changed; } int path_chown_recursive(const char *path, uid_t uid, gid_t gid) { _cleanup_close_ int fd = -1; struct stat st; - int r; - fd = open(path, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|O_NOFOLLOW|O_NOATIME); + fd = open(path, O_RDONLY|O_DIRECTORY|O_CLOEXEC|O_NOFOLLOW|O_NOATIME); if (fd < 0) return -errno; @@ -128,8 +129,5 @@ int path_chown_recursive(const char *pat (!gid_is_valid(gid) || st.st_gid == gid)) return 0; - r = chown_recursive_internal(fd, &st, uid, gid); - fd = -1; /* we donated the fd to the call, regardless if it succeeded or failed */ - - return r; + return chown_recursive_internal(TAKE_FD(fd), &st, uid, gid); /* we donate the fd to the call, regardless if it succeeded or failed */ } diff -Naurp systemd-239-orig/src/core/dbus.c systemd-239/src/core/dbus.c --- systemd-239-orig/src/core/dbus.c 2018-06-22 06:11:49.000000000 -0500 +++ systemd-239/src/core/dbus.c 2018-11-04 08:49:10.195692731 -0600 @@ -1012,7 +1012,7 @@ int bus_init_private(Manager *m) { } (void) mkdir_parents_label(sa.un.sun_path, 0755); - (void) unlink(sa.un.sun_path); + (void) sockaddr_un_unlink(&sa.un); fd = socket(AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0); if (fd < 0) diff -Naurp systemd-239-orig/src/core/dbus-execute.c systemd-239/src/core/dbus-execute.c --- systemd-239-orig/src/core/dbus-execute.c 2018-06-22 06:11:49.000000000 -0500 +++ systemd-239/src/core/dbus-execute.c 2018-11-04 08:49:10.195692731 -0600 @@ -1015,8 +1015,6 @@ static BUS_DEFINE_SET_TRANSIENT_IS_VALID #if HAVE_SECCOMP static BUS_DEFINE_SET_TRANSIENT_IS_VALID(errno, "i", int32_t, int, "%" PRIi32, errno_is_valid); #endif -static BUS_DEFINE_SET_TRANSIENT_IS_VALID(sched_priority, "i", int32_t, int, "%" PRIi32, sched_priority_is_valid); -static BUS_DEFINE_SET_TRANSIENT_IS_VALID(nice, "i", int32_t, int, "%" PRIi32, nice_is_valid); static BUS_DEFINE_SET_TRANSIENT_PARSE(std_input, ExecInput, exec_input_from_string); static BUS_DEFINE_SET_TRANSIENT_PARSE(std_output, ExecOutput, exec_output_from_string); static BUS_DEFINE_SET_TRANSIENT_PARSE(utmp_mode, ExecUtmpMode, exec_utmp_mode_from_string); @@ -1027,7 +1025,6 @@ static BUS_DEFINE_SET_TRANSIENT_PARSE(pr static BUS_DEFINE_SET_TRANSIENT_PARSE_PTR(personality, unsigned long, parse_personality); static BUS_DEFINE_SET_TRANSIENT_TO_STRING_ALLOC(secure_bits, "i", int32_t, int, "%" PRIi32, secure_bits_to_string_alloc_with_check); static BUS_DEFINE_SET_TRANSIENT_TO_STRING_ALLOC(capability, "t", uint64_t, uint64_t, "%" PRIu64, capability_set_to_string_alloc); -static BUS_DEFINE_SET_TRANSIENT_TO_STRING_ALLOC(sched_policy, "i", int32_t, int, "%" PRIi32, sched_policy_to_string_alloc_with_check); static BUS_DEFINE_SET_TRANSIENT_TO_STRING_ALLOC(namespace_flag, "t", uint64_t, unsigned long, "%" PRIu64, namespace_flags_to_string); static BUS_DEFINE_SET_TRANSIENT_TO_STRING(mount_flags, "t", uint64_t, unsigned long, "%" PRIu64, mount_propagation_flags_to_string_with_check); @@ -1070,15 +1067,9 @@ int bus_exec_context_set_transient_prope if (streq(name, "LogLevelMax")) return bus_set_transient_log_level(u, name, &c->log_level_max, message, flags, error); - if (streq(name, "CPUSchedulingPriority")) - return bus_set_transient_sched_priority(u, name, &c->cpu_sched_priority, message, flags, error); - if (streq(name, "Personality")) return bus_set_transient_personality(u, name, &c->personality, message, flags, error); - if (streq(name, "Nice")) - return bus_set_transient_nice(u, name, &c->nice, message, flags, error); - if (streq(name, "StandardInput")) return bus_set_transient_std_input(u, name, &c->std_input, message, flags, error); @@ -1208,9 +1199,6 @@ int bus_exec_context_set_transient_prope if (streq(name, "AmbientCapabilities")) return bus_set_transient_capability(u, name, &c->capability_ambient_set, message, flags, error); - if (streq(name, "CPUSchedulingPolicy")) - return bus_set_transient_sched_policy(u, name, &c->cpu_sched_policy, message, flags, error); - if (streq(name, "RestrictNamespaces")) return bus_set_transient_namespace_flag(u, name, &c->restrict_namespaces, message, flags, error); @@ -1608,6 +1596,72 @@ int bus_exec_context_set_transient_prope } return 1; + + } else if (streq(name, "Nice")) { + int32_t q; + + r = sd_bus_message_read(message, "i", &q); + if (r < 0) + return r; + + if (!nice_is_valid(q)) + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid Nice value: %i", q); + + if (!UNIT_WRITE_FLAGS_NOOP(flags)) { + c->nice = q; + c->nice_set = true; + + unit_write_settingf(u, flags, name, "Nice=%i", q); + } + + return 1; + + } else if (streq(name, "CPUSchedulingPolicy")) { + int32_t q; + + r = sd_bus_message_read(message, "i", &q); + if (r < 0) + return r; + + if (!sched_policy_is_valid(q)) + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid CPU scheduling policy: %i", q); + + if (!UNIT_WRITE_FLAGS_NOOP(flags)) { + _cleanup_free_ char *s = NULL; + + r = sched_policy_to_string_alloc(q, &s); + if (r < 0) + return r; + + c->cpu_sched_policy = q; + c->cpu_sched_priority = CLAMP(c->cpu_sched_priority, sched_get_priority_min(q), sched_get_priority_max(q)); + c->cpu_sched_set = true; + + unit_write_settingf(u, flags, name, "CPUSchedulingPolicy=%s", s); + } + + return 1; + + } else if (streq(name, "CPUSchedulingPriority")) { + int32_t p, min, max; + + r = sd_bus_message_read(message, "i", &p); + if (r < 0) + return r; + + min = sched_get_priority_min(c->cpu_sched_policy); + max = sched_get_priority_max(c->cpu_sched_policy); + if (p < min || p > max) + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid CPU scheduling priority: %i", p); + + if (!UNIT_WRITE_FLAGS_NOOP(flags)) { + c->cpu_sched_priority = p; + c->cpu_sched_set = true; + + unit_write_settingf(u, flags, name, "CPUSchedulingPriority=%i", p); + } + + return 1; } else if (streq(name, "IOSchedulingClass")) { int32_t q; diff -Naurp systemd-239-orig/src/core/dynamic-user.c systemd-239/src/core/dynamic-user.c --- systemd-239-orig/src/core/dynamic-user.c 2018-06-22 06:11:49.000000000 -0500 +++ systemd-239/src/core/dynamic-user.c 2018-11-04 08:49:10.195692731 -0600 @@ -102,9 +102,11 @@ static int dynamic_user_acquire(Manager d = hashmap_get(m->dynamic_users, name); if (d) { - /* We already have a structure for the dynamic user, let's increase the ref count and reuse it */ - d->n_ref++; - *ret = d; + if (ret) { + /* We already have a structure for the dynamic user, let's increase the ref count and reuse it */ + d->n_ref++; + *ret = d; + } return 0; } @@ -525,6 +527,16 @@ static int dynamic_user_realize( num = new_uid; uid_lock_fd = new_uid_lock_fd; } + } else if (is_user && !uid_is_dynamic(num)) { + struct passwd *p; + + /* Statically allocated user may have different uid and gid. So, let's obtain the gid. */ + errno = 0; + p = getpwuid(num); + if (!p) + return errno > 0 ? -errno : -ESRCH; + + gid = p->pw_gid; } /* If the UID/GID was already allocated dynamically, push the data we popped out back in. If it was already diff -Naurp systemd-239-orig/src/core/execute.c systemd-239/src/core/execute.c --- systemd-239-orig/src/core/execute.c 2018-06-22 06:11:49.000000000 -0500 +++ systemd-239/src/core/execute.c 2018-11-04 08:49:10.196692730 -0600 @@ -323,7 +323,8 @@ static int connect_logger_as( uid_t uid, gid_t gid) { - int fd, r; + _cleanup_close_ int fd = -1; + int r; assert(context); assert(params); @@ -339,14 +340,12 @@ static int connect_logger_as( if (r < 0) return r; - if (shutdown(fd, SHUT_RD) < 0) { - safe_close(fd); + if (shutdown(fd, SHUT_RD) < 0) return -errno; - } (void) fd_inc_sndbuf(fd, SNDBUF_SIZE); - dprintf(fd, + if (dprintf(fd, "%s\n" "%s\n" "%i\n" @@ -360,10 +359,12 @@ static int connect_logger_as( !!context->syslog_level_prefix, is_syslog_output(output), is_kmsg_output(output), - is_terminal_output(output)); + is_terminal_output(output)) < 0) + return -errno; - return move_fd(fd, nfd, false); + return move_fd(TAKE_FD(fd), nfd, false); } + static int open_terminal_as(const char *path, int flags, int nfd) { int fd; diff -Naurp systemd-239-orig/src/core/job.c systemd-239/src/core/job.c --- systemd-239-orig/src/core/job.c 2018-06-22 06:11:49.000000000 -0500 +++ systemd-239/src/core/job.c 2018-11-04 08:49:10.196692730 -0600 @@ -10,6 +10,7 @@ #include "dbus-job.h" #include "dbus.h" #include "escape.h" +#include "fileio.h" #include "job.h" #include "log.h" #include "macro.h" @@ -1091,24 +1092,26 @@ int job_serialize(Job *j, FILE *f) { } int job_deserialize(Job *j, FILE *f) { + int r; + assert(j); assert(f); for (;;) { - char line[LINE_MAX], *l, *v; + _cleanup_free_ char *line = NULL; + char *l, *v; size_t k; - if (!fgets(line, sizeof(line), f)) { - if (feof(f)) - return 0; - return -errno; - } + r = read_line(f, LONG_LINE_MAX, &line); + if (r < 0) + return log_error_errno(r, "Failed to read serialization line: %m"); + if (r == 0) + return 0; - char_array_0(line); l = strstrip(line); /* End marker */ - if (l[0] == 0) + if (isempty(l)) return 0; k = strcspn(l, "="); diff -Naurp systemd-239-orig/src/core/killall.c systemd-239/src/core/killall.c --- systemd-239-orig/src/core/killall.c 2018-06-22 06:11:49.000000000 -0500 +++ systemd-239/src/core/killall.c 2018-11-04 08:49:10.196692730 -0600 @@ -23,16 +23,20 @@ static bool ignore_proc(pid_t pid, bool warn_rootfs) { _cleanup_fclose_ FILE *f = NULL; - char c; const char *p; - size_t count; + char c = 0; uid_t uid; int r; /* We are PID 1, let's not commit suicide */ - if (pid == 1) + if (pid <= 1) return true; + /* Ignore kernel threads */ + r = is_kernel_thread(pid); + if (r != 0) + return true; /* also ignore processes where we can't determine this */ + r = get_process_uid(pid, &uid); if (r < 0) return true; /* not really, but better safe than sorry */ @@ -46,11 +50,10 @@ static bool ignore_proc(pid_t pid, bool if (!f) return true; /* not really, but has the desired effect */ - count = fread(&c, 1, 1, f); - - /* Kernel threads have an empty cmdline */ - if (count <= 0) - return true; + /* Try to read the first character of the command line. If the cmdline is empty (which might be the case for + * kernel threads but potentially also other stuff), this line won't do anything, but we don't care much, as + * actual kernel threads are already filtered out above. */ + (void) fread(&c, 1, 1, f); /* Processes with argv[0][0] = '@' we ignore from the killing spree. * diff -Naurp systemd-239-orig/src/core/kmod-setup.c systemd-239/src/core/kmod-setup.c --- systemd-239-orig/src/core/kmod-setup.c 2018-06-22 06:11:49.000000000 -0500 +++ systemd-239/src/core/kmod-setup.c 2018-11-04 08:49:10.196692730 -0600 @@ -76,13 +76,15 @@ int kmod_setup(void) { bool warn_if_module:1; bool (*condition_fn)(void); } kmod_table[] = { - /* auto-loading on use doesn't work before udev is up */ + /* This one we need to load explicitly, since auto-loading on use doesn't work + * before udev created the ghost device nodes, and we need it earlier than that. */ { "autofs4", "/sys/class/misc/autofs", true, false, NULL }, - /* early configure of ::1 on the loopback device */ + /* This one we need to load explicitly, since auto-loading of IPv6 is not done when + * we try to configure ::1 on the loopback device. */ { "ipv6", "/sys/module/ipv6", false, true, NULL }, - /* this should never be a module */ + /* This should never be a module */ { "unix", "/proc/net/unix", true, true, NULL }, #if HAVE_LIBIPTC @@ -94,14 +96,11 @@ int kmod_setup(void) { }; _cleanup_(kmod_unrefp) struct kmod_ctx *ctx = NULL; unsigned int i; - int r; if (have_effective_cap(CAP_SYS_MODULE) == 0) return 0; for (i = 0; i < ELEMENTSOF(kmod_table); i++) { - _cleanup_(kmod_module_unrefp) struct kmod_module *mod = NULL; - if (kmod_table[i].path && access(kmod_table[i].path, F_OK) >= 0) continue; @@ -122,23 +121,7 @@ int kmod_setup(void) { kmod_load_resources(ctx); } - r = kmod_module_new_from_name(ctx, kmod_table[i].module, &mod); - if (r < 0) { - log_error("Failed to lookup module '%s'", kmod_table[i].module); - continue; - } - - r = kmod_module_probe_insert_module(mod, KMOD_PROBE_APPLY_BLACKLIST, NULL, NULL, NULL, NULL); - if (r == 0) - log_debug("Inserted module '%s'", kmod_module_get_name(mod)); - else if (r == KMOD_PROBE_APPLY_BLACKLIST) - log_info("Module '%s' is blacklisted", kmod_module_get_name(mod)); - else { - bool print_warning = kmod_table[i].warn_if_unavailable || (r < 0 && r != -ENOENT); - - log_full_errno(print_warning ? LOG_WARNING : LOG_DEBUG, r, - "Failed to insert module '%s': %m", kmod_module_get_name(mod)); - } + (void) module_load_and_warn(ctx, kmod_table[i].module, kmod_table[i].warn_if_unavailable); } #endif diff -Naurp systemd-239-orig/src/core/load-dropin.c systemd-239/src/core/load-dropin.c --- systemd-239-orig/src/core/load-dropin.c 2018-06-22 06:11:49.000000000 -0500 +++ systemd-239/src/core/load-dropin.c 2018-11-04 08:49:10.196692730 -0600 @@ -92,7 +92,7 @@ static int process_deps(Unit *u, UnitDep log_unit_warning(u, "%s dependency dropin %s target %s has different name", unit_dependency_to_string(dependency), *p, target); - r = unit_add_dependency_by_name(u, dependency, entry, *p, true, UNIT_DEPENDENCY_FILE); + r = unit_add_dependency_by_name(u, dependency, entry, NULL, true, UNIT_DEPENDENCY_FILE); if (r < 0) log_unit_warning_errno(u, r, "Cannot add %s dependency on %s, ignoring: %m", unit_dependency_to_string(dependency), entry); diff -Naurp systemd-239-orig/src/core/load-fragment.c systemd-239/src/core/load-fragment.c --- systemd-239-orig/src/core/load-fragment.c 2018-06-22 06:11:49.000000000 -0500 +++ systemd-239/src/core/load-fragment.c 2018-11-04 08:49:10.196692730 -0600 @@ -3080,7 +3080,7 @@ int config_parse_tasks_max( int r; if (isempty(rvalue)) { - *tasks_max = u->manager->default_tasks_max; + *tasks_max = u ? u->manager->default_tasks_max : UINT64_MAX; return 0; } @@ -3904,7 +3904,7 @@ int config_parse_temporary_filesystems( if (r < 0) continue; - r = temporary_filesystem_add(&c->temporary_filesystems, &c->n_temporary_filesystems, path, w); + r = temporary_filesystem_add(&c->temporary_filesystems, &c->n_temporary_filesystems, resolved, w); if (r == -ENOMEM) return log_oom(); if (r < 0) { diff -Naurp systemd-239-orig/src/core/macros.systemd.in systemd-239/src/core/macros.systemd.in --- systemd-239-orig/src/core/macros.systemd.in 2018-06-22 06:11:49.000000000 -0500 +++ systemd-239/src/core/macros.systemd.in 2018-11-04 08:49:10.196692730 -0600 @@ -18,7 +18,7 @@ %_sysctldir @sysctldir@ %_sysusersdir @sysusersdir@ %_tmpfilesdir @tmpfilesdir@ -%_environmnentdir @environmentdir@ +%_environmentdir @environmentdir@ %_modulesloaddir @modulesloaddir@ %_modprobedir @modprobedir@ %_systemdgeneratordir @systemgeneratordir@ @@ -26,6 +26,10 @@ %_systemd_system_env_generator_dir @systemenvgeneratordir@ %_systemd_user_env_generator_dir @userenvgeneratordir@ +# Because we had one release with a typo... +# This is temporary (Remove after systemd 240 is released) +%_environmnentdir %{warn:Use %%_environmentdir instead}%_environmentdir + %systemd_requires \ Requires(post): systemd \ Requires(preun): systemd \ diff -Naurp systemd-239-orig/src/core/manager.c systemd-239/src/core/manager.c --- systemd-239-orig/src/core/manager.c 2018-06-22 06:11:49.000000000 -0500 +++ systemd-239/src/core/manager.c 2018-11-04 08:49:10.196692730 -0600 @@ -831,9 +831,7 @@ int manager_new(UnitFileScope scope, uns if (r < 0) return r; - r = manager_setup_timezone_change(m); - if (r < 0) - return r; + (void) manager_setup_timezone_change(m); r = manager_setup_sigchld_event_source(m); if (r < 0) @@ -886,9 +884,9 @@ static int manager_setup_notify(Manager return log_oom(); (void) mkdir_parents_label(m->notify_socket, 0755); - (void) unlink(m->notify_socket); + (void) sockaddr_un_unlink(&sa.un); - strncpy(sa.un.sun_path, m->notify_socket, sizeof(sa.un.sun_path)-1); + strncpy(sa.un.sun_path, m->notify_socket, sizeof(sa.un.sun_path)); r = bind(fd, &sa.sa, SOCKADDR_UN_LEN(sa.un)); if (r < 0) return log_error_errno(errno, "bind(%s) failed: %m", sa.un.sun_path); @@ -964,7 +962,7 @@ static int manager_setup_cgroups_agent(M fd_inc_rcvbuf(fd, CGROUPS_AGENT_RCVBUF_SIZE); - (void) unlink(sa.un.sun_path); + (void) sockaddr_un_unlink(&sa.un); /* Only allow root to connect to this socket */ RUN_WITH_UMASK(0077) @@ -1211,6 +1209,45 @@ static unsigned manager_dispatch_gc_job_ return n; } +static unsigned manager_dispatch_stop_when_unneeded_queue(Manager *m) { + unsigned n = 0; + Unit *u; + int r; + + assert(m); + + while ((u = m->stop_when_unneeded_queue)) { + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + assert(m->stop_when_unneeded_queue); + + assert(u->in_stop_when_unneeded_queue); + LIST_REMOVE(stop_when_unneeded_queue, m->stop_when_unneeded_queue, u); + u->in_stop_when_unneeded_queue = false; + + n++; + + if (!unit_is_unneeded(u)) + continue; + + log_unit_debug(u, "Unit is not needed anymore."); + + /* If stopping a unit fails continuously we might enter a stop loop here, hence stop acting on the + * service being unnecessary after a while. */ + + if (!ratelimit_below(&u->auto_stop_ratelimit)) { + log_unit_warning(u, "Unit not needed anymore, but not stopping since we tried this too often recently."); + continue; + } + + /* Ok, nobody needs us anymore. Sniff. Then let's commit suicide */ + r = manager_add_job(u->manager, JOB_STOP, u, JOB_FAIL, &error, NULL); + if (r < 0) + log_unit_warning_errno(u, r, "Failed to enqueue stop job, ignoring: %s", bus_error_message(&error, r)); + } + + return n; +} + static void manager_clear_jobs_and_units(Manager *m) { Unit *u; @@ -1228,6 +1265,7 @@ static void manager_clear_jobs_and_units assert(!m->cleanup_queue); assert(!m->gc_unit_queue); assert(!m->gc_job_queue); + assert(!m->stop_when_unneeded_queue); assert(hashmap_isempty(m->jobs)); assert(hashmap_isempty(m->units)); @@ -2800,6 +2838,9 @@ int manager_loop(Manager *m) { if (manager_dispatch_cgroup_realize_queue(m) > 0) continue; + if (manager_dispatch_stop_when_unneeded_queue(m) > 0) + continue; + if (manager_dispatch_dbus_queue(m) > 0) continue; @@ -3130,22 +3171,19 @@ int manager_deserialize(Manager *m, FILE m->n_reloading++; for (;;) { - char line[LINE_MAX]; + _cleanup_free_ char *line = NULL; const char *val, *l; - if (!fgets(line, sizeof(line), f)) { - if (feof(f)) - r = 0; - else - r = -errno; - + r = read_line(f, LONG_LINE_MAX, &line); + if (r < 0) { + log_error_errno(r, "Failed to read serialization line: %m"); goto finish; } + if (r == 0) + break; - char_array_0(line); l = strstrip(line); - - if (l[0] == 0) + if (isempty(l)) /* end marker */ break; if ((val = startswith(l, "current-job-id="))) { @@ -3312,29 +3350,31 @@ int manager_deserialize(Manager *m, FILE } for (;;) { - Unit *u; - char name[UNIT_NAME_MAX+2]; + _cleanup_free_ char *line = NULL; const char* unit_name; + Unit *u; /* Start marker */ - if (!fgets(name, sizeof(name), f)) { - if (feof(f)) - r = 0; - else - r = -errno; - + r = read_line(f, LONG_LINE_MAX, &line); + if (r < 0) { + log_error_errno(r, "Failed to read serialization line: %m"); goto finish; } + if (r == 0) + break; - char_array_0(name); - unit_name = strstrip(name); + unit_name = strstrip(line); r = manager_load_unit(m, unit_name, NULL, NULL, &u); if (r < 0) { log_notice_errno(r, "Failed to load unit \"%s\", skipping deserialization: %m", unit_name); if (r == -ENOMEM) goto finish; - unit_deserialize_skip(f); + + r = unit_deserialize_skip(f); + if (r < 0) + goto finish; + continue; } @@ -3347,9 +3387,6 @@ int manager_deserialize(Manager *m, FILE } finish: - if (ferror(f)) - r = -EIO; - assert(m->n_reloading > 0); m->n_reloading--; @@ -3736,7 +3773,7 @@ static int manager_run_environment_gener if (!generator_path_any(paths)) return 0; - return execute_directories(paths, DEFAULT_TIMEOUT_USEC, gather_environment, args, NULL); + return execute_directories(paths, DEFAULT_TIMEOUT_USEC, gather_environment, args, NULL, m->environment); } static int manager_run_generators(Manager *m) { @@ -3768,7 +3805,7 @@ static int manager_run_generators(Manage RUN_WITH_UMASK(0022) execute_directories((const char* const*) paths, DEFAULT_TIMEOUT_USEC, - NULL, NULL, (char**) argv); + NULL, NULL, (char**) argv, m->environment); finish: lookup_paths_trim_generator(&m->lookup_paths); diff -Naurp systemd-239-orig/src/core/manager.h systemd-239/src/core/manager.h --- systemd-239-orig/src/core/manager.h 2018-06-22 06:11:49.000000000 -0500 +++ systemd-239/src/core/manager.h 2018-11-04 08:49:10.196692730 -0600 @@ -130,6 +130,9 @@ struct Manager { /* Target units whose default target dependencies haven't been set yet */ LIST_HEAD(Unit, target_deps_queue); + /* Units that might be subject to StopWhenUnneeded= clean-up */ + LIST_HEAD(Unit, stop_when_unneeded_queue); + sd_event *event; /* This maps PIDs we care about to units that are interested in. We allow multiple units to he interested in diff -Naurp systemd-239-orig/src/core/service.c systemd-239/src/core/service.c --- systemd-239-orig/src/core/service.c 2018-06-22 06:11:49.000000000 -0500 +++ systemd-239/src/core/service.c 2018-11-04 08:49:10.197692731 -0600 @@ -3498,7 +3498,11 @@ static void service_notify_message( } if (r > 0) { service_set_main_pid(s, new_main_pid); - unit_watch_pid(UNIT(s), new_main_pid); + + r = unit_watch_pid(UNIT(s), new_main_pid); + if (r < 0) + log_unit_warning_errno(UNIT(s), r, "Failed to watch new main PID "PID_FMT" for service: %m", new_main_pid); + notify_dbus = true; } } @@ -3549,8 +3553,12 @@ static void service_notify_message( _cleanup_free_ char *t = NULL; if (!isempty(e)) { - if (!utf8_is_valid(e)) - log_unit_warning(u, "Status message in notification message is not UTF-8 clean."); + /* Note that this size limit check is mostly paranoia: since the datagram size we are willing + * to process is already limited to NOTIFY_BUFFER_MAX, this limit here should never be hit. */ + if (strlen(e) > STATUS_TEXT_MAX) + log_unit_warning(u, "Status message overly long (%zu > %u), ignoring.", strlen(e), STATUS_TEXT_MAX); + else if (!utf8_is_valid(e)) + log_unit_warning(u, "Status message in notification message is not UTF-8 clean, ignoring."); else { t = strdup(e); if (!t) diff -Naurp systemd-239-orig/src/core/service.h systemd-239/src/core/service.h --- systemd-239-orig/src/core/service.h 2018-06-22 06:11:49.000000000 -0500 +++ systemd-239/src/core/service.h 2018-11-04 08:49:10.197692731 -0600 @@ -202,3 +202,5 @@ const char* service_result_to_string(Ser ServiceResult service_result_from_string(const char *s) _pure_; DEFINE_CAST(SERVICE, Service); + +#define STATUS_TEXT_MAX (16U*1024U) diff -Naurp systemd-239-orig/src/core/shutdown.c systemd-239/src/core/shutdown.c --- systemd-239-orig/src/core/shutdown.c 2018-06-22 06:11:49.000000000 -0500 +++ systemd-239/src/core/shutdown.c 2018-11-04 08:49:10.197692731 -0600 @@ -435,7 +435,7 @@ int main(int argc, char *argv[]) { arguments[0] = NULL; arguments[1] = arg_verb; arguments[2] = NULL; - execute_directories(dirs, DEFAULT_TIMEOUT_USEC, NULL, NULL, arguments); + execute_directories(dirs, DEFAULT_TIMEOUT_USEC, NULL, NULL, arguments, NULL); if (can_initrd) { r = switch_root_initramfs(); diff -Naurp systemd-239-orig/src/core/system.conf.in systemd-239/src/core/system.conf.in --- systemd-239-orig/src/core/system.conf.in 2018-06-22 06:11:49.000000000 -0500 +++ systemd-239/src/core/system.conf.in 2018-11-04 08:49:10.197692731 -0600 @@ -26,6 +26,7 @@ #JoinControllers=cpu,cpuacct net_cls,net_prio #RuntimeWatchdogSec=0 #ShutdownWatchdogSec=10min +#WatchdogDevice= #CapabilityBoundingSet= #NoNewPrivileges=no #SystemCallArchitectures= @@ -62,5 +63,3 @@ #DefaultLimitNICE= #DefaultLimitRTPRIO= #DefaultLimitRTTIME= -#IPAddressAllow= -#IPAddressDeny= diff -Naurp systemd-239-orig/src/core/transaction.c systemd-239/src/core/transaction.c --- systemd-239-orig/src/core/transaction.c 2018-06-22 06:11:49.000000000 -0500 +++ systemd-239/src/core/transaction.c 2018-11-04 08:49:10.197692731 -0600 @@ -526,7 +526,9 @@ static int transaction_is_destructive(Tr if (j->unit->job && (mode == JOB_FAIL || j->unit->job->irreversible) && job_type_is_conflicting(j->unit->job->type, j->type)) return sd_bus_error_setf(e, BUS_ERROR_TRANSACTION_IS_DESTRUCTIVE, - "Transaction is destructive."); + "Transaction for %s/%s is destructive (%s has '%s' job queued, but '%s' is included in transaction).", + tr->anchor_job->unit->id, job_type_to_string(tr->anchor_job->type), + j->unit->id, job_type_to_string(j->unit->job->type), job_type_to_string(j->type)); } return 0; diff -Naurp systemd-239-orig/src/core/umount.c systemd-239/src/core/umount.c --- systemd-239-orig/src/core/umount.c 2018-06-22 06:11:49.000000000 -0500 +++ systemd-239/src/core/umount.c 2018-11-04 08:49:10.197692731 -0600 @@ -72,7 +72,8 @@ int mount_points_list_get(const char *mo for (;;) { struct libmnt_fs *fs; - const char *path, *options, *fstype; + const char *path, *fstype; + _cleanup_free_ char *options = NULL; _cleanup_free_ char *p = NULL; unsigned long remount_flags = 0u; _cleanup_free_ char *remount_options = NULL; @@ -92,9 +93,25 @@ int mount_points_list_get(const char *mo if (cunescape(path, UNESCAPE_RELAX, &p) < 0) return log_oom(); - options = mnt_fs_get_options(fs); fstype = mnt_fs_get_fstype(fs); + /* Combine the generic VFS options with the FS-specific + * options. Duplicates are not a problem here, because the only + * options that should come up twice are typically ro/rw, which + * are turned into MS_RDONLY or the invertion of it. + * + * Even if there are duplicates later in mount_option_mangle() + * it shouldn't hurt anyways as they override each other. + */ + if (!strextend_with_separator(&options, ",", + mnt_fs_get_vfs_options(fs), + NULL)) + return log_oom(); + if (!strextend_with_separator(&options, ",", + mnt_fs_get_fs_options(fs), + NULL)) + return log_oom(); + /* Ignore mount points we can't unmount because they * are API or because we are keeping them open (like * /dev/console). Also, ignore all mounts below API diff -Naurp systemd-239-orig/src/core/unit.c systemd-239/src/core/unit.c --- systemd-239-orig/src/core/unit.c 2018-06-22 06:11:49.000000000 -0500 +++ systemd-239/src/core/unit.c 2018-11-04 08:49:10.197692731 -0600 @@ -438,6 +438,22 @@ void unit_add_to_dbus_queue(Unit *u) { u->in_dbus_queue = true; } +void unit_add_to_stop_when_unneeded_queue(Unit *u) { + assert(u); + + if (u->in_stop_when_unneeded_queue) + return; + + if (!u->stop_when_unneeded) + return; + + if (!UNIT_IS_ACTIVE_OR_RELOADING(unit_active_state(u))) + return; + + LIST_PREPEND(stop_when_unneeded_queue, u->manager->stop_when_unneeded_queue, u); + u->in_stop_when_unneeded_queue = true; +} + static void bidi_set_free(Unit *u, Hashmap *h) { Unit *other; Iterator i; @@ -634,6 +650,9 @@ void unit_free(Unit *u) { if (u->in_target_deps_queue) LIST_REMOVE(target_deps_queue, u->manager->target_deps_queue, u); + if (u->in_stop_when_unneeded_queue) + LIST_REMOVE(stop_when_unneeded_queue, u->manager->stop_when_unneeded_queue, u); + safe_close(u->ip_accounting_ingress_map_fd); safe_close(u->ip_accounting_egress_map_fd); @@ -943,7 +962,7 @@ int unit_add_exec_dependencies(Unit *u, assert(u); assert(c); - if (c->working_directory) { + if (c->working_directory && !c->working_directory_missing_ok) { r = unit_require_mounts_for(u, c->working_directory, UNIT_DEPENDENCY_FILE); if (r < 0) return r; @@ -1950,55 +1969,71 @@ bool unit_can_reload(Unit *u) { return UNIT_VTABLE(u)->reload; } -static void unit_check_unneeded(Unit *u) { - - _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; - - static const UnitDependency needed_dependencies[] = { +bool unit_is_unneeded(Unit *u) { + static const UnitDependency deps[] = { UNIT_REQUIRED_BY, UNIT_REQUISITE_OF, UNIT_WANTED_BY, UNIT_BOUND_BY, }; - - unsigned j; - int r; + size_t j; assert(u); - /* If this service shall be shut down when unneeded then do - * so. */ - if (!u->stop_when_unneeded) - return; + return false; - if (!UNIT_IS_ACTIVE_OR_ACTIVATING(unit_active_state(u))) - return; + /* Don't clean up while the unit is transitioning or is even inactive. */ + if (!UNIT_IS_ACTIVE_OR_RELOADING(unit_active_state(u))) + return false; + if (u->job) + return false; - for (j = 0; j < ELEMENTSOF(needed_dependencies); j++) { + for (j = 0; j < ELEMENTSOF(deps); j++) { Unit *other; Iterator i; void *v; - HASHMAP_FOREACH_KEY(v, other, u->dependencies[needed_dependencies[j]], i) - if (unit_active_or_pending(other) || unit_will_restart(other)) - return; - } + /* If a dependending unit has a job queued, or is active (or in transitioning), or is marked for + * restart, then don't clean this one up. */ - /* If stopping a unit fails continuously we might enter a stop - * loop here, hence stop acting on the service being - * unnecessary after a while. */ - if (!ratelimit_below(&u->auto_stop_ratelimit)) { - log_unit_warning(u, "Unit not needed anymore, but not stopping since we tried this too often recently."); - return; + HASHMAP_FOREACH_KEY(v, other, u->dependencies[deps[j]], i) { + if (other->job) + return false; + + if (!UNIT_IS_INACTIVE_OR_FAILED(unit_active_state(other))) + return false; + + if (unit_will_restart(other)) + return false; + } } - log_unit_info(u, "Unit not needed anymore. Stopping."); + return true; +} - /* Ok, nobody needs us anymore. Sniff. Then let's commit suicide */ - r = manager_add_job(u->manager, JOB_STOP, u, JOB_FAIL, &error, NULL); - if (r < 0) - log_unit_warning_errno(u, r, "Failed to enqueue stop job, ignoring: %s", bus_error_message(&error, r)); +static void check_unneeded_dependencies(Unit *u) { + + static const UnitDependency deps[] = { + UNIT_REQUIRES, + UNIT_REQUISITE, + UNIT_WANTS, + UNIT_BINDS_TO, + }; + size_t j; + + assert(u); + + /* Add all units this unit depends on to the queue that processes StopWhenUnneeded= behaviour. */ + + for (j = 0; j < ELEMENTSOF(deps); j++) { + Unit *other; + Iterator i; + void *v; + + HASHMAP_FOREACH_KEY(v, other, u->dependencies[deps[j]], i) + unit_add_to_stop_when_unneeded_queue(other); + } } static void unit_check_binds_to(Unit *u) { @@ -2098,29 +2133,6 @@ static void retroactively_stop_dependenc manager_add_job(u->manager, JOB_STOP, other, JOB_REPLACE, NULL, NULL); } -static void check_unneeded_dependencies(Unit *u) { - Unit *other; - Iterator i; - void *v; - - assert(u); - assert(UNIT_IS_INACTIVE_OR_DEACTIVATING(unit_active_state(u))); - - /* Garbage collect services that might not be needed anymore, if enabled */ - HASHMAP_FOREACH_KEY(v, other, u->dependencies[UNIT_REQUIRES], i) - if (!UNIT_IS_INACTIVE_OR_DEACTIVATING(unit_active_state(other))) - unit_check_unneeded(other); - HASHMAP_FOREACH_KEY(v, other, u->dependencies[UNIT_WANTS], i) - if (!UNIT_IS_INACTIVE_OR_DEACTIVATING(unit_active_state(other))) - unit_check_unneeded(other); - HASHMAP_FOREACH_KEY(v, other, u->dependencies[UNIT_REQUISITE], i) - if (!UNIT_IS_INACTIVE_OR_DEACTIVATING(unit_active_state(other))) - unit_check_unneeded(other); - HASHMAP_FOREACH_KEY(v, other, u->dependencies[UNIT_BINDS_TO], i) - if (!UNIT_IS_INACTIVE_OR_DEACTIVATING(unit_active_state(other))) - unit_check_unneeded(other); -} - void unit_start_on_failure(Unit *u) { Unit *other; Iterator i; @@ -2423,7 +2435,7 @@ void unit_notify(Unit *u, UnitActiveStat } /* stop unneeded units regardless if going down was expected or not */ - if (UNIT_IS_INACTIVE_OR_DEACTIVATING(ns)) + if (UNIT_IS_INACTIVE_OR_FAILED(ns)) check_unneeded_dependencies(u); if (ns != os && ns == UNIT_FAILED) { @@ -2483,7 +2495,7 @@ void unit_notify(Unit *u, UnitActiveStat if (!MANAGER_IS_RELOADING(u->manager)) { /* Maybe we finished startup and are now ready for being stopped because unneeded? */ - unit_check_unneeded(u); + unit_add_to_stop_when_unneeded_queue(u); /* Maybe we finished startup, but something we needed has vanished? Let's die then. (This happens when * something BindsTo= to a Type=oneshot unit, as these units go directly from starting to inactive, @@ -3368,21 +3380,19 @@ int unit_deserialize(Unit *u, FILE *f, F assert(fds); for (;;) { - char line[LINE_MAX], *l, *v; + _cleanup_free_ char *line = NULL; CGroupIPAccountingMetric m; + char *l, *v; size_t k; - if (!fgets(line, sizeof(line), f)) { - if (feof(f)) - return 0; - return -errno; - } + r = read_line(f, LONG_LINE_MAX, &line); + if (r < 0) + return log_error_errno(r, "Failed to read serialization line: %m"); + if (r == 0) /* eof */ + break; - char_array_0(line); l = strstrip(line); - - /* End marker */ - if (isempty(l)) + if (isempty(l)) /* End marker */ break; k = strcspn(l, "="); @@ -3588,6 +3598,8 @@ int unit_deserialize(Unit *u, FILE *f, F else unit_ref_uid_gid(u, UID_INVALID, gid); + continue; + } else if (streq(l, "ref")) { r = strv_extend(&u->deserialized_refs, v); @@ -3657,23 +3669,27 @@ int unit_deserialize(Unit *u, FILE *f, F return 0; } -void unit_deserialize_skip(FILE *f) { +int unit_deserialize_skip(FILE *f) { + int r; assert(f); /* Skip serialized data for this unit. We don't know what it is. */ for (;;) { - char line[LINE_MAX], *l; + _cleanup_free_ char *line = NULL; + char *l; - if (!fgets(line, sizeof line, f)) - return; + r = read_line(f, LONG_LINE_MAX, &line); + if (r < 0) + return log_error_errno(r, "Failed to read serialization line: %m"); + if (r == 0) + return 0; - char_array_0(line); l = strstrip(line); /* End marker */ if (isempty(l)) - return; + return 1; } } diff -Naurp systemd-239-orig/src/core/unit.h systemd-239/src/core/unit.h --- systemd-239-orig/src/core/unit.h 2018-06-22 06:11:49.000000000 -0500 +++ systemd-239/src/core/unit.h 2018-11-04 08:49:10.197692731 -0600 @@ -212,6 +212,9 @@ typedef struct Unit { /* Target dependencies queue */ LIST_FIELDS(Unit, target_deps_queue); + /* Queue of units with StopWhenUnneeded set that shell be checked for clean-up. */ + LIST_FIELDS(Unit, stop_when_unneeded_queue); + /* PIDs we keep an eye on. Note that a unit might have many * more, but these are the ones we care enough about to * process SIGCHLD for */ @@ -322,6 +325,7 @@ typedef struct Unit { bool in_cgroup_realize_queue:1; bool in_cgroup_empty_queue:1; bool in_target_deps_queue:1; + bool in_stop_when_unneeded_queue:1; bool sent_dbus_new_signal:1; @@ -613,6 +617,7 @@ void unit_add_to_dbus_queue(Unit *u); void unit_add_to_cleanup_queue(Unit *u); void unit_add_to_gc_queue(Unit *u); void unit_add_to_target_deps_queue(Unit *u); +void unit_add_to_stop_when_unneeded_queue(Unit *u); int unit_merge(Unit *u, Unit *other); int unit_merge_by_name(Unit *u, const char *other); @@ -679,7 +684,7 @@ bool unit_can_serialize(Unit *u) _pure_; int unit_serialize(Unit *u, FILE *f, FDSet *fds, bool serialize_jobs); int unit_deserialize(Unit *u, FILE *f, FDSet *fds); -void unit_deserialize_skip(FILE *f); +int unit_deserialize_skip(FILE *f); int unit_serialize_item(Unit *u, FILE *f, const char *key, const char *value); int unit_serialize_item_escaped(Unit *u, FILE *f, const char *key, const char *value); @@ -749,6 +754,8 @@ bool unit_type_supported(UnitType t); bool unit_is_pristine(Unit *u); +bool unit_is_unneeded(Unit *u); + pid_t unit_control_pid(Unit *u); pid_t unit_main_pid(Unit *u); diff -Naurp systemd-239-orig/src/coredump/coredumpctl.c systemd-239/src/coredump/coredumpctl.c --- systemd-239-orig/src/coredump/coredumpctl.c 2018-06-22 06:11:49.000000000 -0500 +++ systemd-239/src/coredump/coredumpctl.c 2018-11-04 08:49:10.197692731 -0600 @@ -654,7 +654,8 @@ static int dump_list(int argc, char **ar * pick a fairly low data threshold here */ sd_journal_set_data_threshold(j, 4096); - if (arg_one) { + /* "info" without pattern implies "-1" */ + if (arg_one || (verb_is_info && argc == 1)) { r = focus(j); if (r < 0) return r; diff -Naurp systemd-239-orig/src/cryptsetup/cryptsetup.c systemd-239/src/cryptsetup/cryptsetup.c --- systemd-239-orig/src/cryptsetup/cryptsetup.c 2018-06-22 06:11:49.000000000 -0500 +++ systemd-239/src/cryptsetup/cryptsetup.c 2018-11-04 08:49:10.197692731 -0600 @@ -333,7 +333,7 @@ static int get_password(const char *vol, name = name_buffer ? name_buffer : vol; - if (asprintf(&text, "Please enter passphrase for disk %s!", name) < 0) + if (asprintf(&text, "Please enter passphrase for disk %s:", name) < 0) return log_oom(); id = strjoina("cryptsetup:", disk_path); @@ -349,7 +349,7 @@ static int get_password(const char *vol, assert(strv_length(passwords) == 1); - if (asprintf(&text, "Please enter passphrase for disk %s! (verification)", name) < 0) + if (asprintf(&text, "Please enter passphrase for disk %s (verification):", name) < 0) return log_oom(); id = strjoina("cryptsetup-verification:", disk_path); diff -Naurp systemd-239-orig/src/cryptsetup/cryptsetup-generator.c systemd-239/src/cryptsetup/cryptsetup-generator.c --- systemd-239-orig/src/cryptsetup/cryptsetup-generator.c 2018-06-22 06:11:49.000000000 -0500 +++ systemd-239/src/cryptsetup/cryptsetup-generator.c 2018-11-04 08:49:10.197692731 -0600 @@ -151,8 +151,13 @@ static int create_disk( fputs("Before=dev-mapper-%i.swap\n", f); } else + /* For loopback devices, add systemd-tmpfiles-setup-dev.service + dependency to ensure that loopback support is available in + the kernel (/dev/loop-control needs to exist) */ fprintf(f, - "RequiresMountsFor=%s\n", + "RequiresMountsFor=%s\n" + "Requires=systemd-tmpfiles-setup-dev.service\n" + "After=systemd-tmpfiles-setup-dev.service\n", u_escaped); r = generator_write_timeouts(arg_dest, device, name, options, &filtered); diff -Naurp systemd-239-orig/src/firstboot/firstboot.c systemd-239/src/firstboot/firstboot.c --- systemd-239-orig/src/firstboot/firstboot.c 2018-06-22 06:11:49.000000000 -0500 +++ systemd-239/src/firstboot/firstboot.c 2018-11-04 08:49:10.198692730 -0600 @@ -4,7 +4,7 @@ #include #include -#ifdef HAVE_CRYPT_H +#if HAVE_CRYPT_H /* libxcrypt is a replacement for glibc's libcrypt, and libcrypt might be * removed from glibc at some point. As part of the removal, defines for * crypt(3) are dropped from unistd.h, and we must include crypt.h instead. diff -Naurp systemd-239-orig/src/hibernate-resume/hibernate-resume-generator.c systemd-239/src/hibernate-resume/hibernate-resume-generator.c --- systemd-239-orig/src/hibernate-resume/hibernate-resume-generator.c 2018-06-22 06:11:49.000000000 -0500 +++ systemd-239/src/hibernate-resume/hibernate-resume-generator.c 2018-11-04 08:49:10.198692730 -0600 @@ -15,6 +15,7 @@ static const char *arg_dest = "/tmp"; static char *arg_resume_device = NULL; +static bool arg_noresume = false; static int parse_proc_cmdline_item(const char *key, const char *value, void *data) { @@ -28,8 +29,15 @@ static int parse_proc_cmdline_item(const if (!s) return log_oom(); - free(arg_resume_device); - arg_resume_device = s; + free_and_replace(arg_resume_device, s); + + } else if (streq(key, "noresume")) { + if (value) { + log_warning("\"noresume\" kernel command line switch specified with an argument, ignoring."); + return 0; + } + + arg_noresume = true; } return 0; @@ -60,6 +68,13 @@ static int process_resume(void) { int main(int argc, char *argv[]) { int r = 0; + log_set_prohibit_ipc(true); + log_set_target(LOG_TARGET_AUTO); + log_parse_environment(); + log_open(); + + umask(0022); + if (argc > 1 && argc != 4) { log_error("This program takes three or no arguments."); return EXIT_FAILURE; @@ -68,21 +83,21 @@ int main(int argc, char *argv[]) { if (argc > 1) arg_dest = argv[1]; - log_set_prohibit_ipc(true); - log_set_target(LOG_TARGET_AUTO); - log_parse_environment(); - log_open(); - - umask(0022); - /* Don't even consider resuming outside of initramfs. */ - if (!in_initrd()) + if (!in_initrd()) { + log_debug("Not running in an initrd, quitting."); return EXIT_SUCCESS; + } r = proc_cmdline_parse(parse_proc_cmdline_item, NULL, 0); if (r < 0) log_warning_errno(r, "Failed to parse kernel command line, ignoring: %m"); + if (arg_noresume) { + log_notice("Found \"noresume\" on the kernel command line, quitting."); + return EXIT_SUCCESS; + } + r = process_resume(); free(arg_resume_device); diff -Naurp systemd-239-orig/src/import/curl-util.c systemd-239/src/import/curl-util.c --- systemd-239-orig/src/import/curl-util.c 2018-06-22 06:11:49.000000000 -0500 +++ systemd-239/src/import/curl-util.c 2018-11-04 08:49:10.198692730 -0600 @@ -41,7 +41,7 @@ static int curl_glue_on_io(sd_event_sour else action = 0; - if (curl_multi_socket_action(g->curl, translated_fd, action, &k) < 0) { + if (curl_multi_socket_action(g->curl, translated_fd, action, &k) != CURLM_OK) { log_debug("Failed to propagate IO event."); return -EINVAL; } @@ -363,7 +363,7 @@ int curl_header_strdup(const void *conte const char *p; char *s; - p = memory_startswith(contents, sz, field); + p = memory_startswith_no_case(contents, sz, field); if (!p) return 0; diff -Naurp systemd-239-orig/src/import/import-compress.c systemd-239/src/import/import-compress.c --- systemd-239-orig/src/import/import-compress.c 2018-06-22 06:11:49.000000000 -0500 +++ systemd-239/src/import/import-compress.c 2018-11-04 08:49:10.198692730 -0600 @@ -14,11 +14,13 @@ void import_compress_free(ImportCompress deflateEnd(&c->gzip); else inflateEnd(&c->gzip); +#if HAVE_BZIP2 } else if (c->type == IMPORT_COMPRESS_BZIP2) { if (c->encoding) BZ2_bzCompressEnd(&c->bzip2); else BZ2_bzDecompressEnd(&c->bzip2); +#endif } c->type = IMPORT_COMPRESS_UNKNOWN; @@ -65,12 +67,14 @@ int import_uncompress_detect(ImportCompr c->type = IMPORT_COMPRESS_GZIP; +#if HAVE_BZIP2 } else if (memcmp(data, bzip2_signature, sizeof(bzip2_signature)) == 0) { r = BZ2_bzDecompressInit(&c->bzip2, 0, 0); if (r != BZ_OK) return -EIO; c->type = IMPORT_COMPRESS_BZIP2; +#endif } else c->type = IMPORT_COMPRESS_UNCOMPRESSED; @@ -149,6 +153,7 @@ int import_uncompress(ImportCompress *c, break; +#if HAVE_BZIP2 case IMPORT_COMPRESS_BZIP2: c->bzip2.next_in = (void*) data; c->bzip2.avail_in = size; @@ -169,6 +174,7 @@ int import_uncompress(ImportCompress *c, } break; +#endif default: assert_not_reached("Unknown compression"); @@ -203,6 +209,7 @@ int import_compress_init(ImportCompress c->type = IMPORT_COMPRESS_GZIP; break; +#if HAVE_BZIP2 case IMPORT_COMPRESS_BZIP2: r = BZ2_bzCompressInit(&c->bzip2, 9, 0, 0); if (r != BZ_OK) @@ -210,6 +217,7 @@ int import_compress_init(ImportCompress c->type = IMPORT_COMPRESS_BZIP2; break; +#endif case IMPORT_COMPRESS_UNCOMPRESSED: c->type = IMPORT_COMPRESS_UNCOMPRESSED; @@ -307,6 +315,7 @@ int import_compress(ImportCompress *c, c break; +#if HAVE_BZIP2 case IMPORT_COMPRESS_BZIP2: c->bzip2.next_in = (void*) data; @@ -328,6 +337,7 @@ int import_compress(ImportCompress *c, c } break; +#endif case IMPORT_COMPRESS_UNCOMPRESSED: @@ -411,6 +421,7 @@ int import_compress_finish(ImportCompres break; +#if HAVE_BZIP2 case IMPORT_COMPRESS_BZIP2: c->bzip2.avail_in = 0; @@ -430,6 +441,7 @@ int import_compress_finish(ImportCompres } while (r != BZ_STREAM_END); break; +#endif case IMPORT_COMPRESS_UNCOMPRESSED: break; @@ -446,7 +458,9 @@ static const char* const import_compress [IMPORT_COMPRESS_UNCOMPRESSED] = "uncompressed", [IMPORT_COMPRESS_XZ] = "xz", [IMPORT_COMPRESS_GZIP] = "gzip", +#if HAVE_BZIP2 [IMPORT_COMPRESS_BZIP2] = "bzip2", +#endif }; DEFINE_STRING_TABLE_LOOKUP(import_compress_type, ImportCompressType); diff -Naurp systemd-239-orig/src/import/import-compress.h systemd-239/src/import/import-compress.h --- systemd-239-orig/src/import/import-compress.h 2018-06-22 06:11:49.000000000 -0500 +++ systemd-239/src/import/import-compress.h 2018-11-04 08:49:10.198692730 -0600 @@ -1,7 +1,9 @@ /* SPDX-License-Identifier: LGPL-2.1+ */ #pragma once +#if HAVE_BZIP2 #include +#endif #include #include #include @@ -24,7 +26,9 @@ typedef struct ImportCompress { union { lzma_stream xz; z_stream gzip; +#if HAVE_BZIP2 bz_stream bzip2; +#endif }; } ImportCompress; diff -Naurp systemd-239-orig/src/import/importd.c systemd-239/src/import/importd.c --- systemd-239-orig/src/import/importd.c 2018-06-22 06:11:49.000000000 -0500 +++ systemd-239/src/import/importd.c 2018-11-04 08:49:10.198692730 -0600 @@ -608,7 +608,7 @@ static int manager_new(Manager **ret) { return -errno; (void) mkdir_parents_label(sa.un.sun_path, 0755); - (void) unlink(sa.un.sun_path); + (void) sockaddr_un_unlink(&sa.un); if (bind(m->notify_fd, &sa.sa, SOCKADDR_UN_LEN(sa.un)) < 0) return -errno; diff -Naurp systemd-239-orig/src/import/import-raw.c systemd-239/src/import/import-raw.c --- systemd-239-orig/src/import/import-raw.c 2018-06-22 06:11:49.000000000 -0500 +++ systemd-239/src/import/import-raw.c 2018-11-04 08:49:10.198692730 -0600 @@ -307,7 +307,7 @@ static int raw_import_write(const void * n = sparse_write(i->output_fd, p, sz, 64); if (n < 0) - return -errno; + return (int) n; if ((size_t) n < sz) return -EIO; diff -Naurp systemd-239-orig/src/import/pull-job.c systemd-239/src/import/pull-job.c --- systemd-239-orig/src/import/pull-job.c 2018-06-22 06:11:49.000000000 -0500 +++ systemd-239/src/import/pull-job.c 2018-11-04 08:49:10.198692730 -0600 @@ -4,6 +4,7 @@ #include "alloc-util.h" #include "fd-util.h" +#include "gcrypt-util.h" #include "hexdecoct.h" #include "import-util.h" #include "io-util.h" @@ -232,10 +233,13 @@ static int pull_job_write_uncompressed(c if (j->allow_sparse) n = sparse_write(j->disk_fd, p, sz, 64); - else + else { n = write(j->disk_fd, p, sz); + if (n < 0) + n = -errno; + } if (n < 0) - return log_error_errno(errno, "Failed to write file: %m"); + return log_error_errno((int) n, "Failed to write file: %m"); if ((size_t) n < sz) { log_error("Short write"); return -EIO; @@ -317,6 +321,8 @@ static int pull_job_open_disk(PullJob *j } if (j->calc_checksum) { + initialize_libgcrypt(false); + if (gcry_md_open(&j->checksum_context, GCRY_MD_SHA256, 0) != 0) { log_error("Failed to initialize hash context."); return -EIO; diff -Naurp systemd-239-orig/src/journal/journalctl.c systemd-239/src/journal/journalctl.c --- systemd-239-orig/src/journal/journalctl.c 2018-06-22 06:11:49.000000000 -0500 +++ systemd-239/src/journal/journalctl.c 2018-11-04 08:49:10.199692729 -0600 @@ -342,11 +342,9 @@ static void help(void) { " -D --directory=PATH Show journal files from directory\n" " --file=PATH Show journal file\n" " --root=ROOT Operate on files below a root directory\n" -#if HAVE_GCRYPT " --interval=TIME Time interval for changing the FSS sealing key\n" " --verify-key=KEY Specify FSS verification key\n" " --force Override of the FSS key pair with --setup-keys\n" -#endif "\nCommands:\n" " -h --help Show this help text\n" " --version Show package version\n" @@ -365,9 +363,7 @@ static void help(void) { " --dump-catalog Show entries in the message catalog\n" " --update-catalog Update the message catalog database\n" " --new-id128 Generate a new 128-bit ID\n" -#if HAVE_GCRYPT " --setup-keys Generate a new FSS key pair\n" -#endif , program_invocation_short_name); } @@ -741,7 +737,7 @@ static int parse_argv(int argc, char *ar case ARG_VERIFY_KEY: case ARG_INTERVAL: case ARG_FORCE: - log_error("Forward-secure sealing not available."); + log_error("Compiled without forward-secure sealing support."); return -EOPNOTSUPP; #endif diff -Naurp systemd-239-orig/src/journal/journald.conf systemd-239/src/journal/journald.conf --- systemd-239-orig/src/journal/journald.conf 2018-06-22 06:11:49.000000000 -0500 +++ systemd-239/src/journal/journald.conf 2018-11-04 08:49:10.200692729 -0600 @@ -40,3 +40,4 @@ #MaxLevelConsole=info #MaxLevelWall=emerg #LineMax=48K +#ReadKMsg=yes diff -Naurp systemd-239-orig/src/journal/journald-native.c systemd-239/src/journal/journald-native.c --- systemd-239-orig/src/journal/journald-native.c 2018-06-22 06:11:49.000000000 -0500 +++ systemd-239/src/journal/journald-native.c 2018-11-04 08:49:10.199692729 -0600 @@ -453,7 +453,7 @@ int server_open_native_socket(Server*s) if (s->native_fd < 0) return log_error_errno(errno, "socket() failed: %m"); - (void) unlink(sa.un.sun_path); + (void) sockaddr_un_unlink(&sa.un); r = bind(s->native_fd, &sa.sa, SOCKADDR_UN_LEN(sa.un)); if (r < 0) diff -Naurp systemd-239-orig/src/journal/journald-server.c systemd-239/src/journal/journald-server.c --- systemd-239-orig/src/journal/journald-server.c 2018-06-22 06:11:49.000000000 -0500 +++ systemd-239/src/journal/journald-server.c 2018-11-04 08:49:10.200692729 -0600 @@ -1036,7 +1036,8 @@ int server_flush_to_var(Server *s, bool r = 0; finish: - journal_file_post_change(s->system_journal); + if (s->system_journal) + journal_file_post_change(s->system_journal); s->runtime_journal = journal_file_close(s->runtime_journal); diff -Naurp systemd-239-orig/src/journal/journald-stream.c systemd-239/src/journal/journald-stream.c --- systemd-239-orig/src/journal/journald-stream.c 2018-06-22 06:11:49.000000000 -0500 +++ systemd-239/src/journal/journald-stream.c 2018-11-04 08:49:10.200692729 -0600 @@ -610,7 +610,17 @@ static int stdout_stream_new(sd_event_so } if (s->n_stdout_streams >= STDOUT_STREAMS_MAX) { - log_warning("Too many stdout streams, refusing connection."); + struct ucred u; + + r = getpeercred(fd, &u); + + /* By closing fd here we make sure that the client won't wait too long for journald to + * gather all the data it adds to the error message to find out that the connection has + * just been refused. + */ + fd = safe_close(fd); + + server_driver_message(s, r < 0 ? 0 : u.pid, NULL, LOG_MESSAGE("Too many stdout streams, refusing connection."), NULL); return 0; } @@ -793,7 +803,7 @@ int server_open_stdout_socket(Server *s) if (s->stdout_fd < 0) return log_error_errno(errno, "socket() failed: %m"); - (void) unlink(sa.un.sun_path); + (void) sockaddr_un_unlink(&sa.un); r = bind(s->stdout_fd, &sa.sa, SOCKADDR_UN_LEN(sa.un)); if (r < 0) diff -Naurp systemd-239-orig/src/journal/journald-syslog.c systemd-239/src/journal/journald-syslog.c --- systemd-239-orig/src/journal/journald-syslog.c 2018-06-22 06:11:49.000000000 -0500 +++ systemd-239/src/journal/journald-syslog.c 2018-11-04 08:49:10.200692729 -0600 @@ -397,7 +397,7 @@ int server_open_syslog_socket(Server *s) if (s->syslog_fd < 0) return log_error_errno(errno, "socket() failed: %m"); - (void) unlink(sa.un.sun_path); + (void) sockaddr_un_unlink(&sa.un); r = bind(s->syslog_fd, &sa.sa, SOCKADDR_UN_LEN(sa.un)); if (r < 0) diff -Naurp systemd-239-orig/src/journal/journal-file.c systemd-239/src/journal/journal-file.c --- systemd-239-orig/src/journal/journal-file.c 2018-06-22 06:11:49.000000000 -0500 +++ systemd-239/src/journal/journal-file.c 2018-11-04 08:49:10.199692729 -0600 @@ -1846,6 +1846,9 @@ static int journal_file_append_entry_int void journal_file_post_change(JournalFile *f) { assert(f); + if (f->fd < 0) + return; + /* inotify() does not receive IN_MODIFY events from file * accesses done via mmap(). After each access we hence * trigger IN_MODIFY by truncating the journal file to its diff -Naurp systemd-239-orig/src/journal/sd-journal.c systemd-239/src/journal/sd-journal.c --- systemd-239-orig/src/journal/sd-journal.c 2018-06-22 06:11:49.000000000 -0500 +++ systemd-239/src/journal/sd-journal.c 2018-11-04 08:49:10.200692729 -0600 @@ -16,6 +16,7 @@ #include "catalog.h" #include "compress.h" #include "dirent-util.h" +#include "escape.h" #include "fd-util.h" #include "fileio.h" #include "format-util.h" @@ -381,7 +382,7 @@ static char *match_make_string(Match *m) return strdup("none"); if (m->type == MATCH_DISCRETE) - return strndup(m->data, m->size); + return cescape_length(m->data, m->size); LIST_FOREACH(matches, i, m->matches) { char *t, *k; diff -Naurp systemd-239-orig/src/journal/test-journal-match.c systemd-239/src/journal/test-journal-match.c --- systemd-239-orig/src/journal/test-journal-match.c 2018-06-22 06:11:49.000000000 -0500 +++ systemd-239/src/journal/test-journal-match.c 2018-11-04 08:49:10.200692729 -0600 @@ -23,6 +23,8 @@ int main(int argc, char *argv[]) { assert_se(sd_journal_add_match(j, "", 0) < 0); assert_se(sd_journal_add_match(j, "=", 0) < 0); assert_se(sd_journal_add_match(j, "=xxxxx", 0) < 0); + assert_se(sd_journal_add_match(j, (uint8_t[4]){'A', '=', '\1', '\2'}, 4) >= 0); + assert_se(sd_journal_add_match(j, (uint8_t[5]){'B', '=', 'C', '\0', 'D'}, 5) >= 0); assert_se(sd_journal_add_match(j, "HALLO=WALDO", 0) >= 0); assert_se(sd_journal_add_match(j, "QUUX=mmmm", 0) >= 0); assert_se(sd_journal_add_match(j, "QUUX=xxxxx", 0) >= 0); @@ -53,7 +55,7 @@ int main(int argc, char *argv[]) { printf("resulting match expression is: %s\n", t); - assert_se(streq(t, "(((L3=ok OR L3=yes) OR ((L4_2=ok OR L4_2=yes) AND (L4_1=ok OR L4_1=yes))) AND ((TWO=two AND (ONE=two OR ONE=one)) OR (PIFF=paff AND (QUUX=yyyyy OR QUUX=xxxxx OR QUUX=mmmm) AND (HALLO= OR HALLO=WALDO))))")); + assert_se(streq(t, "(((L3=ok OR L3=yes) OR ((L4_2=ok OR L4_2=yes) AND (L4_1=ok OR L4_1=yes))) AND ((TWO=two AND (ONE=two OR ONE=one)) OR (PIFF=paff AND (QUUX=yyyyy OR QUUX=xxxxx OR QUUX=mmmm) AND (HALLO= OR HALLO=WALDO) AND B=C\\000D AND A=\\001\\002)))")); return 0; } diff -Naurp systemd-239-orig/src/journal-remote/browse.html systemd-239/src/journal-remote/browse.html --- systemd-239-orig/src/journal-remote/browse.html 2018-06-22 06:11:49.000000000 -0500 +++ systemd-239/src/journal-remote/browse.html 2018-11-04 08:49:10.199692729 -0600 @@ -236,10 +236,12 @@ function entriesLoad(range) { - if (range == null) - range = localStorage["cursor"] + ":0"; - if (range == null) - range = ""; + if (range == null) { + if (localStorage["cursor"] != null && localStorage["cursor"] != "") + range = localStorage["cursor"] + ":0"; + else + range = ""; + } var url = "/entries"; @@ -304,7 +306,6 @@ var buf = ''; for (i in l) { - if (l[i] == '') continue; @@ -322,6 +323,7 @@ else priority = 6; + var clazz; if (priority <= 3) clazz = "message-error"; else if (priority <= 5) @@ -388,7 +390,7 @@ var d = JSON.parse(event.currentTarget.responseText); document.getElementById("diventry").style.display = "block"; - entry = document.getElementById("tableentry"); + var entry = document.getElementById("tableentry"); var buf = ""; for (var key in d) { @@ -455,7 +457,7 @@ (event.currentTarget.status != 200 && event.currentTarget.status != 0)) return; - f = document.getElementById("filter"); + var f = document.getElementById("filter"); var l = event.currentTarget.responseText.split('\n'); var buf = ''; @@ -511,11 +513,12 @@ } function initFilter() { - f = document.getElementById("filter"); + var f = document.getElementById("filter"); var buf = ''; var filter = localStorage["filter"]; + var j; if (filter != null && filter != "") { buf += ''; j = 1; @@ -529,7 +532,7 @@ function installHandlers() { document.onkeyup = onKeyUp; - logs = document.getElementById("divlogs"); + var logs = document.getElementById("divlogs"); logs.addEventListener("mousewheel", onMouseWheel, false); logs.addEventListener("DOMMouseScroll", onMouseWheel, false); } diff -Naurp systemd-239-orig/src/journal-remote/journal-upload.c systemd-239/src/journal-remote/journal-upload.c --- systemd-239-orig/src/journal-remote/journal-upload.c 2018-06-22 06:11:49.000000000 -0500 +++ systemd-239/src/journal-remote/journal-upload.c 2018-11-04 08:49:10.199692729 -0600 @@ -279,30 +279,30 @@ int start_upload(Uploader *u, static size_t fd_input_callback(void *buf, size_t size, size_t nmemb, void *userp) { Uploader *u = userp; - - ssize_t r; + ssize_t n; assert(u); - assert(nmemb <= SSIZE_MAX / size); + assert(nmemb < SSIZE_MAX / size); if (u->input < 0) return 0; - r = read(u->input, buf, size * nmemb); - log_debug("%s: allowed %zu, read %zd", __func__, size*nmemb, r); + assert(!size_multiply_overflow(size, nmemb)); - if (r > 0) - return r; + n = read(u->input, buf, size * nmemb); + log_debug("%s: allowed %zu, read %zd", __func__, size*nmemb, n); + if (n > 0) + return n; u->uploading = false; - if (r == 0) { - log_debug("Reached EOF"); - close_fd_input(u); - return 0; - } else { + if (n < 0) { log_error_errno(errno, "Aborting transfer after read error on input: %m."); return CURL_READFUNC_ABORT; } + + log_debug("Reached EOF"); + close_fd_input(u); + return 0; } static void close_fd_input(Uploader *u) { diff -Naurp systemd-239-orig/src/kernel-install/50-depmod.install systemd-239/src/kernel-install/50-depmod.install --- systemd-239-orig/src/kernel-install/50-depmod.install 2018-06-22 06:11:49.000000000 -0500 +++ systemd-239/src/kernel-install/50-depmod.install 2018-11-04 08:49:10.200692729 -0600 @@ -6,6 +6,7 @@ case "$1" in add) + [[ -d /lib/modules/"$2"/kernel ]] || exit 0 exec depmod -a "$2" ;; remove) diff -Naurp systemd-239-orig/src/libsystemd/disable-mempool.c systemd-239/src/libsystemd/disable-mempool.c --- systemd-239-orig/src/libsystemd/disable-mempool.c 1969-12-31 18:00:00.000000000 -0600 +++ systemd-239/src/libsystemd/disable-mempool.c 2018-11-04 08:49:10.201692729 -0600 @@ -0,0 +1,5 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include "mempool.h" + +const bool mempool_use_allowed = false; diff -Naurp systemd-239-orig/src/libsystemd/meson.build systemd-239/src/libsystemd/meson.build --- systemd-239-orig/src/libsystemd/meson.build 2018-06-22 06:11:49.000000000 -0500 +++ systemd-239/src/libsystemd/meson.build 2018-11-04 08:49:10.201692729 -0600 @@ -80,6 +80,8 @@ libsystemd_sources = files(''' sd-utf8/sd-utf8.c '''.split()) + id128_sources + sd_daemon_c + sd_event_c + sd_login_c +disable_mempool_c = files('disable-mempool.c') + libsystemd_c_args = ['-fvisibility=default'] libsystemd_static = static_library( diff -Naurp systemd-239-orig/src/libsystemd/sd-bus/bus-dump.c systemd-239/src/libsystemd/sd-bus/bus-dump.c --- systemd-239-orig/src/libsystemd/sd-bus/bus-dump.c 2018-06-22 06:11:49.000000000 -0500 +++ systemd-239/src/libsystemd/sd-bus/bus-dump.c 2018-11-04 08:49:10.201692729 -0600 @@ -59,8 +59,14 @@ int bus_message_dump(sd_bus_message *m, "%s%s%s Type=%s%s%s Endian=%c Flags=%u Version=%u Priority=%"PRIi64, m->header->type == SD_BUS_MESSAGE_METHOD_ERROR ? ansi_highlight_red() : m->header->type == SD_BUS_MESSAGE_METHOD_RETURN ? ansi_highlight_green() : - m->header->type != SD_BUS_MESSAGE_SIGNAL ? ansi_highlight() : "", special_glyph(TRIANGULAR_BULLET), ansi_normal(), - ansi_highlight(), bus_message_type_to_string(m->header->type), ansi_normal(), + m->header->type != SD_BUS_MESSAGE_SIGNAL ? ansi_highlight() : "", + special_glyph(TRIANGULAR_BULLET), + ansi_normal(), + + ansi_highlight(), + bus_message_type_to_string(m->header->type) ?: "(unknown)", + ansi_normal(), + m->header->endian, m->header->flags, m->header->version, diff -Naurp systemd-239-orig/src/libsystemd/sd-bus/bus-error.c systemd-239/src/libsystemd/sd-bus/bus-error.c --- systemd-239-orig/src/libsystemd/sd-bus/bus-error.c 2018-06-22 06:11:49.000000000 -0500 +++ systemd-239/src/libsystemd/sd-bus/bus-error.c 2018-11-04 08:49:10.201692729 -0600 @@ -310,6 +310,28 @@ finish: return -bus_error_name_to_errno(e->name); } +int sd_bus_error_move(sd_bus_error *dest, sd_bus_error *e) { + int r; + + if (!sd_bus_error_is_set(e)) { + + if (dest) + *dest = SD_BUS_ERROR_NULL; + + return 0; + } + + r = -bus_error_name_to_errno(e->name); + + if (dest) { + *dest = *e; + *e = SD_BUS_ERROR_NULL; + } else + sd_bus_error_free(e); + + return r; +} + _public_ int sd_bus_error_set_const(sd_bus_error *e, const char *name, const char *message) { if (!name) return 0; diff -Naurp systemd-239-orig/src/libsystemd/sd-bus/bus-error.h systemd-239/src/libsystemd/sd-bus/bus-error.h --- systemd-239-orig/src/libsystemd/sd-bus/bus-error.h 2018-06-22 06:11:49.000000000 -0500 +++ systemd-239/src/libsystemd/sd-bus/bus-error.h 2018-11-04 08:49:10.201692729 -0600 @@ -47,3 +47,5 @@ int bus_error_set_errnofv(sd_bus_error * #define BUS_ERROR_MAP_END_MARKER -'x' BUS_ERROR_MAP_ELF_USE(bus_standard_errors); + +int sd_bus_error_move(sd_bus_error *dest, sd_bus_error *e); diff -Naurp systemd-239-orig/src/libsystemd/sd-bus/bus-introspect.c systemd-239/src/libsystemd/sd-bus/bus-introspect.c --- systemd-239-orig/src/libsystemd/sd-bus/bus-introspect.c 2018-06-22 06:11:49.000000000 -0500 +++ systemd-239/src/libsystemd/sd-bus/bus-introspect.c 2018-11-04 08:49:10.201692729 -0600 @@ -63,7 +63,7 @@ int introspect_write_child_nodes(struct return 0; } -static void introspect_write_flags(struct introspect *i, int type, int flags) { +static void introspect_write_flags(struct introspect *i, int type, uint64_t flags) { if (flags & SD_BUS_VTABLE_DEPRECATED) fputs(" \n", i->f); diff -Naurp systemd-239-orig/src/libsystemd/sd-bus/bus-message.c systemd-239/src/libsystemd/sd-bus/bus-message.c --- systemd-239-orig/src/libsystemd/sd-bus/bus-message.c 2018-06-22 06:11:49.000000000 -0500 +++ systemd-239/src/libsystemd/sd-bus/bus-message.c 2018-11-04 08:49:10.201692729 -0600 @@ -77,19 +77,38 @@ static void message_reset_parts(sd_bus_m m->cached_rindex_part_begin = 0; } -static void message_reset_containers(sd_bus_message *m) { - unsigned i; +static struct bus_container *message_get_container(sd_bus_message *m) { + assert(m); + + if (m->n_containers == 0) + return &m->root_container; + + assert(m->containers); + return m->containers + m->n_containers - 1; +} +static void message_free_last_container(sd_bus_message *m) { + struct bus_container *c; + + c = message_get_container(m); + + free(c->signature); + free(c->peeked_signature); + free(c->offsets); + + /* Move to previous container, but not if we are on root container */ + if (m->n_containers > 0) + m->n_containers--; +} + +static void message_reset_containers(sd_bus_message *m) { assert(m); - for (i = 0; i < m->n_containers; i++) { - free(m->containers[i].signature); - free(m->containers[i].offsets); - } + while (m->n_containers > 0) + message_free_last_container(m); m->containers = mfree(m->containers); - - m->n_containers = m->containers_allocated = 0; + m->containers_allocated = 0; m->root_container.index = 0; } @@ -112,10 +131,8 @@ static sd_bus_message* message_free(sd_b free(m->iovec); message_reset_containers(m); - free(m->root_container.signature); - free(m->root_container.offsets); - - free(m->root_container.peeked_signature); + assert(m->n_containers == 0); + message_free_last_container(m); bus_creds_done(&m->creds); return mfree(m); @@ -1113,16 +1130,6 @@ _public_ int sd_bus_message_set_allow_in return 0; } -static struct bus_container *message_get_container(sd_bus_message *m) { - assert(m); - - if (m->n_containers == 0) - return &m->root_container; - - assert(m->containers); - return m->containers + m->n_containers - 1; -} - struct bus_body_part *message_append_part(sd_bus_message *m) { struct bus_body_part *part; @@ -1949,7 +1956,7 @@ _public_ int sd_bus_message_open_contain char type, const char *contents) { - struct bus_container *c, *w; + struct bus_container *c; uint32_t *array_size = NULL; _cleanup_free_ char *signature = NULL; size_t before, begin = 0; @@ -1994,16 +2001,14 @@ _public_ int sd_bus_message_open_contain return r; /* OK, let's fill it in */ - w = m->containers + m->n_containers++; - w->enclosing = type; - w->signature = TAKE_PTR(signature); - w->index = 0; - w->array_size = array_size; - w->before = before; - w->begin = begin; - w->n_offsets = w->offsets_allocated = 0; - w->offsets = NULL; - w->need_offsets = need_offsets; + m->containers[m->n_containers++] = (struct bus_container) { + .enclosing = type, + .signature = TAKE_PTR(signature), + .array_size = array_size, + .before = before, + .begin = begin, + .need_offsets = need_offsets, + }; return 0; } @@ -3135,6 +3140,7 @@ static int container_next_item(sd_bus_me assert(alignment > 0); *rindex = ALIGN_TO(c->offsets[c->offset_index], alignment); + assert(c->offsets[c->offset_index+1] >= *rindex); c->item_size = c->offsets[c->offset_index+1] - *rindex; } else { @@ -3174,6 +3180,7 @@ static int container_next_item(sd_bus_me assert(alignment > 0); *rindex = ALIGN_TO(c->offsets[c->offset_index], alignment); + assert(c->offsets[c->offset_index+1] >= *rindex); c->item_size = c->offsets[c->offset_index+1] - *rindex; c->offset_index++; @@ -3312,6 +3319,12 @@ _public_ int sd_bus_message_read_basic(s if (IN_SET(type, SD_BUS_TYPE_STRING, SD_BUS_TYPE_OBJECT_PATH, SD_BUS_TYPE_SIGNATURE)) { bool ok; + /* D-Bus spec: The marshalling formats for the string-like types all end + * with a single zero (NUL) byte, but that byte is not considered to be part + * of the text. */ + if (c->item_size == 0) + return -EBADMSG; + r = message_peek_body(m, &rindex, 1, c->item_size, &q); if (r < 0) return r; @@ -3406,6 +3419,10 @@ _public_ int sd_bus_message_read_basic(s return r; l = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q); + if (l == UINT32_MAX) + /* avoid overflow right below */ + return -EBADMSG; + r = message_peek_body(m, &rindex, 1, l+1, &q); if (r < 0) return r; @@ -3428,6 +3445,10 @@ _public_ int sd_bus_message_read_basic(s return r; l = *(uint8_t*) q; + if (l == UINT8_MAX) + /* avoid overflow right below */ + return -EBADMSG; + r = message_peek_body(m, &rindex, 1, l+1, &q); if (r < 0) return r; @@ -3519,7 +3540,7 @@ static int bus_message_enter_array( size_t rindex; void *q; - int r, alignment; + int r; assert(m); assert(c); @@ -3545,6 +3566,7 @@ static int bus_message_enter_array( if (!BUS_MESSAGE_IS_GVARIANT(m)) { /* dbus1 */ + int alignment; r = message_peek_body(m, &rindex, 4, 4, &q); if (r < 0) @@ -3578,7 +3600,8 @@ static int bus_message_enter_array( *n_offsets = 0; } else { - size_t where, p = 0, framing, sz; + size_t where, previous = 0, framing, sz; + int alignment; unsigned i; /* gvariant: variable length array */ @@ -3606,17 +3629,22 @@ static int bus_message_enter_array( if (!*offsets) return -ENOMEM; + alignment = bus_gvariant_get_alignment(c->signature); + assert(alignment > 0); + for (i = 0; i < *n_offsets; i++) { - size_t x; + size_t x, start; + + start = ALIGN_TO(previous, alignment); x = bus_gvariant_read_word_le((uint8_t*) q + i * sz, sz); if (x > c->item_size - sz) return -EBADMSG; - if (x < p) + if (x < start) return -EBADMSG; (*offsets)[i] = rindex + x; - p = x; + previous = x; } *item_size = (*offsets)[0] - rindex; @@ -3686,6 +3714,10 @@ static int bus_message_enter_variant( return r; l = *(uint8_t*) q; + if (l == UINT8_MAX) + /* avoid overflow right below */ + return -EBADMSG; + r = message_peek_body(m, &rindex, 1, l+1, &q); if (r < 0) return r; @@ -3714,7 +3746,7 @@ static int build_struct_offsets( size_t *n_offsets) { unsigned n_variable = 0, n_total = 0, v; - size_t previous = 0, where; + size_t previous, where; const char *p; size_t sz; void *q; @@ -3793,6 +3825,7 @@ static int build_struct_offsets( /* Second, loop again and build an offset table */ p = signature; + previous = m->rindex; while (*p != 0) { size_t n, offset; int k; @@ -3806,37 +3839,34 @@ static int build_struct_offsets( memcpy(t, p, n); t[n] = 0; + size_t align = bus_gvariant_get_alignment(t); + assert(align > 0); + + /* The possible start of this member after including alignment */ + size_t start = ALIGN_TO(previous, align); + k = bus_gvariant_get_size(t); if (k < 0) { size_t x; - /* variable size */ + /* Variable size */ if (v > 0) { v--; x = bus_gvariant_read_word_le((uint8_t*) q + v*sz, sz); if (x >= size) return -EBADMSG; - if (m->rindex + x < previous) - return -EBADMSG; } else - /* The last item's end - * is determined from - * the start of the - * offset array */ + /* The last item's end is determined + * from the start of the offset array */ x = size - (n_variable * sz); offset = m->rindex + x; - - } else { - size_t align; - - /* fixed size */ - align = bus_gvariant_get_alignment(t); - assert(align > 0); - - offset = (*n_offsets == 0 ? m->rindex : ALIGN_TO((*offsets)[*n_offsets-1], align)) + k; - } + if (offset < start) + return -EBADMSG; + } else + /* Fixed size */ + offset = start + k; } previous = (*offsets)[(*n_offsets)++] = offset; @@ -3966,10 +3996,10 @@ static int bus_message_enter_dict_entry( _public_ int sd_bus_message_enter_container(sd_bus_message *m, char type, const char *contents) { - struct bus_container *c, *w; + struct bus_container *c; uint32_t *array_size = NULL; _cleanup_free_ char *signature = NULL; - size_t before; + size_t before, end; _cleanup_free_ size_t *offsets = NULL; size_t n_offsets = 0, item_size = 0; int r; @@ -4048,28 +4078,26 @@ _public_ int sd_bus_message_enter_contai return r; /* OK, let's fill it in */ - w = m->containers + m->n_containers++; - w->enclosing = type; - w->signature = TAKE_PTR(signature); - w->peeked_signature = NULL; - w->index = 0; - - w->before = before; - w->begin = m->rindex; - - /* Unary type has fixed size of 1, but virtual size of 0 */ if (BUS_MESSAGE_IS_GVARIANT(m) && type == SD_BUS_TYPE_STRUCT && isempty(signature)) - w->end = m->rindex + 0; + end = m->rindex + 0; else - w->end = m->rindex + c->item_size; - - w->array_size = array_size; - w->item_size = item_size; - w->offsets = TAKE_PTR(offsets); - w->n_offsets = n_offsets; - w->offset_index = 0; + end = m->rindex + c->item_size; + + m->containers[m->n_containers++] = (struct bus_container) { + .enclosing = type, + .signature = TAKE_PTR(signature), + + .before = before, + .begin = m->rindex, + /* Unary type has fixed size of 1, but virtual size of 0 */ + .end = end, + .array_size = array_size, + .item_size = item_size, + .offsets = TAKE_PTR(offsets), + .n_offsets = n_offsets, + }; return 1; } @@ -4102,13 +4130,9 @@ _public_ int sd_bus_message_exit_contain return -EBUSY; } - free(c->signature); - free(c->peeked_signature); - free(c->offsets); - m->n_containers--; + message_free_last_container(m); c = message_get_container(m); - saved = c->index; c->index = c->saved_index; r = container_next_item(m, c, &m->rindex); @@ -4126,16 +4150,13 @@ static void message_quit_container(sd_bu assert(m->sealed); assert(m->n_containers > 0); - c = message_get_container(m); - /* Undo seeks */ + c = message_get_container(m); assert(m->rindex >= c->before); m->rindex = c->before; /* Free container */ - free(c->signature); - free(c->offsets); - m->n_containers--; + message_free_last_container(m); /* Correct index of new top-level container */ c = message_get_container(m); @@ -4169,20 +4190,20 @@ _public_ int sd_bus_message_peek_type(sd if (contents) { size_t l; - char *sig; r = signature_element_length(c->signature+c->index+1, &l); if (r < 0) return r; - assert(l >= 1); + /* signature_element_length does verification internally */ - sig = strndup(c->signature + c->index + 1, l); - if (!sig) + /* The array element must not be empty */ + assert(l >= 1); + if (free_and_strndup(&c->peeked_signature, + c->signature + c->index + 1, l) < 0) return -ENOMEM; - free(c->peeked_signature); - *contents = c->peeked_signature = sig; + *contents = c->peeked_signature; } if (type) @@ -4195,19 +4216,17 @@ _public_ int sd_bus_message_peek_type(sd if (contents) { size_t l; - char *sig; r = signature_element_length(c->signature+c->index, &l); if (r < 0) return r; - assert(l >= 2); - sig = strndup(c->signature + c->index + 1, l - 2); - if (!sig) + assert(l >= 3); + if (free_and_strndup(&c->peeked_signature, + c->signature + c->index + 1, l - 2) < 0) return -ENOMEM; - free(c->peeked_signature); - *contents = c->peeked_signature = sig; + *contents = c->peeked_signature; } if (type) @@ -4247,9 +4266,8 @@ _public_ int sd_bus_message_peek_type(sd if (k > c->item_size) return -EBADMSG; - free(c->peeked_signature); - c->peeked_signature = strndup((char*) q + 1, k - 1); - if (!c->peeked_signature) + if (free_and_strndup(&c->peeked_signature, + (char*) q + 1, k - 1) < 0) return -ENOMEM; if (!signature_is_valid(c->peeked_signature, true)) @@ -4265,6 +4283,10 @@ _public_ int sd_bus_message_peek_type(sd return r; l = *(uint8_t*) q; + if (l == UINT8_MAX) + /* avoid overflow right below */ + return -EBADMSG; + r = message_peek_body(m, &rindex, 1, l+1, &q); if (r < 0) return r; @@ -4850,6 +4872,10 @@ static int message_peek_field_string( if (r < 0) return r; + if (l == UINT32_MAX) + /* avoid overflow right below */ + return -EBADMSG; + r = message_peek_fields(m, ri, 1, l+1, &q); if (r < 0) return r; @@ -4901,6 +4927,10 @@ static int message_peek_field_signature( return r; l = *(uint8_t*) q; + if (l == UINT8_MAX) + /* avoid overflow right below */ + return -EBADMSG; + r = message_peek_fields(m, ri, 1, l+1, &q); if (r < 0) return r; @@ -4982,18 +5012,18 @@ static int message_skip_fields( } else if (t == SD_BUS_TYPE_ARRAY) { - r = signature_element_length(*signature+1, &l); + r = signature_element_length(*signature + 1, &l); if (r < 0) return r; assert(l >= 1); { - char sig[l-1], *s; + char sig[l + 1], *s = sig; uint32_t nas; int alignment; - strncpy(sig, *signature + 1, l-1); - s = sig; + strncpy(sig, *signature + 1, l); + sig[l] = '\0'; alignment = bus_type_get_alignment(sig[0]); if (alignment < 0) @@ -5037,9 +5067,9 @@ static int message_skip_fields( assert(l >= 2); { - char sig[l-1], *s; - strncpy(sig, *signature + 1, l-1); - s = sig; + char sig[l + 1], *s = sig; + strncpy(sig, *signature + 1, l); + sig[l] = '\0'; r = message_skip_fields(m, ri, (uint32_t) -1, (const char**) &s); if (r < 0) @@ -5048,7 +5078,7 @@ static int message_skip_fields( *signature += l; } else - return -EINVAL; + return -EBADMSG; } } @@ -5079,25 +5109,21 @@ int bus_message_parse_fields(sd_bus_mess if (*p == 0) { size_t l; - char *c; /* We found the beginning of the signature * string, yay! We require the body to be a * structure, so verify it and then strip the * opening/closing brackets. */ - l = ((char*) m->footer + m->footer_accessible) - p - (1 + sz); + l = (char*) m->footer + m->footer_accessible - p - (1 + sz); if (l < 2 || p[1] != SD_BUS_TYPE_STRUCT_BEGIN || p[1 + l - 1] != SD_BUS_TYPE_STRUCT_END) return -EBADMSG; - c = strndup(p + 1 + 1, l - 2); - if (!c) + if (free_and_strndup(&m->root_container.signature, + p + 1 + 1, l - 2) < 0) return -ENOMEM; - - free(m->root_container.signature); - m->root_container.signature = c; break; } @@ -5419,6 +5445,8 @@ int bus_message_parse_fields(sd_bus_mess &m->root_container.item_size, &m->root_container.offsets, &m->root_container.n_offsets); + if (r == -EINVAL) + return -EBADMSG; if (r < 0) return r; } @@ -5433,6 +5461,7 @@ int bus_message_parse_fields(sd_bus_mess _public_ int sd_bus_message_set_destination(sd_bus_message *m, const char *destination) { assert_return(m, -EINVAL); assert_return(destination, -EINVAL); + assert_return(service_name_is_valid(destination), -EINVAL); assert_return(!m->sealed, -EPERM); assert_return(!m->destination, -EEXIST); @@ -5442,6 +5471,7 @@ _public_ int sd_bus_message_set_destinat _public_ int sd_bus_message_set_sender(sd_bus_message *m, const char *sender) { assert_return(m, -EINVAL); assert_return(sender, -EINVAL); + assert_return(service_name_is_valid(sender), -EINVAL); assert_return(!m->sealed, -EPERM); assert_return(!m->sender, -EEXIST); diff -Naurp systemd-239-orig/src/libsystemd/sd-bus/bus-signature.c systemd-239/src/libsystemd/sd-bus/bus-signature.c --- systemd-239-orig/src/libsystemd/sd-bus/bus-signature.c 2018-06-22 06:11:49.000000000 -0500 +++ systemd-239/src/libsystemd/sd-bus/bus-signature.c 2018-11-04 08:49:10.202692728 -0600 @@ -58,6 +58,12 @@ static int signature_element_length_inte p += t; } + if (p - s < 2) + /* D-Bus spec: Empty structures are not allowed; there + * must be at least one type code between the parentheses. + */ + return -EINVAL; + *l = p - s + 1; return 0; } diff -Naurp systemd-239-orig/src/libsystemd/sd-bus/bus-slot.c systemd-239/src/libsystemd/sd-bus/bus-slot.c --- systemd-239-orig/src/libsystemd/sd-bus/bus-slot.c 2018-06-22 06:11:49.000000000 -0500 +++ systemd-239/src/libsystemd/sd-bus/bus-slot.c 2018-11-04 08:49:10.202692728 -0600 @@ -81,7 +81,10 @@ void bus_slot_disconnect(sd_bus_slot *sl (void) bus_remove_match_internal(slot->bus, slot->match_callback.match_string); if (slot->match_callback.install_slot) { - bus_slot_disconnect(slot->match_callback.install_slot); + if (slot->match_callback.install_slot->bus) { + bus_slot_disconnect(slot->match_callback.install_slot); + sd_bus_slot_unref(slot->match_callback.install_slot); + } slot->match_callback.install_slot = sd_bus_slot_unref(slot->match_callback.install_slot); } diff -Naurp systemd-239-orig/src/libsystemd/sd-bus/bus-socket.c systemd-239/src/libsystemd/sd-bus/bus-socket.c --- systemd-239-orig/src/libsystemd/sd-bus/bus-socket.c 2018-06-22 06:11:49.000000000 -0500 +++ systemd-239/src/libsystemd/sd-bus/bus-socket.c 2018-11-04 08:49:10.202692728 -0600 @@ -248,10 +248,7 @@ static bool line_begins(const char *s, s const char *p; p = memory_startswith(s, m, word); - if (!p) - return false; - - return IN_SET(*p, 0, ' '); + return p && (p == (s + m) || *p == ' '); } static int verify_anonymous_token(sd_bus *b, const char *p, size_t l) { diff -Naurp systemd-239-orig/src/libsystemd/sd-bus/test-bus-gvariant.c systemd-239/src/libsystemd/sd-bus/test-bus-gvariant.c --- systemd-239-orig/src/libsystemd/sd-bus/test-bus-gvariant.c 2018-06-22 06:11:49.000000000 -0500 +++ systemd-239/src/libsystemd/sd-bus/test-bus-gvariant.c 2018-11-04 08:49:10.202692728 -0600 @@ -19,7 +19,7 @@ static void test_bus_gvariant_is_fixed_size(void) { assert_se(bus_gvariant_is_fixed_size("") > 0); - assert_se(bus_gvariant_is_fixed_size("()") > 0); + assert_se(bus_gvariant_is_fixed_size("()") == -EINVAL); assert_se(bus_gvariant_is_fixed_size("y") > 0); assert_se(bus_gvariant_is_fixed_size("u") > 0); assert_se(bus_gvariant_is_fixed_size("b") > 0); @@ -44,7 +44,7 @@ static void test_bus_gvariant_is_fixed_s static void test_bus_gvariant_get_size(void) { assert_se(bus_gvariant_get_size("") == 0); - assert_se(bus_gvariant_get_size("()") == 1); + assert_se(bus_gvariant_get_size("()") == -EINVAL); assert_se(bus_gvariant_get_size("y") == 1); assert_se(bus_gvariant_get_size("u") == 4); assert_se(bus_gvariant_get_size("b") == 1); @@ -76,7 +76,7 @@ static void test_bus_gvariant_get_size(v static void test_bus_gvariant_get_alignment(void) { assert_se(bus_gvariant_get_alignment("") == 1); - assert_se(bus_gvariant_get_alignment("()") == 1); + assert_se(bus_gvariant_get_alignment("()") == -EINVAL); assert_se(bus_gvariant_get_alignment("y") == 1); assert_se(bus_gvariant_get_alignment("b") == 1); assert_se(bus_gvariant_get_alignment("u") == 4); diff -Naurp systemd-239-orig/src/libsystemd/sd-bus/test-bus-marshal.c systemd-239/src/libsystemd/sd-bus/test-bus-marshal.c --- systemd-239-orig/src/libsystemd/sd-bus/test-bus-marshal.c 2018-06-22 06:11:49.000000000 -0500 +++ systemd-239/src/libsystemd/sd-bus/test-bus-marshal.c 2018-11-04 08:49:10.202692728 -0600 @@ -151,7 +151,7 @@ int main(int argc, char *argv[]) { assert_se(r >= 0); r = sd_bus_message_append(m, "()"); - assert_se(r >= 0); + assert_se(r == -EINVAL); r = sd_bus_message_append(m, "ba(ss)", 255, 3, "aaa", "1", "bbb", "2", "ccc", "3"); assert_se(r >= 0); @@ -295,7 +295,7 @@ int main(int argc, char *argv[]) { assert_se(v == 10); r = sd_bus_message_read(m, "()"); - assert_se(r > 0); + assert_se(r < 0); r = sd_bus_message_read(m, "ba(ss)", &boolean, 3, &x, &y, &a, &b, &c, &d); assert_se(r > 0); @@ -376,7 +376,7 @@ int main(int argc, char *argv[]) { assert_se(sd_bus_message_verify_type(m, 'a', "{yv}") > 0); - r = sd_bus_message_skip(m, "a{yv}y(ty)y(yt)y()"); + r = sd_bus_message_skip(m, "a{yv}y(ty)y(yt)y"); assert_se(r >= 0); assert_se(sd_bus_message_verify_type(m, 'b', NULL) > 0); diff -Naurp systemd-239-orig/src/libsystemd/sd-bus/test-bus-signature.c systemd-239/src/libsystemd/sd-bus/test-bus-signature.c --- systemd-239-orig/src/libsystemd/sd-bus/test-bus-signature.c 2018-06-22 06:11:49.000000000 -0500 +++ systemd-239/src/libsystemd/sd-bus/test-bus-signature.c 2018-11-04 08:49:10.202692728 -0600 @@ -16,9 +16,9 @@ int main(int argc, char *argv[]) { assert_se(signature_is_single("v", false)); assert_se(signature_is_single("as", false)); assert_se(signature_is_single("(ss)", false)); - assert_se(signature_is_single("()", false)); - assert_se(signature_is_single("(()()()()())", false)); - assert_se(signature_is_single("(((())))", false)); + assert_se(!signature_is_single("()", false)); + assert_se(!signature_is_single("(()()()()())", false)); + assert_se(!signature_is_single("(((())))", false)); assert_se(signature_is_single("((((s))))", false)); assert_se(signature_is_single("{ss}", true)); assert_se(signature_is_single("a{ss}", false)); @@ -63,7 +63,7 @@ int main(int argc, char *argv[]) { assert_se(signature_is_valid("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaas", false)); assert_se(!signature_is_valid("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaau", false)); - assert_se(signature_is_valid("(((((((((((((((((((((((((((((((())))))))))))))))))))))))))))))))", false)); + assert_se(signature_is_valid("((((((((((((((((((((((((((((((((s))))))))))))))))))))))))))))))))", false)); assert_se(!signature_is_valid("((((((((((((((((((((((((((((((((()))))))))))))))))))))))))))))))))", false)); assert_se(namespace_complex_pattern("", "")); diff -Naurp systemd-239-orig/src/libsystemd/sd-device/test-udev-device-thread.c systemd-239/src/libsystemd/sd-device/test-udev-device-thread.c --- systemd-239-orig/src/libsystemd/sd-device/test-udev-device-thread.c 1969-12-31 18:00:00.000000000 -0600 +++ systemd-239/src/libsystemd/sd-device/test-udev-device-thread.c 2018-11-04 08:49:10.202692728 -0600 @@ -0,0 +1,39 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include +#include + +#include "libudev.h" + +#include "macro.h" +#include "udev-util.h" + +static void* thread(void *p) { + struct udev_device **d = p; + + assert_se(!(*d = udev_device_unref(*d))); + + return NULL; +} + +int main(int argc, char *argv[]) { + _cleanup_(udev_unrefp) struct udev *udev; + struct udev_device *loopback; + pthread_t t; + + assert_se(unsetenv("SYSTEMD_MEMPOOL") == 0); + + assert_se(udev = udev_new()); + assert_se(loopback = udev_device_new_from_syspath(udev, "/sys/class/net/lo")); + + assert_se(udev_device_get_properties_list_entry(loopback)); + + assert_se(pthread_create(&t, NULL, thread, &loopback) == 0); + assert_se(pthread_join(t, NULL) == 0); + + assert_se(!loopback); + + return 0; +} diff -Naurp systemd-239-orig/src/libsystemd/sd-netlink/netlink-types.c systemd-239/src/libsystemd/sd-netlink/netlink-types.c --- systemd-239-orig/src/libsystemd/sd-netlink/netlink-types.c 2018-06-22 06:11:49.000000000 -0500 +++ systemd-239/src/libsystemd/sd-netlink/netlink-types.c 2018-11-04 08:49:10.203692727 -0600 @@ -680,7 +680,7 @@ static const NLType genl_wireguard_peer_ [WGPEER_A_PUBLIC_KEY] = { .size = WG_KEY_LEN }, [WGPEER_A_FLAGS] = { .type = NETLINK_TYPE_U32 }, [WGPEER_A_PRESHARED_KEY] = { .size = WG_KEY_LEN }, - [WGPEER_A_PERSISTENT_KEEPALIVE_INTERVAL] = { .type = NETLINK_TYPE_U32 }, + [WGPEER_A_PERSISTENT_KEEPALIVE_INTERVAL] = { .type = NETLINK_TYPE_U16 }, [WGPEER_A_ENDPOINT] = { /* either size of sockaddr_in or sockaddr_in6 depending on address family */ }, [WGPEER_A_ALLOWEDIPS] = { .type = NETLINK_TYPE_NESTED, .type_system = &genl_wireguard_allowedip_type_system }, }; diff -Naurp systemd-239-orig/src/libsystemd/sd-netlink/sd-netlink.c systemd-239/src/libsystemd/sd-netlink/sd-netlink.c --- systemd-239-orig/src/libsystemd/sd-netlink/sd-netlink.c 2018-06-22 06:11:49.000000000 -0500 +++ systemd-239/src/libsystemd/sd-netlink/sd-netlink.c 2018-11-04 08:49:10.203692727 -0600 @@ -564,7 +564,7 @@ int sd_netlink_call_async(sd_netlink *nl if (c->timeout != 0) { r = prioq_put(nl->reply_callbacks_prioq, c, &c->prioq_idx); - if (r > 0) { + if (r < 0) { c->timeout = 0; sd_netlink_call_async_cancel(nl, c->serial); return r; diff -Naurp systemd-239-orig/src/libsystemd-network/dhcp6-internal.h systemd-239/src/libsystemd-network/dhcp6-internal.h --- systemd-239-orig/src/libsystemd-network/dhcp6-internal.h 2018-06-22 06:11:49.000000000 -0500 +++ systemd-239/src/libsystemd-network/dhcp6-internal.h 2018-11-04 08:49:10.200692729 -0600 @@ -91,7 +91,7 @@ int dhcp6_option_append_pd(uint8_t *buf, int dhcp6_option_append_fqdn(uint8_t **buf, size_t *buflen, const char *fqdn); int dhcp6_option_parse(uint8_t **buf, size_t *buflen, uint16_t *optcode, size_t *optlen, uint8_t **optvalue); -int dhcp6_option_parse_status(DHCP6Option *option); +int dhcp6_option_parse_status(DHCP6Option *option, size_t len); int dhcp6_option_parse_ia(DHCP6Option *iaoption, DHCP6IA *ia); int dhcp6_option_parse_ip6addrs(uint8_t *optval, uint16_t optlen, struct in6_addr **addrs, size_t count, diff -Naurp systemd-239-orig/src/libsystemd-network/dhcp6-option.c systemd-239/src/libsystemd-network/dhcp6-option.c --- systemd-239-orig/src/libsystemd-network/dhcp6-option.c 2018-06-22 06:11:49.000000000 -0500 +++ systemd-239/src/libsystemd-network/dhcp6-option.c 2018-11-04 08:49:10.200692729 -0600 @@ -103,7 +103,7 @@ int dhcp6_option_append_ia(uint8_t **buf return -EINVAL; } - if (*buflen < len) + if (*buflen < offsetof(DHCP6Option, data) + len) return -ENOBUFS; ia_hdr = *buf; @@ -247,10 +247,11 @@ int dhcp6_option_parse(uint8_t **buf, si return 0; } -int dhcp6_option_parse_status(DHCP6Option *option) { +int dhcp6_option_parse_status(DHCP6Option *option, size_t len) { DHCP6StatusOption *statusopt = (DHCP6StatusOption *)option; - if (be16toh(option->len) + sizeof(DHCP6Option) < sizeof(*statusopt)) + if (len < sizeof(DHCP6StatusOption) || + be16toh(option->len) + sizeof(DHCP6Option) < sizeof(DHCP6StatusOption)) return -ENOBUFS; return be16toh(statusopt->status); @@ -277,7 +278,7 @@ static int dhcp6_option_parse_address(DH } if (be16toh(option->len) + sizeof(DHCP6Option) > sizeof(*addr_option)) { - r = dhcp6_option_parse_status((DHCP6Option *)addr_option->options); + r = dhcp6_option_parse_status((DHCP6Option *)addr_option->options, be16toh(option->len) + sizeof(DHCP6Option) - sizeof(*addr_option)); if (r != 0) return r < 0 ? r: 0; } @@ -317,7 +318,7 @@ static int dhcp6_option_parse_pdprefix(D } if (be16toh(option->len) + sizeof(DHCP6Option) > sizeof(*pdprefix_option)) { - r = dhcp6_option_parse_status((DHCP6Option *)pdprefix_option->options); + r = dhcp6_option_parse_status((DHCP6Option *)pdprefix_option->options, be16toh(option->len) + sizeof(DHCP6Option) - sizeof(*pdprefix_option)); if (r != 0) return r < 0 ? r: 0; } @@ -462,7 +463,7 @@ int dhcp6_option_parse_ia(DHCP6Option *i case SD_DHCP6_OPTION_STATUS_CODE: - status = dhcp6_option_parse_status(option); + status = dhcp6_option_parse_status(option, optlen); if (status) { log_dhcp6_client(client, "IA status %d", status); diff -Naurp systemd-239-orig/src/libsystemd-network/dhcp-network.c systemd-239/src/libsystemd-network/dhcp-network.c --- systemd-239-orig/src/libsystemd-network/dhcp-network.c 2018-06-22 06:11:49.000000000 -0500 +++ systemd-239/src/libsystemd-network/dhcp-network.c 2018-11-04 08:49:10.200692729 -0600 @@ -126,8 +126,6 @@ int dhcp_network_bind_raw_socket(int ifi const uint8_t *bcast_addr = NULL; uint8_t dhcp_hlen = 0; - assert_return(mac_addr_len > 0, -EINVAL); - if (arp_type == ARPHRD_ETHER) { assert_return(mac_addr_len == ETH_ALEN, -EINVAL); memcpy(ð_mac, mac_addr, ETH_ALEN); diff -Naurp systemd-239-orig/src/libsystemd-network/icmp6-util.c systemd-239/src/libsystemd-network/icmp6-util.c --- systemd-239-orig/src/libsystemd-network/icmp6-util.c 2018-06-22 06:11:49.000000000 -0500 +++ systemd-239/src/libsystemd-network/icmp6-util.c 2018-11-04 08:49:10.200692729 -0600 @@ -174,12 +174,8 @@ int icmp6_receive(int fd, void *buffer, iov.iov_len = size; len = recvmsg(fd, &msg, MSG_DONTWAIT); - if (len < 0) { - if (IN_SET(errno, EAGAIN, EINTR)) - return 0; - + if (len < 0) return -errno; - } if ((size_t) len != size) return -EINVAL; diff -Naurp systemd-239-orig/src/libsystemd-network/ndisc-router.c systemd-239/src/libsystemd-network/ndisc-router.c --- systemd-239-orig/src/libsystemd-network/ndisc-router.c 2018-06-22 06:11:49.000000000 -0500 +++ systemd-239/src/libsystemd-network/ndisc-router.c 2018-11-04 08:49:10.200692729 -0600 @@ -189,7 +189,7 @@ int ndisc_router_parse(sd_ndisc_router * if (has_mtu) { log_ndisc("MTU option specified twice, ignoring."); - continue; + break; } if (length != 8) { @@ -230,7 +230,7 @@ int ndisc_router_parse(sd_ndisc_router * if (has_flag_extension) { log_ndisc("Flags extension option specified twice, ignoring."); - continue; + break; } if (length < 1*8) { diff -Naurp systemd-239-orig/src/libsystemd-network/network-internal.c systemd-239/src/libsystemd-network/network-internal.c --- systemd-239-orig/src/libsystemd-network/network-internal.c 2018-06-22 06:11:49.000000000 -0500 +++ systemd-239/src/libsystemd-network/network-internal.c 2018-11-04 08:49:10.200692729 -0600 @@ -124,7 +124,7 @@ bool net_match_config(Set *match_mac, if (match_arch && condition_test(match_arch) <= 0) return false; - if (match_mac && dev_mac && !set_contains(match_mac, dev_mac)) + if (match_mac && (!dev_mac || !set_contains(match_mac, dev_mac))) return false; if (!net_condition_test_strv(match_paths, dev_path)) diff -Naurp systemd-239-orig/src/libsystemd-network/sd-dhcp6-client.c systemd-239/src/libsystemd-network/sd-dhcp6-client.c --- systemd-239-orig/src/libsystemd-network/sd-dhcp6-client.c 2018-06-22 06:11:49.000000000 -0500 +++ systemd-239/src/libsystemd-network/sd-dhcp6-client.c 2018-11-04 08:49:10.201692729 -0600 @@ -824,7 +824,7 @@ static int client_parse_message( break; case SD_DHCP6_OPTION_STATUS_CODE: - status = dhcp6_option_parse_status(option); + status = dhcp6_option_parse_status(option, optlen); if (status) { log_dhcp6_client(client, "%s Status %s", dhcp6_message_type_to_string(message->type), diff -Naurp systemd-239-orig/src/libsystemd-network/sd-dhcp-client.c systemd-239/src/libsystemd-network/sd-dhcp-client.c --- systemd-239-orig/src/libsystemd-network/sd-dhcp-client.c 2018-06-22 06:11:49.000000000 -0500 +++ systemd-239/src/libsystemd-network/sd-dhcp-client.c 2018-11-04 08:49:10.200692729 -0600 @@ -1644,6 +1644,8 @@ static int client_handle_message(sd_dhcp client->timeout_resend = sd_event_source_unref(client->timeout_resend); + client_notify(client, SD_DHCP_CLIENT_EVENT_EXPIRED); + r = client_initialize(client); if (r < 0) goto error; diff -Naurp systemd-239-orig/src/libsystemd-network/sd-dhcp-lease.c systemd-239/src/libsystemd-network/sd-dhcp-lease.c --- systemd-239-orig/src/libsystemd-network/sd-dhcp-lease.c 2018-06-22 06:11:49.000000000 -0500 +++ systemd-239/src/libsystemd-network/sd-dhcp-lease.c 2018-11-04 08:49:10.201692729 -0600 @@ -276,6 +276,8 @@ sd_dhcp_lease *sd_dhcp_lease_unref(sd_dh free(option); } + free(lease->root_path); + free(lease->timezone); free(lease->hostname); free(lease->domainname); free(lease->dns); diff -Naurp systemd-239-orig/src/locale/keymap-util.c systemd-239/src/locale/keymap-util.c --- systemd-239-orig/src/locale/keymap-util.c 2018-06-22 06:11:49.000000000 -0500 +++ systemd-239/src/locale/keymap-util.c 2018-11-04 08:49:10.203692727 -0600 @@ -72,6 +72,10 @@ void context_free(Context *c) { context_free_locale(c); context_free_x11(c); context_free_vconsole(c); + + sd_bus_message_unref(c->locale_cache); + sd_bus_message_unref(c->x11_cache); + sd_bus_message_unref(c->vc_cache); }; void locale_simplify(char *locale[_VARIABLE_LC_MAX]) { @@ -87,11 +91,13 @@ int locale_read_data(Context *c, sd_bus_ int r; /* Do not try to re-read the file within single bus operation. */ - if (m && m == c->locale_cache) - return 0; + if (m) { + if (m == c->locale_cache) + return 0; - /* To suppress multiple call of stat(), store the message to cache here. */ - c->locale_cache = m; + sd_bus_message_unref(c->locale_cache); + c->locale_cache = sd_bus_message_ref(m); + } r = stat("/etc/locale.conf", &st); if (r < 0 && errno != ENOENT) @@ -155,11 +161,13 @@ int vconsole_read_data(Context *c, sd_bu int r; /* Do not try to re-read the file within single bus operation. */ - if (m && m == c->vc_cache) - return 0; + if (m) { + if (m == c->vc_cache) + return 0; - /* To suppress multiple call of stat(), store the message to cache here. */ - c->vc_cache = m; + sd_bus_message_unref(c->vc_cache); + c->vc_cache = sd_bus_message_ref(m); + } if (stat("/etc/vconsole.conf", &st) < 0) { if (errno != ENOENT) @@ -197,11 +205,13 @@ int x11_read_data(Context *c, sd_bus_mes int r; /* Do not try to re-read the file within single bus operation. */ - if (m && m == c->x11_cache) - return 0; + if (m) { + if (m == c->x11_cache) + return 0; - /* To suppress multiple call of stat(), store the message to cache here. */ - c->x11_cache = m; + sd_bus_message_unref(c->x11_cache); + c->x11_cache = sd_bus_message_ref(m); + } if (stat("/etc/X11/xorg.conf.d/00-keyboard.conf", &st) < 0) { if (errno != ENOENT) diff -Naurp systemd-239-orig/src/login/70-uaccess.rules systemd-239/src/login/70-uaccess.rules --- systemd-239-orig/src/login/70-uaccess.rules 2018-06-22 06:11:49.000000000 -0500 +++ systemd-239/src/login/70-uaccess.rules 1969-12-31 18:00:00.000000000 -0600 @@ -1,80 +0,0 @@ -# SPDX-License-Identifier: LGPL-2.1+ -# -# 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. - -ACTION=="remove", GOTO="uaccess_end" -ENV{MAJOR}=="", GOTO="uaccess_end" - -# PTP/MTP protocol devices, cameras, portable media players -SUBSYSTEM=="usb", ENV{ID_USB_INTERFACES}=="*:060101:*", TAG+="uaccess" - -# Digicams with proprietary protocol -ENV{ID_GPHOTO2}=="?*", TAG+="uaccess" - -# SCSI and USB scanners -ENV{libsane_matched}=="yes", TAG+="uaccess" - -# HPLIP devices (necessary for ink level check and HP tool maintenance) -ENV{ID_HPLIP}=="1", TAG+="uaccess" - -# optical drives -SUBSYSTEM=="block", ENV{ID_CDROM}=="1", TAG+="uaccess" -SUBSYSTEM=="scsi_generic", SUBSYSTEMS=="scsi", ATTRS{type}=="4|5", TAG+="uaccess" - -# Sound devices -SUBSYSTEM=="sound", TAG+="uaccess", \ - OPTIONS+="static_node=snd/timer", OPTIONS+="static_node=snd/seq" - -# ffado is an userspace driver for firewire sound cards -SUBSYSTEM=="firewire", ENV{ID_FFADO}=="1", TAG+="uaccess" - -# Webcams, frame grabber, TV cards -SUBSYSTEM=="video4linux", TAG+="uaccess" -SUBSYSTEM=="dvb", TAG+="uaccess" - -# IIDC devices: industrial cameras and some webcams -SUBSYSTEM=="firewire", ATTR{units}=="*0x00a02d:0x00010*", TAG+="uaccess" -SUBSYSTEM=="firewire", ATTR{units}=="*0x00b09d:0x00010*", TAG+="uaccess" -# AV/C devices: camcorders, set-top boxes, TV sets, audio devices, and more -SUBSYSTEM=="firewire", ATTR{units}=="*0x00a02d:0x010001*", TAG+="uaccess" -SUBSYSTEM=="firewire", ATTR{units}=="*0x00a02d:0x014001*", TAG+="uaccess" - -# DRI video devices -SUBSYSTEM=="drm", KERNEL=="card*", TAG+="uaccess" - -# smart-card readers -ENV{ID_SMARTCARD_READER}=="?*", TAG+="uaccess" - -# (USB) authentication devices -ENV{ID_SECURITY_TOKEN}=="?*", TAG+="uaccess" - -# PDA devices -ENV{ID_PDA}=="?*", TAG+="uaccess" - -# Programmable remote control -ENV{ID_REMOTE_CONTROL}=="1", TAG+="uaccess" - -# joysticks -SUBSYSTEM=="input", ENV{ID_INPUT_JOYSTICK}=="?*", TAG+="uaccess" - -# color measurement devices -ENV{COLOR_MEASUREMENT_DEVICE}=="?*", TAG+="uaccess" - -# DDC/CI device, usually high-end monitors such as the DreamColor -ENV{DDC_DEVICE}=="?*", TAG+="uaccess" - -# media player raw devices (for user-mode drivers, Android SDK, etc.) -SUBSYSTEM=="usb", ENV{ID_MEDIA_PLAYER}=="?*", TAG+="uaccess" - -# software-defined radio communication devices -ENV{ID_SOFTWARE_RADIO}=="?*", TAG+="uaccess" - -# 3D printers, CNC machines, laser cutters, 3D scanners, etc. -ENV{ID_MAKER_TOOL}=="?*", TAG+="uaccess" - -LABEL="uaccess_end" diff -Naurp systemd-239-orig/src/login/70-uaccess.rules.m4 systemd-239/src/login/70-uaccess.rules.m4 --- systemd-239-orig/src/login/70-uaccess.rules.m4 1969-12-31 18:00:00.000000000 -0600 +++ systemd-239/src/login/70-uaccess.rules.m4 2018-11-04 08:49:10.203692727 -0600 @@ -0,0 +1,84 @@ +# SPDX-License-Identifier: LGPL-2.1+ +# +# 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. + +ACTION=="remove", GOTO="uaccess_end" +ENV{MAJOR}=="", GOTO="uaccess_end" + +# PTP/MTP protocol devices, cameras, portable media players +SUBSYSTEM=="usb", ENV{ID_USB_INTERFACES}=="*:060101:*", TAG+="uaccess" + +# Digicams with proprietary protocol +ENV{ID_GPHOTO2}=="?*", TAG+="uaccess" + +# SCSI and USB scanners +ENV{libsane_matched}=="yes", TAG+="uaccess" + +# HPLIP devices (necessary for ink level check and HP tool maintenance) +ENV{ID_HPLIP}=="1", TAG+="uaccess" + +# optical drives +SUBSYSTEM=="block", ENV{ID_CDROM}=="1", TAG+="uaccess" +SUBSYSTEM=="scsi_generic", SUBSYSTEMS=="scsi", ATTRS{type}=="4|5", TAG+="uaccess" + +# Sound devices +SUBSYSTEM=="sound", TAG+="uaccess", \ + OPTIONS+="static_node=snd/timer", OPTIONS+="static_node=snd/seq" + +# ffado is an userspace driver for firewire sound cards +SUBSYSTEM=="firewire", ENV{ID_FFADO}=="1", TAG+="uaccess" + +# Webcams, frame grabber, TV cards +SUBSYSTEM=="video4linux", TAG+="uaccess" +SUBSYSTEM=="dvb", TAG+="uaccess" + +# IIDC devices: industrial cameras and some webcams +SUBSYSTEM=="firewire", ATTR{units}=="*0x00a02d:0x00010*", TAG+="uaccess" +SUBSYSTEM=="firewire", ATTR{units}=="*0x00b09d:0x00010*", TAG+="uaccess" +# AV/C devices: camcorders, set-top boxes, TV sets, audio devices, and more +SUBSYSTEM=="firewire", ATTR{units}=="*0x00a02d:0x010001*", TAG+="uaccess" +SUBSYSTEM=="firewire", ATTR{units}=="*0x00a02d:0x014001*", TAG+="uaccess" + +# DRI video devices +SUBSYSTEM=="drm", KERNEL=="card*", TAG+="uaccess" +m4_ifdef(`DEV_KVM_UACCESS',`` +# KVM +SUBSYSTEM=="misc", KERNEL=="kvm", TAG+="uaccess"'' +)m4_dnl + +# smart-card readers +ENV{ID_SMARTCARD_READER}=="?*", TAG+="uaccess" + +# (USB) authentication devices +ENV{ID_SECURITY_TOKEN}=="?*", TAG+="uaccess" + +# PDA devices +ENV{ID_PDA}=="?*", TAG+="uaccess" + +# Programmable remote control +ENV{ID_REMOTE_CONTROL}=="1", TAG+="uaccess" + +# joysticks +SUBSYSTEM=="input", ENV{ID_INPUT_JOYSTICK}=="?*", TAG+="uaccess" + +# color measurement devices +ENV{COLOR_MEASUREMENT_DEVICE}=="?*", TAG+="uaccess" + +# DDC/CI device, usually high-end monitors such as the DreamColor +ENV{DDC_DEVICE}=="?*", TAG+="uaccess" + +# media player raw devices (for user-mode drivers, Android SDK, etc.) +SUBSYSTEM=="usb", ENV{ID_MEDIA_PLAYER}=="?*", TAG+="uaccess" + +# software-defined radio communication devices +ENV{ID_SOFTWARE_RADIO}=="?*", TAG+="uaccess" + +# 3D printers, CNC machines, laser cutters, 3D scanners, etc. +ENV{ID_MAKER_TOOL}=="?*", TAG+="uaccess" + +LABEL="uaccess_end" diff -Naurp systemd-239-orig/src/login/logind.c systemd-239/src/login/logind.c --- systemd-239-orig/src/login/logind.c 2018-06-22 06:11:49.000000000 -0500 +++ systemd-239/src/login/logind.c 2018-11-04 08:49:10.204692728 -0600 @@ -34,18 +34,21 @@ static int manager_new(Manager **ret) { assert(ret); - m = new0(Manager, 1); + m = new(Manager, 1); if (!m) return -ENOMEM; - m->console_active_fd = -1; - m->reserve_vt_fd = -1; + *m = (Manager) { + .console_active_fd = -1, + .reserve_vt_fd = -1, + }; m->idle_action_not_before_usec = now(CLOCK_MONOTONIC); m->devices = hashmap_new(&string_hash_ops); m->seats = hashmap_new(&string_hash_ops); m->sessions = hashmap_new(&string_hash_ops); + m->sessions_by_leader = hashmap_new(NULL); m->users = hashmap_new(NULL); m->inhibitors = hashmap_new(&string_hash_ops); m->buttons = hashmap_new(&string_hash_ops); @@ -53,7 +56,7 @@ static int manager_new(Manager **ret) { m->user_units = hashmap_new(&string_hash_ops); m->session_units = hashmap_new(&string_hash_ops); - if (!m->devices || !m->seats || !m->sessions || !m->users || !m->inhibitors || !m->buttons || !m->user_units || !m->session_units) + if (!m->devices || !m->seats || !m->sessions || !m->sessions_by_leader || !m->users || !m->inhibitors || !m->buttons || !m->user_units || !m->session_units) return -ENOMEM; m->udev = udev_new(); @@ -112,6 +115,7 @@ static Manager* manager_unref(Manager *m hashmap_free(m->devices); hashmap_free(m->seats); hashmap_free(m->sessions); + hashmap_free(m->sessions_by_leader); hashmap_free(m->users); hashmap_free(m->inhibitors); hashmap_free(m->buttons); @@ -132,6 +136,10 @@ static Manager* manager_unref(Manager *m sd_event_source_unref(m->udev_button_event_source); sd_event_source_unref(m->lid_switch_ignore_event_source); +#if ENABLE_UTMP + sd_event_source_unref(m->utmp_event_source); +#endif + safe_close(m->console_active_fd); udev_monitor_unref(m->udev_seat_monitor); @@ -815,28 +823,28 @@ static int manager_connect_console(Manag assert(m); assert(m->console_active_fd < 0); - /* On certain architectures (S390 and Xen, and containers), - /dev/tty0 does not exist, so don't fail if we can't open - it. */ + /* On certain systems (such as S390, Xen, and containers) /dev/tty0 does not exist (as there is no VC), so + * don't fail if we can't open it. */ + if (access("/dev/tty0", F_OK) < 0) return 0; m->console_active_fd = open("/sys/class/tty/tty0/active", O_RDONLY|O_NOCTTY|O_CLOEXEC); if (m->console_active_fd < 0) { - /* On some systems the device node /dev/tty0 may exist - * even though /sys/class/tty/tty0 does not. */ - if (errno == ENOENT) + /* On some systems /dev/tty0 may exist even though /sys/class/tty/tty0 does not. These are broken, but + * common. Let's complain but continue anyway. */ + if (errno == ENOENT) { + log_warning_errno(errno, "System has /dev/tty0 but not /sys/class/tty/tty0/active which is broken, ignoring: %m"); return 0; + } return log_error_errno(errno, "Failed to open /sys/class/tty/tty0/active: %m"); } r = sd_event_add_io(m->event, &m->console_active_event_source, m->console_active_fd, 0, manager_dispatch_console, m); - if (r < 0) { - log_error("Failed to watch foreground console"); - return r; - } + if (r < 0) + return log_error_errno(r, "Failed to watch foreground console: %m"); /* * SIGRTMIN is used as global VT-release signal, SIGRTMIN + 1 is used @@ -855,7 +863,7 @@ static int manager_connect_console(Manag r = sd_event_add_signal(m->event, NULL, SIGRTMIN, manager_vt_switch, m); if (r < 0) - return r; + return log_error_errno(r, "Failed to subscribe to signal: %m"); return 0; } @@ -979,13 +987,13 @@ static void manager_gc(Manager *m, bool /* First, if we are not closing yet, initiate stopping */ if (session_may_gc(session, drop_not_started) && session_get_state(session) != SESSION_CLOSING) - session_stop(session, false); + (void) session_stop(session, false); /* Normally, this should make the session referenced * again, if it doesn't then let's get rid of it * immediately */ if (session_may_gc(session, drop_not_started)) { - session_finalize(session); + (void) session_finalize(session); session_free(session); } } @@ -996,11 +1004,11 @@ static void manager_gc(Manager *m, bool /* First step: queue stop jobs */ if (user_may_gc(user, drop_not_started)) - user_stop(user, false); + (void) user_stop(user, false); /* Second step: finalize user */ if (user_may_gc(user, drop_not_started)) { - user_finalize(user); + (void) user_finalize(user); user_free(user); } } @@ -1095,6 +1103,9 @@ static int manager_startup(Manager *m) { if (r < 0) return log_error_errno(r, "Failed to register SIGHUP handler: %m"); + /* Connect to utmp */ + manager_connect_utmp(m); + /* Connect to console */ r = manager_connect_console(m); if (r < 0) @@ -1150,15 +1161,18 @@ static int manager_startup(Manager *m) { /* Reserve the special reserved VT */ manager_reserve_vt(m); + /* Read in utmp if it exists */ + manager_read_utmp(m); + /* And start everything */ HASHMAP_FOREACH(seat, m->seats, i) - seat_start(seat); + (void) seat_start(seat); HASHMAP_FOREACH(user, m->users, i) - user_start(user); + (void) user_start(user); HASHMAP_FOREACH(session, m->sessions, i) - session_start(session, NULL); + (void) session_start(session, NULL, NULL); HASHMAP_FOREACH(inhibitor, m->inhibitors, i) inhibitor_start(inhibitor); diff -Naurp systemd-239-orig/src/login/logind-core.c systemd-239/src/login/logind-core.c --- systemd-239-orig/src/login/logind-core.c 2018-06-22 06:11:49.000000000 -0500 +++ systemd-239/src/login/logind-core.c 2018-11-04 08:49:10.203692727 -0600 @@ -5,6 +5,9 @@ #include #include #include +#if ENABLE_UTMP +#include +#endif #include "alloc-util.h" #include "bus-error.h" @@ -14,6 +17,7 @@ #include "fd-util.h" #include "logind.h" #include "parse-util.h" +#include "path-util.h" #include "process-util.h" #include "strv.h" #include "terminal-util.h" @@ -27,6 +31,8 @@ void manager_reset_config(Manager *m) { m->reserve_vt = 6; m->remove_ipc = true; m->inhibit_delay_max = 5 * USEC_PER_SEC; + m->user_stop_delay = 10 * USEC_PER_SEC; + m->handle_power_key = HANDLE_POWEROFF; m->handle_suspend_key = HANDLE_SUSPEND; m->handle_hibernate_key = HANDLE_HIBERNATE; @@ -88,15 +94,16 @@ int manager_add_device(Manager *m, const int manager_add_seat(Manager *m, const char *id, Seat **_seat) { Seat *s; + int r; assert(m); assert(id); s = hashmap_get(m->seats, id); if (!s) { - s = seat_new(m, id); - if (!s) - return -ENOMEM; + r = seat_new(&s, m, id); + if (r < 0) + return r; } if (_seat) @@ -107,15 +114,16 @@ int manager_add_seat(Manager *m, const c int manager_add_session(Manager *m, const char *id, Session **_session) { Session *s; + int r; assert(m); assert(id); s = hashmap_get(m->sessions, id); if (!s) { - s = session_new(m, id); - if (!s) - return -ENOMEM; + r = session_new(&s, m, id); + if (r < 0) + return r; } if (_session) @@ -124,7 +132,14 @@ int manager_add_session(Manager *m, cons return 0; } -int manager_add_user(Manager *m, uid_t uid, gid_t gid, const char *name, User **_user) { +int manager_add_user( + Manager *m, + uid_t uid, + gid_t gid, + const char *name, + const char *home, + User **_user) { + User *u; int r; @@ -133,7 +148,7 @@ int manager_add_user(Manager *m, uid_t u u = hashmap_get(m->users, UID_TO_PTR(uid)); if (!u) { - r = user_new(&u, m, uid, gid, name); + r = user_new(&u, m, uid, gid, name, home); if (r < 0) return r; } @@ -144,7 +159,12 @@ int manager_add_user(Manager *m, uid_t u return 0; } -int manager_add_user_by_name(Manager *m, const char *name, User **_user) { +int manager_add_user_by_name( + Manager *m, + const char *name, + User **_user) { + + const char *home = NULL; uid_t uid; gid_t gid; int r; @@ -152,11 +172,11 @@ int manager_add_user_by_name(Manager *m, assert(m); assert(name); - r = get_user_creds(&name, &uid, &gid, NULL, NULL); + r = get_user_creds(&name, &uid, &gid, &home, NULL); if (r < 0) return r; - return manager_add_user(m, uid, gid, name, _user); + return manager_add_user(m, uid, gid, name, home, _user); } int manager_add_user_by_uid(Manager *m, uid_t uid, User **_user) { @@ -169,7 +189,7 @@ int manager_add_user_by_uid(Manager *m, if (!p) return errno > 0 ? -errno : -ENOENT; - return manager_add_user(m, uid, p->pw_gid, p->pw_name, _user); + return manager_add_user(m, uid, p->pw_gid, p->pw_name, p->pw_dir, _user); } int manager_add_inhibitor(Manager *m, const char* id, Inhibitor **_inhibitor) { @@ -319,13 +339,16 @@ int manager_get_session_by_pid(Manager * if (!pid_is_valid(pid)) return -EINVAL; - r = cg_pid_get_unit(pid, &unit); - if (r < 0) - goto not_found; + s = hashmap_get(m->sessions_by_leader, PID_TO_PTR(pid)); + if (!s) { + r = cg_pid_get_unit(pid, &unit); + if (r < 0) + goto not_found; - s = hashmap_get(m->session_units, unit); - if (!s) - goto not_found; + s = hashmap_get(m->session_units, unit); + if (!s) + goto not_found; + } if (ret) *ret = s; @@ -676,3 +699,142 @@ bool manager_all_buttons_ignored(Manager return true; } + +int manager_read_utmp(Manager *m) { +#if ENABLE_UTMP + int r; + + assert(m); + + if (utmpxname(_PATH_UTMPX) < 0) + return log_error_errno(errno, "Failed to set utmp path to " _PATH_UTMPX ": %m"); + + setutxent(); + + for (;;) { + _cleanup_free_ char *t = NULL; + struct utmpx *u; + const char *c; + Session *s; + + errno = 0; + u = getutxent(); + if (!u) { + if (errno != 0) + log_warning_errno(errno, "Failed to read " _PATH_UTMPX ", ignoring: %m"); + r = 0; + break; + } + + if (u->ut_type != USER_PROCESS) + continue; + + if (!pid_is_valid(u->ut_pid)) + continue; + + t = strndup(u->ut_line, sizeof(u->ut_line)); + if (!t) { + r = log_oom(); + break; + } + + c = path_startswith(t, "/dev/"); + if (c) { + r = free_and_strdup(&t, c); + if (r < 0) { + log_oom(); + break; + } + } + + if (isempty(t)) + continue; + + s = hashmap_get(m->sessions_by_leader, PID_TO_PTR(u->ut_pid)); + if (!s) + continue; + + if (s->tty_validity == TTY_FROM_UTMP && !streq_ptr(s->tty, t)) { + /* This may happen on multiplexed SSH connection (i.e. 'SSH connection sharing'). In + * this case PAM and utmp sessions don't match. In such a case let's invalidate the TTY + * information and never acquire it again. */ + + s->tty = mfree(s->tty); + s->tty_validity = TTY_UTMP_INCONSISTENT; + log_debug("Session '%s' has inconsistent TTY information, dropping TTY information.", s->id); + continue; + } + + /* Never override what we figured out once */ + if (s->tty || s->tty_validity >= 0) + continue; + + s->tty = TAKE_PTR(t); + s->tty_validity = TTY_FROM_UTMP; + log_debug("Acquired TTY information '%s' from utmp for session '%s'.", s->tty, s->id); + } + + endutxent(); + return r; +#else + return 0 +#endif +} + +#if ENABLE_UTMP +static int manager_dispatch_utmp(sd_event_source *s, const struct inotify_event *event, void *userdata) { + Manager *m = userdata; + + assert(m); + + /* If there's indication the file itself might have been removed or became otherwise unavailable, then let's + * reestablish the watch on whatever there's now. */ + if ((event->mask & (IN_ATTRIB|IN_DELETE_SELF|IN_MOVE_SELF|IN_Q_OVERFLOW|IN_UNMOUNT)) != 0) + manager_connect_utmp(m); + + (void) manager_read_utmp(m); + return 0; +} +#endif + +void manager_connect_utmp(Manager *m) { +#if ENABLE_UTMP + sd_event_source *s = NULL; + int r; + + assert(m); + + /* Watch utmp for changes via inotify. We do this to deal with tools such as ssh, which will register the PAM + * session early, and acquire a TTY only much later for the connection. Thus during PAM the TTY won't be known + * yet. ssh will register itself with utmp when it finally acquired the TTY. Hence, let's make use of this, and + * watch utmp for the TTY asynchronously. We use the PAM session's leader PID as key, to find the right entry. + * + * Yes, relying on utmp is pretty ugly, but it's good enough for informational purposes, as well as idle + * detection (which, for tty sessions, relies on the TTY used) */ + + r = sd_event_add_inotify(m->event, &s, _PATH_UTMPX, IN_MODIFY|IN_MOVE_SELF|IN_DELETE_SELF|IN_ATTRIB, manager_dispatch_utmp, m); + if (r < 0) + log_full_errno(r == -ENOENT ? LOG_DEBUG: LOG_WARNING, r, "Failed to create inotify watch on " _PATH_UTMPX ", ignoring: %m"); + else { + r = sd_event_source_set_priority(s, SD_EVENT_PRIORITY_IDLE); + if (r < 0) + log_warning_errno(r, "Failed to adjust utmp event source priority, ignoring: %m"); + + (void) sd_event_source_set_description(s, "utmp"); + } + + sd_event_source_unref(m->utmp_event_source); + m->utmp_event_source = s; +#endif +} + +void manager_reconnect_utmp(Manager *m) { +#if ENABLE_UTMP + assert(m); + + if (m->utmp_event_source) + return; + + manager_connect_utmp(m); +#endif +} diff -Naurp systemd-239-orig/src/login/logind-dbus.c systemd-239/src/login/logind-dbus.c --- systemd-239-orig/src/login/logind-dbus.c 2018-06-22 06:11:49.000000000 -0500 +++ systemd-239/src/login/logind-dbus.c 2018-11-04 08:49:10.204692728 -0600 @@ -772,6 +772,9 @@ static int method_create_session(sd_bus_ } while (hashmap_get(m->sessions, id)); } + /* If we are not watching utmp aleady, try again */ + manager_reconnect_utmp(m); + r = manager_add_user_by_uid(m, uid, &user); if (r < 0) goto fail; @@ -781,9 +784,8 @@ static int method_create_session(sd_bus_ goto fail; session_set_user(session, user); + session_set_leader(session, leader); - session->leader = leader; - session->audit_id = audit_id; session->type = t; session->class = c; session->remote = remote; @@ -795,6 +797,8 @@ static int method_create_session(sd_bus_ r = -ENOMEM; goto fail; } + + session->tty_validity = TTY_FROM_PAM; } if (!isempty(display)) { @@ -845,9 +849,9 @@ static int method_create_session(sd_bus_ r = sd_bus_message_enter_container(message, 'a', "(sv)"); if (r < 0) - return r; + goto fail; - r = session_start(session, message); + r = session_start(session, message, error); if (r < 0) goto fail; @@ -1770,8 +1774,9 @@ static int method_do_shutdown_or_sleep( if (sleep_verb) { r = can_sleep(sleep_verb); if (r == -ENOSPC) - return sd_bus_error_set(error, BUS_ERROR_SLEEP_VERB_NOT_SUPPORTED, - "Not enough swap space for hibernation"); + return sd_bus_error_set(error, BUS_ERROR_SLEEP_VERB_NOT_SUPPORTED, "Not enough swap space for hibernation"); + if (r == -EADV) + return sd_bus_error_set(error, BUS_ERROR_SLEEP_VERB_NOT_SUPPORTED, "Resume not configured, can't hibernate"); if (r == 0) return sd_bus_error_setf(error, BUS_ERROR_SLEEP_VERB_NOT_SUPPORTED, "Sleep verb \"%s\" not supported", sleep_verb); @@ -2155,6 +2160,7 @@ static int method_cancel_scheduled_shutd if (cancelled && m->enable_wall_messages) { _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL; + _cleanup_free_ char *username = NULL; const char *tty = NULL; uid_t uid = 0; int r; @@ -2165,8 +2171,9 @@ static int method_cancel_scheduled_shutd (void) sd_bus_creds_get_tty(creds, &tty); } + username = uid_to_name(uid); utmp_wall("The system shutdown has been cancelled", - uid_to_name(uid), tty, logind_wall_tty_filter, m); + username, tty, logind_wall_tty_filter, m); } return sd_bus_reply_method_return(message, "b", cancelled); @@ -2199,7 +2206,7 @@ static int method_can_shutdown_or_sleep( if (sleep_verb) { r = can_sleep(sleep_verb); - if (IN_SET(r, 0, -ENOSPC)) + if (IN_SET(r, 0, -ENOSPC, -EADV)) return sd_bus_reply_method_return(message, "s", "na"); if (r < 0) return r; @@ -2644,6 +2651,7 @@ const sd_bus_vtable manager_vtable[] = { SD_BUS_PROPERTY("BlockInhibited", "s", property_get_inhibited, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), SD_BUS_PROPERTY("DelayInhibited", "s", property_get_inhibited, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), SD_BUS_PROPERTY("InhibitDelayMaxUSec", "t", NULL, offsetof(Manager, inhibit_delay_max), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("UserStopDelayUSec", "t", NULL, offsetof(Manager, user_stop_delay), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("HandlePowerKey", "s", property_get_handle_action, offsetof(Manager, handle_power_key), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("HandleSuspendKey", "s", property_get_handle_action, offsetof(Manager, handle_suspend_key), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("HandleHibernateKey", "s", property_get_handle_action, offsetof(Manager, handle_hibernate_key), SD_BUS_VTABLE_PROPERTY_CONST), @@ -2724,24 +2732,20 @@ const sd_bus_vtable manager_vtable[] = { }; static int session_jobs_reply(Session *s, const char *unit, const char *result) { - int r = 0; - assert(s); assert(unit); if (!s->started) - return r; + return 0; - if (streq(result, "done")) - r = session_send_create_reply(s, NULL); - else { + if (result && !streq(result, "done")) { _cleanup_(sd_bus_error_free) sd_bus_error e = SD_BUS_ERROR_NULL; - sd_bus_error_setf(&e, BUS_ERROR_JOB_FAILED, "Start job for unit %s failed with '%s'", unit, result); - r = session_send_create_reply(s, &e); + sd_bus_error_setf(&e, BUS_ERROR_JOB_FAILED, "Start job for unit '%s' failed with '%s'", unit, result); + return session_send_create_reply(s, &e); } - return r; + return session_send_create_reply(s, NULL); } int match_job_removed(sd_bus_message *message, void *userdata, sd_bus_error *error) { @@ -2774,30 +2778,29 @@ int match_job_removed(sd_bus_message *me } session = hashmap_get(m->session_units, unit); - if (session && streq_ptr(path, session->scope_job)) { - session->scope_job = mfree(session->scope_job); - session_jobs_reply(session, unit, result); + if (session) { + if (streq_ptr(path, session->scope_job)) { + session->scope_job = mfree(session->scope_job); + (void) session_jobs_reply(session, unit, result); + + session_save(session); + user_save(session->user); + } - session_save(session); - user_save(session->user); session_add_to_gc_queue(session); } user = hashmap_get(m->user_units, unit); - if (user && - (streq_ptr(path, user->service_job) || - streq_ptr(path, user->slice_job))) { - - if (streq_ptr(path, user->service_job)) + if (user) { + if (streq_ptr(path, user->service_job)) { user->service_job = mfree(user->service_job); - if (streq_ptr(path, user->slice_job)) - user->slice_job = mfree(user->slice_job); + LIST_FOREACH(sessions_by_user, session, user->sessions) + (void) session_jobs_reply(session, unit, NULL /* don't propagate user service failures to the client */); - LIST_FOREACH(sessions_by_user, session, user->sessions) - session_jobs_reply(session, unit, result); + user_save(user); + } - user_save(user); user_add_to_gc_queue(user); } @@ -2929,13 +2932,15 @@ int manager_start_scope( pid_t pid, const char *slice, const char *description, - const char *after, - const char *after2, + char **wants, + char **after, + const char *requires_mounts_for, sd_bus_message *more_properties, sd_bus_error *error, char **job) { _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL, *reply = NULL; + char **i; int r; assert(manager); @@ -2973,14 +2978,20 @@ int manager_start_scope( return r; } - if (!isempty(after)) { - r = sd_bus_message_append(m, "(sv)", "After", "as", 1, after); + STRV_FOREACH(i, wants) { + r = sd_bus_message_append(m, "(sv)", "Wants", "as", 1, *i); if (r < 0) return r; } - if (!isempty(after2)) { - r = sd_bus_message_append(m, "(sv)", "After", "as", 1, after2); + STRV_FOREACH(i, after) { + r = sd_bus_message_append(m, "(sv)", "After", "as", 1, *i); + if (r < 0) + return r; + } + + if (!empty_or_root(requires_mounts_for)) { + r = sd_bus_message_append(m, "(sv)", "RequiresMountsFor", "as", 1, requires_mounts_for); if (r < 0) return r; } @@ -3077,7 +3088,8 @@ int manager_stop_unit(Manager *manager, return strdup_job(reply, job); } -int manager_abandon_scope(Manager *manager, const char *scope, sd_bus_error *error) { +int manager_abandon_scope(Manager *manager, const char *scope, sd_bus_error *ret_error) { + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; _cleanup_free_ char *path = NULL; int r; @@ -3094,17 +3106,16 @@ int manager_abandon_scope(Manager *manag path, "org.freedesktop.systemd1.Scope", "Abandon", - error, + &error, NULL, NULL); if (r < 0) { - if (sd_bus_error_has_name(error, BUS_ERROR_NO_SUCH_UNIT) || - sd_bus_error_has_name(error, BUS_ERROR_LOAD_FAILED) || - sd_bus_error_has_name(error, BUS_ERROR_SCOPE_NOT_RUNNING)) { - sd_bus_error_free(error); + if (sd_bus_error_has_name(&error, BUS_ERROR_NO_SUCH_UNIT) || + sd_bus_error_has_name(&error, BUS_ERROR_LOAD_FAILED) || + sd_bus_error_has_name(&error, BUS_ERROR_SCOPE_NOT_RUNNING)) return 0; - } + sd_bus_error_move(ret_error, &error); return r; } @@ -3126,7 +3137,7 @@ int manager_kill_unit(Manager *manager, "ssi", unit, who == KILL_LEADER ? "main" : "all", signo); } -int manager_unit_is_active(Manager *manager, const char *unit) { +int manager_unit_is_active(Manager *manager, const char *unit, sd_bus_error *ret_error) { _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; _cleanup_free_ char *path = NULL; @@ -3162,17 +3173,18 @@ int manager_unit_is_active(Manager *mana sd_bus_error_has_name(&error, BUS_ERROR_LOAD_FAILED)) return false; + sd_bus_error_move(ret_error, &error); return r; } r = sd_bus_message_read(reply, "s", &state); if (r < 0) - return -EINVAL; + return r; - return !streq(state, "inactive") && !streq(state, "failed"); + return !STR_IN_SET(state, "inactive", "failed"); } -int manager_job_is_active(Manager *manager, const char *path) { +int manager_job_is_active(Manager *manager, const char *path, sd_bus_error *ret_error) { _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; int r; @@ -3197,6 +3209,7 @@ int manager_job_is_active(Manager *manag if (sd_bus_error_has_name(&error, SD_BUS_ERROR_UNKNOWN_OBJECT)) return false; + sd_bus_error_move(ret_error, &error); return r; } diff -Naurp systemd-239-orig/src/login/logind-device.c systemd-239/src/login/logind-device.c --- systemd-239-orig/src/login/logind-device.c 2018-06-22 06:11:49.000000000 -0500 +++ systemd-239/src/login/logind-device.c 2018-11-04 08:49:10.204692728 -0600 @@ -99,6 +99,8 @@ void device_attach(Device *d, Seat *s) { } } - if (!had_master && d->master) + if (!had_master && d->master && s->started) { + seat_save(s); seat_send_changed(s, "CanGraphical", NULL); + } } diff -Naurp systemd-239-orig/src/login/logind-gperf.gperf systemd-239/src/login/logind-gperf.gperf --- systemd-239-orig/src/login/logind-gperf.gperf 2018-06-22 06:11:49.000000000 -0500 +++ systemd-239/src/login/logind-gperf.gperf 2018-11-04 08:49:10.204692728 -0600 @@ -23,6 +23,7 @@ Login.KillUserProcesses, conf Login.KillOnlyUsers, config_parse_strv, 0, offsetof(Manager, kill_only_users) Login.KillExcludeUsers, config_parse_strv, 0, offsetof(Manager, kill_exclude_users) Login.InhibitDelayMaxSec, config_parse_sec, 0, offsetof(Manager, inhibit_delay_max) +Login.UserStopDelaySec, config_parse_sec, 0, offsetof(Manager, user_stop_delay) Login.HandlePowerKey, config_parse_handle_action, 0, offsetof(Manager, handle_power_key) Login.HandleSuspendKey, config_parse_handle_action, 0, offsetof(Manager, handle_suspend_key) Login.HandleHibernateKey, config_parse_handle_action, 0, offsetof(Manager, handle_hibernate_key) diff -Naurp systemd-239-orig/src/login/logind.h systemd-239/src/login/logind.h --- systemd-239-orig/src/login/logind.h 2018-06-22 06:11:49.000000000 -0500 +++ systemd-239/src/login/logind.h 2018-11-04 08:49:10.204692728 -0600 @@ -26,6 +26,7 @@ struct Manager { Hashmap *devices; Hashmap *seats; Hashmap *sessions; + Hashmap *sessions_by_leader; Hashmap *users; Hashmap *inhibitors; Hashmap *buttons; @@ -43,6 +44,10 @@ struct Manager { sd_event_source *udev_vcsa_event_source; sd_event_source *udev_button_event_source; +#if ENABLE_UTMP + sd_event_source *utmp_event_source; +#endif + int console_active_fd; unsigned n_autovts; @@ -62,6 +67,7 @@ struct Manager { Hashmap *user_units; usec_t inhibit_delay_max; + usec_t user_stop_delay; /* If an action is currently being executed or is delayed, * this is != 0 and encodes what is being done */ @@ -128,7 +134,7 @@ int manager_add_device(Manager *m, const int manager_add_button(Manager *m, const char *name, Button **_button); int manager_add_seat(Manager *m, const char *id, Seat **_seat); int manager_add_session(Manager *m, const char *id, Session **_session); -int manager_add_user(Manager *m, uid_t uid, gid_t gid, const char *name, User **_user); +int manager_add_user(Manager *m, uid_t uid, gid_t gid, const char *name, const char *home, User **_user); int manager_add_user_by_name(Manager *m, const char *name, User **_user); int manager_add_user_by_uid(Manager *m, uid_t uid, User **_user); int manager_add_inhibitor(Manager *m, const char* id, Inhibitor **_inhibitor); @@ -149,6 +155,10 @@ bool manager_is_docked_or_external_displ bool manager_is_on_external_power(void); bool manager_all_buttons_ignored(Manager *m); +int manager_read_utmp(Manager *m); +void manager_connect_utmp(Manager *m); +void manager_reconnect_utmp(Manager *m); + extern const sd_bus_vtable manager_vtable[]; int match_job_removed(sd_bus_message *message, void *userdata, sd_bus_error *error); @@ -161,13 +171,13 @@ int bus_manager_shutdown_or_sleep_now_or int manager_send_changed(Manager *manager, const char *property, ...) _sentinel_; -int manager_start_scope(Manager *manager, const char *scope, pid_t pid, const char *slice, const char *description, const char *after, const char *after2, sd_bus_message *more_properties, sd_bus_error *error, char **job); +int manager_start_scope(Manager *manager, const char *scope, pid_t pid, const char *slice, const char *description, char **wants, char **after, const char *requires_mounts_for, sd_bus_message *more_properties, sd_bus_error *error, char **job); int manager_start_unit(Manager *manager, const char *unit, sd_bus_error *error, char **job); int manager_stop_unit(Manager *manager, const char *unit, sd_bus_error *error, char **job); int manager_abandon_scope(Manager *manager, const char *scope, sd_bus_error *error); int manager_kill_unit(Manager *manager, const char *unit, KillWho who, int signo, sd_bus_error *error); -int manager_unit_is_active(Manager *manager, const char *unit); -int manager_job_is_active(Manager *manager, const char *path); +int manager_unit_is_active(Manager *manager, const char *unit, sd_bus_error *error); +int manager_job_is_active(Manager *manager, const char *path, sd_bus_error *error); /* gperf lookup function */ const struct ConfigPerfItem* logind_gperf_lookup(const char *key, GPERF_LEN_TYPE length); diff -Naurp systemd-239-orig/src/login/logind-seat.c systemd-239/src/login/logind-seat.c --- systemd-239-orig/src/login/logind-seat.c 2018-06-22 06:11:49.000000000 -0500 +++ systemd-239/src/login/logind-seat.c 2018-11-04 08:49:10.204692728 -0600 @@ -21,33 +21,42 @@ #include "terminal-util.h" #include "util.h" -Seat *seat_new(Manager *m, const char *id) { - Seat *s; +int seat_new(Seat** ret, Manager *m, const char *id) { + _cleanup_(seat_freep) Seat *s = NULL; + int r; + assert(ret); assert(m); assert(id); - s = new0(Seat, 1); + if (!seat_name_is_valid(id)) + return -EINVAL; + + s = new(Seat, 1); if (!s) - return NULL; + return -ENOMEM; + + *s = (Seat) { + .manager = m, + }; s->state_file = strappend("/run/systemd/seats/", id); if (!s->state_file) - return mfree(s); + return -ENOMEM; s->id = basename(s->state_file); - s->manager = m; - if (hashmap_put(m->seats, s->id, s) < 0) { - free(s->state_file); - return mfree(s); - } + r = hashmap_put(m->seats, s->id, s); + if (r < 0) + return r; - return s; + *ret = TAKE_PTR(s); + return 0; } -void seat_free(Seat *s) { - assert(s); +Seat* seat_free(Seat *s) { + if (!s) + return NULL; if (s->in_gc_queue) LIST_REMOVE(gc_queue, s->manager->seat_gc_queue, s); @@ -64,7 +73,8 @@ void seat_free(Seat *s) { free(s->positions); free(s->state_file); - free(s); + + return mfree(s); } int seat_save(Seat *s) { @@ -165,7 +175,7 @@ static int vt_allocate(unsigned int vtnr xsprintf(p, "/dev/tty%u", vtnr); fd = open_terminal(p, O_RDWR|O_NOCTTY|O_CLOEXEC); if (fd < 0) - return -errno; + return fd; return 0; } @@ -189,10 +199,8 @@ int seat_preallocate_vts(Seat *s) { int q; q = vt_allocate(i); - if (q < 0) { - log_error_errno(q, "Failed to preallocate VT %u: %m", i); - r = q; - } + if (q < 0) + r = log_error_errno(q, "Failed to preallocate VT %u: %m", i); } return r; @@ -210,9 +218,9 @@ int seat_apply_acls(Seat *s, Session *ol !!s->active, s->active ? s->active->user->uid : 0); if (r < 0) - log_error_errno(r, "Failed to apply ACLs: %m"); + return log_error_errno(r, "Failed to apply ACLs: %m"); - return r; + return 0; } int seat_set_active(Seat *s, Session *session) { @@ -232,7 +240,7 @@ int seat_set_active(Seat *s, Session *se session_send_changed(old_active, "Active", NULL); } - seat_apply_acls(s, old_active); + (void) seat_apply_acls(s, old_active); if (session && session->started) { session_send_changed(session, "Active", NULL); @@ -421,7 +429,7 @@ int seat_start(Seat *s) { } int seat_stop(Seat *s, bool force) { - int r = 0; + int r; assert(s); @@ -431,9 +439,9 @@ int seat_stop(Seat *s, bool force) { "SEAT_ID=%s", s->id, LOG_MESSAGE("Removed seat %s.", s->id)); - seat_stop_sessions(s, force); + r = seat_stop_sessions(s, force); - unlink(s->state_file); + (void) unlink(s->state_file); seat_add_to_gc_queue(s); if (s->started) diff -Naurp systemd-239-orig/src/login/logind-seat.h systemd-239/src/login/logind-seat.h --- systemd-239-orig/src/login/logind-seat.h 2018-06-22 06:11:49.000000000 -0500 +++ systemd-239/src/login/logind-seat.h 2018-11-04 08:49:10.204692728 -0600 @@ -27,8 +27,10 @@ struct Seat { LIST_FIELDS(Seat, gc_queue); }; -Seat *seat_new(Manager *m, const char *id); -void seat_free(Seat *s); +int seat_new(Seat **ret, Manager *m, const char *id); +Seat* seat_free(Seat *s); + +DEFINE_TRIVIAL_CLEANUP_FUNC(Seat *, seat_free); int seat_save(Seat *s); int seat_load(Seat *s); diff -Naurp systemd-239-orig/src/login/logind-session.c systemd-239/src/login/logind-session.c --- systemd-239-orig/src/login/logind-session.c 2018-06-22 06:11:49.000000000 -0500 +++ systemd-239/src/login/logind-session.c 2018-11-04 08:49:10.204692728 -0600 @@ -5,6 +5,7 @@ #include #include #include +#include #include #include #include @@ -24,57 +25,63 @@ #include "mkdir.h" #include "parse-util.h" #include "path-util.h" +#include "process-util.h" #include "string-table.h" +#include "strv.h" #include "terminal-util.h" #include "user-util.h" #include "util.h" -#include "process-util.h" #define RELEASE_USEC (20*USEC_PER_SEC) static void session_remove_fifo(Session *s); -Session* session_new(Manager *m, const char *id) { - Session *s; +int session_new(Session **ret, Manager *m, const char *id) { + _cleanup_(session_freep) Session *s = NULL; + int r; + assert(ret); assert(m); assert(id); - assert(session_id_valid(id)); - s = new0(Session, 1); + if (!session_id_valid(id)) + return -EINVAL; + + s = new(Session, 1); if (!s) - return NULL; + return -ENOMEM; + + *s = (Session) { + .manager = m, + .fifo_fd = -1, + .vtfd = -1, + .audit_id = AUDIT_SESSION_INVALID, + .tty_validity = _TTY_VALIDITY_INVALID, + }; s->state_file = strappend("/run/systemd/sessions/", id); if (!s->state_file) - return mfree(s); - - s->devices = hashmap_new(&devt_hash_ops); - if (!s->devices) { - free(s->state_file); - return mfree(s); - } + return -ENOMEM; s->id = basename(s->state_file); - if (hashmap_put(m->sessions, s->id, s) < 0) { - hashmap_free(s->devices); - free(s->state_file); - return mfree(s); - } + s->devices = hashmap_new(&devt_hash_ops); + if (!s->devices) + return -ENOMEM; - s->manager = m; - s->fifo_fd = -1; - s->vtfd = -1; - s->audit_id = AUDIT_SESSION_INVALID; + r = hashmap_put(m->sessions, s->id, s); + if (r < 0) + return r; - return s; + *ret = TAKE_PTR(s); + return 0; } -void session_free(Session *s) { +Session* session_free(Session *s) { SessionDevice *sd; - assert(s); + if (!s) + return NULL; if (s->in_gc_queue) LIST_REMOVE(gc_queue, s->manager->session_gc_queue, s); @@ -95,6 +102,8 @@ void session_free(Session *s) { if (s->user->display == s) s->user->display = NULL; + + user_update_last_session_timer(s->user); } if (s->seat) { @@ -112,6 +121,9 @@ void session_free(Session *s) { free(s->scope); } + if (pid_is_valid(s->leader)) + (void) hashmap_remove_value(s->manager->sessions_by_leader, PID_TO_PTR(s->leader), s); + free(s->scope_job); sd_bus_message_unref(s->create_message); @@ -126,7 +138,8 @@ void session_free(Session *s) { hashmap_remove(s->manager->sessions, s->id); free(s->state_file); - free(s); + + return mfree(s); } void session_set_user(Session *s, User *u) { @@ -135,6 +148,32 @@ void session_set_user(Session *s, User * s->user = u; LIST_PREPEND(sessions_by_user, u->sessions, s); + + user_update_last_session_timer(u); +} + +int session_set_leader(Session *s, pid_t pid) { + int r; + + assert(s); + + if (!pid_is_valid(pid)) + return -EINVAL; + + if (s->leader == pid) + return 0; + + r = hashmap_put(s->manager->sessions_by_leader, PID_TO_PTR(pid), s); + if (r < 0) + return r; + + if (pid_is_valid(s->leader)) + (void) hashmap_remove_value(s->manager->sessions_by_leader, PID_TO_PTR(s->leader), s); + + s->leader = pid; + (void) audit_session_from_pid(pid, &s->audit_id); + + return 1; } static void session_save_devices(Session *s, FILE *f) { @@ -170,20 +209,21 @@ int session_save(Session *s) { if (r < 0) goto fail; - assert(s->user); - - fchmod(fileno(f), 0644); + (void) __fsetlocking(f, FSETLOCKING_BYCALLER); + (void) fchmod(fileno(f), 0644); fprintf(f, "# This is private data. Do not parse.\n" "UID="UID_FMT"\n" "USER=%s\n" "ACTIVE=%i\n" + "IS_DISPLAY=%i\n" "STATE=%s\n" "REMOTE=%i\n", s->user->uid, s->user->name, session_is_active(s), + s->user->display == s, session_state_to_string(session_get_state(s)), s->remote); @@ -207,6 +247,9 @@ int session_save(Session *s) { if (s->tty) fprintf(f, "TTY=%s\n", s->tty); + if (s->tty_validity >= 0) + fprintf(f, "TTY_VALIDITY=%s\n", tty_validity_to_string(s->tty_validity)); + if (s->display) fprintf(f, "DISPLAY=%s\n", s->display); @@ -343,6 +386,7 @@ static int session_load_devices(Session int session_load(Session *s) { _cleanup_free_ char *remote = NULL, *seat = NULL, + *tty_validity = NULL, *vtnr = NULL, *state = NULL, *position = NULL, @@ -354,7 +398,8 @@ int session_load(Session *s) { *monotonic = NULL, *controller = NULL, *active = NULL, - *devices = NULL; + *devices = NULL, + *is_display = NULL; int k, r; @@ -367,6 +412,7 @@ int session_load(Session *s) { "FIFO", &s->fifo_path, "SEAT", &seat, "TTY", &s->tty, + "TTY_VALIDITY", &tty_validity, "DISPLAY", &s->display, "REMOTE_HOST", &s->remote_host, "REMOTE_USER", &s->remote_user, @@ -384,6 +430,7 @@ int session_load(Session *s) { "CONTROLLER", &controller, "ACTIVE", &active, "DEVICES", &devices, + "IS_DISPLAY", &is_display, NULL); if (r < 0) @@ -442,9 +489,27 @@ int session_load(Session *s) { seat_claim_position(s->seat, s, npos); } + if (tty_validity) { + TTYValidity v; + + v = tty_validity_from_string(tty_validity); + if (v < 0) + log_debug("Failed to parse TTY validity: %s", tty_validity); + else + s->tty_validity = v; + } + if (leader) { - if (parse_pid(leader, &s->leader) >= 0) - (void) audit_session_from_pid(s->leader, &s->audit_id); + pid_t pid; + + r = parse_pid(leader, &pid); + if (r < 0) + log_debug_errno(r, "Failed to parse leader PID of session: %s", leader); + else { + r = session_set_leader(s, pid); + if (r < 0) + log_warning_errno(r, "Failed to set session leader PID, ignoring: %m"); + } } if (type) { @@ -491,6 +556,18 @@ int session_load(Session *s) { s->was_active = k; } + if (is_display) { + /* Note that when enumerating users are loaded before sessions, hence the display session to use is + * something we have to store along with the session and not the user, as in that case we couldn't + * apply it at the time we load the user. */ + + k = parse_boolean(is_display); + if (k < 0) + log_warning_errno(k, "Failed to parse IS_DISPLAY session property: %m"); + else if (k > 0) + s->user->display = s; + } + if (controller) { if (bus_name_has_owner(s->manager->bus, controller, NULL) > 0) { session_set_controller(s, controller, false, false); @@ -516,7 +593,7 @@ int session_activate(Session *s) { /* on seats with VTs, we let VTs manage session-switching */ if (seat_has_vts(s->seat)) { - if (!s->vtnr) + if (s->vtnr == 0) return -EOPNOTSUPP; return chvt(s->vtnr); @@ -539,17 +616,18 @@ int session_activate(Session *s) { return 0; } -static int session_start_scope(Session *s, sd_bus_message *properties) { +static int session_start_scope(Session *s, sd_bus_message *properties, sd_bus_error *error) { int r; assert(s); assert(s->user); if (!s->scope) { - _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; - char *scope, *job = NULL; + _cleanup_free_ char *scope = NULL; const char *description; + s->scope_job = mfree(s->scope_job); + scope = strjoin("session-", s->id, ".scope"); if (!scope) return log_oom(); @@ -562,21 +640,16 @@ static int session_start_scope(Session * s->leader, s->user->slice, description, - "systemd-logind.service", - "systemd-user-sessions.service", + STRV_MAKE(s->user->runtime_dir_service, s->user->service), /* These two have StopWhenUnneeded= set, hence add a dep towards them */ + STRV_MAKE("systemd-logind.service", "systemd-user-sessions.service", s->user->runtime_dir_service, s->user->service), /* And order us after some more */ + s->user->home, properties, - &error, - &job); - if (r < 0) { - log_error_errno(r, "Failed to start session scope %s: %s", scope, bus_error_message(&error, r)); - free(scope); - return r; - } else { - s->scope = scope; + error, + &s->scope_job); + if (r < 0) + return log_error_errno(r, "Failed to start session scope %s: %s", scope, bus_error_message(error, r)); - free(s->scope_job); - s->scope_job = job; - } + s->scope = TAKE_PTR(scope); } if (s->scope) @@ -585,7 +658,7 @@ static int session_start_scope(Session * return 0; } -int session_start(Session *s, sd_bus_message *properties) { +int session_start(Session *s, sd_bus_message *properties, sd_bus_error *error) { int r; assert(s); @@ -593,6 +666,9 @@ int session_start(Session *s, sd_bus_mes if (!s->user) return -ESTALE; + if (s->stopping) + return -EINVAL; + if (s->started) return 0; @@ -600,8 +676,7 @@ int session_start(Session *s, sd_bus_mes if (r < 0) return r; - /* Create cgroup */ - r = session_start_scope(s, properties); + r = session_start_scope(s, properties, error); if (r < 0) return r; @@ -652,21 +727,24 @@ static int session_stop_scope(Session *s * that is left in the scope is "left-over". Informing systemd about this has the benefit that it will log * when killing any processes left after this point. */ r = manager_abandon_scope(s->manager, s->scope, &error); - if (r < 0) + if (r < 0) { log_warning_errno(r, "Failed to abandon session scope, ignoring: %s", bus_error_message(&error, r)); + sd_bus_error_free(&error); + } + + s->scope_job = mfree(s->scope_job); /* Optionally, let's kill everything that's left now. */ if (force || manager_shall_kill(s->manager, s->user->name)) { - char *job = NULL; - r = manager_stop_unit(s->manager, s->scope, &error, &job); - if (r < 0) - return log_error_errno(r, "Failed to stop session scope: %s", bus_error_message(&error, r)); + r = manager_stop_unit(s->manager, s->scope, &error, &s->scope_job); + if (r < 0) { + if (force) + return log_error_errno(r, "Failed to stop session scope: %s", bus_error_message(&error, r)); - free(s->scope_job); - s->scope_job = job; + log_warning_errno(r, "Failed to stop session scope, ignoring: %s", bus_error_message(&error, r)); + } } else { - s->scope_job = mfree(s->scope_job); /* With no killing, this session is allowed to persist in "closing" state indefinitely. * Therefore session stop and session removal may be two distinct events. @@ -686,8 +764,17 @@ int session_stop(Session *s, bool force) assert(s); + /* This is called whenever we begin with tearing down a session record. It's called in four cases: explicit API + * request via the bus (either directly for the session object or for the seat or user object this session + * belongs to; 'force' is true), or due to automatic GC (i.e. scope vanished; 'force' is false), or because the + * session FIFO saw an EOF ('force' is false), or because the release timer hit ('force' is false). */ + if (!s->user) return -ESTALE; + if (!s->started) + return 0; + if (s->stopping) + return 0; s->timer_event_source = sd_event_source_unref(s->timer_event_source); @@ -779,7 +866,7 @@ int session_release(Session *s) { return sd_event_add_time(s->manager->event, &s->timer_event_source, CLOCK_MONOTONIC, - now(CLOCK_MONOTONIC) + RELEASE_USEC, 0, + usec_add(now(CLOCK_MONOTONIC), RELEASE_USEC), 0, release_timeout_callback, s); } @@ -858,7 +945,7 @@ int session_get_idle_hint(Session *s, du /* For sessions with a leader but no explicitly configured * tty, let's check the controlling tty of the leader */ - if (s->leader > 0) { + if (pid_is_valid(s->leader)) { r = get_process_ctty_atime(s->leader, &atime); if (r >= 0) goto found_atime; @@ -942,7 +1029,8 @@ int session_create_fifo(Session *s) { if (r < 0) return r; - if (asprintf(&s->fifo_path, "/run/systemd/sessions/%s.ref", s->id) < 0) + s->fifo_path = strjoin("/run/systemd/sessions/", s->id, ".ref"); + if (!s->fifo_path) return -ENOMEM; if (mkfifo(s->fifo_path, 0600) < 0 && errno != EEXIST) @@ -954,7 +1042,6 @@ int session_create_fifo(Session *s) { s->fifo_fd = open(s->fifo_path, O_RDONLY|O_CLOEXEC|O_NONBLOCK); if (s->fifo_fd < 0) return -errno; - } if (!s->fifo_event_source) { @@ -984,12 +1071,14 @@ static void session_remove_fifo(Session s->fifo_fd = safe_close(s->fifo_fd); if (s->fifo_path) { - unlink(s->fifo_path); + (void) unlink(s->fifo_path); s->fifo_path = mfree(s->fifo_path); } } bool session_may_gc(Session *s, bool drop_not_started) { + int r; + assert(s); if (drop_not_started && !s->started) @@ -1003,11 +1092,25 @@ bool session_may_gc(Session *s, bool dro return false; } - if (s->scope_job && manager_job_is_active(s->manager, s->scope_job)) - return false; + if (s->scope_job) { + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; - if (s->scope && manager_unit_is_active(s->manager, s->scope)) - return false; + r = manager_job_is_active(s->manager, s->scope_job, &error); + if (r < 0) + log_debug_errno(r, "Failed to determine whether job '%s' is pending, ignoring: %s", s->scope_job, bus_error_message(&error, r)); + if (r != 0) + return false; + } + + if (s->scope) { + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + + r = manager_unit_is_active(s->manager, s->scope, &error); + if (r < 0) + log_debug_errno(r, "Failed to determine whether unit '%s' is active, ignoring: %s", s->scope, bus_error_message(&error, r)); + if (r != 0) + return false; + } return true; } @@ -1312,3 +1415,11 @@ static const char* const kill_who_table[ }; DEFINE_STRING_TABLE_LOOKUP(kill_who, KillWho); + +static const char* const tty_validity_table[_TTY_VALIDITY_MAX] = { + [TTY_FROM_PAM] = "from-pam", + [TTY_FROM_UTMP] = "from-utmp", + [TTY_UTMP_INCONSISTENT] = "utmp-inconsistent", +}; + +DEFINE_STRING_TABLE_LOOKUP(tty_validity, TTYValidity); diff -Naurp systemd-239-orig/src/login/logind-session-dbus.c systemd-239/src/login/logind-session-dbus.c --- systemd-239-orig/src/login/logind-session-dbus.c 2018-06-22 06:11:49.000000000 -0500 +++ systemd-239/src/login/logind-session-dbus.c 2018-11-04 08:49:10.204692728 -0600 @@ -689,6 +689,15 @@ int session_send_lock_all(Manager *m, bo return r; } +static bool session_ready(Session *s) { + assert(s); + + /* Returns true when the session is ready, i.e. all jobs we enqueued for it are done (regardless if successful or not) */ + + return !s->scope_job && + !s->user->service_job; +} + int session_send_create_reply(Session *s, sd_bus_error *error) { _cleanup_(sd_bus_message_unrefp) sd_bus_message *c = NULL; _cleanup_close_ int fifo_fd = -1; @@ -696,19 +705,16 @@ int session_send_create_reply(Session *s assert(s); - /* This is called after the session scope and the user service - * were successfully created, and finishes where + /* This is called after the session scope and the user service were successfully created, and finishes where * bus_manager_create_session() left off. */ if (!s->create_message) return 0; - if (!sd_bus_error_is_set(error) && (s->scope_job || s->user->service_job)) + if (!sd_bus_error_is_set(error) && !session_ready(s)) return 0; - c = s->create_message; - s->create_message = NULL; - + c = TAKE_PTR(s->create_message); if (error) return sd_bus_reply_method_error(c, error); @@ -716,8 +722,7 @@ int session_send_create_reply(Session *s if (fifo_fd < 0) return fifo_fd; - /* Update the session state file before we notify the client - * about the result. */ + /* Update the session state file before we notify the client about the result. */ session_save(s); p = session_bus_path(s); diff -Naurp systemd-239-orig/src/login/logind-session.h systemd-239/src/login/logind-session.h --- systemd-239-orig/src/login/logind-session.h 2018-06-22 06:11:49.000000000 -0500 +++ systemd-239/src/login/logind-session.h 2018-11-04 08:49:10.204692728 -0600 @@ -46,6 +46,14 @@ enum KillWho { _KILL_WHO_INVALID = -1 }; +typedef enum TTYValidity { + TTY_FROM_PAM, + TTY_FROM_UTMP, + TTY_UTMP_INCONSISTENT, /* may happen on ssh sessions with multiplexed TTYs */ + _TTY_VALIDITY_MAX, + _TTY_VALIDITY_INVALID = -1, +} TTYValidity; + struct Session { Manager *manager; @@ -60,8 +68,9 @@ struct Session { dual_timestamp timestamp; - char *tty; char *display; + char *tty; + TTYValidity tty_validity; bool remote; char *remote_user; @@ -97,6 +106,7 @@ struct Session { sd_bus_message *create_message; + /* Set up when a client requested to release the session via the bus */ sd_event_source *timer_event_source; char *controller; @@ -109,9 +119,13 @@ struct Session { LIST_FIELDS(Session, gc_queue); }; -Session *session_new(Manager *m, const char *id); -void session_free(Session *s); +int session_new(Session **ret, Manager *m, const char *id); +Session* session_free(Session *s); + +DEFINE_TRIVIAL_CLEANUP_FUNC(Session *, session_free); + void session_set_user(Session *s, User *u); +int session_set_leader(Session *s, pid_t pid); bool session_may_gc(Session *s, bool drop_not_started); void session_add_to_gc_queue(Session *s); int session_activate(Session *s); @@ -121,7 +135,7 @@ void session_set_idle_hint(Session *s, b int session_get_locked_hint(Session *s); void session_set_locked_hint(Session *s, bool b); int session_create_fifo(Session *s); -int session_start(Session *s, sd_bus_message *properties); +int session_start(Session *s, sd_bus_message *properties, sd_bus_error *error); int session_stop(Session *s, bool force); int session_finalize(Session *s); int session_release(Session *s); @@ -155,6 +169,9 @@ SessionClass session_class_from_string(c const char *kill_who_to_string(KillWho k) _const_; KillWho kill_who_from_string(const char *s) _pure_; +const char* tty_validity_to_string(TTYValidity t) _const_; +TTYValidity tty_validity_from_string(const char *s) _pure_; + int session_prepare_vt(Session *s); void session_restore_vt(Session *s); void session_leave_vt(Session *s); diff -Naurp systemd-239-orig/src/login/logind-user.c systemd-239/src/login/logind-user.c --- systemd-239-orig/src/login/logind-user.c 2018-06-22 06:11:49.000000000 -0500 +++ systemd-239/src/login/logind-user.c 2018-11-04 08:49:10.204692728 -0600 @@ -26,38 +26,52 @@ #include "special.h" #include "stdio-util.h" #include "string-table.h" +#include "strv.h" #include "unit-name.h" #include "user-util.h" #include "util.h" -int user_new(User **out, Manager *m, uid_t uid, gid_t gid, const char *name) { +int user_new(User **ret, + Manager *m, + uid_t uid, + gid_t gid, + const char *name, + const char *home) { + _cleanup_(user_freep) User *u = NULL; char lu[DECIMAL_STR_MAX(uid_t) + 1]; int r; - assert(out); + assert(ret); assert(m); assert(name); - u = new0(User, 1); + u = new(User, 1); if (!u) return -ENOMEM; - u->manager = m; - u->uid = uid; - u->gid = gid; - xsprintf(lu, UID_FMT, uid); + *u = (User) { + .manager = m, + .uid = uid, + .gid = gid, + .last_session_timestamp = USEC_INFINITY, + }; u->name = strdup(name); if (!u->name) return -ENOMEM; + u->home = strdup(home); + if (!u->home) + return -ENOMEM; + if (asprintf(&u->state_file, "/run/systemd/users/"UID_FMT, uid) < 0) return -ENOMEM; if (asprintf(&u->runtime_path, "/run/user/"UID_FMT, uid) < 0) return -ENOMEM; + xsprintf(lu, UID_FMT, uid); r = slice_build_subslice(SPECIAL_USER_SLICE, lu, &u->slice); if (r < 0) return r; @@ -66,6 +80,10 @@ int user_new(User **out, Manager *m, uid if (r < 0) return r; + r = unit_name_build("user-runtime-dir", lu, ".service", &u->runtime_dir_service); + if (r < 0) + return r; + r = hashmap_put(m->users, UID_TO_PTR(uid), u); if (r < 0) return r; @@ -78,8 +96,11 @@ int user_new(User **out, Manager *m, uid if (r < 0) return r; - *out = TAKE_PTR(u); + r = hashmap_put(m->user_units, u->runtime_dir_service, u); + if (r < 0) + return r; + *ret = TAKE_PTR(u); return 0; } @@ -96,19 +117,25 @@ User *user_free(User *u) { if (u->service) hashmap_remove_value(u->manager->user_units, u->service, u); + if (u->runtime_dir_service) + hashmap_remove_value(u->manager->user_units, u->runtime_dir_service, u); + if (u->slice) hashmap_remove_value(u->manager->user_units, u->slice, u); hashmap_remove_value(u->manager->users, UID_TO_PTR(u->uid), u); - u->slice_job = mfree(u->slice_job); + (void) sd_event_source_unref(u->timer_event_source); + u->service_job = mfree(u->service_job); u->service = mfree(u->service); + u->runtime_dir_service = mfree(u->runtime_dir_service); u->slice = mfree(u->slice); u->runtime_path = mfree(u->runtime_path); u->state_file = mfree(u->state_file); u->name = mfree(u->name); + u->home = mfree(u->home); return mfree(u); } @@ -135,9 +162,11 @@ static int user_save_internal(User *u) { fprintf(f, "# This is private data. Do not parse.\n" "NAME=%s\n" - "STATE=%s\n", + "STATE=%s\n" /* friendly user-facing state */ + "STOPPING=%s\n", /* low-level state */ u->name, - user_state_to_string(user_get_state(u))); + user_state_to_string(user_get_state(u)), + yes_no(u->stopping)); /* LEGACY: no-one reads RUNTIME= anymore, drop it at some point */ if (u->runtime_path) @@ -146,9 +175,6 @@ static int user_save_internal(User *u) { if (u->service_job) fprintf(f, "SERVICE_JOB=%s\n", u->service_job); - if (u->slice_job) - fprintf(f, "SLICE_JOB=%s\n", u->slice_job); - if (u->display) fprintf(f, "DISPLAY=%s\n", u->display->id); @@ -159,6 +185,10 @@ static int user_save_internal(User *u) { u->timestamp.realtime, u->timestamp.monotonic); + if (u->last_session_timestamp != USEC_INFINITY) + fprintf(f, "LAST_SESSION_TIMESTAMP=" USEC_FMT "\n", + u->last_session_timestamp); + if (u->sessions) { Session *i; bool first; @@ -272,103 +302,83 @@ int user_save(User *u) { if (!u->started) return 0; - return user_save_internal (u); + return user_save_internal(u); } int user_load(User *u) { - _cleanup_free_ char *display = NULL, *realtime = NULL, *monotonic = NULL; - Session *s = NULL; + _cleanup_free_ char *realtime = NULL, *monotonic = NULL, *stopping = NULL, *last_session_timestamp = NULL; int r; assert(u); r = parse_env_file(NULL, u->state_file, NEWLINE, - "SERVICE_JOB", &u->service_job, - "SLICE_JOB", &u->slice_job, - "DISPLAY", &display, - "REALTIME", &realtime, - "MONOTONIC", &monotonic, + "SERVICE_JOB", &u->service_job, + "STOPPING", &stopping, + "REALTIME", &realtime, + "MONOTONIC", &monotonic, + "LAST_SESSION_TIMESTAMP", &last_session_timestamp, NULL); - if (r < 0) { - if (r == -ENOENT) - return 0; - + if (r == -ENOENT) + return 0; + if (r < 0) return log_error_errno(r, "Failed to read %s: %m", u->state_file); - } - - if (display) - s = hashmap_get(u->manager->sessions, display); - if (s && s->display && display_is_local(s->display)) - u->display = s; + if (stopping) { + r = parse_boolean(stopping); + if (r < 0) + log_debug_errno(r, "Failed to parse 'STOPPING' boolean: %s", stopping); + else + u->stopping = r; + } if (realtime) - timestamp_deserialize(realtime, &u->timestamp.realtime); + (void) timestamp_deserialize(realtime, &u->timestamp.realtime); if (monotonic) - timestamp_deserialize(monotonic, &u->timestamp.monotonic); + (void) timestamp_deserialize(monotonic, &u->timestamp.monotonic); + if (last_session_timestamp) + (void) timestamp_deserialize(last_session_timestamp, &u->last_session_timestamp); - return r; + return 0; } -static int user_start_service(User *u) { +static void user_start_service(User *u) { _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; - char *job; int r; assert(u); - u->service_job = mfree(u->service_job); + /* Start the service containing the "systemd --user" instance (user@.service). Note that we don't explicitly + * start the per-user slice or the systemd-runtime-dir@.service instance, as those are pulled in both by + * user@.service and the session scopes as dependencies. */ - r = manager_start_unit( - u->manager, - u->service, - &error, - &job); - if (r < 0) - /* we don't fail due to this, let's try to continue */ - log_error_errno(r, "Failed to start user service, ignoring: %s", bus_error_message(&error, r)); - else - u->service_job = job; + u->service_job = mfree(u->service_job); - return 0; + r = manager_start_unit(u->manager, u->service, &error, &u->service_job); + if (r < 0) + log_warning_errno(r, "Failed to start user service '%s', ignoring: %s", u->service, bus_error_message(&error, r)); } int user_start(User *u) { - int r; - assert(u); if (u->started && !u->stopping) return 0; - /* - * If u->stopping is set, the user is marked for removal and the slice - * and service stop-jobs are queued. We have to clear that flag before - * queing the start-jobs again. If they succeed, the user object can be - * re-used just fine (pid1 takes care of job-ordering and proper - * restart), but if they fail, we want to force another user_stop() so - * possibly pending units are stopped. - * Note that we don't clear u->started, as we have no clue what state - * the user is in on failure here. Hence, we pretend the user is - * running so it will be properly taken down by GC. However, we clearly - * return an error from user_start() in that case, so no further - * reference to the user is taken. - */ + /* If u->stopping is set, the user is marked for removal and service stop-jobs are queued. We have to clear + * that flag before queing the start-jobs again. If they succeed, the user object can be re-used just fine + * (pid1 takes care of job-ordering and proper restart), but if they fail, we want to force another user_stop() + * so possibly pending units are stopped. */ u->stopping = false; if (!u->started) log_debug("Starting services for new user %s.", u->name); - /* Save the user data so far, because pam_systemd will read the - * XDG_RUNTIME_DIR out of it while starting up systemd --user. - * We need to do user_save_internal() because we have not - * "officially" started yet. */ + /* Save the user data so far, because pam_systemd will read the XDG_RUNTIME_DIR out of it while starting up + * systemd --user. We need to do user_save_internal() because we have not "officially" started yet. */ user_save_internal(u); - /* Spawn user systemd */ - r = user_start_service(u); - if (r < 0) - return r; + /* Start user@UID.service */ + user_start_service(u); if (!u->started) { if (!dual_timestamp_is_set(&u->timestamp)) @@ -383,68 +393,50 @@ int user_start(User *u) { return 0; } -static int user_stop_slice(User *u) { +static void user_stop_service(User *u) { _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; - char *job; int r; assert(u); + assert(u->service); - r = manager_stop_unit(u->manager, u->slice, &error, &job); - if (r < 0) { - log_error("Failed to stop user slice: %s", bus_error_message(&error, r)); - return r; - } - - free(u->slice_job); - u->slice_job = job; - - return r; -} - -static int user_stop_service(User *u) { - _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; - char *job; - int r; + /* The reverse of user_start_service(). Note that we only stop user@UID.service here, and let StopWhenUnneeded= + * deal with the slice and the user-runtime-dir@.service instance. */ - assert(u); - - r = manager_stop_unit(u->manager, u->service, &error, &job); - if (r < 0) { - log_error("Failed to stop user service: %s", bus_error_message(&error, r)); - return r; - } + u->service_job = mfree(u->service_job); - free_and_replace(u->service_job, job); - return r; + r = manager_stop_unit(u->manager, u->service, &error, &u->service_job); + if (r < 0) + log_warning_errno(r, "Failed to stop user service '%s', ignoring: %s", u->service, bus_error_message(&error, r)); } int user_stop(User *u, bool force) { Session *s; - int r = 0, k; + int r = 0; assert(u); - /* Stop jobs have already been queued */ - if (u->stopping) { + /* This is called whenever we begin with tearing down a user record. It's called in two cases: explicit API + * request to do so via the bus (in which case 'force' is true) and automatically due to GC, if there's no + * session left pinning it (in which case 'force' is false). Note that this just initiates tearing down of the + * user, the User object will remain in memory until user_finalize() is called, see below. */ + + if (!u->started) + return 0; + + if (u->stopping) { /* Stop jobs have already been queued */ user_save(u); - return r; + return 0; } LIST_FOREACH(sessions_by_user, s, u->sessions) { + int k; + k = session_stop(s, force); if (k < 0) r = k; } - /* Kill systemd */ - k = user_stop_service(u); - if (k < 0) - r = k; - - /* Kill cgroup */ - k = user_stop_slice(u); - if (k < 0) - r = k; + user_stop_service(u); u->stopping = true; @@ -459,6 +451,9 @@ int user_finalize(User *u) { assert(u); + /* Called when the user is really ready to be freed, i.e. when all unit stop jobs and suchlike for it are + * done. This is called as a result of an earlier user_done() when all jobs are completed. */ + if (u->started) log_debug("User %s logged out.", u->name); @@ -480,7 +475,7 @@ int user_finalize(User *u) { r = k; } - unlink(u->state_file); + (void) unlink(u->state_file); user_add_to_gc_queue(u); if (u->started) { @@ -536,11 +531,40 @@ int user_check_linger_file(User *u) { return -ENOMEM; p = strjoina("/var/lib/systemd/linger/", cc); + if (access(p, F_OK) < 0) { + if (errno != ENOENT) + return -errno; + + return false; + } - return access(p, F_OK) >= 0; + return true; +} + +static bool user_unit_active(User *u) { + const char *i; + int r; + + assert(u->service); + assert(u->runtime_dir_service); + assert(u->slice); + + FOREACH_STRING(i, u->service, u->runtime_dir_service, u->slice) { + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + + r = manager_unit_is_active(u->manager, i, &error); + if (r < 0) + log_debug_errno(r, "Failed to determine whether unit '%s' is active, ignoring: %s", u->service, bus_error_message(&error, r)); + if (r != 0) + return true; + } + + return false; } bool user_may_gc(User *u, bool drop_not_started) { + int r; + assert(u); if (drop_not_started && !u->started) @@ -549,15 +573,36 @@ bool user_may_gc(User *u, bool drop_not_ if (u->sessions) return false; - if (user_check_linger_file(u) > 0) - return false; + if (u->last_session_timestamp != USEC_INFINITY) { + /* All sessions have been closed. Let's see if we shall leave the user record around for a bit */ - if (u->slice_job && manager_job_is_active(u->manager, u->slice_job)) - return false; + if (u->manager->user_stop_delay == USEC_INFINITY) + return false; /* Leave it around forever! */ + if (u->manager->user_stop_delay > 0 && + now(CLOCK_MONOTONIC) < usec_add(u->last_session_timestamp, u->manager->user_stop_delay)) + return false; /* Leave it around for a bit longer. */ + } - if (u->service_job && manager_job_is_active(u->manager, u->service_job)) + /* Is this a user that shall stay around forever ("linger")? Before we say "no" to GC'ing for lingering users, let's check + * if any of the three units that we maintain for this user is still around. If none of them is, + * there's no need to keep this user around even if lingering is enabled. */ + if (user_check_linger_file(u) > 0 && user_unit_active(u)) return false; + /* Check if our job is still pending */ + if (u->service_job) { + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + + r = manager_job_is_active(u->manager, u->service_job, &error); + if (r < 0) + log_debug_errno(r, "Failed to determine whether job '%s' is pending, ignoring: %s", u->service_job, bus_error_message(&error, r)); + if (r != 0) + return false; + } + + /* Note that we don't care if the three units we manage for each user object are up or not, as we are managing + * their state rather than tracking it. */ + return true; } @@ -579,7 +624,7 @@ UserState user_get_state(User *u) { if (u->stopping) return USER_CLOSING; - if (!u->started || u->slice_job || u->service_job) + if (!u->started || u->service_job) return USER_OPENING; if (u->sessions) { @@ -598,7 +643,7 @@ UserState user_get_state(User *u) { return all_closing ? USER_CLOSING : USER_ONLINE; } - if (user_check_linger_file(u) > 0) + if (user_check_linger_file(u) > 0 && user_unit_active(u)) return USER_LINGERING; return USER_CLOSING; @@ -611,11 +656,10 @@ int user_kill(User *u, int signo) { } static bool elect_display_filter(Session *s) { - /* Return true if the session is a candidate for the user’s ‘primary - * session’ or ‘display’. */ + /* Return true if the session is a candidate for the user’s ‘primary session’ or ‘display’. */ assert(s); - return (s->class == SESSION_USER && !s->stopping); + return s->class == SESSION_USER && s->started && !s->stopping; } static int elect_display_compare(Session *s1, Session *s2) { @@ -661,9 +705,8 @@ void user_elect_display(User *u) { assert(u); - /* This elects a primary session for each user, which we call - * the "display". We try to keep the assignment stable, but we - * "upgrade" to better choices. */ + /* This elects a primary session for each user, which we call the "display". We try to keep the assignment + * stable, but we "upgrade" to better choices. */ log_debug("Electing new display for user %s", u->name); LIST_FOREACH(sessions_by_user, s, u->sessions) { @@ -679,6 +722,59 @@ void user_elect_display(User *u) { } } +static int user_stop_timeout_callback(sd_event_source *es, uint64_t usec, void *userdata) { + User *u = userdata; + + assert(u); + user_add_to_gc_queue(u); + + return 0; +} + +void user_update_last_session_timer(User *u) { + int r; + + assert(u); + + if (u->sessions) { + /* There are sessions, turn off the timer */ + u->last_session_timestamp = USEC_INFINITY; + u->timer_event_source = sd_event_source_unref(u->timer_event_source); + return; + } + + if (u->last_session_timestamp != USEC_INFINITY) + return; /* Timer already started */ + + u->last_session_timestamp = now(CLOCK_MONOTONIC); + + assert(!u->timer_event_source); + + if (u->manager->user_stop_delay == 0 || u->manager->user_stop_delay == USEC_INFINITY) + return; + + if (sd_event_get_state(u->manager->event) == SD_EVENT_FINISHED) { + log_debug("Not allocating user stop timeout, since we are already exiting."); + return; + } + + r = sd_event_add_time(u->manager->event, + &u->timer_event_source, + CLOCK_MONOTONIC, + usec_add(u->last_session_timestamp, u->manager->user_stop_delay), 0, + user_stop_timeout_callback, u); + if (r < 0) + log_warning_errno(r, "Failed to enqueue user stop event source, ignoring: %m"); + + if (DEBUG_LOGGING) { + char s[FORMAT_TIMESPAN_MAX]; + + log_debug("Last session of user '%s' logged out, terminating user context in %s.", + u->name, + format_timespan(s, sizeof(s), u->manager->user_stop_delay, USEC_PER_MSEC)); + } +} + static const char* const user_state_table[_USER_STATE_MAX] = { [USER_OFFLINE] = "offline", [USER_OPENING] = "opening", @@ -751,7 +847,7 @@ int config_parse_compat_user_tasks_max( log_syntax(unit, LOG_NOTICE, filename, line, 0, "Support for option %s= has been removed.", lvalue); - log_info("Hint: try creating /etc/systemd/system/user-.slice/50-limits.conf with:\n" + log_info("Hint: try creating /etc/systemd/system/user-.slice.d/50-limits.conf with:\n" " [Slice]\n" " TasksMax=%s", rvalue); diff -Naurp systemd-239-orig/src/login/logind-user-dbus.c systemd-239/src/login/logind-user-dbus.c --- systemd-239-orig/src/login/logind-user-dbus.c 2018-06-22 06:11:49.000000000 -0500 +++ systemd-239/src/login/logind-user-dbus.c 2018-11-04 08:49:10.204692728 -0600 @@ -109,7 +109,7 @@ static int property_get_idle_since_hint( assert(reply); assert(u); - user_get_idle_hint(u, &t); + (void) user_get_idle_hint(u, &t); k = streq(property, "IdleSinceHint") ? t.realtime : t.monotonic; return sd_bus_message_append(reply, "t", k); diff -Naurp systemd-239-orig/src/login/logind-user.h systemd-239/src/login/logind-user.h --- systemd-239-orig/src/login/logind-user.h 2018-06-22 06:11:49.000000000 -0500 +++ systemd-239/src/login/logind-user.h 2018-11-04 08:49:10.204692728 -0600 @@ -23,27 +23,34 @@ struct User { uid_t uid; gid_t gid; char *name; + char *home; char *state_file; char *runtime_path; - char *slice; - char *service; + + char *slice; /* user-UID.slice */ + char *service; /* user@UID.service */ + char *runtime_dir_service; /* user-runtime-dir@UID.service */ char *service_job; - char *slice_job; Session *display; - dual_timestamp timestamp; + dual_timestamp timestamp; /* When this User object was 'started' the first time */ + usec_t last_session_timestamp; /* When the number of sessions of this user went from 1 to 0 the last time */ + + /* Set up when the last session of the user logs out */ + sd_event_source *timer_event_source; bool in_gc_queue:1; - bool started:1; - bool stopping:1; + + bool started:1; /* Whenever the user being started, has been started or is being stopped again. */ + bool stopping:1; /* Whenever the user is being stopped or has been stopped. */ LIST_HEAD(Session, sessions); LIST_FIELDS(User, gc_queue); }; -int user_new(User **out, Manager *m, uid_t uid, gid_t gid, const char *name); +int user_new(User **out, Manager *m, uid_t uid, gid_t gid, const char *name, const char *home); User *user_free(User *u); DEFINE_TRIVIAL_CLEANUP_FUNC(User *, user_free); @@ -60,6 +67,7 @@ int user_load(User *u); int user_kill(User *u, int signo); int user_check_linger_file(User *u); void user_elect_display(User *u); +void user_update_last_session_timer(User *u); extern const sd_bus_vtable user_vtable[]; int user_node_enumerator(sd_bus *bus, const char *path, void *userdata, char ***nodes, sd_bus_error *error); diff -Naurp systemd-239-orig/src/login/logind-utmp.c systemd-239/src/login/logind-utmp.c --- systemd-239-orig/src/login/logind-utmp.c 2018-06-22 06:11:49.000000000 -0500 +++ systemd-239/src/login/logind-utmp.c 2018-11-04 08:49:10.204692728 -0600 @@ -61,7 +61,7 @@ bool logind_wall_tty_filter(const char * static int warn_wall(Manager *m, usec_t n) { char date[FORMAT_TIMESTAMP_MAX] = {}; - _cleanup_free_ char *l = NULL; + _cleanup_free_ char *l = NULL, *username = NULL; usec_t left; int r; @@ -83,8 +83,8 @@ static int warn_wall(Manager *m, usec_t return 0; } - utmp_wall(l, uid_to_name(m->scheduled_shutdown_uid), - m->scheduled_shutdown_tty, logind_wall_tty_filter, m); + username = uid_to_name(m->scheduled_shutdown_uid); + utmp_wall(l, username, m->scheduled_shutdown_tty, logind_wall_tty_filter, m); return 1; } diff -Naurp systemd-239-orig/src/login/meson.build systemd-239/src/login/meson.build --- systemd-239-orig/src/login/meson.build 2018-06-22 06:11:49.000000000 -0500 +++ systemd-239/src/login/meson.build 2018-11-04 08:49:10.204692728 -0600 @@ -58,7 +58,6 @@ loginctl_sources = files(''' user_runtime_dir_sources = files(''' user-runtime-dir.c - logind.h '''.split()) if conf.get('ENABLE_LOGIND') == 1 @@ -81,10 +80,6 @@ if conf.get('ENABLE_LOGIND') == 1 install_data('70-power-switch.rules', install_dir : udevrulesdir) - if conf.get('HAVE_ACL') == 1 - install_data('70-uaccess.rules', install_dir : udevrulesdir) - endif - seat_rules = configure_file( input : '71-seat.rules.in', output : '71-seat.rules', @@ -93,6 +88,15 @@ if conf.get('ENABLE_LOGIND') == 1 install_dir : udevrulesdir) custom_target( + '70-uaccess.rules', + input : '70-uaccess.rules.m4', + output: '70-uaccess.rules', + command : [meson_apply_m4, config_h, '@INPUT@'], + capture : true, + install : conf.get('HAVE_ACL') == 1, + install_dir : udevrulesdir) + + custom_target( '73-seat-late.rules', input : '73-seat-late.rules.m4', output: '73-seat-late.rules', diff -Naurp systemd-239-orig/src/login/org.freedesktop.login1.policy systemd-239/src/login/org.freedesktop.login1.policy --- systemd-239-orig/src/login/org.freedesktop.login1.policy 2018-06-22 06:11:49.000000000 -0500 +++ systemd-239/src/login/org.freedesktop.login1.policy 2018-11-04 08:49:10.204692728 -0600 @@ -343,7 +343,7 @@ auth_admin_keep auth_admin_keep - auth_admin_keep + yes diff -Naurp systemd-239-orig/src/login/pam_systemd.c systemd-239/src/login/pam_systemd.c --- systemd-239-orig/src/login/pam_systemd.c 2018-06-22 06:11:49.000000000 -0500 +++ systemd-239/src/login/pam_systemd.c 2018-11-04 08:49:10.204692728 -0600 @@ -130,7 +130,7 @@ static int get_seat_from_display(const c r = socket_from_display(display, &p); if (r < 0) return r; - strncpy(sa.un.sun_path, p, sizeof(sa.un.sun_path)-1); + strncpy(sa.un.sun_path, p, sizeof(sa.un.sun_path)); fd = socket(AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC, 0); if (fd < 0) @@ -274,6 +274,36 @@ static int append_session_cg_weight(pam_ return 0; } +static bool validate_runtime_directory(pam_handle_t *handle, const char *path, uid_t uid) { + struct stat st; + + assert(path); + + /* Just some extra paranoia: let's not set $XDG_RUNTIME_DIR if the directory we'd set it to isn't actually set + * up properly for us. */ + + if (lstat(path, &st) < 0) { + pam_syslog(handle, LOG_ERR, "Failed to stat() runtime directory '%s': %s", path, strerror(errno)); + goto fail; + } + + if (!S_ISDIR(st.st_mode)) { + pam_syslog(handle, LOG_ERR, "Runtime directory '%s' is not actually a directory.", path); + goto fail; + } + + if (st.st_uid != uid) { + pam_syslog(handle, LOG_ERR, "Runtime directory '%s' is not owned by UID " UID_FMT ", as it should.", path, uid); + goto fail; + } + + return true; + +fail: + pam_syslog(handle, LOG_WARNING, "Not setting $XDG_RUNTIME_DIR, as the directory is not in order."); + return false; +} + _public_ PAM_EXTERN int pam_sm_open_session( pam_handle_t *handle, int flags, @@ -332,10 +362,12 @@ _public_ PAM_EXTERN int pam_sm_open_sess if (asprintf(&rt, "/run/user/"UID_FMT, pw->pw_uid) < 0) return PAM_BUF_ERR; - r = pam_misc_setenv(handle, "XDG_RUNTIME_DIR", rt, 0); - if (r != PAM_SUCCESS) { - pam_syslog(handle, LOG_ERR, "Failed to set runtime dir."); - return r; + if (validate_runtime_directory(handle, rt, pw->pw_uid)) { + r = pam_misc_setenv(handle, "XDG_RUNTIME_DIR", rt, 0); + if (r != PAM_SUCCESS) { + pam_syslog(handle, LOG_ERR, "Failed to set runtime dir."); + return r; + } } r = export_legacy_dbus_address(handle, pw->pw_uid, rt); @@ -379,28 +411,32 @@ _public_ PAM_EXTERN int pam_sm_open_sess tty = strempty(tty); if (strchr(tty, ':')) { - /* A tty with a colon is usually an X11 display, - * placed there to show up in utmp. We rearrange - * things and don't pretend that an X display was a - * tty. */ - + /* A tty with a colon is usually an X11 display, placed there to show up in utmp. We rearrange things + * and don't pretend that an X display was a tty. */ if (isempty(display)) display = tty; tty = NULL; + } else if (streq(tty, "cron")) { - /* cron has been setting PAM_TTY to "cron" for a very - * long time and it probably shouldn't stop doing that - * for compatibility reasons. */ + /* cron is setting PAM_TTY to "cron" for some reason (the commit carries no information why, but + * probably because it wants to set it to something as pam_time/pam_access/… require PAM_TTY to be set + * (as they otherwise even try to update it!) — but cron doesn't actually allocate a TTY for its forked + * off processes.) */ type = "unspecified"; class = "background"; tty = NULL; + } else if (streq(tty, "ssh")) { - /* ssh has been setting PAM_TTY to "ssh" for a very - * long time and probably shouldn't stop doing that - * for compatibility reasons. */ + /* ssh has been setting PAM_TTY to "ssh" (for the same reason as cron does this, see above. For further + * details look for "PAM_TTY_KLUDGE" in the openssh sources). */ type ="tty"; class = "user"; - tty = NULL; + tty = NULL; /* This one is particularly sad, as this means that ssh sessions — even though usually + * associated with a pty — won't be tracked by their tty in logind. This is because ssh + * does the PAM session registration early for new connections, and registers a pty only + * much later (this is because it doesn't know yet if it needs one at all, as whether to + * register a pty or not is negotiated much later in the protocol). */ + } else /* Chop off leading /dev prefix that some clients specify, but others do not. */ tty = skip_dev_prefix(tty); @@ -470,7 +506,7 @@ _public_ PAM_EXTERN int pam_sm_open_sess r = sd_bus_message_append(m, "uusssssussbss", (uint32_t) pw->pw_uid, - (uint32_t) getpid_cached(), + 0, service, type, class, @@ -559,10 +595,12 @@ _public_ PAM_EXTERN int pam_sm_open_sess * in privileged apps clobbering the runtime directory * unnecessarily. */ - r = pam_misc_setenv(handle, "XDG_RUNTIME_DIR", runtime_path, 0); - if (r != PAM_SUCCESS) { - pam_syslog(handle, LOG_ERR, "Failed to set runtime dir."); - return r; + if (validate_runtime_directory(handle, runtime_path, pw->pw_uid)) { + r = pam_misc_setenv(handle, "XDG_RUNTIME_DIR", runtime_path, 0); + if (r != PAM_SUCCESS) { + pam_syslog(handle, LOG_ERR, "Failed to set runtime dir."); + return r; + } } r = export_legacy_dbus_address(handle, pw->pw_uid, runtime_path); diff -Naurp systemd-239-orig/src/login/user-runtime-dir.c systemd-239/src/login/user-runtime-dir.c --- systemd-239-orig/src/login/user-runtime-dir.c 2018-06-22 06:11:49.000000000 -0500 +++ systemd-239/src/login/user-runtime-dir.c 2018-11-04 08:49:10.204692728 -0600 @@ -3,34 +3,44 @@ #include #include +#include "sd-bus.h" + +#include "bus-error.h" #include "fs-util.h" #include "label.h" -#include "logind.h" #include "mkdir.h" #include "mount-util.h" #include "path-util.h" #include "rm-rf.h" +#include "selinux-util.h" #include "smack-util.h" #include "stdio-util.h" #include "string-util.h" #include "strv.h" #include "user-util.h" -static int gather_configuration(size_t *runtime_dir_size) { - Manager m = {}; +static int acquire_runtime_dir_size(uint64_t *ret) { + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + _cleanup_(sd_bus_unrefp) sd_bus *bus = NULL; int r; - manager_reset_config(&m); + r = sd_bus_default_system(&bus); + if (r < 0) + return log_error_errno(r, "Failed to connect to system bus: %m"); - r = manager_parse_config_file(&m); + r = sd_bus_get_property_trivial(bus, "org.freedesktop.login1", "/org/freedesktop/login1", "org.freedesktop.login1.Manager", "RuntimeDirectorySize", &error, 't', ret); if (r < 0) - log_warning_errno(r, "Failed to parse logind.conf: %m"); + return log_error_errno(r, "Failed to acquire runtime directory size: %s", bus_error_message(&error, r)); - *runtime_dir_size = m.runtime_dir_size; return 0; } -static int user_mkdir_runtime_path(const char *runtime_path, uid_t uid, gid_t gid, size_t runtime_dir_size) { +static int user_mkdir_runtime_path( + const char *runtime_path, + uid_t uid, + gid_t gid, + uint64_t runtime_dir_size) { + int r; assert(runtime_path); @@ -48,10 +58,10 @@ static int user_mkdir_runtime_path(const char options[sizeof("mode=0700,uid=,gid=,size=,smackfsroot=*") + DECIMAL_STR_MAX(uid_t) + DECIMAL_STR_MAX(gid_t) - + DECIMAL_STR_MAX(size_t)]; + + DECIMAL_STR_MAX(uint64_t)]; xsprintf(options, - "mode=0700,uid=" UID_FMT ",gid=" GID_FMT ",size=%zu%s", + "mode=0700,uid=" UID_FMT ",gid=" GID_FMT ",size=%" PRIu64 "%s", uid, gid, runtime_dir_size, mac_smack_use() ? ",smackfsroot=*" : ""); @@ -95,41 +105,70 @@ static int user_remove_runtime_path(cons r = rm_rf(runtime_path, 0); if (r < 0) - log_error_errno(r, "Failed to remove runtime directory %s (before unmounting): %m", runtime_path); + log_debug_errno(r, "Failed to remove runtime directory %s (before unmounting), ignoring: %m", runtime_path); - /* Ignore cases where the directory isn't mounted, as that's - * quite possible, if we lacked the permissions to mount - * something */ + /* Ignore cases where the directory isn't mounted, as that's quite possible, if we lacked the permissions to + * mount something */ r = umount2(runtime_path, MNT_DETACH); if (r < 0 && !IN_SET(errno, EINVAL, ENOENT)) - log_error_errno(errno, "Failed to unmount user runtime directory %s: %m", runtime_path); + log_debug_errno(errno, "Failed to unmount user runtime directory %s, ignoring: %m", runtime_path); r = rm_rf(runtime_path, REMOVE_ROOT); - if (r < 0) - log_error_errno(r, "Failed to remove runtime directory %s (after unmounting): %m", runtime_path); + if (r < 0 && r != -ENOENT) + return log_error_errno(r, "Failed to remove runtime directory %s (after unmounting): %m", runtime_path); - return r; + return 0; } -static int do_mount(const char *runtime_path, uid_t uid, gid_t gid) { - size_t runtime_dir_size; +static int do_mount(const char *user) { + char runtime_path[sizeof("/run/user") + DECIMAL_STR_MAX(uid_t)]; + uint64_t runtime_dir_size; + uid_t uid; + gid_t gid; + int r; + + r = get_user_creds(&user, &uid, &gid, NULL, NULL); + if (r < 0) + return log_error_errno(r, + r == -ESRCH ? "No such user \"%s\"" : + r == -ENOMSG ? "UID \"%s\" is invalid or has an invalid main group" + : "Failed to look up user \"%s\": %m", + user); - assert_se(gather_configuration(&runtime_dir_size) == 0); + r = acquire_runtime_dir_size(&runtime_dir_size); + if (r < 0) + return r; + + xsprintf(runtime_path, "/run/user/" UID_FMT, uid); log_debug("Will mount %s owned by "UID_FMT":"GID_FMT, runtime_path, uid, gid); return user_mkdir_runtime_path(runtime_path, uid, gid, runtime_dir_size); } -static int do_umount(const char *runtime_path) { +static int do_umount(const char *user) { + char runtime_path[sizeof("/run/user") + DECIMAL_STR_MAX(uid_t)]; + uid_t uid; + int r; + + /* The user may be already removed. So, first try to parse the string by parse_uid(), + * and if it fails, fallback to get_user_creds().*/ + if (parse_uid(user, &uid) < 0) { + r = get_user_creds(&user, &uid, NULL, NULL, NULL); + if (r < 0) + return log_error_errno(r, + r == -ESRCH ? "No such user \"%s\"" : + r == -ENOMSG ? "UID \"%s\" is invalid or has an invalid main group" + : "Failed to look up user \"%s\": %m", + user); + } + + xsprintf(runtime_path, "/run/user/" UID_FMT, uid); + log_debug("Will remove %s", runtime_path); return user_remove_runtime_path(runtime_path); } int main(int argc, char *argv[]) { - const char *user; - uid_t uid; - gid_t gid; - char runtime_path[sizeof("/run/user") + DECIMAL_STR_MAX(uid_t)]; int r; log_parse_environment(); @@ -144,25 +183,18 @@ int main(int argc, char *argv[]) { return EXIT_FAILURE; } - umask(0022); - - user = argv[2]; - r = get_user_creds(&user, &uid, &gid, NULL, NULL); + r = mac_selinux_init(); if (r < 0) { - log_error_errno(r, - r == -ESRCH ? "No such user \"%s\"" : - r == -ENOMSG ? "UID \"%s\" is invalid or has an invalid main group" - : "Failed to look up user \"%s\": %m", - user); + log_error_errno(r, "Could not initialize labelling: %m\n"); return EXIT_FAILURE; } - xsprintf(runtime_path, "/run/user/" UID_FMT, uid); + umask(0022); if (streq(argv[1], "start")) - r = do_mount(runtime_path, uid, gid); + r = do_mount(argv[2]); else if (streq(argv[1], "stop")) - r = do_umount(runtime_path); + r = do_umount(argv[2]); else assert_not_reached("Unknown verb!"); diff -Naurp systemd-239-orig/src/machine/machine.c systemd-239/src/machine/machine.c --- systemd-239-orig/src/machine/machine.c 2018-06-22 06:11:49.000000000 -0500 +++ systemd-239/src/machine/machine.c 2018-11-04 08:49:10.204692728 -0600 @@ -183,7 +183,7 @@ int machine_save(Machine *m) { m->timestamp.monotonic); if (m->n_netif > 0) { - unsigned i; + size_t i; fputs("NETIF=", f); diff -Naurp systemd-239-orig/src/machine/machinectl.c systemd-239/src/machine/machinectl.c --- systemd-239-orig/src/machine/machinectl.c 2018-06-22 06:11:49.000000000 -0500 +++ systemd-239/src/machine/machinectl.c 2018-11-04 08:49:10.204692728 -0600 @@ -540,7 +540,7 @@ typedef struct MachineStatusInfo { pid_t leader; struct dual_timestamp timestamp; int *netif; - unsigned n_netif; + size_t n_netif; } MachineStatusInfo; static void machine_status_info_clear(MachineStatusInfo *info) { @@ -600,7 +600,7 @@ static void print_machine_status_info(sd printf("\t Root: %s\n", i->root_directory); if (i->n_netif > 0) { - unsigned c; + size_t c; fputs("\t Iface:", stdout); @@ -1998,7 +1998,7 @@ static int transfer_image_common(sd_bus return r; } - r = sd_bus_message_read(reply, "uo", &id, NULL); + r = sd_bus_message_read(reply, "uo", &id, &path); if (r < 0) return bus_log_parse_error(r); diff -Naurp systemd-239-orig/src/machine/machine.h systemd-239/src/machine/machine.h --- systemd-239-orig/src/machine/machine.h 2018-06-22 06:11:49.000000000 -0500 +++ systemd-239/src/machine/machine.h 2018-11-04 08:49:10.204692728 -0600 @@ -57,7 +57,7 @@ struct Machine { sd_bus_message *create_message; int *netif; - unsigned n_netif; + size_t n_netif; LIST_HEAD(Operation, operations); diff -Naurp systemd-239-orig/src/modules-load/modules-load.c systemd-239/src/modules-load/modules-load.c --- systemd-239-orig/src/modules-load/modules-load.c 2018-06-22 06:11:49.000000000 -0500 +++ systemd-239/src/modules-load/modules-load.c 2018-11-04 08:49:10.204692728 -0600 @@ -59,65 +59,6 @@ static int parse_proc_cmdline_item(const return 0; } -static int load_module(struct kmod_ctx *ctx, const char *m) { - const int probe_flags = KMOD_PROBE_APPLY_BLACKLIST; - struct kmod_list *itr; - _cleanup_(kmod_module_unref_listp) struct kmod_list *modlist = NULL; - int r = 0; - - log_debug("load: %s", m); - - r = kmod_module_new_from_lookup(ctx, m, &modlist); - if (r < 0) - return log_error_errno(r, "Failed to lookup alias '%s': %m", m); - - if (!modlist) { - log_error("Failed to find module '%s'", m); - return -ENOENT; - } - - kmod_list_foreach(itr, modlist) { - _cleanup_(kmod_module_unrefp) struct kmod_module *mod = NULL; - int state, err; - - mod = kmod_module_get_module(itr); - state = kmod_module_get_initstate(mod); - - switch (state) { - case KMOD_MODULE_BUILTIN: - log_info("Module '%s' is builtin", kmod_module_get_name(mod)); - break; - - case KMOD_MODULE_LIVE: - log_debug("Module '%s' is already loaded", kmod_module_get_name(mod)); - break; - - default: - err = kmod_module_probe_insert_module(mod, probe_flags, - NULL, NULL, NULL, NULL); - - if (err == 0) - log_info("Inserted module '%s'", kmod_module_get_name(mod)); - else if (err == KMOD_PROBE_APPLY_BLACKLIST) - log_info("Module '%s' is blacklisted", kmod_module_get_name(mod)); - else { - assert(err < 0); - - log_full_errno(err == ENODEV ? LOG_NOTICE : - err == ENOENT ? LOG_WARNING : - LOG_ERR, - err, - "Failed to insert '%s': %m", - kmod_module_get_name(mod)); - if (!IN_SET(err, ENODEV, ENOENT)) - r = err; - } - } - } - - return r; -} - static int apply_file(struct kmod_ctx *ctx, const char *path, bool ignore_enoent) { _cleanup_fclose_ FILE *f = NULL; int r; @@ -151,7 +92,7 @@ static int apply_file(struct kmod_ctx *c if (strchr(COMMENTS "\n", *l)) continue; - k = load_module(ctx, l); + k = module_load_and_warn(ctx, l, true); if (k < 0 && r == 0) r = k; } @@ -248,7 +189,7 @@ int main(int argc, char *argv[]) { char **fn, **i; STRV_FOREACH(i, arg_proc_cmdline_modules) { - k = load_module(ctx, *i); + k = module_load_and_warn(ctx, *i, true); if (k < 0 && r == 0) r = k; } diff -Naurp systemd-239-orig/src/network/netdev/wireguard.c systemd-239/src/network/netdev/wireguard.c --- systemd-239-orig/src/network/netdev/wireguard.c 2018-06-22 06:11:49.000000000 -0500 +++ systemd-239/src/network/netdev/wireguard.c 2018-11-04 08:49:10.229692718 -0600 @@ -108,7 +108,7 @@ static int set_wireguard_interface(NetDe if (r < 0) break; - r = sd_netlink_message_append_u32(message, WGPEER_A_PERSISTENT_KEEPALIVE_INTERVAL, peer->persistent_keepalive_interval); + r = sd_netlink_message_append_u16(message, WGPEER_A_PERSISTENT_KEEPALIVE_INTERVAL, peer->persistent_keepalive_interval); if (r < 0) break; diff -Naurp systemd-239-orig/src/network/networkd-dhcp4.c systemd-239/src/network/networkd-dhcp4.c --- systemd-239-orig/src/network/networkd-dhcp4.c 2018-06-22 06:11:49.000000000 -0500 +++ systemd-239/src/network/networkd-dhcp4.c 2018-11-04 08:49:10.229692718 -0600 @@ -81,7 +81,9 @@ static int link_set_dhcp_routes(Link *li return log_link_warning_errno(link, r, "DHCP error: could not get address: %m"); n = sd_dhcp_lease_get_routes(link->dhcp_lease, &static_routes); - if (n < 0) + if (n == -ENODATA) + log_link_debug_errno(link, n, "DHCP: No routes received from DHCP server: %m"); + else if (n < 0) log_link_debug_errno(link, n, "DHCP error: could not get routes: %m"); for (i = 0; i < n; i++) { diff -Naurp systemd-239-orig/src/network/networkd-dhcp6.c systemd-239/src/network/networkd-dhcp6.c --- systemd-239-orig/src/network/networkd-dhcp6.c 2018-06-22 06:11:49.000000000 -0500 +++ systemd-239/src/network/networkd-dhcp6.c 2018-11-04 08:49:10.229692718 -0600 @@ -119,8 +119,9 @@ static int dhcp6_pd_prefix_distribute(Li Link *link; Manager *manager = dhcp6_link->manager; union in_addr_union prefix; - uint8_t n_prefixes, n_used = 0; + uint64_t n_prefixes, n_used = 0; _cleanup_free_ char *buf = NULL; + _cleanup_free_ char *assigned_buf = NULL; int r; assert(manager); @@ -132,17 +133,17 @@ static int dhcp6_pd_prefix_distribute(Li if (r < 0) return r; - n_prefixes = 1 << (64 - pd_prefix_len); + n_prefixes = UINT64_C(1) << (64 - pd_prefix_len); (void) in_addr_to_string(AF_INET6, &prefix, &buf); - log_link_debug(dhcp6_link, "Assigning up to %u prefixes from %s/%u", + log_link_debug(dhcp6_link, "Assigning up to %" PRIu64 " prefixes from %s/%u", n_prefixes, strnull(buf), pd_prefix_len); while (hashmap_iterate(manager->links, i, (void **)&link, NULL)) { Link *assigned_link; if (n_used == n_prefixes) { - log_link_debug(dhcp6_link, "Assigned %u/%u prefixes from %s/%u", + log_link_debug(dhcp6_link, "Assigned %" PRIu64 "/%" PRIu64 " prefixes from %s/%u", n_used, n_prefixes, strnull(buf), pd_prefix_len); return -EAGAIN; @@ -158,30 +159,34 @@ static int dhcp6_pd_prefix_distribute(Li if (assigned_link != NULL && assigned_link != link) continue; + (void) in_addr_to_string(AF_INET6, &prefix, &assigned_buf); r = dhcp6_pd_prefix_assign(link, &prefix.in6, 64, lifetime_preferred, lifetime_valid); if (r < 0) { - log_link_error_errno(link, r, "Unable to %s prefix %s/%u for link: %m", + log_link_error_errno(link, r, "Unable to %s prefix %s/64 from %s/%u for link: %m", assigned_link ? "update": "assign", + strnull(assigned_buf), strnull(buf), pd_prefix_len); if (assigned_link == NULL) continue; } else - log_link_debug(link, "Assigned prefix %u/%u %s/64 to link", - n_used + 1, n_prefixes, strnull(buf)); + log_link_debug(link, "Assigned prefix %" PRIu64 "/%" PRIu64 " %s/64 from %s/%u to link", + n_used + 1, n_prefixes, + strnull(assigned_buf), + strnull(buf), pd_prefix_len); n_used++; - r = in_addr_prefix_next(AF_INET6, &prefix, pd_prefix_len); + r = in_addr_prefix_next(AF_INET6, &prefix, 64); if (r < 0 && n_used < n_prefixes) return r; } if (n_used < n_prefixes) { Route *route; - int n = n_used; + uint64_t n = n_used; r = route_new(&route); if (r < 0) @@ -221,8 +226,6 @@ static int dhcp6_lease_pd_prefix_acquire if (r < 0) return r; - (void) in_addr_to_string(AF_INET6, (union in_addr_union*) &pd_prefix, &buf); - dhcp6_reset_pd_prefix_network(link); sd_dhcp6_lease_reset_pd_prefix_iter(lease); @@ -231,11 +234,18 @@ static int dhcp6_lease_pd_prefix_acquire &lifetime_valid) >= 0) { if (pd_prefix_len > 64) { + (void) in_addr_to_string(AF_INET6, (union in_addr_union*) &pd_prefix, &buf); log_link_debug(link, "PD Prefix length > 64, ignoring prefix %s/%u", strnull(buf), pd_prefix_len); continue; } + if (pd_prefix_len < 48) { + (void) in_addr_to_string(AF_INET6, (union in_addr_union*) &pd_prefix, &buf); + log_link_warning(link, "PD Prefix length < 48, looks unusual %s/%u", + strnull(buf), pd_prefix_len); + } + r = dhcp6_pd_prefix_distribute(link, &i, &pd_prefix, pd_prefix_len, lifetime_preferred, diff -Naurp systemd-239-orig/src/network/networkd-link.c systemd-239/src/network/networkd-link.c --- systemd-239-orig/src/network/networkd-link.c 2018-06-22 06:11:49.000000000 -0500 +++ systemd-239/src/network/networkd-link.c 2018-11-04 08:49:10.229692718 -0600 @@ -459,6 +459,10 @@ static int link_new(Manager *manager, sd return -ENOMEM; } + r = sd_netlink_message_read_u32(message, IFLA_MASTER, (uint32_t *)&link->master_ifindex); + if (r < 0) + log_link_debug_errno(link, r, "New device has no master, continuing without"); + r = sd_netlink_message_read_ether_addr(message, IFLA_ADDRESS, &link->mac); if (r < 0) log_link_debug_errno(link, r, "MAC address not found for new device, continuing without"); @@ -1087,7 +1091,7 @@ static int link_enter_set_addresses(Link /* now that we can figure out a default address for the dhcp server, start it */ - if (link_dhcp4_server_enabled(link)) { + if (link_dhcp4_server_enabled(link) && (link->flags & IFF_UP)) { Address *address; Link *uplink = NULL; bool acquired_uplink = false; @@ -1272,6 +1276,8 @@ static int link_set_handler(sd_netlink * return 0; } +static int link_configure_after_setting_mtu(Link *link); + static int set_mtu_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userdata) { _cleanup_(link_unrefp) Link *link = userdata; int r; @@ -1280,12 +1286,21 @@ static int set_mtu_handler(sd_netlink *r assert(link); assert(link->ifname); + link->setting_mtu = false; + if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER)) return 1; r = sd_netlink_message_get_errno(m); - if (r < 0) + if (r < 0) { log_link_warning_errno(link, r, "Could not set MTU: %m"); + return 1; + } + + log_link_debug(link, "Setting MTU done."); + + if (link->state == LINK_STATE_PENDING) + (void) link_configure_after_setting_mtu(link); return 1; } @@ -1298,6 +1313,9 @@ int link_set_mtu(Link *link, uint32_t mt assert(link->manager); assert(link->manager->rtnl); + if (link->mtu == mtu || link->setting_mtu) + return 0; + log_link_debug(link, "Setting MTU: %" PRIu32, mtu); r = sd_rtnl_message_new_link(link->manager->rtnl, &req, RTM_SETLINK, link->ifindex); @@ -1628,18 +1646,6 @@ static int link_acquire_ipv6_conf(Link * assert(link); - if (link_dhcp6_enabled(link)) { - assert(link->dhcp6_client); - assert(in_addr_is_link_local(AF_INET6, (const union in_addr_union*)&link->ipv6ll_address) > 0); - - /* start DHCPv6 client in stateless mode */ - r = dhcp6_request_address(link, true); - if (r < 0 && r != -EBUSY) - return log_link_warning_errno(link, r, "Could not acquire DHCPv6 lease: %m"); - else - log_link_debug(link, "Acquiring DHCPv6 lease"); - } - if (link_ipv6_accept_ra_enabled(link)) { assert(link->ndisc); @@ -1700,11 +1706,6 @@ static int link_acquire_conf(Link *link) assert(link); - if (link->setting_mtu) { - link->setting_mtu = false; - return 0; - } - r = link_acquire_ipv4_conf(link); if (r < 0) return r; @@ -2355,6 +2356,10 @@ static int link_enter_join_netdev(Link * return link_joined(link); if (link->network->bond) { + if (link->network->bond->state == NETDEV_STATE_READY && + link->network->bond->ifindex == link->master_ifindex) + return link_joined(link); + log_struct(LOG_DEBUG, LOG_LINK_INTERFACE(link), LOG_NETDEV_INTERFACE(link->network->bond), @@ -2868,6 +2873,19 @@ static int link_configure(Link *link) { return r; } + return link_configure_after_setting_mtu(link); +} + +static int link_configure_after_setting_mtu(Link *link) { + int r; + + assert(link); + assert(link->network); + assert(link->state == LINK_STATE_PENDING); + + if (link->setting_mtu) + return 0; + if (link_has_carrier(link) || link->network->configure_without_carrier) { r = link_acquire_conf(link); if (r < 0) @@ -3275,8 +3293,8 @@ static int link_carrier_lost(Link *link) assert(link); /* Some devices reset itself while setting the MTU. This causes the DHCP client fall into a loop. - setting_mtu keep track whether the device got reset because of setting MTU and does not drop the - configuration and stop the clients as well. */ + * setting_mtu keep track whether the device got reset because of setting MTU and does not drop the + * configuration and stop the clients as well. */ if (link->setting_mtu) return 0; diff -Naurp systemd-239-orig/src/network/networkd-link.h systemd-239/src/network/networkd-link.h --- systemd-239-orig/src/network/networkd-link.h 2018-06-22 06:11:49.000000000 -0500 +++ systemd-239/src/network/networkd-link.h 2018-11-04 08:49:10.229692718 -0600 @@ -51,6 +51,7 @@ typedef struct Link { int n_ref; int ifindex; + int master_ifindex; char *ifname; char *kind; unsigned short iftype; diff -Naurp systemd-239-orig/src/network/networkd-manager.c systemd-239/src/network/networkd-manager.c --- systemd-239-orig/src/network/networkd-manager.c 2018-06-22 06:11:49.000000000 -0500 +++ systemd-239/src/network/networkd-manager.c 2018-11-04 08:49:10.229692718 -0600 @@ -150,7 +150,7 @@ int manager_connect_bus(Manager *m) { if (r < 0) return log_error_errno(r, "Failed to add network enumerator: %m"); - r = bus_request_name_async_may_reload_dbus(m->bus, NULL, "org.freedesktop.network1", 0, NULL); + r = sd_bus_request_name_async(m->bus, NULL, "org.freedesktop.network1", 0, NULL, NULL); if (r < 0) return log_error_errno(r, "Failed to request name: %m"); @@ -1462,12 +1462,12 @@ void manager_free(Manager *m) { while ((pool = m->address_pools)) address_pool_free(pool); - set_free(m->rules); - set_free(m->rules_foreign); - + set_free_with_destructor(m->rules, routing_policy_rule_free); + set_free_with_destructor(m->rules_foreign, routing_policy_rule_free); set_free_with_destructor(m->rules_saved, routing_policy_rule_free); sd_netlink_unref(m->rtnl); + sd_netlink_unref(m->genl); sd_event_unref(m->event); sd_resolve_unref(m->resolve); @@ -1757,7 +1757,7 @@ int manager_set_hostname(Manager *m, con return log_oom(); if (!m->bus || sd_bus_is_ready(m->bus) <= 0) { - log_info("Not connected to system bus, not setting hostname."); + log_debug("Not connected to system bus, setting hostname later."); return 0; } @@ -1805,7 +1805,7 @@ int manager_set_timezone(Manager *m, con return log_oom(); if (!m->bus || sd_bus_is_ready(m->bus) <= 0) { - log_info("Not connected to system bus, not setting timezone."); + log_debug("Not connected to system bus, setting timezone later."); return 0; } diff -Naurp systemd-239-orig/src/network/networkd-network.c systemd-239/src/network/networkd-network.c --- systemd-239-orig/src/network/networkd-network.c 2018-06-22 06:11:49.000000000 -0500 +++ systemd-239/src/network/networkd-network.c 2018-11-04 08:49:10.229692718 -0600 @@ -36,7 +36,12 @@ static int network_config_compare_func(c if (r != 0) return r; - return y->line - x->line; + if (x->line < y->line) + return -1; + if (x->line > y->line) + return 1; + + return 0; } const struct hash_ops network_config_hash_ops = { @@ -80,8 +85,7 @@ void network_apply_anonymize_if_set(Netw network->dhcp_client_identifier = DHCP_CLIENT_ID_MAC; /* RFC 7844 3.10: SHOULD NOT use the Vendor Class Identifier option */ - /* NOTE: it was not initiallized to any value in network_load_one. */ - network->dhcp_vendor_class_identifier = false; + network->dhcp_vendor_class_identifier = mfree(network->dhcp_vendor_class_identifier); /* RFC7844 section 3.6.: The client intending to protect its privacy SHOULD only request a minimal number of options in the PRL and SHOULD also randomly shuffle @@ -201,10 +205,6 @@ static int network_load_one(Manager *man network->dhcp_client_identifier = DHCP_CLIENT_ID_DUID; network->dhcp_route_table = RT_TABLE_MAIN; network->dhcp_route_table_set = false; - /* NOTE: the following vars were not set to any default, - * even if they are commented in the man? - * These vars might be overwriten by network_apply_anonymize_if_set */ - network->dhcp_vendor_class_identifier = false; /* NOTE: from man: UseMTU=... Defaults to false*/ network->dhcp_use_mtu = false; /* NOTE: from man: UseTimezone=... Defaults to "no".*/ @@ -281,6 +281,12 @@ static int network_load_one(Manager *man if (network->ip_masquerade) network->ip_forward |= ADDRESS_FAMILY_IPV4; + if (network->mtu > 0 && network->dhcp_use_mtu) { + log_warning("MTUBytes= in [Link] section and UseMTU= in [DHCP] section are set in %s. " + "Disabling UseMTU=.", filename); + network->dhcp_use_mtu = false; + } + LIST_PREPEND(networks, manager->networks, network); r = hashmap_ensure_allocated(&manager->networks_by_name, &string_hash_ops); diff -Naurp systemd-239-orig/src/nspawn/nspawn.c systemd-239/src/nspawn/nspawn.c --- systemd-239-orig/src/nspawn/nspawn.c 2018-06-22 06:11:49.000000000 -0500 +++ systemd-239/src/nspawn/nspawn.c 2018-11-04 08:49:10.230692717 -0600 @@ -1646,12 +1646,7 @@ static int setup_resolv_conf(const char if (arg_private_network) m = RESOLV_CONF_OFF; else if (have_resolv_conf(STATIC_RESOLV_CONF) > 0 && resolved_listening() > 0) - /* resolved is enabled on the host. In this, case bind mount its static resolv.conf file into the - * container, so that the container can use the host's resolver. Given that network namespacing is - * disabled it's only natural of the container also uses the host's resolver. It also has the big - * advantage that the container will be able to follow the host's DNS server configuration changes - * transparently. */ - m = RESOLV_CONF_BIND_STATIC; + m = arg_read_only && arg_volatile_mode != VOLATILE_YES ? RESOLV_CONF_BIND_STATIC : RESOLV_CONF_COPY_STATIC; else if (have_resolv_conf("/etc/resolv.conf") > 0) m = arg_read_only && arg_volatile_mode != VOLATILE_YES ? RESOLV_CONF_BIND_HOST : RESOLV_CONF_COPY_HOST; else @@ -1987,7 +1982,7 @@ static int setup_journal(const char *dir _cleanup_free_ char *d = NULL; const char *p, *q; bool try; - char id[33]; + char id[33], *dirname; int r; /* Don't link journals in ephemeral mode */ @@ -2011,17 +2006,15 @@ static int setup_journal(const char *dir return -EEXIST; } - r = userns_mkdir(directory, "/var", 0755, 0, 0); - if (r < 0) - return log_error_errno(r, "Failed to create /var: %m"); - - r = userns_mkdir(directory, "/var/log", 0755, 0, 0); - if (r < 0) - return log_error_errno(r, "Failed to create /var/log: %m"); - - r = userns_mkdir(directory, "/var/log/journal", 0755, 0, 0); - if (r < 0) - return log_error_errno(r, "Failed to create /var/log/journal: %m"); + FOREACH_STRING(dirname, "/var", "/var/log", "/var/log/journal") { + r = userns_mkdir(directory, dirname, 0755, 0, 0); + if (r < 0) { + bool ignore = r == -EROFS && try; + log_full_errno(ignore ? LOG_DEBUG : LOG_ERR, r, + "Failed to create %s%s: %m", dirname, ignore ? ", ignoring" : ""); + return ignore ? 0 : r; + } + } (void) sd_id128_to_string(arg_uuid, id); @@ -2746,7 +2739,18 @@ static int inner_child( exec_target = "/usr/lib/systemd/systemd, /lib/systemd/systemd, /sbin/init"; } else if (!strv_isempty(arg_parameters)) { + const char *dollar_path; + exec_target = arg_parameters[0]; + + /* Use the user supplied search $PATH if there is one, or DEFAULT_PATH_COMPAT if not to search the + * binary. */ + dollar_path = strv_env_get(env_use, "PATH"); + if (dollar_path) { + if (putenv((char*) dollar_path) != 0) + return log_error_errno(errno, "Failed to update $PATH: %m"); + } + execvpe(arg_parameters[0], arg_parameters, env_use); } else { if (!arg_chdir) @@ -2775,9 +2779,9 @@ static int setup_sd_notify_child(void) { return log_error_errno(errno, "Failed to allocate notification socket: %m"); (void) mkdir_parents(NSPAWN_NOTIFY_SOCKET_PATH, 0755); - (void) unlink(NSPAWN_NOTIFY_SOCKET_PATH); + (void) sockaddr_un_unlink(&sa.un); - strncpy(sa.un.sun_path, NSPAWN_NOTIFY_SOCKET_PATH, sizeof(sa.un.sun_path)-1); + strncpy(sa.un.sun_path, NSPAWN_NOTIFY_SOCKET_PATH, sizeof(sa.un.sun_path)); r = bind(fd, &sa.sa, SOCKADDR_UN_LEN(sa.un)); if (r < 0) { safe_close(fd); @@ -2902,7 +2906,8 @@ static int outer_child( } } - log_info("Selected user namespace base " UID_FMT " and range " UID_FMT ".", arg_uid_shift, arg_uid_range); + if (!arg_quiet) + log_info("Selected user namespace base " UID_FMT " and range " UID_FMT ".", arg_uid_shift, arg_uid_range); } if (dissected_image) { diff -Naurp systemd-239-orig/src/nspawn/nspawn-cgroup.c systemd-239/src/nspawn/nspawn-cgroup.c --- systemd-239-orig/src/nspawn/nspawn-cgroup.c 2018-06-22 06:11:49.000000000 -0500 +++ systemd-239/src/nspawn/nspawn-cgroup.c 2018-11-04 08:49:10.230692717 -0600 @@ -55,7 +55,7 @@ int chown_cgroup(pid_t pid, CGroupUnifie if (r < 0) return log_error_errno(r, "Failed to chown() cgroup %s: %m", fs); - if (unified_requested == CGROUP_UNIFIED_SYSTEMD) { + if (unified_requested == CGROUP_UNIFIED_SYSTEMD || (unified_requested == CGROUP_UNIFIED_NONE && cg_unified_controller(SYSTEMD_CGROUP_CONTROLLER) > 0)) { _cleanup_free_ char *lfs = NULL; /* Always propagate access rights from unified to legacy controller */ diff -Naurp systemd-239-orig/src/nspawn/nspawn-mount.c systemd-239/src/nspawn/nspawn-mount.c --- systemd-239-orig/src/nspawn/nspawn-mount.c 2018-06-22 06:11:49.000000000 -0500 +++ systemd-239/src/nspawn/nspawn-mount.c 2018-11-04 08:49:10.230692717 -0600 @@ -559,7 +559,7 @@ int mount_all(const char *dest, /* Then we list outer child mounts (i.e. mounts applied *before* entering user namespacing) */ { "tmpfs", "/tmp", "tmpfs", "mode=1777", MS_NOSUID|MS_NODEV|MS_STRICTATIME, MOUNT_FATAL }, - { "tmpfs", "/sys", "tmpfs", "mode=755", MS_NOSUID|MS_NOEXEC|MS_NODEV, + { "tmpfs", "/sys", "tmpfs", "mode=555", MS_NOSUID|MS_NOEXEC|MS_NODEV, MOUNT_FATAL|MOUNT_APPLY_APIVFS_NETNS }, { "sysfs", "/sys", "sysfs", NULL, MS_RDONLY|MS_NOSUID|MS_NOEXEC|MS_NODEV, MOUNT_FATAL|MOUNT_APPLY_APIVFS_RO }, /* skipped if above was mounted */ diff -Naurp systemd-239-orig/src/nss-myhostname/nss-myhostname.c systemd-239/src/nss-myhostname/nss-myhostname.c --- systemd-239-orig/src/nss-myhostname/nss-myhostname.c 2018-06-22 06:11:49.000000000 -0500 +++ systemd-239/src/nss-myhostname/nss-myhostname.c 2018-11-04 08:49:10.230692717 -0600 @@ -45,6 +45,7 @@ enum nss_status _nss_myhostname_gethostb char *r_name; unsigned n; + PROTECT_ERRNO; BLOCK_SIGNALS(NSS_SIGNALS_BLOCK); assert(name); @@ -64,7 +65,6 @@ enum nss_status _nss_myhostname_gethostb n_addresses = local_gateways(NULL, 0, AF_UNSPEC, &addresses); if (n_addresses <= 0) { - *errnop = ENOENT; *h_errnop = HOST_NOT_FOUND; return NSS_STATUS_NOTFOUND; } @@ -81,7 +81,6 @@ enum nss_status _nss_myhostname_gethostb /* We respond to our local host name, our hostname suffixed with a single dot. */ if (!streq(name, hn) && !streq_ptr(startswith(name, hn), ".")) { - *errnop = ENOENT; *h_errnop = HOST_NOT_FOUND; return NSS_STATUS_NOTFOUND; } @@ -157,8 +156,8 @@ enum nss_status _nss_myhostname_gethostb if (ttlp) *ttlp = 0; - /* Explicitly reset all error variables */ - *errnop = 0; + /* Explicitly reset both *h_errnop and h_errno to work around + * https://bugzilla.redhat.com/show_bug.cgi?id=1125975 */ *h_errnop = NETDB_SUCCESS; h_errno = 0; @@ -286,8 +285,8 @@ static enum nss_status fill_in_hostent( if (canonp) *canonp = r_name; - /* Explicitly reset all error variables */ - *errnop = 0; + /* Explicitly reset both *h_errnop and h_errno to work around + * https://bugzilla.redhat.com/show_bug.cgi?id=1125975 */ *h_errnop = NETDB_SUCCESS; h_errno = 0; @@ -309,6 +308,7 @@ enum nss_status _nss_myhostname_gethostb uint32_t local_address_ipv4 = 0; int n_addresses = 0; + PROTECT_ERRNO; BLOCK_SIGNALS(NSS_SIGNALS_BLOCK); assert(name); @@ -334,7 +334,6 @@ enum nss_status _nss_myhostname_gethostb n_addresses = local_gateways(NULL, 0, af, &addresses); if (n_addresses <= 0) { - *errnop = ENOENT; *h_errnop = HOST_NOT_FOUND; return NSS_STATUS_NOTFOUND; } @@ -350,7 +349,6 @@ enum nss_status _nss_myhostname_gethostb } if (!streq(name, hn) && !streq_ptr(startswith(name, hn), ".")) { - *errnop = ENOENT; *h_errnop = HOST_NOT_FOUND; return NSS_STATUS_NOTFOUND; } @@ -393,6 +391,7 @@ enum nss_status _nss_myhostname_gethostb bool additional_from_hostname = false; unsigned n; + PROTECT_ERRNO; BLOCK_SIGNALS(NSS_SIGNALS_BLOCK); assert(addr); @@ -455,7 +454,6 @@ enum nss_status _nss_myhostname_gethostb } } - *errnop = ENOENT; *h_errnop = HOST_NOT_FOUND; return NSS_STATUS_NOTFOUND; diff -Naurp systemd-239-orig/src/nss-mymachines/nss-mymachines.c systemd-239/src/nss-mymachines/nss-mymachines.c --- systemd-239-orig/src/nss-mymachines/nss-mymachines.c 2018-06-22 06:11:49.000000000 -0500 +++ systemd-239/src/nss-mymachines/nss-mymachines.c 2018-11-04 08:49:10.230692717 -0600 @@ -80,6 +80,7 @@ enum nss_status _nss_mymachines_gethostb char *r_name; int n_ifindices, r; + PROTECT_ERRNO; BLOCK_SIGNALS(NSS_SIGNALS_BLOCK); assert(name); @@ -126,7 +127,6 @@ enum nss_status _nss_mymachines_gethostb goto fail; if (c <= 0) { - *errnop = ESRCH; *h_errnop = HOST_NOT_FOUND; return NSS_STATUS_NOTFOUND; } @@ -200,8 +200,8 @@ enum nss_status _nss_mymachines_gethostb if (ttlp) *ttlp = 0; - /* Explicitly reset all error variables */ - *errnop = 0; + /* Explicitly reset both *h_errnop and h_errno to work around + * https://bugzilla.redhat.com/show_bug.cgi?id=1125975 */ *h_errnop = NETDB_SUCCESS; h_errno = 0; @@ -230,6 +230,7 @@ enum nss_status _nss_mymachines_gethostb size_t l, idx, ms, alen; int r; + PROTECT_ERRNO; BLOCK_SIGNALS(NSS_SIGNALS_BLOCK); assert(name); @@ -278,7 +279,6 @@ enum nss_status _nss_mymachines_gethostb goto fail; if (c <= 0) { - *errnop = ENOENT; *h_errnop = HOST_NOT_FOUND; return NSS_STATUS_NOTFOUND; } @@ -364,8 +364,8 @@ enum nss_status _nss_mymachines_gethostb if (canonp) *canonp = r_name; - /* Explicitly reset all error variables */ - *errnop = 0; + /* Explicitly reset both *h_errnop and h_errno to work around + * https://bugzilla.redhat.com/show_bug.cgi?id=1125975 */ *h_errnop = NETDB_SUCCESS; h_errno = 0; @@ -394,6 +394,7 @@ enum nss_status _nss_mymachines_getpwnam size_t l; int r; + PROTECT_ERRNO; BLOCK_SIGNALS(NSS_SIGNALS_BLOCK); assert(name); @@ -401,28 +402,28 @@ enum nss_status _nss_mymachines_getpwnam p = startswith(name, "vu-"); if (!p) - goto not_found; + return NSS_STATUS_NOTFOUND; e = strrchr(p, '-'); if (!e || e == p) - goto not_found; + return NSS_STATUS_NOTFOUND; if (e - p > HOST_NAME_MAX - 1) /* -1 for the last dash */ - goto not_found; + return NSS_STATUS_NOTFOUND; r = parse_uid(e + 1, &uid); if (r < 0) - goto not_found; + return NSS_STATUS_NOTFOUND; machine = strndupa(p, e - p); if (!machine_name_is_valid(machine)) - goto not_found; + return NSS_STATUS_NOTFOUND; if (getenv_bool_secure("SYSTEMD_NSS_BYPASS_BUS") > 0) /* Make sure we can't deadlock if we are invoked by dbus-daemon. This way, it won't be able to resolve * these UIDs, but that should be unproblematic as containers should never be able to connect to a bus * running on the host. */ - goto not_found; + return NSS_STATUS_NOTFOUND; r = sd_bus_open_system(&bus); if (r < 0) @@ -439,7 +440,7 @@ enum nss_status _nss_mymachines_getpwnam machine, (uint32_t) uid); if (r < 0) { if (sd_bus_error_has_name(&error, BUS_ERROR_NO_SUCH_USER_MAPPING)) - goto not_found; + return NSS_STATUS_NOTFOUND; goto fail; } @@ -450,7 +451,7 @@ enum nss_status _nss_mymachines_getpwnam /* Refuse to work if the mapped address is in the host UID range, or if there was no mapping at all. */ if (mapped < HOST_UID_LIMIT || mapped == uid) - goto not_found; + return NSS_STATUS_NOTFOUND; l = strlen(name); if (buflen < l+1) { @@ -468,13 +469,8 @@ enum nss_status _nss_mymachines_getpwnam pwd->pw_dir = (char*) "/"; pwd->pw_shell = (char*) "/sbin/nologin"; - *errnop = 0; return NSS_STATUS_SUCCESS; -not_found: - *errnop = 0; - return NSS_STATUS_NOTFOUND; - fail: *errnop = -r; return NSS_STATUS_UNAVAIL; @@ -493,17 +489,18 @@ enum nss_status _nss_mymachines_getpwuid uint32_t mapped; int r; + PROTECT_ERRNO; BLOCK_SIGNALS(NSS_SIGNALS_BLOCK); if (!uid_is_valid(uid)) - goto not_found; + return NSS_STATUS_NOTFOUND; /* We consider all uids < 65536 host uids */ if (uid < HOST_UID_LIMIT) - goto not_found; + return NSS_STATUS_NOTFOUND; if (getenv_bool_secure("SYSTEMD_NSS_BYPASS_BUS") > 0) - goto not_found; + return NSS_STATUS_NOTFOUND; r = sd_bus_open_system(&bus); if (r < 0) @@ -520,7 +517,7 @@ enum nss_status _nss_mymachines_getpwuid (uint32_t) uid); if (r < 0) { if (sd_bus_error_has_name(&error, BUS_ERROR_NO_SUCH_USER_MAPPING)) - goto not_found; + return NSS_STATUS_NOTFOUND; goto fail; } @@ -530,7 +527,7 @@ enum nss_status _nss_mymachines_getpwuid goto fail; if (mapped == uid) - goto not_found; + return NSS_STATUS_NOTFOUND; if (snprintf(buffer, buflen, "vu-%s-" UID_FMT, machine, (uid_t) mapped) >= (int) buflen) { *errnop = ERANGE; @@ -545,13 +542,8 @@ enum nss_status _nss_mymachines_getpwuid pwd->pw_dir = (char*) "/"; pwd->pw_shell = (char*) "/sbin/nologin"; - *errnop = 0; return NSS_STATUS_SUCCESS; -not_found: - *errnop = 0; - return NSS_STATUS_NOTFOUND; - fail: *errnop = -r; return NSS_STATUS_UNAVAIL; @@ -574,6 +566,7 @@ enum nss_status _nss_mymachines_getgrnam size_t l; int r; + PROTECT_ERRNO; BLOCK_SIGNALS(NSS_SIGNALS_BLOCK); assert(name); @@ -581,25 +574,25 @@ enum nss_status _nss_mymachines_getgrnam p = startswith(name, "vg-"); if (!p) - goto not_found; + return NSS_STATUS_NOTFOUND; e = strrchr(p, '-'); if (!e || e == p) - goto not_found; + return NSS_STATUS_NOTFOUND; if (e - p > HOST_NAME_MAX - 1) /* -1 for the last dash */ - goto not_found; + return NSS_STATUS_NOTFOUND; r = parse_gid(e + 1, &gid); if (r < 0) - goto not_found; + return NSS_STATUS_NOTFOUND; machine = strndupa(p, e - p); if (!machine_name_is_valid(machine)) - goto not_found; + return NSS_STATUS_NOTFOUND; if (getenv_bool_secure("SYSTEMD_NSS_BYPASS_BUS") > 0) - goto not_found; + return NSS_STATUS_NOTFOUND; r = sd_bus_open_system(&bus); if (r < 0) @@ -616,7 +609,7 @@ enum nss_status _nss_mymachines_getgrnam machine, (uint32_t) gid); if (r < 0) { if (sd_bus_error_has_name(&error, BUS_ERROR_NO_SUCH_GROUP_MAPPING)) - goto not_found; + return NSS_STATUS_NOTFOUND; goto fail; } @@ -626,7 +619,7 @@ enum nss_status _nss_mymachines_getgrnam goto fail; if (mapped < HOST_GID_LIMIT || mapped == gid) - goto not_found; + return NSS_STATUS_NOTFOUND; l = sizeof(char*) + strlen(name) + 1; if (buflen < l) { @@ -642,13 +635,8 @@ enum nss_status _nss_mymachines_getgrnam gr->gr_passwd = (char*) "*"; /* locked */ gr->gr_mem = (char**) buffer; - *errnop = 0; return NSS_STATUS_SUCCESS; -not_found: - *errnop = 0; - return NSS_STATUS_NOTFOUND; - fail: *errnop = -r; return NSS_STATUS_UNAVAIL; @@ -667,17 +655,18 @@ enum nss_status _nss_mymachines_getgrgid uint32_t mapped; int r; + PROTECT_ERRNO; BLOCK_SIGNALS(NSS_SIGNALS_BLOCK); if (!gid_is_valid(gid)) - goto not_found; + return NSS_STATUS_NOTFOUND; /* We consider all gids < 65536 host gids */ if (gid < HOST_GID_LIMIT) - goto not_found; + return NSS_STATUS_NOTFOUND; if (getenv_bool_secure("SYSTEMD_NSS_BYPASS_BUS") > 0) - goto not_found; + return NSS_STATUS_NOTFOUND; r = sd_bus_open_system(&bus); if (r < 0) @@ -694,7 +683,7 @@ enum nss_status _nss_mymachines_getgrgid (uint32_t) gid); if (r < 0) { if (sd_bus_error_has_name(&error, BUS_ERROR_NO_SUCH_GROUP_MAPPING)) - goto not_found; + return NSS_STATUS_NOTFOUND; goto fail; } @@ -704,7 +693,7 @@ enum nss_status _nss_mymachines_getgrgid goto fail; if (mapped == gid) - goto not_found; + return NSS_STATUS_NOTFOUND; if (buflen < sizeof(char*) + 1) { *errnop = ERANGE; @@ -722,13 +711,8 @@ enum nss_status _nss_mymachines_getgrgid gr->gr_passwd = (char*) "*"; /* locked */ gr->gr_mem = (char**) buffer; - *errnop = 0; return NSS_STATUS_SUCCESS; -not_found: - *errnop = 0; - return NSS_STATUS_NOTFOUND; - fail: *errnop = -r; return NSS_STATUS_UNAVAIL; diff -Naurp systemd-239-orig/src/nss-resolve/nss-resolve.c systemd-239/src/nss-resolve/nss-resolve.c --- systemd-239-orig/src/nss-resolve/nss-resolve.c 2018-06-22 06:11:49.000000000 -0500 +++ systemd-239/src/nss-resolve/nss-resolve.c 2018-11-04 08:49:10.230692717 -0600 @@ -108,6 +108,7 @@ enum nss_status _nss_resolve_gethostbyna char *r_name; int c, r, i = 0; + PROTECT_ERRNO; BLOCK_SIGNALS(NSS_SIGNALS_BLOCK); assert(name); @@ -140,20 +141,15 @@ enum nss_status _nss_resolve_gethostbyna r = sd_bus_call(bus, req, SD_RESOLVED_QUERY_TIMEOUT_USEC, &error, &reply); if (r < 0) { - if (sd_bus_error_has_name(&error, _BUS_ERROR_DNS "NXDOMAIN")) { - *errnop = ESRCH; - *h_errnop = HOST_NOT_FOUND; - return NSS_STATUS_NOTFOUND; - } + if (sd_bus_error_has_name(&error, _BUS_ERROR_DNS "NXDOMAIN") || + !bus_error_shall_fallback(&error)) + goto not_found; /* Return NSS_STATUS_UNAVAIL when communication with systemd-resolved fails, allowing falling back to other nss modules. Treat all other error conditions as NOTFOUND. This includes DNSSEC errors and suchlike. (We don't use UNAVAIL in this case so that the nsswitch.conf configuration can distuingish such executed but negative replies from complete failure to talk to resolved). */ - if (!bus_error_shall_fallback(&error)) - ret = NSS_STATUS_NOTFOUND; - goto fail; } @@ -162,11 +158,8 @@ enum nss_status _nss_resolve_gethostbyna r = c; goto fail; } - if (c == 0) { - *errnop = ESRCH; - *h_errnop = HOST_NOT_FOUND; - return NSS_STATUS_NOTFOUND; - } + if (c == 0) + goto not_found; if (isempty(canonical)) canonical = name; @@ -247,8 +240,8 @@ enum nss_status _nss_resolve_gethostbyna if (ttlp) *ttlp = 0; - /* Explicitly reset all error variables */ - *errnop = 0; + /* Explicitly reset both *h_errnop and h_errno to work around + * https://bugzilla.redhat.com/show_bug.cgi?id=1125975 */ *h_errnop = NETDB_SUCCESS; h_errno = 0; @@ -258,6 +251,10 @@ fail: *errnop = -r; *h_errnop = NO_RECOVERY; return ret; + +not_found: + *h_errnop = HOST_NOT_FOUND; + return NSS_STATUS_NOTFOUND; } enum nss_status _nss_resolve_gethostbyname3_r( @@ -278,6 +275,7 @@ enum nss_status _nss_resolve_gethostbyna const char *canonical; int c, r, i = 0; + PROTECT_ERRNO; BLOCK_SIGNALS(NSS_SIGNALS_BLOCK); assert(name); @@ -318,14 +316,9 @@ enum nss_status _nss_resolve_gethostbyna r = sd_bus_call(bus, req, SD_RESOLVED_QUERY_TIMEOUT_USEC, &error, &reply); if (r < 0) { - if (sd_bus_error_has_name(&error, _BUS_ERROR_DNS "NXDOMAIN")) { - *errnop = ESRCH; - *h_errnop = HOST_NOT_FOUND; - return NSS_STATUS_NOTFOUND; - } - - if (!bus_error_shall_fallback(&error)) - ret = NSS_STATUS_NOTFOUND; + if (sd_bus_error_has_name(&error, _BUS_ERROR_DNS "NXDOMAIN") || + !bus_error_shall_fallback(&error)) + goto not_found; goto fail; } @@ -335,11 +328,8 @@ enum nss_status _nss_resolve_gethostbyna r = c; goto fail; } - if (c == 0) { - *errnop = ESRCH; - *h_errnop = HOST_NOT_FOUND; - return NSS_STATUS_NOTFOUND; - } + if (c == 0) + goto not_found; if (isempty(canonical)) canonical = name; @@ -427,23 +417,27 @@ enum nss_status _nss_resolve_gethostbyna result->h_length = alen; result->h_addr_list = (char**) r_addr_list; - /* Explicitly reset all error variables */ - *errnop = 0; - *h_errnop = NETDB_SUCCESS; - h_errno = 0; - if (ttlp) *ttlp = 0; if (canonp) *canonp = r_name; + /* Explicitly reset both *h_errnop and h_errno to work around + * https://bugzilla.redhat.com/show_bug.cgi?id=1125975 */ + *h_errnop = NETDB_SUCCESS; + h_errno = 0; + return NSS_STATUS_SUCCESS; fail: *errnop = -r; *h_errnop = NO_RECOVERY; return ret; + +not_found: + *h_errnop = HOST_NOT_FOUND; + return NSS_STATUS_NOTFOUND; } enum nss_status _nss_resolve_gethostbyaddr2_r( @@ -464,6 +458,7 @@ enum nss_status _nss_resolve_gethostbyad const char *n; int r, ifindex; + PROTECT_ERRNO; BLOCK_SIGNALS(NSS_SIGNALS_BLOCK); assert(addr); @@ -516,14 +511,9 @@ enum nss_status _nss_resolve_gethostbyad r = sd_bus_call(bus, req, SD_RESOLVED_QUERY_TIMEOUT_USEC, &error, &reply); if (r < 0) { - if (sd_bus_error_has_name(&error, _BUS_ERROR_DNS "NXDOMAIN")) { - *errnop = ESRCH; - *h_errnop = HOST_NOT_FOUND; - return NSS_STATUS_NOTFOUND; - } - - if (!bus_error_shall_fallback(&error)) - ret = NSS_STATUS_NOTFOUND; + if (sd_bus_error_has_name(&error, _BUS_ERROR_DNS "NXDOMAIN") || + !bus_error_shall_fallback(&error)) + goto not_found; goto fail; } @@ -549,11 +539,8 @@ enum nss_status _nss_resolve_gethostbyad if (r < 0) return r; - if (c <= 0) { - *errnop = ESRCH; - *h_errnop = HOST_NOT_FOUND; - return NSS_STATUS_NOTFOUND; - } + if (c <= 0) + goto not_found; ms += ALIGN(len) + /* the address */ 2 * sizeof(char*) + /* pointers to the address, plus trailing NULL */ @@ -612,8 +599,8 @@ enum nss_status _nss_resolve_gethostbyad if (ttlp) *ttlp = 0; - /* Explicitly reset all error variables */ - *errnop = 0; + /* Explicitly reset both *h_errnop and h_errno to work around + * https://bugzilla.redhat.com/show_bug.cgi?id=1125975 */ *h_errnop = NETDB_SUCCESS; h_errno = 0; @@ -623,6 +610,10 @@ fail: *errnop = -r; *h_errnop = NO_RECOVERY; return ret; + +not_found: + *h_errnop = HOST_NOT_FOUND; + return NSS_STATUS_NOTFOUND; } NSS_GETHOSTBYNAME_FALLBACKS(resolve); diff -Naurp systemd-239-orig/src/nss-systemd/nss-systemd.c systemd-239/src/nss-systemd/nss-systemd.c --- systemd-239-orig/src/nss-systemd/nss-systemd.c 2018-06-22 06:11:49.000000000 -0500 +++ systemd-239/src/nss-systemd/nss-systemd.c 2018-11-04 08:49:10.230692717 -0600 @@ -145,6 +145,7 @@ enum nss_status _nss_systemd_getpwnam_r( size_t l; int bypass, r; + PROTECT_ERRNO; BLOCK_SIGNALS(NSS_SIGNALS_BLOCK); assert(name); @@ -153,26 +154,24 @@ enum nss_status _nss_systemd_getpwnam_r( /* If the username is not valid, then we don't know it. Ideally libc would filter these for us anyway. We don't * generate EINVAL here, because it isn't really out business to complain about invalid user names. */ if (!valid_user_group_name(name)) - goto not_found; + return NSS_STATUS_NOTFOUND; /* Synthesize entries for the root and nobody users, in case they are missing in /etc/passwd */ if (getenv_bool_secure("SYSTEMD_NSS_BYPASS_SYNTHETIC") <= 0) { if (streq(name, root_passwd.pw_name)) { *pwd = root_passwd; - *errnop = 0; return NSS_STATUS_SUCCESS; } if (synthesize_nobody() && streq(name, nobody_passwd.pw_name)) { *pwd = nobody_passwd; - *errnop = 0; return NSS_STATUS_SUCCESS; } } /* Make sure that we don't go in circles when allocating a dynamic UID by checking our own database */ if (getenv_bool_secure("SYSTEMD_NSS_DYNAMIC_BYPASS") > 0) - goto not_found; + return NSS_STATUS_NOTFOUND; bypass = getenv_bool_secure("SYSTEMD_NSS_BYPASS_BUS"); if (bypass <= 0) { @@ -184,7 +183,7 @@ enum nss_status _nss_systemd_getpwnam_r( if (bypass > 0) { r = direct_lookup_name(name, (uid_t*) &translated); if (r == -ENOENT) - goto not_found; + return NSS_STATUS_NOTFOUND; if (r < 0) goto fail; } else { @@ -199,7 +198,7 @@ enum nss_status _nss_systemd_getpwnam_r( name); if (r < 0) { if (sd_bus_error_has_name(&error, BUS_ERROR_NO_SUCH_DYNAMIC_USER)) - goto not_found; + return NSS_STATUS_NOTFOUND; goto fail; } @@ -225,13 +224,8 @@ enum nss_status _nss_systemd_getpwnam_r( pwd->pw_dir = (char*) DYNAMIC_USER_DIR; pwd->pw_shell = (char*) DYNAMIC_USER_SHELL; - *errnop = 0; return NSS_STATUS_SUCCESS; -not_found: - *errnop = 0; - return NSS_STATUS_NOTFOUND; - fail: *errnop = -r; return NSS_STATUS_UNAVAIL; @@ -251,31 +245,30 @@ enum nss_status _nss_systemd_getpwuid_r( size_t l; int bypass, r; + PROTECT_ERRNO; BLOCK_SIGNALS(NSS_SIGNALS_BLOCK); if (!uid_is_valid(uid)) - goto not_found; + return NSS_STATUS_NOTFOUND; /* Synthesize data for the root user and for nobody in case they are missing from /etc/passwd */ if (getenv_bool_secure("SYSTEMD_NSS_BYPASS_SYNTHETIC") <= 0) { if (uid == root_passwd.pw_uid) { *pwd = root_passwd; - *errnop = 0; return NSS_STATUS_SUCCESS; } if (synthesize_nobody() && uid == nobody_passwd.pw_uid) { *pwd = nobody_passwd; - *errnop = 0; return NSS_STATUS_SUCCESS; } } if (!uid_is_dynamic(uid)) - goto not_found; + return NSS_STATUS_NOTFOUND; if (getenv_bool_secure("SYSTEMD_NSS_DYNAMIC_BYPASS") > 0) - goto not_found; + return NSS_STATUS_NOTFOUND; bypass = getenv_bool_secure("SYSTEMD_NSS_BYPASS_BUS"); if (bypass <= 0) { @@ -287,7 +280,7 @@ enum nss_status _nss_systemd_getpwuid_r( if (bypass > 0) { r = direct_lookup_uid(uid, &direct); if (r == -ENOENT) - goto not_found; + return NSS_STATUS_NOTFOUND; if (r < 0) goto fail; @@ -305,7 +298,7 @@ enum nss_status _nss_systemd_getpwuid_r( (uint32_t) uid); if (r < 0) { if (sd_bus_error_has_name(&error, BUS_ERROR_NO_SUCH_DYNAMIC_USER)) - goto not_found; + return NSS_STATUS_NOTFOUND; goto fail; } @@ -331,13 +324,8 @@ enum nss_status _nss_systemd_getpwuid_r( pwd->pw_dir = (char*) DYNAMIC_USER_DIR; pwd->pw_shell = (char*) DYNAMIC_USER_SHELL; - *errnop = 0; return NSS_STATUS_SUCCESS; -not_found: - *errnop = 0; - return NSS_STATUS_NOTFOUND; - fail: *errnop = -r; return NSS_STATUS_UNAVAIL; @@ -358,31 +346,30 @@ enum nss_status _nss_systemd_getgrnam_r( size_t l; int bypass, r; + PROTECT_ERRNO; BLOCK_SIGNALS(NSS_SIGNALS_BLOCK); assert(name); assert(gr); if (!valid_user_group_name(name)) - goto not_found; + return NSS_STATUS_NOTFOUND; /* Synthesize records for root and nobody, in case they are missing form /etc/group */ if (getenv_bool_secure("SYSTEMD_NSS_BYPASS_SYNTHETIC") <= 0) { if (streq(name, root_group.gr_name)) { *gr = root_group; - *errnop = 0; return NSS_STATUS_SUCCESS; } if (synthesize_nobody() && streq(name, nobody_group.gr_name)) { *gr = nobody_group; - *errnop = 0; return NSS_STATUS_SUCCESS; } } if (getenv_bool_secure("SYSTEMD_NSS_DYNAMIC_BYPASS") > 0) - goto not_found; + return NSS_STATUS_NOTFOUND; bypass = getenv_bool_secure("SYSTEMD_NSS_BYPASS_BUS"); if (bypass <= 0) { @@ -394,7 +381,7 @@ enum nss_status _nss_systemd_getgrnam_r( if (bypass > 0) { r = direct_lookup_name(name, (uid_t*) &translated); if (r == -ENOENT) - goto not_found; + return NSS_STATUS_NOTFOUND; if (r < 0) goto fail; } else { @@ -409,7 +396,7 @@ enum nss_status _nss_systemd_getgrnam_r( name); if (r < 0) { if (sd_bus_error_has_name(&error, BUS_ERROR_NO_SUCH_DYNAMIC_USER)) - goto not_found; + return NSS_STATUS_NOTFOUND; goto fail; } @@ -433,13 +420,8 @@ enum nss_status _nss_systemd_getgrnam_r( gr->gr_passwd = (char*) DYNAMIC_USER_PASSWD; gr->gr_mem = (char**) buffer; - *errnop = 0; return NSS_STATUS_SUCCESS; -not_found: - *errnop = 0; - return NSS_STATUS_NOTFOUND; - fail: *errnop = -r; return NSS_STATUS_UNAVAIL; @@ -459,31 +441,30 @@ enum nss_status _nss_systemd_getgrgid_r( size_t l; int bypass, r; + PROTECT_ERRNO; BLOCK_SIGNALS(NSS_SIGNALS_BLOCK); if (!gid_is_valid(gid)) - goto not_found; + return NSS_STATUS_NOTFOUND; /* Synthesize records for root and nobody, in case they are missing from /etc/group */ if (getenv_bool_secure("SYSTEMD_NSS_BYPASS_SYNTHETIC") <= 0) { if (gid == root_group.gr_gid) { *gr = root_group; - *errnop = 0; return NSS_STATUS_SUCCESS; } if (synthesize_nobody() && gid == nobody_group.gr_gid) { *gr = nobody_group; - *errnop = 0; return NSS_STATUS_SUCCESS; } } if (!gid_is_dynamic(gid)) - goto not_found; + return NSS_STATUS_NOTFOUND; if (getenv_bool_secure("SYSTEMD_NSS_DYNAMIC_BYPASS") > 0) - goto not_found; + return NSS_STATUS_NOTFOUND; bypass = getenv_bool_secure("SYSTEMD_NSS_BYPASS_BUS"); if (bypass <= 0) { @@ -495,7 +476,7 @@ enum nss_status _nss_systemd_getgrgid_r( if (bypass > 0) { r = direct_lookup_uid(gid, &direct); if (r == -ENOENT) - goto not_found; + return NSS_STATUS_NOTFOUND; if (r < 0) goto fail; @@ -513,7 +494,7 @@ enum nss_status _nss_systemd_getgrgid_r( (uint32_t) gid); if (r < 0) { if (sd_bus_error_has_name(&error, BUS_ERROR_NO_SUCH_DYNAMIC_USER)) - goto not_found; + return NSS_STATUS_NOTFOUND; goto fail; } @@ -537,13 +518,8 @@ enum nss_status _nss_systemd_getgrgid_r( gr->gr_passwd = (char*) DYNAMIC_USER_PASSWD; gr->gr_mem = (char**) buffer; - *errnop = 0; return NSS_STATUS_SUCCESS; -not_found: - *errnop = 0; - return NSS_STATUS_NOTFOUND; - fail: *errnop = -r; return NSS_STATUS_UNAVAIL; @@ -598,6 +574,7 @@ static void systemd_endent(GetentData *d } static enum nss_status nss_systemd_endent(GetentData *p) { + PROTECT_ERRNO; BLOCK_SIGNALS(NSS_SIGNALS_BLOCK); assert_se(pthread_mutex_lock(&p->mutex) == 0); @@ -668,6 +645,7 @@ static enum nss_status systemd_setent(Ge uid_t id; int bypass, r; + PROTECT_ERRNO; BLOCK_SIGNALS(NSS_SIGNALS_BLOCK); assert(p); @@ -750,6 +728,7 @@ enum nss_status _nss_systemd_getpwent_r( UserEntry *p; size_t len; + PROTECT_ERRNO; BLOCK_SIGNALS(NSS_SIGNALS_BLOCK); assert(result); @@ -778,7 +757,6 @@ enum nss_status _nss_systemd_getpwent_r( break; } if (!p) { - *errnop = ENOENT; ret = NSS_STATUS_NOTFOUND; goto finalize; } @@ -801,6 +779,7 @@ enum nss_status _nss_systemd_getgrent_r( UserEntry *p; size_t len; + PROTECT_ERRNO; BLOCK_SIGNALS(NSS_SIGNALS_BLOCK); assert(result); @@ -827,7 +806,6 @@ enum nss_status _nss_systemd_getgrent_r( break; } if (!p) { - *errnop = ENOENT; ret = NSS_STATUS_NOTFOUND; goto finalize; } diff -Naurp systemd-239-orig/src/portable/portable.c systemd-239/src/portable/portable.c --- systemd-239-orig/src/portable/portable.c 2018-06-22 06:11:49.000000000 -0500 +++ systemd-239/src/portable/portable.c 2018-11-04 08:49:10.231692717 -0600 @@ -782,7 +782,7 @@ static int install_profile_dropin( r = find_profile(profile, m->name, &from); if (r < 0) { - if (r != ENOENT) + if (r != -ENOENT) return log_debug_errno(errno, "Profile '%s' is not accessible: %m", profile); log_debug_errno(errno, "Skipping link to profile '%s', as it does not exist: %m", profile); diff -Naurp systemd-239-orig/src/resolve/resolvconf-compat.c systemd-239/src/resolve/resolvconf-compat.c --- systemd-239-orig/src/resolve/resolvconf-compat.c 2018-06-22 06:11:49.000000000 -0500 +++ systemd-239/src/resolve/resolvconf-compat.c 2018-11-04 08:49:10.231692717 -0600 @@ -53,6 +53,8 @@ static int parse_nameserver(const char * if (strv_push(&arg_set_dns, word) < 0) return log_oom(); + + word = NULL; } return 0; @@ -107,7 +109,6 @@ int resolvconf_parse_argv(int argc, char TYPE_EXCLUSIVE, /* -x */ } type = TYPE_REGULAR; - const char *dot, *iface; int c, r; assert(argc >= 0); @@ -200,30 +201,11 @@ int resolvconf_parse_argv(int argc, char return -EINVAL; } - dot = strchr(argv[optind], '.'); - if (dot) { - iface = strndupa(argv[optind], dot - argv[optind]); - log_debug("Ignoring protocol specifier '%s'.", dot + 1); - } else - iface = argv[optind]; - optind++; - - if (parse_ifindex(iface, &arg_ifindex) < 0) { - int ifi; - - ifi = if_nametoindex(iface); - if (ifi <= 0) { - if (errno == ENODEV && arg_ifindex_permissive) { - log_debug("Interface '%s' not found, but -f specified, ignoring.", iface); - return 0; /* done */ - } + r = ifname_mangle(argv[optind], false); + if (r <= 0) + return r; - return log_error_errno(errno, "Unknown interface '%s': %m", iface); - } - - arg_ifindex = ifi; - arg_ifname = iface; - } + optind++; if (arg_mode == MODE_SET_LINK) { unsigned n = 0; diff -Naurp systemd-239-orig/src/resolve/resolvectl.c systemd-239/src/resolve/resolvectl.c --- systemd-239-orig/src/resolve/resolvectl.c 2018-06-22 06:11:49.000000000 -0500 +++ systemd-239/src/resolve/resolvectl.c 2018-11-04 08:49:10.231692717 -0600 @@ -28,8 +28,8 @@ #include "verbs.h" static int arg_family = AF_UNSPEC; -int arg_ifindex = 0; -const char *arg_ifname = NULL; +static int arg_ifindex = 0; +static char *arg_ifname = NULL; static uint16_t arg_type = 0; static uint16_t arg_class = 0; static bool arg_legend = true; @@ -66,7 +66,7 @@ typedef enum StatusMode { STATUS_NTA, } StatusMode; -static int parse_ifindex_with_warn(const char *s) { +static int parse_ifindex_and_warn(const char *s) { int ifi; assert(s); @@ -74,12 +74,66 @@ static int parse_ifindex_with_warn(const if (parse_ifindex(s, &ifi) < 0) { ifi = if_nametoindex(s); if (ifi <= 0) - return log_error_errno(errno, "Unknown interface %s: %m", s); + return log_error_errno(errno, "Unknown interface '%s': %m", s); } return ifi; } +int ifname_mangle(const char *s, bool allow_loopback) { + _cleanup_free_ char *iface = NULL; + const char *dot; + int r; + + assert(s); + + if (arg_ifname) { + assert(arg_ifindex >= 0); + + if (!allow_loopback && arg_ifindex == LOOPBACK_IFINDEX) { + log_error("Interface can't be the loopback interface (lo). Sorry."); + return -EINVAL; + } + + return 1; + } + + dot = strchr(s, '.'); + if (dot) { + iface = strndup(s, dot - s); + if (!iface) + return log_oom(); + + log_debug("Ignoring protocol specifier '%s'.", dot + 1); + } else { + iface = strdup(s); + if (!iface) + return log_oom(); + } + + if (parse_ifindex(iface, &r) < 0) { + r = if_nametoindex(iface); + if (r <= 0) { + if (errno == ENODEV && arg_ifindex_permissive) { + log_debug("Interface '%s' not found, but -f specified, ignoring.", iface); + return 0; /* done */ + } + + return log_error_errno(errno, "Unknown interface '%s': %m", iface); + } + } + + if (!allow_loopback && r == LOOPBACK_IFINDEX) { + log_error("Interface can't be the loopback interface (lo). Sorry."); + return -EINVAL; + } + + arg_ifindex = r; + arg_ifname = TAKE_PTR(iface); + + return 1; +} + static void print_source(uint64_t flags, usec_t rtt) { char rtt_str[FORMAT_TIMESTAMP_MAX]; @@ -113,18 +167,14 @@ static int resolve_host(sd_bus *bus, con _cleanup_(sd_bus_message_unrefp) sd_bus_message *req = NULL, *reply = NULL; _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; const char *canonical = NULL; - char ifname[IF_NAMESIZE] = ""; unsigned c = 0; - int r; uint64_t flags; usec_t ts; + int r; assert(name); - if (arg_ifindex > 0 && !if_indextoname(arg_ifindex, ifname)) - return log_error_errno(errno, "Failed to resolve interface name for index %i: %m", arg_ifindex); - - log_debug("Resolving %s (family %s, interface %s).", name, af_to_name(arg_family) ?: "*", isempty(ifname) ? "*" : ifname); + log_debug("Resolving %s (family %s, interface %s).", name, af_to_name(arg_family) ?: "*", isempty(arg_ifname) ? "*" : arg_ifname); r = sd_bus_message_new_method_call( bus, @@ -154,6 +204,7 @@ static int resolve_host(sd_bus *bus, con while ((r = sd_bus_message_enter_container(reply, 'r', "iiay")) > 0) { _cleanup_free_ char *pretty = NULL; + char ifname[IF_NAMESIZE] = ""; int ifindex, family; const void *a; size_t sz; @@ -182,7 +233,6 @@ static int resolve_host(sd_bus *bus, con return -EINVAL; } - ifname[0] = 0; if (ifindex > 0 && !if_indextoname(ifindex, ifname)) log_warning_errno(errno, "Failed to resolve interface name for index %i: %m", ifindex); @@ -379,7 +429,6 @@ static int output_rr_packet(const void * static int resolve_record(sd_bus *bus, const char *name, uint16_t class, uint16_t type, bool warn_missing) { _cleanup_(sd_bus_message_unrefp) sd_bus_message *req = NULL, *reply = NULL; _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; - char ifname[IF_NAMESIZE] = ""; unsigned n = 0; uint64_t flags; int r; @@ -388,10 +437,7 @@ static int resolve_record(sd_bus *bus, c assert(name); - if (arg_ifindex > 0 && !if_indextoname(arg_ifindex, ifname)) - return log_error_errno(errno, "Failed to resolve interface name for index %i: %m", arg_ifindex); - - log_debug("Resolving %s %s %s (interface %s).", name, dns_class_to_string(class), dns_type_to_string(type), isempty(ifname) ? "*" : ifname); + log_debug("Resolving %s %s %s (interface %s).", name, dns_class_to_string(class), dns_type_to_string(type), isempty(arg_ifname) ? "*" : arg_ifname); r = sd_bus_message_new_method_call( bus, @@ -645,7 +691,6 @@ static int resolve_service(sd_bus *bus, const char *canonical_name, *canonical_type, *canonical_domain; _cleanup_(sd_bus_message_unrefp) sd_bus_message *req = NULL, *reply = NULL; _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; - char ifname[IF_NAMESIZE] = ""; size_t indent, sz; uint64_t flags; const char *p; @@ -659,15 +704,12 @@ static int resolve_service(sd_bus *bus, name = empty_to_null(name); type = empty_to_null(type); - if (arg_ifindex > 0 && !if_indextoname(arg_ifindex, ifname)) - return log_error_errno(errno, "Failed to resolve interface name for index %i: %m", arg_ifindex); - if (name) - log_debug("Resolving service \"%s\" of type %s in %s (family %s, interface %s).", name, type, domain, af_to_name(arg_family) ?: "*", isempty(ifname) ? "*" : ifname); + log_debug("Resolving service \"%s\" of type %s in %s (family %s, interface %s).", name, type, domain, af_to_name(arg_family) ?: "*", isempty(arg_ifname) ? "*" : arg_ifname); else if (type) - log_debug("Resolving service type %s of %s (family %s, interface %s).", type, domain, af_to_name(arg_family) ?: "*", isempty(ifname) ? "*" : ifname); + log_debug("Resolving service type %s of %s (family %s, interface %s).", type, domain, af_to_name(arg_family) ?: "*", isempty(arg_ifname) ? "*" : arg_ifname); else - log_debug("Resolving service type %s (family %s, interface %s).", domain, af_to_name(arg_family) ?: "*", isempty(ifname) ? "*" : ifname); + log_debug("Resolving service type %s (family %s, interface %s).", domain, af_to_name(arg_family) ?: "*", isempty(arg_ifname) ? "*" : arg_ifname); r = sd_bus_message_new_method_call( bus, @@ -726,6 +768,7 @@ static int resolve_service(sd_bus *bus, while ((r = sd_bus_message_enter_container(reply, 'r', "iiay")) > 0) { _cleanup_free_ char *pretty = NULL; + char ifname[IF_NAMESIZE] = ""; int ifindex, family; const void *a; @@ -753,7 +796,6 @@ static int resolve_service(sd_bus *bus, return -EINVAL; } - ifname[0] = 0; if (ifindex > 0 && !if_indextoname(ifindex, ifname)) log_warning_errno(errno, "Failed to resolve interface name for index %i: %m", ifindex); @@ -1828,7 +1870,7 @@ static int verb_status(int argc, char ** STRV_FOREACH(ifname, argv + 1) { int ifindex; - ifindex = parse_ifindex_with_warn(*ifname); + ifindex = parse_ifindex_and_warn(*ifname); if (ifindex < 0) continue; @@ -1855,25 +1897,20 @@ static int verb_dns(int argc, char **arg _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; _cleanup_(sd_bus_message_unrefp) sd_bus_message *req = NULL; sd_bus *bus = userdata; - int ifindex, r; char **p; + int r; assert(bus); if (argc <= 1) return status_all(bus, STATUS_DNS); - ifindex = parse_ifindex_with_warn(argv[1]); - if (ifindex < 0) - return ifindex; - - if (ifindex == LOOPBACK_IFINDEX) { - log_error("Interface can't be the loopback interface (lo). Sorry."); - return -EINVAL; - } + r = ifname_mangle(argv[1], false); + if (r < 0) + return r; if (argc == 2) - return status_ifindex(bus, ifindex, NULL, STATUS_DNS, NULL); + return status_ifindex(bus, arg_ifindex, NULL, STATUS_DNS, NULL); r = sd_bus_message_new_method_call( bus, @@ -1885,7 +1922,7 @@ static int verb_dns(int argc, char **arg if (r < 0) return bus_log_create_error(r); - r = sd_bus_message_append(req, "i", ifindex); + r = sd_bus_message_append(req, "i", arg_ifindex); if (r < 0) return bus_log_create_error(r); @@ -1924,7 +1961,7 @@ static int verb_dns(int argc, char **arg r = sd_bus_call(bus, req, 0, &error, NULL); if (r < 0) { if (sd_bus_error_has_name(&error, BUS_ERROR_LINK_BUSY)) - return log_interface_is_managed(r, ifindex); + return log_interface_is_managed(r, arg_ifindex); if (arg_ifindex_permissive && sd_bus_error_has_name(&error, BUS_ERROR_NO_SUCH_LINK)) @@ -1940,25 +1977,20 @@ static int verb_domain(int argc, char ** _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; _cleanup_(sd_bus_message_unrefp) sd_bus_message *req = NULL; sd_bus *bus = userdata; - int ifindex, r; char **p; + int r; assert(bus); if (argc <= 1) return status_all(bus, STATUS_DOMAIN); - ifindex = parse_ifindex_with_warn(argv[1]); - if (ifindex < 0) - return ifindex; - - if (ifindex == LOOPBACK_IFINDEX) { - log_error("Interface can't be the loopback interface (lo). Sorry."); - return -EINVAL; - } + r = ifname_mangle(argv[1], false); + if (r < 0) + return r; if (argc == 2) - return status_ifindex(bus, ifindex, NULL, STATUS_DOMAIN, NULL); + return status_ifindex(bus, arg_ifindex, NULL, STATUS_DOMAIN, NULL); r = sd_bus_message_new_method_call( bus, @@ -1970,7 +2002,7 @@ static int verb_domain(int argc, char ** if (r < 0) return bus_log_create_error(r); - r = sd_bus_message_append(req, "i", ifindex); + r = sd_bus_message_append(req, "i", arg_ifindex); if (r < 0) return bus_log_create_error(r); @@ -2003,7 +2035,7 @@ static int verb_domain(int argc, char ** r = sd_bus_call(bus, req, 0, &error, NULL); if (r < 0) { if (sd_bus_error_has_name(&error, BUS_ERROR_LINK_BUSY)) - return log_interface_is_managed(r, ifindex); + return log_interface_is_managed(r, arg_ifindex); if (arg_ifindex_permissive && sd_bus_error_has_name(&error, BUS_ERROR_NO_SUCH_LINK)) @@ -2018,24 +2050,19 @@ static int verb_domain(int argc, char ** static int verb_llmnr(int argc, char **argv, void *userdata) { _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; sd_bus *bus = userdata; - int ifindex, r; + int r; assert(bus); if (argc <= 1) return status_all(bus, STATUS_LLMNR); - ifindex = parse_ifindex_with_warn(argv[1]); - if (ifindex < 0) - return ifindex; - - if (ifindex == LOOPBACK_IFINDEX) { - log_error("Interface can't be the loopback interface (lo). Sorry."); - return -EINVAL; - } + r = ifname_mangle(argv[1], false); + if (r < 0) + return r; if (argc == 2) - return status_ifindex(bus, ifindex, NULL, STATUS_LLMNR, NULL); + return status_ifindex(bus, arg_ifindex, NULL, STATUS_LLMNR, NULL); r = sd_bus_call_method(bus, "org.freedesktop.resolve1", @@ -2044,10 +2071,10 @@ static int verb_llmnr(int argc, char **a "SetLinkLLMNR", &error, NULL, - "is", ifindex, argv[2]); + "is", arg_ifindex, argv[2]); if (r < 0) { if (sd_bus_error_has_name(&error, BUS_ERROR_LINK_BUSY)) - return log_interface_is_managed(r, ifindex); + return log_interface_is_managed(r, arg_ifindex); if (arg_ifindex_permissive && sd_bus_error_has_name(&error, BUS_ERROR_NO_SUCH_LINK)) @@ -2062,24 +2089,19 @@ static int verb_llmnr(int argc, char **a static int verb_mdns(int argc, char **argv, void *userdata) { _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; sd_bus *bus = userdata; - int ifindex, r; + int r; assert(bus); if (argc <= 1) return status_all(bus, STATUS_MDNS); - ifindex = parse_ifindex_with_warn(argv[1]); - if (ifindex < 0) - return ifindex; - - if (ifindex == LOOPBACK_IFINDEX) { - log_error("Interface can't be the loopback interface (lo). Sorry."); - return -EINVAL; - } + r = ifname_mangle(argv[1], false); + if (r < 0) + return r; if (argc == 2) - return status_ifindex(bus, ifindex, NULL, STATUS_MDNS, NULL); + return status_ifindex(bus, arg_ifindex, NULL, STATUS_MDNS, NULL); r = sd_bus_call_method(bus, "org.freedesktop.resolve1", @@ -2088,10 +2110,10 @@ static int verb_mdns(int argc, char **ar "SetLinkMulticastDNS", &error, NULL, - "is", ifindex, argv[2]); + "is", arg_ifindex, argv[2]); if (r < 0) { if (sd_bus_error_has_name(&error, BUS_ERROR_LINK_BUSY)) - return log_interface_is_managed(r, ifindex); + return log_interface_is_managed(r, arg_ifindex); if (arg_ifindex_permissive && sd_bus_error_has_name(&error, BUS_ERROR_NO_SUCH_LINK)) @@ -2106,24 +2128,19 @@ static int verb_mdns(int argc, char **ar static int verb_dns_over_tls(int argc, char **argv, void *userdata) { _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; sd_bus *bus = userdata; - int ifindex, r; + int r; assert(bus); if (argc <= 1) return status_all(bus, STATUS_PRIVATE); - ifindex = parse_ifindex_with_warn(argv[1]); - if (ifindex < 0) - return ifindex; - - if (ifindex == LOOPBACK_IFINDEX) { - log_error("Interface can't be the loopback interface (lo). Sorry."); - return -EINVAL; - } + r = ifname_mangle(argv[1], false); + if (r < 0) + return r; if (argc == 2) - return status_ifindex(bus, ifindex, NULL, STATUS_PRIVATE, NULL); + return status_ifindex(bus, arg_ifindex, NULL, STATUS_PRIVATE, NULL); r = sd_bus_call_method(bus, "org.freedesktop.resolve1", @@ -2132,10 +2149,10 @@ static int verb_dns_over_tls(int argc, c "SetLinkDNSOverTLS", &error, NULL, - "is", ifindex, argv[2]); + "is", arg_ifindex, argv[2]); if (r < 0) { if (sd_bus_error_has_name(&error, BUS_ERROR_LINK_BUSY)) - return log_interface_is_managed(r, ifindex); + return log_interface_is_managed(r, arg_ifindex); if (arg_ifindex_permissive && sd_bus_error_has_name(&error, BUS_ERROR_NO_SUCH_LINK)) @@ -2150,24 +2167,19 @@ static int verb_dns_over_tls(int argc, c static int verb_dnssec(int argc, char **argv, void *userdata) { _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; sd_bus *bus = userdata; - int ifindex, r; + int r; assert(bus); if (argc <= 1) return status_all(bus, STATUS_DNSSEC); - ifindex = parse_ifindex_with_warn(argv[1]); - if (ifindex < 0) - return ifindex; - - if (ifindex == LOOPBACK_IFINDEX) { - log_error("Interface can't be the loopback interface (lo). Sorry."); - return -EINVAL; - } + r = ifname_mangle(argv[1], false); + if (r < 0) + return r; if (argc == 2) - return status_ifindex(bus, ifindex, NULL, STATUS_DNSSEC, NULL); + return status_ifindex(bus, arg_ifindex, NULL, STATUS_DNSSEC, NULL); r = sd_bus_call_method(bus, "org.freedesktop.resolve1", @@ -2176,10 +2188,10 @@ static int verb_dnssec(int argc, char ** "SetLinkDNSSEC", &error, NULL, - "is", ifindex, argv[2]); + "is", arg_ifindex, argv[2]); if (r < 0) { if (sd_bus_error_has_name(&error, BUS_ERROR_LINK_BUSY)) - return log_interface_is_managed(r, ifindex); + return log_interface_is_managed(r, arg_ifindex); if (arg_ifindex_permissive && sd_bus_error_has_name(&error, BUS_ERROR_NO_SUCH_LINK)) @@ -2195,31 +2207,27 @@ static int verb_nta(int argc, char **arg _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; _cleanup_(sd_bus_message_unrefp) sd_bus_message *req = NULL; sd_bus *bus = userdata; - int ifindex, i, r; + char **p; + int r; assert(bus); if (argc <= 1) return status_all(bus, STATUS_NTA); - ifindex = parse_ifindex_with_warn(argv[1]); - if (ifindex < 0) - return ifindex; - - if (ifindex == LOOPBACK_IFINDEX) { - log_error("Interface can't be the loopback interface (lo). Sorry."); - return -EINVAL; - } + r = ifname_mangle(argv[1], false); + if (r < 0) + return r; if (argc == 2) - return status_ifindex(bus, ifindex, NULL, STATUS_NTA, NULL); + return status_ifindex(bus, arg_ifindex, NULL, STATUS_NTA, NULL); - for (i = 2; i < argc; i++) { - r = dns_name_is_valid(argv[i]); + STRV_FOREACH(p, argv + 2) { + r = dns_name_is_valid(*p); if (r < 0) - return log_error_errno(r, "Failed to validate specified domain %s: %m", argv[i]); + return log_error_errno(r, "Failed to validate specified domain %s: %m", *p); if (r == 0) { - log_error("Domain not valid: %s", argv[i]); + log_error("Domain not valid: %s", *p); return -EINVAL; } } @@ -2234,7 +2242,7 @@ static int verb_nta(int argc, char **arg if (r < 0) return bus_log_create_error(r); - r = sd_bus_message_append(req, "i", ifindex); + r = sd_bus_message_append(req, "i", arg_ifindex); if (r < 0) return bus_log_create_error(r); @@ -2245,7 +2253,7 @@ static int verb_nta(int argc, char **arg r = sd_bus_call(bus, req, 0, &error, NULL); if (r < 0) { if (sd_bus_error_has_name(&error, BUS_ERROR_LINK_BUSY)) - return log_interface_is_managed(r, ifindex); + return log_interface_is_managed(r, arg_ifindex); if (arg_ifindex_permissive && sd_bus_error_has_name(&error, BUS_ERROR_NO_SUCH_LINK)) @@ -2260,18 +2268,13 @@ static int verb_nta(int argc, char **arg static int verb_revert_link(int argc, char **argv, void *userdata) { _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; sd_bus *bus = userdata; - int ifindex, r; + int r; assert(bus); - ifindex = parse_ifindex_with_warn(argv[1]); - if (ifindex < 0) - return ifindex; - - if (ifindex == LOOPBACK_IFINDEX) { - log_error("Interface can't be the loopback interface (lo). Sorry."); - return -EINVAL; - } + r = ifname_mangle(argv[1], false); + if (r < 0) + return r; r = sd_bus_call_method(bus, "org.freedesktop.resolve1", @@ -2280,7 +2283,7 @@ static int verb_revert_link(int argc, ch "RevertLink", &error, NULL, - "i", ifindex); + "i", arg_ifindex); if (r < 0) { if (arg_ifindex_permissive && sd_bus_error_has_name(&error, BUS_ERROR_NO_SUCH_LINK)) @@ -2490,12 +2493,10 @@ static int compat_parse_argv(int argc, c break; case 'i': - r = parse_ifindex_with_warn(optarg); + arg_ifname = mfree(arg_ifname); + r = ifname_mangle(optarg, true); if (r < 0) return r; - - arg_ifname = optarg; - arg_ifindex = r; break; case 't': @@ -2792,11 +2793,10 @@ static int native_parse_argv(int argc, c break; case 'i': - r = parse_ifindex_with_warn(optarg); + arg_ifname = mfree(arg_ifname); + r = ifname_mangle(optarg, true); if (r < 0) return r; - - arg_ifindex = r; break; case 't': @@ -3015,6 +3015,8 @@ static int compat_main(int argc, char *a return translate("status", NULL, argc - optind, argv + optind, bus); case MODE_SET_LINK: + assert(arg_ifname); + if (arg_set_dns) { r = translate("dns", arg_ifname, strv_length(arg_set_dns), arg_set_dns, bus); if (r < 0) @@ -3060,6 +3062,8 @@ static int compat_main(int argc, char *a return r; case MODE_REVERT_LINK: + assert(arg_ifname); + return translate("revert", arg_ifname, 0, NULL, bus); case _MODE_INVALID: @@ -3092,7 +3096,7 @@ int main(int argc, char **argv) { goto finish; } - if (streq(program_invocation_short_name, "systemd-resolve")) + if (STR_IN_SET(program_invocation_short_name, "systemd-resolve", "resolvconf")) r = compat_main(argc, argv, bus); else r = native_main(argc, argv, bus); @@ -3103,6 +3107,7 @@ finish: sd_bus_flush_close_unref(bus); pager_close(); + free(arg_ifname); strv_free(arg_set_dns); strv_free(arg_set_domain); strv_free(arg_set_nta); diff -Naurp systemd-239-orig/src/resolve/resolvectl.h systemd-239/src/resolve/resolvectl.h --- systemd-239-orig/src/resolve/resolvectl.h 2018-06-22 06:11:49.000000000 -0500 +++ systemd-239/src/resolve/resolvectl.h 2018-11-04 08:49:10.231692717 -0600 @@ -4,10 +4,6 @@ #include #include -extern int arg_ifindex; -extern const char *arg_ifname; -extern bool arg_ifindex_permissive; - typedef enum ExecutionMode { MODE_RESOLVE_HOST, MODE_RESOLVE_RECORD, @@ -25,6 +21,8 @@ typedef enum ExecutionMode { } ExecutionMode; extern ExecutionMode arg_mode; - extern char **arg_set_dns; extern char **arg_set_domain; +extern bool arg_ifindex_permissive; + +int ifname_mangle(const char *s, bool allow_loopback); diff -Naurp systemd-239-orig/src/resolve/resolved-bus.c systemd-239/src/resolve/resolved-bus.c --- systemd-239-orig/src/resolve/resolved-bus.c 2018-06-22 06:11:49.000000000 -0500 +++ systemd-239/src/resolve/resolved-bus.c 2018-11-04 08:49:10.231692717 -0600 @@ -1920,7 +1920,7 @@ int manager_connect_bus(Manager *m) { if (r < 0) return log_error_errno(r, "Failed to register dnssd enumerator: %m"); - r = bus_request_name_async_may_reload_dbus(m->bus, NULL, "org.freedesktop.resolve1", 0, NULL); + r = sd_bus_request_name_async(m->bus, NULL, "org.freedesktop.resolve1", 0, NULL, NULL); if (r < 0) return log_error_errno(r, "Failed to request name: %m"); diff -Naurp systemd-239-orig/src/resolve/resolved-dns-answer.c systemd-239/src/resolve/resolved-dns-answer.c --- systemd-239-orig/src/resolve/resolved-dns-answer.c 2018-06-22 06:11:49.000000000 -0500 +++ systemd-239/src/resolve/resolved-dns-answer.c 2018-11-04 08:49:10.231692717 -0600 @@ -799,7 +799,7 @@ void dns_answer_dump(DnsAnswer *answer, } } -bool dns_answer_has_dname_for_cname(DnsAnswer *a, DnsResourceRecord *cname) { +int dns_answer_has_dname_for_cname(DnsAnswer *a, DnsResourceRecord *cname) { DnsResourceRecord *rr; int r; @@ -830,7 +830,6 @@ bool dns_answer_has_dname_for_cname(DnsA return r; if (r > 0) return 1; - } return 0; diff -Naurp systemd-239-orig/src/resolve/resolved-dns-answer.h systemd-239/src/resolve/resolved-dns-answer.h --- systemd-239-orig/src/resolve/resolved-dns-answer.h 2018-06-22 06:11:49.000000000 -0500 +++ systemd-239/src/resolve/resolved-dns-answer.h 2018-11-04 08:49:10.231692717 -0600 @@ -65,7 +65,7 @@ int dns_answer_remove_by_rr(DnsAnswer ** int dns_answer_copy_by_key(DnsAnswer **a, DnsAnswer *source, const DnsResourceKey *key, DnsAnswerFlags or_flags); int dns_answer_move_by_key(DnsAnswer **to, DnsAnswer **from, const DnsResourceKey *key, DnsAnswerFlags or_flags); -bool dns_answer_has_dname_for_cname(DnsAnswer *a, DnsResourceRecord *cname); +int dns_answer_has_dname_for_cname(DnsAnswer *a, DnsResourceRecord *cname); static inline size_t dns_answer_size(DnsAnswer *a) { return a ? a->n_rrs : 0; diff -Naurp systemd-239-orig/src/resolve/resolved-dns-cache.c systemd-239/src/resolve/resolved-dns-cache.c --- systemd-239-orig/src/resolve/resolved-dns-cache.c 2018-06-22 06:11:49.000000000 -0500 +++ systemd-239/src/resolve/resolved-dns-cache.c 2018-11-04 08:49:10.231692717 -0600 @@ -792,7 +792,7 @@ static DnsCacheItem *dns_cache_get_by_ke if (dns_type_may_redirect(k->type)) { /* Check if we have a CNAME record instead */ i = hashmap_get(c->by_key, &DNS_RESOURCE_KEY_CONST(k->class, DNS_TYPE_CNAME, n)); - if (i) + if (i && i->type != DNS_CACHE_NODATA) return i; /* OK, let's look for cached DNAME records. */ @@ -801,7 +801,7 @@ static DnsCacheItem *dns_cache_get_by_ke return NULL; i = hashmap_get(c->by_key, &DNS_RESOURCE_KEY_CONST(k->class, DNS_TYPE_DNAME, n)); - if (i) + if (i && i->type != DNS_CACHE_NODATA) return i; /* Jump one label ahead */ diff -Naurp systemd-239-orig/src/resolve/resolved-dns-packet.c systemd-239/src/resolve/resolved-dns-packet.c --- systemd-239-orig/src/resolve/resolved-dns-packet.c 2018-06-22 06:11:49.000000000 -0500 +++ systemd-239/src/resolve/resolved-dns-packet.c 2018-11-04 08:49:10.231692717 -0600 @@ -854,7 +854,9 @@ int dns_packet_append_rr(DnsPacket *p, c if (r < 0) goto fail; - r = dns_packet_append_name(p, rr->srv.name, true, false, NULL); + /* RFC 2782 states "Unless and until permitted by future standards + * action, name compression is not to be used for this field." */ + r = dns_packet_append_name(p, rr->srv.name, false, false, NULL); break; case DNS_TYPE_PTR: diff -Naurp systemd-239-orig/src/resolve/resolved-dns-scope.c systemd-239/src/resolve/resolved-dns-scope.c --- systemd-239-orig/src/resolve/resolved-dns-scope.c 2018-06-22 06:11:49.000000000 -0500 +++ systemd-239/src/resolve/resolved-dns-scope.c 2018-11-04 08:49:10.232692716 -0600 @@ -324,36 +324,54 @@ static int dns_scope_socket( ifindex = dns_server_ifindex(server); - sa.sa.sa_family = server->family; - if (server->family == AF_INET) { - sa.in.sin_port = htobe16(port); - sa.in.sin_addr = server->address.in; + switch (server->family) { + case AF_INET: + sa = (union sockaddr_union) { + .in.sin_family = server->family, + .in.sin_port = htobe16(port), + .in.sin_addr = server->address.in, + }; salen = sizeof(sa.in); - } else if (server->family == AF_INET6) { - sa.in6.sin6_port = htobe16(port); - sa.in6.sin6_addr = server->address.in6; - sa.in6.sin6_scope_id = ifindex; + break; + case AF_INET6: + sa = (union sockaddr_union) { + .in6.sin6_family = server->family, + .in6.sin6_port = htobe16(port), + .in6.sin6_addr = server->address.in6, + .in6.sin6_scope_id = ifindex, + }; salen = sizeof(sa.in6); - } else + break; + default: return -EAFNOSUPPORT; + } } else { assert(family != AF_UNSPEC); assert(address); - sa.sa.sa_family = family; ifindex = s->link ? s->link->ifindex : 0; - if (family == AF_INET) { - sa.in.sin_port = htobe16(port); - sa.in.sin_addr = address->in; + switch (family) { + case AF_INET: + sa = (union sockaddr_union) { + .in.sin_family = family, + .in.sin_port = htobe16(port), + .in.sin_addr = address->in, + }; salen = sizeof(sa.in); - } else if (family == AF_INET6) { - sa.in6.sin6_port = htobe16(port); - sa.in6.sin6_addr = address->in6; - sa.in6.sin6_scope_id = ifindex; + break; + case AF_INET6: + sa = (union sockaddr_union) { + .in6.sin6_family = family, + .in6.sin6_port = htobe16(port), + .in6.sin6_addr = address->in6, + .in6.sin6_scope_id = ifindex, + }; salen = sizeof(sa.in6); - } else + break; + default: return -EAFNOSUPPORT; + } } fd = socket(sa.sa.sa_family, type|SOCK_CLOEXEC|SOCK_NONBLOCK, 0); @@ -394,6 +412,13 @@ static int dns_scope_socket( } } + if (type == SOCK_DGRAM) { + /* Set IP_RECVERR or IPV6_RECVERR to get ICMP error feedback. See discussion in #10345. */ + r = setsockopt(fd, SOL_IP, sa.sa.sa_family == AF_INET ? IP_RECVERR : IPV6_RECVERR, &one, sizeof(one)); + if (r < 0) + return -errno; + } + if (ret_socket_address) *ret_socket_address = sa; else { diff -Naurp systemd-239-orig/src/resolve/resolved-dnssd.c systemd-239/src/resolve/resolved-dnssd.c --- systemd-239-orig/src/resolve/resolved-dnssd.c 2018-06-22 06:11:49.000000000 -0500 +++ systemd-239/src/resolve/resolved-dnssd.c 2018-11-04 08:49:10.232692716 -0600 @@ -11,7 +11,7 @@ const char* const dnssd_service_dirs[] = "/etc/systemd/dnssd", "/run/systemd/dnssd", "/usr/lib/systemd/dnssd", -#ifdef HAVE_SPLIT_USR +#if HAVE_SPLIT_USR "/lib/systemd/dnssd", #endif NULL diff -Naurp systemd-239-orig/src/resolve/resolved-dns-stream.c systemd-239/src/resolve/resolved-dns-stream.c --- systemd-239-orig/src/resolve/resolved-dns-stream.c 2018-06-22 06:11:49.000000000 -0500 +++ systemd-239/src/resolve/resolved-dns-stream.c 2018-11-04 08:49:10.232692716 -0600 @@ -449,8 +449,8 @@ static int on_stream_io(sd_event_source (uint8_t*) DNS_PACKET_DATA(s->read_packet) + s->n_read - sizeof(s->read_size), sizeof(s->read_size) + be16toh(s->read_size) - s->n_read); if (ss < 0) { - if (!IN_SET(errno, EINTR, EAGAIN)) - return dns_stream_complete(s, errno); + if (!IN_SET(-ss, EINTR, EAGAIN)) + return dns_stream_complete(s, -ss); } else if (ss == 0) return dns_stream_complete(s, ECONNRESET); else diff -Naurp systemd-239-orig/src/resolve/resolved-dns-transaction.c systemd-239/src/resolve/resolved-dns-transaction.c --- systemd-239-orig/src/resolve/resolved-dns-transaction.c 2018-06-22 06:11:49.000000000 -0500 +++ systemd-239/src/resolve/resolved-dns-transaction.c 2018-11-04 08:49:10.232692716 -0600 @@ -518,12 +518,13 @@ static int on_stream_connection(DnsStrea } static int on_stream_complete(DnsStream *s, int error) { + _cleanup_(dns_stream_unrefp) DnsStream *p = NULL; DnsTransaction *t, *n; int r = 0; /* Do not let new transactions use this stream */ if (s->server && s->server->stream == s) - s->server->stream = dns_stream_unref(s->server->stream); + p = TAKE_PTR(s->server->stream); if (ERRNO_IS_DISCONNECT(error) && s->protocol != DNS_PROTOCOL_LLMNR) { usec_t usec; @@ -1380,10 +1381,7 @@ static int dns_transaction_prepare(DnsTr dns_transaction_stop_timeout(t); - r = dns_scope_network_good(t->scope); - if (r < 0) - return r; - if (r == 0) { + if (!dns_scope_network_good(t->scope)) { dns_transaction_complete(t, DNS_TRANSACTION_NETWORK_DOWN); return 0; } diff -Naurp systemd-239-orig/src/resolve/resolved-etc-hosts.c systemd-239/src/resolve/resolved-etc-hosts.c --- systemd-239-orig/src/resolve/resolved-etc-hosts.c 2018-06-22 06:11:49.000000000 -0500 +++ systemd-239/src/resolve/resolved-etc-hosts.c 2018-11-04 08:49:10.232692716 -0600 @@ -79,7 +79,7 @@ static const struct hash_ops etc_hosts_i }; static int add_item(Manager *m, int family, const union in_addr_union *address, char **names) { - + _cleanup_strv_free_ char **dummy = names; EtcHostsItem key = { .family = family, .address = *address, @@ -125,6 +125,8 @@ static int add_item(Manager *m, int fami free(item); return log_oom(); } + + dummy = NULL; } } diff -Naurp systemd-239-orig/src/resolve/resolved-manager.c systemd-239/src/resolve/resolved-manager.c --- systemd-239-orig/src/resolve/resolved-manager.c 2018-06-22 06:11:49.000000000 -0500 +++ systemd-239/src/resolve/resolved-manager.c 2018-11-04 08:49:10.232692716 -0600 @@ -1040,9 +1040,9 @@ int manager_send( log_debug("Sending %s packet with id %" PRIu16 " on interface %i/%s.", DNS_PACKET_QR(p) ? "response" : "query", DNS_PACKET_ID(p), ifindex, af_to_name(family)); if (family == AF_INET) - return manager_ipv4_send(m, fd, ifindex, &destination->in, port, &source->in, p); + return manager_ipv4_send(m, fd, ifindex, &destination->in, port, source ? &source->in : NULL, p); if (family == AF_INET6) - return manager_ipv6_send(m, fd, ifindex, &destination->in6, port, &source->in6, p); + return manager_ipv6_send(m, fd, ifindex, &destination->in6, port, source ? &source->in6 : NULL, p); return -EAFNOSUPPORT; } diff -Naurp systemd-239-orig/src/shared/bootspec.c systemd-239/src/shared/bootspec.c --- systemd-239-orig/src/shared/bootspec.c 2018-06-22 06:11:49.000000000 -0500 +++ systemd-239/src/shared/bootspec.c 2018-11-04 08:49:10.233692716 -0600 @@ -23,7 +23,8 @@ void boot_entry_free(BootEntry *entry) { assert(entry); - free(entry->filename); + free(entry->id); + free(entry->path); free(entry->title); free(entry->show_title); free(entry->version); @@ -53,8 +54,12 @@ int boot_entry_load(const char *path, Bo } b = basename(path); - tmp.filename = strndup(b, c - b); - if (!tmp.filename) + tmp.id = strndup(b, c - b); + if (!tmp.id) + return log_oom(); + + tmp.path = strdup(path); + if (!tmp.path) return log_oom(); f = fopen(path, "re"); @@ -205,7 +210,7 @@ int boot_loader_read_conf(const char *pa static int boot_entry_compare(const void *a, const void *b) { const BootEntry *aa = a, *bb = b; - return str_verscmp(aa->filename, bb->filename); + return str_verscmp(aa->id, bb->id); } int boot_entries_find(const char *dir, BootEntry **ret_entries, size_t *ret_n_entries) { @@ -302,7 +307,7 @@ static int boot_entries_uniquify(BootEnt /* Add file name to non-unique titles */ for (i = 0; i < n_entries; i++) if (arr[i]) { - r = asprintf(&s, "%s (%s)", boot_entry_title(entries + i), entries[i].filename); + r = asprintf(&s, "%s (%s)", boot_entry_title(entries + i), entries[i].id); if (r < 0) return -ENOMEM; @@ -319,30 +324,30 @@ static int boot_entries_select_default(c if (config->entry_oneshot) for (i = config->n_entries - 1; i >= 0; i--) - if (streq(config->entry_oneshot, config->entries[i].filename)) { - log_debug("Found default: filename \"%s\" is matched by LoaderEntryOneShot", - config->entries[i].filename); + if (streq(config->entry_oneshot, config->entries[i].id)) { + log_debug("Found default: id \"%s\" is matched by LoaderEntryOneShot", + config->entries[i].id); return i; } if (config->entry_default) for (i = config->n_entries - 1; i >= 0; i--) - if (streq(config->entry_default, config->entries[i].filename)) { - log_debug("Found default: filename \"%s\" is matched by LoaderEntryDefault", - config->entries[i].filename); + if (streq(config->entry_default, config->entries[i].id)) { + log_debug("Found default: id \"%s\" is matched by LoaderEntryDefault", + config->entries[i].id); return i; } if (config->default_pattern) for (i = config->n_entries - 1; i >= 0; i--) - if (fnmatch(config->default_pattern, config->entries[i].filename, FNM_CASEFOLD) == 0) { - log_debug("Found default: filename \"%s\" is matched by pattern \"%s\"", - config->entries[i].filename, config->default_pattern); + if (fnmatch(config->default_pattern, config->entries[i].id, FNM_CASEFOLD) == 0) { + log_debug("Found default: id \"%s\" is matched by pattern \"%s\"", + config->entries[i].id, config->default_pattern); return i; } if (config->n_entries > 0) - log_debug("Found default: last entry \"%s\"", config->entries[config->n_entries - 1].filename); + log_debug("Found default: last entry \"%s\"", config->entries[config->n_entries - 1].id); else log_debug("Found no default boot entry :("); @@ -600,3 +605,37 @@ found: return 0; } + +int find_default_boot_entry( + const char *esp_path, + char **esp_where, + BootConfig *config, + const BootEntry **e) { + + _cleanup_free_ char *where = NULL; + int r; + + assert(config); + assert(e); + + r = find_esp_and_warn(esp_path, false, &where, NULL, NULL, NULL, NULL); + if (r < 0) + return r; + + r = boot_entries_load_config(where, config); + if (r < 0) + return log_error_errno(r, "Failed to load bootspec config from \"%s/loader\": %m", where); + + if (config->default_entry < 0) { + log_error("No entry suitable as default, refusing to guess."); + return -ENOENT; + } + + *e = &config->entries[config->default_entry]; + log_debug("Found default boot entry in file \"%s\"", (*e)->path); + + if (esp_where) + *esp_where = TAKE_PTR(where); + + return 0; +} diff -Naurp systemd-239-orig/src/shared/bootspec.h systemd-239/src/shared/bootspec.h --- systemd-239-orig/src/shared/bootspec.h 2018-06-22 06:11:49.000000000 -0500 +++ systemd-239/src/shared/bootspec.h 2018-11-04 08:49:10.233692716 -0600 @@ -2,11 +2,15 @@ #pragma once -#include +#include +#include +#include -typedef struct BootEntry { - char *filename; +#include "sd-id128.h" +typedef struct BootEntry { + char *id; /* This is the file basename without extension */ + char *path; /* This is the full path to the file */ char *title; char *show_title; char *version; @@ -44,7 +48,9 @@ void boot_config_free(BootConfig *config int boot_entries_load_config(const char *esp_path, BootConfig *config); static inline const char* boot_entry_title(const BootEntry *entry) { - return entry->show_title ?: entry->title ?: entry->filename; + return entry->show_title ?: entry->title ?: entry->id; } int find_esp_and_warn(const char *path, bool unprivileged_mode, char **ret_path, uint32_t *ret_part, uint64_t *ret_pstart, uint64_t *ret_psize, sd_id128_t *ret_uuid); + +int find_default_boot_entry(const char *esp_path, char **esp_where, BootConfig *config, const BootEntry **e); diff -Naurp systemd-239-orig/src/shared/bus-unit-util.c systemd-239/src/shared/bus-unit-util.c --- systemd-239-orig/src/shared/bus-unit-util.c 2018-06-22 06:11:49.000000000 -0500 +++ systemd-239/src/shared/bus-unit-util.c 2018-11-04 08:49:10.233692716 -0600 @@ -634,13 +634,25 @@ static int bus_append_cgroup_property(sd return bus_log_create_error(r); } else { - r = in_addr_prefix_from_string_auto(eq, &family, &prefix, &prefixlen); - if (r < 0) - return log_error_errno(r, "Failed to parse IP address prefix: %s", eq); + for (;;) { + _cleanup_free_ char *word = NULL; - r = bus_append_ip_address_access(m, family, &prefix, prefixlen); - if (r < 0) - return bus_log_create_error(r); + r = extract_first_word(&eq, &word, NULL, 0); + if (r == 0) + break; + if (r == -ENOMEM) + return log_oom(); + if (r < 0) + return log_error_errno(r, "Failed to parse %s: %s", field, eq); + + r = in_addr_prefix_from_string_auto(word, &family, &prefix, &prefixlen); + if (r < 0) + return log_error_errno(r, "Failed to parse IP address prefix: %s", word); + + r = bus_append_ip_address_access(m, family, &prefix, prefixlen); + if (r < 0) + return bus_log_create_error(r); + } } r = sd_bus_message_close_container(m); diff -Naurp systemd-239-orig/src/shared/bus-util.c systemd-239/src/shared/bus-util.c --- systemd-239-orig/src/shared/bus-util.c 2018-06-22 06:11:49.000000000 -0500 +++ systemd-239/src/shared/bus-util.c 2018-11-04 08:49:10.233692716 -0600 @@ -937,7 +937,7 @@ int bus_message_print_all_properties( return log_oom(); r = set_put(*found_properties, name); - if (r < 0 && r != EEXIST) + if (r < 0 && r != -EEXIST) return log_oom(); } @@ -1738,7 +1738,7 @@ static void request_name_destroy_callbac assert(data); assert(data->n_ref > 0); - log_info("%s n_ref=%u", __func__, data->n_ref); + log_debug("%s n_ref=%u", __func__, data->n_ref); data->n_ref--; if (data->n_ref == 0) diff -Naurp systemd-239-orig/src/shared/dissect-image.c systemd-239/src/shared/dissect-image.c --- systemd-239-orig/src/shared/dissect-image.c 2018-06-22 06:11:49.000000000 -0500 +++ systemd-239/src/shared/dissect-image.c 2018-11-04 08:49:10.233692716 -0600 @@ -230,7 +230,7 @@ int dissect_image( .node = TAKE_PTR(n), }; - m->encrypted = streq(fstype, "crypto_LUKS"); + m->encrypted = streq_ptr(fstype, "crypto_LUKS"); *ret = TAKE_PTR(m); @@ -1113,7 +1113,7 @@ int dissected_image_decrypt_interactivel z = strv_free(z); - r = ask_password_auto("Please enter image passphrase!", NULL, "dissect", "dissect", USEC_INFINITY, 0, &z); + r = ask_password_auto("Please enter image passphrase:", NULL, "dissect", "dissect", USEC_INFINITY, 0, &z); if (r < 0) return log_error_errno(r, "Failed to query for passphrase: %m"); diff -Naurp systemd-239-orig/src/shared/efivars.c systemd-239/src/shared/efivars.c --- systemd-239-orig/src/shared/efivars.c 2018-06-22 06:11:49.000000000 -0500 +++ systemd-239/src/shared/efivars.c 2018-11-04 08:49:10.233692716 -0600 @@ -364,9 +364,13 @@ int efi_get_boot_option( if (header->path_len > 0) { uint8_t *dbuf; - size_t dnext; + size_t dnext, doff; + + doff = offsetof(struct boot_option, title) + title_size; + dbuf = buf + doff; + if (header->path_len > l - doff) + return -EINVAL; - dbuf = buf + offsetof(struct boot_option, title) + title_size; dnext = 0; while (dnext < header->path_len) { struct device_path *dpath; diff -Naurp systemd-239-orig/src/shared/enable-mempool.c systemd-239/src/shared/enable-mempool.c --- systemd-239-orig/src/shared/enable-mempool.c 1969-12-31 18:00:00.000000000 -0600 +++ systemd-239/src/shared/enable-mempool.c 2018-11-04 08:49:10.233692716 -0600 @@ -0,0 +1,5 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include "mempool.h" + +const bool mempool_use_allowed = true; diff -Naurp systemd-239-orig/src/shared/fdset.c systemd-239/src/shared/fdset.c --- systemd-239-orig/src/shared/fdset.c 2018-06-22 06:11:49.000000000 -0500 +++ systemd-239/src/shared/fdset.c 2018-11-04 08:49:10.233692716 -0600 @@ -211,13 +211,16 @@ fail: int fdset_close_others(FDSet *fds) { void *e; Iterator i; - int *a; + int *a = NULL; size_t j = 0, m; m = fdset_size(fds); - a = newa(int, m); - SET_FOREACH(e, MAKE_SET(fds), i) - a[j++] = PTR_TO_FD(e); + + if (m > 0) { + a = newa(int, m); + SET_FOREACH(e, MAKE_SET(fds), i) + a[j++] = PTR_TO_FD(e); + } assert(j == m); diff -Naurp systemd-239-orig/src/shared/firewall-util.c systemd-239/src/shared/firewall-util.c --- systemd-239-orig/src/shared/firewall-util.c 2018-06-22 06:11:49.000000000 -0500 +++ systemd-239/src/shared/firewall-util.c 2018-11-04 08:49:10.233692716 -0600 @@ -50,8 +50,14 @@ static int entry_fill_basics( entry->ip.proto = protocol; if (in_interface) { + size_t l; + + l = strlen(in_interface); + assert(l < sizeof entry->ip.iniface); + assert(l < sizeof entry->ip.iniface_mask); + strcpy(entry->ip.iniface, in_interface); - memset(entry->ip.iniface_mask, 0xFF, strlen(in_interface)+1); + memset(entry->ip.iniface_mask, 0xFF, l + 1); } if (source) { entry->ip.src = source->in; diff -Naurp systemd-239-orig/src/shared/install.c systemd-239/src/shared/install.c --- systemd-239-orig/src/shared/install.c 2018-06-22 06:11:49.000000000 -0500 +++ systemd-239/src/shared/install.c 2018-11-04 08:49:10.233692716 -0600 @@ -681,7 +681,7 @@ static int remove_marked_symlinks( return r; } -static bool is_symlink_with_known_name(const UnitFileInstallInfo *i, const char *name) { +static int is_symlink_with_known_name(const UnitFileInstallInfo *i, const char *name) { int r; if (streq(name, i->name)) @@ -1874,10 +1874,10 @@ static int install_context_apply( if (q < 0) return q; - r = install_info_traverse(scope, c, paths, i, flags, NULL); - if (r < 0) { + q = install_info_traverse(scope, c, paths, i, flags, NULL); + if (q < 0) { unit_file_changes_add(changes, n_changes, r, i->name, NULL); - return r; + return q; } /* We can attempt to process a masked unit when a different unit diff -Naurp systemd-239-orig/src/shared/logs-show.c systemd-239/src/shared/logs-show.c --- systemd-239-orig/src/shared/logs-show.c 2018-06-22 06:11:49.000000000 -0500 +++ systemd-239/src/shared/logs-show.c 2018-11-04 08:49:10.234692715 -0600 @@ -374,7 +374,7 @@ static int output_short( unsigned n_columns, OutputFlags flags, Set *output_fields, - size_t highlight[2]) { + const size_t highlight[2]) { int r; const void *data; @@ -505,7 +505,7 @@ static int output_verbose( unsigned n_columns, OutputFlags flags, Set *output_fields, - size_t highlight[2]) { + const size_t highlight[2]) { const void *data; size_t length; @@ -613,7 +613,7 @@ static int output_export( unsigned n_columns, OutputFlags flags, Set *output_fields, - size_t highlight[2]) { + const size_t highlight[2]) { sd_id128_t boot_id; char sid[33]; @@ -754,7 +754,7 @@ static int output_json( unsigned n_columns, OutputFlags flags, Set *output_fields, - size_t highlight[2]) { + const size_t highlight[2]) { uint64_t realtime, monotonic; _cleanup_free_ char *cursor = NULL; @@ -968,7 +968,7 @@ static int output_cat( unsigned n_columns, OutputFlags flags, Set *output_fields, - size_t highlight[2]) { + const size_t highlight[2]) { const void *data; size_t l; @@ -1023,7 +1023,7 @@ static int (*output_funcs[_OUTPUT_MODE_M unsigned n_columns, OutputFlags flags, Set *output_fields, - size_t highlight[2]) = { + const size_t highlight[2]) = { [OUTPUT_SHORT] = output_short, [OUTPUT_SHORT_ISO] = output_short, @@ -1048,7 +1048,7 @@ int show_journal_entry( unsigned n_columns, OutputFlags flags, char **output_fields, - size_t highlight[2], + const size_t highlight[2], bool *ellipsized) { int ret; diff -Naurp systemd-239-orig/src/shared/logs-show.h systemd-239/src/shared/logs-show.h --- systemd-239-orig/src/shared/logs-show.h 2018-06-22 06:11:49.000000000 -0500 +++ systemd-239/src/shared/logs-show.h 2018-11-04 08:49:10.234692715 -0600 @@ -20,7 +20,7 @@ int show_journal_entry( unsigned n_columns, OutputFlags flags, char **output_fields, - size_t highlight[2], + const size_t highlight[2], bool *ellipsized); int show_journal( FILE *f, diff -Naurp systemd-239-orig/src/shared/machine-pool.c systemd-239/src/shared/machine-pool.c --- systemd-239-orig/src/shared/machine-pool.c 2018-06-22 06:11:49.000000000 -0500 +++ systemd-239/src/shared/machine-pool.c 2018-11-04 08:49:10.234692715 -0600 @@ -379,14 +379,21 @@ int grow_machine_directory(void) { new_size = old_size + max_add; r = btrfs_resize_loopback("/var/lib/machines", new_size, true); - if (r <= 0) - return r; + if (r < 0) + return log_debug_errno(r, "Failed to resize loopback: %m"); + if (r == 0) + return 0; /* Also bump the quota, of both the subvolume leaf qgroup, as * well as of any subtree quota group by the same id but a * higher level, if it exists. */ - (void) btrfs_qgroup_set_limit("/var/lib/machines", 0, new_size); - (void) btrfs_subvol_set_subtree_quota_limit("/var/lib/machines", 0, new_size); + r = btrfs_qgroup_set_limit("/var/lib/machines", 0, new_size); + if (r < 0) + log_debug_errno(r, "Failed to set btrfs limit: %m"); + + r = btrfs_subvol_set_subtree_quota_limit("/var/lib/machines", 0, new_size); + if (r < 0) + log_debug_errno(r, "Failed to set btrfs subtree limit: %m"); log_info("Grew /var/lib/machines btrfs loopback file system to %s.", format_bytes(buf, sizeof(buf), new_size)); return 1; diff -Naurp systemd-239-orig/src/shared/meson.build systemd-239/src/shared/meson.build --- systemd-239-orig/src/shared/meson.build 2018-06-22 06:11:49.000000000 -0500 +++ systemd-239/src/shared/meson.build 2018-11-04 08:49:10.234692715 -0600 @@ -36,6 +36,7 @@ shared_sources = files(''' dropin.h efivars.c efivars.h + enable-mempool.c fdset.c fdset.h firewall-util.h @@ -63,6 +64,7 @@ shared_sources = files(''' machine-image.h machine-pool.c machine-pool.h + module-util.h nsflags.c nsflags.h output-mode.c @@ -123,6 +125,10 @@ if conf.get('HAVE_LIBIPTC') == 1 shared_sources += files('firewall-util.c') endif +if conf.get('HAVE_KMOD') == 1 + shared_sources += files('module-util.c') +endif + libshared_name = 'systemd-shared-@0@'.format(meson.project_version()) libshared_deps = [threads, @@ -132,6 +138,7 @@ libshared_deps = [threads, libcryptsetup, libgcrypt, libiptc, + libkmod, libseccomp, libselinux, libidn, diff -Naurp systemd-239-orig/src/shared/module-util.c systemd-239/src/shared/module-util.c --- systemd-239-orig/src/shared/module-util.c 1969-12-31 18:00:00.000000000 -0600 +++ systemd-239/src/shared/module-util.c 2018-11-04 08:49:10.234692715 -0600 @@ -0,0 +1,72 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include + +#include "module-util.h" + +int module_load_and_warn(struct kmod_ctx *ctx, const char *module, bool verbose) { + const int probe_flags = KMOD_PROBE_APPLY_BLACKLIST; + struct kmod_list *itr; + _cleanup_(kmod_module_unref_listp) struct kmod_list *modlist = NULL; + int r = 0; + + /* verbose==true means we should log at non-debug level if we + * fail to find or load the module. */ + + log_debug("Loading module: %s", module); + + r = kmod_module_new_from_lookup(ctx, module, &modlist); + if (r < 0) + return log_full_errno(verbose ? LOG_ERR : LOG_DEBUG, r, + "Failed to lookup module alias '%s': %m", module); + + if (!modlist) { + log_full_errno(verbose ? LOG_ERR : LOG_DEBUG, r, + "Failed to find module '%s'", module); + return -ENOENT; + } + + kmod_list_foreach(itr, modlist) { + _cleanup_(kmod_module_unrefp) struct kmod_module *mod = NULL; + int state, err; + + mod = kmod_module_get_module(itr); + state = kmod_module_get_initstate(mod); + + switch (state) { + case KMOD_MODULE_BUILTIN: + log_full(verbose ? LOG_INFO : LOG_DEBUG, + "Module '%s' is builtin", kmod_module_get_name(mod)); + break; + + case KMOD_MODULE_LIVE: + log_debug("Module '%s' is already loaded", kmod_module_get_name(mod)); + break; + + default: + err = kmod_module_probe_insert_module(mod, probe_flags, + NULL, NULL, NULL, NULL); + if (err == 0) + log_full(verbose ? LOG_INFO : LOG_DEBUG, + "Inserted module '%s'", kmod_module_get_name(mod)); + else if (err == KMOD_PROBE_APPLY_BLACKLIST) + log_full(verbose ? LOG_INFO : LOG_DEBUG, + "Module '%s' is blacklisted", kmod_module_get_name(mod)); + else { + assert(err < 0); + + log_full_errno(!verbose ? LOG_DEBUG : + err == -ENODEV ? LOG_NOTICE : + err == -ENOENT ? LOG_WARNING : + LOG_ERR, + err, + "Failed to insert module '%s': %m", + kmod_module_get_name(mod)); + if (!IN_SET(err, -ENODEV, -ENOENT)) + r = err; + } + } + } + + return r; +} diff -Naurp systemd-239-orig/src/shared/module-util.h systemd-239/src/shared/module-util.h --- systemd-239-orig/src/shared/module-util.h 1969-12-31 18:00:00.000000000 -0600 +++ systemd-239/src/shared/module-util.h 2018-11-04 08:49:10.234692715 -0600 @@ -0,0 +1,12 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include + +#include "macro.h" + +DEFINE_TRIVIAL_CLEANUP_FUNC(struct kmod_ctx*, kmod_unref); +DEFINE_TRIVIAL_CLEANUP_FUNC(struct kmod_module*, kmod_module_unref); +DEFINE_TRIVIAL_CLEANUP_FUNC(struct kmod_list*, kmod_module_unref_list); + +int module_load_and_warn(struct kmod_ctx *ctx, const char *module, bool verbose); diff -Naurp systemd-239-orig/src/shared/ptyfwd.c systemd-239/src/shared/ptyfwd.c --- systemd-239-orig/src/shared/ptyfwd.c 2018-06-22 06:11:49.000000000 -0500 +++ systemd-239/src/shared/ptyfwd.c 2018-11-04 08:49:10.234692715 -0600 @@ -20,6 +20,7 @@ #include "log.h" #include "macro.h" #include "ptyfwd.h" +#include "terminal-util.h" #include "time-util.h" struct PTYForward { @@ -421,8 +422,17 @@ int pty_forward_new( f->master = master; - if (ioctl(STDOUT_FILENO, TIOCGWINSZ, &ws) >= 0) - (void) ioctl(master, TIOCSWINSZ, &ws); + if (ioctl(STDOUT_FILENO, TIOCGWINSZ, &ws) < 0) { + /* If we can't get the resolution from the output fd, then use our internal, regular width/height, + * i.e. something derived from $COLUMNS and $LINES if set. */ + + ws = (struct winsize) { + .ws_row = lines(), + .ws_col = columns(), + }; + } + + (void) ioctl(master, TIOCSWINSZ, &ws); if (!(flags & PTY_FORWARD_READ_ONLY)) { if (tcgetattr(STDIN_FILENO, &f->saved_stdin_attr) >= 0) { diff -Naurp systemd-239-orig/src/shared/seccomp-util.c systemd-239/src/shared/seccomp-util.c --- systemd-239-orig/src/shared/seccomp-util.c 2018-06-22 06:11:49.000000000 -0500 +++ systemd-239/src/shared/seccomp-util.c 2018-11-04 08:49:10.234692715 -0600 @@ -651,6 +651,7 @@ const SyscallFilterSet syscall_filter_se "rt_sigqueueinfo\0" "rt_tgsigqueueinfo\0" "setns\0" + "swapcontext\0" /* Some archs e.g. powerpc32 are using it to do userspace context switches */ "tgkill\0" "times\0" "tkill\0" @@ -1056,7 +1057,15 @@ int seccomp_parse_syscall_filter_full( if (!(flags & SECCOMP_PARSE_INVERT) == !!(flags & SECCOMP_PARSE_WHITELIST)) { r = hashmap_put(filter, INT_TO_PTR(id + 1), INT_TO_PTR(errno_num)); if (r < 0) - return flags & SECCOMP_PARSE_LOG ? log_oom() : -ENOMEM; + switch (r) { + case -ENOMEM: + return flags & SECCOMP_PARSE_LOG ? log_oom() : -ENOMEM; + case -EEXIST: + assert_se(hashmap_update(filter, INT_TO_PTR(id + 1), INT_TO_PTR(errno_num)) == 0); + break; + default: + return r; + } } else (void) hashmap_remove(filter, INT_TO_PTR(id + 1)); } diff -Naurp systemd-239-orig/src/shared/sleep-config.c systemd-239/src/shared/sleep-config.c --- systemd-239-orig/src/shared/sleep-config.c 2018-06-22 06:11:49.000000000 -0500 +++ systemd-239/src/shared/sleep-config.c 2018-11-04 08:49:10.234692715 -0600 @@ -13,6 +13,7 @@ #include #include "alloc-util.h" +#include "bootspec.h" #include "conf-parser.h" #include "def.h" #include "env-util.h" @@ -21,12 +22,16 @@ #include "log.h" #include "macro.h" #include "parse-util.h" +#include "path-util.h" +#include "proc-cmdline.h" #include "sleep-config.h" #include "string-util.h" #include "strv.h" -int parse_sleep_config(const char *verb, char ***_modes, char ***_states, usec_t *_delay) { - +int parse_sleep_config(const char *verb, bool *ret_allow, char ***ret_modes, char ***ret_states, usec_t *ret_delay) { + int allow_suspend = -1, allow_hibernate = -1, + allow_s2h = -1, allow_hybrid_sleep = -1; + bool allow; _cleanup_strv_free_ char **suspend_mode = NULL, **suspend_state = NULL, **hibernate_mode = NULL, **hibernate_state = NULL, @@ -35,13 +40,19 @@ int parse_sleep_config(const char *verb, usec_t delay = 180 * USEC_PER_MINUTE; const ConfigTableItem items[] = { - { "Sleep", "SuspendMode", config_parse_strv, 0, &suspend_mode }, - { "Sleep", "SuspendState", config_parse_strv, 0, &suspend_state }, - { "Sleep", "HibernateMode", config_parse_strv, 0, &hibernate_mode }, - { "Sleep", "HibernateState", config_parse_strv, 0, &hibernate_state }, - { "Sleep", "HybridSleepMode", config_parse_strv, 0, &hybrid_mode }, - { "Sleep", "HybridSleepState", config_parse_strv, 0, &hybrid_state }, - { "Sleep", "HibernateDelaySec", config_parse_sec, 0, &delay}, + { "Sleep", "AllowSuspend", config_parse_tristate, 0, &allow_suspend }, + { "Sleep", "AllowHibernation", config_parse_tristate, 0, &allow_hibernate }, + { "Sleep", "AllowSuspendThenHibernate", config_parse_tristate, 0, &allow_s2h }, + { "Sleep", "AllowHybridSleep", config_parse_tristate, 0, &allow_hybrid_sleep }, + + { "Sleep", "SuspendMode", config_parse_strv, 0, &suspend_mode }, + { "Sleep", "SuspendState", config_parse_strv, 0, &suspend_state }, + { "Sleep", "HibernateMode", config_parse_strv, 0, &hibernate_mode }, + { "Sleep", "HibernateState", config_parse_strv, 0, &hibernate_state }, + { "Sleep", "HybridSleepMode", config_parse_strv, 0, &hybrid_mode }, + { "Sleep", "HybridSleepState", config_parse_strv, 0, &hybrid_state }, + + { "Sleep", "HibernateDelaySec", config_parse_sec, 0, &delay}, {} }; @@ -51,6 +62,8 @@ int parse_sleep_config(const char *verb, CONFIG_PARSE_WARN, NULL); if (streq(verb, "suspend")) { + allow = allow_suspend != 0; + /* empty by default */ modes = TAKE_PTR(suspend_mode); @@ -60,6 +73,8 @@ int parse_sleep_config(const char *verb, states = strv_new("mem", "standby", "freeze", NULL); } else if (streq(verb, "hibernate")) { + allow = allow_hibernate != 0; + if (hibernate_mode) modes = TAKE_PTR(hibernate_mode); else @@ -71,6 +86,9 @@ int parse_sleep_config(const char *verb, states = strv_new("disk", NULL); } else if (streq(verb, "hybrid-sleep")) { + allow = allow_hybrid_sleep > 0 || + (allow_suspend != 0 && allow_hibernate != 0); + if (hybrid_mode) modes = TAKE_PTR(hybrid_mode); else @@ -81,21 +99,26 @@ int parse_sleep_config(const char *verb, else states = strv_new("disk", NULL); - } else if (streq(verb, "suspend-then-hibernate")) + } else if (streq(verb, "suspend-then-hibernate")) { + allow = allow_s2h > 0 || + (allow_suspend != 0 && allow_hibernate != 0); + modes = states = NULL; - else + } else assert_not_reached("what verb"); if ((!modes && STR_IN_SET(verb, "hibernate", "hybrid-sleep")) || (!states && !streq(verb, "suspend-then-hibernate"))) return log_oom(); - if (_modes) - *_modes = TAKE_PTR(modes); - if (_states) - *_states = TAKE_PTR(states); - if (_delay) - *_delay = delay; + if (ret_allow) + *ret_allow = allow; + if (ret_modes) + *ret_modes = TAKE_PTR(modes); + if (ret_states) + *ret_states = TAKE_PTR(states); + if (ret_delay) + *ret_delay = delay; return 0; } @@ -193,18 +216,30 @@ int find_hibernate_location(char **devic "%zu " /* used */ "%*i\n", /* priority */ &dev_field, &type_field, &size_field, &used_field); + if (k == EOF) + break; if (k != 4) { - if (k == EOF) - break; - log_warning("Failed to parse /proc/swaps:%u", i); continue; } - if (streq(type_field, "partition") && endswith(dev_field, "\\040(deleted)")) { - log_warning("Ignoring deleted swapfile '%s'.", dev_field); - continue; + if (streq(type_field, "file")) { + + if (endswith(dev_field, "\\040(deleted)")) { + log_warning("Ignoring deleted swap file '%s'.", dev_field); + continue; + } + + } else if (streq(type_field, "partition")) { + const char *fn; + + fn = path_startswith(dev_field, "/dev/"); + if (fn && startswith(fn, "zram")) { + log_debug("Ignoring compressed RAM swap device '%s'.", dev_field); + continue; + } } + if (device) *device = TAKE_PTR(dev_field); if (type) @@ -247,12 +282,94 @@ static bool enough_swap_for_hibernation( } r = act <= (size - used) * HIBERNATION_SWAP_THRESHOLD; - log_debug("Hibernation is %spossible, Active(anon)=%llu kB, size=%zu kB, used=%zu kB, threshold=%.2g%%", - r ? "" : "im", act, size, used, 100*HIBERNATION_SWAP_THRESHOLD); + log_debug("%s swap for hibernation, Active(anon)=%llu kB, size=%zu kB, used=%zu kB, threshold=%.2g%%", + r ? "Enough" : "Not enough", act, size, used, 100*HIBERNATION_SWAP_THRESHOLD); return r; } +static int check_resume_keys(const char *key, const char *value, void *data) { + assert_se(key); + assert_se(data); + + int *resume = data; + + if (*resume == 0) + /* Exit if we already know we can't resume. */ + return 0; + + if (streq(key, "noresume")) { + log_debug("Found \"noresume\" on the kernel command line, hibernation is disabled."); + *resume = 0; + + } else if (streq(key, "resume")) { + log_debug("Found resume= option on the kernel command line, hibernation is possible."); + *resume = 1; + } + + return 0; +} + +static int resume_configured_in_options(const char *options) { + int resume = -1, r; + + /* We don't use PROC_CMDLINE_STRIP_RD_PREFIX here, so rd.resume is *not* supported. */ + r = proc_cmdline_parse_given(options, check_resume_keys, &resume, 0); + if (r < 0) + return r; + + if (resume < 0) + log_debug("Couldn't find resume= option, hibernation is disabled."); + return resume > 0; +} + +static int resume_configured(void) { + _cleanup_(boot_config_free) BootConfig config = {}; + const BootEntry *e; + int r; + + /* Check whether a valid resume= option is present. If possible, we query the boot options + * for the default kernel. If the system is not using sd-boot, fall back to checking the + * current kernel command line. This is not perfect, but should suffice for most cases. */ + + r = find_default_boot_entry(NULL, NULL, &config, &e); + if (r == -ENOKEY) + log_debug_errno(r, "Cannot find the ESP partition mount point, falling back to other checks."); + else if (r < 0) + return log_debug_errno(r, "Cannot read boot configuration from ESP, assuming hibernation is not possible."); + else { + _cleanup_free_ char *options = NULL; + + options = strv_join(e->options, " "); + if (!options) + return log_oom(); + + r = resume_configured_in_options(options); + if (r < 0) + return log_error_errno(r, "Failed to parse kernel options in \"%s\": %m", + strnull(e->path)); + return r; + } + + /* If we can't figure out the default boot entry, let's fall back to current kernel cmdline */ + _cleanup_free_ char *line = NULL; + r = proc_cmdline(&line); + if (IN_SET(r, -EPERM, -EACCES, -ENOENT)) + log_debug_errno(r, "Cannot access /proc/cmdline: %m"); + else if (r < 0) + return log_error_errno(r, "Failed to query /proc/cmdline: %m"); + else { + r = resume_configured_in_options(line); + if (r < 0) + return log_error_errno(r, "Failed to parse kernel proc cmdline: %m"); + + return r; + } + + log_debug("Couldn't detect any resume mechanism, hibernation is disabled."); + return false; +} + int read_fiemap(int fd, struct fiemap **ret) { _cleanup_free_ struct fiemap *fiemap = NULL, *result_fiemap = NULL; struct stat statinfo; @@ -337,6 +454,8 @@ int read_fiemap(int fd, struct fiemap ** return 0; } +static int can_sleep_internal(const char *verb, bool check_allowed); + static bool can_s2h(void) { const char *p; int r; @@ -349,8 +468,8 @@ static bool can_s2h(void) { } FOREACH_STRING(p, "suspend", "hibernate") { - r = can_sleep(p); - if (IN_SET(r, 0, -ENOSPC)) { + r = can_sleep_internal(p, false); + if (IN_SET(r, 0, -ENOSPC, -EADV)) { log_debug("Unable to %s system.", p); return false; } @@ -361,19 +480,25 @@ static bool can_s2h(void) { return true; } -int can_sleep(const char *verb) { +static int can_sleep_internal(const char *verb, bool check_allowed) { + bool allow; _cleanup_strv_free_ char **modes = NULL, **states = NULL; int r; assert(STR_IN_SET(verb, "suspend", "hibernate", "hybrid-sleep", "suspend-then-hibernate")); - if (streq(verb, "suspend-then-hibernate")) - return can_s2h(); - - r = parse_sleep_config(verb, &modes, &states, NULL); + r = parse_sleep_config(verb, &allow, &modes, &states, NULL); if (r < 0) return false; + if (check_allowed && !allow) { + log_debug("Sleep mode \"%s\" is disabled by configuration.", verb); + return false; + } + + if (streq(verb, "suspend-then-hibernate")) + return can_s2h(); + if (!can_sleep_state(states) || !can_sleep_disk(modes)) return false; @@ -383,5 +508,14 @@ int can_sleep(const char *verb) { if (!enough_swap_for_hibernation()) return -ENOSPC; + r = resume_configured(); + if (r <= 0) + /* We squash all errors (e.g. EPERM) into a single value for reporting. */ + return -EADV; + return true; } + +int can_sleep(const char *verb) { + return can_sleep_internal(verb, true); +} diff -Naurp systemd-239-orig/src/shared/sleep-config.h systemd-239/src/shared/sleep-config.h --- systemd-239-orig/src/shared/sleep-config.h 2018-06-22 06:11:49.000000000 -0500 +++ systemd-239/src/shared/sleep-config.h 2018-11-04 08:49:10.234692715 -0600 @@ -5,7 +5,7 @@ #include "time-util.h" int read_fiemap(int fd, struct fiemap **ret); -int parse_sleep_config(const char *verb, char ***modes, char ***states, usec_t *delay); +int parse_sleep_config(const char *verb, bool *ret_allow, char ***ret_modes, char ***ret_states, usec_t *ret_delay); int find_hibernate_location(char **device, char **type, size_t *size, size_t *used); int can_sleep(const char *verb); diff -Naurp systemd-239-orig/src/sleep/sleep.c systemd-239/src/sleep/sleep.c --- systemd-239-orig/src/sleep/sleep.c 2018-06-22 06:11:49.000000000 -0500 +++ systemd-239/src/sleep/sleep.c 2018-11-04 08:49:10.234692715 -0600 @@ -131,7 +131,6 @@ static int write_state(FILE **f, char ** } static int execute(char **modes, char **states) { - char *arguments[] = { NULL, (char*) "pre", @@ -162,7 +161,7 @@ static int execute(char **modes, char ** return log_error_errno(r, "Failed to write mode to /sys/power/disk: %m");; } - execute_directories(dirs, DEFAULT_TIMEOUT_USEC, NULL, NULL, arguments); + execute_directories(dirs, DEFAULT_TIMEOUT_USEC, NULL, NULL, arguments, NULL); log_struct(LOG_INFO, "MESSAGE_ID=" SD_MESSAGE_SLEEP_START_STR, @@ -171,15 +170,18 @@ static int execute(char **modes, char ** r = write_state(&f, states); if (r < 0) - return log_error_errno(r, "Failed to write /sys/power/state: %m"); - - log_struct(LOG_INFO, - "MESSAGE_ID=" SD_MESSAGE_SLEEP_STOP_STR, - LOG_MESSAGE("System resumed."), - "SLEEP=%s", arg_verb); + log_struct_errno(LOG_ERR, r, + "MESSAGE_ID=" SD_MESSAGE_SLEEP_STOP_STR, + LOG_MESSAGE("Failed to suspend system. System resumed again: %m"), + "SLEEP=%s", arg_verb); + else + log_struct(LOG_INFO, + "MESSAGE_ID=" SD_MESSAGE_SLEEP_STOP_STR, + LOG_MESSAGE("System resumed."), + "SLEEP=%s", arg_verb); arguments[1] = (char*) "post"; - execute_directories(dirs, DEFAULT_TIMEOUT_USEC, NULL, NULL, arguments); + execute_directories(dirs, DEFAULT_TIMEOUT_USEC, NULL, NULL, arguments, NULL); return r; } @@ -216,13 +218,11 @@ static int execute_s2h(usec_t hibernate_ char time_str[DECIMAL_STR_MAX(uint64_t)]; int r; - r = parse_sleep_config("suspend", &suspend_modes, &suspend_states, - NULL); + r = parse_sleep_config("suspend", NULL, &suspend_modes, &suspend_states, NULL); if (r < 0) return r; - r = parse_sleep_config("hibernate", &hibernate_modes, - &hibernate_states, NULL); + r = parse_sleep_config("hibernate", NULL, &hibernate_modes, &hibernate_states, NULL); if (r < 0) return r; @@ -327,6 +327,7 @@ static int parse_argv(int argc, char *ar } int main(int argc, char *argv[]) { + bool allow; _cleanup_strv_free_ char **modes = NULL, **states = NULL; usec_t delay = 0; int r; @@ -339,10 +340,15 @@ int main(int argc, char *argv[]) { if (r <= 0) goto finish; - r = parse_sleep_config(arg_verb, &modes, &states, &delay); + r = parse_sleep_config(arg_verb, &allow, &modes, &states, &delay); if (r < 0) goto finish; + if (!allow) { + log_error("Sleep mode \"%s\" is disabled by configuration, refusing.", arg_verb); + return EXIT_FAILURE; + } + if (streq(arg_verb, "suspend-then-hibernate")) r = execute_s2h(delay); else diff -Naurp systemd-239-orig/src/systemctl/systemctl.c systemd-239/src/systemctl/systemctl.c --- systemd-239-orig/src/systemctl/systemctl.c 2018-06-22 06:11:49.000000000 -0500 +++ systemd-239/src/systemctl/systemctl.c 2018-11-04 08:49:10.235692715 -0600 @@ -2436,7 +2436,7 @@ static int unit_file_find_path(LookupPat if (r == -ENOMEM) return log_oom(); if (r < 0) - return log_error_errno(r, "Failed to access path '%s': %m", path); + return log_error_errno(r, "Failed to access path \"%s\": %m", path); if (unit_path) *unit_path = TAKE_PTR(lpath); @@ -2544,12 +2544,16 @@ static int unit_find_paths( if (r < 0) return r; - if (r > 0) + if (r > 0) { + if (null_or_empty_path(path)) + /* The template is masked. Let's cut the process short. */ + return -ERFKILL; + /* We found the unit file. If we followed symlinks, this name might be * different then the unit_name with started with. Look for dropins matching * that "final" name. */ r = set_put(names, basename(path)); - else if (!template) + } else if (!template) /* No unit file, let's look for dropins matching the original name. * systemd has fairly complicated rules (based on unit type and provenience), * which units are allowed not to have the main unit file. We err on the @@ -2623,10 +2627,24 @@ static int get_state_one_unit(sd_bus *bu return 0; } -static int unit_is_masked(sd_bus *bus, const char *name) { +static int unit_is_masked(sd_bus *bus, LookupPaths *lp, const char *name) { _cleanup_free_ char *load_state = NULL; int r; + if (unit_name_is_valid(name, UNIT_NAME_TEMPLATE)) { + _cleanup_free_ char *path = NULL; + + /* A template cannot be loaded, but it can be still masked, so + * we need to use a different method. */ + + r = unit_file_find_path(lp, name, &path); + if (r < 0) + return r; + if (r == 0) + return false; + return null_or_empty_path(path); + } + r = unit_load_state(bus, name, &load_state); if (r < 0) return r; @@ -2636,7 +2654,7 @@ static int unit_is_masked(sd_bus *bus, c static int check_triggering_units(sd_bus *bus, const char *name) { _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; - _cleanup_free_ char *n = NULL, *path = NULL; + _cleanup_free_ char *n = NULL, *path = NULL, *load_state = NULL; _cleanup_strv_free_ char **triggered_by = NULL; bool print_warning_label = true; UnitActiveState active_state; @@ -2647,9 +2665,12 @@ static int check_triggering_units(sd_bus if (r < 0) return log_error_errno(r, "Failed to mangle unit name: %m"); - r = unit_is_masked(bus, n); - if (r != 0) - return r < 0 ? r : 0; + r = unit_load_state(bus, name, &load_state); + if (r < 0) + return r; + + if (streq(load_state, "masked")) + return 0; path = unit_dbus_path_from_name(n); if (!path) @@ -3125,10 +3146,10 @@ static int start_unit(int argc, char *ar * another active unit (socket, path, timer) */ if (!arg_quiet && streq(method, "StopUnit")) STRV_FOREACH(name, names) - check_triggering_units(bus, *name); + (void) check_triggering_units(bus, *name); } - if (r >= 0 && arg_wait) { + if (r >= 0 && arg_wait && !set_isempty(wait_context.unit_paths)) { int q; q = sd_event_loop(wait_context.event); if (q < 0) @@ -3439,21 +3460,12 @@ static int load_kexec_kernel(void) { if (access(KEXEC, X_OK) < 0) return log_error_errno(errno, KEXEC" is not available: %m"); - r = find_esp_and_warn(arg_esp_path, false, &where, NULL, NULL, NULL, NULL); - if (r == -ENOKEY) /* find_esp_and_warn() doesn't warn about this case */ + r = find_default_boot_entry(arg_esp_path, &where, &config, &e); + if (r == -ENOKEY) /* find_default_boot_entry() doesn't warn about this case */ return log_error_errno(r, "Cannot find the ESP partition mount point."); - if (r < 0) /* But it logs about all these cases, hence don't log here again */ - return r; - - r = boot_entries_load_config(where, &config); if (r < 0) - return log_error_errno(r, "Failed to load bootspec config from \"%s/loader\": %m", where); - - if (config.default_entry < 0) { - log_error("No entry suitable as default, refusing to guess."); - return -ENOENT; - } - e = &config.entries[config.default_entry]; + /* But it logs about all these cases, hence don't log here again */ + return r; if (strv_length(e->initrd) > 1) { log_error("Boot entry specifies multiple initrds, which is not supported currently."); @@ -5341,6 +5353,13 @@ static int cat(int argc, char *argv[], v _cleanup_strv_free_ char **dropin_paths = NULL; r = unit_find_paths(bus, *name, &lp, &fragment_path, &dropin_paths); + if (r == -ERFKILL) { + printf("%s# unit %s is masked%s\n", + ansi_highlight_magenta(), + *name, + ansi_normal()); + continue; + } if (r < 0) return r; else if (r == 0) @@ -6906,6 +6925,7 @@ static int find_paths_to_edit(sd_bus *bu } static int edit(int argc, char *argv[], void *userdata) { + _cleanup_(lookup_paths_free) LookupPaths lp = {}; _cleanup_strv_free_ char **names = NULL; _cleanup_strv_free_ char **paths = NULL; char **original, **tmp; @@ -6922,6 +6942,10 @@ static int edit(int argc, char *argv[], return -EINVAL; } + r = lookup_paths_init(&lp, arg_scope, 0, arg_root); + if (r < 0) + return log_error_errno(r, "Failed to determine unit paths: %m"); + r = acquire_bus(BUS_MANAGER, &bus); if (r < 0) return r; @@ -6931,7 +6955,7 @@ static int edit(int argc, char *argv[], return log_error_errno(r, "Failed to expand names: %m"); STRV_FOREACH(tmp, names) { - r = unit_is_masked(bus, *tmp); + r = unit_is_masked(bus, &lp, *tmp); if (r < 0) return r; @@ -8394,8 +8418,10 @@ static int halt_main(void) { if (r < 0) return r; - if (arg_when > 0) - return logind_schedule_shutdown(); + /* Delayed shutdown requested, and was successful */ + if (arg_when > 0 && logind_schedule_shutdown() == 0) + return 0; + /* no delay, or logind failed or is not at all available */ if (geteuid() != 0) { if (arg_dry_run || arg_force > 0) { diff -Naurp systemd-239-orig/src/test/meson.build systemd-239/src/test/meson.build --- systemd-239-orig/src/test/meson.build 2018-06-22 06:11:49.000000000 -0500 +++ systemd-239/src/test/meson.build 2018-11-04 08:49:10.235692715 -0600 @@ -60,6 +60,11 @@ tests += [ libmount, libblkid]], + [['src/test/test-chown-rec.c'], + [libcore, + libshared], + []], + [['src/test/test-job-type.c'], [libcore, libshared], @@ -392,6 +397,10 @@ tests += [ [], []], + [['src/test/test-set-disable-mempool.c'], + [], + [threads]], + [['src/test/test-bitmap.c'], [], []], @@ -870,6 +879,12 @@ tests += [ [['src/libsystemd/sd-login/test-login.c'], [], []], + + [['src/libsystemd/sd-device/test-udev-device-thread.c'], + [libbasic, + libshared_static, + libudev], + [threads]], ] if cxx.found() diff -Naurp systemd-239-orig/src/test/test-chown-rec.c systemd-239/src/test/test-chown-rec.c --- systemd-239-orig/src/test/test-chown-rec.c 1969-12-31 18:00:00.000000000 -0600 +++ systemd-239/src/test/test-chown-rec.c 2018-11-04 08:49:10.235692715 -0600 @@ -0,0 +1,160 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include + +#include "alloc-util.h" +#include "chown-recursive.h" +#include "fileio.h" +#include "log.h" +#include "rm-rf.h" +#include "string-util.h" +#include "tests.h" + +static const uint8_t acl[] = { + 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x07, 0x00, + 0xff, 0xff, 0xff, 0xff, 0x02, 0x00, 0x07, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x07, 0x00, + 0xff, 0xff, 0xff, 0xff, 0x10, 0x00, 0x07, 0x00, + 0xff, 0xff, 0xff, 0xff, 0x20, 0x00, 0x05, 0x00, + 0xff, 0xff, 0xff, 0xff, +}; + +static const uint8_t default_acl[] = { + 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x07, 0x00, + 0xff, 0xff, 0xff, 0xff, 0x04, 0x00, 0x07, 0x00, + 0xff, 0xff, 0xff, 0xff, 0x08, 0x00, 0x07, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x10, 0x00, 0x07, 0x00, + 0xff, 0xff, 0xff, 0xff, 0x20, 0x00, 0x05, 0x00, + 0xff, 0xff, 0xff, 0xff, +}; + +static bool has_xattr(const char *p) { + char buffer[sizeof(acl) * 4]; + + if (lgetxattr(p, "system.posix_acl_access", buffer, sizeof(buffer)) < 0) { + if (IN_SET(errno, EOPNOTSUPP, ENOTTY, ENODATA, ENOSYS)) + return false; + } + + return true; +} + +static void test_chown_recursive(void) { + _cleanup_(rm_rf_physical_and_freep) char *t = NULL; + struct stat st; + const char *p; + + umask(022); + assert_se(mkdtemp_malloc(NULL, &t) >= 0); + + p = strjoina(t, "/dir"); + assert_se(mkdir(p, 0777) >= 0); + assert_se(lstat(p, &st) >= 0); + assert_se(S_ISDIR(st.st_mode)); + assert_se((st.st_mode & 07777) == 0755); + assert_se(st.st_uid == 0); + assert_se(st.st_gid == 0); + assert_se(!has_xattr(p)); + + p = strjoina(t, "/dir/symlink"); + assert_se(symlink("../../", p) >= 0); + assert_se(lstat(p, &st) >= 0); + assert_se(S_ISLNK(st.st_mode)); + assert_se((st.st_mode & 07777) == 0777); + assert_se(st.st_uid == 0); + assert_se(st.st_gid == 0); + assert_se(!has_xattr(p)); + + p = strjoina(t, "/dir/reg"); + assert_se(mknod(p, S_IFREG|0777, 0) >= 0); + assert_se(lstat(p, &st) >= 0); + assert_se(S_ISREG(st.st_mode)); + assert_se((st.st_mode & 07777) == 0755); + assert_se(st.st_uid == 0); + assert_se(st.st_gid == 0); + assert_se(!has_xattr(p)); + + p = strjoina(t, "/dir/sock"); + assert_se(mknod(p, S_IFSOCK|0777, 0) >= 0); + assert_se(lstat(p, &st) >= 0); + assert_se(S_ISSOCK(st.st_mode)); + assert_se((st.st_mode & 07777) == 0755); + assert_se(st.st_uid == 0); + assert_se(st.st_gid == 0); + assert_se(!has_xattr(p)); + + p = strjoina(t, "/dir/fifo"); + assert_se(mknod(p, S_IFIFO|0777, 0) >= 0); + assert_se(lstat(p, &st) >= 0); + assert_se(S_ISFIFO(st.st_mode)); + assert_se((st.st_mode & 07777) == 0755); + assert_se(st.st_uid == 0); + assert_se(st.st_gid == 0); + assert_se(!has_xattr(p)); + + /* We now apply an xattr to the dir, and check it again */ + p = strjoina(t, "/dir"); + assert_se(setxattr(p, "system.posix_acl_access", acl, sizeof(acl), 0) >= 0); + assert_se(setxattr(p, "system.posix_acl_default", default_acl, sizeof(default_acl), 0) >= 0); + assert_se(lstat(p, &st) >= 0); + assert_se(S_ISDIR(st.st_mode)); + assert_se((st.st_mode & 07777) == 0775); /* acl change changed the mode too */ + assert_se(st.st_uid == 0); + assert_se(st.st_gid == 0); + assert_se(has_xattr(p)); + + assert_se(path_chown_recursive(t, 1, 2) >= 0); + + p = strjoina(t, "/dir"); + assert_se(lstat(p, &st) >= 0); + assert_se(S_ISDIR(st.st_mode)); + assert_se((st.st_mode & 07777) == 0775); + assert_se(st.st_uid == 1); + assert_se(st.st_gid == 2); + assert_se(!has_xattr(p)); + + p = strjoina(t, "/dir/symlink"); + assert_se(lstat(p, &st) >= 0); + assert_se(S_ISLNK(st.st_mode)); + assert_se((st.st_mode & 07777) == 0777); + assert_se(st.st_uid == 1); + assert_se(st.st_gid == 2); + assert_se(!has_xattr(p)); + + p = strjoina(t, "/dir/reg"); + assert_se(lstat(p, &st) >= 0); + assert_se(S_ISREG(st.st_mode)); + assert_se((st.st_mode & 07777) == 0755); + assert_se(st.st_uid == 1); + assert_se(st.st_gid == 2); + assert_se(!has_xattr(p)); + + p = strjoina(t, "/dir/sock"); + assert_se(lstat(p, &st) >= 0); + assert_se(S_ISSOCK(st.st_mode)); + assert_se((st.st_mode & 07777) == 0755); + assert_se(st.st_uid == 1); + assert_se(st.st_gid == 2); + assert_se(!has_xattr(p)); + + p = strjoina(t, "/dir/fifo"); + assert_se(lstat(p, &st) >= 0); + assert_se(S_ISFIFO(st.st_mode)); + assert_se((st.st_mode & 07777) == 0755); + assert_se(st.st_uid == 1); + assert_se(st.st_gid == 2); + assert_se(!has_xattr(p)); +} + +int main(int argc, char *argv[]) { + log_set_max_level(LOG_DEBUG); + log_parse_environment(); + log_open(); + + if (geteuid() != 0) + return EXIT_TEST_SKIP; + + test_chown_recursive(); + + return EXIT_SUCCESS; +} diff -Naurp systemd-239-orig/src/test/test-execute.c systemd-239/src/test/test-execute.c --- systemd-239-orig/src/test/test-execute.c 2018-06-22 06:11:49.000000000 -0500 +++ systemd-239/src/test/test-execute.c 2018-11-04 08:49:10.236692714 -0600 @@ -105,6 +105,25 @@ invalid: return false; } +static bool check_user_has_group_with_same_name(const char *name) { + struct passwd *p; + struct group *g; + + assert(name); + + p = getpwnam(name); + if (!p || + !streq(p->pw_name, name)) + return false; + + g = getgrgid(p->pw_gid); + if (!g || + !streq(g->gr_name, name)) + return false; + + return true; +} + static bool is_inaccessible_available(void) { char *p; @@ -427,6 +446,10 @@ static void test_exec_supplementarygroup static void test_exec_dynamicuser(Manager *m) { test(m, "exec-dynamicuser-fixeduser.service", 0, CLD_EXITED); + if (check_user_has_group_with_same_name("adm")) + test(m, "exec-dynamicuser-fixeduser-adm.service", 0, CLD_EXITED); + if (check_user_has_group_with_same_name("games")) + test(m, "exec-dynamicuser-fixeduser-games.service", 0, CLD_EXITED); test(m, "exec-dynamicuser-fixeduser-one-supplementarygroup.service", 0, CLD_EXITED); test(m, "exec-dynamicuser-supplementarygroups.service", 0, CLD_EXITED); test(m, "exec-dynamicuser-statedir.service", 0, CLD_EXITED); diff -Naurp systemd-239-orig/src/test/test-exec-util.c systemd-239/src/test/test-exec-util.c --- systemd-239-orig/src/test/test-exec-util.c 2018-06-22 06:11:49.000000000 -0500 +++ systemd-239/src/test/test-exec-util.c 2018-11-04 08:49:10.236692714 -0600 @@ -16,6 +16,7 @@ #include "fs-util.h" #include "log.h" #include "macro.h" +#include "path-util.h" #include "rm-rf.h" #include "string-util.h" #include "strv.h" @@ -115,9 +116,9 @@ static void test_execute_directory(bool assert_se(chmod(mask2e, 0755) == 0); if (gather_stdout) - execute_directories(dirs, DEFAULT_TIMEOUT_USEC, ignore_stdout, ignore_stdout_args, NULL); + execute_directories(dirs, DEFAULT_TIMEOUT_USEC, ignore_stdout, ignore_stdout_args, NULL, NULL); else - execute_directories(dirs, DEFAULT_TIMEOUT_USEC, NULL, NULL, NULL); + execute_directories(dirs, DEFAULT_TIMEOUT_USEC, NULL, NULL, NULL, NULL); assert_se(chdir(template_lo) == 0); assert_se(access("it_works", F_OK) >= 0); @@ -182,7 +183,7 @@ static void test_execution_order(void) { assert_se(chmod(override, 0755) == 0); assert_se(chmod(masked, 0755) == 0); - execute_directories(dirs, DEFAULT_TIMEOUT_USEC, ignore_stdout, ignore_stdout_args, NULL); + execute_directories(dirs, DEFAULT_TIMEOUT_USEC, ignore_stdout, ignore_stdout_args, NULL, NULL); assert_se(read_full_file(output, &contents, NULL) >= 0); assert_se(streq(contents, "30-override\n80-foo\n90-bar\nlast\n")); @@ -264,7 +265,7 @@ static void test_stdout_gathering(void) assert_se(chmod(name2, 0755) == 0); assert_se(chmod(name3, 0755) == 0); - r = execute_directories(dirs, DEFAULT_TIMEOUT_USEC, gather_stdout, args, NULL); + r = execute_directories(dirs, DEFAULT_TIMEOUT_USEC, gather_stdout, args, NULL, NULL); assert_se(r >= 0); log_info("got: %s", output); @@ -275,7 +276,7 @@ static void test_stdout_gathering(void) static void test_environment_gathering(void) { char template[] = "/tmp/test-exec-util.XXXXXXX", **p; const char *dirs[] = {template, NULL}; - const char *name, *name2, *name3; + const char *name, *name2, *name3, *old; int r; char **tmp = NULL; /* this is only used in the forked process, no cleanup here */ @@ -321,7 +322,32 @@ static void test_environment_gathering(v assert_se(chmod(name2, 0755) == 0); assert_se(chmod(name3, 0755) == 0); - r = execute_directories(dirs, DEFAULT_TIMEOUT_USEC, gather_environment, args, NULL); + /* When booting in containers or without initramfs there might not be + * any PATH in the environ and if there is no PATH /bin/sh built-in + * PATH may leak and override systemd's DEFAULT_PATH which is not + * good. Force our own PATH in environment, to prevent expansion of sh + * built-in $PATH */ + old = getenv("PATH"); + r = setenv("PATH", "no-sh-built-in-path", 1); + assert_se(r >= 0); + + r = execute_directories(dirs, DEFAULT_TIMEOUT_USEC, gather_environment, args, NULL, NULL); + assert_se(r >= 0); + + STRV_FOREACH(p, env) + log_info("got env: \"%s\"", *p); + + assert_se(streq(strv_env_get(env, "A"), "22:23:24")); + assert_se(streq(strv_env_get(env, "B"), "12")); + assert_se(streq(strv_env_get(env, "C"), "001")); + assert_se(streq(strv_env_get(env, "PATH"), "no-sh-built-in-path:/no/such/file")); + + /* now retest with "default" path passed in, as created by + * manager_default_environment */ + env = strv_free(env); + env = strv_new("PATH=" DEFAULT_PATH, NULL); + + r = execute_directories(dirs, DEFAULT_TIMEOUT_USEC, gather_environment, args, NULL, env); assert_se(r >= 0); STRV_FOREACH(p, env) @@ -330,7 +356,10 @@ static void test_environment_gathering(v assert_se(streq(strv_env_get(env, "A"), "22:23:24")); assert_se(streq(strv_env_get(env, "B"), "12")); assert_se(streq(strv_env_get(env, "C"), "001")); - assert_se(endswith(strv_env_get(env, "PATH"), ":/no/such/file")); + assert_se(streq(strv_env_get(env, "PATH"), DEFAULT_PATH ":/no/such/file")); + + /* reset environ PATH */ + (void) setenv("PATH", old, 1); } int main(int argc, char *argv[]) { diff -Naurp systemd-239-orig/src/test/test-format-table.c systemd-239/src/test/test-format-table.c --- systemd-239-orig/src/test/test-format-table.c 2018-06-22 06:11:49.000000000 -0500 +++ systemd-239/src/test/test-format-table.c 2018-11-04 08:49:10.236692714 -0600 @@ -5,6 +5,30 @@ #include "string-util.h" #include "time-util.h" +static void test_issue_9549(void) { + _cleanup_(table_unrefp) Table *table = NULL; + _cleanup_free_ char *formatted = NULL; + + assert_se(table = table_new("NAME", "TYPE", "RO", "USAGE", "CREATED", "MODIFIED")); + assert_se(table_set_align_percent(table, TABLE_HEADER_CELL(3), 100) >= 0); + assert_se(table_add_many(table, + TABLE_STRING, "foooo", + TABLE_STRING, "raw", + TABLE_BOOLEAN, false, + TABLE_SIZE, (uint64_t) (673.7*1024*1024), + TABLE_STRING, "Wed 2018-07-11 00:10:33 JST", + TABLE_STRING, "Wed 2018-07-11 00:16:00 JST") >= 0); + + table_set_width(table, 75); + assert_se(table_format(table, &formatted) >= 0); + + printf("%s\n", formatted); + assert_se(streq(formatted, + "NAME TYPE RO USAGE CREATED MODIFIED \n" + "foooo raw no 673.6M Wed 2018-07-11 00:10:33 J… Wed 2018-07-11 00:16:00 JST\n" + )); +} + int main(int argc, char *argv[]) { _cleanup_(table_unrefp) Table *t = NULL; @@ -135,5 +159,7 @@ int main(int argc, char *argv[]) { " yes xxx yes xxx xxx \n" "5min 5min \n")); + test_issue_9549(); + return 0; } diff -Naurp systemd-239-orig/src/test/test-install-root.c systemd-239/src/test/test-install-root.c --- systemd-239-orig/src/test/test-install-root.c 2018-06-22 06:11:49.000000000 -0500 +++ systemd-239/src/test/test-install-root.c 2018-11-04 08:49:10.236692714 -0600 @@ -861,7 +861,7 @@ static void test_with_dropin(const char unit_file_changes_free(changes, n_changes); changes = NULL; n_changes = 0; - assert_se(unit_file_enable(UNIT_FILE_SYSTEM, 0, root, STRV_MAKE("with-dropin-4a.service"), &changes, &n_changes) == 1); + assert_se(unit_file_enable(UNIT_FILE_SYSTEM, 0, root, STRV_MAKE("with-dropin-4a.service"), &changes, &n_changes) == 2); assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "with-dropin-3.service", &state) >= 0 && state == UNIT_FILE_ENABLED); assert_se(n_changes == 2); assert_se(changes[0].type == UNIT_FILE_SYMLINK); diff -Naurp systemd-239-orig/src/test/test-proc-cmdline.c systemd-239/src/test/test-proc-cmdline.c --- systemd-239-orig/src/test/test-proc-cmdline.c 2018-06-22 06:11:49.000000000 -0500 +++ systemd-239/src/test/test-proc-cmdline.c 2018-11-04 08:49:10.236692714 -0600 @@ -1,6 +1,7 @@ /* SPDX-License-Identifier: LGPL-2.1+ */ #include "alloc-util.h" +#include "env-util.h" #include "log.h" #include "macro.h" #include "proc-cmdline.h" @@ -19,28 +20,68 @@ static int parse_item(const char *key, c } static void test_proc_cmdline_parse(void) { - assert_se(proc_cmdline_parse(parse_item, &obj, true) >= 0); + log_info("/* %s */", __func__); + + assert_se(proc_cmdline_parse(parse_item, &obj, PROC_CMDLINE_STRIP_RD_PREFIX) >= 0); } -static void test_runlevel_to_target(void) { - in_initrd_force(false); - assert_se(streq_ptr(runlevel_to_target(NULL), NULL)); - assert_se(streq_ptr(runlevel_to_target("unknown-runlevel"), NULL)); - assert_se(streq_ptr(runlevel_to_target("rd.unknown-runlevel"), NULL)); - assert_se(streq_ptr(runlevel_to_target("3"), SPECIAL_MULTI_USER_TARGET)); - assert_se(streq_ptr(runlevel_to_target("rd.rescue"), NULL)); +static void test_proc_cmdline_override(void) { + log_info("/* %s */", __func__); - in_initrd_force(true); - assert_se(streq_ptr(runlevel_to_target(NULL), NULL)); - assert_se(streq_ptr(runlevel_to_target("unknown-runlevel"), NULL)); - assert_se(streq_ptr(runlevel_to_target("rd.unknown-runlevel"), NULL)); - assert_se(streq_ptr(runlevel_to_target("3"), NULL)); - assert_se(streq_ptr(runlevel_to_target("rd.rescue"), SPECIAL_RESCUE_TARGET)); + assert_se(putenv((char*) "SYSTEMD_PROC_CMDLINE=foo_bar=quux wuff-piep=tuet zumm") == 0); + + /* Test if the override works */ + _cleanup_free_ char *line = NULL, *value = NULL; + assert_se(proc_cmdline(&line) >= 0); + + /* Test if parsing makes uses of the override */ + assert_se(streq(line, "foo_bar=quux wuff-piep=tuet zumm")); + assert_se(proc_cmdline_get_key("foo_bar", 0, &value) > 0 && streq_ptr(value, "quux")); +} + +static int parse_item_given(const char *key, const char *value, void *data) { + assert_se(key); + assert_se(data); + + bool *strip = data; + + log_info("%s: option <%s> = <%s>", __func__, key, strna(value)); + if (streq(key, "foo_bar")) + assert_se(streq(value, "quux")); + else if (streq(key, "wuff-piep")) + assert_se(streq(value, "tuet ")); + else if (in_initrd() && *strip && streq(key, "zumm")) + assert_se(!value); + else if (in_initrd() && !*strip && streq(key, "rd.zumm")) + assert_se(!value); + else + assert_not_reached("Bad key!"); + + return 0; +} + +static void test_proc_cmdline_given(bool flip_initrd) { + log_info("/* %s (flip: %s) */", __func__, yes_no(flip_initrd)); + + if (flip_initrd) + in_initrd_force(!in_initrd()); + + bool t = true, f = false; + assert_se(proc_cmdline_parse_given("foo_bar=quux wuff-piep=\"tuet \" rd.zumm", + parse_item_given, &t, PROC_CMDLINE_STRIP_RD_PREFIX) >= 0); + + assert_se(proc_cmdline_parse_given("foo_bar=quux wuff-piep=\"tuet \" rd.zumm", + parse_item_given, &f, 0) >= 0); + + + if (flip_initrd) + in_initrd_force(!in_initrd()); } static void test_proc_cmdline_get_key(void) { _cleanup_free_ char *value = NULL; + log_info("/* %s */", __func__); putenv((char*) "SYSTEMD_PROC_CMDLINE=foo_bar=quux wuff-piep=tuet zumm"); assert_se(proc_cmdline_get_key("", 0, &value) == -EINVAL); @@ -78,6 +119,7 @@ static void test_proc_cmdline_get_key(vo static void test_proc_cmdline_get_bool(void) { bool value = false; + log_info("/* %s */", __func__); putenv((char*) "SYSTEMD_PROC_CMDLINE=foo_bar bar-waldo=1 x_y-z=0 quux=miep"); assert_se(proc_cmdline_get_bool("", &value) == -EINVAL); @@ -94,6 +136,7 @@ static void test_proc_cmdline_get_bool(v } static void test_proc_cmdline_key_streq(void) { + log_info("/* %s */", __func__); assert_se(proc_cmdline_key_streq("", "")); assert_se(proc_cmdline_key_streq("a", "a")); @@ -110,6 +153,7 @@ static void test_proc_cmdline_key_streq( } static void test_proc_cmdline_key_startswith(void) { + log_info("/* %s */", __func__); assert_se(proc_cmdline_key_startswith("", "")); assert_se(proc_cmdline_key_startswith("x", "")); @@ -124,11 +168,33 @@ static void test_proc_cmdline_key_starts assert_se(!proc_cmdline_key_startswith("foo-bar", "foo_xx")); } +static void test_runlevel_to_target(void) { + log_info("/* %s */", __func__); + + in_initrd_force(false); + assert_se(streq_ptr(runlevel_to_target(NULL), NULL)); + assert_se(streq_ptr(runlevel_to_target("unknown-runlevel"), NULL)); + assert_se(streq_ptr(runlevel_to_target("rd.unknown-runlevel"), NULL)); + assert_se(streq_ptr(runlevel_to_target("3"), SPECIAL_MULTI_USER_TARGET)); + assert_se(streq_ptr(runlevel_to_target("rd.rescue"), NULL)); + + in_initrd_force(true); + assert_se(streq_ptr(runlevel_to_target(NULL), NULL)); + assert_se(streq_ptr(runlevel_to_target("unknown-runlevel"), NULL)); + assert_se(streq_ptr(runlevel_to_target("rd.unknown-runlevel"), NULL)); + assert_se(streq_ptr(runlevel_to_target("3"), NULL)); + assert_se(streq_ptr(runlevel_to_target("rd.rescue"), SPECIAL_RESCUE_TARGET)); +} + int main(void) { log_parse_environment(); log_open(); test_proc_cmdline_parse(); + test_proc_cmdline_override(); + test_proc_cmdline_given(false); + /* Repeat the same thing, but now flip our ininitrdness */ + test_proc_cmdline_given(true); test_proc_cmdline_key_streq(); test_proc_cmdline_key_startswith(); test_proc_cmdline_get_key(); diff -Naurp systemd-239-orig/src/test/test-set-disable-mempool.c systemd-239/src/test/test-set-disable-mempool.c --- systemd-239-orig/src/test/test-set-disable-mempool.c 1969-12-31 18:00:00.000000000 -0600 +++ systemd-239/src/test/test-set-disable-mempool.c 2018-11-04 08:49:10.236692714 -0600 @@ -0,0 +1,55 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include + +#include "process-util.h" +#include "set.h" +#include "tests.h" + +#define NUM 100 + +static void* thread(void *p) { + Set **s = p; + + assert_se(s); + assert_se(*s); + + assert_se(!is_main_thread()); + assert_se(set_size(*s) == NUM); + *s = set_free(*s); + + return NULL; +} + +static void test_one(const char *val) { + pthread_t t; + int x[NUM] = {}; + unsigned i; + Set *s; + + log_info("Testing with SYSTEMD_MEMPOOL=%s", val); + assert_se(setenv("SYSTEMD_MEMPOOL", val, true) == 0); + assert_se(is_main_thread()); + + assert_se(s = set_new(NULL)); + for (i = 0; i < NUM; i++) + assert_se(set_put(s, &x[i])); + + assert_se(pthread_create(&t, NULL, thread, &s) == 0); + assert_se(pthread_join(t, NULL) == 0); + + assert_se(!s); +} + +int main(int argc, char *argv[]) { + log_set_max_level(LOG_DEBUG); + log_parse_environment(); + log_open(); + + test_one("0"); + /* The value $SYSTEMD_MEMPOOL= is cached. So the following + * test should also succeed. */ + test_one("1"); + + return 0; +} diff -Naurp systemd-239-orig/src/test/test-sleep.c systemd-239/src/test/test-sleep.c --- systemd-239-orig/src/test/test-sleep.c 2018-06-22 06:11:49.000000000 -0500 +++ systemd-239/src/test/test-sleep.c 2018-11-04 08:49:10.236692714 -0600 @@ -1,5 +1,6 @@ /* SPDX-License-Identifier: LGPL-2.1+ */ +#include #include #include @@ -13,7 +14,7 @@ static void test_parse_sleep_config(void const char *verb; FOREACH_STRING(verb, "suspend", "hibernate", "hybrid-sleep", "suspend-then-hibernate") - assert_se(parse_sleep_config(verb, NULL, NULL, NULL) == 0); + assert_se(parse_sleep_config(verb, NULL, NULL, NULL, NULL) == 0); } static int test_fiemap(const char *path) { @@ -32,14 +33,14 @@ static int test_fiemap(const char *path) if (r < 0) return log_error_errno(r, "Unable to read extent map for '%s': %m", path); log_info("extent map information for %s:", path); - log_info("\t start: %llu", fiemap->fm_start); - log_info("\t length: %llu", fiemap->fm_length); - log_info("\t flags: %u", fiemap->fm_flags); - log_info("\t number of mapped extents: %u", fiemap->fm_mapped_extents); - log_info("\t extent count: %u", fiemap->fm_extent_count); + log_info("\t start: %" PRIu64, (uint64_t) fiemap->fm_start); + log_info("\t length: %" PRIu64, (uint64_t) fiemap->fm_length); + log_info("\t flags: %" PRIu32, fiemap->fm_flags); + log_info("\t number of mapped extents: %" PRIu32, fiemap->fm_mapped_extents); + log_info("\t extent count: %" PRIu32, fiemap->fm_extent_count); if (fiemap->fm_extent_count > 0) - log_info("\t first extent location: %llu", - fiemap->fm_extents[0].fe_physical / page_size()); + log_info("\t first extent location: %" PRIu64, + (uint64_t) (fiemap->fm_extents[0].fe_physical / page_size())); return 0; } diff -Naurp systemd-239-orig/src/test/test-string-util.c systemd-239/src/test/test-string-util.c --- systemd-239-orig/src/test/test-string-util.c 2018-06-22 06:11:49.000000000 -0500 +++ systemd-239/src/test/test-string-util.c 2018-11-04 08:49:10.237692714 -0600 @@ -5,6 +5,7 @@ #include "macro.h" #include "string-util.h" #include "strv.h" +#include "tests.h" #include "utf8.h" static void test_string_erase(void) { @@ -30,6 +31,64 @@ static void test_string_erase(void) { assert_se(x[9] == '\0'); } +static void test_free_and_strndup_one(char **t, const char *src, size_t l, const char *expected, bool change) { + int r; + + log_debug("%s: \"%s\", \"%s\", %zd (expect \"%s\", %s)", + __func__, strnull(*t), strnull(src), l, strnull(expected), yes_no(change)); + + r = free_and_strndup(t, src, l); + assert_se(streq_ptr(*t, expected)); + assert_se(r == change); /* check that change occurs only when necessary */ +} + +static void test_free_and_strndup(void) { + static const struct test_case { + const char *src; + size_t len; + const char *expected; + } cases[] = { + {"abc", 0, ""}, + {"abc", 0, ""}, + {"abc", 1, "a"}, + {"abc", 2, "ab"}, + {"abc", 3, "abc"}, + {"abc", 4, "abc"}, + {"abc", 5, "abc"}, + {"abc", 5, "abc"}, + {"abc", 4, "abc"}, + {"abc", 3, "abc"}, + {"abc", 2, "ab"}, + {"abc", 1, "a"}, + {"abc", 0, ""}, + + {"", 0, ""}, + {"", 1, ""}, + {"", 2, ""}, + {"", 0, ""}, + {"", 1, ""}, + {"", 2, ""}, + {"", 2, ""}, + {"", 1, ""}, + {"", 0, ""}, + + {NULL, 0, NULL}, + + {"foo", 3, "foo"}, + {"foobar", 6, "foobar"}, + }; + + _cleanup_free_ char *t = NULL; + const char *prev_expected = t; + + for (unsigned i = 0; i < ELEMENTSOF(cases); i++) { + test_free_and_strndup_one(&t, + cases[i].src, cases[i].len, cases[i].expected, + !streq_ptr(cases[i].expected, prev_expected)); + prev_expected = t; + } +} + static void test_ascii_strcasecmp_n(void) { assert_se(ascii_strcasecmp_n("", "", 0) == 0); @@ -496,8 +555,32 @@ static void test_memory_startswith(void) assert_se(!memory_startswith("xxx", 4, "xxxx")); } +static void test_memory_startswith_no_case(void) { + assert_se(streq(memory_startswith_no_case("", 0, ""), "")); + assert_se(streq(memory_startswith_no_case("", 1, ""), "")); + assert_se(streq(memory_startswith_no_case("x", 2, ""), "x")); + assert_se(streq(memory_startswith_no_case("X", 2, ""), "X")); + assert_se(!memory_startswith_no_case("", 1, "X")); + assert_se(!memory_startswith_no_case("", 1, "xxxxXXXX")); + assert_se(streq(memory_startswith_no_case("xxx", 4, "X"), "xx")); + assert_se(streq(memory_startswith_no_case("XXX", 4, "x"), "XX")); + assert_se(streq(memory_startswith_no_case("XXX", 4, "X"), "XX")); + assert_se(streq(memory_startswith_no_case("xxx", 4, "XX"), "x")); + assert_se(streq(memory_startswith_no_case("XXX", 4, "xx"), "X")); + assert_se(streq(memory_startswith_no_case("XXX", 4, "XX"), "X")); + assert_se(streq(memory_startswith_no_case("xxx", 4, "XXX"), "")); + assert_se(streq(memory_startswith_no_case("XXX", 4, "xxx"), "")); + assert_se(streq(memory_startswith_no_case("XXX", 4, "XXX"), "")); + + assert_se(memory_startswith_no_case((char[2]){'x', 'x'}, 2, "xx")); + assert_se(memory_startswith_no_case((char[2]){'x', 'X'}, 2, "xX")); + assert_se(memory_startswith_no_case((char[2]){'X', 'x'}, 2, "Xx")); + assert_se(memory_startswith_no_case((char[2]){'X', 'X'}, 2, "XX")); +} + int main(int argc, char *argv[]) { test_string_erase(); + test_free_and_strndup(); test_ascii_strcasecmp_n(); test_ascii_strcasecmp_nn(); test_cellescape(); @@ -525,6 +608,7 @@ int main(int argc, char *argv[]) { test_first_word(); test_strlen_ptr(); test_memory_startswith(); + test_memory_startswith_no_case(); return 0; } diff -Naurp systemd-239-orig/src/test/test-time-util.c systemd-239/src/test/test-time-util.c --- systemd-239-orig/src/test/test-time-util.c 2018-06-22 06:11:49.000000000 -0500 +++ systemd-239/src/test/test-time-util.c 2018-11-04 08:49:10.237692714 -0600 @@ -54,7 +54,7 @@ static void test_parse_sec_fix_0(void) { assert_se(parse_sec_fix_0("5s", &u) >= 0); assert_se(u == 5 * USEC_PER_SEC); assert_se(parse_sec_fix_0("0s", &u) >= 0); - assert_se(u == 0 * USEC_PER_SEC); + assert_se(u == USEC_INFINITY); assert_se(parse_sec_fix_0("0", &u) >= 0); assert_se(u == USEC_INFINITY); assert_se(parse_sec_fix_0(" 0", &u) >= 0); diff -Naurp systemd-239-orig/src/timedate/timedated.c systemd-239/src/timedate/timedated.c --- systemd-239-orig/src/timedate/timedated.c 2018-06-22 06:11:49.000000000 -0500 +++ systemd-239/src/timedate/timedated.c 2018-11-04 08:49:10.237692714 -0600 @@ -43,6 +43,10 @@ typedef struct Context { char *zone; bool local_rtc; Hashmap *polkit_registry; + sd_bus_message *cache; + + sd_bus_slot *slot_job_removed; + char *path_ntp_unit; LIST_HEAD(UnitStatusInfo, units); } Context; @@ -70,6 +74,10 @@ static void context_free(Context *c) { free(c->zone); bus_verify_polkit_async_registry_free(c->polkit_registry); + sd_bus_message_unref(c->cache); + + sd_bus_slot_unref(c->slot_job_removed); + free(c->path_ntp_unit); while ((p = c->units)) { LIST_REMOVE(units, c->units, p); @@ -301,18 +309,20 @@ static int context_update_ntp_status(Con { "UnitFileState", "s", NULL, offsetof(UnitStatusInfo, unit_file_state) }, {} }; - static sd_bus_message *_m = NULL; UnitStatusInfo *u; int r; assert(c); assert(bus); - /* Suppress multiple call of context_update_ntp_status() within single DBus transaction. */ - if (m && m == _m) - return 0; + /* Suppress calling context_update_ntp_status() multiple times within single DBus transaction. */ + if (m) { + if (m == c->cache) + return 0; - _m = m; + sd_bus_message_unref(c->cache); + c->cache = sd_bus_message_ref(m); + } LIST_FOREACH(units, u, c->units) { _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; @@ -340,17 +350,55 @@ static int context_update_ntp_status(Con return 0; } -static int unit_start_or_stop(UnitStatusInfo *u, sd_bus *bus, sd_bus_error *error, bool start) { +static int match_job_removed(sd_bus_message *m, void *userdata, sd_bus_error *error) { + const char *path; + Context *c = userdata; int r; + assert(c); + assert(m); + + r = sd_bus_message_read(m, "uoss", NULL, &path, NULL, NULL); + if (r < 0) { + bus_log_parse_error(r); + return 0; + } + + if (!streq_ptr(path, c->path_ntp_unit)) + return 0; + + (void) sd_bus_emit_properties_changed(sd_bus_message_get_bus(m), "/org/freedesktop/timedate1", "org.freedesktop.timedate1", "NTP", NULL); + + c->slot_job_removed = sd_bus_slot_unref(c->slot_job_removed); + c->path_ntp_unit = mfree(c->path_ntp_unit); + + return 0; +} + +static int unit_start_or_stop(Context *c, UnitStatusInfo *u, sd_bus *bus, sd_bus_error *error, bool start) { + _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; + _cleanup_(sd_bus_slot_unrefp) sd_bus_slot *slot = NULL; + const char *path; + int r; + + assert(c); assert(u); assert(bus); assert(error); - /* Call context_update_ntp_status() to update UnitStatusInfo before calling this. */ + /* This method may be called frequently. Forget the previous job if it has not completed yet. */ + c->slot_job_removed = sd_bus_slot_unref(c->slot_job_removed); - if (streq(u->active_state, "active") == start) - return 0; + r = sd_bus_match_signal_async( + bus, + &slot, + "org.freedesktop.systemd1", + "/org/freedesktop/systemd1", + "org.freedesktop.systemd1.Manager", + "JobRemoved", + match_job_removed, NULL, c); + if (r < 0) + return r; r = sd_bus_call_method( bus, @@ -359,13 +407,22 @@ static int unit_start_or_stop(UnitStatus "org.freedesktop.systemd1.Manager", start ? "StartUnit" : "StopUnit", error, - NULL, + &reply, "ss", u->name, "replace"); if (r < 0) return r; + r = sd_bus_message_read(reply, "o", &path); + if (r < 0) + return bus_log_parse_error(r); + + r = free_and_strdup(&c->path_ntp_unit, path); + if (r < 0) + return log_oom(); + + c->slot_job_removed = TAKE_PTR(slot); return 0; } @@ -417,8 +474,9 @@ static int unit_enable_or_disable(UnitSt error, NULL, NULL); - if (r < 0) - return r; + if (r < 0) + return r; + return 0; } @@ -808,7 +866,7 @@ static int method_set_ntp(sd_bus_message if (q < 0) r = q; - q = unit_start_or_stop(u, bus, error, enable); + q = unit_start_or_stop(c, u, bus, error, enable); if (q < 0) r = q; } @@ -822,17 +880,17 @@ static int method_set_ntp(sd_bus_message if (r < 0) continue; - r = unit_start_or_stop(u, bus, error, enable); + r = unit_start_or_stop(c, u, bus, error, enable); break; } - else if (context_ntp_service_is_active(c) <= 0) + else LIST_FOREACH(units, u, c->units) { if (!streq(u->load_state, "loaded") || !streq(u->unit_file_state, "enabled")) continue; - r = unit_start_or_stop(u, bus, error, enable); + r = unit_start_or_stop(c, u, bus, error, enable); break; } @@ -841,8 +899,6 @@ static int method_set_ntp(sd_bus_message log_info("Set NTP to %sd", enable_disable(enable)); - (void) sd_bus_emit_properties_changed(bus, "/org/freedesktop/timedate1", "org.freedesktop.timedate1", "NTP", NULL); - return sd_bus_reply_method_return(m, NULL); } diff -Naurp systemd-239-orig/src/timesync/timesyncd-bus.c systemd-239/src/timesync/timesyncd-bus.c --- systemd-239-orig/src/timesync/timesyncd-bus.c 2018-06-22 06:11:49.000000000 -0500 +++ systemd-239/src/timesync/timesyncd-bus.c 2018-11-04 08:49:10.237692714 -0600 @@ -185,7 +185,7 @@ int manager_connect_bus(Manager *m) { if (r < 0) return log_error_errno(r, "Failed to add manager object vtable: %m"); - r = bus_request_name_async_may_reload_dbus(m->bus, NULL, "org.freedesktop.timesync1", 0, NULL); + r = sd_bus_request_name_async(m->bus, NULL, "org.freedesktop.timesync1", 0, NULL, NULL); if (r < 0) return log_error_errno(r, "Failed to request name: %m"); diff -Naurp systemd-239-orig/src/tmpfiles/tmpfiles.c systemd-239/src/tmpfiles/tmpfiles.c --- systemd-239-orig/src/tmpfiles/tmpfiles.c 2018-06-22 06:11:49.000000000 -0500 +++ systemd-239/src/tmpfiles/tmpfiles.c 2018-11-04 08:49:10.237692714 -0600 @@ -1035,7 +1035,8 @@ static int fd_set_acls(Item *item, int f if (item->acl_access) r = path_set_acl(procfs_path, path, ACL_TYPE_ACCESS, item->acl_access, item->force); - if (r == 0 && item->acl_default) + /* set only default acls to folders */ + if (r == 0 && item->acl_default && S_ISDIR(st->st_mode)) r = path_set_acl(procfs_path, path, ACL_TYPE_DEFAULT, item->acl_default, item->force); if (r > 0) @@ -1052,7 +1053,7 @@ static int fd_set_acls(Item *item, int f static int path_set_acls(Item *item, const char *path) { int r = 0; -#ifdef HAVE_ACL +#if HAVE_ACL _cleanup_close_ int fd = -1; struct stat st; @@ -1067,9 +1068,9 @@ static int path_set_acls(Item *item, con return log_error_errno(errno, "Failed to fstat() file %s: %m", path); r = fd_set_acls(item, fd, &st); - #endif - return r; - } +#endif + return r; +} #define ATTRIBUTES_ALL \ (FS_NOATIME_FL | \ diff -Naurp systemd-239-orig/src/tty-ask-password-agent/tty-ask-password-agent.c systemd-239/src/tty-ask-password-agent/tty-ask-password-agent.c --- systemd-239-orig/src/tty-ask-password-agent/tty-ask-password-agent.c 2018-06-22 06:11:49.000000000 -0500 +++ systemd-239/src/tty-ask-password-agent/tty-ask-password-agent.c 2018-11-04 08:49:10.237692714 -0600 @@ -323,7 +323,7 @@ static int parse_password(const char *fi if (asprintf(&_wall, "%s%sPassword entry required for \'%s\' (PID %u).\r\n" - "Please enter password with the systemd-tty-ask-password-agent tool!", + "Please enter password with the systemd-tty-ask-password-agent tool:", strempty(*wall), *wall ? "\r\n\r\n" : "", message, diff -Naurp systemd-239-orig/src/udev/collect/collect.c systemd-239/src/udev/collect/collect.c --- systemd-239-orig/src/udev/collect/collect.c 2018-06-22 06:11:49.000000000 -0500 +++ systemd-239/src/udev/collect/collect.c 2018-11-04 08:49:10.238692713 -0600 @@ -60,7 +60,7 @@ static inline struct _mate *node_to_mate _noreturn_ static void sig_alrm(int signo) { - exit(4); + _exit(4); } static void usage(void) diff -Naurp systemd-239-orig/src/udev/meson.build systemd-239/src/udev/meson.build --- systemd-239-orig/src/udev/meson.build 2018-06-22 06:11:49.000000000 -0500 +++ systemd-239/src/udev/meson.build 2018-11-04 08:49:10.238692713 -0600 @@ -123,6 +123,7 @@ install_libudev_static = static_library( shared_sources, libsystemd_sources, libudev_sources, + disable_mempool_c, include_directories : includes, build_by_default : static_libudev != 'false', install : static_libudev != 'false', @@ -134,7 +135,7 @@ install_libudev_static = static_library( libudev = shared_library( 'udev', - 'udev.h', # pick a header file at random to work around old meson bug + disable_mempool_c, version : libudev_version, include_directories : includes, link_args : ['-shared', diff -Naurp systemd-239-orig/src/udev/net/ethtool-util.c systemd-239/src/udev/net/ethtool-util.c --- systemd-239-orig/src/udev/net/ethtool-util.c 2018-06-22 06:11:49.000000000 -0500 +++ systemd-239/src/udev/net/ethtool-util.c 2018-11-04 08:49:10.238692713 -0600 @@ -320,7 +320,7 @@ int ethtool_set_features(int *fd, const if (r < 0) return log_warning_errno(r, "link_config: could not get ethtool features for %s", ifname); - sfeatures = alloca0(sizeof(struct ethtool_gstrings) + DIV_ROUND_UP(strings->len, 32U) * sizeof(sfeatures->features[0])); + sfeatures = alloca0(sizeof(struct ethtool_sfeatures) + DIV_ROUND_UP(strings->len, 32U) * sizeof(sfeatures->features[0])); sfeatures->cmd = ETHTOOL_SFEATURES; sfeatures->size = DIV_ROUND_UP(strings->len, 32U); diff -Naurp systemd-239-orig/src/udev/udev-builtin-kmod.c systemd-239/src/udev/udev-builtin-kmod.c --- systemd-239-orig/src/udev/udev-builtin-kmod.c 2018-06-22 06:11:49.000000000 -0500 +++ systemd-239/src/udev/udev-builtin-kmod.c 2018-11-04 08:49:10.238692713 -0600 @@ -18,55 +18,23 @@ static struct kmod_ctx *ctx = NULL; -static int load_module(struct udev *udev, const char *alias) { - _cleanup_(kmod_module_unref_listp) struct kmod_list *list = NULL; - struct kmod_list *l; - int err; - - err = kmod_module_new_from_lookup(ctx, alias, &list); - if (err < 0) - return err; - - if (list == NULL) - log_debug("No module matches '%s'", alias); - - kmod_list_foreach(l, list) { - _cleanup_(kmod_module_unrefp) struct kmod_module *mod = NULL; - - mod = kmod_module_get_module(l); - - err = kmod_module_probe_insert_module(mod, KMOD_PROBE_APPLY_BLACKLIST, NULL, NULL, NULL, NULL); - if (err == KMOD_PROBE_APPLY_BLACKLIST) - log_debug("Module '%s' is blacklisted", kmod_module_get_name(mod)); - else if (err == 0) - log_debug("Inserted '%s'", kmod_module_get_name(mod)); - else - log_debug("Failed to insert '%s'", kmod_module_get_name(mod)); - } - - return err; -} - _printf_(6,0) static void udev_kmod_log(void *data, int priority, const char *file, int line, const char *fn, const char *format, va_list args) { log_internalv(priority, 0, file, line, fn, format, args); } static int builtin_kmod(struct udev_device *dev, int argc, char *argv[], bool test) { - struct udev *udev = udev_device_get_udev(dev); int i; if (!ctx) return 0; if (argc < 3 || !streq(argv[1], "load")) { - log_error("expect: %s load ", argv[0]); + log_error("%s: expected: load ", argv[0]); return EXIT_FAILURE; } - for (i = 2; argv[i]; i++) { - log_debug("Execute '%s' '%s'", argv[1], argv[i]); - load_module(udev, argv[i]); - } + for (i = 2; argv[i]; i++) + (void) module_load_and_warn(ctx, argv[i], false); return EXIT_SUCCESS; } diff -Naurp systemd-239-orig/src/udev/udev-ctrl.c systemd-239/src/udev/udev-ctrl.c --- systemd-239-orig/src/udev/udev-ctrl.c 2018-06-22 06:11:49.000000000 -0500 +++ systemd-239/src/udev/udev-ctrl.c 2018-11-04 08:49:10.238692713 -0600 @@ -119,7 +119,7 @@ int udev_ctrl_enable_receiving(struct ud if (!uctrl->bound) { err = bind(uctrl->sock, &uctrl->saddr.sa, uctrl->addrlen); if (err < 0 && errno == EADDRINUSE) { - unlink(uctrl->saddr.un.sun_path); + (void) sockaddr_un_unlink(&uctrl->saddr.un); err = bind(uctrl->sock, &uctrl->saddr.sa, uctrl->addrlen); } @@ -161,7 +161,7 @@ int udev_ctrl_cleanup(struct udev_ctrl * if (uctrl == NULL) return 0; if (uctrl->cleanup_socket) - unlink(uctrl->saddr.un.sun_path); + sockaddr_un_unlink(&uctrl->saddr.un); return 0; } diff -Naurp systemd-239-orig/sysctl.d/50-default.conf systemd-239/sysctl.d/50-default.conf --- systemd-239-orig/sysctl.d/50-default.conf 2018-06-22 06:11:49.000000000 -0500 +++ systemd-239/sysctl.d/50-default.conf 2018-11-04 08:49:10.239692713 -0600 @@ -33,9 +33,6 @@ net.ipv4.conf.all.promote_secondaries = # Fair Queue CoDel packet scheduler to fight bufferbloat net.core.default_qdisc = fq_codel -# Request Explicit Congestion Notification (ECN) on both in and outgoing connections -net.ipv4.tcp_ecn = 1 - # Enable hard and soft link protection fs.protected_hardlinks = 1 fs.protected_symlinks = 1 diff -Naurp systemd-239-orig/sysusers.d/systemd.conf.m4 systemd-239/sysusers.d/systemd.conf.m4 --- systemd-239-orig/sysusers.d/systemd.conf.m4 2018-06-22 06:11:49.000000000 -0500 +++ systemd-239/sysusers.d/systemd.conf.m4 2018-11-04 08:49:10.239692713 -0600 @@ -6,6 +6,15 @@ # (at your option) any later version. g systemd-journal - - +m4_ifdef(`ENABLE_NETWORKD', +u systemd-network - "systemd Network Management" +)m4_dnl +m4_ifdef(`ENABLE_RESOLVE', +u systemd-resolve - "systemd Resolver" +)m4_dnl +m4_ifdef(`ENABLE_TIMESYNCD', +u systemd-timesync - "systemd Time Synchronization" +)m4_dnl m4_ifdef(`ENABLE_COREDUMP', u systemd-coredump - "systemd Core Dumper" )m4_dnl diff -Naurp systemd-239-orig/test/fuzz-regressions/fuzz-bus-message/crash-e1b811da5ca494e494b77c6bd8e1c2f2989425c5 systemd-239/test/fuzz-regressions/fuzz-bus-message/crash-e1b811da5ca494e494b77c6bd8e1c2f2989425c5 --- systemd-239-orig/test/fuzz-regressions/fuzz-bus-message/crash-e1b811da5ca494e494b77c6bd8e1c2f2989425c5 1969-12-31 18:00:00.000000000 -0600 +++ systemd-239/test/fuzz-regressions/fuzz-bus-message/crash-e1b811da5ca494e494b77c6bd8e1c2f2989425c5 2018-11-04 08:49:10.241692711 -0600 @@ -0,0 +1 @@ +l g(abv) \ No newline at end of file diff -Naurp systemd-239-orig/test/meson.build systemd-239/test/meson.build --- systemd-239-orig/test/meson.build 2018-06-22 06:11:49.000000000 -0500 +++ systemd-239/test/meson.build 2018-11-04 08:49:10.243692711 -0600 @@ -45,6 +45,8 @@ test_data_files = ''' test-execute/exec-cpuaffinity1.service test-execute/exec-cpuaffinity2.service test-execute/exec-cpuaffinity3.service + test-execute/exec-dynamicuser-fixeduser-adm.service + test-execute/exec-dynamicuser-fixeduser-games.service test-execute/exec-dynamicuser-fixeduser-one-supplementarygroup.service test-execute/exec-dynamicuser-fixeduser.service test-execute/exec-dynamicuser-statedir-migrate-step1.service diff -Naurp systemd-239-orig/test/test-execute/exec-dynamicuser-fixeduser-adm.service systemd-239/test/test-execute/exec-dynamicuser-fixeduser-adm.service --- systemd-239-orig/test/test-execute/exec-dynamicuser-fixeduser-adm.service 1969-12-31 18:00:00.000000000 -0600 +++ systemd-239/test/test-execute/exec-dynamicuser-fixeduser-adm.service 2018-11-04 08:49:10.244692710 -0600 @@ -0,0 +1,11 @@ +[Unit] +Description=Test DynamicUser with static User= whose uid and gid are different +# On Fedora, user adm has uid==3 and gid==4. + +[Service] +Type=oneshot +ExecStart=/bin/sh -x -c 'test "$$(id -nG)" = "adm" && test "$$(id -ng)" = "adm" && test "$$(id -nu)" = "adm"' +# Multiple ExecStart= lines causes the issue #9702. +ExecStart=/bin/sh -x -c 'test "$$(id -nG)" = "adm" && test "$$(id -ng)" = "adm" && test "$$(id -nu)" = "adm"' +DynamicUser=yes +User=adm diff -Naurp systemd-239-orig/test/test-execute/exec-dynamicuser-fixeduser-games.service systemd-239/test/test-execute/exec-dynamicuser-fixeduser-games.service --- systemd-239-orig/test/test-execute/exec-dynamicuser-fixeduser-games.service 1969-12-31 18:00:00.000000000 -0600 +++ systemd-239/test/test-execute/exec-dynamicuser-fixeduser-games.service 2018-11-04 08:49:10.244692710 -0600 @@ -0,0 +1,11 @@ +[Unit] +Description=Test DynamicUser with static User= whose uid and gid are different +# On Ubuntu or Debian, user games has uid==5 and gid==60. + +[Service] +Type=oneshot +ExecStart=/bin/sh -x -c 'test "$$(id -nG)" = "games" && test "$$(id -ng)" = "games" && test "$$(id -nu)" = "games"' +# Multiple ExecStart= lines causes the issue #9702. +ExecStart=/bin/sh -x -c 'test "$$(id -nG)" = "games" && test "$$(id -ng)" = "games" && test "$$(id -nu)" = "games"' +DynamicUser=yes +User=games diff -Naurp systemd-239-orig/test/test-execute/exec-privatenetwork-yes.service systemd-239/test/test-execute/exec-privatenetwork-yes.service --- systemd-239-orig/test/test-execute/exec-privatenetwork-yes.service 2018-06-22 06:11:49.000000000 -0500 +++ systemd-239/test/test-execute/exec-privatenetwork-yes.service 2018-11-04 08:49:10.244692710 -0600 @@ -2,6 +2,6 @@ Description=Test for PrivateNetwork [Service] -ExecStart=/bin/sh -x -c '! ip link | grep ": " | grep -Ev ": (lo|sit0@.*):"' +ExecStart=/bin/sh -x -c '! ip link | grep ": " | grep -Ev ": (lo|(sit0|ip6tnl0|ip6gre0)@.*):"' Type=oneshot PrivateNetwork=yes diff -Naurp systemd-239-orig/tmpfiles.d/systemd.conf.m4 systemd-239/tmpfiles.d/systemd.conf.m4 --- systemd-239-orig/tmpfiles.d/systemd.conf.m4 2018-06-22 06:11:49.000000000 -0500 +++ systemd-239/tmpfiles.d/systemd.conf.m4 2018-11-04 08:49:10.246692710 -0600 @@ -17,9 +17,9 @@ d /run/systemd/users 0755 root root - d /run/systemd/machines 0755 root root - d /run/systemd/shutdown 0755 root root - m4_ifdef(`ENABLE_NETWORKD', -d /run/systemd/netif - - - - -d /run/systemd/netif/links - - - - -d /run/systemd/netif/leases - - - - +d /run/systemd/netif 0755 systemd-network systemd-network - +d /run/systemd/netif/links 0755 systemd-network systemd-network - +d /run/systemd/netif/leases 0755 systemd-network systemd-network - )m4_dnl d /run/log 0755 root root - diff -Naurp systemd-239-orig/tools/gdb-sd_dump_hashmaps.py systemd-239/tools/gdb-sd_dump_hashmaps.py --- systemd-239-orig/tools/gdb-sd_dump_hashmaps.py 2018-06-22 06:11:49.000000000 -0500 +++ systemd-239/tools/gdb-sd_dump_hashmaps.py 2018-11-04 08:49:10.246692710 -0600 @@ -2,6 +2,8 @@ # -*- Mode: python; coding: utf-8; indent-tabs-mode: nil -*- */ # SPDX-License-Identifier: LGPL-2.1+ +from __future__ import print_function + import gdb class sd_dump_hashmaps(gdb.Command): @@ -19,7 +21,7 @@ class sd_dump_hashmaps(gdb.Command): ulong_t = gdb.lookup_type("unsigned long") debug_offset = gdb.parse_and_eval("(unsigned long)&((HashmapBase*)0)->debug") - print "type, hash, indirect, entries, max_entries, buckets, creator" + print("type, hash, indirect, entries, max_entries, buckets, creator") while d: h = gdb.parse_and_eval("(HashmapBase*)((char*)%d - %d)" % (int(d.cast(ulong_t)), debug_offset)) @@ -34,7 +36,7 @@ class sd_dump_hashmaps(gdb.Command): t = ["plain", "ordered", "set"][int(h["type"])] - print "{}, {}, {}, {}, {}, {}, {} ({}:{})".format(t, h["hash_ops"], bool(h["has_indirect"]), n_entries, d["max_entries"], n_buckets, d["func"], d["file"], d["line"]) + print("{}, {}, {}, {}, {}, {}, {} ({}:{})".format(t, h["hash_ops"], bool(h["has_indirect"]), n_entries, d["max_entries"], n_buckets, d["func"], d["file"], d["line"])) if arg != "" and n_entries > 0: dib_raw_addr = storage_ptr + (all_entry_sizes[h["type"]] * n_buckets) @@ -46,10 +48,10 @@ class sd_dump_hashmaps(gdb.Command): for dib in sorted(iter(histogram)): if dib != 255: - print "{:>3} {:>8} {} of entries".format(dib, histogram[dib], 100.0*histogram[dib]/n_entries) + print("{:>3} {:>8} {} of entries".format(dib, histogram[dib], 100.0*histogram[dib]/n_entries)) else: - print "{:>3} {:>8} {} of slots".format(dib, histogram[dib], 100.0*histogram[dib]/n_buckets) - print "mean DIB of entries: {}".format(sum([dib*histogram[dib] for dib in iter(histogram) if dib != 255])*1.0/n_entries) + print("{:>3} {:>8} {} of slots".format(dib, histogram[dib], 100.0*histogram[dib]/n_buckets)) + print("mean DIB of entries: {}".format(sum([dib*histogram[dib] for dib in iter(histogram) if dib != 255])*1.0/n_entries)) blocks = [] current_len = 1 @@ -70,9 +72,9 @@ class sd_dump_hashmaps(gdb.Command): if len(blocks) > 1 and blocks[0][0] == blocks[0][1] and blocks[-1][0] == n_buckets - 1: blocks[0][1] += blocks[-1][1] blocks = blocks[0:-1] - print "max block: {}".format(max(blocks, key=lambda a: a[1])) - print "sum block lens: {}".format(sum(b[1] for b in blocks)) - print "mean block len: {}".format((1.0 * sum(b[1] for b in blocks) / len(blocks))) + print("max block: {}".format(max(blocks, key=lambda a: a[1]))) + print("sum block lens: {}".format(sum(b[1] for b in blocks))) + print("mean block len: {}".format((1.0 * sum(b[1] for b in blocks) / len(blocks)))) d = d["debug_list_next"] diff -Naurp systemd-239-orig/units/meson-add-wants.sh systemd-239/units/meson-add-wants.sh --- systemd-239-orig/units/meson-add-wants.sh 2018-06-22 06:11:49.000000000 -0500 +++ systemd-239/units/meson-add-wants.sh 2018-11-04 08:49:10.246692710 -0600 @@ -18,10 +18,10 @@ unitpath="${DESTDIR:-}${unitdir}/${unit} case "$target" in */) - mkdir -p -m 0755 "$dir" + mkdir -vp -m 0755 "$dir" ;; *) - mkdir -p -m 0755 "$(basename "$dir")" + mkdir -vp -m 0755 "$(dirname "$dir")" ;; esac diff -Naurp systemd-239-orig/units/systemd-ask-password-console.path systemd-239/units/systemd-ask-password-console.path --- systemd-239-orig/units/systemd-ask-password-console.path 2018-06-22 06:11:49.000000000 -0500 +++ systemd-239/units/systemd-ask-password-console.path 2018-11-04 08:49:10.247692709 -0600 @@ -11,7 +11,7 @@ Description=Dispatch Password Requests to Console Directory Watch Documentation=man:systemd-ask-password-console.service(8) DefaultDependencies=no -Conflicts=shutdown.target +Conflicts=shutdown.target emergency.service After=plymouth-start.service Before=paths.target shutdown.target cryptsetup.target ConditionPathExists=!/run/plymouth/pid diff -Naurp systemd-239-orig/units/systemd-ask-password-console.service.in systemd-239/units/systemd-ask-password-console.service.in --- systemd-239-orig/units/systemd-ask-password-console.service.in 2018-06-22 06:11:49.000000000 -0500 +++ systemd-239/units/systemd-ask-password-console.service.in 2018-11-04 08:49:10.247692709 -0600 @@ -11,7 +11,7 @@ Description=Dispatch Password Requests to Console Documentation=man:systemd-ask-password-console.service(8) DefaultDependencies=no -Conflicts=shutdown.target +Conflicts=shutdown.target emergency.service After=plymouth-start.service systemd-vconsole-setup.service Before=shutdown.target ConditionPathExists=!/run/plymouth/pid diff -Naurp systemd-239-orig/units/systemd-ask-password-wall.path systemd-239/units/systemd-ask-password-wall.path --- systemd-239-orig/units/systemd-ask-password-wall.path 2018-06-22 06:11:49.000000000 -0500 +++ systemd-239/units/systemd-ask-password-wall.path 2018-11-04 08:49:10.247692709 -0600 @@ -11,7 +11,7 @@ Description=Forward Password Requests to Wall Directory Watch Documentation=man:systemd-ask-password-console.service(8) DefaultDependencies=no -Conflicts=shutdown.target +Conflicts=shutdown.target emergency.service Before=paths.target shutdown.target cryptsetup.target [Path] diff -Naurp systemd-239-orig/units/systemd-journal-flush.service.in systemd-239/units/systemd-journal-flush.service.in --- systemd-239-orig/units/systemd-journal-flush.service.in 2018-06-22 06:11:49.000000000 -0500 +++ systemd-239/units/systemd-journal-flush.service.in 2018-11-04 08:49:10.247692709 -0600 @@ -12,9 +12,8 @@ Description=Flush Journal to Persistent Documentation=man:systemd-journald.service(8) man:journald.conf(5) DefaultDependencies=no Requires=systemd-journald.service -After=systemd-journald.service -After=systemd-remount-fs.service -Before=systemd-user-sessions.service systemd-tmpfiles-setup.service +After=systemd-journald.service systemd-remount-fs.service +Before=systemd-tmpfiles-setup.service RequiresMountsFor=/var/log/journal [Service] diff -Naurp systemd-239-orig/units/systemd-networkd.service.in systemd-239/units/systemd-networkd.service.in --- systemd-239-orig/units/systemd-networkd.service.in 2018-06-22 06:11:49.000000000 -0500 +++ systemd-239/units/systemd-networkd.service.in 2018-11-04 08:49:10.247692709 -0600 @@ -13,7 +13,7 @@ Documentation=man:systemd-networkd.servi ConditionCapability=CAP_NET_ADMIN DefaultDependencies=no # systemd-udevd.service can be dropped once tuntap is moved to netlink -After=systemd-udevd.service network-pre.target systemd-sysctl.service +After=systemd-udevd.service network-pre.target systemd-sysusers.service systemd-sysctl.service Before=network.target multi-user.target shutdown.target Conflicts=shutdown.target Wants=network.target @@ -25,9 +25,9 @@ RestartSec=0 ExecStart=!!@rootlibexecdir@/systemd-networkd WatchdogSec=3min User=systemd-network -DynamicUser=yes CapabilityBoundingSet=CAP_NET_ADMIN CAP_NET_BIND_SERVICE CAP_NET_BROADCAST CAP_NET_RAW AmbientCapabilities=CAP_NET_ADMIN CAP_NET_BIND_SERVICE CAP_NET_BROADCAST CAP_NET_RAW +ProtectSystem=strict ProtectHome=yes ProtectControlGroups=yes ProtectKernelModules=yes diff -Naurp systemd-239-orig/units/systemd-resolved.service.in systemd-239/units/systemd-resolved.service.in --- systemd-239-orig/units/systemd-resolved.service.in 2018-06-22 06:11:49.000000000 -0500 +++ systemd-239/units/systemd-resolved.service.in 2018-11-04 08:49:10.247692709 -0600 @@ -14,7 +14,7 @@ Documentation=https://www.freedesktop.or Documentation=https://www.freedesktop.org/wiki/Software/systemd/writing-network-configuration-managers Documentation=https://www.freedesktop.org/wiki/Software/systemd/writing-resolver-clients DefaultDependencies=no -After=systemd-networkd.service +After=systemd-sysusers.service systemd-networkd.service Before=network.target nss-lookup.target shutdown.target Conflicts=shutdown.target Wants=nss-lookup.target @@ -26,10 +26,11 @@ RestartSec=0 ExecStart=!!@rootlibexecdir@/systemd-resolved WatchdogSec=3min User=systemd-resolve -DynamicUser=yes CapabilityBoundingSet=CAP_SETPCAP CAP_NET_RAW CAP_NET_BIND_SERVICE AmbientCapabilities=CAP_SETPCAP CAP_NET_RAW CAP_NET_BIND_SERVICE +PrivateTmp=yes PrivateDevices=yes +ProtectSystem=strict ProtectHome=yes ProtectControlGroups=yes ProtectKernelTunables=yes diff -Naurp systemd-239-orig/units/systemd-timesyncd.service.in systemd-239/units/systemd-timesyncd.service.in --- systemd-239-orig/units/systemd-timesyncd.service.in 2018-06-22 06:11:49.000000000 -0500 +++ systemd-239/units/systemd-timesyncd.service.in 2018-11-04 08:49:10.248692708 -0600 @@ -13,7 +13,7 @@ Documentation=man:systemd-timesyncd.serv ConditionCapability=CAP_SYS_TIME ConditionVirtualization=!container DefaultDependencies=no -After=systemd-remount-fs.service +After=systemd-remount-fs.service systemd-sysusers.service Before=time-sync.target sysinit.target shutdown.target Conflicts=shutdown.target Wants=time-sync.target @@ -25,10 +25,11 @@ RestartSec=0 ExecStart=!!@rootlibexecdir@/systemd-timesyncd WatchdogSec=3min User=systemd-timesync -DynamicUser=yes CapabilityBoundingSet=CAP_SYS_TIME AmbientCapabilities=CAP_SYS_TIME +PrivateTmp=yes PrivateDevices=yes +ProtectSystem=strict ProtectHome=yes ProtectControlGroups=yes ProtectKernelTunables=yes diff -Naurp systemd-239-orig/units/systemd-tmpfiles-setup.service.in systemd-239/units/systemd-tmpfiles-setup.service.in --- systemd-239-orig/units/systemd-tmpfiles-setup.service.in 2018-06-22 06:11:49.000000000 -0500 +++ systemd-239/units/systemd-tmpfiles-setup.service.in 2018-11-04 08:49:10.248692708 -0600 @@ -12,7 +12,7 @@ Description=Create Volatile Files and Di Documentation=man:tmpfiles.d(5) man:systemd-tmpfiles(8) DefaultDependencies=no Conflicts=shutdown.target -After=local-fs.target systemd-sysusers.service +After=local-fs.target systemd-sysusers.service systemd-journald.service Before=sysinit.target shutdown.target RefuseManualStop=yes diff -Naurp systemd-239-orig/units/user-runtime-dir@.service.in systemd-239/units/user-runtime-dir@.service.in --- systemd-239-orig/units/user-runtime-dir@.service.in 2018-06-22 06:11:49.000000000 -0500 +++ systemd-239/units/user-runtime-dir@.service.in 2018-11-04 08:49:10.248692708 -0600 @@ -8,10 +8,15 @@ # (at your option) any later version. [Unit] -Description=/run/user/%i mount wrapper +Description=User Runtime Directory /run/user/%i +Documentation=man:user@.service(5) +After=systemd-user-sessions.service dbus.service StopWhenUnneeded=yes +IgnoreOnIsolate=yes [Service] ExecStart=@rootlibexecdir@/systemd-user-runtime-dir start %i ExecStop=@rootlibexecdir@/systemd-user-runtime-dir stop %i +Type=oneshot RemainAfterExit=true +Slice=user-%i.slice diff -Naurp systemd-239-orig/units/user@.service.in systemd-239/units/user@.service.in --- systemd-239-orig/units/user@.service.in 2018-06-22 06:11:49.000000000 -0500 +++ systemd-239/units/user@.service.in 2018-11-04 08:49:10.248692708 -0600 @@ -9,9 +9,11 @@ [Unit] Description=User Manager for UID %i +Documentation=man:user@.service(5) After=systemd-user-sessions.service After=user-runtime-dir@%i.service Requires=user-runtime-dir@%i.service +IgnoreOnIsolate=yes [Service] User=%i diff -Naurp systemd-239-orig/units/user-.slice.d/10-defaults.conf systemd-239/units/user-.slice.d/10-defaults.conf --- systemd-239-orig/units/user-.slice.d/10-defaults.conf 2018-06-22 06:11:49.000000000 -0500 +++ systemd-239/units/user-.slice.d/10-defaults.conf 2018-11-04 08:49:10.248692708 -0600 @@ -9,7 +9,9 @@ [Unit] Description=User Slice of UID %j +Documentation=man:user@.service(5) After=systemd-user-sessions.service +StopWhenUnneeded=yes [Slice] TasksMax=33%