UndefinedBehaviorSanitizer

UndefinedBehaviorSanitizer (UBSan), çeşitli türlerdeki tanımlanmamış davranışları kontrol etmek için derleme zamanı enstrümantasyonu gerçekleştirir. UBSan, tanımsız davranışla ilgili birçok hatayı algılayabilse de Android şunları destekler:

  • hizalama
  • bool
  • sınırlar
  • enum
  • float-cast-overflow
  • float-divide-by-zero
  • integer-divide-by-zero
  • nonnull-attribute
  • null
  • return
  • returns-nonnull-attribute
  • shift-base
  • shift-exponent
  • signed-integer-overflow
  • ulaşılamıyor
  • unsigned-integer-overflow
  • vla-bound

unsigned-integer-overflow, teknik olarak tanımsız davranış olmasa da temizleyiciye dahil edilir ve mediaserver bileşenleri de dahil olmak üzere birçok Android modülünde, olası tamsayı taşması güvenlik açıklarını ortadan kaldırmak için kullanılır.

Uygulama

Android derleme sisteminde UBSan'i genel veya yerel olarak etkinleştirebilirsiniz. UBSan'i genel olarak etkinleştirmek için Android.mk'de SANITIZE_TARGET'ı ayarlayın. UBSan'i modül düzeyinde etkinleştirmek için LOCAL_SANITIZE'ı ayarlayın ve Android.mk'da aramak istediğiniz tanımlanmamış 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)

Ayrıca, 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 temizleyiciyi etkinleştirmek için integer ve default-ub olmak üzere iki kısayol da bulunur. integer, integer-divide-by-zero, signed-integer-overflow ve unsigned-integer-overflow öğelerini etkinleştirir. default-ub, derleyici performansıyla ilgili minimum düzeyde sorun içeren kontrolleri etkinleştirir: bool, integer-divide-by-zero, return, returns-nonnull-attribute, shift-exponent, unreachable and vla-bound. Tamsayı temizleyici sınıfı SANITIZE_TARGET ve LOCAL_SANITIZE ile kullanılabilirken default-ub yalnızca SANITIZE_TARGET ile kullanılabilir.

Daha iyi hata raporlama

Android'in varsayılan UBSan uygulaması, tanımlanmamış davranışla karşılaşıldığında belirtilen bir işlevi çağırır. Bu işlev varsayılan olarak iptal edilir. Ancak, Ekim 2016'dan itibaren Android'deki UBSan, karşılaşılan tanımsız davranış türü, dosya ve kaynak kodu satırı bilgileri dahil olmak üzere daha ayrıntılı hata raporları veren isteğe bağlı bir çalışma zamanı kitaplığına sahiptir. Bu hata raporlamayı tam sayı kontrolleriyle etkinleştirmek için Android.mk dosyasına aşağıdakileri ekleyin:

LOCAL_SANITIZE:=integer
LOCAL_SANITIZE_DIAG:=integer

LOCAL_SANITIZE değeri, derleme sırasında temizleyicinin etkinleştirilmesini sağlar. LOCAL_SANITIZE_DIAG, belirtilen temizleyici için teşhis modunu etkinleştirir. LOCAL_SANITIZE ve LOCAL_SANITIZE_DIAG'ı farklı değerlere ayarlamak mümkündür ancak yalnızca LOCAL_SANITIZE'daki kontroller etkinleştirilir. Bir kontrol, LOCAL_SANITIZE içinde belirtilmemiş ancak LOCAL_SANITIZE_DIAG içinde belirtilmişse kontrol etkinleştirilmez ve teşhis mesajları verilmez.

UBSan çalışma zamanı kitaplığı tarafından sağlanan bilgilere dair bir örneği aşağıda bulabilirsiniz:

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

Tam sayı taşması temizleme

İstenmeyen tam sayı taşmaları, bellek erişimleri veya bellek ayırmalarıyla ilişkili değişkenlerde bellek bozulmasına ya da bilgi ifşası güvenlik açıklarına neden olabilir. Bununla mücadele etmek için Android 7.0'da medya çerçevesini güçlendirmek amacıyla Clang'in UndefinedBehaviorSanitizer (UBSan) imzalı ve imzasız tam sayı taşması temizleyicilerini ekledik. Android 9'da, UBSan'ı daha fazla bileşeni kapsayacak şekilde genişlettik ve derleme sistemi desteğini iyileştirdik.

Bu, taşma olasılığı olan aritmetik işlemler ve talimatlarla ilgili denetimler ekleyerek taşma gerçekleşirse işlemi güvenli bir şekilde durdurmak için tasarlanmıştır. Bu temizleyiciler, temel nedeni tam sayı taşması olan tüm bellek bozulması ve bilgi ifşası güvenlik açıklarını (ör. orijinal Stagefright güvenlik açığı) azaltabilir.

Örnekler ve kaynak

Derleyici tarafından sağlanan Integer Overflow Sanitization (IntSan), aritmetik taşmaları tespit etmek için derleme sırasında ikili dosyaya enstrümantasyon ekler. Platform genelindeki çeşitli bileşenlerde (ör. /platform/external/libnl/Android.bp) varsayılan olarak etkindir.

Uygulama

IntSan, UBSan'ın işaretli ve işaretsiz tam sayı taşması temizleyicilerini kullanır. Bu azaltma, modül düzeyinde etkinleştirilir. Android'in kritik bileşenlerinin güvenliğini sağlamaya 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 küçük bir performans yükü vardır. Bu yük, kodun kullanımına ve aritmetik işlemlerin yaygınlığına bağlıdır. Küçük bir ek yük yüzdesi bekleyin ve performansın sorun olup olmadığını test edin.

Makefile'larda IntSan desteği

Bir makefile'da IntSan'ı 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, virgülle ayrılmış bir temizleyici listesi alır. integer_overflow, varsayılan BLOCKLIST ile imzalı ve imzasız tam sayı taşması temizleyicileri için önceden paketlenmiş bir seçenekler kümesidir.
  • LOCAL_SANITIZE_DIAG, temizleyiciler için teşhis modunu etkinleştirir. Taşmalarda durdurulmayacağından ve azaltmanın güvenlik avantajını tamamen ortadan kaldıracağından teşhis modunu yalnızca test sırasında kullanın. Daha fazla bilgi için Sorun giderme bölümüne bakın.
  • LOCAL_SANITIZE_BLOCKLIST, işlevlerin ve kaynak dosyaların temizlenmesini önlemek için bir BLOCKLIST dosyası belirtmenize olanak tanır. Daha fazla bilgi için Sorun giderme bölümüne bakın.

Daha ayrıntılı kontrol istiyorsanız aşağıdaki işaretlerden birini veya ikisini kullanarak temizleyicileri 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

Bir plan dosyasında (ör. /platform/external/libnl/Android.bp) tam sayı taşması temizlemeyi 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 imzalı ve imzasız tam sayı taşması temizleyicileri için önceden paketlenmiş bir seçenekler kümesidir.

diag özellik grubu, temizleyiciler için teşhis modunu etkinleştirir. Teşhis modunu yalnızca test sırasında kullanın. Tanılama modu, taşmalarda işlemi durdurmaz. Bu durum, kullanıcı derlemelerindeki azaltma işleminin güvenlik avantajını tamamen ortadan kaldırır. Daha fazla bilgi için Sorun giderme bölümüne bakın.

BLOCKLIST özelliği, geliştiricilerin işlevlerin ve kaynak dosyaların temizlenmesini engellemelerine olanak tanıyan bir BLOCKLIST dosyası belirtilmesine olanak tanır. Daha fazla bilgi için Sorun giderme bölümüne bakın.

Temizleyicileri tek tek 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 tam sayı taşması temizlemeyi etkinleştiriyorsanız veya tam sayı taşması temizleme özelliği olan platform kitaplıklarını kullanıyorsanız, iptallere neden olan zararsız tam sayı taşmalarıyla ilgili birkaç sorunla karşılaşabilirsiniz. İyi huylu taşmaların ortaya çıkmasını sağlamak için bileşenleri temizleme etkinleştirilmiş şekilde test etmeniz gerekir.

Kullanıcı derlemelerinde temizleme işleminden kaynaklanan sonlandırmaları bulmak için: SIGABRT Aşağıdakiler gibi, UBSan tarafından yakalanan bir taşmanın belirtildiği Abort mesajlarıyla birlikte kilitlenmeleri arayın:

pid: ###, tid: ###, name: Binder:###  >>> /system/bin/surfaceflinger <<<
    signal 6 (SIGABRT), code -6 (SI_TKILL), fault addr --------
    Abort message: 'ubsan: sub-overflow'

Yığın izi, iptale neden olan işlevi içermelidir. Ancak satır içi işlevlerde meydana gelen taşmalar yığın izinde görünmeyebilir.

Temel nedeni daha kolay belirlemek için iptali tetikleyen kitaplıkta teşhisleri etkinleştirin ve hatayı yeniden oluşturmayı deneyin. Teşhis etkinleştirildiğinde işlem iptal edilmez ve çalışmaya devam eder. Durdurulmaması, her hata düzeltildikten sonra yeniden derleme yapmaya gerek kalmadan belirli bir yürütme yolundaki zararsız taşma sayısını en üst düzeye çıkarmanıza yardımcı olur. Teşhis aracı, satır numarasını ve iptale neden olan kaynak dosyasını içeren bir hata mesajı oluşturur:

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şlem bulunduktan sonra taşmanın zararsız ve amaçlandığından (ör. güvenlik açısından bir etkisi olmadığından) emin olun. Dezenfektan işleminin iptal edilmesini önlemek için:

  • Taşmayı önlemek için kodu yeniden düzenleme (örnek)
  • Clang'in __builtin_*_overflow işlevleri aracılığıyla açıkça taşma (örnek)
  • no_sanitize özelliğini belirterek işlevde temizlemeyi devre dışı bırakma (örnek)
  • BLOCKLIST dosyası aracılığıyla bir işlevin veya kaynak dosyanın temizlenmesini devre dışı bırakma (örnek)

Mümkün olan en ayrıntılı çözümü kullanmalısınız. Örneğin, çok sayıda aritmetik işlem içeren ve tek bir taşma işlemi olan büyük bir işlevin tamamı engellenmek yerine tek işlemin yeniden düzenlenmesi gerekir.

Zararsız taşmalara neden olabilecek yaygın kalıplar şunlardır:

  • İşaretli bir türe dönüştürülmeden önce işaretsiz taşmanın gerçekleştiği örtülü dönüştürmeler (örnek)
  • Silme işleminde döngü dizinini azaltan bağlı liste silme işlemleri (örnek)
  • Gerçek maksimum değeri (örnek) belirtmek yerine -1'e işaretsiz bir tür atama
  • Koşuldaki işaretsiz bir tam sayıyı azaltan döngüler (örnek, örnek)

Geliştiricilerin, temizleyici tarafından taşma tespit edilen durumlarda temizlemeyi devre dışı bırakmadan önce bunun gerçekten zararsız olduğunu ve istenmeyen yan etkileri veya güvenlik etkileri olmadığını doğrulaması önerilir.

IntSan'ı devre dışı bırakma

IntSan'ı BLOCKLIST'ler veya işlev özellikleri ile devre dışı bırakabilirsiniz. Yalnızca kodu yeniden düzenlemek makul değilse veya performansla ilgili sorunlu bir ek yük varsa bu özelliği dikkatli bir şekilde ve nadiren devre dışı bırakın.

IntSan'ı işlev özellikleri ve BLOCKLIST dosyası biçimlendirmesi ile devre dışı bırakma hakkında daha fazla bilgi için yukarı akış Clang belgelerine bakın. Engellenenler listesi, diğer temizleyicileri etkilememek için hedef temizleyiciyi belirten bölüm adları kullanılarak belirli temizleyiciyle sınırlandırılmalıdır.

Doğrulama

Şu anda, tam sayı taşması temizleme için özel olarak tasarlanmış bir CTS testi yoktur. Bunun yerine, cihazı etkilemediğini doğrulamak için CTS testlerinin IntSan etkin veya devre dışı bırakılmışken geçtiğinden emin olun.

Sınır temizleme

BoundsSanitizer (BoundSan), dizi erişimlerinin etrafına sınır denetimleri eklemek için ikili dosyalara enstrümantasyon ekler. Bu kontroller, derleyici derleme sırasında erişimin güvenli olacağını kanıtlayamazsa ve dizinin boyutu çalışma zamanında bilinecekse (böylece kontrol edilebilir) eklenir. Android 10, Bluetooth ve codec'lerde BoundSan'i kullanır. BoundSan, derleyici tarafından sağlanır ve platform genelindeki çeşitli bileşenlerde varsayılan olarak etkindir.

Uygulama

BoundSan, UBSan'ın sınır temizleyicisini kullanır. Bu azaltma, modül düzeyinde etkinleştirilir. Android'in kritik bileşenlerinin güvenliğini sağlamaya yardımcı olur ve devre dışı bırakılmamalıdır.

Ek bileşenler için BoundSan'ı etkinleştirmenizi önemle tavsiye ederiz. İdeal adaylar, güvenilmeyen kullanıcı girişini ayrıştıran ayrıcalıklı yerel kod veya karmaşık yerel koddur. BoundSan'ın etkinleştirilmesiyle ilişkili performans ek yükü, güvenli olduğu kanıtlanamayan dizi erişimlerinin sayısına bağlıdır. Ortalama olarak küçük bir ek yük yüzdesi bekleyin ve performansın sorun olup olmadığını test edin.

Blueprint dosyalarında BoundSan'ı etkinleştirme

BoundSan, ikili ve kitaplık modülleri için misc_undefined temizleme özelliğine "bounds" eklenerek blueprint dosyalarında etkinleştirilebilir:

    sanitize: {
       misc_undefined: ["bounds"],
       diag: {
          misc_undefined: ["bounds"],
       },
       BLOCKLIST: "modulename_BLOCKLIST.txt",
diag

diag özelliği, dezenfektanlar için teşhis modunu etkinleştirir. Teşhis modunu yalnızca test sırasında kullanın. Teşhis modu, taşma durumunda işlemi durdurmaz. Bu durum, azaltma işleminin güvenlik avantajını ortadan kaldırır ve daha yüksek performans ek yükü oluşturur. Bu nedenle, üretim derlemeleri için önerilmez.

ENGELLEDİĞİNİZ KULLANICILARIN 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 performansla ilgili bir sorun varsa ve hedeflenen dosyalar/fonksiyonlar önemli ölçüde katkıda bulunuyorsa kullanın. Dizilere erişimin güvenli olduğundan emin olmak için bu dosyaları/işlevleri manuel olarak denetleyin. Daha fazla bilgi için Sorun giderme bölümüne bakın.

Make dosyalarında BoundSan'ı etkinleştirme

BoundSan, ikili ve kitaplık modülleri için LOCAL_SANITIZE değişkenine "bounds" eklenerek makefile'larda etkinleştirilebilir:

    LOCAL_SANITIZE := bounds
    # Optional features
    LOCAL_SANITIZE_DIAG := bounds
    LOCAL_SANITIZE_BLOCKLIST := modulename_BLOCKLIST.txt

LOCAL_SANITIZE, virgülle ayrılmış bir temizleyici listesini kabul eder.

LOCAL_SANITIZE_DIAG teşhis modunu etkinleştirir. Yalnızca test sırasında teşhis modunu kullanın. Teşhis modu, taşmalarda işlemi durdurmaz. Bu durum, azaltma işleminin güvenlik avantajını ortadan kaldırır ve daha yüksek performans ek yükü oluşturur. Bu nedenle, üretim derlemeleri için önerilmez.

LOCAL_SANITIZE_BLOCKLIST, geliştiricilerin işlevlerin ve kaynak dosyaların temizlenmesini engellemelerine olanak tanıyan bir BLOCKLIST dosyasının belirtilmesine izin verir. Bu özelliği yalnızca performansla ilgili bir sorun varsa ve hedeflenen dosyalar/fonksiyonlar önemli ölçüde katkıda bulunuyorsa kullanın. Dizilere erişimin güvenli olduğundan emin olmak için bu dosyaları/işlevleri manuel olarak denetleyin. Daha fazla bilgi için Sorun giderme bölümüne bakın.

BoundSan'ı devre dışı bırakma

BoundSan'ı, BLOCKLIST'ler veya işlev özellikleri içeren işlevlerde ve kaynak dosyalarında devre dışı bırakabilirsiniz. BoundSan'ı etkin tutmanız önerilir. Bu nedenle, yalnızca işlev veya dosya büyük miktarda performans ek yükü oluşturuyorsa ve kaynak manuel olarak incelenmişse devre dışı bırakın.

BoundSan'ı işlev özellikleri ve BLOCKLIST dosyası biçimlendirmesi ile devre dışı bırakma hakkında daha fazla bilgi için Clang LLVM dokümanlarına bakın. Diğer temizleyicileri etkilememek için hedef temizleyiciyi belirten bölüm adlarını kullanarak BLOCKLISTing'i belirli bir temizleyiciyle sınırlayın.

Doğrulama

BoundSan için özel olarak tasarlanmış bir CTS testi yoktur. Bunun yerine, cihazı etkilemediğini doğrulamak için BoundSan etkin olsun veya olmasın CTS testlerinin başarılı olduğundan emin olun.

Sorun giderme

Sınırlı erişimlerin daha önce algılanmamış olanlarının ele alındığından emin olmak için BoundSan'ı etkinleştirdikten sonra bileşenleri kapsamlı bir şekilde test edin.

BoundSan hataları, aşağıdaki mezar taşı iptal mesajını içerdiğinden kolayca tanımlanabilir:

    pid: ###, tid: ###, name: Binder:###  >>> /system/bin/foobar <<<
    signal 6 (SIGABRT), code -6 (SI_TKILL), fault addr --------
    Abort message: 'ubsan: out-of-bounds'

Teşhis modunda çalıştırıldığında kaynak dosya, satır numarası ve dizin değeri logcat konumuna yazdırılır. Bu mod varsayılan olarak iptal mesajı vermez. Hata olup olmadığını kontrol etmek için logcat bölümünü inceleyin.

    external/foo/bar.c:293:13: runtime error: index -1 out of bounds for type 'int [24]'