TanımsızDavranışSanitizer

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]'