UndefinedBehaviorSanitizer

UndefinedBehaviorSanitizer (UBSan), çeşitli türde tanımlanmamış davranışları kontrol etmek için derleme zamanında enstrümasyon gerçekleştirir. UBSan, tanımlanmamış davranışla ilgili birçok hatayı tespit edebilse de Android aşağıdakileri destekler:

  • hiza
  • bool
  • sınırlar
  • enum
  • float-cast-overflow
  • float-divide-by-zero
  • tamsayı-sıfıra-bölme
  • nonnull-attribute
  • boş
  • 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ımlanmamış bir davranış olmasa da temizleyiciye dahil edilir ve gizli tam sayı taşması güvenlik açıklarını ortadan kaldırmak için mediaserver bileşenleri de dahil olmak üzere birçok Android modülünde kullanılır.

Uygulama

Android derleme sisteminde UBSan'ı global olarak veya yerel olarak etkinleştirebilirsiniz. UBSan'ı dünya genelinde etkinleştirmek için Android.mk'de SANITIZE_TARGET'ı ayarlayın. UBSan'ı modül düzeyinde etkinleştirmek için LOCAL_SANITIZE'ı ayarlayın ve Android.mk'de aradığınız tanımlanmamış davranışları belirtin. Örnek:

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)

Eşdeğer taslak (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, bir dizi temizleyiciyi aynı anda etkinleştirmek için integer ve default-ub adlı iki kısayol da vardır. integer, integer-divide-by-zero, signed-integer-overflow ve unsigned-integer-overflow'i etkinleştirir. default-ub, derleyici performansıyla ilgili en az soruna sahip kontrolleri etkinleştirir: bool, integer-divide-by-zero, return, returns-nonnull-attribute, shift-exponent, unreachable and vla-bound. Tam sayı 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ış bir davranışla karşılaşıldığında belirtilen bir işlevi çağırır. Bu işlev varsayılan olarak iptaldir. Ancak Ekim 2016'dan itibaren Android'deki UBSan'da, karşılaşılan tanımlanmamış davranış türü, dosya ve kaynak kodu satır bilgileri dahil olmak üzere daha ayrıntılı hata raporları sağlayan isteğe bağlı bir çalışma zamanı kitaplığı vardır. Tam sayı kontrolleri ile bu hata raporlamasını 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 temizleyiciyi etkinleştirir. 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'da belirtilmez ancak LOCAL_SANITIZE_DIAG'da belirtilirse kontrol etkinleştirilmez ve teşhis mesajları verilmez.

UBSan çalışma zamanı kitaplığı tarafından sağlanan bilgilere ö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')

Tam sayı taşması temizleme

Arızi tam sayı taşmaları, bellek erişimleriyle veya bellek atamalarıyla ilişkili değişkenlerde bellek bozulmasına ya da bilgi ifşa etme açıklıklarına neden olabilir. Bu sorunla mücadele etmek için Android 7.0'da medya çerçevesini güçlendirmek amacıyla Clang'ın 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 bu bileşen için derleme sistemi desteğini iyileştirdik.

Bu, taşma meydana gelmesi durumunda işlemi güvenli bir şekilde iptal etmek için taşma ihtimali olan aritmetik işlemler / talimatları etrafında kontroller eklemek üzere tasarlanmıştır. Bu temizleyiciler, temel nedeni tam sayı taşması olan bellek bozulması ve bilgi ifşası güvenlik açıklarının tüm sınıfını (ör. orijinal Stagefright güvenlik açığı) azaltabilir.

Örnekler ve kaynak

Tam Sayı Aşımı Sanitasyonu (IntSan), derleyici tarafından sağlanır ve aritmetik taşmaları algılamak için derleme sırasında ikili dosyaya ölçüm ekler. Bu özellik, platformdaki çeşitli bileşenlerde (ör. /platform/external/libnl/Android.bp) varsayılan olarak etkindir.

Uygulama

IntSan, UBSan'ın imzalı ve imzasız tam sayı taşması temizleyicilerini kullanır. Bu azaltma, modül başına düzeyde etkinleştirilir. Android'in kritik bileşenlerinin güvende kalmasına yardımcı olur ve devre dışı bırakılmamalıdır.

Ek bileşenler için Tam Sayı Aşımı Temizleme özelliğini etkinleştirmenizi önemle tavsiye ederiz. İdeal adaylar, ayrıcalıklı doğal kod veya güvenilmeyen kullanıcı girişini ayrıştıran doğal koddur. Kodun kullanımına ve aritmetik işlemlerin yaygınlığına bağlı olarak temizleyiciyle ilişkili küçük bir performans yükü vardır. Küçük bir genel gider yüzdesi bekleyin ve performansın sorun olup olmadığını test edin.

Makefile'lerde IntSan desteği

Bir makefile'de IntSan'ı etkinleştirmek için şunları 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 ENGELENENLER LİSTESİ ile tek tek imzalanan ve imzalanmayan tam sayı taşması temizleyicileri için önceden paketlenmiş bir seçenek grubudur.
  • LOCAL_SANITIZE_DIAG, temizleyiciler için teşhis modunu etkinleştirir. Teşhis modu, taşmalar sırasında işlemi iptal etmez. Bu nedenle, azaltmanın güvenlik avantajını tamamen ortadan kaldırır. Bu nedenle, 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 temizleyicileri bir veya iki işareti kullanarak 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 desteği

/platform/external/libnl/Android.bp gibi bir taslak dosyasında tam sayı taşması temizlemeyi etkinleştirmek için:

   sanitize: {
          integer_overflow: true,
          diag: {
              integer_overflow: true,
          },
          BLOCKLIST: "modulename_BLOCKLIST.txt",
       },

Make dosyalarında olduğu gibi integer_overflow mülkü, varsayılan BLOCKLIST ile tek tek imzalı ve imzasız tam sayı taşması temizleyicileri için önceden paketlenmiş bir seçenek kümesidir.

diag özellik grubu, temizleyiciler için teşhis modunu etkinleştirir. Teşhis modunu yalnızca test sırasında kullanın. Teşhis modu, taşmalar olduğunda işlemi iptal etmez. Bu da kullanıcı derlemelerinde azaltmanın güvenlik avantajını tamamen ortadan kaldırır. Daha fazla bilgi için Sorun giderme bölümüne bakın.

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

Dezenfektanları tek tek etkinleştirmek için:

   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ı temizlemesi yapılan platform kitaplıklarını kullanıyorsanız, kesintiye neden olan iyi huylu tam sayı taşmalarıyla ilgili birkaç sorunla karşılaşabilirsiniz. Olumlu taşmaların gösterilebildiğinden emin olmak için bileşenleri temizleme özelliği etkinleştirilmiş şekilde test etmeniz gerekir.

Kullanıcı derlemelerinde temizlemeden kaynaklanan kesintileri bulmak için UBSan tarafından yakalanan bir taşmayı belirten Abort mesajları içeren SIGABRT kilitlenmelerini 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 izleme, işlemin iptal edilmesine neden olan işlevi içermelidir. Ancak satır içi işlevlerde gerçekleşen taşmalar yığın izlemede görünmeyebilir.

Temel nedeni daha kolay belirlemek için kitaplıkta teşhisi etkinleştirin, işlemi iptal edin ve hatayı yeniden oluşturmayı deneyin. Teşhis etkinleştirildiğinde işlem iptal edilmez, bunun yerine çalışmaya devam eder. İptal edilmemesi, her hatayı düzelttikten sonra yeniden derlemek zorunda kalmadan belirli bir yürütme yolunda iyi huylu taşmaların sayısını en üst düzeye çıkarmaya yardımcı olur. Teşhis, işlemin iptal edilmesine neden olan satır numarasını ve kaynak dosyayı 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 iyi huylu ve istenen bir işlem olduğundan (ör. güvenlikle ilgili bir etkisi olmadığından) emin olun. Aşağıdakileri yaparak temizleyicinin iptal sorununu çözebilirsiniz:

  • Aşırı akışı ö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 özelliğini belirterek işlevde temizlemeyi devre dışı bırakma (örnek)
  • Bir işlevin veya kaynak dosyanın temizlenmesini bir BLOCKLIST dosyası aracılığıyla devre dışı bırakma (ö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şlemi içeren büyük bir işlevin tümünün ENGELLENER LİSTESİ'ne eklenmesi yerine tek işlemin yeniden yapılandırılması gerekir.

İyi huylu taşmalara neden olabilecek yaygın kalıplar şunlardır:

  • İmzalı bir türe aktarılmadan önce imzasız bir taşmanın meydana geldiği örtük aktarımlar (örnek)
  • Silme işleminde döngü dizesini azaltan bağlı liste silme işlemleri (örnek)
  • Gerçek maksimum değeri belirtmek yerine -1 değerine işaretsiz bir tür atama (örnek)
  • Koşuldaki imzasız bir tam sayıyı azaltan döngüler (örnek, örnek)

Geliştiricilerin, temizleyicinin taşma algıladığı durumlarda, temizlemeyi devre dışı bırakmadan önce bunun istenmeyen yan etkileri veya güvenlikle ilgili sonuçları olmayan, gerçekten iyi huylu bir durum olduğundan emin olmaları önerilir.

IntSan'ı devre dışı bırakma

IntSan'ı BLOCKLIST'ler veya işlev özellikleriyle devre dışı bırakabilirsiniz. Yalnızca kodun yeniden düzenlenmesinin makul olmadığı durumlarda veya performansla ilgili sorunlu bir yükü olduğunda, bu özelliği az miktarda devre dışı bırakın.

İşlev özellikleri ve BLOCKLIST dosya biçimlendirmesi ile IntSan'ı devre dışı bırakma hakkında daha fazla bilgi için yayın öncesi Clang belgelerine bakın. Diğer temizleyicileri etkilememek için hedef temizleyiciyi belirten bölüm adları kullanılarak BLOCKLISTing, belirli bir temizleyiciye göre kapsamlandırılmalıdır.

Doğrulama

Şu anda tam sayı taşması temizliği için özel bir CTS testi yoktur. Bunun yerine, cihazı etkilemediğini doğrulamak için IntSan etkinken veya etkin değilken CTS testlerinin geçtiğinden emin olun.

Sınır temizleme

BoundsSanitizer (BoundSan), dizi erişimlerinin etrafına sınır denetimleri eklemek için ikili dosyalar Derleyici, derleme zamanında erişimin güvenli olacağını kanıtlayamazsa ve dizi boyutu, kontrol edilebilmesi için çalışma zamanında bilinecekse bu kontroller eklenir. Android 10, BoundSan'ı Bluetooth ve codec'lerde dağıtır. BoundSan, derleyici tarafından sağlanır ve platformdaki çeşitli bileşenlerde varsayılan olarak etkindir.

Uygulama

BoundSan, UBSan'ın sınır temizleyicisini kullanır. Bu azaltma, modül başına düzeyde etkinleştirilir. Android'in kritik bileşenlerinin güvende kalmasına yardımcı olur ve devre dışı bırakılmamalıdır.

BoundSan'ı ek bileşenler için etkinleştirmenizi önemle tavsiye ederiz. İdeal adaylar, ayrıcalıklı doğal kod veya güvenilmeyen kullanıcı girişini ayrıştıran karmaşık doğal koddur. BoundSan'ın etkinleştirilmesiyle 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 ek maliyet yüzdesi bekleyin ve performansın sorun oluşturup oluşturmadığını test edin.

BoundSan'ı taslak dosyalarında etkinleştirme

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

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

diag mülkü, dezenfektanlar için teşhis modunu etkinleştirir. Teşhis modunu yalnızca test sırasında kullanın. Teşhis modu, taşmalar olduğunda işlemi iptal etmez. Bu durum, azaltmanın güvenlik avantajını ortadan kaldırır ve daha yüksek performans yükü getirir. Bu nedenle, üretim yapıları için önerilmez.

ENGELLENENLER LİSTESİ

BLOCKLIST mülkü, 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 bir katkı sağlıyorsa kullanın. Dizi erişimlerinin 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.

Makefile'lerde BoundSan'ı etkinleştirme

BoundSan, makefile'lerde ikili ve kitaplık modülleri için LOCAL_SANITIZE değişkenine "bounds" eklenerek 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 listesi kabul eder.

LOCAL_SANITIZE_DIAG, teşhis modunu açar. Teşhis modunu yalnızca test sırasında kullanın. Teşhis modu, taşmalar olduğunda işlemi iptal etmez. Bu durum, azaltmanın güvenlik avantajını ortadan kaldırır ve daha yüksek bir performans yükü getirir. 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 bir katkı sağlıyorsa kullanın. Dizi erişimlerinin 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 özellikleriyle işlevlerde ve kaynak dosyalarda devre dışı bırakabilirsiniz. BoundSan'ı etkin durumda tutmak en iyisidir. Bu nedenle, yalnızca işlev veya dosya çok fazla performans yükü oluşturuyorsa ve kaynak manuel olarak incelendiyse devre dışı bırakın.

BoundSan'ı işlev özellikleri ve BLOCKLIST dosya 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 ENGELENENLER LİSTESİ'ni belirli bir temizleyiciye göre kapsamlandırın.

Doğrulama

BoundSan için özel bir CTS testi yoktur. Bunun yerine, cihazı etkilemediğini doğrulamak için BoundSan etkinleştirilmiş veya devre dışı bırakılmış halde CTS testlerinin geçtiğinden emin olun.

Sorun giderme

Önceden tespit edilmemiş, sınır dışı erişimlerden emin olmak için BoundSan'ı etkinleştirdikten sonra bileşenleri kapsamlı bir şekilde test edin.

BoundSan hataları, aşağıdaki tombstone 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'e yazdırılır. Bu mod varsayılan olarak iptal mesajı vermez. Hata olup olmadığını kontrol etmek için logcat dosyasını inceleyin.

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