ゆの in SystemTap - ゆの対応カーネルですよ!

Fedora 9のLinuxカーネルSystemTapでライブに改造して『ゆの』対応にしてみます。x / _ / x
#「ゆの in language」の趣旨とは申し訳ないくらいに違うかもだけど。。
元ネタ: ゆの in Ruby - 冬通りに消え行く制服ガールは、夢物語にリアルを求めない。 - subtech


試すにはちょっと事前準備が要ります。

1. SystemTapと必要なモノをインストール。

# yum install kernel-devel systemtap
# debuginfo-install kernel

(Fedora9の場合。8ならyum -enablerepo=debuginfo install kernel-debuginfo とかかな?)

2. 以下のスクリプトをファイル「yuno.stp」に保存。

function memset(buf:long, src:string, size:long) %{ /* DANGER !! */
  char *buf = (void*)(long)THIS->buf;
  char *src = (void*)(long)THIS->src;
  memcpy(buf, src, (int)THIS->size);
%}

probe kernel.function("sys_read").return {
  if (execname() == "cat") {
    if ($count >= 4096 && $return < 1024) {
      x = "ひだまり"
      for (c = 0; c < $return; c++) {
	t = substr(user_string($buf), c, 1)
	if (t == "x") {
	  if (k)
	    x .= "x365"
	  k = 1
	} else if (t == "_") {
	  x .= "スケッチ"
	} else if (t == "<") {
	  x .= substr(user_string($buf), c+1, $return - c);
	} else if (t != " " && t != "/") {
	  // printf("%s\n", x)
	  memset($buf, x, strlen(x))
	  $return = strlen(x)
	  next;
	}
      }
    }
  }
}

3. 以下の内容の「ゆの」ファイルを作ります。

% cat yuno
x / _ / x < 来週も見てくださいね!

4. 別窓で実行開始(要root権限)。これだけでは何も起こりませんが…

# stap -vg yuno.stp
...
Pass 5: starting run.

5. catでyunoを読んでみると…

% cat yuno
ひだまりスケッチx365 来週も見てくださいね!

ファイルの中身が「ひだまりスケッチ×365」に変わった!?

いえいえ、tacとかlessで見てみればゆののままであることが分かります。

% tac yuno
x / _ / x < 来週も見てくださいね!

また、stapコマンドをCtrl-Cで止めると元に戻ります。

なお、正しいゆの以外を読ませると何が起こるか分からない(最悪カーネルがお亡くなりになる)のでやめた方が良いと思います。

解説 → id:NeoCat:20080713:1215944363

ゆの in SystemTap - 解説?

id:NeoCat:20080713:1215944362 の簡単な解説です。

まずSystemTapとは、簡単なスクリプトLinuxカーネルの動きを解析するためのツールです。
詳しくはRedHatの解説in日本語とか本家サイトとか、man stapとかman stapexとかをどうぞ。


普通は情報をとるだけのread-onlyで、安全面がちゃんと考慮されているのですが、裏技で-gオプションをつけるとカーネルの動きを変更できてしまいます。
好きな場所にCのコードを埋め込んだり、システムコールの返り値を書き換えたり、何でもしたい放題!


ゆのSystemTapスクリプトでは、カーネルのreadシステムコールの完了部分にフック(probe)を入れ、
プロセスがcatコマンドの場合に限り、読んだ内容を解析して、ゆのを発見すると勝手に読んだ中身のメモリを書き換えるというシロモノです。
execname() == "cat" という条件分岐を取り除くと、安全策に引っかからない限りどんなプロセスでも対象になりますが非常に危険。
なにしろメモリの書き換えはEmbedded-Cを使ってmemcpyするという強引っぷり。
ご利用は計画的に。

ゆの in SystemTap - 応用

id:NeoCat:20080713:1215944362 のようなテクニックを使うと、どんな言語でもソースの読み込み時点で書き変えてしまうことにより、ゆの対応にできる? 例えば

% cat yuno.rb
puts "x / _ / x < 来週も見てくださいね!"
% ruby yuno.rb  <= 書き換えられた上で読み込まれる
ひだまりスケッチx365 来週も見てくださいね!

といった具合。ズル以外の何でも無いですね...

なお、前のエントリのスクリプトのままでは[x/_ ]以外の知らない文字に出会うと諦めてしまうので駄目。