خانه » بررسی Sanitizerهای LLVM – بخش سوم

بررسی Sanitizerهای LLVM – بخش سوم

LLVM Sanitizer

توسط Vulnerlab
109 بازدید
Sanitizer - سنی تایزر

17. آشنایی با SanitizerStats

Sanitizerها از يك مكانيزم ساده براي جمع‌آوري آمار پروفايلينگ (profiling statistics) پشتيباني مي‌كنند تا درک هزينه‌ها و overhead مرتبط با استفاده از sanitizerها را تسهيل كنند.

   17.1 نحوه ساخت و اجرا

در حال حاضر SanitizerStats تنها با Control Flow Integrity (CFI)[1] قابل استفاده است. علاوه بر -fsanitize=cfi*، بايد -fsanitize-stats نيز اضافه شود. اين كار باعث مي‌شود برنامه تعداد دفعات فعال شدن هر check مربوط به CFI را بشمارد.

در زمان اجرا، متغير محيطي  SANITIZER_STATS_PATH را تنظيم كنيد تا خروجي آمار به يك فايل دلخواه نوشته شود. فايل هنگام خروج فرآيند (process exit) نوشته خواهد شد.
جايگزيني‌هاي زير بر روي مقدار اين متغير اعمال مي‌شوند:

  • %b – basename فايل اجرایی
  • %p – شناسه فرآيند (PID)

همچنين مي‌توان سيگنال SIGUSR2 را به فرآيند ارسال كرد تا آمار sanitizer فوري نوشته شود.

ابزار sanstats براي dump كردن آمار استفاده مي‌شود. اين ابزار يك آرگومان خط فرمان مي‌گيرد كه مسير فايل آمار توليد شده توسط برنامه‌اي است كه با -fsanitize-stats  كامپايل شده است.

خروجي ابزار sanstats شامل چهار ستون است كه با فاصله از هم جدا شده‌اند:

  1. ستون اول: فايل و شماره خط محل فراخواني (call site)
  2. ستون دوم: نام تابع
  3. ستون سوم: نوع آمار جمع‌آوري شده (در اين مورد، نوع کنترل صحت جریان کنترل – CFI check)
  4. ستون چهارم: تعداد فراخواني‌ها

برای مثال:

				
					cat -n vcall.cc
     1 struct A {
     2   virtual void f() {}
     3 };
     4
     5 __attribute__((noinline)) void g(A *a) {
     6   a->f();
     7 }
     8
     9 int main() {
    10   A a;
    11   g(&a);
    12 }
clang++ -fsanitize=cfi -fvisibility=hidden -flto -fuse-ld=gold vcall.cc -fsanitize-stats -g
SANITIZER_STATS_PATH=a.stats ./a.out
sanstats a.stats
vcall.cc:6 _Z1gP1A cfi-vcall 1

				
			

18. آشنایی با Sanitizer special case list

اين مستند روش غيرفعال كردن يا تغيير رفتار ابزارهاي sanitizer براي برخي موجوديت‌هاي سطح سورس (source-level entities) را از طريق ارائه يك فايل خاص در زمان كامپايل توضيح مي‌دهد.

   18.1 هدف و نحوه استفاده

كاربران ابزارهاي sanitizer، مانند AddressSanitizer، Hardware-assisted AddressSanitizer، ThreadSanitizer، MemorySanitizer يا UndefinedBehaviorSanitizer  ممكن است بخواهند برخي چك‌ها را براي موجوديت‌هاي مشخص سطح سورس غيرفعال يا تغيير دهند تا:

  • افزايش سرعت توابع پرتكرار (hot function) كه صحت آن‌ها تاييد شده است؛
  • ناديده گرفتن توابعي كه كارهاي سطح پايين انجام مي‌دهند (مثلاً دستكاري استاك thread و عبور از مرزهاي frame)؛
  • ناديده گرفتن مشكلات شناخته‌شده.

براي اين كار، كاربر مي‌تواند فايلی شامل موجوديت‌هايي كه مي‌خواهد ناديده گرفته شوند ايجاد كند و آن را در زمان كامپايل با استفاده از -fsanitize-ignorelist به clang ارائه دهد.
براي جزئيات بيشتر به Clang Compiler User’s Manual  [2]مراجعه كنيد.

   18.2 مثال:

				
					$ cat foo.c
#include <stdlib.h>
void bad_foo() {
  int *a = (int*)malloc(40);
  a[10] = 1;
  free(a);
}
int main() { bad_foo(); }
$ cat ignorelist.txt
# Ignore reports from bad_foo function.
fun:bad_foo
$ clang -fsanitize=address foo.c ; ./a.out
# AddressSanitizer prints an error report.
$ clang -fsanitize=address -fsanitize-ignorelist=ignorelist.txt foo.c ; ./a.out
# No error report here.

				
			

   18.3 نحوه استفاده با UndefinedBehaviorSanitizer

Sanitizerهاي unsigned-integer-overflow، signed-integer-overflow، implicit-signed-integer-truncation، implicit-unsigned-integer-truncation و enum از امكان تنظيم instrumentation بر اساس نوع (type) پشتيباني مي‌كنند. به طور پيش‌فرض، اين sanitizerهاي پشتيباني‌شده، instrumentation خود را براي ورودي‌هايي كه در ignorelist مشخص شده‌اند غيرفعال مي‌كنند.

				
					$ cat foo.c
void foo() {
  int a = 2147483647; // INT_MAX
  ++a;                // Normally, an overflow with -fsanitize=signed-integer-overflow
}
$ cat ignorelist.txt
[signed-integer-overflow]
type:int
$ clang -fsanitize=signed-integer-overflow -fsanitize-ignorelist=ignorelist.txt foo.c ; ./a.out
# no signed-integer-overflow error

				
			

به عنوان مثال، ارائه فايل ignorelist.txt فوق با -fsanitize-ignorelist=ignorelist.txt باعث مي‌شود instrumentation overflow sanitizer براي عمليات رياضي شامل مقادير از نوع int غيرفعال شود. همچنين دسته‌بندي =sanitize پشتيباني مي‌شود. ورودي‌هاي =sanitize باعث فعال شدن instrumentation sanitizer مي‌شوند، حتي اگر قبلاً توسط ورودي‌هاي ديگر غيرفعال شده باشد. ورودي‌ها مي‌توانند از نوع src، type، global، fun و mainfile باشند.

با اين روش، مي‌توان instrumentation را براي برخي يا تمام نوع‌ها غيرفعال كرد و به طور مشخص instrumentation را براي يك يا چند نوع فعال نمود – از جمله نوع‌هايي كه با typedef تعريف شده‌اند. اين يك روش براي ايجاد نوعي “allowlist” براي sanitizerهاي پشتيباني‌شده است.

				
					$ cat ignorelist.txt
[implicit-signed-integer-truncation]
type:*
type:T=sanitize

$ cat foo.c
typedef char T;
typedef char U;
void foo(int toobig) {
  T a = toobig;    // instrumented
  U b = toobig;    // not instrumented
  char c = toobig; // also not instrumented
}

				
			

ChatGPT said:

اگر چندين ورودي با همان منبع (source) مطابقت داشته باشند، آخرين ورودي اولويت خواهد داشت. در ادامه چند مثال ارائه شده است:

				
					$ cat ignorelist1.txt
# test.cc will not be instrumented.
src:*
src:*/mylib/*=sanitize
src:*/mylib/test.cc

$ cat ignorelist2.txt
# test.cc will be instrumented.
src:*
src:*/mylib/test.cc
src:*/mylib/*=sanitize

$ cat ignorelist3.txt
# Type T will not be instrumented.
type:*
type:T=sanitize
type:T

$ cat ignorelist4.txt
# Function `bad_bar` will be instrumented.
# Function `good_bar` will not be instrumented.
fun:*
fun:*bar
fun:bad_bar=sanitize

				
			

   18.4 قالب (Format)

Ignorelist شامل ورودي‌هايي است كه به صورت اختياري در بخش‌ها (sections) گروهبندي شده‌اند. خطوط خالي و خطوطي كه با “#” شروع مي‌شوند ناديده گرفته مي‌شوند.

توجه:

  • قبل از Clang 18، نام بخش‌ها و ورودي‌ها از يك نوع regex متغير استفاده مي‌كردند كه در آن “ به `.` تبديل مي‌شد.
  • در Clang 18 (D154014) به glob منتقل شد و برنامه‌ريزي شده كه پشتيباني از regex در Clang 19 حذف شود.
  • براي Clang 18، regex پشتيباني مي‌شود اگر خط اول فايل شامل `!specialcaselistv1` باشد.
  • بسياري از ليست‌هاي خاص از `.` براي نمايش كاراكتر حقيقي (literal) استفاده مي‌كنند و از متاكاراكترهاي regex مانند `(` يا `)` استفاده نمي‌كنند، بنابراين تحت تاثير انتقال از regex به glob قرار نمي‌گيرند.
  • براي جزئيات بيشتر، به اين [پست در discourse][3] مراجعه كنيد.
  • نام بخش‌ها به صورت glob و داخل براكت‌ها [ ] نوشته مي‌شوند و مشخص مي‌كنند ورودي‌هاي بعدي به كدام sanitizer اعمال مي‌شوند.
  •    مثال: `[address]` برای AddressSanitizer
  •    مثال: `[{cfivcall,cfiicall}]` برای Control Flow Integrity بررسی virtual و indirect call
  •  ورودي‌هايي كه بدون بخش باشند، تحت بخش `[  ]` قرار مي‌گيرند و براي تمام sanitizerهاي فعال اعمال مي‌شوند.
  • هر ورودي شامل نوع موجوديت (entity type)، يك دو نقطه `:` و يك glob براي مشخص كردن نام موجوديت‌ها است.  به طور اختياري، مي‌توان با = يك دسته‌بندي toolspecific اضافه كرد، مثال:
				
					 fun:*ExampleFunc=example_category.
				
			

 دو نوع موجوديت عمومي (generic):

  • `src` – براي مشخص كردن فايل‌هاي سورس
  • `fun` – براي مشخص كردن توابع

 برخي ابزارهاي sanitizer ممكن است نوع‌ها و دسته‌بندي‌هاي اختصاصي داشته باشند – به مستندات toolspecific مراجعه كنيد.

				
					# Lines starting with # are ignored.
# Turn off checks for the source file
# Entries without sections are placed into [*] and apply to all sanitizers
src:path/to/source/file.c
src:*/source/file.c
# Turn off checks for this main file, including files included by it.
# Useful when the main file instead of an included file should be ignored.
mainfile:file.c
# Turn off checks for a particular functions (use mangled names):
fun:_Z8MyFooBarv
# Glob brace expansions and character ranges are supported
fun:bad_{foo,bar}
src:bad_source[1-9].c
# "*" matches zero or more characters
src:bad/sources/*
fun:*BadFunction*
# Specific sanitizer tools may introduce categories.
src:/special/path/*=special_sources
# Sections can be used to limit ignorelist entries to specific sanitizers
[address]
fun:*BadASanFunc*
# Section names are globs
[{cfi-vcall,cfi-icall}]
fun:*BadCfiCall

				
			

mainfile مشابه استفاده از -fno-sanitize= برای مجموعه‌ای از فایل‌ها است، اما نيازي به پيكربندي پيچيده در سيستم ساخت ندارد. اين روش براي توابع با linkage داخلي (internal linkage) بسيار مناسب است، اما براي توابع ++C با linkage مبهم (vague linkage) يك نكته مهم دارد.

توابع ++C با linkage مبهم، مانند توابع inline و template instantiations، در زمان لينك‌گيري تكراري‌هاي خود را يكسان مي‌سازند (deduplicate). يك تابع كه توسط  pattern mainfile خاصي ناديده گرفته شده است ممكن است نسخه غالب (prevailing copy) انتخاب شده توسط لينكر نباشد. بنابراين، استفاده از mainfile نيازمند احتياط است. با اين حال، هنوز مي‌تواند مفيد باشد، به عنوان مثال وقتي patternها طوري انتخاب مي‌شوند كه نسخه غالب ناديده گرفته شود (با ريسك action-at-a-distance ).

 mainfile مي‌تواند براي فعال‌سازي يك چك UBSan در يك كدبیس بزرگ مفيد باشد، مخصوصاً زماني كه پيدا كردن فريم استاك مستقيم كه باعث خطا شده براي هر خطا دشوار است.

19. آشنایی با Hardware-assisted AddressSanitizer (معروف به HWASAN)

HWASAN ابزاری مشابه AddressSanitizer اما با کمک سخت‌افزاری جزئی است. AddressSanitizer هر 8 بایت از حافظه برنامه را با 1 بایت تگ علامت‌گذاری می‌کند (با استفاده از shadow memory)، از redzones برای یافتن buffer-overflow و از quarantine برای use-after-free استفاده می‌کند. این redzones، quarantine و تا حدی shadow، منبع مصرف حافظه بالای AddressSanitizer[4] هستند. جزئیات بیشتر در مقاله AddressSanitizer موجود است.

HWASAN از [5]Address Tagging در AArch64 (یا top-byte-ignore, TBI) بهره می‌برد، یک قابلیت سخت‌افزاری که اجازه می‌دهد نرم‌افزار از 8 بیت بالاترین آدرس یک pointer 64 بیتی به عنوان تگ استفاده کند. HWASAN از این ویژگی برای پیاده‌سازی ابزاری مشابه AddressSanitizer استفاده می‌کند، اما با مصرف حافظه کمتر و دقت کمی متفاوت (اغلب بهتر).

در x86_64، Intel Linear Address Masking (LAM) [6]نیز تگ‌گذاری آدرس را فراهم می‌کند، ولی هنوز سخت‌افزار آن به طور گسترده موجود نیست. برای x86_64، HWASAN از page aliasing برای پیاده‌سازی محدود استفاده می‌کند.

   19.1 الگوریتم

  • همه‌ی اشیاء حافظه (heap، stack، global) با TG بایت تراز می‌شوند (TG، مثلاً 16 یا 64، به آن tagging granularity می‌گویند).
  • برای هر شیء، یک تگ تصادفی T به اندازه TS بیت انتخاب می‌شود (TS، یا tag size، مثلاً 4 یا 8).
  • pointer شیء با T تگ می‌شود.
  • حافظه شیء نیز با T تگ می‌شود (با استفاده از shadow memory با نسبت TG=>1).
  • هر load و store برای خواندن تگ حافظه و مقایسه آن با تگ pointer instrumented می‌شود؛ در صورت ناسازگاری تگ، خطا رخ می‌دهد.

برای جزئیات بیشتر: مقاله  HWASAN[7] را مطالعه کنید.

   19.2 Short Granules

Short granule: اندازه‌ای بین 1 تا TG-1 بایت. اندازه short granule در همان مکان shadow memory ذخیره می‌شود که معمولاً تگ granule قرار دارد، در حالی که تگ واقعی granule در آخرین بایت آن ذخیره می‌شود. برای بررسی تطابق pointer tag با memory tag، HWASAN دو حالت را بررسی می‌کند:

  • pointer tag برابر memory tag در shadow memory است، یا
  • shadow memory شامل اندازه short granule است، مقدار بارگذاری شده در محدوده granule قرار دارد و pointer tag برابر آخرین بایت granule است.

تگ‌های pointer بین 1 تا TG-1 محتمل و برابر با سایر تگ‌ها هستند. بنابراین این تگ‌ها در حافظه دو تعبیر دارند:

  • Full tag interpretation: pointer tag بین 1 تا TG-1 و آخرین بایت granule داده معمولی است.
  • Short tag interpretation: pointer tag در granule ذخیره شده است.

هنگام تشخیص خطا نزدیک memory tag بین 1 تا TG-1، HWASAN هم memory tag و هم آخرین بایت granule را نشان می‌دهد. تصمیم نهایی بر عهده کاربر است.

   19.3 ابزار دهی ( Instrumentation)

      19.3.1 دسترسی حافظه

اکثر دسترسی‌های حافظه با فراخوانی یک توالی دستورات جدا شده (outlined instruction sequence) که تگ‌ها را بررسی می‌کند، پیش‌فرض می‌شوند. اندازه کد و overhead عملکرد کاهش می‌یابد با:

  • استفاده از calling convention سفارشی که اکثر رجیسترها را حفظ می‌کند.
  • تخصصی کردن برای رجیستری که آدرس در آن است و نوع و اندازه دسترسی حافظه.

توالی فعلی چنین کاری را انجام می‌دهد:

				
					// int foo(int *a) { return *a; }
// clang -O2 --target=aarch64-linux-android30 -fsanitize=hwaddress -S -o - load.c
[...]
foo:
      stp     x30, x20, [sp, #-16]!
      adrp    x20, :got:__hwasan_shadow               // load shadow address from GOT into x20
      ldr     x20, [x20, :got_lo12:__hwasan_shadow]
      bl      __hwasan_check_x0_2_short_v2            // call outlined tag check
                                                      // (arguments: x0 = address, x20 = shadow base;
                                                      // "2" encodes the access type and size)
      ldr     w0, [x0]                                // inline load
      ldp     x30, x20, [sp], #16
      ret

[...]
__hwasan_check_x0_2_short_v2:
      sbfx    x16, x0, #4, #52                        // shadow offset
      ldrb    w16, [x20, x16]                         // load shadow tag
      cmp     x16, x0, lsr #56                        // extract address tag, compare with shadow tag
      b.ne    .Ltmp0                                  // jump to short tag handler on mismatch
.Ltmp1:
      ret
.Ltmp0:
      cmp     w16, #15                                // is this a short tag?
      b.hi    .Ltmp2                                  // if not, error
      and     x17, x0, #0xf                           // find the address's position in the short granule
      add     x17, x17, #3                            // adjust to the position of the last byte loaded
      cmp     w16, w17                                // check that position is in bounds
      b.ls    .Ltmp2                                  // if not, error
      orr     x16, x0, #0xf                           // compute address of last byte of granule
      ldrb    w16, [x16]                              // load tag from it
      cmp     x16, x0, lsr #56                        // compare with pointer tag
      b.eq    .Ltmp1                                  // if matches, continue
.Ltmp2:
      stp     x0, x1, [sp, #-256]!                    // save original x0, x1 on stack (they will be overwritten)
      stp     x29, x30, [sp, #232]                    // create frame record
      mov     x1, #2                                  // set x1 to a constant indicating the type of failure
      adrp    x16, :got:__hwasan_tag_mismatch_v2      // call runtime function to save remaining registers and report error
      ldr     x16, [x16, :got_lo12:__hwasan_tag_mismatch_v2] // (load address from GOT to avoid potential register clobbers in delay load handler)
      br      x16

				
			

در HWASAN، تگ‌گذاری حافظه به سه بخش اصلی تقسیم می‌شود: Heap، Stack و Globals.

      19.3.2 Heap

تگ‌گذاری حافظه heap و pointerها توسط malloc انجام می‌شود. این می‌تواند بر اساس هر mallocی باشد که تمام اشیاء را TG-aligned می‌کند. هنگام فراخوانی free، حافظه با یک تگ متفاوت علامت‌گذاری می‌شود.

      19.3.3 Stack

فریم‌های stack با تراز کردن همه allocaهای غیرقابل promotion بر اساس TG و تگ‌گذاری حافظه در prologue و epilogue تابع instrumented می‌شوند. تگ‌ها برای هر alloca به‌صورت مستقل تولید نمی‌شوند، چون نگهداری M pointer زنده برای M alloca باعث افزایش فشار روی رجیسترها می‌شود.

در عوض، یک تگ پایه BaseTag در prologue تولید می‌شود و تگ alloca شماره M با تابع ReTag(BaseTag, M) محاسبه می‌شود که ReTag می‌تواند ساده باشد، مانند XOR با عدد M. این instrumentation برای stack منبع عمده overhead محسوب می‌شود ولی می‌تواند اختیاری باشد.

      19.3.4 متغیرهای سراسری (Globals)

اکثر متغیرهای سراسری در کدهایی که با HWASAN ابزاردهی شده‌اند، برچسب‌گذاری می‌شوند. این کار از طریق مکانیزم‌های زیر انجام می‌شود:

  • آدرس هر متغیر سراسری دارای یک برچسب ثابت است. اولین متغیر سراسری تعریف‌شده در یک واحد ترجمه، یک برچسب شبه‌تصادفی (pseudorandom) بر اساس هش مسیر فایل دریافت می‌کند. برچسب‌های متغیرهای سراسری بعدی به‌صورت افزایشی نسبت به برچسب قبلی تخصیص داده می‌شوند.
  • برچسب متغیر سراسری به آدرس نماد آن در جدول نمادهای فایل شیء اضافه می‌شود. این کار باعث می‌شود که آدرس متغیر سراسری هنگام گرفتن آدرس آن، برچسب‌گذاری شود.
  • هنگام گرفتن مستقیم آدرس یک متغیر سراسری (یعنی بدون استفاده از GOT)، لازم است از یک دنباله دستور ویژه برای افزودن برچسب به آدرس استفاده شود، زیرا در غیر این صورت برچسب باعث می‌شود آدرس خارج از مدل کد کوچک (۴ گیگابایت در AArch64) قرار گیرد. هیچ تغییری لازم نیست زمانی که آدرس از طریق GOT گرفته شود، زیرا آدرس ذخیره‌شده در GOT شامل برچسب خواهد بود.
  • برای هر متغیر سراسری برچسب‌گذاری‌شده، یک بخش مرتبط به نام hwasan_globals ایجاد می‌شود، که آدرس متغیر، اندازه آن و برچسبش را مشخص می‌کند. این بخش‌ها توسط لینک‌کننده به یک بخش واحد hwasan_globals متصل می‌شوند که توسط زمان اجرا (از طریق یادداشت ELF) هنگام بارگذاری باینری شمارش شده و حافظه مطابق برچسب‌گذاری می‌شود.

یک مثال کامل در ادامه ارائه شده است:

				
					// int x = 1; int *f() { return &amp;x; }
// clang -O2 --target=aarch64-linux-android30 -fsanitize=hwaddress -S -o - global.c

[...]
f:
      adrp    x0, :pg_hi21_nc:x            // set bits 12-63 to upper bits of untagged address
      movk    x0, #:prel_g3:x+0x100000000  // set bits 48-63 to tag
      add     x0, x0, :lo12:x              // set bits 0-11 to lower bits of address
      ret

[...]
      .data
.Lx.hwasan:
      .word   1

      .globl  x
      .set x, .Lx.hwasan+0x2d00000000000000

[...]
      .section        .note.hwasan.globals,"aG",@note,hwasan.module_ctor,comdat
.Lhwasan.note:
      .word   8                            // namesz
      .word   8                            // descsz
      .word   3                            // NT_LLVM_HWASAN_GLOBALS
      .asciz  "LLVM\000\000\000"
      .word   __start_hwasan_globals-.Lhwasan.note
      .word   __stop_hwasan_globals-.Lhwasan.note

[...]
      .section        hwasan_globals,"ao",@progbits,.Lx.hwasan,unique,2
.Lx.hwasan.descriptor:
      .word   .Lx.hwasan-.Lx.hwasan.descriptor
      .word   0x2d000004                   // tag = 0x2d, size = 4

				
			

   19.4 گزارش خطا (Error Reporting)

خطاها توسط دستور HLT ایجاد می‌شوند و توسط یک هندلر سیگنال مدیریت می‌شوند.

   19.5 صفت (Attribute)

HWASAN از صفت LLVM IR مخصوص خود به نام `sanitize_hwaddress` و یک صفت تابع متناظر در C استفاده می‌کند. جایگزین دیگر می‌توانست استفاده از صفت ASAN به نام `sanitize_address` باشد. دلایل استفاده از صفت مجزا عبارتند از:

  • کاربران ممکن است بخواهند ASAN را غیرفعال کنند اما HWASAN فعال بماند، یا بالعکس، زیرا این ابزارها دارای توافق‌پذیری و محدودیت‌های متفاوتی هستند.
  • LLVM به‌طور ایده‌آل از فلگ‌ها برای تصمیم‌گیری در مورد اجرای passها (ASAN یا HWASAN) استفاده نمی‌کند و این تصمیم بر اساس صفات توابع گرفته می‌شود.

این بدان معناست که کاربران HWASAN ممکن است نیاز داشته باشند صفت جدید را به کدی که قبلاً از صفت قدیمی استفاده می‌کرده اضافه کنند.

   19.6 مقایسه با AddressSanitizer

HWASAN:

  • قابلیت حمل کمتری نسبت به ASAN دارد، زیرا به برچسب‌گذاری آدرس سخت‌افزاری (AArch64) وابسته است. برچسب‌گذاری آدرس می‌تواند با ابزاردهی کامپایلر شبیه‌سازی شود، اما نیاز است قبل از هر بار خواندن یا نوشتن، برچسب‌ها حذف شوند، که در محیط‌های واقعی حاوی کد غیرابزاردهی‌شده عملی نیست.
  • ممکن است مشکلات سازگاری داشته باشد اگر کد هدف از بیت‌های بالای اشاره‌گر برای مقاصد دیگر استفاده کند.
  • ممکن است تغییراتی در هسته سیستم‌عامل لازم باشد (به عنوان مثال، Linux به اشاره‌گرهای برچسب‌دار پاس داده‌شده از فضای آدرس حساس است: [لینک مستندات](https://www.kernel.org/doc/Documentation/arm64/taggedpointers.txt)).
  • برای تشخیص سرریز بافر، نیاز به redzone ندارد، اما تشخیص سرریز بافر به‌صورت احتمالی است، با احتمال تقریبی ۱/(2TS) برای از دست دادن باگ (۶.۲۵٪ یا ۰.۳۹٪ برای TS ۴ و ۸ بیت).
  • برای تشخیص استفاده از heap پس از آزادسازی یا استفاده از stack پس از بازگشت نیازی به quarantine ندارد. تشخیص نیز مشابهاً احتمالی است.
  • حجم حافظه مورد استفاده HWASAN بسیار کمتر از ASAN است: ۱/TG حافظه اضافی برای shadow و مقداری سربار به دلیل هم‌ترازی اشیاء با TG.

   19.7 ملاحظات امنیتی

HWASAN یک ابزار تشخیص باگ است و زمان اجرای آن برای لینک شدن با فایل‌های اجرایی تولیدی مناسب نیست. هرچند ممکن است برای تست مفید باشد، زمان اجرای HWASAN با محدودیت‌های امنیتی توسعه داده نشده است و می‌تواند امنیت فایل اجرایی نهایی را به خطر بیندازد.

   19.8 معماری‌های پشتیبانی‌ شده

 HWASAN به برچسب‌گذاری آدرس یا Address Tagging[8] وابسته است که تنها در AArch64 در دسترس است. برای سایر معماری‌های ۶۴ بیتی، امکان حذف برچسب‌ها قبل از هر load/store با ابزاردهی کامپایلر وجود دارد، اما قابلیت اجرا محدود خواهد بود، زیرا معمولاً همه کدها ابزاردهی نمی‌شوند.

 در x86_64، HWASAN از صفحه‌های معادل (page aliasing) برای قرار دادن برچسب‌ها در بیت‌های آدرس کاربران استفاده می‌کند. در حال حاضر فقط برچسب‌گذاری heap پشتیبانی می‌شود. صفحات معادل بر حافظه مشترک مبتنی هستند، که باعث اشتراک heap بین فرآیندها می‌شود اگر برنامه از `fork()` استفاده کند. بنابراین x86_64 فقط برای برنامه‌هایی که fork نمی‌کنند امن است.

 HWASAN در حال حاضر معماری‌های ۳۲ بیتی را پشتیبانی نمی‌کند، زیرا آن‌ها از برچسب‌گذاری آدرس پشتیبانی نمی‌کنند و فضای آدرس محدود است و پیاده‌سازی page aliasing به‌سختی ممکن است.

   19.9 کارهای مرتبط (Related Work)

[9] SPARC ADI و [10]Arm MTE ابزار مشابهی عمدتاً در سخت‌افزار پیاده‌سازی کرده‌اند.

 مقاله Effective and Efficient Memory Protection Using Dynamic Tainting[11] رویکردهای مشابه (قفل و کلید) را بررسی می‌کند.

مقاله Watchdog[12] رویکرد سنگین‌تر اما مشابه قفل و کلید را ارائه می‌دهد.

پاورقی:

				
					[1] https://clang.llvm.org/docs/ControlFlowIntegrity.html
[2] https://clang.llvm.org/docs/UsersManual.html
[3] https://reviews.llvm.org/D154014
[4] https://clang.llvm.org/docs/AddressSanitizer.html
[5] http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.den0024a/ch12s05s01.html
[6] https://software.intel.com/content/www/us/en/develop/download/intel-architecture-instruction-set-extensions-programming-reference.html
[7] https://arxiv.org/pdf/1802.09517.pdf
[8] http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.den0024a/ch12s05s01.html
[9] https://lazytyped.blogspot.com/2017/09/getting-started-with-adi.html
[10] https://developer.arm.com/documentation/108035/0100/Introduction-to-the-Memory-Tagging-Extension
[11] https://www.cc.gatech.edu/~orso/papers/clause.doudalis.orso.prvulovic.pdf
[12] https://www.cis.upenn.edu/acg/papers/isca12_watchdog.pdf
				
			

مراجع:

				
					https://docs.nersc.gov/tools/debug/sanitizers/#cpu-sanitizers
https://docs.nersc.gov/tools/debug/sanitizers/
https://iree.dev/developers/debugging/sanitizers/
https://github.com/google/sanitizers
https://iree.dev/developers/debugging/sanitizers/
https://docs.nersc.gov/tools/debug/sanitizers/#:~:text=LLVM%20Sanitizers%20are%20a%20group,with%20a%20specific%20debugging%20capability.
https://clang.llvm.org/docs/index.html
https://llvm.org/docs/LibFuzzer.html
https://llvm.org/docs/Reference.html
https://llvm.org/docs/FuzzingLLVM.html
https://appsec.guide/docs/fuzzing/c-cpp/libfuzzer/
https://aviii.hashnode.dev/the-art-of-fuzzing-a-step-by-step-guide-to-coverage-guided-fuzzing-with-libfuzzer
https://www.moritz.systems/blog/an-introduction-to-llvm-libfuzzer/
https://github.com/google/sanitizers/wiki/AddressSanitizerInHardware
https://source.android.com/docs/security/test/hwasan
				
			

همچنین ممکن است دوست داشته باشید

پیام بگذارید

wpChatIcon
wpChatIcon