在 Solaris 11 中使用空变量从 Perl 进行 syswrite 调用时,OpenSSH 会话会被终止

在 Solaris 11 中使用空变量从 Perl 进行 syswrite 调用时,OpenSSH 会话会被终止

我们在 Solaris 11.4 中遇到了一个奇怪的问题。

当从 Perl 运行以下代码时会出现问题

my $emptystring = "";
syswrite STDOUT, $emptystring;

使用空变量执行 syswrite 调用会导致OpenSSH 会话被终止:-(

这个问题对我们来说是新问题,它是在从 Solaris 11.3 迁移到 Solaris 11.3 后出现的Solaris 11.4 和 OpenSSH 8.1(7.9之前的版本不存在这个问题)

出现此错误仅当输出是标准输出时. 如果脚本的输出重定向到文件,则一切正常

如果跟踪脚本并在如下调用truss中发生错误:write

23886:  write(1, 0x004B6450, 0)             = 0

显示的写入调用是在一切正常的情况下进行的,当出现错误时,会话将被终止,桁架输出将停止,此行之后的所有内容都不会显示。


更多信息:我们已经测试了为 Solaris 11.3 编译的二进制文件,它们可以工作!所以显然问题来自我们的编译,但我们还不知道为什么......继续......


更多信息:la编译没有显着差异。这OpenSSH服务器的日志表明空值被视为 EOF如下图所示,它显示了存在此错误的 OpenSSH 与另一个行为正确的 OpenSSH 之间的差异。

在此输入图像描述

显示它的行如下:

debug2: channel 0: read<=0 rfd 16 len 0
debug2: channel 0: read failed
debug2: channel 0: chan_shutdown_read (i0 o0 sock -1 wfd 16 efd -1 [closed])
debug2: channel 0: input open -> drain
debug2: channel 0: ibuf empty
debug2: channel 0: send eof
debug3: send packet: type 96
debug2: channel 0: input drain -> closed

任何想法?

答案1

找到解决方案了! :-) 简而言之,我们必须设置C标志PTY_ZEROREAD在编译的配置阶段

channels.c源代码文件中我们可以看到错误在哪里抛出......

#ifndef PTY_ZEROREAD
    if (len <= 0) {
#else
    if ((!c->isatty && len <= 0) ||
        (c->isatty && (len < 0 || (len == 0 && errno != 0)))) {
#endif
        debug2("channel %d: read<=0 rfd %d len %zd",
            c->self, c->rfd, len);
        if (c->type != SSH_CHANNEL_OPEN) {
            debug2("channel %d: not open", c->self);
            chan_mark_dead(ssh, c);
            return -1;
        } else {
            chan_read_failed(ssh, c);
        }
        return -1;
    }

我们可以看到编译标志PTY_ZEROREAD更改终端中处理零长度消息的方式。

要解决该问题,该configure命令必须设置 C 标志,如以下命令的最后一行所示:

./configure --with-zlib           \
        --with-pam                \
        --with-md5-passwords      \
        CFLAGS="-DPTY_ZEROREAD=1"

相关内容