Стековий кадр

Матеріал з Вікіпедії — вільної енциклопедії.
Перейти до навігації Перейти до пошуку

Стековий кадр (від англ. stack frame) — механізм передавання аргументів і виділення тимчасової пам'яті (в процедурах мов програмування високого рівня) з використанням системного стека.

Технологія[ред. | ред. код]

Типовий випадок використання стека в програмі мовою високого рівня на прикладі виклику процедури з аргументами «A, B, C» (з угодами виклику cdecl) у порівнянні з мовою асемблера

Зазвичай системний стек використовується для зберігання адрес повернення при виклику підпрограм, а також збереження/відновлення значень регістрів процесора.

Передача аргументів[ред. | ред. код]

При виклику процедури аргументи надсилаються в стек, і тільки потім керування передається у процедуру. Таким чином, процедура отримує стек, на вершині якого лежить адреса повернення, а під нею — аргументи, з якими її викликано.

При поверненні з процедури (або після нього, див. нижче) аргументи повинні бути зняті зі стека.

Виділення тимчасової пам'яті[ред. | ред. код]

Якщо вказівник стека змістити «вище» (у бік збільшення стека), то частина пам'яті в стеку виявиться невикористаною (зокрема й при виклику третьої процедури) і може використовуватися на потреби процедури, аж до моменту повернення на місце виклику. Таким чином, мови високого рівня організовують змінні, що існують тільки всередині процедури (у мові Сі їх називають «автоматичними»).

Перед поверненням процедура має повернути вказівник стека в початкове положення (тобто на адресу повернення).

Домовленості для різних мов програмування[ред. | ред. код]

Різні компілятори мов високого рівня по-різному підходять до організації стекового кадру в залежності від особливостей апаратної платформи і стандартів конкретної мови. Основні відмінності стосуються порядку передавання аргументів у стек і їх зняття зі стека при поверненні.

Недоліки стекового кадру[ред. | ред. код]

Стековий кадр — зручна технологія виділення тимчасової пам'яті для передавання довільного числа аргументів або внутрішнього використання. Однак вона має низку недоліків.

Продуктивність[ред. | ред. код]

Передавання даних через пам'ять без необхідності уповільнює виконання програми (порівняно з програмами мовою асемблера, в яких більшість аргументів і тимчасових даних розміщують у регістрах процесора).

Для зменшення звернень до локальних змінних програма оптимізується при компіляції для використання регістрів замість змінних у пам'яті або для зберігання їхніх проміжних значень.

Деякі мови використовують домовленості щодо виклику, що підтримують передавання цілочисельних аргументів через регістри.

Безпека[ред. | ред. код]

Стековий кадр перемежовує дані програми з критичними даними — вказівниками, значеннями регістрів і адресами повернення. Це, в поєднанні з архітектурними особливостями деяких процесорів (а саме — напрямком зростання стека), робить дуже легко досяжним зловмисне перекриття критичних даних внаслідок переповнення буфера (зрозуміло, перш за все, програма має містити помилку, яка дозволить виконати переповнення).

Такий «невдалий», з точки зору переповнення буфера, напрямок зростання машинного стека мають апаратні платформи x86.

Атака з переповнення буфера в стеку зазвичай реалізується так:

  • Програма, що атакує, надсилає на мережеве з'єднання (або інший засіб міжпроцесної взаємодії) блок даних, свідомо більший від розміру буфера цільової програми.
  • Неправильно написана (вразлива) процедура дозволяє записати зайві дані за межі буфера (тобто, допускає його переповнення), через початок стекового кадру і адресу повернення. Блок даних скомпонований так, щоб адреса повернення в стеку заміщалася адресою коду експлойта, який міститься в тому ж завантаженому блоці даних (виконання цього коду з привілеями виконуваної програми і є метою атаки).
  • При поверненні з уразливої процедури, керування через змінену адресу повернення передається на код експлойта.

Див. також[ред. | ред. код]