@@ -1545,6 +1545,7 @@ static int gss_marshal(struct rpc_task *task, struct xdr_stream *xdr)
15451545 struct kvec iov ;
15461546 struct xdr_buf verf_buf ;
15471547 int status ;
1548+ u32 seqno ;
15481549
15491550 /* Credential */
15501551
@@ -1556,15 +1557,16 @@ static int gss_marshal(struct rpc_task *task, struct xdr_stream *xdr)
15561557 cred_len = p ++ ;
15571558
15581559 spin_lock (& ctx -> gc_seq_lock );
1559- req -> rq_seqno = (ctx -> gc_seq < MAXSEQ ) ? ctx -> gc_seq ++ : MAXSEQ ;
1560+ seqno = (ctx -> gc_seq < MAXSEQ ) ? ctx -> gc_seq ++ : MAXSEQ ;
1561+ xprt_rqst_add_seqno (req , seqno );
15601562 spin_unlock (& ctx -> gc_seq_lock );
1561- if (req -> rq_seqno == MAXSEQ )
1563+ if (* req -> rq_seqnos == MAXSEQ )
15621564 goto expired ;
15631565 trace_rpcgss_seqno (task );
15641566
15651567 * p ++ = cpu_to_be32 (RPC_GSS_VERSION );
15661568 * p ++ = cpu_to_be32 (ctx -> gc_proc );
1567- * p ++ = cpu_to_be32 (req -> rq_seqno );
1569+ * p ++ = cpu_to_be32 (* req -> rq_seqnos );
15681570 * p ++ = cpu_to_be32 (gss_cred -> gc_service );
15691571 p = xdr_encode_netobj (p , & ctx -> gc_wire_ctx );
15701572 * cred_len = cpu_to_be32 ((p - (cred_len + 1 )) << 2 );
@@ -1678,17 +1680,31 @@ gss_refresh_null(struct rpc_task *task)
16781680 return 0 ;
16791681}
16801682
1683+ static u32
1684+ gss_validate_seqno_mic (struct gss_cl_ctx * ctx , u32 seqno , __be32 * seq , __be32 * p , u32 len )
1685+ {
1686+ struct kvec iov ;
1687+ struct xdr_buf verf_buf ;
1688+ struct xdr_netobj mic ;
1689+
1690+ * seq = cpu_to_be32 (seqno );
1691+ iov .iov_base = seq ;
1692+ iov .iov_len = 4 ;
1693+ xdr_buf_from_iov (& iov , & verf_buf );
1694+ mic .data = (u8 * )p ;
1695+ mic .len = len ;
1696+ return gss_verify_mic (ctx -> gc_gss_ctx , & verf_buf , & mic );
1697+ }
1698+
16811699static int
16821700gss_validate (struct rpc_task * task , struct xdr_stream * xdr )
16831701{
16841702 struct rpc_cred * cred = task -> tk_rqstp -> rq_cred ;
16851703 struct gss_cl_ctx * ctx = gss_cred_get_ctx (cred );
16861704 __be32 * p , * seq = NULL ;
1687- struct kvec iov ;
1688- struct xdr_buf verf_buf ;
1689- struct xdr_netobj mic ;
16901705 u32 len , maj_stat ;
16911706 int status ;
1707+ int i = 1 ; /* don't recheck the first item */
16921708
16931709 p = xdr_inline_decode (xdr , 2 * sizeof (* p ));
16941710 if (!p )
@@ -1705,13 +1721,10 @@ gss_validate(struct rpc_task *task, struct xdr_stream *xdr)
17051721 seq = kmalloc (4 , GFP_KERNEL );
17061722 if (!seq )
17071723 goto validate_failed ;
1708- * seq = cpu_to_be32 (task -> tk_rqstp -> rq_seqno );
1709- iov .iov_base = seq ;
1710- iov .iov_len = 4 ;
1711- xdr_buf_from_iov (& iov , & verf_buf );
1712- mic .data = (u8 * )p ;
1713- mic .len = len ;
1714- maj_stat = gss_verify_mic (ctx -> gc_gss_ctx , & verf_buf , & mic );
1724+ maj_stat = gss_validate_seqno_mic (ctx , task -> tk_rqstp -> rq_seqnos [0 ], seq , p , len );
1725+ /* RFC 2203 5.3.3.1 - compute the checksum of each sequence number in the cache */
1726+ while (unlikely (maj_stat == GSS_S_BAD_SIG && i < task -> tk_rqstp -> rq_seqno_count ))
1727+ maj_stat = gss_validate_seqno_mic (ctx , task -> tk_rqstp -> rq_seqnos [i ], seq , p , len );
17151728 if (maj_stat == GSS_S_CONTEXT_EXPIRED )
17161729 clear_bit (RPCAUTH_CRED_UPTODATE , & cred -> cr_flags );
17171730 if (maj_stat )
@@ -1750,7 +1763,7 @@ gss_wrap_req_integ(struct rpc_cred *cred, struct gss_cl_ctx *ctx,
17501763 if (!p )
17511764 goto wrap_failed ;
17521765 integ_len = p ++ ;
1753- * p = cpu_to_be32 (rqstp -> rq_seqno );
1766+ * p = cpu_to_be32 (* rqstp -> rq_seqnos );
17541767
17551768 if (rpcauth_wrap_req_encode (task , xdr ))
17561769 goto wrap_failed ;
@@ -1847,7 +1860,7 @@ gss_wrap_req_priv(struct rpc_cred *cred, struct gss_cl_ctx *ctx,
18471860 if (!p )
18481861 goto wrap_failed ;
18491862 opaque_len = p ++ ;
1850- * p = cpu_to_be32 (rqstp -> rq_seqno );
1863+ * p = cpu_to_be32 (* rqstp -> rq_seqnos );
18511864
18521865 if (rpcauth_wrap_req_encode (task , xdr ))
18531866 goto wrap_failed ;
@@ -2001,7 +2014,7 @@ gss_unwrap_resp_integ(struct rpc_task *task, struct rpc_cred *cred,
20012014 offset = rcv_buf -> len - xdr_stream_remaining (xdr );
20022015 if (xdr_stream_decode_u32 (xdr , & seqno ))
20032016 goto unwrap_failed ;
2004- if (seqno != rqstp -> rq_seqno )
2017+ if (seqno != * rqstp -> rq_seqnos )
20052018 goto bad_seqno ;
20062019 if (xdr_buf_subsegment (rcv_buf , & gss_data , offset , len ))
20072020 goto unwrap_failed ;
@@ -2045,7 +2058,7 @@ gss_unwrap_resp_integ(struct rpc_task *task, struct rpc_cred *cred,
20452058 trace_rpcgss_unwrap_failed (task );
20462059 goto out ;
20472060bad_seqno :
2048- trace_rpcgss_bad_seqno (task , rqstp -> rq_seqno , seqno );
2061+ trace_rpcgss_bad_seqno (task , * rqstp -> rq_seqnos , seqno );
20492062 goto out ;
20502063bad_mic :
20512064 trace_rpcgss_verify_mic (task , maj_stat );
@@ -2077,7 +2090,7 @@ gss_unwrap_resp_priv(struct rpc_task *task, struct rpc_cred *cred,
20772090 if (maj_stat != GSS_S_COMPLETE )
20782091 goto bad_unwrap ;
20792092 /* gss_unwrap decrypted the sequence number */
2080- if (be32_to_cpup (p ++ ) != rqstp -> rq_seqno )
2093+ if (be32_to_cpup (p ++ ) != * rqstp -> rq_seqnos )
20812094 goto bad_seqno ;
20822095
20832096 /* gss_unwrap redacts the opaque blob from the head iovec.
@@ -2093,7 +2106,7 @@ gss_unwrap_resp_priv(struct rpc_task *task, struct rpc_cred *cred,
20932106 trace_rpcgss_unwrap_failed (task );
20942107 return - EIO ;
20952108bad_seqno :
2096- trace_rpcgss_bad_seqno (task , rqstp -> rq_seqno , be32_to_cpup (-- p ));
2109+ trace_rpcgss_bad_seqno (task , * rqstp -> rq_seqnos , be32_to_cpup (-- p ));
20972110 return - EIO ;
20982111bad_unwrap :
20992112 trace_rpcgss_unwrap (task , maj_stat );
@@ -2118,14 +2131,14 @@ gss_xmit_need_reencode(struct rpc_task *task)
21182131 if (!ctx )
21192132 goto out ;
21202133
2121- if (gss_seq_is_newer (req -> rq_seqno , READ_ONCE (ctx -> gc_seq )))
2134+ if (gss_seq_is_newer (* req -> rq_seqnos , READ_ONCE (ctx -> gc_seq )))
21222135 goto out_ctx ;
21232136
21242137 seq_xmit = READ_ONCE (ctx -> gc_seq_xmit );
2125- while (gss_seq_is_newer (req -> rq_seqno , seq_xmit )) {
2138+ while (gss_seq_is_newer (* req -> rq_seqnos , seq_xmit )) {
21262139 u32 tmp = seq_xmit ;
21272140
2128- seq_xmit = cmpxchg (& ctx -> gc_seq_xmit , tmp , req -> rq_seqno );
2141+ seq_xmit = cmpxchg (& ctx -> gc_seq_xmit , tmp , * req -> rq_seqnos );
21292142 if (seq_xmit == tmp ) {
21302143 ret = false;
21312144 goto out_ctx ;
@@ -2134,7 +2147,7 @@ gss_xmit_need_reencode(struct rpc_task *task)
21342147
21352148 win = ctx -> gc_win ;
21362149 if (win > 0 )
2137- ret = !gss_seq_is_newer (req -> rq_seqno , seq_xmit - win );
2150+ ret = !gss_seq_is_newer (* req -> rq_seqnos , seq_xmit - win );
21382151
21392152out_ctx :
21402153 gss_put_ctx (ctx );
0 commit comments