Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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

+482 -135
+32 -15
fs/ceph/addr.c
··· 1000 1000 { 1001 1001 struct inode *inode = mapping->host; 1002 1002 struct ceph_fs_client *fsc = ceph_inode_to_fs_client(inode); 1003 - unsigned int wsize = i_blocksize(inode); 1003 + struct ceph_inode_info *ci = ceph_inode(inode); 1004 + unsigned int wsize = ci->i_layout.stripe_unit; 1004 1005 1005 1006 if (fsc->mount_options->wsize < wsize) 1006 1007 wsize = fsc->mount_options->wsize; ··· 1284 1283 } 1285 1284 1286 1285 static 1287 - int ceph_process_folio_batch(struct address_space *mapping, 1288 - struct writeback_control *wbc, 1289 - struct ceph_writeback_ctl *ceph_wbc) 1286 + void ceph_process_folio_batch(struct address_space *mapping, 1287 + struct writeback_control *wbc, 1288 + struct ceph_writeback_ctl *ceph_wbc) 1290 1289 { 1291 1290 struct inode *inode = mapping->host; 1292 1291 struct ceph_fs_client *fsc = ceph_inode_to_fs_client(inode); 1293 1292 struct ceph_client *cl = fsc->client; 1294 1293 struct folio *folio = NULL; 1295 1294 unsigned i; 1296 - int rc = 0; 1295 + int rc; 1297 1296 1298 1297 for (i = 0; can_next_page_be_processed(ceph_wbc, i); i++) { 1299 1298 folio = ceph_wbc->fbatch.folios[i]; ··· 1323 1322 rc = ceph_check_page_before_write(mapping, wbc, 1324 1323 ceph_wbc, folio); 1325 1324 if (rc == -ENODATA) { 1326 - rc = 0; 1327 1325 folio_unlock(folio); 1328 1326 ceph_wbc->fbatch.folios[i] = NULL; 1329 1327 continue; 1330 1328 } else if (rc == -E2BIG) { 1331 - rc = 0; 1332 1329 folio_unlock(folio); 1333 1330 ceph_wbc->fbatch.folios[i] = NULL; 1334 1331 break; ··· 1378 1379 } 1379 1380 1380 1381 ceph_wbc->processed_in_fbatch = i; 1381 - 1382 - return rc; 1383 1382 } 1384 1383 1385 1384 static inline ··· 1663 1666 tag_pages_for_writeback(mapping, ceph_wbc.index, ceph_wbc.end); 1664 1667 1665 1668 while (!has_writeback_done(&ceph_wbc)) { 1666 - ceph_wbc.locked_pages = 0; 1669 + BUG_ON(ceph_wbc.locked_pages); 1670 + BUG_ON(ceph_wbc.pages); 1671 + 1667 1672 ceph_wbc.max_pages = ceph_wbc.wsize >> PAGE_SHIFT; 1668 1673 1669 1674 get_more_pages: ··· 1683 1684 break; 1684 1685 1685 1686 process_folio_batch: 1686 - rc = ceph_process_folio_batch(mapping, wbc, &ceph_wbc); 1687 + ceph_process_folio_batch(mapping, wbc, &ceph_wbc); 1687 1688 ceph_shift_unused_folios_left(&ceph_wbc.fbatch); 1688 - if (rc) 1689 - goto release_folios; 1690 1689 1691 1690 /* did we get anything? */ 1692 1691 if (!ceph_wbc.locked_pages) ··· 2196 2199 struct ceph_osd_request *req = NULL; 2197 2200 struct ceph_cap_flush *prealloc_cf = NULL; 2198 2201 struct folio *folio = NULL; 2202 + struct ceph_snap_context *snapc = NULL; 2199 2203 u64 inline_version = CEPH_INLINE_NONE; 2200 2204 struct page *pages[1]; 2201 2205 int err = 0; ··· 2224 2226 if (inline_version == 1) /* initial version, no data */ 2225 2227 goto out_uninline; 2226 2228 2229 + down_read(&fsc->mdsc->snap_rwsem); 2230 + spin_lock(&ci->i_ceph_lock); 2231 + if (__ceph_have_pending_cap_snap(ci)) { 2232 + struct ceph_cap_snap *capsnap = 2233 + list_last_entry(&ci->i_cap_snaps, 2234 + struct ceph_cap_snap, 2235 + ci_item); 2236 + snapc = ceph_get_snap_context(capsnap->context); 2237 + } else { 2238 + if (!ci->i_head_snapc) { 2239 + ci->i_head_snapc = ceph_get_snap_context( 2240 + ci->i_snap_realm->cached_context); 2241 + } 2242 + snapc = ceph_get_snap_context(ci->i_head_snapc); 2243 + } 2244 + spin_unlock(&ci->i_ceph_lock); 2245 + up_read(&fsc->mdsc->snap_rwsem); 2246 + 2227 2247 folio = read_mapping_folio(inode->i_mapping, 0, file); 2228 2248 if (IS_ERR(folio)) { 2229 2249 err = PTR_ERR(folio); ··· 2257 2241 req = ceph_osdc_new_request(&fsc->client->osdc, &ci->i_layout, 2258 2242 ceph_vino(inode), 0, &len, 0, 1, 2259 2243 CEPH_OSD_OP_CREATE, CEPH_OSD_FLAG_WRITE, 2260 - NULL, 0, 0, false); 2244 + snapc, 0, 0, false); 2261 2245 if (IS_ERR(req)) { 2262 2246 err = PTR_ERR(req); 2263 2247 goto out_unlock; ··· 2273 2257 req = ceph_osdc_new_request(&fsc->client->osdc, &ci->i_layout, 2274 2258 ceph_vino(inode), 0, &len, 1, 3, 2275 2259 CEPH_OSD_OP_WRITE, CEPH_OSD_FLAG_WRITE, 2276 - NULL, ci->i_truncate_seq, 2260 + snapc, ci->i_truncate_seq, 2277 2261 ci->i_truncate_size, false); 2278 2262 if (IS_ERR(req)) { 2279 2263 err = PTR_ERR(req); ··· 2336 2320 folio_put(folio); 2337 2321 } 2338 2322 out: 2323 + ceph_put_snap_context(snapc); 2339 2324 ceph_free_cap_flush(prealloc_cf); 2340 2325 doutc(cl, "%llx.%llx inline_version %llu = %d\n", 2341 2326 ceph_vinop(inode), inline_version, err);
+16 -1
fs/ceph/file.c
··· 2568 2568 struct ceph_inode_info *ci = ceph_inode(inode); 2569 2569 struct ceph_fs_client *fsc = ceph_inode_to_fs_client(inode); 2570 2570 struct ceph_osd_request *req; 2571 + struct ceph_snap_context *snapc; 2571 2572 int ret = 0; 2572 2573 loff_t zero = 0; 2573 2574 int op; ··· 2583 2582 op = CEPH_OSD_OP_ZERO; 2584 2583 } 2585 2584 2585 + spin_lock(&ci->i_ceph_lock); 2586 + if (__ceph_have_pending_cap_snap(ci)) { 2587 + struct ceph_cap_snap *capsnap = 2588 + list_last_entry(&ci->i_cap_snaps, 2589 + struct ceph_cap_snap, 2590 + ci_item); 2591 + snapc = ceph_get_snap_context(capsnap->context); 2592 + } else { 2593 + BUG_ON(!ci->i_head_snapc); 2594 + snapc = ceph_get_snap_context(ci->i_head_snapc); 2595 + } 2596 + spin_unlock(&ci->i_ceph_lock); 2597 + 2586 2598 req = ceph_osdc_new_request(&fsc->client->osdc, &ci->i_layout, 2587 2599 ceph_vino(inode), 2588 2600 offset, length, 2589 2601 0, 1, op, 2590 2602 CEPH_OSD_FLAG_WRITE, 2591 - NULL, 0, 0, false); 2603 + snapc, 0, 0, false); 2592 2604 if (IS_ERR(req)) { 2593 2605 ret = PTR_ERR(req); 2594 2606 goto out; ··· 2615 2601 ceph_osdc_put_request(req); 2616 2602 2617 2603 out: 2604 + ceph_put_snap_context(snapc); 2618 2605 return ret; 2619 2606 } 2620 2607
+3 -2
include/linux/ceph/ceph_fs.h
··· 89 89 } __attribute__ ((packed)); 90 90 91 91 /* crypto algorithms */ 92 - #define CEPH_CRYPTO_NONE 0x0 93 - #define CEPH_CRYPTO_AES 0x1 92 + #define CEPH_CRYPTO_NONE 0x0 93 + #define CEPH_CRYPTO_AES 0x1 94 + #define CEPH_CRYPTO_AES256KRB5 0x2 /* AES256-CTS-HMAC384-192 */ 94 95 95 96 #define CEPH_AES_IV "cephsageyudagreg" 96 97
+1
net/ceph/Kconfig
··· 6 6 select CRYPTO_AES 7 7 select CRYPTO_CBC 8 8 select CRYPTO_GCM 9 + select CRYPTO_KRB5 9 10 select CRYPTO_LIB_SHA256 10 11 select CRYPTO 11 12 select KEYS
+142 -53
net/ceph/auth_x.c
··· 17 17 #include "auth_x.h" 18 18 #include "auth_x_protocol.h" 19 19 20 + static const u32 ticket_key_usages[] = { 21 + CEPHX_KEY_USAGE_TICKET_SESSION_KEY, 22 + CEPHX_KEY_USAGE_TICKET_BLOB, 23 + CEPHX_KEY_USAGE_AUTH_CONNECTION_SECRET 24 + }; 25 + 26 + static const u32 authorizer_key_usages[] = { 27 + CEPHX_KEY_USAGE_AUTHORIZE, 28 + CEPHX_KEY_USAGE_AUTHORIZE_CHALLENGE, 29 + CEPHX_KEY_USAGE_AUTHORIZE_REPLY 30 + }; 31 + 32 + static const u32 client_key_usages[] = { 33 + CEPHX_KEY_USAGE_TICKET_SESSION_KEY 34 + }; 35 + 20 36 static void ceph_x_validate_tickets(struct ceph_auth_client *ac, int *pneed); 21 37 22 38 static int ceph_x_is_authenticated(struct ceph_auth_client *ac) ··· 60 44 return !!need; 61 45 } 62 46 63 - static int ceph_x_encrypt_offset(void) 47 + static int __ceph_x_encrypt_offset(const struct ceph_crypto_key *key) 64 48 { 65 - return sizeof(u32) + sizeof(struct ceph_x_encrypt_header); 49 + return ceph_crypt_data_offset(key) + 50 + sizeof(struct ceph_x_encrypt_header); 66 51 } 67 52 68 - static int ceph_x_encrypt_buflen(int ilen) 53 + static int ceph_x_encrypt_offset(const struct ceph_crypto_key *key) 69 54 { 70 - return ceph_x_encrypt_offset() + ilen + 16; 55 + return sizeof(u32) + __ceph_x_encrypt_offset(key); 71 56 } 72 57 73 - static int ceph_x_encrypt(struct ceph_crypto_key *secret, void *buf, 74 - int buf_len, int plaintext_len) 58 + /* 59 + * AES: ciphertext_len | hdr | data... | padding 60 + * AES256KRB5: ciphertext_len | confounder | hdr | data... | hmac 61 + */ 62 + static int ceph_x_encrypt_buflen(const struct ceph_crypto_key *key, 63 + int data_len) 75 64 { 76 - struct ceph_x_encrypt_header *hdr = buf + sizeof(u32); 65 + int encrypt_len = sizeof(struct ceph_x_encrypt_header) + data_len; 66 + return sizeof(u32) + ceph_crypt_buflen(key, encrypt_len); 67 + } 68 + 69 + static int ceph_x_encrypt(const struct ceph_crypto_key *key, int usage_slot, 70 + void *buf, int buf_len, int plaintext_len) 71 + { 72 + struct ceph_x_encrypt_header *hdr; 77 73 int ciphertext_len; 78 74 int ret; 79 75 76 + hdr = buf + sizeof(u32) + ceph_crypt_data_offset(key); 80 77 hdr->struct_v = 1; 81 78 hdr->magic = cpu_to_le64(CEPHX_ENC_MAGIC); 82 79 83 - ret = ceph_crypt(secret, true, buf + sizeof(u32), buf_len - sizeof(u32), 84 - plaintext_len + sizeof(struct ceph_x_encrypt_header), 80 + ret = ceph_crypt(key, usage_slot, true, buf + sizeof(u32), 81 + buf_len - sizeof(u32), plaintext_len + sizeof(*hdr), 85 82 &ciphertext_len); 86 83 if (ret) 87 84 return ret; ··· 103 74 return sizeof(u32) + ciphertext_len; 104 75 } 105 76 106 - static int __ceph_x_decrypt(struct ceph_crypto_key *secret, void *p, 107 - int ciphertext_len) 77 + static int __ceph_x_decrypt(const struct ceph_crypto_key *key, int usage_slot, 78 + void *p, int ciphertext_len) 108 79 { 109 - struct ceph_x_encrypt_header *hdr = p; 80 + struct ceph_x_encrypt_header *hdr; 110 81 int plaintext_len; 111 82 int ret; 112 83 113 - ret = ceph_crypt(secret, false, p, ciphertext_len, ciphertext_len, 114 - &plaintext_len); 84 + ret = ceph_crypt(key, usage_slot, false, p, ciphertext_len, 85 + ciphertext_len, &plaintext_len); 115 86 if (ret) 116 87 return ret; 117 88 89 + hdr = p + ceph_crypt_data_offset(key); 118 90 if (le64_to_cpu(hdr->magic) != CEPHX_ENC_MAGIC) { 119 91 pr_err("%s bad magic\n", __func__); 120 92 return -EINVAL; ··· 124 94 return plaintext_len - sizeof(*hdr); 125 95 } 126 96 127 - static int ceph_x_decrypt(struct ceph_crypto_key *secret, void **p, void *end) 97 + static int ceph_x_decrypt(const struct ceph_crypto_key *key, int usage_slot, 98 + void **p, void *end) 128 99 { 129 100 int ciphertext_len; 130 101 int ret; ··· 133 102 ceph_decode_32_safe(p, end, ciphertext_len, e_inval); 134 103 ceph_decode_need(p, end, ciphertext_len, e_inval); 135 104 136 - ret = __ceph_x_decrypt(secret, *p, ciphertext_len); 105 + ret = __ceph_x_decrypt(key, usage_slot, *p, ciphertext_len); 137 106 if (ret < 0) 138 107 return ret; 139 108 ··· 224 193 } 225 194 226 195 /* blob for me */ 227 - dp = *p + ceph_x_encrypt_offset(); 228 - ret = ceph_x_decrypt(secret, p, end); 196 + dp = *p + ceph_x_encrypt_offset(secret); 197 + ret = ceph_x_decrypt(secret, 198 + 0 /* CEPHX_KEY_USAGE_TICKET_SESSION_KEY */, 199 + p, end); 229 200 if (ret < 0) 230 201 goto out; 231 202 dout(" decrypted %d bytes\n", ret); ··· 238 205 goto bad; 239 206 240 207 ret = ceph_crypto_key_decode(&new_session_key, &dp, dend); 208 + if (ret) 209 + goto out; 210 + 211 + ret = ceph_crypto_key_prepare(&new_session_key, ticket_key_usages, 212 + ARRAY_SIZE(ticket_key_usages)); 241 213 if (ret) 242 214 goto out; 243 215 ··· 258 220 ceph_decode_8_safe(p, end, is_enc, bad); 259 221 if (is_enc) { 260 222 /* encrypted */ 261 - tp = *p + ceph_x_encrypt_offset(); 262 - ret = ceph_x_decrypt(&th->session_key, p, end); 223 + tp = *p + ceph_x_encrypt_offset(&th->session_key); 224 + ret = ceph_x_decrypt(&th->session_key, 225 + 1 /* CEPHX_KEY_USAGE_TICKET_BLOB */, 226 + p, end); 263 227 if (ret < 0) 264 228 goto out; 265 229 dout(" encrypted ticket, decrypted %d bytes\n", ret); ··· 352 312 p = (void *)(msg_a + 1) + le32_to_cpu(msg_a->ticket_blob.blob_len); 353 313 end = au->buf->vec.iov_base + au->buf->vec.iov_len; 354 314 355 - msg_b = p + ceph_x_encrypt_offset(); 315 + msg_b = p + ceph_x_encrypt_offset(&au->session_key); 356 316 msg_b->struct_v = 2; 357 317 msg_b->nonce = cpu_to_le64(au->nonce); 358 318 if (server_challenge) { ··· 364 324 msg_b->server_challenge_plus_one = 0; 365 325 } 366 326 367 - ret = ceph_x_encrypt(&au->session_key, p, end - p, sizeof(*msg_b)); 327 + ret = ceph_x_encrypt(&au->session_key, 328 + 0 /* CEPHX_KEY_USAGE_AUTHORIZE */, 329 + p, end - p, sizeof(*msg_b)); 368 330 if (ret < 0) 369 331 return ret; 370 332 ··· 409 367 if (ret) 410 368 goto out_au; 411 369 370 + ret = ceph_crypto_key_prepare(&au->session_key, authorizer_key_usages, 371 + ARRAY_SIZE(authorizer_key_usages)); 372 + if (ret) 373 + goto out_au; 374 + 412 375 maxlen = sizeof(*msg_a) + ticket_blob_len + 413 - ceph_x_encrypt_buflen(sizeof(*msg_b)); 376 + ceph_x_encrypt_buflen(&au->session_key, sizeof(*msg_b)); 414 377 dout(" need len %d\n", maxlen); 415 378 if (au->buf && au->buf->alloc_len < maxlen) { 416 379 ceph_buffer_put(au->buf); ··· 553 506 if (need & CEPH_ENTITY_TYPE_AUTH) { 554 507 struct ceph_x_authenticate *auth = (void *)(head + 1); 555 508 void *enc_buf = xi->auth_authorizer.enc_buf; 556 - struct ceph_x_challenge_blob *blob = enc_buf + 557 - ceph_x_encrypt_offset(); 509 + struct ceph_x_challenge_blob *blob; 558 510 u64 *u; 559 511 560 512 p = auth + 1; ··· 563 517 dout(" get_auth_session_key\n"); 564 518 head->op = cpu_to_le16(CEPHX_GET_AUTH_SESSION_KEY); 565 519 566 - /* encrypt and hash */ 520 + if (xi->secret.type == CEPH_CRYPTO_AES) { 521 + blob = enc_buf + ceph_x_encrypt_offset(&xi->secret); 522 + } else { 523 + BUILD_BUG_ON(SHA256_DIGEST_SIZE + sizeof(*blob) > 524 + CEPHX_AU_ENC_BUF_LEN); 525 + blob = enc_buf + SHA256_DIGEST_SIZE; 526 + } 527 + 567 528 get_random_bytes(&auth->client_challenge, sizeof(u64)); 568 529 blob->client_challenge = auth->client_challenge; 569 530 blob->server_challenge = cpu_to_le64(xi->server_challenge); 570 - ret = ceph_x_encrypt(&xi->secret, enc_buf, CEPHX_AU_ENC_BUF_LEN, 571 - sizeof(*blob)); 572 - if (ret < 0) 573 - return ret; 531 + 532 + if (xi->secret.type == CEPH_CRYPTO_AES) { 533 + ret = ceph_x_encrypt(&xi->secret, 0 /* dummy */, 534 + enc_buf, CEPHX_AU_ENC_BUF_LEN, 535 + sizeof(*blob)); 536 + if (ret < 0) 537 + return ret; 538 + } else { 539 + ceph_hmac_sha256(&xi->secret, blob, sizeof(*blob), 540 + enc_buf); 541 + ret = SHA256_DIGEST_SIZE; 542 + } 574 543 575 544 auth->struct_v = 3; /* nautilus+ */ 576 545 auth->key = 0; ··· 695 634 ceph_decode_need(p, end, len, e_inval); 696 635 dout("%s connection secret blob len %d\n", __func__, len); 697 636 if (len > 0) { 698 - dp = *p + ceph_x_encrypt_offset(); 699 - ret = ceph_x_decrypt(&th->session_key, p, *p + len); 637 + dp = *p + ceph_x_encrypt_offset(&th->session_key); 638 + ret = ceph_x_decrypt(&th->session_key, 639 + 2 /* CEPHX_KEY_USAGE_AUTH_CONNECTION_SECRET */, 640 + p, *p + len); 700 641 if (ret < 0) 701 642 return ret; 702 643 ··· 862 799 int ret; 863 800 864 801 /* no leading len */ 865 - ret = __ceph_x_decrypt(secret, challenge, challenge_len); 802 + ret = __ceph_x_decrypt(secret, 803 + 1 /* CEPHX_KEY_USAGE_AUTHORIZE_CHALLENGE */, 804 + challenge, challenge_len); 866 805 if (ret < 0) 867 806 return ret; 868 807 869 808 dout("%s decrypted %d bytes\n", __func__, ret); 870 - dp = challenge + sizeof(struct ceph_x_encrypt_header); 809 + dp = challenge + __ceph_x_encrypt_offset(secret); 871 810 dend = dp + ret; 872 811 873 812 ceph_decode_skip_8(&dp, dend, e_inval); /* struct_v */ ··· 916 851 u8 struct_v; 917 852 int ret; 918 853 919 - dp = *p + ceph_x_encrypt_offset(); 920 - ret = ceph_x_decrypt(secret, p, end); 854 + dp = *p + ceph_x_encrypt_offset(secret); 855 + ret = ceph_x_decrypt(secret, 2 /* CEPHX_KEY_USAGE_AUTHORIZE_REPLY */, 856 + p, end); 921 857 if (ret < 0) 922 858 return ret; 923 859 ··· 1040 974 __le32 front_crc; 1041 975 __le32 middle_crc; 1042 976 __le32 data_crc; 1043 - } __packed *sigblock = enc_buf + ceph_x_encrypt_offset(); 977 + } __packed *sigblock = enc_buf + 978 + ceph_x_encrypt_offset(&au->session_key); 1044 979 1045 980 sigblock->len = cpu_to_le32(4*sizeof(u32)); 1046 981 sigblock->header_crc = msg->hdr.crc; ··· 1049 982 sigblock->middle_crc = msg->footer.middle_crc; 1050 983 sigblock->data_crc = msg->footer.data_crc; 1051 984 1052 - ret = ceph_x_encrypt(&au->session_key, enc_buf, 1053 - CEPHX_AU_ENC_BUF_LEN, sizeof(*sigblock)); 985 + ret = ceph_x_encrypt(&au->session_key, 0 /* dummy */, 986 + enc_buf, CEPHX_AU_ENC_BUF_LEN, 987 + sizeof(*sigblock)); 1054 988 if (ret < 0) 1055 989 return ret; 1056 990 ··· 1066 998 __le32 data_crc; 1067 999 __le32 data_len; 1068 1000 __le32 seq_lower_word; 1069 - } __packed *sigblock = enc_buf; 1001 + } __packed *sigblock; 1070 1002 struct { 1071 1003 __le64 a, b, c, d; 1072 1004 } __packed *penc = enc_buf; 1073 - int ciphertext_len; 1005 + 1006 + if (au->session_key.type == CEPH_CRYPTO_AES) { 1007 + /* no leading len, no ceph_x_encrypt_header */ 1008 + sigblock = enc_buf; 1009 + } else { 1010 + BUILD_BUG_ON(SHA256_DIGEST_SIZE + sizeof(*sigblock) > 1011 + CEPHX_AU_ENC_BUF_LEN); 1012 + sigblock = enc_buf + SHA256_DIGEST_SIZE; 1013 + } 1074 1014 1075 1015 sigblock->header_crc = msg->hdr.crc; 1076 1016 sigblock->front_crc = msg->footer.front_crc; ··· 1089 1013 sigblock->data_len = msg->hdr.data_len; 1090 1014 sigblock->seq_lower_word = *(__le32 *)&msg->hdr.seq; 1091 1015 1092 - /* no leading len, no ceph_x_encrypt_header */ 1093 - ret = ceph_crypt(&au->session_key, true, enc_buf, 1094 - CEPHX_AU_ENC_BUF_LEN, sizeof(*sigblock), 1095 - &ciphertext_len); 1096 - if (ret) 1097 - return ret; 1016 + if (au->session_key.type == CEPH_CRYPTO_AES) { 1017 + int ciphertext_len; /* unused */ 1018 + 1019 + ret = ceph_crypt(&au->session_key, 0 /* dummy */, 1020 + true, enc_buf, CEPHX_AU_ENC_BUF_LEN, 1021 + sizeof(*sigblock), &ciphertext_len); 1022 + if (ret) 1023 + return ret; 1024 + } else { 1025 + ceph_hmac_sha256(&au->session_key, sigblock, 1026 + sizeof(*sigblock), enc_buf); 1027 + } 1098 1028 1099 1029 *psig = penc->a ^ penc->b ^ penc->c ^ penc->d; 1100 1030 } ··· 1174 1092 int ret; 1175 1093 1176 1094 dout("ceph_x_init %p\n", ac); 1177 - ret = -ENOMEM; 1178 1095 xi = kzalloc(sizeof(*xi), GFP_NOFS); 1179 1096 if (!xi) 1180 - goto out; 1097 + return -ENOMEM; 1181 1098 1182 1099 ret = -EINVAL; 1183 1100 if (!ac->key) { 1184 1101 pr_err("no secret set (for auth_x protocol)\n"); 1185 - goto out_nomem; 1102 + goto err_xi; 1186 1103 } 1187 1104 1188 1105 ret = ceph_crypto_key_clone(&xi->secret, ac->key); 1189 1106 if (ret < 0) { 1190 1107 pr_err("cannot clone key: %d\n", ret); 1191 - goto out_nomem; 1108 + goto err_xi; 1109 + } 1110 + 1111 + ret = ceph_crypto_key_prepare(&xi->secret, client_key_usages, 1112 + ARRAY_SIZE(client_key_usages)); 1113 + if (ret) { 1114 + pr_err("cannot prepare key: %d\n", ret); 1115 + goto err_secret; 1192 1116 } 1193 1117 1194 1118 xi->starting = true; ··· 1205 1117 ac->ops = &ceph_x_ops; 1206 1118 return 0; 1207 1119 1208 - out_nomem: 1120 + err_secret: 1121 + ceph_crypto_key_destroy(&xi->secret); 1122 + err_xi: 1209 1123 kfree(xi); 1210 - out: 1211 1124 return ret; 1212 1125 }
+38
net/ceph/auth_x_protocol.h
··· 6 6 #define CEPHX_GET_PRINCIPAL_SESSION_KEY 0x0200 7 7 #define CEPHX_GET_ROTATING_KEY 0x0400 8 8 9 + /* Client <-> AuthMonitor */ 10 + /* 11 + * The AUTH session's connection secret: encrypted with the AUTH 12 + * ticket session key 13 + */ 14 + #define CEPHX_KEY_USAGE_AUTH_CONNECTION_SECRET 0x03 15 + /* 16 + * The ticket's blob for the client ("blob for me", contains the 17 + * session key): encrypted with the client's secret key in case of 18 + * the AUTH ticket and the AUTH ticket session key in case of other 19 + * service tickets 20 + */ 21 + #define CEPHX_KEY_USAGE_TICKET_SESSION_KEY 0x04 22 + /* 23 + * The ticket's blob for the service (ceph_x_ticket_blob): possibly 24 + * encrypted with the old AUTH ticket session key in case of the AUTH 25 + * ticket and not encrypted in case of other service tickets 26 + */ 27 + #define CEPHX_KEY_USAGE_TICKET_BLOB 0x05 28 + 29 + /* Client <-> Service */ 30 + /* 31 + * The client's authorization request (ceph_x_authorize_b): 32 + * encrypted with the service ticket session key 33 + */ 34 + #define CEPHX_KEY_USAGE_AUTHORIZE 0x10 35 + /* 36 + * The service's challenge (ceph_x_authorize_challenge): 37 + * encrypted with the service ticket session key 38 + */ 39 + #define CEPHX_KEY_USAGE_AUTHORIZE_CHALLENGE 0x11 40 + /* 41 + * The service's final reply (ceph_x_authorize_reply + the service 42 + * session's connection secret): encrypted with the service ticket 43 + * session key 44 + */ 45 + #define CEPHX_KEY_USAGE_AUTHORIZE_REPLY 0x12 46 + 9 47 /* common bits */ 10 48 struct ceph_x_ticket_blob { 11 49 __u8 struct_v;
+224 -53
net/ceph/crypto.c
··· 7 7 #include <linux/sched.h> 8 8 #include <linux/slab.h> 9 9 #include <crypto/aes.h> 10 + #include <crypto/krb5.h> 10 11 #include <crypto/skcipher.h> 11 12 #include <linux/key-type.h> 12 13 #include <linux/sched/mm.h> ··· 17 16 #include <linux/ceph/decode.h> 18 17 #include "crypto.h" 19 18 20 - /* 21 - * Set ->key and ->tfm. The rest of the key should be filled in before 22 - * this function is called. 23 - */ 24 - static int set_secret(struct ceph_crypto_key *key, void *buf) 19 + static int set_aes_tfm(struct ceph_crypto_key *key) 25 20 { 26 21 unsigned int noio_flag; 27 22 int ret; 28 23 29 - key->key = NULL; 30 - key->tfm = NULL; 24 + noio_flag = memalloc_noio_save(); 25 + key->aes_tfm = crypto_alloc_sync_skcipher("cbc(aes)", 0, 0); 26 + memalloc_noio_restore(noio_flag); 27 + if (IS_ERR(key->aes_tfm)) { 28 + ret = PTR_ERR(key->aes_tfm); 29 + key->aes_tfm = NULL; 30 + return ret; 31 + } 31 32 33 + ret = crypto_sync_skcipher_setkey(key->aes_tfm, key->key, key->len); 34 + if (ret) 35 + return ret; 36 + 37 + return 0; 38 + } 39 + 40 + static int set_krb5_tfms(struct ceph_crypto_key *key, const u32 *key_usages, 41 + int key_usage_cnt) 42 + { 43 + struct krb5_buffer TK = { .len = key->len, .data = key->key }; 44 + unsigned int noio_flag; 45 + int ret = 0; 46 + int i; 47 + 48 + if (WARN_ON_ONCE(key_usage_cnt > ARRAY_SIZE(key->krb5_tfms))) 49 + return -EINVAL; 50 + 51 + key->krb5_type = crypto_krb5_find_enctype( 52 + KRB5_ENCTYPE_AES256_CTS_HMAC_SHA384_192); 53 + if (!key->krb5_type) 54 + return -ENOPKG; 55 + 56 + /* 57 + * Despite crypto_krb5_prepare_encryption() taking a gfp mask, 58 + * crypto_alloc_aead() inside of it allocates with GFP_KERNEL. 59 + */ 60 + noio_flag = memalloc_noio_save(); 61 + for (i = 0; i < key_usage_cnt; i++) { 62 + key->krb5_tfms[i] = crypto_krb5_prepare_encryption( 63 + key->krb5_type, &TK, key_usages[i], 64 + GFP_NOIO); 65 + if (IS_ERR(key->krb5_tfms[i])) { 66 + ret = PTR_ERR(key->krb5_tfms[i]); 67 + key->krb5_tfms[i] = NULL; 68 + goto out_flag; 69 + } 70 + } 71 + 72 + out_flag: 73 + memalloc_noio_restore(noio_flag); 74 + return ret; 75 + } 76 + 77 + int ceph_crypto_key_prepare(struct ceph_crypto_key *key, 78 + const u32 *key_usages, int key_usage_cnt) 79 + { 32 80 switch (key->type) { 33 81 case CEPH_CRYPTO_NONE: 34 82 return 0; /* nothing to do */ 35 83 case CEPH_CRYPTO_AES: 36 - break; 84 + return set_aes_tfm(key); 85 + case CEPH_CRYPTO_AES256KRB5: 86 + hmac_sha256_preparekey(&key->hmac_key, key->key, key->len); 87 + return set_krb5_tfms(key, key_usages, key_usage_cnt); 37 88 default: 38 89 return -ENOTSUPP; 39 90 } 40 - 41 - if (!key->len) 42 - return -EINVAL; 43 - 44 - key->key = kmemdup(buf, key->len, GFP_NOIO); 45 - if (!key->key) { 46 - ret = -ENOMEM; 47 - goto fail; 48 - } 49 - 50 - /* crypto_alloc_sync_skcipher() allocates with GFP_KERNEL */ 51 - noio_flag = memalloc_noio_save(); 52 - key->tfm = crypto_alloc_sync_skcipher("cbc(aes)", 0, 0); 53 - memalloc_noio_restore(noio_flag); 54 - if (IS_ERR(key->tfm)) { 55 - ret = PTR_ERR(key->tfm); 56 - key->tfm = NULL; 57 - goto fail; 58 - } 59 - 60 - ret = crypto_sync_skcipher_setkey(key->tfm, key->key, key->len); 61 - if (ret) 62 - goto fail; 63 - 64 - return 0; 65 - 66 - fail: 67 - ceph_crypto_key_destroy(key); 68 - return ret; 69 91 } 70 92 93 + /* 94 + * @dst should be zeroed before this function is called. 95 + */ 71 96 int ceph_crypto_key_clone(struct ceph_crypto_key *dst, 72 97 const struct ceph_crypto_key *src) 73 98 { 74 - memcpy(dst, src, sizeof(struct ceph_crypto_key)); 75 - return set_secret(dst, src->key); 99 + dst->type = src->type; 100 + dst->created = src->created; 101 + dst->len = src->len; 102 + 103 + dst->key = kmemdup(src->key, src->len, GFP_NOIO); 104 + if (!dst->key) 105 + return -ENOMEM; 106 + 107 + return 0; 76 108 } 77 109 110 + /* 111 + * @key should be zeroed before this function is called. 112 + */ 78 113 int ceph_crypto_key_decode(struct ceph_crypto_key *key, void **p, void *end) 79 114 { 80 - int ret; 81 - 82 115 ceph_decode_need(p, end, 2*sizeof(u16) + sizeof(key->created), bad); 83 116 key->type = ceph_decode_16(p); 84 117 ceph_decode_copy(p, &key->created, sizeof(key->created)); 85 118 key->len = ceph_decode_16(p); 86 119 ceph_decode_need(p, end, key->len, bad); 87 - ret = set_secret(key, *p); 120 + if (key->len > CEPH_MAX_KEY_LEN) { 121 + pr_err("secret too big %d\n", key->len); 122 + return -EINVAL; 123 + } 124 + 125 + key->key = kmemdup(*p, key->len, GFP_NOIO); 126 + if (!key->key) 127 + return -ENOMEM; 128 + 88 129 memzero_explicit(*p, key->len); 89 130 *p += key->len; 90 - return ret; 131 + return 0; 91 132 92 133 bad: 93 134 dout("failed to decode crypto key\n"); ··· 165 122 166 123 void ceph_crypto_key_destroy(struct ceph_crypto_key *key) 167 124 { 168 - if (key) { 169 - kfree_sensitive(key->key); 170 - key->key = NULL; 171 - if (key->tfm) { 172 - crypto_free_sync_skcipher(key->tfm); 173 - key->tfm = NULL; 125 + int i; 126 + 127 + if (!key) 128 + return; 129 + 130 + kfree_sensitive(key->key); 131 + key->key = NULL; 132 + 133 + if (key->type == CEPH_CRYPTO_AES) { 134 + if (key->aes_tfm) { 135 + crypto_free_sync_skcipher(key->aes_tfm); 136 + key->aes_tfm = NULL; 137 + } 138 + } else if (key->type == CEPH_CRYPTO_AES256KRB5) { 139 + memzero_explicit(&key->hmac_key, sizeof(key->hmac_key)); 140 + for (i = 0; i < ARRAY_SIZE(key->krb5_tfms); i++) { 141 + if (key->krb5_tfms[i]) { 142 + crypto_free_aead(key->krb5_tfms[i]); 143 + key->krb5_tfms[i] = NULL; 144 + } 174 145 } 175 146 } 176 147 } ··· 264 207 static int ceph_aes_crypt(const struct ceph_crypto_key *key, bool encrypt, 265 208 void *buf, int buf_len, int in_len, int *pout_len) 266 209 { 267 - SYNC_SKCIPHER_REQUEST_ON_STACK(req, key->tfm); 210 + SYNC_SKCIPHER_REQUEST_ON_STACK(req, key->aes_tfm); 268 211 struct sg_table sgt; 269 212 struct scatterlist prealloc_sg; 270 213 char iv[AES_BLOCK_SIZE] __aligned(8); ··· 280 223 return ret; 281 224 282 225 memcpy(iv, aes_iv, AES_BLOCK_SIZE); 283 - skcipher_request_set_sync_tfm(req, key->tfm); 226 + skcipher_request_set_sync_tfm(req, key->aes_tfm); 284 227 skcipher_request_set_callback(req, 0, NULL, NULL); 285 228 skcipher_request_set_crypt(req, sgt.sgl, sgt.sgl, crypt_len, iv); 286 229 ··· 325 268 return ret; 326 269 } 327 270 328 - int ceph_crypt(const struct ceph_crypto_key *key, bool encrypt, 271 + static int ceph_krb5_encrypt(const struct ceph_crypto_key *key, int usage_slot, 272 + void *buf, int buf_len, int in_len, int *pout_len) 273 + { 274 + struct sg_table sgt; 275 + struct scatterlist prealloc_sg; 276 + int ret; 277 + 278 + if (WARN_ON_ONCE(usage_slot >= ARRAY_SIZE(key->krb5_tfms))) 279 + return -EINVAL; 280 + 281 + ret = setup_sgtable(&sgt, &prealloc_sg, buf, buf_len); 282 + if (ret) 283 + return ret; 284 + 285 + ret = crypto_krb5_encrypt(key->krb5_type, key->krb5_tfms[usage_slot], 286 + sgt.sgl, sgt.nents, buf_len, AES_BLOCK_SIZE, 287 + in_len, false); 288 + if (ret < 0) { 289 + pr_err("%s encrypt failed: %d\n", __func__, ret); 290 + goto out_sgt; 291 + } 292 + 293 + *pout_len = ret; 294 + ret = 0; 295 + 296 + out_sgt: 297 + teardown_sgtable(&sgt); 298 + return ret; 299 + } 300 + 301 + static int ceph_krb5_decrypt(const struct ceph_crypto_key *key, int usage_slot, 302 + void *buf, int buf_len, int in_len, int *pout_len) 303 + { 304 + struct sg_table sgt; 305 + struct scatterlist prealloc_sg; 306 + size_t data_off = 0; 307 + size_t data_len = in_len; 308 + int ret; 309 + 310 + if (WARN_ON_ONCE(usage_slot >= ARRAY_SIZE(key->krb5_tfms))) 311 + return -EINVAL; 312 + 313 + ret = setup_sgtable(&sgt, &prealloc_sg, buf, in_len); 314 + if (ret) 315 + return ret; 316 + 317 + ret = crypto_krb5_decrypt(key->krb5_type, key->krb5_tfms[usage_slot], 318 + sgt.sgl, sgt.nents, &data_off, &data_len); 319 + if (ret) { 320 + pr_err("%s decrypt failed: %d\n", __func__, ret); 321 + goto out_sgt; 322 + } 323 + 324 + WARN_ON(data_off != AES_BLOCK_SIZE); 325 + *pout_len = data_len; 326 + 327 + out_sgt: 328 + teardown_sgtable(&sgt); 329 + return ret; 330 + } 331 + 332 + int ceph_crypt(const struct ceph_crypto_key *key, int usage_slot, bool encrypt, 329 333 void *buf, int buf_len, int in_len, int *pout_len) 330 334 { 331 335 switch (key->type) { ··· 396 278 case CEPH_CRYPTO_AES: 397 279 return ceph_aes_crypt(key, encrypt, buf, buf_len, in_len, 398 280 pout_len); 281 + case CEPH_CRYPTO_AES256KRB5: 282 + return encrypt ? 283 + ceph_krb5_encrypt(key, usage_slot, buf, buf_len, in_len, 284 + pout_len) : 285 + ceph_krb5_decrypt(key, usage_slot, buf, buf_len, in_len, 286 + pout_len); 399 287 default: 400 288 return -ENOTSUPP; 289 + } 290 + } 291 + 292 + int ceph_crypt_data_offset(const struct ceph_crypto_key *key) 293 + { 294 + switch (key->type) { 295 + case CEPH_CRYPTO_NONE: 296 + case CEPH_CRYPTO_AES: 297 + return 0; 298 + case CEPH_CRYPTO_AES256KRB5: 299 + /* confounder */ 300 + return AES_BLOCK_SIZE; 301 + default: 302 + BUG(); 303 + } 304 + } 305 + 306 + int ceph_crypt_buflen(const struct ceph_crypto_key *key, int data_len) 307 + { 308 + switch (key->type) { 309 + case CEPH_CRYPTO_NONE: 310 + return data_len; 311 + case CEPH_CRYPTO_AES: 312 + /* PKCS#7 padding at the end */ 313 + return data_len + AES_BLOCK_SIZE - 314 + (data_len & (AES_BLOCK_SIZE - 1)); 315 + case CEPH_CRYPTO_AES256KRB5: 316 + /* confounder at the beginning and 192-bit HMAC at the end */ 317 + return AES_BLOCK_SIZE + data_len + 24; 318 + default: 319 + BUG(); 320 + } 321 + } 322 + 323 + void ceph_hmac_sha256(const struct ceph_crypto_key *key, const void *buf, 324 + int buf_len, u8 hmac[SHA256_DIGEST_SIZE]) 325 + { 326 + switch (key->type) { 327 + case CEPH_CRYPTO_NONE: 328 + case CEPH_CRYPTO_AES: 329 + memset(hmac, 0, SHA256_DIGEST_SIZE); 330 + return; 331 + case CEPH_CRYPTO_AES256KRB5: 332 + hmac_sha256(&key->hmac_key, buf, buf_len, hmac); 333 + return; 334 + default: 335 + BUG(); 401 336 } 402 337 } 403 338 ··· 466 295 goto err; 467 296 468 297 ret = -ENOMEM; 469 - ckey = kmalloc(sizeof(*ckey), GFP_KERNEL); 298 + ckey = kzalloc(sizeof(*ckey), GFP_KERNEL); 470 299 if (!ckey) 471 300 goto err; 472 301
+18 -3
net/ceph/crypto.h
··· 2 2 #ifndef _FS_CEPH_CRYPTO_H 3 3 #define _FS_CEPH_CRYPTO_H 4 4 5 + #include <crypto/sha2.h> 5 6 #include <linux/ceph/types.h> 6 7 #include <linux/ceph/buffer.h> 7 8 8 - #define CEPH_KEY_LEN 16 9 + #define CEPH_MAX_KEY_LEN 32 9 10 #define CEPH_MAX_CON_SECRET_LEN 64 10 11 11 12 /* ··· 17 16 struct ceph_timespec created; 18 17 int len; 19 18 void *key; 20 - struct crypto_sync_skcipher *tfm; 19 + 20 + union { 21 + struct crypto_sync_skcipher *aes_tfm; 22 + struct { 23 + struct hmac_sha256_key hmac_key; 24 + const struct krb5_enctype *krb5_type; 25 + struct crypto_aead *krb5_tfms[3]; 26 + }; 27 + }; 21 28 }; 22 29 30 + int ceph_crypto_key_prepare(struct ceph_crypto_key *key, 31 + const u32 *key_usages, int key_usage_cnt); 23 32 int ceph_crypto_key_clone(struct ceph_crypto_key *dst, 24 33 const struct ceph_crypto_key *src); 25 34 int ceph_crypto_key_decode(struct ceph_crypto_key *key, void **p, void *end); ··· 37 26 void ceph_crypto_key_destroy(struct ceph_crypto_key *key); 38 27 39 28 /* crypto.c */ 40 - int ceph_crypt(const struct ceph_crypto_key *key, bool encrypt, 29 + int ceph_crypt(const struct ceph_crypto_key *key, int usage_slot, bool encrypt, 41 30 void *buf, int buf_len, int in_len, int *pout_len); 31 + int ceph_crypt_data_offset(const struct ceph_crypto_key *key); 32 + int ceph_crypt_buflen(const struct ceph_crypto_key *key, int data_len); 33 + void ceph_hmac_sha256(const struct ceph_crypto_key *key, const void *buf, 34 + int buf_len, u8 hmac[SHA256_DIGEST_SIZE]); 42 35 int ceph_crypto_init(void); 43 36 void ceph_crypto_shutdown(void); 44 37
+8 -8
net/ceph/messenger_v2.c
··· 779 779 return 0; /* auth_x, secure mode */ 780 780 } 781 781 782 - static void ceph_hmac_sha256(struct ceph_connection *con, 783 - const struct kvec *kvecs, int kvec_cnt, 784 - u8 hmac[SHA256_DIGEST_SIZE]) 782 + static void con_hmac_sha256(struct ceph_connection *con, 783 + const struct kvec *kvecs, int kvec_cnt, 784 + u8 hmac[SHA256_DIGEST_SIZE]) 785 785 { 786 786 struct hmac_sha256_ctx ctx; 787 787 int i; ··· 1438 1438 if (!buf) 1439 1439 return -ENOMEM; 1440 1440 1441 - ceph_hmac_sha256(con, con->v2.in_sign_kvecs, con->v2.in_sign_kvec_cnt, 1442 - CTRL_BODY(buf)); 1441 + con_hmac_sha256(con, con->v2.in_sign_kvecs, con->v2.in_sign_kvec_cnt, 1442 + CTRL_BODY(buf)); 1443 1443 1444 1444 return prepare_control(con, FRAME_TAG_AUTH_SIGNATURE, buf, 1445 1445 SHA256_DIGEST_SIZE); ··· 2360 2360 */ 2361 2361 static int process_auth_done(struct ceph_connection *con, void *p, void *end) 2362 2362 { 2363 - u8 session_key_buf[CEPH_KEY_LEN + 16]; 2363 + u8 session_key_buf[CEPH_MAX_KEY_LEN + 16]; 2364 2364 u8 con_secret_buf[CEPH_MAX_CON_SECRET_LEN + 16]; 2365 2365 u8 *session_key = PTR_ALIGN(&session_key_buf[0], 16); 2366 2366 u8 *con_secret = PTR_ALIGN(&con_secret_buf[0], 16); ··· 2436 2436 return -EINVAL; 2437 2437 } 2438 2438 2439 - ceph_hmac_sha256(con, con->v2.out_sign_kvecs, con->v2.out_sign_kvec_cnt, 2440 - hmac); 2439 + con_hmac_sha256(con, con->v2.out_sign_kvecs, con->v2.out_sign_kvec_cnt, 2440 + hmac); 2441 2441 2442 2442 ceph_decode_need(&p, end, SHA256_DIGEST_SIZE, bad); 2443 2443 if (crypto_memneq(p, hmac, SHA256_DIGEST_SIZE)) {