On Tue, Dec 12, 2017 at 03:32:50PM +0100, Patrick Wildt wrote:
> On Wed, Nov 29, 2017 at 07:50:21PM +0100, Claudio Jeker wrote:
> > More or less. It seems that msg_local is garbage:
> > $3 = {msg_data = 0x1b4e541fa4c0, msg_offset = 0, msg_local = {
> >     ss_len = 128 '\200', ss_family = 192 'À', 
> >     __ss_pad1 = 0x7f7ffffda8c2 "Ì]\001", __ss_pad2 = 30024042514159, 
> >     __ss_pad3 = 0x7f7ffffda8d0 "Ьýÿ\177\177"}, msg_locallen = 128, 
> >   msg_peer = {ss_len = 16 '\020', ss_family = 2 '\002', 
> >     __ss_pad1 = 0x7f7ffffda9ca "\001ô>0\036\005", __ss_pad2 = 0, 
> >     __ss_pad3 = 0x7f7ffffda9d8 ""}, msg_peerlen = 16, 
> > 
> > Why so I don't know.
> 
> I found it.  socket_getaddr is called to retrieve information about the
> socket behind the file descriptor.  If I understand correctly, we need
> to pass the length of the struct to getsockname() so that it knows how
> far it can fill the struct.  So far we always passed stack garbage, so
> sometimes it worked, sometimes not.  Then getsockname() does not change
> the struct, so sockaddr_storage ss is still stack garbarge, and that
> ends up in msg_local.
> 
> I think recvfromto() suffers the same.  The caller ikev2_msg_cb() does
> pass the correct size to recvfromto(), but then recvfromto() uncondi-
> tionally overwrites it with zero before calling getsockname().
> 
> Opinions?
> 
> Patrick

Markus points out that socket_getaddr() is promised a pointer to a
sockaddr_storage, so we don't need to pass the length and can just
initialize sslen correctly.

diff --git a/sbin/iked/util.c b/sbin/iked/util.c
index 1d4cee2c424..e67dae27d8a 100644
--- a/sbin/iked/util.c
+++ b/sbin/iked/util.c
@@ -93,7 +93,7 @@ socket_setport(struct sockaddr *sa, in_port_t port)
 int
 socket_getaddr(int s, struct sockaddr_storage *ss)
 {
-       socklen_t sslen;
+       socklen_t sslen = sizeof(*ss);
 
        return (getsockname(s, (struct sockaddr *)ss, &sslen));
 }
@@ -366,7 +366,6 @@ recvfromto(int s, void *buf, size_t len, int flags, struct 
sockaddr *from,
                return (-1);
 
        *fromlen = from->sa_len;
-       *tolen = 0;
 
        if (getsockname(s, to, tolen) != 0)
                *tolen = 0;

Reply via email to