Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 1f4c86c0 authored by Trond Myklebust's avatar Trond Myklebust
Browse files

NFS: Don't use GFP_KERNEL in rpcsec_gss downcalls



Again, we can deadlock if the memory reclaim triggers a writeback that
requires a rpcsec_gss credential lookup.

Signed-off-by: default avatarTrond Myklebust <Trond.Myklebust@netapp.com>
parent 8535b2be
Loading
Loading
Loading
Loading
+4 −2
Original line number Original line Diff line number Diff line
@@ -35,7 +35,8 @@ int gss_import_sec_context(
		const void*		input_token,
		const void*		input_token,
		size_t			bufsize,
		size_t			bufsize,
		struct gss_api_mech	*mech,
		struct gss_api_mech	*mech,
		struct gss_ctx		**ctx_id);
		struct gss_ctx		**ctx_id,
		gfp_t			gfp_mask);
u32 gss_get_mic(
u32 gss_get_mic(
		struct gss_ctx		*ctx_id,
		struct gss_ctx		*ctx_id,
		struct xdr_buf		*message,
		struct xdr_buf		*message,
@@ -89,7 +90,8 @@ struct gss_api_ops {
	int (*gss_import_sec_context)(
	int (*gss_import_sec_context)(
			const void		*input_token,
			const void		*input_token,
			size_t			bufsize,
			size_t			bufsize,
			struct gss_ctx		*ctx_id);
			struct gss_ctx		*ctx_id,
			gfp_t			gfp_mask);
	u32 (*gss_get_mic)(
	u32 (*gss_get_mic)(
			struct gss_ctx		*ctx_id,
			struct gss_ctx		*ctx_id,
			struct xdr_buf		*message,
			struct xdr_buf		*message,
+2 −1
Original line number Original line Diff line number Diff line
@@ -295,7 +295,8 @@ u32
krb5_derive_key(const struct gss_krb5_enctype *gk5e,
krb5_derive_key(const struct gss_krb5_enctype *gk5e,
		const struct xdr_netobj *inkey,
		const struct xdr_netobj *inkey,
		struct xdr_netobj *outkey,
		struct xdr_netobj *outkey,
		const struct xdr_netobj *in_constant);
		const struct xdr_netobj *in_constant,
		gfp_t gfp_mask);


u32
u32
gss_krb5_des3_make_key(const struct gss_krb5_enctype *gk5e,
gss_krb5_des3_make_key(const struct gss_krb5_enctype *gk5e,
+1 −1
Original line number Original line Diff line number Diff line
@@ -229,7 +229,7 @@ gss_fill_context(const void *p, const void *end, struct gss_cl_ctx *ctx, struct
		p = ERR_PTR(-EFAULT);
		p = ERR_PTR(-EFAULT);
		goto err;
		goto err;
	}
	}
	ret = gss_import_sec_context(p, seclen, gm, &ctx->gc_gss_ctx);
	ret = gss_import_sec_context(p, seclen, gm, &ctx->gc_gss_ctx, GFP_NOFS);
	if (ret < 0) {
	if (ret < 0) {
		p = ERR_PTR(ret);
		p = ERR_PTR(ret);
		goto err;
		goto err;
+5 −4
Original line number Original line Diff line number Diff line
@@ -150,7 +150,8 @@ static void krb5_nfold(u32 inbits, const u8 *in,
u32 krb5_derive_key(const struct gss_krb5_enctype *gk5e,
u32 krb5_derive_key(const struct gss_krb5_enctype *gk5e,
		    const struct xdr_netobj *inkey,
		    const struct xdr_netobj *inkey,
		    struct xdr_netobj *outkey,
		    struct xdr_netobj *outkey,
		    const struct xdr_netobj *in_constant)
		    const struct xdr_netobj *in_constant,
		    gfp_t gfp_mask)
{
{
	size_t blocksize, keybytes, keylength, n;
	size_t blocksize, keybytes, keylength, n;
	unsigned char *inblockdata, *outblockdata, *rawkey;
	unsigned char *inblockdata, *outblockdata, *rawkey;
@@ -175,15 +176,15 @@ u32 krb5_derive_key(const struct gss_krb5_enctype *gk5e,
	/* allocate and set up buffers */
	/* allocate and set up buffers */


	ret = ENOMEM;
	ret = ENOMEM;
	inblockdata = kmalloc(blocksize, GFP_KERNEL);
	inblockdata = kmalloc(blocksize, gfp_mask);
	if (inblockdata == NULL)
	if (inblockdata == NULL)
		goto err_free_cipher;
		goto err_free_cipher;


	outblockdata = kmalloc(blocksize, GFP_KERNEL);
	outblockdata = kmalloc(blocksize, gfp_mask);
	if (outblockdata == NULL)
	if (outblockdata == NULL)
		goto err_free_in;
		goto err_free_in;


	rawkey = kmalloc(keybytes, GFP_KERNEL);
	rawkey = kmalloc(keybytes, gfp_mask);
	if (rawkey == NULL)
	if (rawkey == NULL)
		goto err_free_out;
		goto err_free_out;


+18 −16
Original line number Original line Diff line number Diff line
@@ -369,7 +369,7 @@ set_cdata(u8 cdata[GSS_KRB5_K5CLENGTH], u32 usage, u8 seed)
}
}


static int
static int
context_derive_keys_des3(struct krb5_ctx *ctx)
context_derive_keys_des3(struct krb5_ctx *ctx, gfp_t gfp_mask)
{
{
	struct xdr_netobj c, keyin, keyout;
	struct xdr_netobj c, keyin, keyout;
	u8 cdata[GSS_KRB5_K5CLENGTH];
	u8 cdata[GSS_KRB5_K5CLENGTH];
@@ -396,7 +396,7 @@ context_derive_keys_des3(struct krb5_ctx *ctx)
	/* derive cksum */
	/* derive cksum */
	set_cdata(cdata, KG_USAGE_SIGN, KEY_USAGE_SEED_CHECKSUM);
	set_cdata(cdata, KG_USAGE_SIGN, KEY_USAGE_SEED_CHECKSUM);
	keyout.data = ctx->cksum;
	keyout.data = ctx->cksum;
	err = krb5_derive_key(ctx->gk5e, &keyin, &keyout, &c);
	err = krb5_derive_key(ctx->gk5e, &keyin, &keyout, &c, gfp_mask);
	if (err) {
	if (err) {
		dprintk("%s: Error %d deriving cksum key\n",
		dprintk("%s: Error %d deriving cksum key\n",
			__func__, err);
			__func__, err);
@@ -487,7 +487,7 @@ out_err:
}
}


static int
static int
context_derive_keys_new(struct krb5_ctx *ctx)
context_derive_keys_new(struct krb5_ctx *ctx, gfp_t gfp_mask)
{
{
	struct xdr_netobj c, keyin, keyout;
	struct xdr_netobj c, keyin, keyout;
	u8 cdata[GSS_KRB5_K5CLENGTH];
	u8 cdata[GSS_KRB5_K5CLENGTH];
@@ -503,7 +503,7 @@ context_derive_keys_new(struct krb5_ctx *ctx)
	/* initiator seal encryption */
	/* initiator seal encryption */
	set_cdata(cdata, KG_USAGE_INITIATOR_SEAL, KEY_USAGE_SEED_ENCRYPTION);
	set_cdata(cdata, KG_USAGE_INITIATOR_SEAL, KEY_USAGE_SEED_ENCRYPTION);
	keyout.data = ctx->initiator_seal;
	keyout.data = ctx->initiator_seal;
	err = krb5_derive_key(ctx->gk5e, &keyin, &keyout, &c);
	err = krb5_derive_key(ctx->gk5e, &keyin, &keyout, &c, gfp_mask);
	if (err) {
	if (err) {
		dprintk("%s: Error %d deriving initiator_seal key\n",
		dprintk("%s: Error %d deriving initiator_seal key\n",
			__func__, err);
			__func__, err);
@@ -518,7 +518,7 @@ context_derive_keys_new(struct krb5_ctx *ctx)
	/* acceptor seal encryption */
	/* acceptor seal encryption */
	set_cdata(cdata, KG_USAGE_ACCEPTOR_SEAL, KEY_USAGE_SEED_ENCRYPTION);
	set_cdata(cdata, KG_USAGE_ACCEPTOR_SEAL, KEY_USAGE_SEED_ENCRYPTION);
	keyout.data = ctx->acceptor_seal;
	keyout.data = ctx->acceptor_seal;
	err = krb5_derive_key(ctx->gk5e, &keyin, &keyout, &c);
	err = krb5_derive_key(ctx->gk5e, &keyin, &keyout, &c, gfp_mask);
	if (err) {
	if (err) {
		dprintk("%s: Error %d deriving acceptor_seal key\n",
		dprintk("%s: Error %d deriving acceptor_seal key\n",
			__func__, err);
			__func__, err);
@@ -533,7 +533,7 @@ context_derive_keys_new(struct krb5_ctx *ctx)
	/* initiator sign checksum */
	/* initiator sign checksum */
	set_cdata(cdata, KG_USAGE_INITIATOR_SIGN, KEY_USAGE_SEED_CHECKSUM);
	set_cdata(cdata, KG_USAGE_INITIATOR_SIGN, KEY_USAGE_SEED_CHECKSUM);
	keyout.data = ctx->initiator_sign;
	keyout.data = ctx->initiator_sign;
	err = krb5_derive_key(ctx->gk5e, &keyin, &keyout, &c);
	err = krb5_derive_key(ctx->gk5e, &keyin, &keyout, &c, gfp_mask);
	if (err) {
	if (err) {
		dprintk("%s: Error %d deriving initiator_sign key\n",
		dprintk("%s: Error %d deriving initiator_sign key\n",
			__func__, err);
			__func__, err);
@@ -543,7 +543,7 @@ context_derive_keys_new(struct krb5_ctx *ctx)
	/* acceptor sign checksum */
	/* acceptor sign checksum */
	set_cdata(cdata, KG_USAGE_ACCEPTOR_SIGN, KEY_USAGE_SEED_CHECKSUM);
	set_cdata(cdata, KG_USAGE_ACCEPTOR_SIGN, KEY_USAGE_SEED_CHECKSUM);
	keyout.data = ctx->acceptor_sign;
	keyout.data = ctx->acceptor_sign;
	err = krb5_derive_key(ctx->gk5e, &keyin, &keyout, &c);
	err = krb5_derive_key(ctx->gk5e, &keyin, &keyout, &c, gfp_mask);
	if (err) {
	if (err) {
		dprintk("%s: Error %d deriving acceptor_sign key\n",
		dprintk("%s: Error %d deriving acceptor_sign key\n",
			__func__, err);
			__func__, err);
@@ -553,7 +553,7 @@ context_derive_keys_new(struct krb5_ctx *ctx)
	/* initiator seal integrity */
	/* initiator seal integrity */
	set_cdata(cdata, KG_USAGE_INITIATOR_SEAL, KEY_USAGE_SEED_INTEGRITY);
	set_cdata(cdata, KG_USAGE_INITIATOR_SEAL, KEY_USAGE_SEED_INTEGRITY);
	keyout.data = ctx->initiator_integ;
	keyout.data = ctx->initiator_integ;
	err = krb5_derive_key(ctx->gk5e, &keyin, &keyout, &c);
	err = krb5_derive_key(ctx->gk5e, &keyin, &keyout, &c, gfp_mask);
	if (err) {
	if (err) {
		dprintk("%s: Error %d deriving initiator_integ key\n",
		dprintk("%s: Error %d deriving initiator_integ key\n",
			__func__, err);
			__func__, err);
@@ -563,7 +563,7 @@ context_derive_keys_new(struct krb5_ctx *ctx)
	/* acceptor seal integrity */
	/* acceptor seal integrity */
	set_cdata(cdata, KG_USAGE_ACCEPTOR_SEAL, KEY_USAGE_SEED_INTEGRITY);
	set_cdata(cdata, KG_USAGE_ACCEPTOR_SEAL, KEY_USAGE_SEED_INTEGRITY);
	keyout.data = ctx->acceptor_integ;
	keyout.data = ctx->acceptor_integ;
	err = krb5_derive_key(ctx->gk5e, &keyin, &keyout, &c);
	err = krb5_derive_key(ctx->gk5e, &keyin, &keyout, &c, gfp_mask);
	if (err) {
	if (err) {
		dprintk("%s: Error %d deriving acceptor_integ key\n",
		dprintk("%s: Error %d deriving acceptor_integ key\n",
			__func__, err);
			__func__, err);
@@ -598,7 +598,8 @@ out_err:
}
}


static int
static int
gss_import_v2_context(const void *p, const void *end, struct krb5_ctx *ctx)
gss_import_v2_context(const void *p, const void *end, struct krb5_ctx *ctx,
		gfp_t gfp_mask)
{
{
	int keylen;
	int keylen;


@@ -645,7 +646,7 @@ gss_import_v2_context(const void *p, const void *end, struct krb5_ctx *ctx)
	}
	}


	ctx->mech_used.data = kmemdup(gss_kerberos_mech.gm_oid.data,
	ctx->mech_used.data = kmemdup(gss_kerberos_mech.gm_oid.data,
				      gss_kerberos_mech.gm_oid.len, GFP_KERNEL);
				      gss_kerberos_mech.gm_oid.len, gfp_mask);
	if (unlikely(ctx->mech_used.data == NULL)) {
	if (unlikely(ctx->mech_used.data == NULL)) {
		p = ERR_PTR(-ENOMEM);
		p = ERR_PTR(-ENOMEM);
		goto out_err;
		goto out_err;
@@ -654,12 +655,12 @@ gss_import_v2_context(const void *p, const void *end, struct krb5_ctx *ctx)


	switch (ctx->enctype) {
	switch (ctx->enctype) {
	case ENCTYPE_DES3_CBC_RAW:
	case ENCTYPE_DES3_CBC_RAW:
		return context_derive_keys_des3(ctx);
		return context_derive_keys_des3(ctx, gfp_mask);
	case ENCTYPE_ARCFOUR_HMAC:
	case ENCTYPE_ARCFOUR_HMAC:
		return context_derive_keys_rc4(ctx);
		return context_derive_keys_rc4(ctx);
	case ENCTYPE_AES128_CTS_HMAC_SHA1_96:
	case ENCTYPE_AES128_CTS_HMAC_SHA1_96:
	case ENCTYPE_AES256_CTS_HMAC_SHA1_96:
	case ENCTYPE_AES256_CTS_HMAC_SHA1_96:
		return context_derive_keys_new(ctx);
		return context_derive_keys_new(ctx, gfp_mask);
	default:
	default:
		return -EINVAL;
		return -EINVAL;
	}
	}
@@ -670,20 +671,21 @@ out_err:


static int
static int
gss_import_sec_context_kerberos(const void *p, size_t len,
gss_import_sec_context_kerberos(const void *p, size_t len,
				struct gss_ctx *ctx_id)
				struct gss_ctx *ctx_id,
				gfp_t gfp_mask)
{
{
	const void *end = (const void *)((const char *)p + len);
	const void *end = (const void *)((const char *)p + len);
	struct  krb5_ctx *ctx;
	struct  krb5_ctx *ctx;
	int ret;
	int ret;


	ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
	ctx = kzalloc(sizeof(*ctx), gfp_mask);
	if (ctx == NULL)
	if (ctx == NULL)
		return -ENOMEM;
		return -ENOMEM;


	if (len == 85)
	if (len == 85)
		ret = gss_import_v1_context(p, end, ctx);
		ret = gss_import_v1_context(p, end, ctx);
	else
	else
		ret = gss_import_v2_context(p, end, ctx);
		ret = gss_import_v2_context(p, end, ctx, gfp_mask);


	if (ret == 0)
	if (ret == 0)
		ctx_id->internal_ctx_id = ctx;
		ctx_id->internal_ctx_id = ctx;
Loading