Merge tag 'nfs-for-5.7-1' of git://git.linux-nfs.org/projects/trondmy/linux-nfs
Pull NFS client updates from Trond Myklebust: "Highlights include: Stable fixes: - Fix a page leak in nfs_destroy_unlinked_subrequests() - Fix use-after-free issues in nfs_pageio_add_request() - Fix new mount code constant_table array definitions - finish_automount() requires us to hold 2 refs to the mount record Features: - Improve the accuracy of telldir/seekdir by using 64-bit cookies when possible. - Allow one RDMA active connection and several zombie connections to prevent blocking if the remote server is unresponsive. - Limit the size of the NFS access cache by default - Reduce the number of references to credentials that are taken by NFS - pNFS files and flexfiles drivers now support per-layout segment COMMIT lists. - Enable partial-file layout segments in the pNFS/flexfiles driver. - Add support for CB_RECALL_ANY to the pNFS flexfiles layout type - pNFS/flexfiles Report NFS4ERR_DELAY and NFS4ERR_GRACE errors from the DS using the layouterror mechanism. Bugfixes and cleanups: - SUNRPC: Fix krb5p regressions - Don't specify NFS version in "UDP not supported" error - nfsroot: set tcp as the default transport protocol - pnfs: Return valid stateids in nfs_layout_find_inode_by_stateid() - alloc_nfs_open_context() must use the file cred when available - Fix locking when dereferencing the delegation cred - Fix memory leaks in O_DIRECT when nfs_get_lock_context() fails - Various clean ups of the NFS O_DIRECT commit code - Clean up RDMA connect/disconnect - Replace zero-length arrays with C99-style flexible arrays" * tag 'nfs-for-5.7-1' of git://git.linux-nfs.org/projects/trondmy/linux-nfs: (86 commits) NFS: Clean up process of marking inode stale. SUNRPC: Don't start a timer on an already queued rpc task NFS/pnfs: Reference the layout cred in pnfs_prepare_layoutreturn() NFS/pnfs: Fix dereference of layout cred in pnfs_layoutcommit_inode() NFS: Beware when dereferencing the delegation cred NFS: Add a module parameter to set nfs_mountpoint_expiry_timeout NFS: finish_automount() requires us to hold 2 refs to the mount record NFS: Fix a few constant_table array definitions NFS: Try to join page groups before an O_DIRECT retransmission NFS: Refactor nfs_lock_and_join_requests() NFS: Reverse the submission order of requests in __nfs_pageio_add_request() NFS: Clean up nfs_lock_and_join_requests() NFS: Remove the redundant function nfs_pgio_has_mirroring() NFS: Fix memory leaks in nfs_pageio_stop_mirroring() NFS: Fix a request reference leak in nfs_direct_write_clear_reqs() NFS: Fix use-after-free issues in nfs_pageio_add_request() NFS: Fix races nfs_page_group_destroy() vs nfs_destroy_unlinked_subrequests() NFS: Fix a page leak in nfs_destroy_unlinked_subrequests() NFS: Remove unused FLUSH_SYNC support in nfs_initiate_pgio() pNFS/flexfiles: Specify the layout segment range in LAYOUTGET ...
This commit is contained in:
@@ -20,6 +20,7 @@
|
||||
#include <linux/sunrpc/clnt.h>
|
||||
#include <linux/sunrpc/auth.h>
|
||||
#include <linux/sunrpc/auth_gss.h>
|
||||
#include <linux/sunrpc/gss_krb5.h>
|
||||
#include <linux/sunrpc/svcauth_gss.h>
|
||||
#include <linux/sunrpc/gss_err.h>
|
||||
#include <linux/workqueue.h>
|
||||
@@ -1050,7 +1051,7 @@ gss_create_new(const struct rpc_auth_create_args *args, struct rpc_clnt *clnt)
|
||||
goto err_put_mech;
|
||||
auth = &gss_auth->rpc_auth;
|
||||
auth->au_cslack = GSS_CRED_SLACK >> 2;
|
||||
auth->au_rslack = GSS_VERF_SLACK >> 2;
|
||||
auth->au_rslack = GSS_KRB5_MAX_SLACK_NEEDED >> 2;
|
||||
auth->au_verfsize = GSS_VERF_SLACK >> 2;
|
||||
auth->au_ralign = GSS_VERF_SLACK >> 2;
|
||||
auth->au_flags = 0;
|
||||
@@ -1724,8 +1725,9 @@ bad_mic:
|
||||
goto out;
|
||||
}
|
||||
|
||||
static int gss_wrap_req_integ(struct rpc_cred *cred, struct gss_cl_ctx *ctx,
|
||||
struct rpc_task *task, struct xdr_stream *xdr)
|
||||
static noinline_for_stack int
|
||||
gss_wrap_req_integ(struct rpc_cred *cred, struct gss_cl_ctx *ctx,
|
||||
struct rpc_task *task, struct xdr_stream *xdr)
|
||||
{
|
||||
struct rpc_rqst *rqstp = task->tk_rqstp;
|
||||
struct xdr_buf integ_buf, *snd_buf = &rqstp->rq_snd_buf;
|
||||
@@ -1816,8 +1818,9 @@ out:
|
||||
return -EAGAIN;
|
||||
}
|
||||
|
||||
static int gss_wrap_req_priv(struct rpc_cred *cred, struct gss_cl_ctx *ctx,
|
||||
struct rpc_task *task, struct xdr_stream *xdr)
|
||||
static noinline_for_stack int
|
||||
gss_wrap_req_priv(struct rpc_cred *cred, struct gss_cl_ctx *ctx,
|
||||
struct rpc_task *task, struct xdr_stream *xdr)
|
||||
{
|
||||
struct rpc_rqst *rqstp = task->tk_rqstp;
|
||||
struct xdr_buf *snd_buf = &rqstp->rq_snd_buf;
|
||||
@@ -1934,35 +1937,69 @@ gss_unwrap_resp_auth(struct rpc_cred *cred)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
/*
|
||||
* RFC 2203, Section 5.3.2.2
|
||||
*
|
||||
* struct rpc_gss_integ_data {
|
||||
* opaque databody_integ<>;
|
||||
* opaque checksum<>;
|
||||
* };
|
||||
*
|
||||
* struct rpc_gss_data_t {
|
||||
* unsigned int seq_num;
|
||||
* proc_req_arg_t arg;
|
||||
* };
|
||||
*/
|
||||
static noinline_for_stack int
|
||||
gss_unwrap_resp_integ(struct rpc_task *task, struct rpc_cred *cred,
|
||||
struct gss_cl_ctx *ctx, struct rpc_rqst *rqstp,
|
||||
struct xdr_stream *xdr)
|
||||
{
|
||||
struct xdr_buf integ_buf, *rcv_buf = &rqstp->rq_rcv_buf;
|
||||
u32 data_offset, mic_offset, integ_len, maj_stat;
|
||||
struct xdr_buf gss_data, *rcv_buf = &rqstp->rq_rcv_buf;
|
||||
struct rpc_auth *auth = cred->cr_auth;
|
||||
u32 len, offset, seqno, maj_stat;
|
||||
struct xdr_netobj mic;
|
||||
__be32 *p;
|
||||
int ret;
|
||||
|
||||
p = xdr_inline_decode(xdr, 2 * sizeof(*p));
|
||||
if (unlikely(!p))
|
||||
ret = -EIO;
|
||||
mic.data = NULL;
|
||||
|
||||
/* opaque databody_integ<>; */
|
||||
if (xdr_stream_decode_u32(xdr, &len))
|
||||
goto unwrap_failed;
|
||||
integ_len = be32_to_cpup(p++);
|
||||
if (integ_len & 3)
|
||||
if (len & 3)
|
||||
goto unwrap_failed;
|
||||
data_offset = (u8 *)(p) - (u8 *)rcv_buf->head[0].iov_base;
|
||||
mic_offset = integ_len + data_offset;
|
||||
if (mic_offset > rcv_buf->len)
|
||||
offset = rcv_buf->len - xdr_stream_remaining(xdr);
|
||||
if (xdr_stream_decode_u32(xdr, &seqno))
|
||||
goto unwrap_failed;
|
||||
if (be32_to_cpup(p) != rqstp->rq_seqno)
|
||||
if (seqno != rqstp->rq_seqno)
|
||||
goto bad_seqno;
|
||||
if (xdr_buf_subsegment(rcv_buf, &gss_data, offset, len))
|
||||
goto unwrap_failed;
|
||||
|
||||
if (xdr_buf_subsegment(rcv_buf, &integ_buf, data_offset, integ_len))
|
||||
/*
|
||||
* The xdr_stream now points to the beginning of the
|
||||
* upper layer payload, to be passed below to
|
||||
* rpcauth_unwrap_resp_decode(). The checksum, which
|
||||
* follows the upper layer payload in @rcv_buf, is
|
||||
* located and parsed without updating the xdr_stream.
|
||||
*/
|
||||
|
||||
/* opaque checksum<>; */
|
||||
offset += len;
|
||||
if (xdr_decode_word(rcv_buf, offset, &len))
|
||||
goto unwrap_failed;
|
||||
if (xdr_buf_read_mic(rcv_buf, &mic, mic_offset))
|
||||
offset += sizeof(__be32);
|
||||
if (offset + len > rcv_buf->len)
|
||||
goto unwrap_failed;
|
||||
maj_stat = gss_verify_mic(ctx->gc_gss_ctx, &integ_buf, &mic);
|
||||
mic.len = len;
|
||||
mic.data = kmalloc(len, GFP_NOFS);
|
||||
if (!mic.data)
|
||||
goto unwrap_failed;
|
||||
if (read_bytes_from_xdr_buf(rcv_buf, offset, mic.data, mic.len))
|
||||
goto unwrap_failed;
|
||||
|
||||
maj_stat = gss_verify_mic(ctx->gc_gss_ctx, &gss_data, &mic);
|
||||
if (maj_stat == GSS_S_CONTEXT_EXPIRED)
|
||||
clear_bit(RPCAUTH_CRED_UPTODATE, &cred->cr_flags);
|
||||
if (maj_stat != GSS_S_COMPLETE)
|
||||
@@ -1970,19 +2007,24 @@ gss_unwrap_resp_integ(struct rpc_task *task, struct rpc_cred *cred,
|
||||
|
||||
auth->au_rslack = auth->au_verfsize + 2 + 1 + XDR_QUADLEN(mic.len);
|
||||
auth->au_ralign = auth->au_verfsize + 2;
|
||||
return 0;
|
||||
ret = 0;
|
||||
|
||||
out:
|
||||
kfree(mic.data);
|
||||
return ret;
|
||||
|
||||
unwrap_failed:
|
||||
trace_rpcgss_unwrap_failed(task);
|
||||
return -EIO;
|
||||
goto out;
|
||||
bad_seqno:
|
||||
trace_rpcgss_bad_seqno(task, rqstp->rq_seqno, be32_to_cpup(p));
|
||||
return -EIO;
|
||||
trace_rpcgss_bad_seqno(task, rqstp->rq_seqno, seqno);
|
||||
goto out;
|
||||
bad_mic:
|
||||
trace_rpcgss_verify_mic(task, maj_stat);
|
||||
return -EIO;
|
||||
goto out;
|
||||
}
|
||||
|
||||
static int
|
||||
static noinline_for_stack int
|
||||
gss_unwrap_resp_priv(struct rpc_task *task, struct rpc_cred *cred,
|
||||
struct gss_cl_ctx *ctx, struct rpc_rqst *rqstp,
|
||||
struct xdr_stream *xdr)
|
||||
|
Reference in New Issue
Block a user