FORTIFY_SOURCE¶
Sınırsız libc çağrılarını, tespit edilen overflow'da abort eden bounds-aware
__*_chkvaryantlarına yeniden yazan glibc+compiler hardening (-D_FORTIFY_SOURCE=1/2/3).
Mechanism¶
Note
Flag set edilip optimization açıkken compiler, memcpy/strcpy/sprintf
gibi çağrıları __memcpy_chk/__strcpy_chk/__sprintf_chk ile değiştirir ve
fazladan bir argüman geçirir: __builtin_object_size(dest, type)'tan gelen,
compiler'ın hedef object boyutu tahmini. _chk fonksiyonu istenen uzunluğu
bilinen boyutla karşılaştırır ve overrun durumunda __chk_fail() çağırır (ki o
da abort() eder). Check, compiler'ın object'e dair görüşüne dayandığı için
boyutun çözülebilmesi adına çağrının tipik olarak inline edilebilir olması gerekir
ve optimization (-O1+) şarttır — -O0'da hiç fortification yoktur.
Level 3 (GCC 12+, Clang) yerine __builtin_dynamic_object_size koyar ve runtime
bir boyut ifadesi üretir; böylece heap/dinamik boyutlu buffer'lar da check edilebilir.
Walkthrough¶
char a[3]; strcpy(a, longstring); için compiler
__strcpy_chk(a, longstring, 3) üretir; runtime'da bir overrun abort eder:
Level farkları:
=1,__builtin_object_size(a, 0)kullanır — gevşek, tüm-allocation görüşü.=2, daha katı olan__builtin_object_size(a, 1)kullanır:strcpy(&g.b.a[1], b)için level 1 boyut11(tam struct) verirken level 23(yalnızca en içteki field) verir.=2ayrıca yazılabilir bir format string içindeki%n'i de işaretler:*** %n in writable segment detected ***.=3,__builtin_dynamic_object_sizekullanır, böylecemalloc(n)buffer'ları runtime'da check edilebilir.
Detection¶
Gözlemlenebilir iz, *** buffer overflow detected *** (veya *** %n in
writable segment detected ***) mesajıyla gelen runtime abort()'tur.
Mitigation¶
Warning
Kapsam, object boyutunun compiler tarafından bilindiği durumlarla sınırlıdır.
Boyut opak ise — =1/=2'de birçok heap pointer, inline edilmemiş sınırlar
boyunca geçen pointer'lar veya optimizer'ın fold edemediği boyutlar —
__builtin_object_size, (size_t)-1 döner ve çağrı check edilmeyen libc
fonksiyonuna düşer, yani overflow yakalanmaz.
Yalnızca glibc'nin _chk wrapper'ı sağladığı libc fonksiyonlarını fortify eder;
doğrudan buffer write'ları, özel copy loop'ları ve read()-into-buffer kapsam
dışıdır. Kernel karşılığı için
FORTIFY_SOURCE against canary leaks ve
hardened usercopy'ye bakın.