Public bug reported:
Broken: socat 1.8.1.1-1 on Ubuntu 26.04 LTS (glibc 2.43-2ubuntu2)
Works: socat 1.8.0.0-4build3 on Ubuntu 24.04 LTS (glibc 2.39-0ubuntu8.7)
Works: socat 1.8.0.0-4build3 installed in the same Ubuntu 26.04
environment via apt downgrade (nothing else changed)
SUMMARY
=======
When socat is invoked with a baud-rate option such as b1000000, the
value it writes into the tty's c_cflag is wrong in 1.8.1.1. Instead of
OR-ing in the B1000000 macro (= 0x1008), it OR-s in the decimal number
1000000 (= 0xF4240). This leaves CBAUD as B0 ("hang up"), with
CBAUDEX/BOTHER not set either, so the kernel has no way to recover the
requested baud rate.
REPRODUCTION
============
Setup: Ubuntu, socat 1.8.1.1-1, strace.
Step 1 - start socat bridging two PTYs at 1 Mbaud:
socat -d -d \
PTY,link=/tmp/socat_a,raw,echo=0,b1000000 \
PTY,link=/tmp/socat_b,raw,echo=0,b1000000
Step 2 - check what socat wrote into c_cflag in a different terminal:
stty -F /tmp/socat_a -a | head -1
Kill socat.
With socat 1.8.0.0 the first line contains "speed 1000000 baud".
With socat 1.8.1.1 the first line contains "speed 0 baud".
Step 3 (for the exact ioctl payload) - run the same command under
strace and inspect the single TCSETSW(2) call socat issues per tty:
strace -e trace=ioctl -tt -s 256 -o /tmp/socat.strace \
socat -d -d \
PTY,link=/tmp/socat_a,raw,echo=0,b1000000 \
PTY,link=/tmp/socat_b,raw,echo=0,b1000000 &
sleep 0.3
kill %1 2>/dev/null
grep -E 'TCSETSW2?' /tmp/socat.strace
C_CFLAG COMPARISON
==================
socat 1.8.0.0 (works):
c_cflag = B1000000 | B9600<<IBSHIFT | CS8 | CREAD | HUPCL | CLOCAL
socat 1.8.1.1 (broken):
c_cflag = B0 | B38400<<IBSHIFT | CS8 | CSTOPB | CREAD | PARODD |
HUPCL | CLOCAL | 0x4000
1.8.1.1 has no B1000000 in CBAUD and has four extra bits set that where
not requested (B38400<<IBSHIFT, CSTOPB, PARODD, 0x4000).
1.8.0.0 sets B1000000 cleanly with no extras.
Analysis
========
Add the four "extra" bits up:
B38400<<IBSHIFT (CIBAUD field, value 0xF) 0x000F0000
0x4000 (bit 14, no defined flag) 0x00004000
PARODD (bit 9) 0x00000200
CSTOPB (bit 6) 0x00000040
SUM: 0x000F4240
0x000F4240 is exactly 1,000,000 in decimal - the value that was passed
in the b1000000 option. The "extras" are the four bit-positions
where 1,000,000 happens to fall in the c_cflag flag layout; strace
labels each position with the c_cflag flag name that lives there. The
B1000000 macro (defined in <asm-generic/termbits.h> as 0x1008) is
never OR-ed in.
HARDWARE
========
The same regression also reproduces against serial hardware - a
USB CDC-ACM device (SEGGER J-Link VCP) at /dev/ttyACMx on the same
Ubuntu 26.04 host. The command structure is identical, with the
device path in place of one PTY:
socat -d -d \
/dev/ttyACMx,raw,echo=0,crtscts=1,b1000000 \
PTY,link=/tmp/test,raw,echo=0,crtscts=1,b1000000
The c_cflag written via TCSETSW2 matches the broken pattern above.
The USB bridge is then reprogrammed to the wrong baud rate via
CDC-ACM SET_LINE_CODING, and the remote serial peer cannot
communicate.
** Affects: socat (Ubuntu)
Importance: Undecided
Status: New
--
You received this bug notification because you are a member of Ubuntu
Bugs, which is subscribed to Ubuntu.
https://bugs.launchpad.net/bugs/2153418
Title:
socat 1.8.1.1 option b<rate> breaks serial communication at non-
default baud rates
To manage notifications about this bug go to:
https://bugs.launchpad.net/ubuntu/+source/socat/+bug/2153418/+subscriptions
--
ubuntu-bugs mailing list
[email protected]
https://lists.ubuntu.com/mailman/listinfo/ubuntu-bugs