Re: [PATCH (untested)] Subnet support in knfsd.

Andi Kleen (ak@muc.de)
Mon, 22 Feb 1999 12:32:03 +0100


On Mon, Feb 22, 1999 at 11:58:56AM +0100, David Woodhouse wrote:
>
> ak@muc.de said:
> > And this only covers the special case of subnet exports, not NIS
> > group exports, dns domain wildcard exports, ..... Adding all these to
> > the kernel is not possible (and not desirable). Matching the
> > traditional Unix kernel design rule of providing "mechanism not
> > policy" I think it is best to add some call back mechanism, where the
> > kernel can ask user space to reauthenticate before refusing a file
> > handle. mountd could handle this too, e.g. via a netlink socket.
>
> That was my initial idea. I considered the way kerneld used to work, and
> thought it would be too complex, though.
>
> The callback to the user space authentication would be very slow. Can we wait
> that long in exp_getclient(), even for a request that we would otherwise have
> rejected?

Not in exp_getclient, but somewhere else. It would require a redo list for
NFS (similar to what IP uses when a socket is locked). Not very complicated.
Also needs a simple timeout mechanism.
>
> We add a character device /dev/nfsauth, for kernel->user communication. This
> is not a netlink socket for two reasons:
> 1. I can't find any documentation on netlink sockets.
> 2. Using a locally-defined character device will allow us to notice
> immediately if the user-space daemon dies and closes it, saving
> us from waiting forever.

I would propose using netlink sockets, because they do already supply a very nice
framework for non blocking pseudo reliable kernel<->user space communication. No
need to reinvent the flat tire.

(2) can be easily done by checking for sk->dead on the kernel netlink socket.

> We add a new kind of client entry, the 'negative' client. This is extremely
> similar to the negative dentry, and prevents up from looking up
> non-authenticated hosts repeatedly.

Sounds good.

> In exp_getclient(), upon finding that an address has no corresponding client
> entry, we...

I thought more like:

1. Check nlsk->dead, if true return NULL
2. Initialize a simple structure with IP address
3. Use netlink_broadcast to send it to any listening clients.
5. Return -1

(Not waiting because you don't want to block a nfsd thread - otherwise a very simple
DOS would be possible).

In the nfsd main loop:

If -1 is returned put the complete request on a timeout list (with resource checks)

Before the svc_recv():

Check if anything is in the redo list, if yes process that.

Netlink input callback is called with an IP address in packet:
1. Search it in timeout list.
2. Unqueue the old request from the timeout list.
If the answer is positive:
Put it into the redo list (with maximum length and tail drop)
Otherwise
Free request
Add negative lookup entry (again with strict memory resource limits)

Periodic GC timer:

- Remove all negative client entries that are too old and all old packets in the
timeout list.

> Q: How do we combat the potential DoS attack caused by flooding the kernel with
> requests from unknown IP addresses? Once they're given negative centries, it's
> fine, but while the authentication is happening, the server thread is blocked.
> Do we need some way of queueing the request for later, and letting the server
> thread go back to serve other requests while it's waiting for an answer?

Blocking the server thread is not acceptable. Netlink solves it nicely.

> Would it be permissible to return EAGAIN to the remote client if there's
> already a host (or nrservs/2 hosts) waiting for authentication? Or just to
> reject the request and hope that they try again anyway?

For UDP it is easy, just drop it - the other end just will retransmit.
For TCP I am not sure. Unfortunately NFS has no EAGAIN.

-Andi

-- 
This is like TV. I don't like TV.

- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.rutgers.edu Please read the FAQ at http://www.tux.org/lkml/