UnDefinitionBehaviorSanitizer (UBSan), çeşitli tanımlanmamış davranış türlerini kontrol etmek için derleme zamanı izlemesi gerçekleştirir. UBSan birçok tanımlanmamış davranış hatasını tespit edebilme yeteneğine sahip olsa da Android şunları destekler:
- hizalama
- bool
- sınırlar
- Sıralama
- şamandıra-döküm-taşma
- kayan nokta sıfıra bölme
- tam sayı sıfıra bölme
- boş olmayan öznitelik
- hükümsüz
- geri dönmek
- null olmayan özniteliği döndürür
- vardiya tabanı
- kaydırma üssü
- işaretli-tamsayı-taşması
- ulaşılamaz
- işaretsiz-tamsayı-taşması
- vla'ya bağlı
imzasız tamsayı taşması, teknik olarak tanımlanmamış bir davranış olmasa da, temizleyiciye dahil edilir ve gizli tamsayı taşması güvenlik açıklarını ortadan kaldırmak için medya sunucusu bileşenleri de dahil olmak üzere birçok Android modülünde kullanılır.
Uygulama
Android derleme sisteminde UBSan'ı global veya yerel olarak etkinleştirebilirsiniz. UBSan'ı global olarak etkinleştirmek için Android.mk'de SANITIZE_TARGET ayarını yapın. UBSan'ı modül bazında etkinleştirmek için LOCAL_SANITIZE ayarını yapın ve Android.mk'de aramak istediğiniz tanımsız davranışları belirtin. Örneğin:
LOCAL_PATH:= $(call my-dir) include $(CLEAR_VARS) LOCAL_CFLAGS := -std=c11 -Wall -Werror -O0 LOCAL_SRC_FILES:= sanitizer-status.c LOCAL_MODULE:= sanitizer-status LOCAL_SANITIZE := alignment bounds null unreachable integer LOCAL_SANITIZE_DIAG := alignment bounds null unreachable integer include $(BUILD_EXECUTABLE)
Ve eşdeğer plan (Android.bp) yapılandırması:
cc_binary { cflags: [ "-std=c11", "-Wall", "-Werror", "-O0", ], srcs: ["sanitizer-status.c"], name: "sanitizer-status", sanitize: { misc_undefined: [ "alignment", "bounds", "null", "unreachable", "integer", ], diag: { misc_undefined: [ "alignment", "bounds", "null", "unreachable", "integer", ], }, }, }
UBSan kısayolları
Android'de aynı anda bir dizi dezenfektanı etkinleştirmek için integer
ve default-ub
üzere iki kısayol da vardır. integer integer-divide-by-zero
, signed-integer-overflow
ve unsigned-integer-overflow
etkinleştirir. default-ub
derleyici performans sorunlarının minimum düzeyde olduğu kontrolleri etkinleştirir: bool, integer-divide-by-zero, return, returns-nonnull-attribute, shift-exponent, unreachable and vla-bound
. Tamsayı sanitizer sınıfı SANITIZE_TARGET ve LOCAL_SANITIZE ile kullanılabilirken varsayılan-ub yalnızca SANITIZE_TARGET ile kullanılabilir.
Daha iyi hata raporlama
Android'in varsayılan UBSan uygulaması, tanımlanmamış bir davranışla karşılaşıldığında belirli bir işlevi çağırır. Varsayılan olarak bu işlev iptal edilir. Bununla birlikte, Ekim 2016'dan itibaren Android'deki UBSan, karşılaşılan tanımsız davranış türü, dosya ve kaynak kod satırı bilgileri de dahil olmak üzere daha ayrıntılı hata raporlaması sağlayan isteğe bağlı bir çalışma zamanı kitaplığına sahiptir. Tamsayı kontrolleriyle bu hata raporlamayı etkinleştirmek için aşağıdakini bir Android.mk dosyasına ekleyin:
LOCAL_SANITIZE:=integer LOCAL_SANITIZE_DIAG:=integer
LOCAL_SANITIZE değeri, oluşturma sırasında temizleyiciyi etkinleştirir. LOCAL_SANITIZE_DIAG, belirtilen dezenfektan için teşhis modunu açar. LOCAL_SANITIZE ve LOCAL_SANITIZE_DIAG'yi farklı değerlere ayarlamak mümkündür ancak yalnızca LOCAL_SANITIZE içindeki kontroller etkinleştirilir. LOCAL_SANITIZE'de bir kontrol belirtilmemiş ancak LOCAL_SANITIZE_DIAG'da belirtilmişse, kontrol etkinleştirilmez ve teşhis mesajları verilmez.
UBSan çalışma zamanı kitaplığı tarafından sağlanan bilgilere bir örnek:
pixel-xl:/ # sanitizer-status ubsan sanitizer-status/sanitizer-status.c:53:6: runtime error: unsigned integer overflow: 18446744073709551615 + 1 cannot be represented in type 'size_t' (aka 'unsigned long')
Tamsayı Taşması Temizleme
İstenmeyen tamsayı taşmaları, bellek erişimleri veya bellek tahsisleriyle ilişkili değişkenlerde bellek bozulmasına veya bilgilerin açığa çıkması güvenlik açıklarına neden olabilir. Bununla mücadele etmek için, Android 7.0'daki medya çerçevesini güçlendirmek amacıyla Clang'ın UnDefinitionBehaviorSanitizer (UBSan) imzalı ve imzasız tamsayı taşması temizleyicilerini ekledik. Android 9'da UBSan'ı daha fazla bileşeni kapsayacak şekilde genişlettik ve bunun için yapı sistemi desteğini geliştirdik.
Bu, taşma meydana gelmesi durumunda işlemi güvenli bir şekilde iptal etmek için taşma olasılığı bulunan aritmetik işlemlere/talimatlara denetimler eklemek üzere tasarlanmıştır. Bu temizleyiciler, orijinal Stagefright güvenlik açığı gibi, temel nedenin bir tamsayı taşması olduğu durumlarda tüm bir bellek bozulması ve bilginin açığa çıkması güvenlik açıklarını azaltabilir.
Örnekler ve kaynak
Tamsayı Taşması Temizleme (IntSan), derleyici tarafından sağlanır ve aritmetik taşmaları tespit etmek için derleme süresi boyunca ikili dosyaya enstrümantasyon ekler. Platformdaki çeşitli bileşenlerde varsayılan olarak etkindir, örneğin /platform/external/libnl/Android.bp
.
Uygulama
IntSan, UBSan'ın imzalı ve imzasız tamsayı taşma temizleyicilerini kullanır. Bu azaltma, modül başına düzeyde etkinleştirilir. Android'in kritik bileşenlerinin güvende tutulmasına yardımcı olur ve devre dışı bırakılmamalıdır.
Ek bileşenler için Tamsayı Taşması Temizlemeyi etkinleştirmenizi önemle tavsiye ederiz. İdeal adaylar ayrıcalıklı yerel kod veya güvenilmeyen kullanıcı girişini ayrıştıran yerel koddur. Temizleyiciyle ilişkili, kodun kullanımına ve aritmetik işlemlerin yaygınlığına bağlı olarak küçük bir performans yükü vardır. Küçük bir genel gider yüzdesi bekleyin ve performansın endişe verici olup olmadığını test edin.
Makefile'larda IntSan'ı desteklemek
IntSan'ı bir makefile'da etkinleştirmek için şunu ekleyin:
LOCAL_SANITIZE := integer_overflow # Optional features LOCAL_SANITIZE_DIAG := integer_overflow LOCAL_SANITIZE_BLOCKLIST := modulename_BLOCKLIST.txt
-
LOCAL_SANITIZE
temizleyicilerin virgülle ayrılmış bir listesini alır;integer_overflow
, varsayılan BLOCKLIST ile bireysel imzalı ve imzasız tamsayı taşma temizleyicileri için önceden paketlenmiş bir seçenekler kümesidir. -
LOCAL_SANITIZE_DIAG
dezenfektanlar için teşhis modunu açar. Tanılama modunu yalnızca test sırasında kullanın, çünkü bu, taşmaları iptal etmeyecek ve azaltmanın güvenlik avantajını tamamen ortadan kaldıracaktır. Ek ayrıntılar için Sorun Giderme'ye bakın. -
LOCAL_SANITIZE_BLOCKLIST
işlevlerin ve kaynak dosyaların temizlenmesini önlemek için bir BLOCKLIST dosyası belirtmenize olanak tanır. Ek ayrıntılar için Sorun Giderme'ye bakın.
Daha ayrıntılı bir kontrol istiyorsanız, işaretlerden birini veya her ikisini birden kullanarak sanitizatörleri ayrı ayrı etkinleştirin:
LOCAL_SANITIZE := signed-integer-overflow, unsigned-integer-overflow LOCAL_SANITIZE_DIAG := signed-integer-overflow, unsigned-integer-overflow
Plan dosyalarında IntSan'ı destekleme
/platform/external/libnl/Android.bp
gibi bir plan dosyasında tamsayı taşması temizliğini etkinleştirmek için şunu ekleyin:
sanitize: { integer_overflow: true, diag: { integer_overflow: true, }, BLOCKLIST: "modulename_BLOCKLIST.txt", },
Make dosyalarında olduğu gibi, integer_overflow
özelliği, varsayılan BLOCKLIST ile bireysel imzalı ve imzasız tamsayı taşma temizleyicileri için önceden paketlenmiş bir seçenekler kümesidir.
diag
özellik seti, sanite edici maddeler için teşhis modunu etkinleştirir. Tanılama modunu yalnızca test sırasında kullanın. Tanılama modu taşmalar durumunda iptal edilmez; bu da kullanıcı yapılarındaki azaltmanın güvenlik avantajını tamamen ortadan kaldırır. Ek ayrıntılar için Sorun Giderme'ye bakın.
BLOCKLIST
özelliği, geliştiricilerin işlevlerin ve kaynak dosyaların temizlenmesini engellemesine olanak tanıyan bir BLOCKLIST dosyasının belirtilmesine olanak tanır. Ek ayrıntılar için Sorun Giderme'ye bakın.
Dezenfektanları ayrı ayrı etkinleştirmek için şunu kullanın:
sanitize: { misc_undefined: ["signed-integer-overflow", "unsigned-integer-overflow"], diag: { misc_undefined: ["signed-integer-overflow", "unsigned-integer-overflow",], }, BLOCKLIST: "modulename_BLOCKLIST.txt", },
Sorun giderme
Yeni bileşenlerde tamsayı taşması temizliğini etkinleştiriyorsanız veya tamsayı taşması temizliği olan platform kitaplıklarına güveniyorsanız, zararsız tamsayı taşmalarının iptallere neden olduğu birkaç sorunla karşılaşabilirsiniz. İyi huylu taşmaların ortaya çıkabildiğinden emin olmak için bileşenleri temizleme etkinleştirilmiş şekilde test etmelisiniz.
Kullanıcı yapılarında temizlemenin neden olduğu iptalleri bulmak için, UBSan tarafından yakalanan bir taşmayı belirten Abort mesajlarıyla SIGABRT
çökmelerini arayın, örneğin:
pid: ###, tid: ###, name: Binder:### >>> /system/bin/surfaceflinger <<< signal 6 (SIGABRT), code -6 (SI_TKILL), fault addr -------- Abort message: 'ubsan: sub-overflow'
Yığın izlemesi, iptale neden olan işlevi içermelidir, ancak satır içi işlevlerde meydana gelen taşmalar yığın izlemesinde belirgin olmayabilir.
Temel nedeni daha kolay belirlemek için kitaplıktaki iptali tetikleyen tanılamayı etkinleştirin ve hatayı yeniden oluşturmaya çalışın. Tanılama etkinleştirildiğinde işlem durdurulmayacak ve bunun yerine çalışmaya devam edecektir. İptal etmemek, her hatayı düzelttikten sonra yeniden derlemeye gerek kalmadan belirli bir yürütme yolundaki zararsız taşmaların sayısını en üst düzeye çıkarmaya yardımcı olur. Tanılama, iptale neden olan satır numarasını ve kaynak dosyayı içeren bir hata mesajı üretir:
frameworks/native/services/surfaceflinger/SurfaceFlinger.cpp:2188:32: runtime error: unsigned integer overflow: 0 - 1 cannot be represented in type 'size_t' (aka 'unsigned long')
Sorunlu aritmetik işlemin yeri belirlendikten sonra, taşmanın zararsız ve amaçlanmış olduğundan (örn. herhangi bir güvenlik etkisi olmadığından) emin olun. Dezenfektan iptalini şu şekilde çözebilirsiniz:
- Taşmayı önlemek için kodu yeniden düzenleme ( örnek )
- Clang'ın __builtin__*_overflow işlevleri aracılığıyla açıkça taşma ( örnek )
-
no_sanitize
niteliğini belirterek işlevdeki temizlemeyi devre dışı bırakma ( örnek ) - Bir işlevin veya kaynak dosyanın BLOCKLIST dosyası yoluyla temizlenmesinin devre dışı bırakılması ( örnek )
Mümkün olan en ayrıntılı çözümü kullanmalısınız. Örneğin, birçok aritmetik işlemi ve tek bir taşma işlemini içeren büyük bir fonksiyonda, tüm fonksiyonun BLOCKLIST'lenmesi yerine tek bir işlemin yeniden düzenlenmesi gerekir.
İyi huylu taşmalara neden olabilecek yaygın modeller şunlardır:
- İmzalı bir türe dönüştürülmeden önce imzasız taşmanın meydana geldiği örtülü dönüşümler ( örnek )
- Silme sırasında döngü indeksini azaltan bağlantılı liste silme işlemleri ( örnek )
- Gerçek maksimum değeri belirtmek yerine imzasız bir türü -1'e atamak ( örnek )
- Koşuldaki işaretsiz bir tamsayıyı azaltan döngüler ( örnek , örnek )
Geliştiricilerin, sanitizatörün bir taşma tespit ettiği durumlarda, sanitizasyonu devre dışı bırakmadan önce bunun gerçekten zararsız olduğundan ve herhangi bir istenmeyen yan etki veya güvenlik etkisi olmadığından emin olmaları önerilir.
IntSan'ı Devre Dışı Bırakma
IntSan'ı BLOCKLIST'ler veya işlev nitelikleriyle devre dışı bırakabilirsiniz. Dikkatli bir şekilde ve yalnızca kodu yeniden düzenlemenin mantıksız olduğu durumlarda veya sorunlu performans yükü olduğunda devre dışı bırakın.
IntSan'ı işlev nitelikleri ve BLOCKLIST dosya formatıyla devre dışı bırakma hakkında daha fazla bilgi için yukarı akış Clang belgelerine bakın. ENGELLEME LİSTESİ, diğer sanitizatörlerin etkilenmesini önlemek için hedef sanitizeri belirten bölüm adları kullanılarak belirli sanitizeri kapsayacak şekilde kapsanmalıdır.
Doğrulama
Şu anda Tamsayı Taşması Temizleme için özel olarak herhangi bir CTS testi bulunmamaktadır. Bunun yerine, cihazı etkilemediğini doğrulamak için CTS testlerinin IntSan etkinken veya olmadan geçtiğinden emin olun.
Sınır Sterilizasyonu
BoundsSanitizer (BoundSan), dizi erişimlerinin etrafına sınır kontrolleri eklemek için ikili dosyalara araçlar ekler. Bu kontroller, derleyicinin derleme zamanında erişimin güvenli olacağını kanıtlayamaması ve dizinin boyutunun çalışma zamanında bilinip bilinmeyeceği ve böylece kontrol edilebilmesi durumunda eklenir. Android 10, Bluetooth ve codec bileşenlerinde BoundSan'ı dağıtır. BoundSan, derleyici tarafından sağlanır ve platformdaki çeşitli bileşenlerde varsayılan olarak etkinleştirilir.
Uygulama
BoundSan, UBSan'ın sınır temizleyicisini kullanıyor. Bu azaltma, modül başına düzeyde etkinleştirilir. Android'in kritik bileşenlerinin güvende tutulmasına yardımcı olur ve devre dışı bırakılmamalıdır.
Ek bileşenler için BoundSan'ı etkinleştirmenizi önemle tavsiye ederiz. İdeal adaylar, ayrıcalıklı yerel kod veya güvenilmeyen kullanıcı girişini ayrıştıran karmaşık yerel koddur. BoundSan'ı etkinleştirmeyle ilişkili performans yükü, güvenli olduğu kanıtlanamayan dizi erişimlerinin sayısına bağlıdır. Ortalama olarak küçük bir genel gider yüzdesi bekleyin ve performansın endişe verici olup olmadığını test edin.
Plan dosyalarında BoundSan'ı etkinleştirme
BoundSan, ikili modüller ve kütüphane modülleri için misc_undefined
sanitize özelliğine "bounds"
eklenerek plan dosyalarında etkinleştirilebilir:
sanitize: { misc_undefined: ["bounds"], diag: { misc_undefined: ["bounds"], }, BLOCKLIST: "modulename_BLOCKLIST.txt",
teşhis
diag
özelliği, sanitizatörler için teşhis modunu etkinleştirir. Tanılama modunu yalnızca test sırasında kullanın. Tanılama modu taşmalar durumunda iptal edilmez; bu da azaltmanın güvenlik avantajını ortadan kaldırır ve daha yüksek performans yükü taşır; bu nedenle üretim yapıları için önerilmez.
BLOK LİSTESİ
BLOCKLIST
özelliği, geliştiricilerin işlevlerin ve kaynak dosyaların temizlenmesini önlemek için kullanabileceği bir BLOCKLIST dosyasının belirtilmesine olanak tanır. Bu özelliği yalnızca performans önemliyse ve hedeflenen dosyalar/işlevler önemli ölçüde katkıda bulunuyorsa kullanın. Dizi erişimlerinin güvenli olduğundan emin olmak için bu dosyaları/işlevleri manuel olarak denetleyin. Ek ayrıntılar için Sorun Giderme'ye bakın.
Makefile'larda BoundSan'ı etkinleştirme
BoundSan, ikili modüller ve kütüphane modülleri için LOCAL_SANITIZE
değişkenine "bounds"
eklenerek makefile dosyalarında etkinleştirilebilir:
LOCAL_SANITIZE := bounds # Optional features LOCAL_SANITIZE_DIAG := bounds LOCAL_SANITIZE_BLOCKLIST := modulename_BLOCKLIST.txt
LOCAL_SANITIZE
virgülle ayrılmış temizleyicilerin listesini kabul eder.
LOCAL_SANITIZE_DIAG
teşhis modunu açar. Tanılama modunu yalnızca test sırasında kullanın. Tanılama modu taşmalar durumunda iptal edilmez; bu da azaltmanın güvenlik avantajını ortadan kaldırır ve daha yüksek performans yükü taşır; bu nedenle üretim yapıları için önerilmez.
LOCAL_SANITIZE_BLOCKLIST
geliştiricilerin işlevlerin ve kaynak dosyaların temizlenmesini engellemesine olanak tanıyan bir BLOCKLIST dosyasının belirtilmesine olanak tanır. Bu özelliği yalnızca performans önemliyse ve hedeflenen dosyalar/işlevler önemli ölçüde katkıda bulunuyorsa kullanın. Dizi erişimlerinin güvenli olduğundan emin olmak için bu dosyaları/işlevleri manuel olarak denetleyin. Ek ayrıntılar için Sorun Giderme'ye bakın.
BoundSan'ı Devre Dışı Bırakma
BLOCKLIST'ler veya işlev öznitelikleri ile işlevlerde ve kaynak dosyalarda BoundSan'ı devre dışı bırakabilirsiniz. BoundSan'ı etkin tutmak en iyisidir, bu nedenle yalnızca işlev veya dosya büyük miktarda performans yükü oluşturuyorsa ve kaynak manuel olarak incelendiyse devre dışı bırakın.
BoundSan'ı işlev nitelikleriyle ve BLOCKLIST dosya formatıyla devre dışı bırakma hakkında daha fazla bilgi için Clang LLVM belgelerine bakın. Diğer dezenfektanların etkilenmesini önlemek için hedef dezenfektanı belirten bölüm adlarını kullanarak BLOCKLIST'in kapsamını belirli bir dezenfektanı kapsayacak şekilde belirleyin.
Doğrulama
BoundSan'a özel bir CTS testi yoktur. Bunun yerine, cihazı etkilemediğini doğrulamak için CTS testlerinin BoundSan etkin olsun veya olmasın başarılı olduğundan emin olun.
Sorun giderme
Daha önce tespit edilmemiş sınır dışı erişimlerin ele alındığından emin olmak için BoundSan'ı etkinleştirdikten sonra bileşenleri kapsamlı bir şekilde test edin.
BoundSan hataları, aşağıdaki iptal mesajını içerdiklerinden kolaylıkla tespit edilebilir:
pid: ###, tid: ###, name: Binder:### >>> /system/bin/foobar <<< signal 6 (SIGABRT), code -6 (SI_TKILL), fault addr -------- Abort message: 'ubsan: out-of-bounds'
Tanılama modunda çalışırken kaynak dosya, satır numarası ve dizin değeri logcat
yazdırılır. Varsayılan olarak bu mod bir iptal mesajı atmaz. Hata olup olmadığını kontrol etmek için logcat
inceleyin.
external/foo/bar.c:293:13: runtime error: index -1 out of bounds for type 'int [24]'