From: Herbert Xu <herbert@gondor.apana.org.au> Date: 2004-06-28 23:14:39
Hi:
The recent thread on NLMSG_OK has reminded me about an old problem
with NETLINK.
The problem is that any user on the system can launch a DoS attack on
any NETLINK application by flooding its NETLINK address with packets.
This will easily fill up the receive queue of the destination
application and therefore cause legitimate packets from the kernel
or elsewhere to be dropped.
The solution seems simple. We already have a connect(2) call for
NETLINK sockets. So why don't we check the connected address of
the destination socket against the address of the sender before
putting the packet on the queue?
Any comments before I go ahead and code it?
Cheers,
--
Visit Openswan at http://www.openswan.org/
Email: Herbert Xu ~{PmV>HI~} [off-list ref]
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt
From: David S. Miller <hidden> Date: 2004-06-29 00:30:39
On Tue, 29 Jun 2004 09:14:39 +1000
Herbert Xu [off-list ref] wrote:
The solution seems simple. We already have a connect(2) call for
NETLINK sockets. So why don't we check the connected address of
the destination socket against the address of the sender before
putting the packet on the queue?
Any comments before I go ahead and code it?
This really won't break any existing legitimate cases?
Are you sure?
The solution seems simple. We already have a connect(2) call for
NETLINK sockets. So why don't we check the connected address of
the destination socket against the address of the sender before
putting the packet on the queue?
Do you mean the restriction sort of made in AF_UNIX SOCK_DGRAM:
a connected socket receives messages only from its destination?
I think this is safe.
It was not done because netlink sockets were expected to listen
for broadcasts, so that this kind of protection would be not useful
and even harmful. But taking into account that inter-application
communication is not used, only kernel sends broadcasts and applications
talking to kernel will receive such broadcasts, because they are connected
to kernel.
The troube is that pid of kernel socket used to be 0, so that
applications connected to kernel are not connected in technical sense. :-)
Apparently, to implement this we have to add some kind of flag
marking connected sockets.
Alexey
From: Herbert Xu <herbert@gondor.apana.org.au> Date: 2004-06-29 08:45:52
On Tue, Jun 29, 2004 at 12:22:52PM +0400, Alexey Kuznetsov wrote:
Do you mean the restriction sort of made in AF_UNIX SOCK_DGRAM:
a connected socket receives messages only from its destination?
Exactly. Another example would be UDP over IP.
It was not done because netlink sockets were expected to listen
for broadcasts, so that this kind of protection would be not useful
and even harmful. But taking into account that inter-application
communication is not used, only kernel sends broadcasts and applications
talking to kernel will receive such broadcasts, because they are connected
to kernel.
I've had a look in the various NETLINK applications that I know of,
including quagga/iproute/iptables and all the stuff that I wrote,
none of them does a connect at all.
So it should be harmless to introduce this new semantics.
The troube is that pid of kernel socket used to be 0, so that
applications connected to kernel are not connected in technical sense. :-)
That's kind of a good thing since it means that existing applications
are less likely to call connect(2) :)
Apparently, to implement this we have to add some kind of flag
marking connected sockets.
Or we can set the disconnected pid to a negative value since POSIX
requires pid_t to be signed. I see that you've reserved everything
between -4096 and 0. So perhaps we can pick -1?
From: Herbert Xu <herbert@gondor.apana.org.au> Date: 2004-06-29 11:18:33
On Tue, Jun 29, 2004 at 03:14:33PM +0400, Alexey Kuznetsov wrote:
quoted
Or we can set the disconnected pid to a negative value since POSIX
requires pid_t to be signed. I see that you've reserved everything
between -4096 and 0. So perhaps we can pick -1?
From: Herbert Xu <herbert@gondor.apana.org.au> Date: 2004-06-30 11:27:51
On Tue, Jun 29, 2004 at 09:18:33PM +1000, herbert wrote:
quoted
quoted
Or we can set the disconnected pid to a negative value since POSIX
requires pid_t to be signed. I see that you've reserved everything
between -4096 and 0. So perhaps we can pick -1?
Actually that doesn't quite work. Users are allowed to bind to any
non-zero address including -1. Besides, we already have sock->sk_state
and socket->state which are perfect for this.
So here is a patch to disallow sending unicast messages to connected
sockets from addresses other than the one that it is connected to.
I've tested it with a locally patched Openswan and it works as
intended by stopping me from sending bogus messages to it and
still allowing kernel messages to go through.
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Cheers,
--
Visit Openswan at http://www.openswan.org/
Email: Herbert Xu ~{PmV>HI~} [off-list ref]
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt
From: David S. Miller <hidden> Date: 2004-06-30 22:36:06
Why don't you combine the two "ERR_PTR(-ECONNREFUSED)" tests
into one test like:
if ((nlk->pid == 0 && !nlk->data_ready) ||
(sock->sk_state == NELTINK_CONNECTED &&
nlk->dst_pid != nlk_sk(ssk)->pid)) {
sock_put(sock);
return ERR_PTR(-ECONNREFUSED);
}
so we don't have two copies of the "sock_put(); return ERR_PTR()"
thing emitted by the compiler?
From: Herbert Xu <herbert@gondor.apana.org.au> Date: 2004-06-30 23:01:47
On Wed, Jun 30, 2004 at 03:36:06PM -0700, David S. Miller wrote:
Why don't you combine the two "ERR_PTR(-ECONNREFUSED)" tests
into one test like:
if ((nlk->pid == 0 && !nlk->data_ready) ||
(sock->sk_state == NELTINK_CONNECTED &&
nlk->dst_pid != nlk_sk(ssk)->pid)) {
sock_put(sock);
return ERR_PTR(-ECONNREFUSED);
}
so we don't have two copies of the "sock_put(); return ERR_PTR()"
thing emitted by the compiler?