Commit 87a367f1 authored by Linus Torvalds's avatar Linus Torvalds
Browse files

Merge tag 'ceph-for-7.0-rc1' of https://github.com/ceph/ceph-client

Pull ceph updates from Ilya Dryomov:
 "This adds support for the upcoming aes256k key type in CephX that is
  based on Kerberos 5 and brings a bunch of assorted CephFS fixes from
  Ethan and Sam. One of Sam's patches in particular undoes a change in
  the fscrypt area that had an inadvertent side effect of making CephFS
  behave as if mounted with wsize=4096 and leading to the corresponding
  degradation in performance, especially for sequential writes"

* tag 'ceph-for-7.0-rc1' of https://github.com/ceph/ceph-client:
  ceph: assert loop invariants in ceph_writepages_start()
  ceph: remove error return from ceph_process_folio_batch()
  ceph: fix write storm on fscrypted files
  ceph: do not propagate page array emplacement errors as batch errors
  ceph: supply snapshot context in ceph_uninline_data()
  ceph: supply snapshot context in ceph_zero_partial_object()
  libceph: adapt ceph_x_challenge_blob hashing and msgr1 message signing
  libceph: add support for CEPH_CRYPTO_AES256KRB5
  libceph: introduce ceph_crypto_key_prepare()
  libceph: generalize ceph_x_encrypt_offset() and ceph_x_encrypt_buflen()
  libceph: define and enforce CEPH_MAX_KEY_LEN
parents 0ba83f09 cfdde144
Loading
Loading
Loading
Loading
+32 −15
Original line number Diff line number Diff line
@@ -1000,7 +1000,8 @@ unsigned int ceph_define_write_size(struct address_space *mapping)
{
	struct inode *inode = mapping->host;
	struct ceph_fs_client *fsc = ceph_inode_to_fs_client(inode);
	unsigned int wsize = i_blocksize(inode);
	struct ceph_inode_info *ci = ceph_inode(inode);
	unsigned int wsize = ci->i_layout.stripe_unit;

	if (fsc->mount_options->wsize < wsize)
		wsize = fsc->mount_options->wsize;
@@ -1283,7 +1284,7 @@ static inline int move_dirty_folio_in_page_array(struct address_space *mapping,
}

static
int ceph_process_folio_batch(struct address_space *mapping,
void ceph_process_folio_batch(struct address_space *mapping,
			      struct writeback_control *wbc,
			      struct ceph_writeback_ctl *ceph_wbc)
{
@@ -1292,7 +1293,7 @@ int ceph_process_folio_batch(struct address_space *mapping,
	struct ceph_client *cl = fsc->client;
	struct folio *folio = NULL;
	unsigned i;
	int rc = 0;
	int rc;

	for (i = 0; can_next_page_be_processed(ceph_wbc, i); i++) {
		folio = ceph_wbc->fbatch.folios[i];
@@ -1322,12 +1323,10 @@ int ceph_process_folio_batch(struct address_space *mapping,
		rc = ceph_check_page_before_write(mapping, wbc,
						  ceph_wbc, folio);
		if (rc == -ENODATA) {
			rc = 0;
			folio_unlock(folio);
			ceph_wbc->fbatch.folios[i] = NULL;
			continue;
		} else if (rc == -E2BIG) {
			rc = 0;
			folio_unlock(folio);
			ceph_wbc->fbatch.folios[i] = NULL;
			break;
@@ -1379,8 +1378,6 @@ int ceph_process_folio_batch(struct address_space *mapping,
	}

	ceph_wbc->processed_in_fbatch = i;

	return rc;
}

static inline
@@ -1666,7 +1663,9 @@ static int ceph_writepages_start(struct address_space *mapping,
		tag_pages_for_writeback(mapping, ceph_wbc.index, ceph_wbc.end);

	while (!has_writeback_done(&ceph_wbc)) {
		ceph_wbc.locked_pages = 0;
		BUG_ON(ceph_wbc.locked_pages);
		BUG_ON(ceph_wbc.pages);

		ceph_wbc.max_pages = ceph_wbc.wsize >> PAGE_SHIFT;

get_more_pages:
@@ -1684,10 +1683,8 @@ static int ceph_writepages_start(struct address_space *mapping,
			break;

process_folio_batch:
		rc = ceph_process_folio_batch(mapping, wbc, &ceph_wbc);
		ceph_process_folio_batch(mapping, wbc, &ceph_wbc);
		ceph_shift_unused_folios_left(&ceph_wbc.fbatch);
		if (rc)
			goto release_folios;

		/* did we get anything? */
		if (!ceph_wbc.locked_pages)
@@ -2199,6 +2196,7 @@ int ceph_uninline_data(struct file *file)
	struct ceph_osd_request *req = NULL;
	struct ceph_cap_flush *prealloc_cf = NULL;
	struct folio *folio = NULL;
	struct ceph_snap_context *snapc = NULL;
	u64 inline_version = CEPH_INLINE_NONE;
	struct page *pages[1];
	int err = 0;
@@ -2226,6 +2224,24 @@ int ceph_uninline_data(struct file *file)
	if (inline_version == 1) /* initial version, no data */
		goto out_uninline;

	down_read(&fsc->mdsc->snap_rwsem);
	spin_lock(&ci->i_ceph_lock);
	if (__ceph_have_pending_cap_snap(ci)) {
		struct ceph_cap_snap *capsnap =
				list_last_entry(&ci->i_cap_snaps,
						struct ceph_cap_snap,
						ci_item);
		snapc = ceph_get_snap_context(capsnap->context);
	} else {
		if (!ci->i_head_snapc) {
			ci->i_head_snapc = ceph_get_snap_context(
				ci->i_snap_realm->cached_context);
		}
		snapc = ceph_get_snap_context(ci->i_head_snapc);
	}
	spin_unlock(&ci->i_ceph_lock);
	up_read(&fsc->mdsc->snap_rwsem);

	folio = read_mapping_folio(inode->i_mapping, 0, file);
	if (IS_ERR(folio)) {
		err = PTR_ERR(folio);
@@ -2241,7 +2257,7 @@ int ceph_uninline_data(struct file *file)
	req = ceph_osdc_new_request(&fsc->client->osdc, &ci->i_layout,
				    ceph_vino(inode), 0, &len, 0, 1,
				    CEPH_OSD_OP_CREATE, CEPH_OSD_FLAG_WRITE,
				    NULL, 0, 0, false);
				    snapc, 0, 0, false);
	if (IS_ERR(req)) {
		err = PTR_ERR(req);
		goto out_unlock;
@@ -2257,7 +2273,7 @@ int ceph_uninline_data(struct file *file)
	req = ceph_osdc_new_request(&fsc->client->osdc, &ci->i_layout,
				    ceph_vino(inode), 0, &len, 1, 3,
				    CEPH_OSD_OP_WRITE, CEPH_OSD_FLAG_WRITE,
				    NULL, ci->i_truncate_seq,
				    snapc, ci->i_truncate_seq,
				    ci->i_truncate_size, false);
	if (IS_ERR(req)) {
		err = PTR_ERR(req);
@@ -2320,6 +2336,7 @@ int ceph_uninline_data(struct file *file)
		folio_put(folio);
	}
out:
	ceph_put_snap_context(snapc);
	ceph_free_cap_flush(prealloc_cf);
	doutc(cl, "%llx.%llx inline_version %llu = %d\n",
	      ceph_vinop(inode), inline_version, err);
+16 −1
Original line number Diff line number Diff line
@@ -2568,6 +2568,7 @@ static int ceph_zero_partial_object(struct inode *inode,
	struct ceph_inode_info *ci = ceph_inode(inode);
	struct ceph_fs_client *fsc = ceph_inode_to_fs_client(inode);
	struct ceph_osd_request *req;
	struct ceph_snap_context *snapc;
	int ret = 0;
	loff_t zero = 0;
	int op;
@@ -2582,12 +2583,25 @@ static int ceph_zero_partial_object(struct inode *inode,
		op = CEPH_OSD_OP_ZERO;
	}

	spin_lock(&ci->i_ceph_lock);
	if (__ceph_have_pending_cap_snap(ci)) {
		struct ceph_cap_snap *capsnap =
				list_last_entry(&ci->i_cap_snaps,
						struct ceph_cap_snap,
						ci_item);
		snapc = ceph_get_snap_context(capsnap->context);
	} else {
		BUG_ON(!ci->i_head_snapc);
		snapc = ceph_get_snap_context(ci->i_head_snapc);
	}
	spin_unlock(&ci->i_ceph_lock);

	req = ceph_osdc_new_request(&fsc->client->osdc, &ci->i_layout,
					ceph_vino(inode),
					offset, length,
					0, 1, op,
					CEPH_OSD_FLAG_WRITE,
					NULL, 0, 0, false);
					snapc, 0, 0, false);
	if (IS_ERR(req)) {
		ret = PTR_ERR(req);
		goto out;
@@ -2601,6 +2615,7 @@ static int ceph_zero_partial_object(struct inode *inode,
	ceph_osdc_put_request(req);

out:
	ceph_put_snap_context(snapc);
	return ret;
}

+3 −2
Original line number Diff line number Diff line
@@ -91,6 +91,7 @@ struct ceph_dir_layout {
/* crypto algorithms */
#define CEPH_CRYPTO_NONE       0x0
#define CEPH_CRYPTO_AES        0x1
#define CEPH_CRYPTO_AES256KRB5 0x2 /* AES256-CTS-HMAC384-192 */

#define CEPH_AES_IV "cephsageyudagreg"

+1 −0
Original line number Diff line number Diff line
@@ -6,6 +6,7 @@ config CEPH_LIB
	select CRYPTO_AES
	select CRYPTO_CBC
	select CRYPTO_GCM
	select CRYPTO_KRB5
	select CRYPTO_LIB_SHA256
	select CRYPTO
	select KEYS
+142 −53
Original line number Diff line number Diff line
@@ -17,6 +17,22 @@
#include "auth_x.h"
#include "auth_x_protocol.h"

static const u32 ticket_key_usages[] = {
	CEPHX_KEY_USAGE_TICKET_SESSION_KEY,
	CEPHX_KEY_USAGE_TICKET_BLOB,
	CEPHX_KEY_USAGE_AUTH_CONNECTION_SECRET
};

static const u32 authorizer_key_usages[] = {
	CEPHX_KEY_USAGE_AUTHORIZE,
	CEPHX_KEY_USAGE_AUTHORIZE_CHALLENGE,
	CEPHX_KEY_USAGE_AUTHORIZE_REPLY
};

static const u32 client_key_usages[] = {
	CEPHX_KEY_USAGE_TICKET_SESSION_KEY
};

static void ceph_x_validate_tickets(struct ceph_auth_client *ac, int *pneed);

static int ceph_x_is_authenticated(struct ceph_auth_client *ac)
@@ -44,28 +60,41 @@ static int ceph_x_should_authenticate(struct ceph_auth_client *ac)
	return !!need;
}

static int ceph_x_encrypt_offset(void)
static int __ceph_x_encrypt_offset(const struct ceph_crypto_key *key)
{
	return sizeof(u32) + sizeof(struct ceph_x_encrypt_header);
	return ceph_crypt_data_offset(key) +
	       sizeof(struct ceph_x_encrypt_header);
}

static int ceph_x_encrypt_buflen(int ilen)
static int ceph_x_encrypt_offset(const struct ceph_crypto_key *key)
{
	return sizeof(u32) + __ceph_x_encrypt_offset(key);
}

/*
 * AES: ciphertext_len | hdr | data... | padding
 * AES256KRB5: ciphertext_len | confounder | hdr | data... | hmac
 */
static int ceph_x_encrypt_buflen(const struct ceph_crypto_key *key,
				 int data_len)
{
	return ceph_x_encrypt_offset() + ilen + 16;
	int encrypt_len = sizeof(struct ceph_x_encrypt_header) + data_len;
	return sizeof(u32) + ceph_crypt_buflen(key, encrypt_len);
}

static int ceph_x_encrypt(struct ceph_crypto_key *secret, void *buf,
			  int buf_len, int plaintext_len)
static int ceph_x_encrypt(const struct ceph_crypto_key *key, int usage_slot,
			  void *buf, int buf_len, int plaintext_len)
{
	struct ceph_x_encrypt_header *hdr = buf + sizeof(u32);
	struct ceph_x_encrypt_header *hdr;
	int ciphertext_len;
	int ret;

	hdr = buf + sizeof(u32) + ceph_crypt_data_offset(key);
	hdr->struct_v = 1;
	hdr->magic = cpu_to_le64(CEPHX_ENC_MAGIC);

	ret = ceph_crypt(secret, true, buf + sizeof(u32), buf_len - sizeof(u32),
			 plaintext_len + sizeof(struct ceph_x_encrypt_header),
	ret = ceph_crypt(key, usage_slot, true, buf + sizeof(u32),
			 buf_len - sizeof(u32), plaintext_len + sizeof(*hdr),
			 &ciphertext_len);
	if (ret)
		return ret;
@@ -74,18 +103,19 @@ static int ceph_x_encrypt(struct ceph_crypto_key *secret, void *buf,
	return sizeof(u32) + ciphertext_len;
}

static int __ceph_x_decrypt(struct ceph_crypto_key *secret, void *p,
			    int ciphertext_len)
static int __ceph_x_decrypt(const struct ceph_crypto_key *key, int usage_slot,
			    void *p, int ciphertext_len)
{
	struct ceph_x_encrypt_header *hdr = p;
	struct ceph_x_encrypt_header *hdr;
	int plaintext_len;
	int ret;

	ret = ceph_crypt(secret, false, p, ciphertext_len, ciphertext_len,
			 &plaintext_len);
	ret = ceph_crypt(key, usage_slot, false, p, ciphertext_len,
			 ciphertext_len, &plaintext_len);
	if (ret)
		return ret;

	hdr = p + ceph_crypt_data_offset(key);
	if (le64_to_cpu(hdr->magic) != CEPHX_ENC_MAGIC) {
		pr_err("%s bad magic\n", __func__);
		return -EINVAL;
@@ -94,7 +124,8 @@ static int __ceph_x_decrypt(struct ceph_crypto_key *secret, void *p,
	return plaintext_len - sizeof(*hdr);
}

static int ceph_x_decrypt(struct ceph_crypto_key *secret, void **p, void *end)
static int ceph_x_decrypt(const struct ceph_crypto_key *key, int usage_slot,
			  void **p, void *end)
{
	int ciphertext_len;
	int ret;
@@ -102,7 +133,7 @@ static int ceph_x_decrypt(struct ceph_crypto_key *secret, void **p, void *end)
	ceph_decode_32_safe(p, end, ciphertext_len, e_inval);
	ceph_decode_need(p, end, ciphertext_len, e_inval);

	ret = __ceph_x_decrypt(secret, *p, ciphertext_len);
	ret = __ceph_x_decrypt(key, usage_slot, *p, ciphertext_len);
	if (ret < 0)
		return ret;

@@ -193,8 +224,10 @@ static int process_one_ticket(struct ceph_auth_client *ac,
	}

	/* blob for me */
	dp = *p + ceph_x_encrypt_offset();
	ret = ceph_x_decrypt(secret, p, end);
	dp = *p + ceph_x_encrypt_offset(secret);
	ret = ceph_x_decrypt(secret,
			     0 /* CEPHX_KEY_USAGE_TICKET_SESSION_KEY */,
			     p, end);
	if (ret < 0)
		goto out;
	dout(" decrypted %d bytes\n", ret);
@@ -208,6 +241,11 @@ static int process_one_ticket(struct ceph_auth_client *ac,
	if (ret)
		goto out;

	ret = ceph_crypto_key_prepare(&new_session_key, ticket_key_usages,
				      ARRAY_SIZE(ticket_key_usages));
	if (ret)
		goto out;

	ceph_decode_need(&dp, dend, sizeof(struct ceph_timespec), bad);
	ceph_decode_timespec64(&validity, dp);
	dp += sizeof(struct ceph_timespec);
@@ -220,8 +258,10 @@ static int process_one_ticket(struct ceph_auth_client *ac,
	ceph_decode_8_safe(p, end, is_enc, bad);
	if (is_enc) {
		/* encrypted */
		tp = *p + ceph_x_encrypt_offset();
		ret = ceph_x_decrypt(&th->session_key, p, end);
		tp = *p + ceph_x_encrypt_offset(&th->session_key);
		ret = ceph_x_decrypt(&th->session_key,
				     1 /* CEPHX_KEY_USAGE_TICKET_BLOB */,
				     p, end);
		if (ret < 0)
			goto out;
		dout(" encrypted ticket, decrypted %d bytes\n", ret);
@@ -312,7 +352,7 @@ static int encrypt_authorizer(struct ceph_x_authorizer *au,
	p = (void *)(msg_a + 1) + le32_to_cpu(msg_a->ticket_blob.blob_len);
	end = au->buf->vec.iov_base + au->buf->vec.iov_len;

	msg_b = p + ceph_x_encrypt_offset();
	msg_b = p + ceph_x_encrypt_offset(&au->session_key);
	msg_b->struct_v = 2;
	msg_b->nonce = cpu_to_le64(au->nonce);
	if (server_challenge) {
@@ -324,7 +364,9 @@ static int encrypt_authorizer(struct ceph_x_authorizer *au,
		msg_b->server_challenge_plus_one = 0;
	}

	ret = ceph_x_encrypt(&au->session_key, p, end - p, sizeof(*msg_b));
	ret = ceph_x_encrypt(&au->session_key,
			     0 /* CEPHX_KEY_USAGE_AUTHORIZE */,
			     p, end - p, sizeof(*msg_b));
	if (ret < 0)
		return ret;

@@ -367,8 +409,13 @@ static int ceph_x_build_authorizer(struct ceph_auth_client *ac,
	if (ret)
		goto out_au;

	ret = ceph_crypto_key_prepare(&au->session_key, authorizer_key_usages,
				      ARRAY_SIZE(authorizer_key_usages));
	if (ret)
		goto out_au;

	maxlen = sizeof(*msg_a) + ticket_blob_len +
		ceph_x_encrypt_buflen(sizeof(*msg_b));
		ceph_x_encrypt_buflen(&au->session_key, sizeof(*msg_b));
	dout("  need len %d\n", maxlen);
	if (au->buf && au->buf->alloc_len < maxlen) {
		ceph_buffer_put(au->buf);
@@ -506,8 +553,7 @@ static int ceph_x_build_request(struct ceph_auth_client *ac,
	if (need & CEPH_ENTITY_TYPE_AUTH) {
		struct ceph_x_authenticate *auth = (void *)(head + 1);
		void *enc_buf = xi->auth_authorizer.enc_buf;
		struct ceph_x_challenge_blob *blob = enc_buf +
							ceph_x_encrypt_offset();
		struct ceph_x_challenge_blob *blob;
		u64 *u;

		p = auth + 1;
@@ -517,14 +563,29 @@ static int ceph_x_build_request(struct ceph_auth_client *ac,
		dout(" get_auth_session_key\n");
		head->op = cpu_to_le16(CEPHX_GET_AUTH_SESSION_KEY);

		/* encrypt and hash */
		if (xi->secret.type == CEPH_CRYPTO_AES) {
			blob = enc_buf + ceph_x_encrypt_offset(&xi->secret);
		} else {
			BUILD_BUG_ON(SHA256_DIGEST_SIZE + sizeof(*blob) >
				     CEPHX_AU_ENC_BUF_LEN);
			blob = enc_buf + SHA256_DIGEST_SIZE;
		}

		get_random_bytes(&auth->client_challenge, sizeof(u64));
		blob->client_challenge = auth->client_challenge;
		blob->server_challenge = cpu_to_le64(xi->server_challenge);
		ret = ceph_x_encrypt(&xi->secret, enc_buf, CEPHX_AU_ENC_BUF_LEN,

		if (xi->secret.type == CEPH_CRYPTO_AES) {
			ret = ceph_x_encrypt(&xi->secret, 0 /* dummy */,
					     enc_buf, CEPHX_AU_ENC_BUF_LEN,
					     sizeof(*blob));
			if (ret < 0)
				return ret;
		} else {
			ceph_hmac_sha256(&xi->secret, blob, sizeof(*blob),
					 enc_buf);
			ret = SHA256_DIGEST_SIZE;
		}

		auth->struct_v = 3;  /* nautilus+ */
		auth->key = 0;
@@ -634,8 +695,10 @@ static int handle_auth_session_key(struct ceph_auth_client *ac, u64 global_id,
	ceph_decode_need(p, end, len, e_inval);
	dout("%s connection secret blob len %d\n", __func__, len);
	if (len > 0) {
		dp = *p + ceph_x_encrypt_offset();
		ret = ceph_x_decrypt(&th->session_key, p, *p + len);
		dp = *p + ceph_x_encrypt_offset(&th->session_key);
		ret = ceph_x_decrypt(&th->session_key,
				     2 /* CEPHX_KEY_USAGE_AUTH_CONNECTION_SECRET */,
				     p, *p + len);
		if (ret < 0)
			return ret;

@@ -799,12 +862,14 @@ static int decrypt_authorizer_challenge(struct ceph_crypto_key *secret,
	int ret;

	/* no leading len */
	ret = __ceph_x_decrypt(secret, challenge, challenge_len);
	ret = __ceph_x_decrypt(secret,
			       1 /* CEPHX_KEY_USAGE_AUTHORIZE_CHALLENGE */,
			       challenge, challenge_len);
	if (ret < 0)
		return ret;

	dout("%s decrypted %d bytes\n", __func__, ret);
	dp = challenge + sizeof(struct ceph_x_encrypt_header);
	dp = challenge + __ceph_x_encrypt_offset(secret);
	dend = dp + ret;

	ceph_decode_skip_8(&dp, dend, e_inval);  /* struct_v */
@@ -851,8 +916,9 @@ static int decrypt_authorizer_reply(struct ceph_crypto_key *secret,
	u8 struct_v;
	int ret;

	dp = *p + ceph_x_encrypt_offset();
	ret = ceph_x_decrypt(secret, p, end);
	dp = *p + ceph_x_encrypt_offset(secret);
	ret = ceph_x_decrypt(secret, 2 /* CEPHX_KEY_USAGE_AUTHORIZE_REPLY */,
			     p, end);
	if (ret < 0)
		return ret;

@@ -974,7 +1040,8 @@ static int calc_signature(struct ceph_x_authorizer *au, struct ceph_msg *msg,
			__le32 front_crc;
			__le32 middle_crc;
			__le32 data_crc;
		} __packed *sigblock = enc_buf + ceph_x_encrypt_offset();
		} __packed *sigblock = enc_buf +
				       ceph_x_encrypt_offset(&au->session_key);

		sigblock->len = cpu_to_le32(4*sizeof(u32));
		sigblock->header_crc = msg->hdr.crc;
@@ -982,8 +1049,9 @@ static int calc_signature(struct ceph_x_authorizer *au, struct ceph_msg *msg,
		sigblock->middle_crc = msg->footer.middle_crc;
		sigblock->data_crc =  msg->footer.data_crc;

		ret = ceph_x_encrypt(&au->session_key, enc_buf,
				     CEPHX_AU_ENC_BUF_LEN, sizeof(*sigblock));
		ret = ceph_x_encrypt(&au->session_key, 0 /* dummy */,
				     enc_buf, CEPHX_AU_ENC_BUF_LEN,
				     sizeof(*sigblock));
		if (ret < 0)
			return ret;

@@ -998,11 +1066,19 @@ static int calc_signature(struct ceph_x_authorizer *au, struct ceph_msg *msg,
			__le32 data_crc;
			__le32 data_len;
			__le32 seq_lower_word;
		} __packed *sigblock = enc_buf;
		} __packed *sigblock;
		struct {
			__le64 a, b, c, d;
		} __packed *penc = enc_buf;
		int ciphertext_len;

		if (au->session_key.type == CEPH_CRYPTO_AES) {
			/* no leading len, no ceph_x_encrypt_header */
			sigblock = enc_buf;
		} else {
			BUILD_BUG_ON(SHA256_DIGEST_SIZE + sizeof(*sigblock) >
				     CEPHX_AU_ENC_BUF_LEN);
			sigblock = enc_buf + SHA256_DIGEST_SIZE;
		}

		sigblock->header_crc = msg->hdr.crc;
		sigblock->front_crc = msg->footer.front_crc;
@@ -1013,12 +1089,18 @@ static int calc_signature(struct ceph_x_authorizer *au, struct ceph_msg *msg,
		sigblock->data_len = msg->hdr.data_len;
		sigblock->seq_lower_word = *(__le32 *)&msg->hdr.seq;

		/* no leading len, no ceph_x_encrypt_header */
		ret = ceph_crypt(&au->session_key, true, enc_buf,
				 CEPHX_AU_ENC_BUF_LEN, sizeof(*sigblock),
				 &ciphertext_len);
		if (au->session_key.type == CEPH_CRYPTO_AES) {
			int ciphertext_len; /* unused */

			ret = ceph_crypt(&au->session_key, 0 /* dummy */,
					 true, enc_buf, CEPHX_AU_ENC_BUF_LEN,
					 sizeof(*sigblock), &ciphertext_len);
			if (ret)
				return ret;
		} else {
			ceph_hmac_sha256(&au->session_key, sigblock,
					 sizeof(*sigblock), enc_buf);
		}

		*psig = penc->a ^ penc->b ^ penc->c ^ penc->d;
	}
@@ -1092,21 +1174,27 @@ int ceph_x_init(struct ceph_auth_client *ac)
	int ret;

	dout("ceph_x_init %p\n", ac);
	ret = -ENOMEM;
	xi = kzalloc(sizeof(*xi), GFP_NOFS);
	if (!xi)
		goto out;
		return -ENOMEM;

	ret = -EINVAL;
	if (!ac->key) {
		pr_err("no secret set (for auth_x protocol)\n");
		goto out_nomem;
		goto err_xi;
	}

	ret = ceph_crypto_key_clone(&xi->secret, ac->key);
	if (ret < 0) {
		pr_err("cannot clone key: %d\n", ret);
		goto out_nomem;
		goto err_xi;
	}

	ret = ceph_crypto_key_prepare(&xi->secret, client_key_usages,
				      ARRAY_SIZE(client_key_usages));
	if (ret) {
		pr_err("cannot prepare key: %d\n", ret);
		goto err_secret;
	}

	xi->starting = true;
@@ -1117,8 +1205,9 @@ int ceph_x_init(struct ceph_auth_client *ac)
	ac->ops = &ceph_x_ops;
	return 0;

out_nomem:
err_secret:
	ceph_crypto_key_destroy(&xi->secret);
err_xi:
	kfree(xi);
out:
	return ret;
}
Loading