#include <libubus.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// 定义参数解析结构
enum
{
MEMORY_LEAK_AMOUNT,
// TRIGGER_NULL_POINTER,
__PARAM_MAX
};
static const struct blobmsg_policy mem_policy[__PARAM_MAX] = {
[MEMORY_LEAK_AMOUNT] = {.name = "leak_amount", .type = BLOBMSG_TYPE_INT32},
// [TRIGGER_NULL_POINTER] = {.name = "trigger_null", .type = BLOBMSG_TYPE_BOOL},
};
// 全局变量用于持续内存泄漏
static char **global_leaked_memory = NULL;
static int leak_count = 0;
static int ubus_trigger_memory_leak(struct ubus_context *ctx, struct ubus_object *obj,
struct ubus_request_data *req, const char *method,
struct blob_attr *msg)
{
struct blob_attr *tb[__PARAM_MAX];
int leak_amount = 0;
int leak_count = 0;
char **global_leaked_memory = NULL; // 假设已声明为全局变量
// 解析参数
blobmsg_parse(mem_policy, __PARAM_MAX, tb, blob_data(msg), blob_len(msg));
if (tb[MEMORY_LEAK_AMOUNT])
{
leak_amount = blobmsg_get_u32(tb[MEMORY_LEAK_AMOUNT]);
}
// 创建响应缓冲区
struct blob_buf b = {};
blob_buf_init(&b, 0);
// 触发多种内存泄漏类型
if (leak_amount > 0)
{
// 类型1:常规malloc泄漏
void *leak1 = malloc(leak_amount * 1024);
if (leak1)
{
memset(leak1, 0xAA, leak_amount * 1024);
global_leaked_memory = realloc(global_leaked_memory, (leak_count + 1) * sizeof(char *));
global_leaked_memory[leak_count++] = leak1;
}
// 类型2:calloc泄漏
void *leak2 = calloc(leak_amount / 2, 2048);
if (leak2)
{
memset(leak2, 0xBB, leak_amount * 1024);
global_leaked_memory = realloc(global_leaked_memory, (leak_count + 1) * sizeof(char *));
global_leaked_memory[leak_count++] = leak2;
}
// 类型3:realloc泄漏
void *leak3 = realloc(NULL, leak_amount * 2048);
if (leak3)
{
memset(leak3, 0xCC, leak_amount * 2048);
global_leaked_memory = realloc(global_leaked_memory, (leak_count + 1) * sizeof(char *));
global_leaked_memory[leak_count++] = leak3;
}
blobmsg_add_u32(&b, "total_leaked_kb", leak_amount * 4); // 估算总泄漏量
blobmsg_add_u32(&b, "leaked_objects", leak_count);
}
blobmsg_add_string(&b, "status", leak_amount > 0 ? "memory_leaked" : "no_leak_requested");
ubus_send_reply(ctx, req, b.head);
blob_buf_free(&b);
return UBUS_STATUS_OK;
}
static int ubus_trigger_null_pointer(struct ubus_context *ctx, struct ubus_object *obj,
struct ubus_request_data *req, const char *method,
struct blob_attr *msg)
{
struct blob_attr *tb[__PARAM_MAX];
int severity = 1;
bool trigger_crash = true; // 实际启用时设置为true
// 解析参数
blobmsg_parse(mem_policy, __PARAM_MAX, tb, blob_data(msg), blob_len(msg));
if (tb[MEMORY_LEAK_AMOUNT])
{ // 复用参数作为严重级别
severity = blobmsg_get_u32(tb[MEMORY_LEAK_AMOUNT]);
severity = (severity % 4) + 1; // 限制在1-4范围内
}
// 创建响应缓冲区
struct blob_buf b = {};
blob_buf_init(&b, 0);
blobmsg_add_u32(&b, "severity", severity);
const char *action_desc = "";
// 根据严重级别触发不同类型的空指针访问
switch (severity)
{
case 1: // 简单空指针解引用
action_desc = "simple_null_dereference";
if (trigger_crash)
{
int *null_ptr = NULL;
*null_ptr = 42; // 实际触发崩溃
}
break;
case 2: // 空函数指针调用
action_desc = "null_function_call";
if (trigger_crash)
{
void (*func)(void) = NULL;
func(); // 实际触发崩溃
}
break;
case 3: // 空结构体成员访问
action_desc = "null_struct_member_access";
if (trigger_crash)
{
struct Test
{
int value;
} *test = NULL;
int val = test->value; // 实际触发崩溃
}
break;
case 4: // 空指针数组访问
action_desc = "null_array_access";
if (trigger_crash)
{
int *array = NULL;
array[0] = 99; // 实际触发崩溃
}
break;
}
blobmsg_add_string(&b, "action", action_desc);
blobmsg_add_string(&b, "status", trigger_crash ? "crash_triggered" : "dry_run");
if (!trigger_crash)
{
blobmsg_add_string(&b, "warning", "Run_with_trigger_crash=true_to_actually_crash");
}
ubus_send_reply(ctx, req, b.head);
blob_buf_free(&b);
// 如果实际触发崩溃,此处不会执行
return trigger_crash ? UBUS_STATUS_INTERNAL_ERROR : UBUS_STATUS_OK;
}
static struct ubus_method memleak_ubus_methods[] =
{
UBUS_METHOD("leak_memory", ubus_trigger_memory_leak, mem_policy),
UBUS_METHOD("null_pointer", ubus_trigger_null_pointer, mem_policy),
};
static struct ubus_object_type memleak_ubus_obj_type = UBUS_OBJECT_TYPE("memory_leak", memleak_ubus_methods);
static struct ubus_object memleak_ubus_obj =
{
.name = "memory_leak",
.type = &memleak_ubus_obj_type,
.methods = memleak_ubus_methods,
.n_methods = ARRAY_SIZE(memleak_ubus_methods),
};
// 清理函数
void cleanup_leaked_memory(void)
{
for (int i = 0; i < leak_count; i++)
{
free(global_leaked_memory[i]);
}
free(global_leaked_memory);
global_leaked_memory = NULL;
leak_count = 0;
}
int mem_ubus_init(struct ubus_context *ctx)
{
if (ctx == NULL)
{
printf("ubus context is null.\n");
return -1;
}
if (ubus_add_object(ctx, &cstg_ubus_obj) != 0)
{
printf("ubus add obj failed\n");
return -1;
}
return 0;
}
修改上述代码,创建主子双进制,子进程触发内存泄漏,父进程回收子进程或者终止子进程并返回消息