Skip to content

Commit 4dd9daa

Browse files
chuckleverChuck Lever
authored andcommitted
SUNRPC: Fix crasher in unwrap_integ_data()
If a zero length is passed to kmalloc() it returns 0x10, which is not a valid address. gss_verify_mic() subsequently crashes when it attempts to dereference that pointer. Instead of allocating this memory on every call based on an untrusted size value, use a piece of dynamically-allocated scratch memory that is always available. Signed-off-by: Chuck Lever <[email protected]> Reviewed-by: Jeff Layton <[email protected]>
1 parent c65d9df commit 4dd9daa

File tree

1 file changed

+32
-23
lines changed

1 file changed

+32
-23
lines changed

net/sunrpc/auth_gss/svcauth_gss.c

Lines changed: 32 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -49,11 +49,36 @@
4949
#include <linux/sunrpc/svcauth.h>
5050
#include <linux/sunrpc/svcauth_gss.h>
5151
#include <linux/sunrpc/cache.h>
52+
#include <linux/sunrpc/gss_krb5.h>
5253

5354
#include <trace/events/rpcgss.h>
5455

5556
#include "gss_rpc_upcall.h"
5657

58+
/*
59+
* Unfortunately there isn't a maximum checksum size exported via the
60+
* GSS API. Manufacture one based on GSS mechanisms supported by this
61+
* implementation.
62+
*/
63+
#define GSS_MAX_CKSUMSIZE (GSS_KRB5_TOK_HDR_LEN + GSS_KRB5_MAX_CKSUM_LEN)
64+
65+
/*
66+
* This value may be increased in the future to accommodate other
67+
* usage of the scratch buffer.
68+
*/
69+
#define GSS_SCRATCH_SIZE GSS_MAX_CKSUMSIZE
70+
71+
struct gss_svc_data {
72+
/* decoded gss client cred: */
73+
struct rpc_gss_wire_cred clcred;
74+
/* save a pointer to the beginning of the encoded verifier,
75+
* for use in encryption/checksumming in svcauth_gss_release: */
76+
__be32 *verf_start;
77+
struct rsc *rsci;
78+
79+
/* for temporary results */
80+
u8 gsd_scratch[GSS_SCRATCH_SIZE];
81+
};
5782

5883
/* The rpcsec_init cache is used for mapping RPCSEC_GSS_{,CONT_}INIT requests
5984
* into replies.
@@ -887,13 +912,11 @@ read_u32_from_xdr_buf(struct xdr_buf *buf, int base, u32 *obj)
887912
static int
888913
unwrap_integ_data(struct svc_rqst *rqstp, struct xdr_buf *buf, u32 seq, struct gss_ctx *ctx)
889914
{
915+
struct gss_svc_data *gsd = rqstp->rq_auth_data;
890916
u32 integ_len, rseqno, maj_stat;
891-
int stat = -EINVAL;
892917
struct xdr_netobj mic;
893918
struct xdr_buf integ_buf;
894919

895-
mic.data = NULL;
896-
897920
/* NFS READ normally uses splice to send data in-place. However
898921
* the data in cache can change after the reply's MIC is computed
899922
* but before the RPC reply is sent. To prevent the client from
@@ -917,11 +940,9 @@ unwrap_integ_data(struct svc_rqst *rqstp, struct xdr_buf *buf, u32 seq, struct g
917940
/* copy out mic... */
918941
if (read_u32_from_xdr_buf(buf, integ_len, &mic.len))
919942
goto unwrap_failed;
920-
if (mic.len > RPC_MAX_AUTH_SIZE)
921-
goto unwrap_failed;
922-
mic.data = kmalloc(mic.len, GFP_KERNEL);
923-
if (!mic.data)
943+
if (mic.len > sizeof(gsd->gsd_scratch))
924944
goto unwrap_failed;
945+
mic.data = gsd->gsd_scratch;
925946
if (read_bytes_from_xdr_buf(buf, integ_len + 4, mic.data, mic.len))
926947
goto unwrap_failed;
927948
maj_stat = gss_verify_mic(ctx, &integ_buf, &mic);
@@ -932,20 +953,17 @@ unwrap_integ_data(struct svc_rqst *rqstp, struct xdr_buf *buf, u32 seq, struct g
932953
goto bad_seqno;
933954
/* trim off the mic and padding at the end before returning */
934955
xdr_buf_trim(buf, round_up_to_quad(mic.len) + 4);
935-
stat = 0;
936-
out:
937-
kfree(mic.data);
938-
return stat;
956+
return 0;
939957

940958
unwrap_failed:
941959
trace_rpcgss_svc_unwrap_failed(rqstp);
942-
goto out;
960+
return -EINVAL;
943961
bad_seqno:
944962
trace_rpcgss_svc_seqno_bad(rqstp, seq, rseqno);
945-
goto out;
963+
return -EINVAL;
946964
bad_mic:
947965
trace_rpcgss_svc_mic(rqstp, maj_stat);
948-
goto out;
966+
return -EINVAL;
949967
}
950968

951969
static inline int
@@ -1023,15 +1041,6 @@ unwrap_priv_data(struct svc_rqst *rqstp, struct xdr_buf *buf, u32 seq, struct gs
10231041
return -EINVAL;
10241042
}
10251043

1026-
struct gss_svc_data {
1027-
/* decoded gss client cred: */
1028-
struct rpc_gss_wire_cred clcred;
1029-
/* save a pointer to the beginning of the encoded verifier,
1030-
* for use in encryption/checksumming in svcauth_gss_release: */
1031-
__be32 *verf_start;
1032-
struct rsc *rsci;
1033-
};
1034-
10351044
static int
10361045
svcauth_gss_set_client(struct svc_rqst *rqstp)
10371046
{

0 commit comments

Comments
 (0)