ダイエットのためソース解析メモ

以前、http://d.hatena.ne.jp/himainu/20070226
macroをattributeにすることで、
ストレージ消費量をダイエットする話があった。
メモリのダイエットにも使えると想像される。
理論値の計算のため、
ソースを読んで、typeattribute&allowがどれくらいメモリ&ストレージ食うのか
解析してみた。解析メモ。

typeattributeのメモリ、ストレージ消費量

policydbのtype_attr_mapで、attributeは記憶。

/* type -> attribute reverse mapping */
struct ebitmap *type_attr_map;

type_attr_mapの配列になってるみたい。

ebitmapの定義。

ebitmap.h


29 struct ebitmap {
30 struct ebitmap_node *node; /* first node in the bitmap */
31 u32 highbit; /* highest position in the total bitmap */
32 };

23 struct ebitmap_node {
24 u32 startbit; /* starting position in the total bitmap */
25 MAPTYPE map; /* this node's portion of the bitmap */
26 struct ebitmap_node *next;
27 };


で、これが、type->attributeにどうマッピングされてるの?

294 struct ebitmap *sattr, *tattr;
..
331 sattr = &policydb.type_attr_map[scontext->type - 1];
332 tattr = &policydb.type_attr_map[tcontext->type - 1];

のように使われてる。

type_attr_map[0]は、タイプ1番、
type_attr_map[1]は、タイプ2番の
ために使われる。

で、各配列要素ごとに、
ebitmap_nodeのリストがあると。
ebitmap_nodeのリストは、ビットマップをあらわす。
「map」エントリがそう。
例えば、
一つ目のebitmap_nodeは、
attribute0〜63までの付与状況
2つ目は、
attribute64-123までの付与状況
...
をあらわす。ビットが「1」になってると、そのタイプが該当のattributeを持っていることになる。

さて、メモリダイエット的に気になるのが、こいつのメモリ消費量。
ebitmap_node一つあたり、
startbit(32bit)+ MAPTYPE(64bit) + next(32bit)= 128bit = 16byte
食ってる。
type_attr_mapの配列要素毎に、
attributeの数がaとすると、a/64(小数点以下切り上げ)個の
ebitmap_nodeがあるのか。
type_attr_mapの配列要素ごとに、a/64(切り上げ) * 16byte + 8byte(size of struct ebitmap) のメモリを使う。

type_attr_mapの配列個数はtypeの個数。t個とすると、

type_attr_mapのメモリ消費量は、
t * (a/64(切り上げ) * 16 + 8) byteとなる

ちなみに、バイナリポリシ内でのtype_attrのストレージ消費量は、途中をはしょると
t* (a/64(切り上げ) * 12 +8) byte
# ebitmap_read関数を解析
#12なのは、 struct ebitmap_node *next;(4byte)が不要な為

allowのメモリ、ストレージ消費量

メモリ消費量は、以前見たとおり、
http://d.hatena.ne.jp/himainu/20070723
一個のallowで16byte消費、
あとは、プラス、slabでさらに16byte。
freeコマンドでusedと出るのは、出るのはslabも含めてるっぽい
#slabでメモリを食うことは、重要なことなのかは、調べなきゃ、、、

ストレージ消費量は、
avtab.cのソースを見る。
avtab_read_itemで一つのallowを読んでる。

378 rc = next_entry(buf16, fp, sizeof(u16)*4);
379 if (rc < 0) {
380 printk("security: avtab: truncated entry\n");
381 return -1;
382 }
383
384 items = 0;
385 key.source_type = le16_to_cpu(buf16[items++]);
386 key.target_type = le16_to_cpu(buf16[items++]);
387 key.target_class = le16_to_cpu(buf16[items++]);
388 key.specified = le16_to_cpu(buf16[items++]);
389
390 rc = next_entry(buf32, fp, sizeof(u32));
391 if (rc < 0) {
392 printk("security: avtab: truncated entry\n");
393 return -1;
394 }
395 datum.data = le32_to_cpu(*buf32);
396 return insertf(a, &key, &datum, p);

next_entryで、バイナリポリシから指定バイト分だけ、バッファに読んでるが、
sizeof(u16)*4 , sizeof(u32)を読んでいる。
つまり、16*4+32=96bit = 12 byte。
一つのallowでストレージは12byte食う。。はず。
だが、1万ルールあったとして、12 * 10000 = 120 k?
うーむ実測より小さいような、、

#ちなみに、ポリシのバージョンが<20の時は、ポリシフォーマットに無駄があって
#最低24byte食ってた。