用户态通过IOCTL传递字符串至内核态出现乱码问题求助
问题分析与解决
问题根源
用户态调用DeviceIoControl时,传入的缓冲区长度是strlen(welcome)——这个函数返回的是字符串**不含终止符\0**的字符数。内核态用%s格式打印时,要求字符串必须以\0结尾,否则会持续读取后续内存直到碰到\0,这就导致末尾出现随机乱码;偶尔正常是巧合遇到内存里的\0,完全不可靠。
修复方案
1. 修改用户态代码
将传入的缓冲区长度改为包含终止符的长度,也就是strlen(welcome) + 1,确保内核能拿到完整的带终止符的字符串:
const char* welcome = "Hello from user mode"; // 字符串字面量默认自带\0,无需手动添加 bResult = DeviceIoControl(hDevice, IO_PRINT_MSG_REQUEST, (char*)welcome, strlen(welcome) + 1, NULL, 0, &Bytes, NULL);
2. 内核态安全优化(可选)
如果无法确保用户态一定会传入带终止符的字符串,内核态可以主动处理,避免越界:
case IO_PRINT_MSG_REQUEST: buffer = irp->AssociatedIrp.SystemBuffer; // 获取用户态传入的缓冲区总长度 ULONG inputLen = IoGetCurrentIrpStackLocation(irp)->Parameters.DeviceIoControl.InputBufferLength; if (inputLen > 0 && buffer != NULL) { // 手动添加终止符,确保字符串结束 ((char*)buffer)[inputLen - 1] = '\0'; DbgPrint("IOCTL HELLO."); DbgPrint("Message received : %s\n", buffer); } // 必须完成IRP的收尾操作 irp->IoStatus.Status = STATUS_SUCCESS; irp->IoStatus.Information = 0; IoCompleteRequest(irp, IO_NO_INCREMENT); return STATUS_SUCCESS;
注:原内核代码缺少
IoCompleteRequest等IRP收尾逻辑,可能引发其他问题,建议补上。
验证效果
修改后内核态打印的字符串会正常终止,稳定显示Message received : Hello from user mode,不会再出现随机乱码。
内容的提问来源于stack exchange,提问作者Cesar
相关产品推荐
相关产品推荐

