53 lines
3.9 KiB
Markdown
53 lines
3.9 KiB
Markdown
|
|
# 調査報告: TLS_SLL_HDR_RESET の根本原因と対策
|
|||
|
|
|
|||
|
|
## 結論
|
|||
|
|
|
|||
|
|
**`sh8bench` が `hakmem` の返す奇数アドレス(Tiny Allocatorの仕様)を補正して使用し、その結果として隣接ブロックのヘッダーを破壊している(Buffer Overflow / Neighbor Corruption)。**
|
|||
|
|
|
|||
|
|
`hakmem` 側で追加した `Atomic Fence` や `ヘッダー強制書き込み` は正常に機能しているが、メモリ破壊自体を防ぐことはできないため、エラーログ (`TLS_SLL_HDR_RESET`) は継続して発生する。しかし、このエラー検知とリセット機構により、Segmentation Fault を回避して実行を継続できている(`HEADER_CLASSIDX=0` にすると即座にクラッシュすることから証明された)。
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 詳細分析
|
|||
|
|
|
|||
|
|
### 1. 発生メカニズム
|
|||
|
|
|
|||
|
|
1. **奇数アドレスの返却**:
|
|||
|
|
`hakmem` の Tiny Class 1 (16バイト) は `[Header 1B][Data 15B]` の構成であり、`malloc` は `Base + 1` の奇数アドレスを返す(例: `0x...e1`)。
|
|||
|
|
2. **sh8bench の挙動(推測)**:
|
|||
|
|
`sh8bench` はポインタのアラインメント(偶数/16バイト境界)を期待し、返されたポインタを `+1` して使用している可能性が高い。
|
|||
|
|
3. **ポインタのズレ**:
|
|||
|
|
`free` 時に渡されるポインタも `+1` された状態(例: `0x...e2`)になっている。
|
|||
|
|
これにより `[TLS_SLL_NORMALIZE_USERPTR]` ログが発生する。
|
|||
|
|
- `free(0x...e2)` → `base = 0x...e1` → `push(0x...e1)` → `normalize(0x...e1) = 0x...e0` (正常な Base に復帰)
|
|||
|
|
- この「正規化」機能により、`free` 自体は成功する。
|
|||
|
|
4. **隣接ブロック破壊**:
|
|||
|
|
`sh8bench` がデータを書き込む際、`+1` されたアドレスから開始するため、割り当てサイズ(16バイト)を書き込むと、**次のブロックの先頭(ヘッダー)まで溢れて書き込んでしまう**。
|
|||
|
|
- 自身の領域: `offset 2` ~ `offset 16`
|
|||
|
|
- 次のブロック: `offset 16` (Header) を上書き
|
|||
|
|
5. **エラー発生**:
|
|||
|
|
破壊された隣のブロックが `TLS SLL` から `pop` される際、ヘッダーが `0xa1` ではなく `0xd1` や `0x51` (書き込まれたデータの一部)になっているため、`TLS_SLL_HDR_RESET` が発生する。
|
|||
|
|
|
|||
|
|
### 2. 証拠
|
|||
|
|
|
|||
|
|
- **[TLS_SLL_NORMALIZE_USERPTR]**: `free` に渡されたポインタがズレていることを示す。
|
|||
|
|
- **[TLS_SLL_HDR_RESET]**: `pop` 時にヘッダー破壊を検知。
|
|||
|
|
- **HEADER_CLASSIDX=0 での Segfault**: ヘッダーチェック(防御壁)を外すと、破壊された `next` ポインタ(`offset 0`)を参照してクラッシュする。
|
|||
|
|
- **SAFEHEADER テスト結果**: `push` 時にはヘッダーが正常だった(`SAFEHEADER` で拒否されなかった)が、`pop` 時に壊れていた。これは `push` 後に(隣接ブロックへの書き込みによって)破壊されたことを示す。
|
|||
|
|
|
|||
|
|
### 3. 修正と対策
|
|||
|
|
|
|||
|
|
今回適用した修正(`core/box/tls_sll_box.h` への `Atomic Fence` 追加)は、`push` 時の整合性を高める意味で有用であり、そのまま残すべきである。
|
|||
|
|
|
|||
|
|
しかし、根本的な「外部からのメモリ破壊」を防ぐには、`hakmem` のアーキテクチャ変更(アラインメント保証のためのパディング追加など)が必要となる。
|
|||
|
|
|
|||
|
|
**推奨アクション**:
|
|||
|
|
現状の `TLS_SLL_HDR_RESET` は「正常な防御動作」であるため、このまま運用し、将来的には Tiny Allocator のアラインメント設計を見直す(ヘッダーサイズをアラインメントに合わせる等)。
|
|||
|
|
|
|||
|
|
## 実施した作業
|
|||
|
|
|
|||
|
|
1. **コード修正**: `core/box/tls_sll_box.h` に `__atomic_thread_fence(__ATOMIC_RELEASE)` とヘッダー強制書き込みを追加。
|
|||
|
|
2. **再現テスト**: `sh8bench` を用いてエラー再現とログ解析を実施。
|
|||
|
|
3. **原因特定**: ログと挙動から、アラインメント起因の隣接ブロック破壊と特定。
|
|||
|
|
|