無料Wikiサービス | デモページ
検索

アクセス数
最近のコメント
kprobe - ななし
ksetの実装 - スーパーコピー
カーネルスレッドとは - ノース
カーネルスレッドとは - nbyst
asmlinkageってなに? - ノース
asmlinkageってなに? - よろしく
はじめ - ノース
はじめ - ノース
はじめ - 楽打連動ユーザー
はじめ - 楽打連動ユーザー
Adsense
広告情報が設定されていません。

builtin_object_size


__builtin_object_sizeはgccの機能で、コンパイル時にサイズを取得します。以降私の解釈です。引数のtypeは0/1/2/3ですが、そうでなくビット0/ビット1としてのフラグとなります。typeが0/2すなわちビット0がセットされない場合と、(type=1/3)でビット0がセットされている場合。typeが0/1のビット1がセットされない場合と、(type=2/3)でビット1がセットされている場合での対応です。

ビット0がセットされていれば引数そのもののサイズ、セットされていればかかるバッファに関連する領域も含めてのサイズとなります。

ビット1がセットされていればサイズが取得できない時の返値は0、されてなければ-1となります。
#include "stdio.h"

static void     obj_size(void* to);

struct hoge {
       char buf0[10];
       char buf1[20];
       char buf2[30]; };

void    main()
{
       obj_size("12345");
}

static void     obj_size(void* to)
{
       struct hoge buf;

       printf("%d\n",  __builtin_object_size(buf.buf1, 0));
       printf("%d\n",  __builtin_object_size(buf.buf1, 1));
       printf("%d\n",  __builtin_object_size(buf.buf1, 2));
       printf("%d\n",  __builtin_object_size(buf.buf1, 3));
       printf("\n");
       printf("%d\n",  __builtin_object_size(to, 0));
       printf("%d\n",  __builtin_object_size(to, 1));
       printf("%d\n",  __builtin_object_size(to, 2));
       printf("%d\n",  __builtin_object_size(to, 3));
}

[root@localhost lkm]# ./a.out
50
20
50
20

-1
-1
0
0

補足

__compiletime_object_size()は、ユーザ空間からカーネル空間にバッファを複写するcopy_from_user()で使われています。__compiletime_object_size()の引数は、copy_from_user()の引数toで、それではサイズが取得できないのではと。故copy_from_user()はinlineで展開されます。

__builtin_object_size()は、staticバッファを前提とした機能で、サイズチェックをコード上に記述する手間を無くします。(サイズ値の変更毎にかかる修正も必要ありません。gccが行ってくれます。)

なお、サイズが取得できない時の返値を-1/0としてる理由ですが、返値をそのままstrncpy()等の引数とするケースを想定してのことではと・・・。そうする事で最悪のケースは必ず回避できます。
#define __compiletime_object_size(obj) __builtin_object_size(obj, 0)

static inline unsigned long __must_check copy_from_user(void *to,
                                         const void __user *from,
                                         unsigned long n)
{
       int sz = __compiletime_object_size(to);

       might_fault();
       if (likely(sz == -1 || sz >= n))
               n = _copy_from_user(to, from, n);
#ifdef CONFIG_DEBUG_VM
       else
               WARN(1, "Buffer overflow detected!\n");
#endif
       return n;
}
sz==-1の時も、_copy_from_user()となっていますが、呼び出し側で動的にバッファを確保するケースで、複写するサイズ分のバッファを確保したり、ないし呼び出し側で複写サイズとバッファに応じたチェックを行うことを前提とします。


最終更新 2014/11/26 04:16:54 - north
(2014/11/26 04:16:54 作成)