Bug 28349 - Segfault for ping -R on qemux86 caused by recvmsg()
Summary: Segfault for ping -R on qemux86 caused by recvmsg()
Status: RESOLVED FIXED
Alias: None
Product: glibc
Classification: Unclassified
Component: libc (show other bugs)
Version: 2.34
: P2 normal
Target Milestone: 2.35
Assignee: Adhemerval Zanella
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2021-09-18 06:18 UTC by Yi Zhao
Modified: 2022-01-28 21:21 UTC (History)
5 users (show)

See Also:
Host:
Target:
Build:
Last reconfirmed:
Project(s) to access:
ssh public key:
fweimer: security-


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Yi Zhao 2021-09-18 06:18:01 UTC
We encountered a segfault for ping -R on Yocto qemux86 (i686) with glibc 2.34.

Kernel: 5.10 and 5.13
Glibc: 2.34
ping: iputils-20210722


When the kernel parmameter net.ipv4.ping_group_range is disabled, the ping -R works well:

root@qemux86:~# cat /proc/sys/net/ipv4/ping_group_range
1       0
root@qemux86:~# uname -a
Linux qemux86 5.10.53-yocto-standard #1 SMP PREEMPT Sun Jul 25 15:15:01 UTC 2021 i686 i686 i386 GNU/Linux
root@qemux86:~#
root@qemux86:~# ping -c1 -R 127.0.0.1
PING 127.0.0.1 (127.0.0.1) 56(124) bytes of data.
64 bytes from 127.0.0.1: icmp_seq=1 ttl=64 time=0.028 ms
RR:     127.0.0.1
        127.0.0.1
        127.0.0.1
        127.0.0.1


--- 127.0.0.1 ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 0.028/0.028/0.028/0.000 ms


However, the segfault occurs when net.ipv4.ping_group_range is enabled:

root@qemux86:~# echo "0    2147483647" >  /proc/sys/net/ipv4/ping_group_range
root@qemux86:~# 
root@qemux86:~# cat /proc/sys/net/ipv4/ping_group_range 
0       2147483647
root@qemux86:~# 
root@qemux86:~# ping -R 127.0.0.1
PING 127.0.0.1 (127.0.0.1) 56(124) bytes of data.
Segmentation fault
root@qemux86:~# 

This issue is introduced by glibc commit 13c51549e2077f2f3bf84e8fd0b46d8b0c615912:

commit 13c51549e2077f2f3bf84e8fd0b46d8b0c615912
Author: Adhemerval Zanella <adhemerval.zanella@linaro.org>
Date:   Mon Sep 7 17:08:46 2020 -0300

    linux: Add fallback for 64-bit time_t SO_TIMESTAMP{NS}
    

Here are some gdb outputs:

$ gdb ping
Reading symbols from ping...
Reading symbols from /bin/.debug/ping.iputils...
(gdb) set args -R 127.0.0.1
(gdb) b main_loop
Breakpoint 1 at 0x8510: file ../git/ping/ping_common.c, line 558.
(gdb) r
Starting program: /bin/ping -R 127.0.0.1
PING 127.0.0.1 (127.0.0.1) 56(124) bytes of data.

Breakpoint 1, main_loop (rts=0xbfffca30, fset=0x414068 <ping4_func_set>, sock=0xbfffca00, packet=0x416310 "", packlen=192) at ../git/ping/ping_common.c:558
558     {
(gdb) n
572                     if (rts->exiting)
(gdb) 
574                     if (rts->npackets && rts->nreceived + rts->nerrors >= rts->npackets)
(gdb) 
576                     if (rts->deadline && rts->nerrors)
(gdb) 
579                     if (rts->status_snapshot)
(gdb) 
584                             next = pinger(rts, fset, sock);
(gdb) 
585                             next = schedule_exit(rts, next);
(gdb) 
586                     } while (next <= 0);
(gdb) 
600                     if (rts->opt_adaptive || rts->opt_flood_poll || next < SCHINT(rts->interval)) {
(gdb) 
641                             iov.iov_len = packlen;
(gdb) 
642                             memset(&msg, 0, sizeof(msg));
(gdb) 
643                             msg.msg_name = addrbuf;
(gdb) 
645                             msg.msg_iov = &iov;
(gdb) 
647                             msg.msg_control = ans_data;
(gdb) 
650                             cc = recvmsg(sock->fd, &msg, polling);
(gdb) p msg
$1 = {msg_name = 0xbfffb3dc, msg_namelen = 128, msg_iov = 0xbfffb3b0, msg_iovlen = 1, msg_control = 0xbfffb45c, msg_controllen = 4096, msg_flags = 0}
(gdb) s
__libc_recvmsg (fd=3, msg=0xbfffb3c0, flags=0) at ../sysdeps/unix/sysv/linux/recvmsg.c:25
25      {
(gdb) n
28        socklen_t orig_controllen = msg != NULL ? msg->msg_controllen : 0;
(gdb) n
34        r = SOCKETCALL_CANCEL (recvmsg, fd, msg, flags);
(gdb) p *msg
$2 = {msg_name = 0xbfffb3dc, msg_namelen = 128, msg_iov = 0xbfffb3b0, msg_iovlen = 1, msg_control = 0xbfffb45c, msg_controllen = 4096, msg_flags = 0}
(gdb) n
38        if (r >= 0 && orig_controllen != 0)
(gdb) p *msg
$3 = {msg_name = 0xbfffb3dc, msg_namelen = 16, msg_iov = 0xbfffb3b0, msg_iovlen = 1, msg_control = 0xbfffb45c, msg_controllen = 88, msg_flags = 0}
(gdb) n
39          __convert_scm_timestamps (msg, orig_controllen);
(gdb) n
42        return r;
(gdb) p *msg
$4 = {msg_name = 0xbfffb3dc, msg_namelen = 16, msg_iov = 0xbfffb3b0, msg_iovlen = 1, msg_control = 0xbfffb45c, msg_controllen = 116, msg_flags = 0}
(gdb) n
main_loop (rts=0xbfffca30, fset=0x414068 <ping4_func_set>, sock=0xbfffca00, packet=0x416310 "", packlen=192) at ../git/ping/ping_common.c:653
653                             if (cc < 0) {
(gdb) n
674                                     for (c = CMSG_FIRSTHDR(&msg); c; c = CMSG_NXTHDR(&msg, c)) {
(gdb) n
675                                             if (c->cmsg_level != SOL_SOCKET ||
(gdb) p *c
$5 = {cmsg_len = 20, cmsg_level = 1, cmsg_type = 29, __cmsg_data = 0xbfffb468 "$}Ea\327`"}
(gdb) n
678                                             if (c->cmsg_len < CMSG_LEN(sizeof(struct timeval)))
(gdb) n
680                                             recv_timep = (struct timeval *)CMSG_DATA(c);
(gdb) n
674                                     for (c = CMSG_FIRSTHDR(&msg); c; c = CMSG_NXTHDR(&msg, c)) {
(gdb) n
675                                             if (c->cmsg_level != SOL_SOCKET ||
(gdb) p *c
$6 = {cmsg_len = 28, cmsg_level = 1, cmsg_type = 63, __cmsg_data = 0xbfffb47c "$}Ea"}
(gdb) n
674                                     for (c = CMSG_FIRSTHDR(&msg); c; c = CMSG_NXTHDR(&msg, c)) {
(gdb) n
675                                             if (c->cmsg_level != SOL_SOCKET ||
(gdb) p *c
$7 = {cmsg_len = 2132027143, cmsg_level = 2130771968, cmsg_type = 2130771968, __cmsg_data = 0xbfffb498 ""}
(gdb) n
674                                     for (c = CMSG_FIRSTHDR(&msg); c; c = CMSG_NXTHDR(&msg, c)) {
(gdb) n

Program received signal SIGSEGV, Segmentation fault.
0x00408925 in __cmsg_nxthdr (__cmsg=0x3f13db94, __mhdr=0xbfffb3c0) at /usr/include/bits/socket.h:322
322           || ((unsigned char *) __cmsg + CMSG_ALIGN (__cmsg->cmsg_len)
(gdb)
Comment 1 Fabian Vogt 2021-12-15 09:23:46 UTC
I encountered the same bug and narrowed it down to recvmsg corrupting the cmsg buffer due to several bugs in the added __convert_scm_timestamps function. I'm working on a patch to address those.
Comment 2 Florian Weimer 2021-12-15 10:09:39 UTC
(In reply to Fabian Vogt from comment #1)
> I encountered the same bug and narrowed it down to recvmsg corrupting the
> cmsg buffer due to several bugs in the added __convert_scm_timestamps
> function. I'm working on a patch to address those.

Would you be able to help reviewing these patches?

[PATCH v3 0/2] Fix 64-bit time_t ancillary socket conversion
https://sourceware.org/pipermail/libc-alpha/2021-December/134088.html

I believe they are related.
Comment 3 Fabian Vogt 2021-12-15 10:12:26 UTC
(In reply to Florian Weimer from comment #2)
> (In reply to Fabian Vogt from comment #1)
> > I encountered the same bug and narrowed it down to recvmsg corrupting the
> > cmsg buffer due to several bugs in the added __convert_scm_timestamps
> > function. I'm working on a patch to address those.
> 
> Would you be able to help reviewing these patches?
> 
> [PATCH v3 0/2] Fix 64-bit time_t ancillary socket conversion
> https://sourceware.org/pipermail/libc-alpha/2021-December/134088.html
> 
> I believe they are related.

The linked patch fixes one of the bugs I found, but not another one. What's the way to proceed there, send a patch with just the missing fix?
Comment 4 Fabian Vogt 2021-12-15 10:13:52 UTC
BTW: After clicking on "Save Changes" to add a comment on this bug, I end up on the page for bug 28350 for some reason. Does anyone else have that weird behaviour?
Comment 5 Florian Weimer 2021-12-15 10:19:40 UTC
(In reply to Fabian Vogt from comment #3)
> (In reply to Florian Weimer from comment #2)
> > (In reply to Fabian Vogt from comment #1)
> > > I encountered the same bug and narrowed it down to recvmsg corrupting the
> > > cmsg buffer due to several bugs in the added __convert_scm_timestamps
> > > function. I'm working on a patch to address those.
> > 
> > Would you be able to help reviewing these patches?
> > 
> > [PATCH v3 0/2] Fix 64-bit time_t ancillary socket conversion
> > https://sourceware.org/pipermail/libc-alpha/2021-December/134088.html
> > 
> > I believe they are related.
> 
> The linked patch fixes one of the bugs I found, but not another one. What's
> the way to proceed there, send a patch with just the missing fix?

Comment on the mailing list thread and take it from there, I would say.


(In reply to Fabian Vogt from comment #4)
> BTW: After clicking on "Save Changes" to add a comment on this bug, I end up
> on the page for bug 28350 for some reason. Does anyone else have that weird
> behaviour?

By default, Bugzilla switches to the next bug in your search results. It's something you can configure under Preferences (under “After changing a bug”).
Comment 6 Fabian Vogt 2021-12-15 13:53:59 UTC
(In reply to Florian Weimer from comment #5)
> (In reply to Fabian Vogt from comment #3)
> > (In reply to Florian Weimer from comment #2)
> > > (In reply to Fabian Vogt from comment #1)
> > > > I encountered the same bug and narrowed it down to recvmsg corrupting the
> > > > cmsg buffer due to several bugs in the added __convert_scm_timestamps
> > > > function. I'm working on a patch to address those.
> > > 
> > > Would you be able to help reviewing these patches?
> > > 
> > > [PATCH v3 0/2] Fix 64-bit time_t ancillary socket conversion
> > > https://sourceware.org/pipermail/libc-alpha/2021-December/134088.html
> > > 
> > > I believe they are related.
> > 
> > The linked patch fixes one of the bugs I found, but not another one. What's
> > the way to proceed there, send a patch with just the missing fix?
> 
> Comment on the mailing list thread and take it from there, I would say.

Done: https://sourceware.org/pipermail/libc-alpha/2021-December/134193.html

> (In reply to Fabian Vogt from comment #4)
> > BTW: After clicking on "Save Changes" to add a comment on this bug, I end up
> > on the page for bug 28350 for some reason. Does anyone else have that weird
> > behaviour?
> 
> By default, Bugzilla switches to the next bug in your search results. It's
> something you can configure under Preferences (under “After changing a bug”).

Thanks! What a strange default. My last search was from a day ago...
Comment 7 Adhemerval Zanella 2022-01-28 21:21:39 UTC
Fixed on 2.35.