Derleme dosyaları projeye dahil edildiğinde mmap'den beklenmeyen yürütme izni


94

Bununla kafamı duvara vuruyorum.

Projemde mmap, mapping ( /proc/self/maps) ile bellek ayırdığımda , yalnızca okunabilir bellek istememe rağmen okunabilir ve yürütülebilir bir bölge olduğunu gösteriyor .

Strace (iyi görünüyor) ve diğer hata ayıklama içine baktıktan sonra, bu garip sorunu önlemek gibi görünüyor tek şey tespit edebildi: derleme dosyaları projeden kaldırma ve sadece saf C. bırakarak (ne ?!)

İşte benim garip örneğim, Ubunbtu 19.04 ve varsayılan gcc üzerinde çalışıyorum.

Hedef yürütülebilir dosyayı ASM dosyasıyla (boş) mmapderlerseniz, okunamayan ve yürütülebilir bir bölge döndürür, onsuz oluşturursanız doğru davranır. /proc/self/mapsBenim örneğime gömülü çıktı bakın .

example.c

#include <stdio.h>
#include <string.h>
#include <sys/mman.h>

int main()
{
    void* p;
    p = mmap(NULL, 8192,PROT_READ,MAP_ANONYMOUS|MAP_PRIVATE,-1,0);

    {
        FILE *f;
        char line[512], s_search[17];
        snprintf(s_search,16,"%lx",(long)p);
        f = fopen("/proc/self/maps","r");
        while (fgets(line,512,f))
        {
            if (strstr(line,s_search)) fputs(line,stderr);
        }

        fclose(f);
    }

    return 0;
}

example.s : Boş bir dosya!

çıktılar

ASM dahil sürüm ile

VirtualBox:~/mechanics/build$ gcc example.c example.s -o example && ./example
7f78d6e08000-7f78d6e0a000 r-xp 00000000 00:00 0 

ASM dahil sürüm olmadan

VirtualBox:~/mechanics/build$ gcc example.c -o example && ./example
7f1569296000-7f1569298000 r--p 00000000 00:00 0 

5
Bu çok garip.
fuz

6
Bunu sadece GCC (CMake yok) ile çoğaltmayı başardım, bu yüzden örneği daha az yapmak için soruyu düzenledim.
Joseph Sible-Reinstate Monica


Haklı olabilirsin, cevabının bir kısmı READ_IMPLIES_EXEC persona civarında olmalı
Ben Hirschberg

Kaynak dosyalarınızı ile birleştirin -Wa,--noexecstack.
jww

Yanıtlar:


90

Linux bir var yürütme alanını denilen READ_IMPLIES_EXECile ayrılan tüm sayfaları neden olur, PROT_READayrıca verilecek PROT_EXEC. Bu program size bunun etkin olup olmadığını gösterecektir:

#include <stdio.h>
#include <sys/personality.h>

int main(void) {
    printf("Read-implies-exec is %s\n", personality(0xffffffff) & READ_IMPLIES_EXEC ? "true" : "false");
    return 0;
}

Bunu boş bir .sdosyayla birlikte derlerseniz, dosyanın etkin olduğunu görürsünüz, ancak bir dosya devre dışı bırakılır. Bunun ilk değeri, ikili dosyanızdaki ELF meta bilgisinden gelir . Yap readelf -Wl example. Boş .sdosya olmadan derlediğinizde bu satırı görürsünüz :

  GNU_STACK      0x000000 0x0000000000000000 0x0000000000000000 0x000000 0x000000 RW  0x10

Ama bunu derlediğinizde:

  GNU_STACK      0x000000 0x0000000000000000 0x0000000000000000 0x000000 0x000000 RWE 0x10

RWESadece yerine not edin RW. Bunun nedeni, bağlayıcının, açıkça belirtmedikleri belirtilmedikçe derleme dosyalarınızın read-implies-exec gerektirdiğini ve programınızın herhangi bir bölümünün read-implies-exec gerektirdiğini varsaymasıdır. . GCC'nin derlediği montaj dosyaları, bu çizgiyle buna ihtiyaç duymadığını söyler (derlerseniz bunu görürsünüz -S):

        .section        .note.GNU-stack,"",@progbits

Bu satırı girin example.s, bağlayıcıya da ona ihtiyaç duymadığını söyleyecektir ve programınız beklendiği gibi çalışacaktır.


13
Kutsal saçmalık, bu garip bir varsayılan. Sanırım alet zinciri noexec'ten önce vardı ve noexec'i varsayılan yapmak kırılmış şeylere sahip olabilirdi. Şimdi NASM / YASM gibi diğer toplayıcıların nasıl .odosya oluşturduğunu merak ediyorum ! Her neyse, sanırım bu kullanılan mekanizma gcc -zexecstackve neden sadece yığını değil her şeyi çalıştırılabilir kılıyor.
Peter Cordes

23
@Peter - Bu yüzden birleştirici kullanan Botan, Crypto ++ ve OpenSSL gibi projeler ekliyor -Wa,--noexecstack. Bence çok kötü keskin bir kenar. Sessiz nx-yığın kaybı bir güvenlik açığı olmalıdır. Binutil millet bunu düzeltmelidir.
jww

14
@jww Gerçekten de bir güvenlik sorunu, daha önce kimsenin bildirmediği garip
Ben Hirschberg

4
+1, ancak satırın anlamı / mantığı .note.GNU-stack,"",@progbitsaçıklanırsa bu cevap çok daha iyi olurdu - şu anda opak, "bu sihirli karakter dizisi bu etkiye neden oluyor" a eşdeğer, ancak dize açıkça bir çeşit semantik.
mtraceur

33

Montaj dosyalarınızı GNU'ya özgü bölüm yönergesi değişkenleriyle değiştirmeye alternatif olarak, montaj dosyaları -Wa,--noexecstackoluşturmak için komut satırınıza ekleyebilirsiniz . Örneğin, müslümanlarda nasıl yaptığımı görün configure:

https://git.musl-libc.org/cgit/musl/commit/configure?id=adefe830dd376be386df5650a09c313c483adf1a

En azından bazı entegre clang sürümleri ile clang'ın --noexecstack(olmadan -Wa) geçirilmesini gerektirebileceğine inanıyorum , bu yüzden yapılandırma komut dosyanız muhtemelen her ikisini de kontrol etmeli ve hangisinin kabul edildiğini görmelidir.

Aynı sonucu elde etmek için -Wl,-z,noexecstackbağlantı zamanında (in LDFLAGS) da kullanabilirsiniz . Bunun dezavantajı, projenizin .adiğer yazılımlar tarafından kullanılmak üzere statik ( ) kütüphane dosyaları üretmesi durumunda yardımcı olmamasıdır , çünkü daha sonra diğer programlar tarafından kullanıldığında bağlantı zamanı seçeneklerini kontrol etmezsiniz.


1
Hmm ... Bu yazıyı okumadan önce Zengin Felker olduğunu bilmiyordum. Görünen ad dalias neden olmasın?
SS Anne
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.