Yayınlanma tarihi: 19 Mart 2025
Skrifa, Rust'ta yazılmış ve Chrome'daki yazı tipi işlemenin tüm kullanıcılarımız için güvenli olmasını sağlamak amacıyla FreeType'in yerine oluşturulmuştur. Skifra, Rust'un bellek güvenliğinden yararlanır ve Chrome'daki yazı tipi teknolojisi iyileştirmelerinde daha hızlı iterasyon yapmamıza olanak tanır. FreeType'ten Skrifa'ya geçiş, yazı tipi kodumuzda değişiklik yaparken hem çevik hem de korkusuz olmamızı sağlıyor. Artık güvenlik hatalarını düzeltmek için çok daha az zaman harcıyoruz. Bu da güncellemelerin daha hızlı yapılmasına ve daha iyi kod kalitesine yol açıyor.
Bu yayında, Chrome'un FreeType'ten neden vazgeçtiği ve bu geçişin sağladığı iyileştirmelerle ilgili bazı ilginç teknik ayrıntılar paylaşılmaktadır.
FreeType neden değiştiriliyor?
Web'in benzersizliği, kullanıcıların çeşitli güvenilmeyen kaynaklardan güvenilmeyen kaynakları getirmelerine olanak tanıması ve bu işlemin sorunsuz ve güvenli bir şekilde gerçekleşmesini beklemesidir. Bu varsayım genellikle doğrudur ancak kullanıcılara bu vaadi tutmak da bir maliyete sahiptir. Örneğin, Chrome bir web yazı tipini (ağ üzerinden yayınlanan bir yazı tipi) güvenli bir şekilde kullanmak için çeşitli güvenlik önlemleri kullanır:
- Yazı tipi işleme, iki kural uyarınca korumalı alanda gerçekleşir: Yazı tipleri güvenilir değildir ve bunları kullanan kod güvenli değildir.
- Yazı tipleri, işlenmeden önce OpenType Temizleyici'den geçirilir.
- Yazı tiplerinin sıkıştırılmasını ve işlenmesini sağlayan tüm kitaplıklar bulunma testi ile kontrol edilir.
Chrome, FreeType ile birlikte gelir ve Android, ChromeOS ve Linux'ta birincil yazı tipi işleme kitaplığı olarak bu kitaplıktan yararlanır. Bu, FreeType'te bir güvenlik açığı varsa çok sayıda kullanıcının risk altında olduğu anlamına gelir.
FreeType kitaplığı, Chrome tarafından metrikleri hesaplamak ve yazı tiplerinden ipucu verilen ana hatları yüklemek için kullanılır. Genel olarak, FreeType'in kullanımı Google için büyük bir kazanç oldu. Karmaşık bir görevi iyi bir şekilde yerine getiriyor. Bu çözüme çok güveniyor ve katkıda bulunuyoruz. Ancak güvenli olmayan bir kodla yazılmıştır ve kökeni, kötü amaçlı girişlerin daha az olası olduğu bir zamana dayanır. Google'ın, bulanıklık testi ile bulunan sorun akışına ayak uydurması için en az 0,25 tam zamanlı yazılım mühendisi gerekir. Daha da kötüsü, her şeyi bulamıyoruz veya bulduğumuz şeyleri yalnızca kod kullanıcılara dağıtıldıktan sonra buluyoruz.
Bu sorun kalıbı FreeType'e özgü değildir. Bulabildiğimiz en iyi yazılım mühendislerini kullandığımızda, her değişikliği kod incelemesinden geçirdiğimizde ve testler istediğimizde bile diğer güvenli olmayan kitaplıklarda sorunlar olduğunu gözlemliyoruz.
Sorunların neden tekrar ortaya çıktığı
FreeType'in güvenliğini değerlendirirken ortaya çıkabilecek üç ana sorun sınıfı gözlemledik (liste tam değildir):
Güvenli olmayan bir dilin kullanılması
Desen/Sorun | Örnek |
---|---|
Manuel bellek yönetimi |
|
Kontrol edilmeyen dizi erişimi | CVE-2022-27404 |
Tam sayı taşmaları | CFF çizimi ve ipucu için TrueType ipucu içeren yerleşik sanal makinelerin yürütülmesi sırasında https://issues.oss-fuzz.com/issues?q=FreeType%20Integer-overflow |
Sıfırlama ve sıfırlama dışı atama işlemlerinin yanlış kullanımı | https://gitlab.freedesktop.org/freetype/freetype/-/merge_requests/94 adresindeki tartışma, daha sonra 8 fuzzer sorunu bulundu |
Geçersiz yayınlar | Makro kullanımıyla ilgili aşağıdaki satıra bakın |
Projeye özgü sorunlar
Desen/Sorun | Örnek |
---|---|
Makrolar, açık boyut yazma eksikliğini gizliyor |
|
Yeni kod, savunma amaçlı yazılmış olsa bile sürekli olarak hata ekler. |
|
Test eksikliği |
|
Bağımlılık sorunları
Bulanıklaştırma, FreeType'in bağımlı olduğu kitaplıklarda (ör. bzip2, libpng ve zlib) tekrar tekrar sorun tespit etti. Örneğin, freetype_bdf_fuzzer: inflate içinde ilklendirilmemiş değer kullanımı ile ilgili sorunları karşılaştırın.
Bulanıklaştırma yeterli değil
Rastgele oluşturulan geçersiz girişler de dahil olmak üzere çok çeşitli girişlerle yapılan otomatik test olan bulanıklık testi, Chrome'un kararlı sürümüne giren birçok sorun türünü bulmak için tasarlanmıştır. FreeType'i Google'ın oss-fuzz projesi kapsamında fuzz testine tabi tutarız. Sorunları tespit eder ancak aşağıdaki nedenlerden dolayı yazı tiplerinin fuzzing'e karşı bir miktar dirençli olduğu kanıtlanmıştır.
Yazı tipi dosyaları, birden fazla farklı bilgi türü içerdiğinden video dosyalarına benzer şekilde karmaşıktır. Yazı tipi dosyaları, birden fazla tablo için bir kapsayıcı biçimidir. Her tablo, ekranda doğru şekilde yerleştirilmiş bir simge oluşturmak için metin ve yazı tiplerini birlikte işlemede farklı bir amaca hizmet eder. Yazı tipi dosyasında şunları bulabilirsiniz:
- Değişken yazı tipleri için yazı tipi adları ve parametreler gibi statik meta veriler.
- Unicode karakterlerinden gliflere eşlemeler.
- Simgelerin ekran düzeni için karmaşık bir kural kümesi ve dil bilgisi.
- Görsel bilgiler: Ekrana yerleştirilen simgelerin nasıl göründüğünü açıklayan simge şekilleri ve resim bilgileri.
- Görsel tablolar da TrueType ipucu programları içerebilir. Bu programlar, karakter şeklini değiştirmek için çalıştırılan mini programlardır.
- CFF veya CFF2 tablolarındaki karakter dizeleri. Bunlar, CFF oluşturma motorunda yürütülen zorunlu eğri çizme ve ipucu verme talimatlarıdır.
Yazı tipi dosyalarında, kendi programlama dili ve durum makinesi işleme özelliğine sahip olma eşdeğeri bir karmaşıklık vardır. Bu nedenle, yazı tiplerinin yürütülmesi için belirli sanal makineler gerekir.
Bu biçimin karmaşıklığı nedeniyle, bulanıklık testi, yazı tipi dosyalarındaki sorunları bulma konusunda eksikliklere sahiptir.
İyi bir kod kapsamı veya fuzzer ilerleme kaydının elde edilmesi aşağıdaki nedenlerden dolayı zordur:
- Basit bit çevirme/kaydırma/ekleme/silme tarzı değiştiricileri kullanarak TrueType ipucu programları, CFF karakter dizeleri ve OpenType düzenini bulanıklaştırmak, tüm durum kombinasyonlarına ulaşma konusunda zorlanır.
- Bulanıklaştırma işleminin en azından kısmen geçerli yapılar oluşturması gerekir. Rastgele mutasyon nadiren bu şekilde çalışır. Bu nedenle, özellikle daha derin kod seviyelerinde iyi bir kapsam elde etmek zordur.
- ClusterFuzz ve oss-fuzz'daki mevcut fuzzing çalışmaları henüz yapıya duyarlı mutasyon kullanmıyor. Dil bilgisine veya yapıya duyarlı değiştiricilerin kullanılması, erken reddedilen varyantların üretilmesini önlemeye yardımcı olabilir. Bununla birlikte, geliştirmenin daha uzun sürmesi ve arama alanının bazı kısımlarını atlama olasılığı da ortaya çıkar.
Bulanıklaştırma işleminin ilerleyebilmesi için birden fazla tablodaki verilerin senkronize olması gerekir:
- Fuzzer'ların normal mutasyon kalıpları kısmen geçerli veriler üretmediğinden birçok iterasyon reddedilir ve ilerleme yavaşlar.
- Karakter eşleme, OpenType düzen tabloları ve karakter çizimi birbirine bağlıdır ve birbirine bağlıdır. Bu da köşelerine fuzzing ile ulaşılması zor olan bir kombinasyon alanı oluşturur.
- Örneğin, yüksek önem derecesine sahip tt_face_get_paintCOLRv1 güvenlik açığının bulunması 10 aydan uzun sürdü.
Elimizden geleni yapmamıza rağmen, yazı tipi güvenlik sorunları son kullanıcılara defalarca ulaştı. FreeType'i Rust alternatifiyle değiştirmek, birden fazla güvenlik açığı sınıfını tamamen önler.
Chrome'da Skrifa
Skia, Chrome tarafından kullanılan grafik kitaplığıdır. Skia, yazı tiplerinden meta verileri ve harf biçimlerini yüklemek için FreeType'ten yararlanır. Skrifa, Fontations kitaplık ailesinin bir parçası olan ve Skia tarafından kullanılan FreeType bölümlerinin güvenli bir alternatifini sunan bir Rust kitaplığıdır.
FreeType'ten Skia'ya geçiş yapmak için Chrome ekibi, Skrifa'ya dayalı yeni bir Skia yazı tipi arka ucu geliştirdi ve değişikliği kullanıcılara kademeli olarak kullanıma sundu:
- Chrome 128'de (Ağustos 2024) güvenli bir deneme çalışması olarak, renkli yazı tipleri ve CFF2 gibi daha az kullanılan yazı tipi biçimlerinde kullanılmak üzere yazı tipi biçimlendirmelerini etkinleştirdik.
- Chrome 133'te (Şubat 2025) Linux, Android ve ChromeOS'te tüm web yazı tipi kullanımları için ve Windows ile Mac'te yedek olarak web yazı tipi kullanımları için yazı tipi dönüşümlerini etkinleştirdik. Bu, sistemin bir yazı tipi biçimini desteklemediği ancak Chrome'un bu biçimi göstermesi gerektiği durumlarda geçerlidir.
Chrome'a entegrasyon için Rust'ın Chrome güvenlik ekibi tarafından kullanıma sunulan kod tabanına sorunsuz bir şekilde entegre edilmesini sağlıyoruz.
Gelecekte, Linux ve ChromeOS'ten başlayarak Android'de de işletim sistemi yazı tipleri için Fontations'a geçeceğiz.
Öncelikle güvenlik
Birincil hedefimiz, belleğe izin verilen alanın dışından erişimden kaynaklanan güvenlik açıklarını azaltmak (veya ideal olarak ortadan kaldırmak)tır. Rust, güvenli olmayan kod bloklarından kaçındığınız sürece bu özelliği hazır olarak sunar.
Performans hedeflerimiz, şu anda güvenli olmayan bir işlem gerçekleştirmemizi gerektiriyor: İsteğe bağlı baytların güçlü şekilde yazılmış bir veri yapısı olarak yeniden yorumlanması. Bu sayede, gereksiz kopyalar oluşturmadan bir yazı tipi dosyasından verileri okuyabiliriz. Bu, hızlı bir yazı tipi ayrıştırıcı oluşturmak için gereklidir.
Kendi güvenli olmayan kodumuzu kullanmaktan kaçınmak için bu sorumluluğu, özel olarak bu amaç için tasarlanmış ve ekosistem genelinde yaygın olarak test edilip kullanılan bir Rust kitaplığı olan bytemuck'a devretmeyi tercih ettik. Ham verilerin yeniden yorumlanmasını bytemuck'ta yoğunlaştırmak, bu işlevi tek bir yerde ve denetlenmiş olarak kullanmamızı ve bu amaç için güvenli olmayan kodu tekrarlamaktan kaçınmamızı sağlar. Safe transmute projesi, bu işlevi doğrudan Rust derleyicisine dahil etmeyi amaçlamaktadır. Bu özellik kullanıma sunulduğunda geçişi yapacağız.
Doğruluk önemlidir
Skrifa, çoğu veri yapısının değiştirilemez şekilde tasarlandığı bağımsız bileşenlerden oluşur. Bu, okunabilirliği, sürdürülebilirliği ve çoklu iş parçacılığını iyileştirir. Ayrıca kodu birim testine daha uygun hale getirir. Bu fırsattan yararlanarak, düşük düzey ayrıştırma rutinlerinden üst düzey ipucu veren sanal makinelere kadar tüm yığınımızı kapsayan yaklaşık 700 birim test paketi oluşturduk.
Doğruluk, doğruluğu da ifade eder ve FreeType, yüksek kaliteli ana hatlar oluşturması nedeniyle çok takdir edilir. Uygun bir değişim olması için bu kaliteyi eşleştirmemiz gerekir. Bu amaçla, çok çeşitli yapılandırmalarda yazı tipi dosyası grupları için Skrifa ve FreeType'in çıktılarını karşılaştıran fauntlet adlı özel bir araç geliştirdik. Bu sayede, kalitede gerileme yaşamaktan kaçınabileceğimizi biliyoruz.
Ayrıca, Chromium'a entegrasyondan önce Skia'da geniş bir piksel karşılaştırması yaptık. Bu karşılaştırmada, FreeType oluşturma işlemini Skrifa ve Skia oluşturma işlemiyle karşılaştırarak gerekli tüm oluşturma modlarında (farklı kenar yumuşatma ve ipucu modlarında) piksel farklılıklarının kesinlikle minimum düzeyde olmasını sağladık.
Bulanık test, bir yazılım parçasının hatalı biçimlendirilmiş ve kötü amaçlı girişlere nasıl tepki vereceğini belirlemek için önemli bir araçtır. Haziran 2024'ten bu yana yeni kodumuzu sürekli olarak fuzzing testine tabi tutuyoruz. Bu, Rust kitaplıklarının kendisini ve entegrasyon kodunu kapsar. Bu yazının yazıldığı tarih itibarıyla fuzzer 39 hata tespit etmesine rağmen bunlardan hiçbirinin güvenlik açısından kritik olmadığını belirtmek isteriz. İstenmeyen görsel sonuçlara veya hatta kontrollü kilitlenmelere neden olabilir ancak istismar edilebilir güvenlik açıklarına yol açmaz.
Devam edelim.
Metin için Rust kullanmaya yönelik çabalarımızın sonuçlarından çok memnunuz. Kullanıcılara daha güvenli kod sunmak ve geliştirici üretkenliğini artırmak bizim için büyük bir kazançtır. Rust'ı metin yığınlarımızda kullanma fırsatlarını aramaya devam etmeyi planlıyoruz. Daha fazla bilgi edinmek isterseniz Oxidize'de Google Fonts'un gelecek planlarından bazılarına göz atabilirsiniz.