Tetsuo Handa
from-****@i-lov*****
2009年 7月 3日 (金) 14:34:03 JST
熊猫です。 TOMOYO 1.6.7 / 1.6.7p1 / 1.6.8 に関して、 CONFIG_SLOB=y の場合に バッファオーバーフローする可能性が発見されました。 CONFIG_SLAB=y または CONFIG_SLUB=y の場合は問題ありません。 問題となるコードは以下の部分です。 −−−定義部分−−− #define CCS_MAX_PATHNAME_LEN 4000 #define CCS_EXEC_TMPSIZE 4096 struct ccs_execve_entry { struct list_head list; struct task_struct *task; /* = current */ struct ccs_request_info r; struct ccs_obj_info obj; struct linux_binprm *bprm; int srcu_idx; /* For execute_handler */ const struct ccs_path_info *handler; char *program_path; /* Size is CCS_MAX_PATHNAME_LEN bytes */ /* For dumping argv[] and envp[]. */ struct ccs_page_dump dump; /* For temporary use. */ char *tmp; /* Size is CCS_EXEC_TMPSIZE bytes */ }; −−−割り当て部分−−− ee->program_path = kzalloc(CCS_MAX_PATHNAME_LEN, GFP_KERNEL); ee->tmp = kzalloc(CCS_MAX_PATHNAME_LEN, GFP_KERNEL); −−−利用部分−−− new_domain_name = ee->tmp; if (ccs_is_domain_initializer(r->domain->domainname, &rn, &ln)) { /* Transit to the child of ccs_kernel_domain domain. */ snprintf(new_domain_name, CCS_EXEC_TMPSIZE - 1, ROOT_NAME " " "%s", ee->program_path); ee->tmp には CCS_EXEC_TMPSIZE バイトの領域が割り当てられるとコメントに 書かれていますが、実際には CCS_MAX_PATHNAME_LEN バイトしか要求して いませんでした。 slab アロケータおよび slub アロケータを使用している場合は(内部処理により 2 のべき乗に丸められることにより)実際には 4096 バイトが割り当てられるため、 問題は生じません。しかし、 slob アロケータを使用している場合は 4000 バイト ちょうどしか割り当てられないため、バッファオーバーフローする可能性があります。 http://sourceforge.jp/projects/tomoyo/releases/?package_id=5026 から ダウンロードできるバイナリパッケージに関しては、 slob アロケータを 使っていないため、そのままでも大丈夫です。 自分でコンパイルされている方は、 CONFIG_SLOB=y となっていないかどうか確認し、 CONFIG_SLOB=y となっていた場合には以下のパッチを適用またはホットフィックスを ダウンロードして再コンパイルしていただきますようお願いいたします。 ccs-patch-1.6.8-20090703.tar.gz MD5:1114ea8c201d78b044c87f2127932b8e --- fs/tomoyo_domain.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) --- ccs-patch.orig/fs/tomoyo_domain.c +++ ccs-patch/fs/tomoyo_domain.c @@ -1227,7 +1227,7 @@ static struct ccs_execve_entry *ccs_allo return NULL; memset(ee, 0, sizeof(*ee)); ee->program_path = ccs_alloc(CCS_MAX_PATHNAME_LEN, false); - ee->tmp = ccs_alloc(CCS_MAX_PATHNAME_LEN, false); + ee->tmp = ccs_alloc(CCS_EXEC_TMPSIZE, false); if (!ee->program_path || !ee->tmp) { ccs_free(ee->program_path); ccs_free(ee->tmp);