Skip to content

Commit

Permalink
SUNRPC: Replace krb5_seq_lock with a lockless scheme
Browse files Browse the repository at this point in the history
Signed-off-by: Trond Myklebust <trond.myklebust@hammerspace.com>
  • Loading branch information
Trond Myklebust committed Sep 30, 2018
1 parent 0c1c19f commit 571ed1f
Show file tree
Hide file tree
Showing 3 changed files with 30 additions and 18 deletions.
3 changes: 2 additions & 1 deletion include/linux/sunrpc/gss_krb5.h
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,8 @@ struct krb5_ctx {
u8 acceptor_integ[GSS_KRB5_MAX_KEYLEN];
};

extern spinlock_t krb5_seq_lock;
extern u32 gss_seq_send_fetch_and_inc(struct krb5_ctx *ctx);
extern u64 gss_seq_send64_fetch_and_inc(struct krb5_ctx *ctx);

/* The length of the Kerberos GSS token header */
#define GSS_KRB5_TOK_HDR_LEN (16)
Expand Down
37 changes: 26 additions & 11 deletions net/sunrpc/auth_gss/gss_krb5_seal.c
Original file line number Diff line number Diff line change
Expand Up @@ -68,8 +68,6 @@
# define RPCDBG_FACILITY RPCDBG_AUTH
#endif

DEFINE_SPINLOCK(krb5_seq_lock);

static void *
setup_token(struct krb5_ctx *ctx, struct xdr_netobj *token)
{
Expand Down Expand Up @@ -124,6 +122,30 @@ setup_token_v2(struct krb5_ctx *ctx, struct xdr_netobj *token)
return krb5_hdr;
}

u32
gss_seq_send_fetch_and_inc(struct krb5_ctx *ctx)
{
u32 old, seq_send = READ_ONCE(ctx->seq_send);

do {
old = seq_send;
seq_send = cmpxchg(&ctx->seq_send, old, old + 1);
} while (old != seq_send);
return seq_send;
}

u64
gss_seq_send64_fetch_and_inc(struct krb5_ctx *ctx)
{
u64 old, seq_send = READ_ONCE(ctx->seq_send);

do {
old = seq_send;
seq_send = cmpxchg(&ctx->seq_send64, old, old + 1);
} while (old != seq_send);
return seq_send;
}

static u32
gss_get_mic_v1(struct krb5_ctx *ctx, struct xdr_buf *text,
struct xdr_netobj *token)
Expand Down Expand Up @@ -154,9 +176,7 @@ gss_get_mic_v1(struct krb5_ctx *ctx, struct xdr_buf *text,

memcpy(ptr + GSS_KRB5_TOK_HDR_LEN, md5cksum.data, md5cksum.len);

spin_lock(&krb5_seq_lock);
seq_send = ctx->seq_send++;
spin_unlock(&krb5_seq_lock);
seq_send = gss_seq_send_fetch_and_inc(ctx);

if (krb5_make_seq_num(ctx, ctx->seq, ctx->initiate ? 0 : 0xff,
seq_send, ptr + GSS_KRB5_TOK_HDR_LEN, ptr + 8))
Expand All @@ -174,7 +194,6 @@ gss_get_mic_v2(struct krb5_ctx *ctx, struct xdr_buf *text,
.data = cksumdata};
void *krb5_hdr;
s32 now;
u64 seq_send;
u8 *cksumkey;
unsigned int cksum_usage;
__be64 seq_send_be64;
Expand All @@ -185,11 +204,7 @@ gss_get_mic_v2(struct krb5_ctx *ctx, struct xdr_buf *text,

/* Set up the sequence number. Now 64-bits in clear
* text and w/o direction indicator */
spin_lock(&krb5_seq_lock);
seq_send = ctx->seq_send64++;
spin_unlock(&krb5_seq_lock);

seq_send_be64 = cpu_to_be64(seq_send);
seq_send_be64 = cpu_to_be64(gss_seq_send64_fetch_and_inc(ctx));
memcpy(krb5_hdr + 8, (char *) &seq_send_be64, 8);

if (ctx->initiate) {
Expand Down
8 changes: 2 additions & 6 deletions net/sunrpc/auth_gss/gss_krb5_wrap.c
Original file line number Diff line number Diff line change
Expand Up @@ -228,9 +228,7 @@ gss_wrap_kerberos_v1(struct krb5_ctx *kctx, int offset,

memcpy(ptr + GSS_KRB5_TOK_HDR_LEN, md5cksum.data, md5cksum.len);

spin_lock(&krb5_seq_lock);
seq_send = kctx->seq_send++;
spin_unlock(&krb5_seq_lock);
seq_send = gss_seq_send_fetch_and_inc(kctx);

/* XXX would probably be more efficient to compute checksum
* and encrypt at the same time: */
Expand Down Expand Up @@ -477,9 +475,7 @@ gss_wrap_kerberos_v2(struct krb5_ctx *kctx, u32 offset,
*be16ptr++ = 0;

be64ptr = (__be64 *)be16ptr;
spin_lock(&krb5_seq_lock);
*be64ptr = cpu_to_be64(kctx->seq_send64++);
spin_unlock(&krb5_seq_lock);
*be64ptr = cpu_to_be64(gss_seq_send64_fetch_and_inc(kctx));

err = (*kctx->gk5e->encrypt_v2)(kctx, offset, buf, pages);
if (err)
Expand Down

0 comments on commit 571ed1f

Please sign in to comment.