Re: Preventing Denial of Service Attack In IPC Serialization
email@example.com (Le Chaud Lapin) wrote (abridged):
I understand what you are saying, but this is not really the issue.
You're talking about picking a buffer that is limited in size but
big enough to avoid reallocation....
The point of limiting the vector's capacity is to keep the allocation in
proportion to the amount of data sent. It's not itself trying to limit
the amount of data sent, because that is the socket's job.
I'm reluctant to say much more now, because I am not sure I am helping,
but I do wonder if the above point is something you grasp.
The problem was that, if you have a generalized C++ std::string
object, that is being serialized into, you do not want the source
of the serialization to induce the target to allocate a huge
amount of memory for that string.
Actually we don't mind if that happens, provided that the source has
permission to send that much data.
It should be intuitively obvious that the socket, while *EXTREMELY*
capable of limiting how many bytes is received by it, will not have
a clue what that limit should be.
The author of the socket class does not know, but it is the
responsibility of whoever opens the socket to know.
Only the context of the application, and specially, the point
of serialization of objects, will know what that limit should be.
I agree the application should know, but the objects being deserialised
won't. It will depend on things like the total amount of memory available,
the number of sockets we aim to support concurrently, their relative
priority, etc. It's a high-level policy decision.
What the objects will know is how much memory they are likely to need,
but that's quite a different number.
That's why I proposed my stack solution.
Using a stack lets you have different limits over different parts of the
data structure, but that doesn't help address the problem. The problem is
the total memory allocated on behalf of the socket.
In my serialization framework, there is only one buffer associated
with a socket. Data comes into the buffer, and I serialize into
objects from that buffer with no problem. The limit on the size of
that buffer _never_ changes.
Agreed. The limit on the amount a socket may receive is different to the
size of its internal buffer.
But I think you miss what I was saying there. The gain in efficiency
comes not from a larger socket buffer, but from allowing vectors to
pre-allocate more capacity.
The number returned by bytes_allowed() can safely be at least as big as
the number of bytes currently in the socket buffer. We can allow it to be
quite a bit bigger, too. The bigger it is the more efficient we are (due
to less vector resizing), and the more vulnerable we are. If a 16MB
vector would be a denial of service attack, the socket limits
bytes_allowed() to much less than 16Mb.
Now the $1,000,000USD question: "What is the value of size?"
Whatever the source cares to send. The socket decides whether the source
has used up its memory budget. As long as the source is within budget it
can send as big a vector as it likes.
This code in the nude would be tedious, and the problem
would still exist for each T element of the vector.
Obviously it would be encapsulated by some generic component of the
serialisation framework. Only variable-sized elements have to worry about
it at all.
-- Dave Harris, Nottingham, UK.
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]