CVE-2013-2094 (Linuxカーネル権限昇格の脆弱性)

2年ぶりくらいかな? スラッシュドットにタレコんでみたら採用された。(Linux カーネルに権限昇格の脆弱性、広範囲に影響か)

詳しい方が既にコメントを付けてくれているようなので、ここでは補足と落ち穂拾いをしてみる。

概要

今回の脆弱性については、Redditの記事が一番詳しく書かれている。

※5/24追記:以下の記事の方が詳しいかも

正直、Linuxカーネルプログラミングには全く詳しくないので、きちんと理解してないけど……。バグはkernel/events/core.c 内。パッチは以下1行のみで、int型をu64型に直せば良い。

--- a/kernel/events/core.c
+++ b/kernel/events/core.c
@@ -5331,7 +5331,7 @@ static void sw_perf_event_destroy(struct perf_event *event)
static int perf_swevent_init(struct perf_event *event)
{
- int event_id = event->attr.config;
+ u64 event_id = event->attr.config;
if (event->attr.type != PERF_TYPE_SOFTWARE)
return -ENOENT;

event_idというu64型の値をint型で受け取っており、その際に全てのビットを適切にチェックしていないため悪意のあるコードを実行可能となっている。u64はunsignedなので、負のevent_idを突っ込んでやることでexploitできるようだ。(実際はそんなに単純な話じゃないみたいだけど)

Exploitコード

スラッシュドットの記事にはさすがにリンクを付けなかったけど、簡単に試せるExploitコードが既に出回っている。一般ユーザが実行するとrootが取得可能なことを確認した。

対象OS

Linuxカーネル2.6.37以上3.8.9未満までらしい。

私が試した限り、CentOS 5.5ではExploit不可、CentOS 6.3および6.4では可だった。CentOSカーネル2.6.32なのだけど、最新カーネルからバックポートしているのでその際にこのバグも混入したらしい。(もちろんRedHatも影響アリ)

u64ってなんぞ

これはLinuxカーネルプログラミングで使われる型で、unsigned long long 。カーネルソースを拾ってきて、include/asm-generic/int-ll64.h を覗いてみると分かる。

/*
 * asm-generic/int-ll64.h
 *
 * Integer declarations for architectures which use "long long"
 * for 64-bit types.
 */
#ifndef _ASM_GENERIC_INT_LL64_H
#define _ASM_GENERIC_INT_LL64_H

#include <uapi/asm-generic/int-ll64.h>


#ifndef __ASSEMBLY__

typedef signed char s8;
typedef unsigned char u8;

typedef signed short s16;
typedef unsigned short u16;

typedef signed int s32;
typedef unsigned int u32;

typedef signed long long s64;
typedef unsigned long long u64;

2013/08/08追記

ITProにも記事が出ていた(http://itpro.nikkeibp.co.jp/article/COLUMN/20130723/493624/)。

どうやらAndroid 4.0-4.2系にも影響があったらしい。くわばらくわばら