UNIXの使い方
(ラズパイZeroで学ぶLinux)
 

-- C言語のメモリ配置 --

プログラムはパソコンのメインメモリであるRAM(Random Access Memory)上に配置される。
C言語の関数中で宣言した自動変数(ローカル変数)は、スタックメモリと呼ばれる領域に配置され
外部メモリ等のあらかじめ宣言されている変数は、データ領域と呼ばれる部分に配置されます。
また動的にメモリを使いたい場合は、ヒープ領域とよばれるOSが管理する未使メモリ領域からmalloc()関数を使って取得します。
このようにプログラム自信をおくコード領域、スタック領域、データ領域、ヒープ領域の4つのメモリ領域を使ってプログラムが実行されます。
なかでもスタックメモリは注意が必要です。
なぜかというと、自動変数(関数のローカル変数)はこの領域に確保されるのですがこの領域には関数が呼出元に戻る為のアドレスも確保されているため標準入力やファイルを読取るメモリとしてこの部分を安易に使うと悪用され外部からのコードを実行される可能性が出るためです。
このような手法をバッファオーバーフローやバッファオーバーランと言いますが、これを防ぐ為には宣言した自動変数の領域を外部操作で超えないように制御する必要があります。

※以下のソースはx86用のコードです
以下のソースは正常にmain関数からsub2関数を呼び出すプログラムですが、

#include <stdio.h>

int sub1() {
    printf("sub1\n");
}

int sub2() {
    printf("sub2\n");
}

int main() {
    sub2();

    return 0;
}

以下プログラムを実行してみるとsub2の後sub1が実行されていることが分かります。

#include <stdio.h>

int sub1() {
    printf("sub1\n");
}

int sub2() {
    // 関数へのポインターバッファを宣言
    int (*buf[2])();

    printf("sub2\n");
    // わざとこの関数の戻りアドレスをsub1に書き変える
    buf[3]=sub1;
}

int main() {
    sub2();

    return 0;
}

このように自動変数を使う場合は絶対に外部操作で確保したメモリ以上の部分にアクセスできないようにする必要があります。
C言語を使う場合最も注意すべきところです。

To Top