Integralność przepływu sterowania w jądrze

Integralność przepływu sterowania (CFI) to mechanizm zabezpieczeń, który uniemożliwia wprowadzanie zmian w oryginalnym grafie przepływu sterowania skompilowanego pliku binarnego, co znacznie utrudnia przeprowadzanie takich ataków.

Od Androida 9 możesz włączyć CFI w jądrze.

Jądro systemu Linux ma 2 różne implementacje CFI:

  • w przypadku Linuksa 6.0 i starszych wersji – Clang CFI, która opiera się na Clang LTO,
  • w przypadku Linuksa 6.1 i nowszych wersji – Clang KCFI.

Clang CFI wymaga kompilacji z optymalizacją czasu łączenia (LTO). LTO zachowuje reprezentację kodu bitowego LLVM plików obiektowych do czasu łączenia, co pozwala kompilatorowi lepiej określić, jakie optymalizacje można zastosować. Podczas testów w Androidzie połączenie LTO i CFI spowodowało znikome obciążenie rozmiaru kodu i wydajności. Włączenie LTO znacznie wydłuża jednak czas kompilacji jądra.

Clang KCFI nie wymaga LTO, więc nowsze jądra Androida korzystają z CFI bez obciążenia związanego z czasem kompilacji LTO.

Implementacja

CFI jest kontrolowana przez opcję CONFIG_CFI_CLANG, która włącza Clang CFI lub Clang KCFI.

Więcej informacji technicznych o CFI i sposobie obsługi innych kontroli przepływu sterowania znajdziesz w dokumentacji projektu LLVM. KCFI jest tam określana jako -fsanitize=kcfi.

Rozwiązywanie problemów

Po włączeniu CFI rozwiąż wszelkie błędy niezgodności typów, które mogą występować w sterownikach. Pośrednie wywołanie funkcji za pomocą niezgodnego wskaźnika funkcji powoduje wyzwolenie CFI. Gdy zostanie wykryty błąd CFI, jądro wyświetli ostrzeżenie, które zawiera zarówno wywołaną funkcję, jak i ślad stosu, który doprowadził do błędu. Aby to naprawić, upewnij się, że wskaźniki funkcji zawsze mają ten sam typ co wywoływana funkcja.

Aby ułatwić debugowanie błędów CFI, włącz CONFIG_CFI_PERMISSIVE, która wyświetla ostrzeżenie zamiast powodować panikę jądra. Trybu permisywnego nie należy używać w środowisku produkcyjnym.

Weryfikacja

Obecnie nie ma testów CTS przeznaczonych specjalnie do CFI. Zamiast tego upewnij się, że testy CTS przechodzą z włączoną i wyłączoną CFI, aby sprawdzić, czy CFI nie ma wpływu na urządzenie.