NFSD: Replace RQ_SPLICE_OK in nfsd_read()
authorChuck Lever <chuck.lever@oracle.com>
Fri, 17 Nov 2023 22:14:33 +0000 (17:14 -0500)
committerChuck Lever <chuck.lever@oracle.com>
Sun, 7 Jan 2024 22:54:25 +0000 (17:54 -0500)
RQ_SPLICE_OK is a bit of a layering violation. Also, a subsequent
patch is going to provide a mechanism for always disabling splice
reads.

Splicing is an issue only for NFS READs, so refactor nfsd_read() to
check the auth type directly instead of relying on an rq_flag
setting.

The new helper will be added into the NFSv4 read path in a
subsequent patch.

Reviewed-by: Jeff Layton <jlayton@kernel.org>
Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
fs/nfsd/vfs.c
fs/nfsd/vfs.h

index c260cbf..cc63fd5 100644 (file)
@@ -1209,6 +1209,30 @@ out_nfserr:
        return nfserr;
 }
 
+/**
+ * nfsd_read_splice_ok - check if spliced reading is supported
+ * @rqstp: RPC transaction context
+ *
+ * Return values:
+ *   %true: nfsd_splice_read() may be used
+ *   %false: nfsd_splice_read() must not be used
+ *
+ * NFS READ normally uses splice to send data in-place. However the
+ * data in cache can change after the reply's MIC is computed but
+ * before the RPC reply is sent. To prevent the client from
+ * rejecting the server-computed MIC in this somewhat rare case, do
+ * not use splice with the GSS integrity and privacy services.
+ */
+bool nfsd_read_splice_ok(struct svc_rqst *rqstp)
+{
+       switch (svc_auth_flavor(rqstp)) {
+       case RPC_AUTH_GSS_KRB5I:
+       case RPC_AUTH_GSS_KRB5P:
+               return false;
+       }
+       return true;
+}
+
 /**
  * nfsd_read - Read data from a file
  * @rqstp: RPC transaction context
@@ -1238,7 +1262,7 @@ __be32 nfsd_read(struct svc_rqst *rqstp, struct svc_fh *fhp,
                return err;
 
        file = nf->nf_file;
-       if (file->f_op->splice_read && test_bit(RQ_SPLICE_OK, &rqstp->rq_flags))
+       if (file->f_op->splice_read && nfsd_read_splice_ok(rqstp))
                err = nfsd_splice_read(rqstp, fhp, file, offset, count, eof);
        else
                err = nfsd_iter_read(rqstp, fhp, file, offset, count, 0, eof);
index e3c2959..702fbc4 100644 (file)
@@ -114,6 +114,7 @@ __be32              nfsd_iter_read(struct svc_rqst *rqstp, struct svc_fh *fhp,
                                struct file *file, loff_t offset,
                                unsigned long *count, unsigned int base,
                                u32 *eof);
+bool           nfsd_read_splice_ok(struct svc_rqst *rqstp);
 __be32         nfsd_read(struct svc_rqst *rqstp, struct svc_fh *fhp,
                                loff_t offset, unsigned long *count,
                                u32 *eof);