Linux メモリ保護機能の実装 (mlock, MADV_DONTDUMP, MADV_WIPEONFORK)
セキュリティ強化のため、Linux 固有のメモリ保護機能を追加: ### 実装した保護機能 1. **mlock()** - スワップ防止 - センシティブなメモリをディスクへのスワップから保護 - 権限不足の場合は警告出力の上継続(フォールバック) 2. **MADV_DONTDUMP** - コアダンプ漏洩防止 - コアダンプ生成時にメモリ内容を除外 - プライベート鍵がダンプに含まれないようにする 3. **MADV_WIPEONFORK** - fork() 子プロセス漏洩防止 - fork() 後の子プロセスからメモリ内容を消去 - 子プロセスへの鍵漏洩を防止 ### 変更ファイル - src/se050_scp03.c - SCP03 コンテキストのメモリ保護 - src/se050_keystore.c - キーストアコンテキストのメモリ保護 ### 実装詳細 - Linux 環境でのみ有効(#ifdef __linux__) - 非 Linux プラットフォームではフォールバック - mlock 失敗時は警告のみ出力(処理継続) - madvise 失敗時はエラーログ出力(非致命的) ### 注意事項 - mlock には CAP_IPC_LOCK 権限または RLIMIT_MEMLOCK クォータが必要 - 権限不足の場合でも機能は動作(保護なしで継続) - 本番環境では適切な権限設定を推奨
This commit is contained in:
+83
-1
@@ -7,12 +7,72 @@
|
||||
* License: MIT (Clean-room implementation)
|
||||
*/
|
||||
|
||||
#define _GNU_SOURCE /* For MADV_DONTDUMP, MADV_WIPEONFORK */
|
||||
#define _POSIX_C_SOURCE 200809L
|
||||
|
||||
#include "se050_wireguard.h"
|
||||
#include "se050_crypto_utils.h"
|
||||
#include "se050_keystore_internal.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
|
||||
/* Linux memory protection */
|
||||
#ifdef __linux__
|
||||
#include <sys/mman.h>
|
||||
#endif
|
||||
|
||||
/* ============================================================================
|
||||
* Memory Protection (Linux-specific)
|
||||
* ============================================================================ */
|
||||
|
||||
/**
|
||||
* @brief Protect sensitive memory from being swapped or dumped
|
||||
*/
|
||||
#ifdef __linux__
|
||||
static se050_status_t protect_sensitive_memory(void *ptr, size_t size)
|
||||
{
|
||||
/* 1. Prevent swapping to disk (optional - may fail due to permissions) */
|
||||
if (mlock(ptr, size) != 0) {
|
||||
/* mlock may fail due to ulimit restrictions. Log warning but continue. */
|
||||
fprintf(stderr, "Warning: mlock failed (%s). Memory may be swapped.\n", strerror(errno));
|
||||
/* Continue without mlock - better than failing entirely */
|
||||
}
|
||||
|
||||
/* 2. Exclude from core dumps */
|
||||
if (madvise(ptr, size, MADV_DONTDUMP) != 0) {
|
||||
perror("madvise MADV_DONTDUMP failed");
|
||||
/* Non-fatal, continue */
|
||||
}
|
||||
|
||||
/* 3. Clear in child processes after fork() */
|
||||
if (madvise(ptr, size, MADV_WIPEONFORK) != 0) {
|
||||
perror("madvise MADV_WIPEONFORK failed");
|
||||
/* Non-fatal, continue */
|
||||
}
|
||||
|
||||
return SE050_OK;
|
||||
}
|
||||
|
||||
static void release_memory_protection(void *ptr, size_t size)
|
||||
{
|
||||
munlock(ptr, size);
|
||||
}
|
||||
#else
|
||||
static se050_status_t protect_sensitive_memory(void *ptr, size_t size)
|
||||
{
|
||||
(void)ptr;
|
||||
(void)size;
|
||||
return SE050_OK;
|
||||
}
|
||||
|
||||
static void release_memory_protection(void *ptr, size_t size)
|
||||
{
|
||||
(void)ptr;
|
||||
(void)size;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* ============================================================================
|
||||
* Key Store Management
|
||||
@@ -21,6 +81,7 @@
|
||||
se050_status_t se050_keystore_init(se050_keystore_ctx_t **ctx, se050_session_ctx_t *session)
|
||||
{
|
||||
se050_keystore_ctx_t *keystore;
|
||||
size_t ctx_size;
|
||||
|
||||
if (!ctx || !session) {
|
||||
return SE050_ERR_INVALID_ARG;
|
||||
@@ -32,11 +93,28 @@ se050_status_t se050_keystore_init(se050_keystore_ctx_t **ctx, se050_session_ctx
|
||||
return SE050_ERR_FAIL;
|
||||
}
|
||||
|
||||
ctx_size = sizeof(*keystore);
|
||||
|
||||
/* Apply memory protection (Linux only) */
|
||||
if (protect_sensitive_memory(keystore, ctx_size) != SE050_OK) {
|
||||
free(keystore);
|
||||
return SE050_ERR_FAIL;
|
||||
}
|
||||
|
||||
keystore->session = session;
|
||||
keystore->max_objects = 16; /* Maximum 16 keys */
|
||||
keystore->objects = (key_object_t *)calloc(keystore->max_objects, sizeof(key_object_t));
|
||||
|
||||
if (!keystore->objects) {
|
||||
release_memory_protection(keystore, ctx_size);
|
||||
free(keystore);
|
||||
return SE050_ERR_FAIL;
|
||||
}
|
||||
|
||||
/* Protect key objects array */
|
||||
if (protect_sensitive_memory(keystore->objects, keystore->max_objects * sizeof(key_object_t)) != SE050_OK) {
|
||||
free(keystore->objects);
|
||||
release_memory_protection(keystore, ctx_size);
|
||||
free(keystore);
|
||||
return SE050_ERR_FAIL;
|
||||
}
|
||||
@@ -65,8 +143,9 @@ void se050_keystore_free(se050_keystore_ctx_t *ctx)
|
||||
}
|
||||
}
|
||||
|
||||
/* Free key objects array */
|
||||
/* Release memory protection for key objects array */
|
||||
if (ctx->objects) {
|
||||
release_memory_protection(ctx->objects, ctx->max_objects * sizeof(key_object_t));
|
||||
free(ctx->objects);
|
||||
ctx->objects = NULL;
|
||||
}
|
||||
@@ -74,6 +153,9 @@ void se050_keystore_free(se050_keystore_ctx_t *ctx)
|
||||
ctx->num_objects = 0;
|
||||
ctx->max_objects = 0;
|
||||
|
||||
/* Release memory protection for context */
|
||||
release_memory_protection(ctx, sizeof(*ctx));
|
||||
|
||||
/* Free key store context */
|
||||
free(ctx);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user