Commit 36d179fd authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull nfsd updates from Chuck Lever:

 - filehandle signing to defend against filehandle-guessing attacks
   (Benjamin Coddington)

   The server now appends a SipHash-2-4 MAC to each filehandle when
   the new "sign_fh" export option is enabled. NFSD then verifies
   filehandles received from clients against the expected MAC;
   mismatches return NFS error STALE

 - convert the entire NLMv4 server-side XDR layer from hand-written C to
   xdrgen-generated code, spanning roughly thirty patches (Chuck Lever)

   XDR functions are generally boilerplate code and are easy to get
   wrong. The goals of this conversion are improved memory safety, lower
   maintenance burden, and groundwork for eventual Rust code generation
   for these functions.

 - improve pNFS block/SCSI layout robustness with two related changes
   (Dai Ngo)

   SCSI persistent reservation fencing is now tracked per client and
   per device via an xarray, to avoid both redundant preempt operations
   on devices already fenced and a potential NFSD deadlock when all nfsd
   threads are waiting for a layout return.

 - scalability and infrastructure improvements

   Sincere thanks to all contributors, reviewers, testers, and bug
   reporters who participated in the v7.1 NFSD development cycle.

* tag 'nfsd-7.1' of git://git.kernel.org/pub/scm/linux/kernel/git/cel/linux: (83 commits)
  NFSD: Docs: clean up pnfs server timeout docs
  nfsd: fix comment typo in nfsxdr
  nfsd: fix comment typo in nfs3xdr
  NFSD: convert callback RPC program to per-net namespace
  NFSD: use per-operation statidx for callback procedures
  svcrdma: Use contiguous pages for RDMA Read sink buffers
  SUNRPC: Add svc_rqst_page_release() helper
  SUNRPC: xdr.h: fix all kernel-doc warnings
  svcrdma: Factor out WR chain linking into helper
  svcrdma: Add Write chunk WRs to the RPC's Send WR chain
  svcrdma: Clean up use of rdma->sc_pd->device
  svcrdma: Clean up use of rdma->sc_pd->device in Receive paths
  svcrdma: Add fair queuing for Send Queue access
  SUNRPC: Optimize rq_respages allocation in svc_alloc_arg
  SUNRPC: Track consumed rq_pages entries
  svcrdma: preserve rq_next_page in svc_rdma_save_io_pages
  SUNRPC: Handle NULL entries in svc_rqst_release_pages
  SUNRPC: Allocate a separate Reply page array
  SUNRPC: Tighten bounds checking in svc_rqst_replace_page
  NFSD: Sign filehandles
  ...
parents c1f49dea d644a698
Loading
Loading
Loading
Loading
+30 −0
Original line number Diff line number Diff line
@@ -40,3 +40,33 @@ how to translate the device into a serial number from SCSI EVPD 0x80::

	echo "fencing client ${CLIENT} serial ${EVPD}" >> /var/log/pnfsd-fence.log
	EOF

If the nfsd server needs to fence a non-responding client and the
fencing operation fails, the server logs a warning message in the
system log with the following format:

    FENCE failed client[IP_address] clid[#n] device[dev_name]

    where:

    - IP_address: refers to the IP address of the affected client.
    - #n: indicates the unique client identifier.
    - dev_name: specifies the name of the block device related
      to the fencing attempt.

The server will repeatedly retry the operation indefinitely. During
this time, access to the affected file is restricted for all other
clients. This is to prevent potential data corruption if multiple
clients access the same file simultaneously.

To restore access to the affected file for other clients, the admin
needs to take the following actions:

    - shutdown or power off the client being fenced.
    - manually expire the client to release all its state on the server::

        echo 'expire' > /proc/fs/nfsd/clients/clid/ctl

    where:

      - clid: is the unique client identifier displayed in the system log.
+31 −0
Original line number Diff line number Diff line
@@ -22,3 +22,34 @@ option and the underlying SCSI device support persistent reservations.
On the client make sure the kernel has the CONFIG_PNFS_BLOCK option
enabled, and the file system is mounted using the NFSv4.1 protocol
version (mount -o vers=4.1).

If the nfsd server needs to fence a non-responding client and the
fencing operation fails, the server logs a warning message in the
system log with the following format:

    FENCE failed client[IP_address] clid[#n] device[dev_name]

    where:

    - IP_address: refers to the IP address of the affected client.
    - #n: indicates the unique client identifier.
    - dev_name: specifies the name of the block device related
      to the fencing attempt.

The server will repeatedly retry the operation indefinitely. During
this time, access to the affected file is restricted for all other
clients. This is to prevent potential data corruption if multiple
clients access the same file simultaneously.

To restore access to the affected file for other clients, the admin
needs to take the following actions:

    - shutdown or power off the client being fenced.
    - manually expire the client to release all its state on the server::

        echo 'expire' > /proc/fs/nfsd/clients/clid/ctl

    where:

      - clid: is the unique client identifier displayed in the system log.
+2 −0
Original line number Diff line number Diff line
@@ -398,6 +398,7 @@ prototypes::
	bool (*lm_breaker_owns_lease)(struct file_lock *);
        bool (*lm_lock_expirable)(struct file_lock *);
        void (*lm_expire_lock)(void);
        bool (*lm_breaker_timedout)(struct file_lease *);

locking rules:

@@ -412,6 +413,7 @@ lm_breaker_owns_lease: yes no no
lm_lock_expirable	yes		no			no
lm_expire_lock		no		no			yes
lm_open_conflict	yes		no			no
lm_breaker_timedout     yes             no                      no
======================	=============	=================	=========

buffer_head
+85 −0
Original line number Diff line number Diff line
@@ -206,3 +206,88 @@ following flags are defined:
    all of an inode's dirty data on last close. Exports that behave this
    way should set EXPORT_OP_FLUSH_ON_CLOSE so that NFSD knows to skip
    waiting for writeback when closing such files.

Signed Filehandles
------------------

To protect against filehandle guessing attacks, the Linux NFS server can be
configured to sign filehandles with a Message Authentication Code (MAC).

Standard NFS filehandles are often predictable. If an attacker can guess
a valid filehandle for a file they do not have permission to access via
directory traversal, they may be able to bypass path-based permissions
(though they still remain subject to inode-level permissions).

Signed filehandles prevent this by appending a MAC to the filehandle
before it is sent to the client. Upon receiving a filehandle back from a
client, the server re-calculates the MAC using its internal key and
verifies it against the one provided. If the signatures do not match,
the server treats the filehandle as invalid (returning NFS[34]ERR_STALE).

Note that signing filehandles provides integrity and authenticity but
not confidentiality. The contents of the filehandle remain visible to
the client; they simply cannot be forged or modified.

Configuration
~~~~~~~~~~~~~

To enable signed filehandles, the administrator must provide a signing
key to the kernel and enable the "sign_fh" export option.

1. Providing a Key
   The signing key is managed via the nfsd netlink interface. This key
   is per-network-namespace and must be set before any exports using
   "sign_fh" become active.

2. Export Options
   The feature is controlled on a per-export basis in /etc/exports:

   sign_fh
     Enables signing for all filehandles generated under this export.

   no_sign_fh
     (Default) Disables signing.

Key Management and Rotation
~~~~~~~~~~~~~~~~~~~~~~~~~~~

The security of this mechanism relies entirely on the secrecy of the
signing key.

Initial Setup:
  The key should be generated using a high-quality random source and
  loaded early in the boot process or during the nfs-server startup
  sequence.

Changing Keys:
  If a key is changed while clients have active mounts, existing
  filehandles held by those clients will become invalid, resulting in
  "Stale file handle" errors on the client side.

Safe Rotation:
  Currently, there is no mechanism for "graceful" key rotation
  (maintaining multiple valid keys). Changing the key is an atomic
  operation that immediately invalidates all previous signatures.

Transitioning Exports
~~~~~~~~~~~~~~~~~~~~~

When adding or removing the "sign_fh" flag from an active export, the
following behaviors should be expected:

+-------------------+---------------------------------------------------+
| Change            | Result for Existing Clients                       |
+===================+===================================================+
| Adding sign_fh    | Clients holding unsigned filehandles will find    |
|                   | them rejected, as the server now expects a        |
|                   | signature.                                        |
+-------------------+---------------------------------------------------+
| Removing sign_fh  | Clients holding signed filehandles will find them |
|                   | rejected, as the server now expects the           |
|                   | filehandle to end at its traditional boundary     |
|                   | without a MAC.                                    |
+-------------------+---------------------------------------------------+

Because filehandles are often cached persistently by clients, adding or
removing this option should generally be done during a scheduled maintenance
window involving a NFS client unmount/remount.
+6 −0
Original line number Diff line number Diff line
@@ -81,6 +81,11 @@ attribute-sets:
      -
        name: min-threads
        type: u32
      -
        name: fh-key
        type: binary
        checks:
            exact-len: 16
  -
    name: version
    attributes:
@@ -163,6 +168,7 @@ operations:
            - leasetime
            - scope
            - min-threads
            - fh-key
    -
      name: threads-get
      doc: get the maximum number of running threads
Loading