Current-Users archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
Re: Regression on rtadvd (was: Re: CVS commit: src/usr.sbin/rtadvd)
On Mon, Jun 15, 2015 at 5:58 AM, Timo Buhrmester <fstd.lkml%gmail.com@localhost> wrote:
>> Module Name: src
>> Committed By: roy
>> Date: Fri Jun 5 14:15:41 UTC 2015
>>
>> Modified Files:
>> src/usr.sbin/rtadvd: rtadvd.c
>>
>> Log Message:
>> Set the hoplimit of 255 as specified in RFC 4861 section 4.2
>> using the IPV6_MULTICAST_HOPS socket option rather than using CMSG
>> when constructing each message.
> This commit broke rtadvd for me, on i386, which now gives "Invalid argument" on the call to sendmsg() that is supposed to generate RAs.
>
> Here's two gdb transcripts:
>
> This is what happens AFTER the offending commit:
>
> | # gdb -q rtadvd
> | (gdb) break rtadvd.c:1699
> | (gdb) run -df vr1
> | [...]
> | Breakpoint 1, ra_output (rai=0xbb91c0e0) at /usr/src.head/usr.sbin/rtadvd/rtadvd.c:1699
> | 1699 i = sendmsg(sock, &sndmhdr, 0);
> | (gdb) bt
> | #0 ra_output (rai=0xbb91c0e0) at /usr/src.head/usr.sbin/rtadvd/rtadvd.c:1699
> | #1 0x0804cdbf in ra_timeout (data=0xbb91c0e0) at /usr/src.head/usr.sbin/rtadvd/rtadvd.c:1779
> | #2 0x08052610 in rtadvd_check_timer () at /usr/src.head/usr.sbin/rtadvd/timer.c:130
> | #3 0x080499c0 in main (argc=-1, argv=0xbfbfec64) at /usr/src.head/usr.sbin/rtadvd/rtadvd.c:315
> | (gdb) x/28xb &sndmhdr
> | 0x8058b2c <sndmhdr>: 0x40 0x7e 0x05 0x08 0x1c 0x00 0x00 0x00
> | 0x8058b34 <sndmhdr+8>: 0xc4 0x8a 0x05 0x08 0x01 0x00 0x00 0x00
> | 0x8058b3c <sndmhdr+16>: 0xd0 0xa0 0x90 0xbb 0x30 0x00 0x00 0x00
> | 0x8058b44 <sndmhdr+24>: 0x00 0x00 0x00 0x00
> | (gdb) n
> | 1701 if (i < 0 || (size_t)i != rai->ra_datalen) {
> | (gdb) print i
> | $1 = -1
> | (gdb) n
> | [...]
> | rtadvd[3794]: <ra_output> sendmsg on vr1: Invalid argument
>
>
>
> The following is what it looked like BEFORE the offending commit:
>
> | # gdb -q rtadvd
> | (gdb) break rtadvd.c:1702
> | (gdb) run -df vr1
> | [...]
> | Breakpoint 1, ra_output (rai=0xbb91c0e0) at /usr/src.head/usr.sbin/rtadvd/rtadvd.c:1702
> | 1702 i = sendmsg(sock, &sndmhdr, 0);
> | (gdb) bt
> | #0 ra_output (rai=0xbb91c0e0) at /usr/src.head/usr.sbin/rtadvd/rtadvd.c:1702
> | #1 0x0804cdcf in ra_timeout (data=0xbb91c0e0) at /usr/src.head/usr.sbin/rtadvd/rtadvd.c:1782
> | #2 0x08052620 in rtadvd_check_timer () at /usr/src.head/usr.sbin/rtadvd/timer.c:130
> | #3 0x080499c0 in main (argc=-1, argv=0xbfbfec64) at /usr/src.head/usr.sbin/rtadvd/rtadvd.c:315
> | (gdb) x/28xb &sndmhdr
> | 0x8058b0c <sndmhdr>: 0x20 0x7e 0x05 0x08 0x1c 0x00 0x00 0x00
> | 0x8058b14 <sndmhdr+8>: 0xa4 0x8a 0x05 0x08 0x01 0x00 0x00 0x00
> | 0x8058b1c <sndmhdr+16>: 0xd0 0xa0 0x90 0xbb 0x30 0x00 0x00 0x00
> | 0x8058b24 <sndmhdr+24>: 0x00 0x00 0x00 0x00
> | (gdb) n
> | 1704 if (i < 0 || (size_t)i != rai->ra_datalen) {
> | (gdb) print i
> | $2 = 56
>
>
>
> The difference in the representations of `sndmhdr` are in the 1st and 9th byte, which on i386 correspond to the 1st and 3rd members of struct sndhdr:
> | void *msg_name; /* optional address */
> | and struct iovec *msg_iov; /* scatter/gather array */
>
>
> I've manually tracked the failing code path down through the sendmsg system call:
> sys/kern/uipc_syscalls.c:620 do_sys_sendmsg_so() ``error = (*so->so_send)(so, sa, &auio, NULL, control, flags, l);''
> sys/kern/uipc_socket.c:1602 sosend() ``error = (*so->so_proto->pr_usrreqs->pr_send)(so, top, addr, control, l);''
> sys/netinet6/raw_ip6.c:891 rip6_send() ``error = rip6_output(m, so, dst, control);''
> sys/netinet6/raw_ip6.c:391 rip6_output() ``if ((error = ip6_setpktopts(control, &opt, [...]''
> sys/netinet6/ip6_output.c:2705 ip6_setpktopts() ``if (cm->cmsg_len == 0 || cm->cmsg_len > control->m_len)''
>
> The last function is where the EINVAL is produced, due to cm->cmsg_len being zero (in the 2nd iteration of the enclosing loop)
> Unfortunately, I couldn't figure out what's supposed to happen there.
>
>
> Any ideas?
It seems that the kernel attempts to read non-existent cmsg
which was removed by the commit. Can you try the below patch?
It reduces cmsg buffer length as hoplimit cmsg is removed.
ozaki-r
diff --git a/usr.sbin/rtadvd/rtadvd.c b/usr.sbin/rtadvd/rtadvd.c
index 66885c4..f2016eb 100644
--- a/usr.sbin/rtadvd/rtadvd.c
+++ b/usr.sbin/rtadvd/rtadvd.c
@@ -1503,8 +1503,7 @@ sock_open(void)
exit(1);
}
- sndcmsgbuflen = CMSG_SPACE(sizeof(struct in6_pktinfo)) +
- CMSG_SPACE(sizeof(int));
+ sndcmsgbuflen = CMSG_SPACE(sizeof(struct in6_pktinfo));
sndcmsgbuf = malloc(sndcmsgbuflen);
if (sndcmsgbuf == NULL) {
syslog(LOG_ERR, "<%s> malloc: %m", __func__);
Home |
Main Index |
Thread Index |
Old Index