C dili üçün Clang-a əsaslanan tampon hədlərinin yoxlama rejimi həyata keçirilib.

Apple şirkətinin mühəndisləri, C dili kodunun yığılması zamanı buferlərlə təhlükəsiz işləmə zəmanətləri təqdim edən «-fbounds-safety» rejiminin sınaq üçün hazır olduğunu açıqlayıb. Bu rejim, Apple tərəfindən Swift layihəsi üçün dəstəklənən LLVM forkunun tərkibinə daxildir. Gələcəkdə «-fbounds-safety» funksionallığının tədricən LLVM/Clang-in əsas kod bazasına inteqrasiya edilməsi planlaşdırılır.

Qeyd olunur ki, təklif olunan müdafiə mexanizmi Apple məhsullarında, məsələn, XNU nüvəsi, firmware, səs işləmək üçün kitabxanalar və şəkil deşifrə edicilərində artıq aktiv şəkildə tətbiq olunur. «-fbounds-safety» rejiminin aktivləşdirilməsi tətbiqlərin performansını orta hesabla 5% (şəraitdən asılı olaraq -1%-dən 29%-ə qədər) azaldır, kodun həcmini isə 9.1% artırır (şəraitdən asılı olaraq -1.4%-dən 38%-ə qədər) və yığmanı 11% yavaşladır.

«-fbounds-safety» rejiminin göstəriş üstündə olan yaddaş sahəsindən çıxmaların avtomatik aşkarlanması üçün kodda xüsusi annotasiyaların əlavə edilməsi və «ptrcheck.h» başlıq faylının daxil edilməsi tələb olunur. Təklif olunan müdafiə metodunun mahiyyəti, əllə təyin edilmiş annotasiyalar və ya kompilyator tərəfindən bilinən ölçülərə əsaslanan icazəli sərhədlərin yoxlanmasının avtomatik əlavə edilməsidir.

Geniş göstəricilərin (wide pointer) kodda istifadəsindən fərqli olaraq, buferin yuxarı və aşağı sərhədləri haqqında məlumat olmadan «-fbounds-safety» rejiminin istifadəsi ABI (Tətbiq İkili İnterfeysi) pozmur, ixrac olunan göstəricilərin formatını dəyişmir və layihənin hamısı üçün yenidən işləməyi tələb etmir. «-fbounds-safety» rejimində geniş göstəricilər yalnız ABI ilə üst-üstə düşməyən sahələrdə tətbiq olunur, ABI-yə təsir edən göstəricilər üçün isə sınama ilə bağlı annotasiyalarla birlikdə adi göstəricilər istifadə olunur.

Annotasiyalar, obyektlər massivini göstərən strukturların sahələrində və funksiya parametrindəki göstəricilərə əlavə edilməlidir, eyni zamanda göstəricilərlə qlobal dəyişənlərə də əlavə olunmalıdır. Lokal dəyişənlərdəki göstəricilər üçün annotasiyaların əlavə edilməsinə ehtiyac yoxdur, çünki onlar avtomatik olaraq artıq icazəli sərhəd məlumatı olan geniş göstəricilər kimi emal olunur. Kodda annotasiyaların əlavə olunmasını tələb edən konstruksiyalara dair göstərişlər, «-fbounds-safety» flag-ı ilə başlatıldıqda kompilyator tərəfindən verilir.

«-fbounds-safety» əsaslı qoruma modeli tədricən, fayl-fayl tətbiq oluna bilər, proyektin bütün inkişafını dayandırmadan. Layihəyə qoruma əlavə etmək, kodun müəyyən bir faylında annotasiyaların göstərilməsinə, kompilatorun xəbərdarlıqlarının aradan qaldırılmasına və proqramın sınaqdan keçirilməsinə mənsubdur; sonra bu mərhələlər növbəti fayl üçün təkrarlanır. Əlavə olunan annotasiyalarla kod adi C kodu ilə və «-fbounds-safety» dəstəkləməyən kompilatorlarla uyğun qalır (başqa kompilatorlarla yığıldıqda və ya «-fbounds-safety» flaqı olmadan yığılarkən əlavə sərhəd yoxlamaları əlavə edilmir).

Proqram icrası zamanı, uyğun sərhədlərin aşılması aşkar edilərsə, istisna yaradılır və proqramın icrası başa çatır. Yanlış annotasiyalar göstərildikdə də qəfil dayanma baş verə bilər, buna görə «-fbounds-safety» istifadə edildikdə əlavə proqram sınağı aparılmalıdır.

Aşağıdakı nümunədə «int *p» parametrinə «__counted_by(n)» annotasiyası əlavə olunub, bu isə icra zamanı sərhəd yoxlamasını artırır. Əgər bu annotasiya göstərilmədən «-fbounds-safety» rejimində kodu kompilasiyaya təqdim etsəniz, kompilator „p[i] = 0“ ifadəsini işləyərkən massiv sərhədləri haqqında məlumatın çatışmaması barədə xəbərdarlıq verəcək. #include void init_buf(int *__counted_by(n) p, int n) { for (int i = 0; i < n; ++i) p[i] = 0; // «-fbounds-safety» rejimində kompilator avtomatik olaraq «if (i = n) trap();» koduna bənzər bir yoxlama əlavə edəcək. }

İstiqamətləri olan yerli dəyişənlər üçün yoxlamalar avtomatik olaraq əlavə edilir, məsələn: void foo(int i){ char *buf = (char *)malloc(10); // buf üçün sərhəd məlumatları saxlanılır buf[i] = 0xff; // avtomatik olaraq «if (buf + i = buf + 10) trap();» yoxlaması əlavə ediləcək. }

Mümkünsə, kompilator optimizasiya aparır və əlavə kodun əlavə olunmasını istisna edir, əgər kodda lazım olan yoxlamalar artıq mevcutdursa. Məsələn: for (size_t i = 0; i < count; ++i) { buf[i] = i; // «if (i = count) trap()» yoxlaması əlavə edilməyəcək, çünki yuxarıda artıq «i < count» şərti var və i 0-dan kiçik ola bilməz. }

Əsas annotasiyalar:

  • «__counted_by(N)» — hədəf tipinin elementləri ilə buferin ölçüsünü müəyyən edir.
  • «__sized_by(N)» — buferin baytla ölçüsünü müəyyən edir.
  • » __ended_by(P)» — buferin üst sərhədini müəyyən edir.
  • «__null_terminated» — buferin sonu olaraq sıfır simvolunu nəzərə alır.
  • «__single» — istiqaməti bir obyektə bağlayır. Açıq şəkildə annotasiya gösterilmədikdə ABI-yə təsir edən istiqamətlər üçün standart olaraq tətbiq edilir.
  • «__bidi_indexable» — üst və aşağı sərhədlər haqqında məlumatla inkişaf etmiş istiqamətdir. ABI-yə təsir etməyən istiqamətlər üçün standart olaraq tətbiq edilir.
  • «__indexable» — genişləndirilmiş göstərici, yuxarı sərhəd haqqında məlumatla.
  • «__unsafe_indexable» — sərhəd yoxlaması olmadan göstərici (məsələn, xarici koddan göstəriciləri əldə etmək üçün qeyri-mühafizə olunan kodla uyğunluq üçün).

Mənbə: opennet.ru

DDoS qoruması olan saytlara etibarlı hosting satın alın, VPS VDS serverlər 🔥 DDoS qoruması olan saytlara etibarlı hosting satın alın, VPS VDS serverlər | ProHoster