Hmmm... if I've got a UDP protocol using a variable-size packet, is
there a way to see how big a packet is before I read it, so I can
allocate a "right size" buffer?
Printable View
Hmmm... if I've got a UDP protocol using a variable-size packet, is
there a way to see how big a packet is before I read it, so I can
allocate a "right size" buffer?
Joe Pfeiffer <pfeiffer@cs.nmsu.edu> writes:
[color=blue]
> Hmmm... if I've got a UDP protocol using a variable-size packet, is
> there a way to see how big a packet is before I read it, so I can
> allocate a "right size" buffer?[/color]
(following up my own post)
Ah, found it. ioctl FIONREAD
On Oct 19, 6:55*pm, Joe Pfeiffer <pfeif...@cs.nmsu.edu> wrote:
[color=blue]
> Joe Pfeiffer <pfeif...@cs.nmsu.edu> writes:[/color]
[color=blue][color=green]
> > Hmmm... *if I've got a UDP protocol using a variable-size packet, is
> > there a way to see how big a packet is before I read it, so I can
> > allocate a "right size" buffer?[/color][/color]
[color=blue]
> (following up my own post)
> Ah, found it. *ioctl FIONREAD[/color]
That won't work. Please don't do that.
Consider, for example the following situation:
1) You call FIONREAD, it tells you there's a 20 bytes datagram
waiting.
2) The OS drops the datagram, but then receives a 35 byte datagram, or
a 5 byte datagram.
3) You call 'recvmsg', excpecting a 20 byte datagram.
You cannot "freeze the world" so that information stays current across
two unrelated system calls. That is a common cause of bugs and pain.
In fact, it is an assumption almost exactly like this one that caused
an exploitable flaw in Linux's inetd super-server.
The correct solution is to allocate a buffer that is as larger as the
largest datagram your program supports. If you need to copy the data
into a 'right-sized' buffer later, do so.
DS
David Schwartz <davids@webmaster.com> writes:
[color=blue]
> On Oct 19, 6:55*pm, Joe Pfeiffer <pfeif...@cs.nmsu.edu> wrote:
>[color=green]
>> Joe Pfeiffer <pfeif...@cs.nmsu.edu> writes:[/color]
>[color=green][color=darkred]
>> > Hmmm... *if I've got a UDP protocol using a variable-size packet, is
>> > there a way to see how big a packet is before I read it, so I can
>> > allocate a "right size" buffer?[/color][/color]
>[color=green]
>> (following up my own post)
>> Ah, found it. *ioctl FIONREAD[/color]
>
> That won't work. Please don't do that.
>
> Consider, for example the following situation:
>
> 1) You call FIONREAD, it tells you there's a 20 bytes datagram
> waiting.
>
> 2) The OS drops the datagram, but then receives a 35 byte datagram, or
> a 5 byte datagram.
>
> 3) You call 'recvmsg', excpecting a 20 byte datagram.
>
> You cannot "freeze the world" so that information stays current across
> two unrelated system calls. That is a common cause of bugs and pain.
> In fact, it is an assumption almost exactly like this one that caused
> an exploitable flaw in Linux's inetd super-server.
>
> The correct solution is to allocate a buffer that is as larger as the
> largest datagram your program supports. If you need to copy the data
> into a 'right-sized' buffer later, do so.[/color]
One way to avoid copying data is to allocate a buffer larger than the
maximum message size, and stack incoming messages until the remaining
size is too small. On Linux you could use mremap() and munmap() to
implement a sliding window of sorts, avoiding both copies and memory
overhead.
--
Måns Rullgård
[email]mans@mansr.com[/email]
David Schwartz <davids@webmaster.com> writes:
[color=blue]
> On Oct 19, 6:55*pm, Joe Pfeiffer <pfeif...@cs.nmsu.edu> wrote:
>[color=green]
>> Joe Pfeiffer <pfeif...@cs.nmsu.edu> writes:[/color]
>[color=green][color=darkred]
>> > Hmmm... *if I've got a UDP protocol using a variable-size packet, is
>> > there a way to see how big a packet is before I read it, so I can
>> > allocate a "right size" buffer?[/color][/color]
>[color=green]
>> (following up my own post)
>> Ah, found it. *ioctl FIONREAD[/color]
>
> That won't work. Please don't do that.[/color]
<example snipped>
That's... surprising. I would have thought that by the time a packet
is waiting for you to read it, it would be secure from dropping (I can
see how this wouldn't be thread-safe, but that's another issue).
I'd be curious to see a description of the inetd vulnerability.
On Oct 20, 3:02*pm, Joe Pfeiffer <pfeif...@cs.nmsu.edu> wrote:
[color=blue]
> That's... *surprising. *I would have thought that by the time a packet
> is waiting for you to read it, it would be secure from dropping (I can
> see how this wouldn't be thread-safe, but that's another issue).[/color]
Nope. UDP datagrams are always discardable.
[color=blue]
> I'd be curious to see a description of the inetd vulnerability.[/color]
Consider the following:
1) You have UDP checksum verification off.
2) You call 'select', it tells you that you have a datagram waiting.
3) An administrator decides to turn UDP checksum verification on
globally.
4) You call 'recvmsg', but the datagram you found in step 2 was
discarded because its checksum was invalid. You are now hung forever,
or at least until someone sends you a datagram.
Status-reporting functions tell you the status at some undefined
instant in-between when you called them and when they returned. They
do not come with future guarantees. This is a very common source of
serious bugs.
"I couldn't think of any way it go wrong" doesn't cut it in my book.
The world is full of ways it go wrong that various yous couldn't think
of.
DS