Powtarzalne kompilacje
Kompilacje odtwarzalne , zwane także kompilacjami deterministycznymi , to proces kompilacji oprogramowania, który zapewnia możliwość odtworzenia powstałego kodu binarnego . Kod źródłowy skompilowany przy użyciu kompilacji deterministycznej zawsze będzie generował ten sam plik binarny.
Powtarzalne kompilacje mogą działać jako część łańcucha zaufania ; kod źródłowy można podpisać, a kompilacja deterministyczna może udowodnić, że plik binarny został skompilowany z zaufanego kodu źródłowego. Zweryfikowane, powtarzalne kompilacje stanowią silny środek zaradczy przed atakami, w których pliki binarne nie odpowiadają ich kodowi źródłowemu, np. dlatego, że osoba atakująca umieściła złośliwy kod w pliku binarnym. To jest odpowiedni atak; napastnicy czasami atakują pliki binarne, ale nie kod źródłowy, np. dlatego, że mogą zmienić jedynie rozproszony plik binarny lub aby uniknąć wykrycia, ponieważ jest to kod źródłowy, który programiści zwykle przeglądają i modyfikują. W ankiecie przeprowadzonej wśród 17 ekspertów powtarzalne konstrukcje uzyskały bardzo wysoką ocenę użyteczności od 58,8% uczestników, ale także ocenę wysokiego kosztu od 70,6%. Podejmowane są różne wysiłki mające na celu modyfikację narzędzi do tworzenia oprogramowania w celu zmniejszenia tych kosztów.
Metody
Aby proces kompilacji był deterministyczny, dane wejściowe kompilatora muszą być takie same, niezależnie od używanego środowiska kompilacji. Zwykle wiąże się to z normalizacją zmiennych , które mogą się zmieniać, takich jak kolejność plików wejściowych, znaczniki czasu , ustawienia regionalne i ścieżki .
Ponadto kompilatory nie mogą same wprowadzać niedeterminizmu. Czasami dzieje się tak, gdy używasz tabel skrótów z losową wartością początkową skrótu. Może się to również zdarzyć podczas używania adresu zmiennych, ponieważ różni się to od randomizacji układu przestrzeni adresowej (ASLR).
Systemy kompilacji , takie jak Bazel i Gitian, mogą służyć do automatyzacji deterministycznych procesów kompilacji.
Historia
Projekt GNU wykorzystywał powtarzalne kompilacje na początku lat 90-tych. Dzienniki zmian z 1992 roku wskazują na ciągłe wysiłki.
Jednym ze starszych projektów promujących powtarzalne kompilacje jest projekt Bitcoin z Gitianem. Później, w 2013 roku, Tor (sieć anonimowości) zaczął używać Gitian do swoich powtarzalnych kompilacji.
W lipcu 2013 roku projekt Debian rozpoczął wdrażanie odtwarzalnych kompilacji w całym archiwum pakietów.
Do lipca 2017 r. udowodniono, że ponad 90% pakietów w repozytorium buduje się w sposób powtarzalny.
W listopadzie 2018 roku projekt Reproducible Builds dołączył do Software Freedom Conservancy .
F-droid wykorzystuje powtarzalne kompilacje, aby zagwarantować, że dystrybuowane pliki APK korzystają z deklarowanego darmowego kodu źródłowego .
Tails wykorzystuje powtarzalne kompilacje i wyjaśnia innym, jak zweryfikować ich dystrybucję .
NixOS twierdzi, że kompilacja jest w 100% odtwarzalna w czerwcu 2021 r.
Wyzwania
Według projektu Reproducible Builds znaczniki czasu są „największym źródłem problemów z odtwarzalnością. Wiele narzędzi do tworzenia rejestruje bieżącą datę i godzinę… a większość formatów archiwów z radością rejestruje czasy modyfikacji na podstawie własnych znaczników czasu”. Zalecają, aby „lepiej użyć daty istotnej dla kodu źródłowego zamiast kompilacji: stare oprogramowanie zawsze można zbudować później”, jeśli można je odtworzyć. Identyfikują kilka sposobów modyfikowania procesów kompilacji, aby to zrobić:
- Ustaw zmienną środowiskową SOURCE_DATE_EPOCH na liczbę sekund od 1 stycznia 1970, używając czegoś z kodu źródłowego. Narzędzia obsługujące tę zmienną środowiskową będą używać jej wartości (jeśli jest ustawiona) zamiast bieżącej daty i godziny.
- Dane wyjściowe przetwarzania końcowego w celu usunięcia znaczników czasu lub ich normalizacji. Często może w tym pomóc niedeterminizm paska narzędzi.
- Użyj biblioteki takiej jak libfaketime, aby przechwytywać żądania dotyczące bieżącej pory dnia i zapewniać kontrolowaną odpowiedź.
W niektórych przypadkach należy wprowadzić inne zmiany, aby proces kompilacji był powtarzalny. Na przykład niektóre struktury danych nie gwarantują stabilnego porządku przy każdym wykonaniu. Typowym rozwiązaniem jest modyfikacja procesu kompilacji w celu określenia posortowanych wyników tych struktur.