summaryrefslogtreecommitdiff
path: root/Documentation/filesystems/nfs/keyring.rst
blob: 29367e71a8013b3df721380deac8edbb7209ca38 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
.. SPDX-License-Identifier: GPL-2.0

====================================
The per-namespace NFS client keyring
====================================

The NFS client holds one keyring, named ".nfs", per network
namespace. An xprtsec=mtls mount presents the client certificate and
private key named by its cert_serial= and privkey_serial= mount
options, and the handshake links the mount's namespace .nfs keyring
into tlshd before tlshd reads those keys. Keys placed on the .nfs
keyring therefore need not grant user read permission: tlshd reaches
them as a possessor, and a tlshd in another network namespace never
possesses them.

The keyring is owned by the owner of the network namespace's user
namespace, with KEY_POS_ALL and KEY_USR_ALL less SETATTR. It is not
charged to any quota. Keys added to it by userspace are charged to
the user that adds them.

Finding the keyring serial number
=================================

The .nfs keyring is not linked into any keyring that userspace
possesses, so a serial number is the only way to name it. The NFS
client registers a key type, "nfs_keyring", whose sole purpose is to
hand that serial number out. Its request_key handler runs in the
caller's context and does not upcall to /sbin/request-key.

To obtain the serial number, request a key of type "nfs_keyring" with
the description ".nfs" and read its payload::

	id=$(keyctl request2 nfs_keyring .nfs "" @s)
	serial=$(keyctl print $id)

The contract of the key type is:

 * The description is the string ".nfs". Any other description is
   rejected with EINVAL before a key is allocated.

 * The callout info must be present. request_key() with a NULL
   callout_info never invokes a handler and returns ENOKEY when no
   matching key exists, so use request_key() with an empty string, or
   ``keyctl request2`` rather than ``keyctl request``. The content of
   the callout info is ignored.

 * The payload is the keyring serial number as decimal ASCII digits
   with no terminating NUL. The return value of keyctl_read() gives
   the length; a buffer of 12 bytes is sufficient.

 * add_key() with this type accepts only that payload. A key carrying
   any other value is rejected with EINVAL, so a key found in the
   caller's keyrings always holds the serial number of the caller's
   namespace.

 * The key type carries KEY_TYPE_NET_DOMAIN. A key instantiated in one
   network namespace does not answer a request made in another, so a
   process that keeps its session keyring across setns() receives the
   serial number of the namespace it is in at the time of the request.

The serial number is not a secret. The keyring's own permissions
decide what a caller can do with it.

Provisioning credentials
========================

Add the client certificate and private key to the .nfs keyring as
keys that grant no user read permission, then pass their serial
numbers as cert_serial= and privkey_serial= mount options.