2019/01/07

[c/c++][CERT]パディングの中まで気にするのか

C言語の再履修シリーズ。


DCL39-C. 信頼境界を越えて構造体を渡すとき情報漏えいしない
https://www.jpcert.or.jp/sc-rules/c-dcl39-c.html


何を言っているのかなかなかわからなかったが、たぶんこういうことだろう。

  • 構造体や共用体では、メンバ間にパディングが入ることがある
  • ビットフィールドでも、ビットのパディングが入ることがある
  • パディングの値は不定
  • 不定ゆえに、メンバの書き換えを行う場合にどういう値が入るかも不定
  • そのため、意図していない有用なデータが書き込まれるかもしれない


問題は、最後の部分だ。
いきなり文章が飛躍しているが、タイトルの通り気にするのは「信頼境界」で、例で上がっている「カーネルとユーザスペース間」のような、カーネルからユーザスペースに値を渡すときに、情報を漏らしてはいけないのにカーネル側から漏れてしまうことを懸念している。


memset()の例では、4byteアラインメント(レジスタも4byte)だとして、構造体メンバの真ん中に1byteのメンバがいる。
ここの書き換えを行うときに「どうせ1byteしか見ないからいいや」とコンパイラが判断して、1byteのメンバ分のレジスタしか書き換えず、残りの3byteはそのままで、しかも書込みは4byteで行ったりすると、レジスタの残り3byteはそのときの値を残したままなので、ユーザスペースに渡すデータに書き込まれてしまう、と。


えー、そんなことまで考慮しないといけないのぉ。。。


対策案としてあげてあるコードは、構造体メンバをシリアライズしてユーザスペースに渡して、向こう側で構造体に戻す、というものだ。
つまりまあ、機器間で通信データを作ってやりとりするようなものですな。

ここまでやるんですなぁ。

0 件のコメント:

コメントを投稿

コメントありがとうございます。
スパムかもしれない、と私が思ったら、
申し訳ないですが勝手に削除することもあります。