Hi Vincent,

On Wed, May 18, 2016 at 09:58:33AM +0200, Vincent Bernat wrote:
>  ??? 15 mai 2016 09:55 +0200, Vincent Bernat <ber...@luffy.cx> :
> 
> >> I suppose that some new features of gcc started to rely on the
> >> strict-aliasing rule without taking -fno-strict-aliasing into
> >> consideration. I didn't find anything in the bugzilla, but it's easy to
> >> miss something as there are about 500 bugs opened about aliasing.
> >>
> >> I'll open a bug about this.
> >
> > Here is the bug:
> >  https://gcc.gnu.org/bugzilla/show_bug.cgi?id=71120
> >
> > With luck, we should get some pointers on why and how.
> 
> So, it appears this is not a bug in GCC and it is not an aliasing
> problem but the fact that the compiler doesn't have to use memcpy() to
> copy the struct, but can copy individual member, padding excluded.

Yes, this is even a security problem which painfully affects the kernel.

> And sin_addr would be in the padding, so not copied.

That makes sense then.

> A bug has been filed
> for the glibc since the bug is in the definition:
> 
>  https://sourceware.org/bugzilla/show_bug.cgi?id=20111

Great, thanks for the link and going through this. As was mentionned
there, sockaddr_storage is expected by users and in literature to be
able to carry other addresses.

> We could either use an union like discussed previously or locally fix
> this with a memcpy(). I suppose the union would be a longer term (and
> safer since we can be exhaustive about it) fix but far more invasive.

I have the same feeling, but it would make a few switch/case occurences
cleaner or at least more explicit. For the short term and backports I
guess only memcpy() will be usable, so we should probably start by this,
backport it, then work on changing all this to a union.

> I suspect there are other uses of sockaddr_storage that could lead to
> some bugs.

If there is one, there are many.

> For example, connection.c:747. ss_family will be set to 0,
> but eventual port and address can be random. However, it seems that in
> the remaining of the code, only ss_family is important. But maybe, it
> would be better to use memset() here.

Good point.

Maybe we would need to develop a few macros (or inline functions) to
manipulate sockaddr_storage. We already have a few, I don't think we
need that many. set_port, set_addr, set_family, copy_addr and I don't
know what.

> On the other hand, on proto_tcp.c:225, bind_addr is correctly zeroed out
> with memset. Same on standard.c:829.
> 
> I also note on proto_http.c:3192, a "struct sockaddr_storage from" that
> may be more safe to replace by "struct sockaddr_storage *from" since it
> is used read-only. But maybe the compiler is smart enough to not do a
> copy and therefore the bug is not triggered here.

I didn't notice this one, good catch. It should even be a const.

> I didn't review all uses, only uses of "struct sockaddr_storage
> something". I should check for "struct sockaddr_storage *something" and
> eventual use of "*something =", but I suspect that it doesn't exist
> without a "struct sockaddr_storage something_else" around.

I think that once we get rid of *all* sockaddr_storage we'll find them
all :-)

> So, quick fix is a memcpy() in cfgparse.c and in proto_http.c:3192 and
> using memset() in connection.c:747 for consistency (so that somebody
> doesn't copy this code for something more general).
> 
> Can do the patches but union would be more work.

That works for me. Let's have Arthur test them to confirm the issue goes
away for him.

Thanks!
Willy


Reply via email to