Linux下FPGA内核模块ioctl超时通知实现是否正确?
问题回答
该实现不是应用层获取ioctl超时通知的正确方式,存在多个逻辑漏洞和安全风险,具体问题如下:
- 存在竞态条件风险
操作全局中断标记sInterruptFlagPacket时没有加锁/原子操作保护,该变量会同时被中断上下文、ioctl进程上下文修改,多核场景下很容易出现值被覆盖、中断事件丢失的问题。且你在wait_event_interruptible_timeout返回后无差别清空标记,无论本次调用是超时、被信号打断、还是正常拿到中断,都会清空标记,可能会误清掉刚触发的下一次中断标记,导致后续ioctl调用丢失事件。 - 返回值处理逻辑错误
wait_event_interruptible_timeout的返回值规则为:条件触发时返回剩余的超时时间(值>0),超时返回0,被信号中断返回负的错误码(如
-ERESTARTSYS)
你直接把原始返回值赋值给InterruptRequest.Error返回给应用层,应用层无法区分「正常中断触发」「超时」「被信号打断」三种场景,也就无法正确判断是否发生了超时。 - 缺少用户态内存操作校验
copy_from_user和copy_to_user调用时没有检查返回值,如果用户传入的地址是非法地址,会直接返回未拷贝的字节数,未处理的情况下会引发内核oops甚至崩溃。
修正建议
你可以按照以下逻辑调整代码:
- 将
sInterruptFlagPacket改为原子变量,或者操作时持有自旋锁保证并发安全 - 按返回值分支处理逻辑,不要无差别清空中断标记:
case INTERRUPT_REQUEST_CODE: if (copy_from_user(&InterruptRequest, (void __user *)IoctlParam, sizeof(INTERRUPT_REQUEST))) { rc = -EFAULT; break; } rc = wait_event_interruptible_timeout(sWaitQueuePacket, atomic_read(&sInterruptFlagPacket) != 0, Request.timeout); if (rc > 0) { // 正常触发中断,清标记,返回成功 atomic_set(&sInterruptFlagPacket, 0); InterruptRequest.Error = 0; } else if (rc == 0) { // 超时,返回超时错误码 InterruptRequest.Error = -ETIMEDOUT; } else { // 被信号打断,返回对应错误码 InterruptRequest.Error = rc; } if (copy_to_user((void __user *)IoctlParam, &InterruptRequest, sizeof(INTERRUPT_REQUEST))) { rc = -EFAULT; } break;
- 应用层拿到返回的
Error字段后,判断值为-ETIMEDOUT即可确认是超时触发。
内容的提问来源于stack exchange,提问作者Zvi Vered
相关产品推荐
相关产品推荐

