Tenemos un problema extraño en Solaris 11.4.
El problema surge cuando se ejecuta un código como el siguiente desde Perl
my $emptystring = "";
syswrite STDOUT, $emptystring;
La ejecución de una llamada syswrite con una variable vacía provoca que la sesión de OpenSSH se elimine 🙁
El problema es nuevo para nosotros, y surge tras la migración de Solaris 11.3 a Solaris 11.4 y con OpenSSH 8.1 (con la versión anterior 7.9 el problema no está)
Este error ocurre solo si la salida es la salida estándar . Si la salida del script se redirige a un archivo, todo funciona bien
Si el script se rastrea con truss
el error ocurre en un write
llamada como esta:
23886: write(1, 0x004B6450, 0) = 0
La llamada de escritura que se muestra es para cuando todo está bien, cuando surge el error, la sesión se cancela y la salida de truss se detiene en esta línea y todo lo que sigue no se muestra.
Más información: Hemos probado binarios compilados para Solaris 11.3 y ¡funcionan!. Entonces, aparentemente, el problema proviene de nuestra compilación, pero aún no sabemos por qué … Al continuar…
Más información: No hay una diferencia notable entre la compilación. Los logs del servidor OpenSSH mostrar que el valor vacío se toma como un EOF , como podemos ver en la siguiente imagen, que muestran la diferencia entre un OpenSSH con este bug y otro que se comporta correctamente.
Las líneas que lo muestran son las siguientes:
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
¿Alguna idea?
Respuesta aceptada:
¡Solución encontrada! 🙂 En resumen, tenemos que establecer la bandera C PTY_ZEROREAD
en la fase de configuración de la compilación .
En channels.c
archivo del código fuente podemos ver donde se arroja el error …
#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;
}
Y podemos ver que el indicador de compilación PTY_ZEROREAD
cambia cómo se tratan los mensajes de longitud cero en las terminales.
Para resolver el problema, configure
El comando debe realizarse con el indicador C configurado como se muestra en la última línea del siguiente comando:
./configure --with-zlib \
--with-pam \
--with-md5-passwords \
CFLAGS="-DPTY_ZEROREAD=1"