Eski bir C derleyicisini kullanmak bir güvenlik riski oluşturuyor mu?


139

Üretimde kimsenin umursamadığı bazı inşa sistemlerimiz var ve bu makineler GCC 3 veya GCC 2 gibi GCC'nin eski versiyonlarını çalıştırıyor.

Ve yönetimi daha yeni bir sürüme yükseltmeye ikna edemiyorum: "kırılmazsa, düzeltmeyin" diyorlar.

Çok eski bir kod tabanını (80'lerde yazılmış) koruduğumuz için, bu C89 kodu bu derleyiciler üzerinde gayet iyi derleniyor.

Ama bu eski şeyleri kullanmanın iyi bir fikir olduğundan emin değilim.

Sorum şu:

Eski bir C derleyicisi kullanmak, derlenmiş programın güvenliğini tehlikeye atabilir mi?

GÜNCELLEME:

Aynı kod, Windows hedefleri için Visual Studio 2008 tarafından oluşturulmuştur ve MSVC henüz C99 veya C11'i desteklememektedir (daha yeni MSVC'nin çalışıp çalışmadığını bilmiyorum) ve en son GCC'yi kullanarak Linux kutumda oluşturabilirim. Dolayısıyla, daha yeni bir GCC'ye düşecek olsaydık, muhtemelen eskisi kadar iyi inşa ederdi.


5
İlginç bir soru - bu da hızlı bir şekilde okunmaya değer olabilir - developers.slashdot.org/story/13/10/29/2150211/… .. böylece daha yeni derleyiciler optimizasyon sırasında güvenliği tehlikeye atabilir.
Neil

6
Bu eski gcc sürümleri ASLR için PIC / PIE'ye derlemeyi destekliyor mu? Yığın kanaryalarını destekliyorlar mı? W ^ X (NX)? Aksi takdirde, güvenlik açıkları için azaltma önlemleri eksikliği yükseltme için iyi bir nedendir.
EOF

12
Sadece gcc 4.x'deki uyarılara bakmak, sahip olduğunuzu bilmediğiniz mevcut güvenlik deliklerinin bir miktarını hemen ortaya çıkarabilir.
OrangeDog

7
@OrangeDog: Neden gcc 4.x? gcc6 güncel sürüm serisidir ve gcc 5 bir süredir piyasadadır. Ama evet, -O3 -Wall -Wextra -fsanitize=undefinedmodern gcc ve clang ile tespit edilen sorunları düzeltmek yardımcı olacaktır.
Peter Cordes

4
@OrangeDog GCC pazarlama sürüm numaralarına geçti. GCC 5, varsayılan C ve C ++ standartlarını ve libstdc ++ ABI'yi değiştirdikleri için büyük bir sürüm desteğini hak etti. GCC 6, 5.1 olarak adlandırılmalıdır.
zwol

Yanıtlar:


102

Aslında tam tersini savunurum.

Davranışın C standardı tarafından tanımlanmadığı, ancak belirli bir platformda "aptal bir derleyici" ile ne olacağı aşikar olduğu bazı durumlar vardır. İşaretli bir tamsayının taşmasına izin vermek veya iki farklı türde değişken olsa da aynı belleğe erişmek gibi durumlar.

Gcc (ve clang) 'ın son sürümleri, bu durumları, ikili kodun "tanımlanmamış davranış" koşulundaki davranış biçimini değiştirmeleri durumunda umursamayan optimizasyon fırsatları olarak ele almaya başlamıştır. Kod tabanınız C'yi "taşınabilir bir birleştirici" gibi tedavi eden kişiler tarafından yazılmışsa, bu çok kötüdür. Zaman ilerledikçe, iyimserler, bu optimizasyonları yaparken daha büyük ve daha büyük kod parçalarına bakmaya başladılar, ikili, "aptal bir derleyici tarafından inşa edilen bir ikili" ne yapacağından başka bir şey yapacaklar.

"Geleneksel" davranışı (yukarıda bahsettiğim iki için -fwrapv ve -fno-katı-örtüşme) geri yüklemek için derleyici anahtarları vardır, ancak önce bunları bilmeniz gerekir.

Prensipte bir derleyici hata, uyumlu kodu bir güvenlik deliğine dönüştürebilirken, bunun büyük bir şemada ihmal edilebilir olduğunu düşünürüm.


13
Ancak bu argüman her iki şekilde de işe yarıyor. Bir derleyici tahmin edilebilir "tanımlanmamış davranış" varsa, o zaman kötü niyetli kullanımı yapmak tartışmasız daha kolay olabilir ...
André

18
@Andre Derlenmiş kod zaten öngörülebilir tanımsız davranışa sahiptir. Yani, kod derlendikten sonra, bu derlenmiş versiyonda, öngörülemeyen herhangi bir davranış öngörülebilir.
user253751

6
people who treated C like a "portable assembler"C ne olsa değil mi?
Maksimum

10
@Max Bu cevap, "taşınabilir montajcı" kavramının modern optimizatörler nedeniyle pratikte en azından modası geçmiş olduğu konusunda tam olarak uyarıyor. Ve başlamak için hiçbir zaman kavramsal olarak doğru olmadığını iddia ediyorum.
Theodoros Chatzigiannakis

6
Tanımsız davranışlara güvenen ve daha sonra ektiklerini toplamaya başlayanlar için burada sempati yok. Bu, yeni derleyicilerin doğal olarak daha az güvenli olduğu anlamına gelmez - bu, uyumsuz kodun bir saatli bomba olduğu anlamına gelir. Suçlama buna göre paylaştırılmalıdır.
underscore_d

52

Her iki eylem planında da riskler vardır.


Eski derleyiciler olgunluk avantajına sahiptir ve içlerinde kırılan her şey muhtemelen (ancak hiçbir garanti yoktur) başarılı bir şekilde çözülmüştür.

Bu durumda, yeni bir derleyici potansiyel yeni hata kaynağıdır.


Öte yandan, daha yeni derleyiciler ek takımlarla birlikte gelir :

  • GCC ve Clang şimdi dezenfektanlara sahip , çeşitli türlerin tanımlanmamış davranışlarını tespit etmek için çalışma zamanını düzenleyebilen bulunuyor (Google Derleyici ekibinin Chandler Carruth, geçen yıl tam kapsama ulaşmasını beklediğini iddia etti)
  • Clang, en azından, özellikler sertleştirme , örneğin Kontrol Akışı Bütünlüğü , kontrol akışının yüksek jaklarını tespit etmekle ilgilidir, ayrıca yığın parçalama saldırılarına karşı koruma sağlamak için sertleştirme aletleri de vardır (yığının kontrol akışı bölümünü veri kısmından ayırarak) ; sertleştirme özellikleri genellikle düşük ek yüktür (<% 1 CPU ek yükü)
  • Clang / LLVM ayrıca test edilen fonksiyonun giriş alanını akıllıca araştıran enstrümanlı bulanık birim testleri oluşturmak için bir araç olan libFuzzer üzerinde çalışıyor (henüz keşfedilmemiş yürütme yollarını almak için girişi düzenleyerek)

İkili dosyalarınızı dezenfektanlarla (Adres Temizleyici, Bellek Temizleyici veya Tanımsız Davranış Temizleyici) enstrümanın ardından ( örneğin Amerikan Bulanık Lop'ı kullanarak) bulanıklaştırmak , bir dizi yüksek profilli yazılımdaki açıkları ortaya çıkarmıştır, örneğin bu LWN.net makalesine bakın .

Derleyicinizi yükseltmedikçe bu yeni araçlara ve gelecekteki tüm araçlara erişilemez.

Güçsüz bir derleyicide kalarak, kafanızı kumun içine sokuyorsunuz ve parmaklarınızı kırılganlık bulunmayan bir şekilde geçiyorsunuz. Ürününüz yüksek değerli bir hedefse, tekrar değerlendirmenizi öneririm.


Not: Üretim derleyicisini yükseltmezseniz bile, güvenlik açığını yine de denetlemek için yeni bir derleyici kullanmak isteyebilirsiniz; bunlar farklı derleyiciler olduğu için garantilerin azaldığını unutmayın.


1
+1, yeni derleyicilerin diğer cevapların 'b-ama benim eski eski UB' bandwagon'una kazıklamak yerine daha güvenli olabileceği durumlardan bahsetmekten rahatsızlık duyuyor. Bu, doğrudan güvenlikle ilgili olmayan, ancak makul modern olmak için daha fazla itici güç sağlayan diğer birçok iyileştirmenin üstünde.
underscore_d

'Müstehcenlik yoluyla güvenliği' savunmak gibi hissetse de; eski derleyicileri etkileyen hatalar bilinir ve halka açıktır. Yeni derleyicilerin hataları tanıtacağını kabul etsem de, bu hatalar önceki sürümlerde olduğu gibi henüz herkese açık değil, bu da uygulamayı sık sık güncelliyorsanız bir miktar güvenlik.
The6P4C

Chandler Carruth çok tatlı ve bu harika şeylerden bahsediyor. Yapabilirsem onunla evlenirdim.
Daniel Kamil Kozar

46

Derlenmiş kodunuzda kullanılabilecek hatalar var. Hatalar üç kaynaktan gelir: Kaynak kodunuzdaki hatalar, derleyici ve kütüphanelerdeki hatalar ve kaynak kodunuzda derleyicinin hataya dönüştüğü tanımsız davranış. (Tanımsız davranış bir hatadır, ancak derlenmiş koddaki bir hata değildir. Örnek olarak, i = i ++; C veya C ++ 'da bir hatadır, ancak derlenmiş kodunuzda i 1 artabilir ve Tamam veya ayarlanmış olabilir. bazı ıvır zıvır ve böcek olmak).

Derlenmiş kodunuzdaki hata oranı, test ve müşteri hata raporları nedeniyle hataların düzeltilmesi nedeniyle muhtemelen düşüktür. Bu yüzden başlangıçta çok sayıda hata olmuş olabilir, ancak bu azalmıştır.

Daha yeni bir derleyiciye yükseltirseniz, derleyici hatalarının getirdiği hataları kaybedebilirsiniz. Ama bu böceklerin hepsi bilginize göre kimsenin bulamadığı ve kimsenin sömürmediği hatalar olurdu. Ancak yeni derleyici kendi başına hatalara sahip olabilir ve daha da önemlisi daha yeni derleyiciler, tanımlanmamış davranışı derlenmiş koddaki hatalara dönüştürme konusunda daha güçlü bir eğilime sahiptir.

Böylece derlenmiş kodunuzda bir sürü yeni hata olacak; bilgisayar korsanlarının bulabileceği ve istismar edebileceği tüm hatalar. Ve çok fazla test yapmazsanız ve uzun süre hata bulmak için kodunuzu müşterilerle bırakmazsanız, daha az güvenli olacaktır.


6
Başka bir deyişle ... derleyicinin hangi sorunları ortaya çıkardığını anlamanın kolay bir yolu yok ve yaptığınız her şeyi değiştirerek farklı bir dizi bilinmeyen sorun elde etmek mi?
Jeremy Kato

1
@ JererKato: Eh, farklı bilinen sorunlar da elde ettiğiniz bazı durumlar var . Derleyicinin kendisinde bilinen güvenlik kusurlarının ne olduğundan emin değilim, ancak somut bir örnek uğruna, yeni bir derleyiciye güncellemenin de en son libc'yi alabilmesi anlamına geldiğini varsayalım (eski olanı kullanmak mümkün olmamak demektir) ) bunu yapmak için, o zaman diye biliyorum sen bu kusur tamir ediyoruz getaddrinfo(): access.redhat.com/articles/2161461 . Bu örnek aslında bir derleyici güvenlik hatası değildir, ancak 10 yıldan fazla bir süredir bilinen bazı sabit kusurlar vardır.
Steve Jessop

2
Heh, aslında bu kusur sadece 2008'de tanıtıldı, bu yüzden sorgulayan ondan güvende olabilir. Ama benim açımdan o örnekle ilgili değil, eski bir araç zincirinin kodunuza koyacağı bilinen hatalar var. Yani sen bilinmeyenli yeni bir dizi tanıtmak doğrudur güncellemek, ama bu olmadığı zaman bütün yapmanız . Temel olarak, en yeni araç zincirinin giderdiği bilinen kritik kusurda bırakarak "zarınızı" daha güvenli olup olmadığınızı tahmin etmeniz mi, yoksa kendi kodunuzdaki tüm tanımlanmamış davranışlarda zarları tekrar yuvarlamanın bilinmeyen sonuçlarını almanız gerekir.
Steve Jessop

19

Eğer kırılmazsa, tamir etme

Patronunuz bunu söylerken kulağa doğru geliyor, ancak daha önemli faktör, girdilerin, çıktıların, arabellek taşmalarının korunmasıdır. Bunların eksikliği, kullanılan derleyiciden bağımsız olarak, bu bakış açısından zincirdeki en zayıf halkadır.

Ancak, kod tabanı eskiyse ve kullanılan K&R C'nin tip güvenliği, güvensiz araçlar, vb. Gibi zayıflıklarını azaltmak için çalışmalar yapılmışsa , derleyiciyi daha modern C99'a yükseltmek / C11 standartları her şeyi kırıyor mu? "

Yan etkileri tetikleyebilecek daha yeni C standartlarına geçmek için açık bir yol olması şartıyla, eski kod tabanının bir çatalını denemek, değerlendirmek ve ekstra tip kontrolleri, akıl sağlığı kontrolleri koymak ve daha yeni derleyicinin giriş / çıkış veri kümeleri üzerinde herhangi bir etkisi vardır.

Daha sonra patronunuza gösterebilirsiniz, " İşte güncellenmiş kod tabanı, yeniden düzenlenmiş, daha çok endüstri tarafından kabul edilen C99 / C11 standartlarına uygun ... ".

Yani, üzerinde tartılması gerekecekti kumar çok dikkatli , değişime direnç bu ortamda orada gösterebilir ve daha yeni şeyler dokunmak reddedebilir.

DÜZENLE

Sadece birkaç dakika oturdu, bu kadar fark etti, K & R tarafından üretilen kod 16bit'lik bir platformda çalışıyor olabilir, olasılıklar, daha modern bir derleyiciye yükseltme aslında kod tabanını kırabilir, mimari açıdan düşünüyorum, 32bit kod üretilecekti Bu başka olduğunu, giriş / çıkış veri setleri için kullanılan yapılar üzerine komik yan etkileri olabilir kocaman dikkatlice tartmak için faktördür.

Ayrıca OP, kod tabanını oluşturmak için Visual Studio 2008'i kullandığından bahsettiğinden, gcc kullanmak MinGW veya Cygwin'i çevreye getirmeye neden olabilir, bu da hedef Linux için değilse, çevre üzerinde bir etki değişikliği olabilir. Denemeye değer, eski K&R kod tabanındaki gürültüyü en aza indirmek için derleyiciye ek anahtarlar eklemek zorunda kalabilir, diğer önemli şey, hiçbir işlevin bozulmadığından emin olmak için çok fazla test yapmaktır, ağrılı bir egzersiz olabilir.


Aynı kod, Windows hedefleri için Visual Studio 2008 tarafından oluşturulmuştur ve MSVC henüz C99 veya C11'i desteklememektedir (daha yeni MSVC'nin çalışıp çalışmadığını bilmiyorum) ve en son GCC'yi kullanarak Linux kutumda oluşturabilirim. Dolayısıyla, daha yeni bir GCC'ye düşecek olsaydık, muhtemelen eskisi kadar iyi inşa ederdi.
Calmarius

@Calmarius kafa kafaya teşekkür için teşekkürler, belki de yorum eklemek için sorunuzu düzenlemek en iyisi olabilir, Bu önemli :) Ve orada olmalıydı; D
t0mm13b

@Calmarius, yeni güncellenen soru hakkındaki düşüncem olan cevabımı düzenledi.
t0mm13b

2
“16 bit platform üzerinde çalışıyor olabilir, şans, daha modern derleyiciye yükseltme aslında kod tabanını kırabilir, mimari açıdan düşünüyorum, 32bit kod” Sorunun kodu yeni uygulama tanımlı olarak taşımakla ilgili olduğunu düşünmüyorum parametreleri.
Pascal Cuoq

Kabul. Bu var mümkün bir çalışma zamanı açığı bir derleyici hata yarattığı edilebileceğini. Ama o , kodun, arabellek ve yığın taşması gibi şeyler nedeniyle çalışma zamanı güvenlik açıkları içermesi çok daha olasıdır . Bu nedenle, bu kod tabanını daha güvenli hale getirmek için zaman harcadığınızda, programınızın sınırlarını aşmadığından emin olmak için giriş dizelerinin uzunluğunu kontrol etmek gibi şeylere yatırım yapmalısınız. Daha yeni bir derleyici almak pek yardımcı olmaz. Yerel dize ve dizi nesnelerine sahip bir dilde kodu sıfırdan yeniden yazmak çok yardımcı olacaktır. Ama patronun bunun bedelini ödemeyecek.
O. Jones

9

Eski bir C derleyicisi kullanmak, derlenmiş programın güvenliğini tehlikeye atabilir mi?

Tabii ki, eski derleyici programınızı etkileyeceğini bildiğiniz bilinen hataları içeriyorsa.

Soru şu, öyle mi? Kesin olarak bilmek için, sürümünüzden bugüne kadar olan tüm değişiklik günlüğünü okumalı ve yıllar boyunca düzeltilen her bir hatayı kontrol etmelisiniz.

Programınızı etkileyecek derleyici hatalarına dair bir kanıt bulamazsanız, GCC'yi sadece bunun için güncellemek biraz paranoyak gibi görünüyor. Daha yeni sürümlerin henüz keşfedilmemiş yeni hatalar içerebileceğini unutmayın. Son zamanlarda GCC 5 ve C11 desteği ile birçok değişiklik yapıldı.

Bununla birlikte, 80'lerde yazılmış kod, büyük olasılıkla, derleyiciye bakılmaksızın, güvenlik açıkları ve kötü tanımlanmış davranışa güvenmekle ağzına kadar doludur. Burada standart C'den bahsediyoruz.


6
Bunun paranoya olduğunu sanmıyorum; Bence OP patronunu ikna etmek için nedenler icat etmeye çalışıyor. Muhtemelen OP aslında yeni bir derleyici istiyor çünkü daha iyi asm yapıyorlar (LTO ile çapraz dosya optimizasyonu dahil), daha kullanışlı tanılama / uyarılara sahipler ve modern dil özelliklerine ve sözdizimine izin veriyorlar. (örneğin C11 stdatomik).
Peter Cordes

9

Kötü niyetli bir geliştiricinin bir derleyici hatasıyla arka kapıyı gizleyebileceği bir güvenlik riski vardır. Kullanılan derleyicideki bilinen hataların miktarına bağlı olarak, arka kapı az ya da çok göze çarpmayan görünebilir (her durumda, nokta, kaynak düzeyinde kıvrık bile olsa kodun doğru olmasıdır. buggy olmayan bir derleyici arka kapıyı bulamaz, çünkü arka kapı bu koşullarda mevcut değildir). Ekstra inkar edilebilirlik noktaları için, kötü amaçlı geliştirici daha önce bilinmeyen derleyici hatalarını kendi başlarına arayabilir. Yine, kamuflajın kalitesi bulunan derleyici hatalarının seçimine bağlı olacaktır.

Bu saldırı, bu makaledeki sudo programında gösterilmiştir . bcrypt, Javascript minifiers için harika bir takip yazdı .

Bunun dışında endişe, C derleyicileri evrimi tanımsız davranış faydalanmak oldu daha ve daha ve daha iyi niyetle yazılmış eski C kodu aslında daha zaman bir C derleyicisi ile derlenen veya en derlenmiş güvenli olacağını, böylece agresif -O0 (ancak bazı yeni program kırıcı UB'den yararlanan optimizasyonlar -O0'da bile derleyicilerin yeni sürümlerinde tanıtıldı ).


7

Eski derleyiciler bilinen hack saldırılarına karşı koruma sağlamayabilir. Örneğin istif parçalama koruması, GCC 4.1'e kadar kullanılmamıştır . Bu nedenle, eski derleyicilerle derlenen kod, daha yeni derleyicilerin koruyacağı şekillerde savunmasız olabilir.


6

Endişelenmeniz gereken bir diğer husus da yeni kodun geliştirilmesi .

Eski derleyiciler, bazı dil özellikleri için programcı tarafından standartlaştırılan ve beklenenden farklı davranışlara sahip olabilir. Bu uyumsuzluk, gelişimi yavaşlatabilir ve sömürülebilecek ince hataları ortaya çıkarabilir.

Eski derleyiciler daha az özellik sunar (dil özellikleri dahil!) Ve aynı zamanda optimize etmezler. Programcılar bu eksikliklerin üstesinden gelebilir - örneğin eksik özellikleri yeniden uygulayarak veya anlaşılması zor ancak daha hızlı çalışan akıllı kod yazarak - ince hataların yaratılması için yeni fırsatlar yaratır.


5

Hayır

Nedeni basittir, eski derleyicinin eski hataları ve açıkları olabilir, ancak yeni derleyicinin yeni hataları ve açıkları olacaktır.

Yeni bir derleyiciye yükselterek herhangi bir hatayı "düzeltmezsiniz". Yeni böcekler ve istismarlar için eski böcekleri ve istismarları değiştirme.


3
Bunlar çok basit görünüyor: Yeni derleyicinin zayıf yönleri olabilir, ancak eski derleyiciden daha az olmalarını beklerim ve o zamandan beri bilinen çeşitli kod güvenlik açıklarını tespit etmesi muhtemeldir.
PJTraill

Ancak yeni derleyicinin bilinmeyen yeni zayıflıkları olabilir. Derleyici tek başına güncellenmesi gereken bir güvenlik riski değildir. Yüzey alanınızı azaltmıyorsunuz. Bilinmeyen bir küme için bilinen bir dizi sorunu alıp satmanız.
coteyr

Böceklerin bulunmasına yardımcı olan araçlar, GCC'nin ilk günlerinden bu yana büyük ölçüde iyileşmiştir ve kaliteyi iyileştirmek için bu araçlar (statik analiz, enstrümanlı kod dinamik analizi / temizleyiciler, füzerler, vb.) Derleyici koduna da uygulanmıştır. GCC 2 döneminde tüm böcek sınıflarını bulmak çok zordu. Derleyici hatalarının sürümler arasında karşılaştırılması - bkz. Sayfa 7: cs.utah.edu/~regehr/papers/pldi11-preprint.pdf GCC 4.5 ve LLVM 2.8 (en son yayıncılıkta), en az hatadan kaynaklanıyor.
Jetski S-tipi

2

Eski derleyicideki herhangi bir hatanın, yeni bir derleyici kullanmak yerine iyi bilinmesi ve belgelenmesi olasılığı daha yüksektir, böylece etrafındaki kodlamalarla bu hataları önlemek için önlemler alınabilir. Yani bu yükseltme için bir argüman olarak yeterli değil. Çalıştığım tartışmaların aynısı, gömülü yazılım için bir kod tabanı üzerinde GCC 4.6.1 kullanıyoruz ve yeni, belgelenmemiş hatalardan korkma nedeniyle en son derleyiciye yükseltme konusunda büyük bir isteksizlik var.


0

Sorunuz iki bölüme ayrılıyor:

  • Açık: “Eski derleyiciyi kullanmada daha büyük bir risk var mı” (başlığınızdaki az çok)
  • Örtük: “Yönetimi yükseltmeye nasıl ikna edebilirim”

Belki de hem mevcut kod tabanınızda istismar edilebilir bir kusur bularak hem de daha yeni bir derleyicinin bunu tespit edeceğini göstererek cevap verebilirsiniz. Tabii ki yönetiminiz “bunu eski derleyiciyle buldunuz” diyebilir, ancak bunun önemli bir çabaya mal olduğunu belirtebilirsiniz. Veya güvenlik açığını bulmak için yeni derleyici üzerinden çalıştırırsınız, sonra kodu yeni derleyiciyle derleyebiliyorsanız / kullanabiliyorsanız güvenlik açığından yararlanabilirsiniz. Dostça bir bilgisayar korsanından yardım isteyebilirsiniz, ancak bu onlara güvenmeye ve onlara kodu gösterme / izin verme (ve yeni derleyiciyi kullanma) özelliklerine bağlıdır.

Ancak sisteminiz bilgisayar korsanlarına maruz kalmıyorsa, derleyici yükseltmesinin etkinliğinizi artıracağı konusunda belki de daha fazla ilgilenmelisiniz: MSVS 2013 Kod Analizi, MSVS 2010'dan çok daha erken potansiyel hataları bulur ve C99 / C11'i az ya da çok destekler - resmi olarak foryapılıp yapılmadığından emin değilim, ancak bildirimler ifadeleri izleyebilir ve değişkenleri- döngülerde bildirebilirsiniz.

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.