5757#define IN_S_HANDLE_CONTROL_REMAINDER 3
5858#define IN_S_PREPARE_READ_DATA 4
5959#define IN_S_PREPARE_READ_DATA_CONT 5
60- #define IN_S_HANDLE_EPILOGUE 6
61- #define IN_S_FINISH_SKIP 7
60+ #define IN_S_PREPARE_READ_ENC_PAGE 6
61+ #define IN_S_HANDLE_EPILOGUE 7
62+ #define IN_S_FINISH_SKIP 8
6263
6364#define OUT_S_QUEUE_DATA 1
6465#define OUT_S_QUEUE_DATA_CONT 2
@@ -1032,22 +1033,41 @@ static int decrypt_control_remainder(struct ceph_connection *con)
10321033 padded_len (rem_len ) + CEPH_GCM_TAG_LEN );
10331034}
10341035
1035- static int decrypt_message (struct ceph_connection * con )
1036+ static int decrypt_tail (struct ceph_connection * con )
10361037{
1038+ struct sg_table enc_sgt = {};
10371039 struct sg_table sgt = {};
1040+ int tail_len ;
10381041 int ret ;
10391042
1043+ tail_len = tail_onwire_len (con -> in_msg , true);
1044+ ret = sg_alloc_table_from_pages (& enc_sgt , con -> v2 .in_enc_pages ,
1045+ con -> v2 .in_enc_page_cnt , 0 , tail_len ,
1046+ GFP_NOIO );
1047+ if (ret )
1048+ goto out ;
1049+
10401050 ret = setup_message_sgs (& sgt , con -> in_msg , FRONT_PAD (con -> v2 .in_buf ),
10411051 MIDDLE_PAD (con -> v2 .in_buf ), DATA_PAD (con -> v2 .in_buf ),
10421052 con -> v2 .in_buf , true);
10431053 if (ret )
10441054 goto out ;
10451055
1046- ret = gcm_crypt (con , false, sgt .sgl , sgt .sgl ,
1047- tail_onwire_len (con -> in_msg , true));
1056+ dout ("%s con %p msg %p enc_page_cnt %d sg_cnt %d\n" , __func__ , con ,
1057+ con -> in_msg , con -> v2 .in_enc_page_cnt , sgt .orig_nents );
1058+ ret = gcm_crypt (con , false, enc_sgt .sgl , sgt .sgl , tail_len );
1059+ if (ret )
1060+ goto out ;
1061+
1062+ WARN_ON (!con -> v2 .in_enc_page_cnt );
1063+ ceph_release_page_vector (con -> v2 .in_enc_pages ,
1064+ con -> v2 .in_enc_page_cnt );
1065+ con -> v2 .in_enc_pages = NULL ;
1066+ con -> v2 .in_enc_page_cnt = 0 ;
10481067
10491068out :
10501069 sg_free_table (& sgt );
1070+ sg_free_table (& enc_sgt );
10511071 return ret ;
10521072}
10531073
@@ -1737,8 +1757,7 @@ static void prepare_read_data(struct ceph_connection *con)
17371757{
17381758 struct bio_vec bv ;
17391759
1740- if (!con_secure (con ))
1741- con -> in_data_crc = -1 ;
1760+ con -> in_data_crc = -1 ;
17421761 ceph_msg_data_cursor_init (& con -> v2 .in_cursor , con -> in_msg ,
17431762 data_len (con -> in_msg ));
17441763
@@ -1751,11 +1770,10 @@ static void prepare_read_data_cont(struct ceph_connection *con)
17511770{
17521771 struct bio_vec bv ;
17531772
1754- if (!con_secure (con ))
1755- con -> in_data_crc = ceph_crc32c_page (con -> in_data_crc ,
1756- con -> v2 .in_bvec .bv_page ,
1757- con -> v2 .in_bvec .bv_offset ,
1758- con -> v2 .in_bvec .bv_len );
1773+ con -> in_data_crc = ceph_crc32c_page (con -> in_data_crc ,
1774+ con -> v2 .in_bvec .bv_page ,
1775+ con -> v2 .in_bvec .bv_offset ,
1776+ con -> v2 .in_bvec .bv_len );
17591777
17601778 ceph_msg_data_advance (& con -> v2 .in_cursor , con -> v2 .in_bvec .bv_len );
17611779 if (con -> v2 .in_cursor .total_resid ) {
@@ -1766,21 +1784,94 @@ static void prepare_read_data_cont(struct ceph_connection *con)
17661784 }
17671785
17681786 /*
1769- * We've read all data. Prepare to read data padding (if any)
1770- * and epilogue.
1787+ * We've read all data. Prepare to read epilogue.
17711788 */
17721789 reset_in_kvecs (con );
1773- if (con_secure (con )) {
1774- if (need_padding (data_len (con -> in_msg )))
1775- add_in_kvec (con , DATA_PAD (con -> v2 .in_buf ),
1776- padding_len (data_len (con -> in_msg )));
1777- add_in_kvec (con , con -> v2 .in_buf , CEPH_EPILOGUE_SECURE_LEN );
1790+ add_in_kvec (con , con -> v2 .in_buf , CEPH_EPILOGUE_PLAIN_LEN );
1791+ con -> v2 .in_state = IN_S_HANDLE_EPILOGUE ;
1792+ }
1793+
1794+ static void prepare_read_tail_plain (struct ceph_connection * con )
1795+ {
1796+ struct ceph_msg * msg = con -> in_msg ;
1797+
1798+ if (!front_len (msg ) && !middle_len (msg )) {
1799+ WARN_ON (!data_len (msg ));
1800+ prepare_read_data (con );
1801+ return ;
1802+ }
1803+
1804+ reset_in_kvecs (con );
1805+ if (front_len (msg )) {
1806+ add_in_kvec (con , msg -> front .iov_base , front_len (msg ));
1807+ WARN_ON (msg -> front .iov_len != front_len (msg ));
1808+ }
1809+ if (middle_len (msg )) {
1810+ add_in_kvec (con , msg -> middle -> vec .iov_base , middle_len (msg ));
1811+ WARN_ON (msg -> middle -> vec .iov_len != middle_len (msg ));
1812+ }
1813+
1814+ if (data_len (msg )) {
1815+ con -> v2 .in_state = IN_S_PREPARE_READ_DATA ;
17781816 } else {
17791817 add_in_kvec (con , con -> v2 .in_buf , CEPH_EPILOGUE_PLAIN_LEN );
1818+ con -> v2 .in_state = IN_S_HANDLE_EPILOGUE ;
1819+ }
1820+ }
1821+
1822+ static void prepare_read_enc_page (struct ceph_connection * con )
1823+ {
1824+ struct bio_vec bv ;
1825+
1826+ dout ("%s con %p i %d resid %d\n" , __func__ , con , con -> v2 .in_enc_i ,
1827+ con -> v2 .in_enc_resid );
1828+ WARN_ON (!con -> v2 .in_enc_resid );
1829+
1830+ bv .bv_page = con -> v2 .in_enc_pages [con -> v2 .in_enc_i ];
1831+ bv .bv_offset = 0 ;
1832+ bv .bv_len = min (con -> v2 .in_enc_resid , (int )PAGE_SIZE );
1833+
1834+ set_in_bvec (con , & bv );
1835+ con -> v2 .in_enc_i ++ ;
1836+ con -> v2 .in_enc_resid -= bv .bv_len ;
1837+
1838+ if (con -> v2 .in_enc_resid ) {
1839+ con -> v2 .in_state = IN_S_PREPARE_READ_ENC_PAGE ;
1840+ return ;
17801841 }
1842+
1843+ /*
1844+ * We are set to read the last piece of ciphertext (ending
1845+ * with epilogue) + auth tag.
1846+ */
1847+ WARN_ON (con -> v2 .in_enc_i != con -> v2 .in_enc_page_cnt );
17811848 con -> v2 .in_state = IN_S_HANDLE_EPILOGUE ;
17821849}
17831850
1851+ static int prepare_read_tail_secure (struct ceph_connection * con )
1852+ {
1853+ struct page * * enc_pages ;
1854+ int enc_page_cnt ;
1855+ int tail_len ;
1856+
1857+ tail_len = tail_onwire_len (con -> in_msg , true);
1858+ WARN_ON (!tail_len );
1859+
1860+ enc_page_cnt = calc_pages_for (0 , tail_len );
1861+ enc_pages = ceph_alloc_page_vector (enc_page_cnt , GFP_NOIO );
1862+ if (IS_ERR (enc_pages ))
1863+ return PTR_ERR (enc_pages );
1864+
1865+ WARN_ON (con -> v2 .in_enc_pages || con -> v2 .in_enc_page_cnt );
1866+ con -> v2 .in_enc_pages = enc_pages ;
1867+ con -> v2 .in_enc_page_cnt = enc_page_cnt ;
1868+ con -> v2 .in_enc_resid = tail_len ;
1869+ con -> v2 .in_enc_i = 0 ;
1870+
1871+ prepare_read_enc_page (con );
1872+ return 0 ;
1873+ }
1874+
17841875static void __finish_skip (struct ceph_connection * con )
17851876{
17861877 con -> in_seq ++ ;
@@ -2589,46 +2680,26 @@ static int __handle_control(struct ceph_connection *con, void *p)
25892680 }
25902681
25912682 msg = con -> in_msg ; /* set in process_message_header() */
2592- if (!front_len (msg ) && !middle_len (msg )) {
2593- if (!data_len (msg ))
2594- return process_message (con );
2595-
2596- prepare_read_data (con );
2597- return 0 ;
2598- }
2599-
2600- reset_in_kvecs (con );
26012683 if (front_len (msg )) {
26022684 WARN_ON (front_len (msg ) > msg -> front_alloc_len );
2603- add_in_kvec (con , msg -> front .iov_base , front_len (msg ));
26042685 msg -> front .iov_len = front_len (msg );
2605-
2606- if (con_secure (con ) && need_padding (front_len (msg )))
2607- add_in_kvec (con , FRONT_PAD (con -> v2 .in_buf ),
2608- padding_len (front_len (msg )));
26092686 } else {
26102687 msg -> front .iov_len = 0 ;
26112688 }
26122689 if (middle_len (msg )) {
26132690 WARN_ON (middle_len (msg ) > msg -> middle -> alloc_len );
2614- add_in_kvec (con , msg -> middle -> vec .iov_base , middle_len (msg ));
26152691 msg -> middle -> vec .iov_len = middle_len (msg );
2616-
2617- if (con_secure (con ) && need_padding (middle_len (msg )))
2618- add_in_kvec (con , MIDDLE_PAD (con -> v2 .in_buf ),
2619- padding_len (middle_len (msg )));
26202692 } else if (msg -> middle ) {
26212693 msg -> middle -> vec .iov_len = 0 ;
26222694 }
26232695
2624- if (data_len (msg )) {
2625- con -> v2 .in_state = IN_S_PREPARE_READ_DATA ;
2626- } else {
2627- add_in_kvec (con , con -> v2 .in_buf ,
2628- con_secure (con ) ? CEPH_EPILOGUE_SECURE_LEN :
2629- CEPH_EPILOGUE_PLAIN_LEN );
2630- con -> v2 .in_state = IN_S_HANDLE_EPILOGUE ;
2631- }
2696+ if (!front_len (msg ) && !middle_len (msg ) && !data_len (msg ))
2697+ return process_message (con );
2698+
2699+ if (con_secure (con ))
2700+ return prepare_read_tail_secure (con );
2701+
2702+ prepare_read_tail_plain (con );
26322703 return 0 ;
26332704}
26342705
@@ -2717,7 +2788,7 @@ static int handle_epilogue(struct ceph_connection *con)
27172788 int ret ;
27182789
27192790 if (con_secure (con )) {
2720- ret = decrypt_message (con );
2791+ ret = decrypt_tail (con );
27212792 if (ret ) {
27222793 if (ret == - EBADMSG )
27232794 con -> error_msg = "integrity error, bad epilogue auth tag" ;
@@ -2792,6 +2863,10 @@ static int populate_in_iter(struct ceph_connection *con)
27922863 prepare_read_data_cont (con );
27932864 ret = 0 ;
27942865 break ;
2866+ case IN_S_PREPARE_READ_ENC_PAGE :
2867+ prepare_read_enc_page (con );
2868+ ret = 0 ;
2869+ break ;
27952870 case IN_S_HANDLE_EPILOGUE :
27962871 ret = handle_epilogue (con );
27972872 break ;
@@ -3326,20 +3401,16 @@ void ceph_con_v2_revoke(struct ceph_connection *con)
33263401
33273402static void revoke_at_prepare_read_data (struct ceph_connection * con )
33283403{
3329- int remaining ; /* data + [data padding] + epilogue */
3404+ int remaining ;
33303405 int resid ;
33313406
3407+ WARN_ON (con_secure (con ));
33323408 WARN_ON (!data_len (con -> in_msg ));
33333409 WARN_ON (!iov_iter_is_kvec (& con -> v2 .in_iter ));
33343410 resid = iov_iter_count (& con -> v2 .in_iter );
33353411 WARN_ON (!resid );
33363412
3337- if (con_secure (con ))
3338- remaining = padded_len (data_len (con -> in_msg )) +
3339- CEPH_EPILOGUE_SECURE_LEN ;
3340- else
3341- remaining = data_len (con -> in_msg ) + CEPH_EPILOGUE_PLAIN_LEN ;
3342-
3413+ remaining = data_len (con -> in_msg ) + CEPH_EPILOGUE_PLAIN_LEN ;
33433414 dout ("%s con %p resid %d remaining %d\n" , __func__ , con , resid ,
33443415 remaining );
33453416 con -> v2 .in_iter .count -= resid ;
@@ -3350,8 +3421,9 @@ static void revoke_at_prepare_read_data(struct ceph_connection *con)
33503421static void revoke_at_prepare_read_data_cont (struct ceph_connection * con )
33513422{
33523423 int recved , resid ; /* current piece of data */
3353- int remaining ; /* [data padding] + epilogue */
3424+ int remaining ;
33543425
3426+ WARN_ON (con_secure (con ));
33553427 WARN_ON (!data_len (con -> in_msg ));
33563428 WARN_ON (!iov_iter_is_bvec (& con -> v2 .in_iter ));
33573429 resid = iov_iter_count (& con -> v2 .in_iter );
@@ -3363,24 +3435,34 @@ static void revoke_at_prepare_read_data_cont(struct ceph_connection *con)
33633435 ceph_msg_data_advance (& con -> v2 .in_cursor , recved );
33643436 WARN_ON (resid > con -> v2 .in_cursor .total_resid );
33653437
3366- if (con_secure (con ))
3367- remaining = padding_len (data_len (con -> in_msg )) +
3368- CEPH_EPILOGUE_SECURE_LEN ;
3369- else
3370- remaining = CEPH_EPILOGUE_PLAIN_LEN ;
3371-
3438+ remaining = CEPH_EPILOGUE_PLAIN_LEN ;
33723439 dout ("%s con %p total_resid %zu remaining %d\n" , __func__ , con ,
33733440 con -> v2 .in_cursor .total_resid , remaining );
33743441 con -> v2 .in_iter .count -= resid ;
33753442 set_in_skip (con , con -> v2 .in_cursor .total_resid + remaining );
33763443 con -> v2 .in_state = IN_S_FINISH_SKIP ;
33773444}
33783445
3446+ static void revoke_at_prepare_read_enc_page (struct ceph_connection * con )
3447+ {
3448+ int resid ; /* current enc page (not necessarily data) */
3449+
3450+ WARN_ON (!con_secure (con ));
3451+ WARN_ON (!iov_iter_is_bvec (& con -> v2 .in_iter ));
3452+ resid = iov_iter_count (& con -> v2 .in_iter );
3453+ WARN_ON (!resid || resid > con -> v2 .in_bvec .bv_len );
3454+
3455+ dout ("%s con %p resid %d enc_resid %d\n" , __func__ , con , resid ,
3456+ con -> v2 .in_enc_resid );
3457+ con -> v2 .in_iter .count -= resid ;
3458+ set_in_skip (con , resid + con -> v2 .in_enc_resid );
3459+ con -> v2 .in_state = IN_S_FINISH_SKIP ;
3460+ }
3461+
33793462static void revoke_at_handle_epilogue (struct ceph_connection * con )
33803463{
33813464 int resid ;
33823465
3383- WARN_ON (!iov_iter_is_kvec (& con -> v2 .in_iter ));
33843466 resid = iov_iter_count (& con -> v2 .in_iter );
33853467 WARN_ON (!resid );
33863468
@@ -3399,6 +3481,9 @@ void ceph_con_v2_revoke_incoming(struct ceph_connection *con)
33993481 case IN_S_PREPARE_READ_DATA_CONT :
34003482 revoke_at_prepare_read_data_cont (con );
34013483 break ;
3484+ case IN_S_PREPARE_READ_ENC_PAGE :
3485+ revoke_at_prepare_read_enc_page (con );
3486+ break ;
34023487 case IN_S_HANDLE_EPILOGUE :
34033488 revoke_at_handle_epilogue (con );
34043489 break ;
@@ -3432,6 +3517,13 @@ void ceph_con_v2_reset_protocol(struct ceph_connection *con)
34323517 clear_out_sign_kvecs (con );
34333518 free_conn_bufs (con );
34343519
3520+ if (con -> v2 .in_enc_pages ) {
3521+ WARN_ON (!con -> v2 .in_enc_page_cnt );
3522+ ceph_release_page_vector (con -> v2 .in_enc_pages ,
3523+ con -> v2 .in_enc_page_cnt );
3524+ con -> v2 .in_enc_pages = NULL ;
3525+ con -> v2 .in_enc_page_cnt = 0 ;
3526+ }
34353527 if (con -> v2 .out_enc_pages ) {
34363528 WARN_ON (!con -> v2 .out_enc_page_cnt );
34373529 ceph_release_page_vector (con -> v2 .out_enc_pages ,
0 commit comments