Signal Handling and Reentrancy

C で書かれた昔のプログラムをデバッグ中に 「シグナルハンドラー内で syslog や printf はご法度」というようなコメントに出くわす。引き継ぎ時に知ったかぶりで説明できるように調査。


まずはキーワード「リエントラント(再入可能)」の定義から(wikipedia より)

In computing, a computer program or subroutine is called reentrant if it can be interrupted in the middle of its execution and then safely called again (“re-entered“) before its previous invocations complete executing. The interruption could be caused by an internal action such as a jump or call or by an external action such as a hardware interrupt or signal. Once the reentered invocation completes, the previous invocations will resume correct execution.

signal handling and non-reentrancy

そのものズバリの現象が “Common Weakness Enumeration (CWE)-479: Signal Handler Use of a Non-reentrant Function” で紹介されていた。

syslog のように実行時にメモリを確保する(scratch space = space on the hard disk drive that is dedicated for only temporary storage)関数がハンドラー経由で同時に呼ばれると、メモリのメタデータを破壊してしまい、 undefined で 場合によっては exploitable な状態になる。

glibc のマニュアルでは Signal Handling -> Defining Handlers -> Signal Handling and Nonreentrant Functions に記載がある。

OpenBSD ではこの問題を防ぐために syslog の reentrant バージョンの syslog_r というのが存在する。

recommended programming practices
IBM DeveloperWorks では問題の起きる2例(Signals and non-reentrant functions & Non-reentrant functions and static variables)とsuggested practice が紹介されている。

Use reentrant functions for safer signal handling — How and when to employ reentrancy to keep your code bug free @ IBM DeveloperWorks

なお、DeveloperWorks  の解説記事 “Signals and non-reentrant functions” の Listing 1 の次のプログラムを実行したところ


struct two_int { int a, b; } data;

void signal_handler(int signum){
  printf ("%d, %d\n", data.a, data.b);
  alarm (1);

int main (void){
  static struct two_int zeros = { 0, 0 }, ones = { 1, 1 };
  signal (SIGALRM, signal_handler);
  data = zeros;
  alarm (1);

  while (1)
    {data = zeros; data = ones;}

Kernel 2.6.9-5 & GLIBC 2.3.4 では data = zeros または data = ones の変数操作が複数ステップで行われているらしく、期待通りの問題が起きたが、Kernel 2.6.32-24 & GLIBC 2.11.1 では割り込み無しに1ステップで(=アトミックに)行われているらしく、問題が発生しなかった。(glibc のバージョンは $ ldd –version で調べられる)



ながらく積ん読状態だった 冨永 和人権藤 克彦 著の「例解UNIXプログラミング教室」(2007, ピアソンエデュケーション)の §9.11「競合状態:シグナル処理が難しい理由」(pp.300-312)に関連する記述がある。

著:冨永 和人、権藤 克彦

Tagged with: , , ,
Posted in linux

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

  • RT @__apf__: How to write a research paper: a guide for software engineers & practitioners.… /cc @inwyrd 6 months ago
  • RT @HayatoChiba: 昔、自然と対話しながら数学に打ち込んだら何かを悟れるのではと思いたち、専門書1つだけ持ってパワースポットで名高い奈良の山奥に1週間籠ったことがある。しかし泊まった民宿にドカベンが全巻揃っていたため、水島新司と対話しただけで1週間過ぎた。 それ… 6 months ago
  • RT @googlecloud: Ever wonder what underwater fiber optic internet cables look like? Look no further than this deep dive w/ @NatAndLo: https… 6 months ago
  • @ijin UTC+01:00 な時間帯で生活しています、、、 1 year ago
  • RT @mattcutts: Google's world-class Site Reliability Engineering team wrote a new book:… It's about managing produc… 1 year ago
%d bloggers like this: