Files
hakmem/docs/tls_sll_hdr_reset_investigation_report.md

53 lines
3.9 KiB
Markdown
Raw Normal View History

# 調査報告: 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. **原因特定**: ログと挙動から、アラインメント起因の隣接ブロック破壊と特定。