On Sat, 07 Jun 2025 22:44:40 +0000 Witold Baryluk <[email protected]> 
wrote:
Package: moreutils
Version: 0.69-1
Severity: normal
File: /usr/bin/ifdata
X-Debbugs-Cc: [email protected]

All statistics related commands from ifdata has some bug resulting in
program termination.

$ ifdata -si enp65s0f0np0
*** stack smashing detected ***: terminated
Aborted (core dumped)
Hello,
I tried to track this down, and it originates from a fscanf in get_stats,
which tries to put the interface name into the "char name[10]" variable.

I was able to reproduce it inside a VM by attaching a virtual usb network 
adapter,
which gets a 15 bytes interface name ((qemu) device_add usb-net,id=usb-net1).

A package built with attached patch no longer shows the stack smashing.

Kind regards,
Bernhard


(rr) bt
#0  0x00007fd71a387f25 in __vfscanf_internal (s=<optimized out>, format=<optimized 
out>, argptr=argptr@entry=0x7ffde7e7a7d0, mode_flags=mode_flags@entry=2) at 
./stdio-common/vfscanf-internal.c:3020
#1  0x00007fd71a3785e9 in __isoc99_fscanf (stream=stream@entry=0x562293989350, 
format=format@entry=0x562255d75078 " %20[^:]:%llu %llu %llu %llu %llu %llu %llu %llu 
%llu %llu %llu %llu %llu %llu %llu %llu") at ./stdio-common/isoc99_fscanf.c:30
#2  0x0000562255d73d78 in get_stats (iface=iface@entry=0x7ffde7e7bdc9 
"enx405400123457") at ./ifdata.c:291
#3  0x0000562255d732e5 in main (argc=3, argv=0x7ffde7e7ab68) at ./ifdata.c:576
From ba05f7e0f7e5a1037ee2ad692dae59c47e86e42a Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Bernhard=20=C3=9Cbelacker?= <[email protected]>
Date: Tue, 16 Sep 2025 15:05:48 +0200
Subject: [PATCH] ifdata: Fix stack smashing by fscanf in get_stats. (Closes:
 #1107470)

Debian-Bug: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=1107470
---
 ifdata.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/ifdata.c b/ifdata.c
index 6e0bd0b..4f5d801 100644
--- a/ifdata.c
+++ b/ifdata.c
@@ -270,7 +270,7 @@ static void skipline(FILE *fd) {
 struct if_stat *get_stats(const char *iface) {
 	FILE *fd;
 	struct if_stat *ifstat;
-	char name[10];
+	char name[20];
 
 	if (!(ifstat = malloc(sizeof(struct if_stat)))) {
 		perror("malloc");
-- 
2.47.3

# minimal Trixie/stable amd64 qemu VM 2025-09-16

(qemu) device_add usb-net,id=usb-net1

apt install moreutils moreutils-dbgsym valgrind gdb rr mc git
apt build-dep moreutils


mkdir /home/benutzer/source/moreutils/orig -p
cd    /home/benutzer/source/moreutils/orig
apt source moreutils


root@debian:~# ifdata -si enx405400123457
*** stack smashing detected ***: terminated
Abgebrochen
root@debian:~#

root@debian:~# rr record ifdata -si enx405400123457
rr: Saving execution to trace directory `/root/.local/share/rr/ifdata-0'.
*** stack smashing detected ***: terminated
Abgebrochen
root@debian:~#

root@debian:~# rr replay -a ifdata-0
*** stack smashing detected ***: terminated
root@debian:~#

rr replay --debugger-option=-q ifdata-0
directory /home/benutzer/source/moreutils/orig/moreutils-0.69
set width 0
set pagination off
display/i $pc
cont
bt

root@debian:~# rr replay --debugger-option=-q ifdata-0
Reading symbols from /root/.local/share/rr/ifdata-0/mmap_hardlink_4_ifdata...
Reading symbols from 
/usr/lib/debug/.build-id/7f/8a0189b2e434757dfab0a88e0a371c575dc2c5.debug...
Remote debugging using 127.0.0.1:2805
Reading symbols from /lib64/ld-linux-x86-64.so.2...
Reading symbols from 
/usr/lib/debug/.build-id/da/08404553b441511cbee6b34bc78fe29fd5d14c.debug...
warning: BFD: warning: system-supplied DSO at 0x6fffd000 has a section 
extending past end of file
warning: Discarding section .replay.text which has an invalid size (27) [in 
module system-supplied DSO at 0x6fffd000]
0x00007fd71a555440 in _start () from /lib64/ld-linux-x86-64.so.2
(rr) directory /home/benutzer/source/moreutils/orig/moreutils-0.69
Source directories searched: 
/home/benutzer/source/moreutils/orig/moreutils-0.69:$cdir:$cwd
(rr) set width 0
(rr) set pagination off
(rr) display/i $pc
1: x/i $pc
=> 0x7fd71a555440 <_start>:     mov    %rsp,%rdi
(rr) cont
Continuing.
*** stack smashing detected ***: terminated

Program received signal SIGABRT, Aborted.
__pthread_kill_implementation (threadid=<optimized out>, signo=signo@entry=6, 
no_tid=no_tid@entry=0) at ./nptl/pthread_kill.c:44
warning: 44     ./nptl/pthread_kill.c: Datei oder Verzeichnis nicht gefunden
1: x/i $pc
=> 0x7fd71a3b395c <__pthread_kill_implementation+268>:  mov    %eax,%ebx
(rr) bt
#0  __pthread_kill_implementation (threadid=<optimized out>, 
signo=signo@entry=6, no_tid=no_tid@entry=0) at ./nptl/pthread_kill.c:44
#1  0x00007fd71a3b39ff in __pthread_kill_internal (threadid=<optimized out>, 
signo=6) at ./nptl/pthread_kill.c:89
#2  0x00007fd71a35ecc2 in __GI_raise (sig=sig@entry=6) at 
../sysdeps/posix/raise.c:26
#3  0x00007fd71a3474ac in __GI_abort () at ./stdlib/abort.c:73
#4  0x00007fd71a348291 in __libc_message_impl (fmt=fmt@entry=0x7fd71a4ca1a4 
"*** %s ***: terminated\n") at ../sysdeps/posix/libc_fatal.c:134
#5  0x00007fd71a43a995 in __GI___fortify_fail (msg=msg@entry=0x7fd71a4ca1bc 
"stack smashing detected") at ./debug/fortify_fail.c:24
#6  0x00007fd71a43bbb0 in __stack_chk_fail () at ./debug/stack_chk_fail.c:24
#7  0x0000562255d73e0c in get_stats (iface=iface@entry=0x7ffde7e7bdc9 
"enx405400123457") at ./ifdata.c:321
#8  0x0000562255d732e5 in main (argc=3, argv=0x7ffde7e7ab68) at ./ifdata.c:576
(rr) b get_stats
Breakpoint 1 at 0x562255d73bd0: file ./ifdata.c, line 270.
(rr) reverse-cont
Continuing.

Program received signal SIGABRT, Aborted.
__pthread_kill_implementation (threadid=<optimized out>, signo=signo@entry=6, 
no_tid=no_tid@entry=0) at ./nptl/pthread_kill.c:44
44      in ./nptl/pthread_kill.c
1: x/i $pc
=> 0x7fd71a3b395c <__pthread_kill_implementation+268>:  mov    %eax,%ebx
(rr) reverse-cont
Continuing.

Breakpoint 1, get_stats (iface=iface@entry=0x7ffde7e7bdc9 "enx405400123457") at 
./ifdata.c:270
270     struct if_stat *get_stats(const char *iface) {
1: x/i $pc
=> 0x562255d73bd0 <get_stats>:  endbr64
(rr) stepi
0x0000562255d73bd4      270     struct if_stat *get_stats(const char *iface) {
1: x/i $pc
=> 0x562255d73bd4 <get_stats+4>:        push   %r15
(rr) 
0x0000562255d73bd6      270     struct if_stat *get_stats(const char *iface) {
1: x/i $pc
=> 0x562255d73bd6 <get_stats+6>:        push   %r14
(rr) 
0x0000562255d73bd8      270     struct if_stat *get_stats(const char *iface) {
1: x/i $pc
=> 0x562255d73bd8 <get_stats+8>:        push   %r13
(rr) 
0x0000562255d73bda      270     struct if_stat *get_stats(const char *iface) {
1: x/i $pc
=> 0x562255d73bda <get_stats+10>:       push   %r12
(rr) 
0x0000562255d73bdc      270     struct if_stat *get_stats(const char *iface) {
1: x/i $pc
=> 0x562255d73bdc <get_stats+12>:       push   %rbp
(rr) 
0x0000562255d73bdd      270     struct if_stat *get_stats(const char *iface) {
1: x/i $pc
=> 0x562255d73bdd <get_stats+13>:       push   %rbx
(rr) 
0x0000562255d73bde      270     struct if_stat *get_stats(const char *iface) {
1: x/i $pc
=> 0x562255d73bde <get_stats+14>:       sub    $0x98,%rsp
(rr) 
0x0000562255d73be5      270     struct if_stat *get_stats(const char *iface) {
1: x/i $pc
=> 0x562255d73be5 <get_stats+21>:       mov    %rdi,0x60(%rsp)
(rr) 
0x0000562255d73bea      275             if (!(ifstat = malloc(sizeof(struct 
if_stat)))) {
1: x/i $pc
=> 0x562255d73bea <get_stats+26>:       mov    $0x80,%edi
(rr) 
0x0000562255d73bef      270     struct if_stat *get_stats(const char *iface) {
1: x/i $pc
=> 0x562255d73bef <get_stats+31>:       mov    %fs:0x28,%rax
(rr) 
0x0000562255d73bf8      270     struct if_stat *get_stats(const char *iface) {
1: x/i $pc
=> 0x562255d73bf8 <get_stats+40>:       mov    %rax,0x88(%rsp)
(rr) x/1xg $rsp + 0x88
0x7ffde7e7a9a8: 0x000000000000000d
(rr) watch *0x7ffde7e7a9a8
Hardware watchpoint 2: *0x7ffde7e7a9a8
(rr) stepi

Hardware watchpoint 2: *0x7ffde7e7a9a8

Old value = 13
New value = -763956224
0x0000562255d73c00 in get_stats (iface=iface@entry=0x7ffde7e7bdc9 
"enx405400123457") at ./ifdata.c:270
270     struct if_stat *get_stats(const char *iface) {
1: x/i $pc
=> 0x562255d73c00 <get_stats+48>:       xor    %eax,%eax
(rr) cont
Continuing.

Hardware watchpoint 2: *0x7ffde7e7a9a8

Old value = -763956224
New value = -763956174
0x00007fd71a387f25 in __vfscanf_internal (s=<optimized out>, format=<optimized 
out>, argptr=argptr@entry=0x7ffde7e7a7d0, mode_flags=mode_flags@entry=2) at 
./stdio-common/vfscanf-internal.c:3020
warning: 3020   ./stdio-common/vfscanf-internal.c: Datei oder Verzeichnis nicht 
gefunden
1: x/i $pc
=> 0x7fd71a387f25 <__vfscanf_internal+16053>:   lea    0x1(%rbx),%rax
(rr) bt
#0  0x00007fd71a387f25 in __vfscanf_internal (s=<optimized out>, 
format=<optimized out>, argptr=argptr@entry=0x7ffde7e7a7d0, 
mode_flags=mode_flags@entry=2) at ./stdio-common/vfscanf-internal.c:3020
#1  0x00007fd71a3785e9 in __isoc99_fscanf (stream=stream@entry=0x562293989350, 
format=format@entry=0x562255d75078 " %20[^:]:%llu %llu %llu %llu %llu %llu %llu 
%llu %llu %llu %llu %llu %llu %llu %llu %llu") at 
./stdio-common/isoc99_fscanf.c:30
#2  0x0000562255d73d78 in get_stats (iface=iface@entry=0x7ffde7e7bdc9 
"enx405400123457") at ./ifdata.c:291
#3  0x0000562255d732e5 in main (argc=3, argv=0x7ffde7e7ab68) at ./ifdata.c:576
(rr) frame 2
#2  0x0000562255d73d78 in get_stats (iface=iface@entry=0x7ffde7e7bdc9 
"enx405400123457") at ./ifdata.c:291
291                     int items = fscanf(fd,
(rr) list
286             /* Skip header */
287             skipline(fd);
288             skipline(fd);
289
290             do {
291                     int items = fscanf(fd,
292                             " %20[^:]:%llu %llu %llu %llu %llu %llu %llu 
%llu "
293                             "%llu %llu %llu %llu %llu %llu %llu %llu",
294                             name,
295                             &ifstat->in_bytes,    &ifstat->in_packets,
(rr) print sizeof(name)
$1 = 10
(rr)


https://git.kitenet.net/index.cgi/moreutils.git/tree/ifdata.c#n273
https://git.kitenet.net/index.cgi/moreutils.git/tree/ifdata.c#n291

Reply via email to