On Tue, Dec 12 2017, Patrick Wildt <patr...@blueri.se> wrote:
> 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().

... and then cmsg handling should update *tolen.

>> Opinions?

The getsockname(2) doesn't seem to perform anything useful: the ikev2
process gets a fully initialized sockaddr (len, family, address,
port) along with the socket, and recvfromto() could just care about
filling the address using cmsg parsing.

>> 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.

ok jca@ for socket_getaddr(), also ok for recvfromto() since the code is
confusing as is, but if I'm not mistaken we could just remove the
getsockname(2) call.

> 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;
>

-- 
jca | PGP : 0x1524E7EE / 5135 92C1 AD36 5293 2BDF  DDCC 0DFA 74AE 1524 E7EE

Reply via email to