可以要求 Linux 内核使用 CTS/RTS 流控制,通过r选项在console=参数中。例如,一个波特率为 9600bps、8 个数据位、无奇偶校验且采用 CTS/RTS 流控制的串行链路配置如图 A-1 所示。
因为 Linux 内核只发送数据,CTS/RTS 流控制的实现方式是检查 Clear to Send (CTS) 信号是否未被置位。实现此功能的代码位于/usr/src/linux/drivers/char/serial.c,相关部分见图 A-2。
图 A-2. 用于控制台 CTS/RTS 流控制的内核源代码
static inline void wait_for_xmitr(struct async_struct *info) { … /* Wait for flow control if necessary */ if (info->flags & ASYNC_CONS_FLOW) { tmout = 1000000; while (--tmout && ((serial_in(info, UART_MSR) & UART_MSR_CTS) == 0)); } } |
由tmout值为 1000000 驱动的循环会导致等待约一秒钟,直到 CTS 线路被置位。
此代码忽略了 RS-232 数据集就绪 (Data Set Ready) 和数据载波检测 (Data Carrier Detect) 状态线的状态。这会产生一些后果。
如果 RS-232 电缆被拔掉或者终端服务器端口空闲,那么对于写入控制台的每个字符,代码都会等待约一秒钟,直到 CTS 被置位。因此,当启动机器时,写入控制台的大量字符可能会导致重启等待时间非常长。
只有在数据载波检测 (Data Carrier Detect) 和数据集就绪 (Data Set Ready) 都被置位的情况下,Clear to Send (CTS) 才能被有效置位。代码应该考虑到未供电设备的情况,这种设备可能导致 CTS 信号浮空。
在循环一百万次之后,如果 Clear to Send (CTS) 仍然未被置位,则字符仍然会被发送。因此,内核不能用于多点 RS-232 线路。应该丢弃字符。
即使数据载波检测 (Data Carrier Detect) 未被置位,字符也会被发送。因此,连接的调制解调器可能处于命令模式。如果攻击者可以将任意文本放入控制台消息中,则会导致安全漏洞。由于许多控制台消息包含从用户事件派生的错误文本,因此将 AT&F 放入控制台消息并取消编程调制解调器的自动应答配置并不太困难。
由于这些错误,本 HOWTO 不再建议使用内核级流控制。作者有一个内核补丁,修复了所有当前报告的错误,并正在尝试将该补丁集成到主线内核中。一旦内核错误得到纠正,本 HOWTO 将再次建议使用内核级流控制。