Re: [PATCH v3 1/9] net: Add struct sockaddr_unspec for sockaddr of unknown length

From
David Laight <hidden>
Date
2025-10-22 09:26:28
Also in
bpf, linux-hardening, lkml
Reply to
Kees Cook, 2025-10-21
On Tue, 21 Oct 2025 12:42:10 -0700
Kees Cook [off-list ref] wrote:
On Tue, Oct 21, 2025 at 10:26:00AM +0100, David Laight wrote:
quoted
On Mon, 20 Oct 2025 14:26:30 -0700
Kees Cook [off-list ref] wrote:
  
quoted
Add flexible sockaddr structure to support addresses longer than the
traditional 14-byte struct sockaddr::sa_data limitation without
requiring the full 128-byte sa_data of struct sockaddr_storage. This
allows the network APIs to pass around a pointer to an object that
isn't lying to the compiler about how big it is, but must be accompanied
by its actual size as an additional parameter.

It's possible we may way to migrate to including the size with the
struct in the future, e.g.:

struct sockaddr_unspec {
	u16 sa_data_len;
	u16 sa_family;
	u8  sa_data[] __counted_by(sa_data_len);
};  
One on the historic Unix implementations split the 'sa_family'
field into two single byte fields - the second one containing the length.
That might work - although care would be needed not to pass a length
back to userspace.  
I think this is just asking for trouble -- leaving that inline could
be hard to track down places that needed filtering out.

It might be easier to move to a separate struct like I suggest above,
though maybe as:

struct sockaddr_sized {
    u16 sa_data_len;
    struct {
        u16 sa_family;
        u8  sa_data[] __counted_by(sa_data_len);
    } sa_unspec;
};

(So it's easier to cast between implementation-specific sockaddr and the
"sa_unspec" member.)

And then pass that around. But I think that'll require a LOT of
refactoring. But that could happen separately from this change, which is
to just get us back to the existing state of passing around an unknown
sized object but now we're not lying to the compiler about its size.
The problem with that is it misaligns things later on.
And you really want to be using the length from the user,
which includes sa_family.

I'm not sure it even works if the extra sa_data_len is u32 (or even u64).

I did wonder if 'union casts' would help.
They would require a union of pointers to all possible sockaddr formats.
Annoyingly I don't think you can avoid the need for the cast on the
call sites for a lot of the functions - unless they are renamed to have
unique names (so a #define can add the cast).

If you do add a #define, it can generate the size from that of the
supplied address structure (and error things that are stupidly short).

	David

Thread (21 messages) 21 messages, 3 authors, last reply 2025-10-23
Keyboard shortcuts
hback out one level
jnext message in thread / next series-diff position
kprevious message in thread / previous series-diff position
ldrill in
Escclose help / fold thread tree
?toggle this help