@@ -289,22 +289,25 @@ static int hdr_read_disk(struct crypt_device *cd,
289289 */
290290static int hdr_write_disk (struct crypt_device * cd ,
291291 struct device * device , struct luks2_hdr * hdr ,
292- const char * json_area , int secondary )
292+ const char * json_area , size_t write_area_len ,
293+ int secondary )
293294{
294295 struct luks2_hdr_disk hdr_disk ;
295296 uint64_t offset = secondary ? hdr -> hdr_size : 0 ;
296297 size_t hdr_json_len ;
297298 int devfd , r ;
298299
300+ hdr_json_len = hdr -> hdr_size - LUKS2_HDR_BIN_LEN ;
301+
302+ assert (write_area_len <= hdr_json_len );
303+
299304 log_dbg (cd , "Trying to write LUKS2 header (%zu bytes) at offset %" PRIu64 "." ,
300- hdr -> hdr_size , offset );
305+ write_area_len , offset );
301306
302307 devfd = device_open_locked (cd , device , O_RDWR );
303308 if (devfd < 0 )
304309 return devfd == -1 ? - EINVAL : devfd ;
305310
306- hdr_json_len = hdr -> hdr_size - LUKS2_HDR_BIN_LEN ;
307-
308311 hdr_to_disk (hdr , & hdr_disk , secondary , offset );
309312
310313 /*
@@ -321,8 +324,8 @@ static int hdr_write_disk(struct crypt_device *cd,
321324 */
322325 if (write_lseek_blockwise (devfd , device_block_size (cd , device ),
323326 device_alignment (device ),
324- CONST_CAST (char * )json_area , hdr_json_len ,
325- LUKS2_HDR_BIN_LEN + offset ) < (ssize_t )hdr_json_len ) {
327+ CONST_CAST (char * )json_area , write_area_len ,
328+ LUKS2_HDR_BIN_LEN + offset ) < (ssize_t )write_area_len ) {
326329 return - EIO ;
327330 }
328331
@@ -401,7 +404,7 @@ int LUKS2_disk_hdr_write(struct crypt_device *cd, struct luks2_hdr *hdr, struct
401404{
402405 char * json_area ;
403406 const char * json_text ;
404- size_t json_area_len ;
407+ size_t json_data_len , json_area_len , json_area_write_len ;
405408 int r ;
406409
407410 if (hdr -> version != 2 ) {
@@ -413,28 +416,47 @@ int LUKS2_disk_hdr_write(struct crypt_device *cd, struct luks2_hdr *hdr, struct
413416 if (r )
414417 return r ;
415418
416- /*
417- * Allocate and zero JSON area (of proper header size).
418- */
419- json_area_len = hdr -> hdr_size - LUKS2_HDR_BIN_LEN ;
420- json_area = crypt_zalloc (json_area_len );
421- if (!json_area )
422- return - ENOMEM ;
423-
424419 /*
425420 * Generate text space-efficient JSON representation to json area.
426421 */
427422 json_text = crypt_jobj_to_string_on_disk (hdr -> jobj );
428423 if (!json_text || !* json_text ) {
429424 log_dbg (cd , "Cannot parse JSON object to text representation." );
430- free (json_area );
431425 return - ENOMEM ;
432426 }
433- if (strlen (json_text ) > (json_area_len - 1 )) {
434- log_dbg (cd , "JSON is too large (%zu > %zu)." , strlen (json_text ), json_area_len );
435- free (json_area );
427+
428+ json_area_len = hdr -> hdr_size - LUKS2_HDR_BIN_LEN ;
429+ json_area_write_len = json_data_len = strlen (json_text );
430+
431+ if (json_data_len > (json_area_len - 1 )) {
432+ log_dbg (cd , "JSON is too large (%zu > %zu)." , json_data_len , json_area_len );
436433 return - EINVAL ;
437434 }
435+
436+ /*
437+ * Allocate and zero JSON area (of proper header size).
438+ */
439+ json_area = crypt_zalloc (json_area_len );
440+ if (!json_area )
441+ return - ENOMEM ;
442+
443+ /*
444+ * If the metadata in 'json_area' buffer is smaller than last on-disk
445+ * metadata we also have to erase the remaining bytes between the tail
446+ * of current metadata and the on-disk metadata end pointer. Set write
447+ * area length large enough to overwrite it.
448+ *
449+ * If seqid_check is turned off (during LUKS2 format) write entire
450+ * LUKS2 metadata size instead.
451+ *
452+ * Turn off the optimization also during metadata upconversion
453+ * (hdr->on_disk_json_end_offset == 0).
454+ */
455+ if (seqid_check && (json_data_len < hdr -> on_disk_json_end_offset ))
456+ json_area_write_len = hdr -> on_disk_json_end_offset ;
457+ else if (!seqid_check || !hdr -> on_disk_json_end_offset )
458+ json_area_write_len = json_area_len ;
459+
438460 strncpy (json_area , json_text , json_area_len );
439461
440462 if (seqid_check )
@@ -450,13 +472,16 @@ int LUKS2_disk_hdr_write(struct crypt_device *cd, struct luks2_hdr *hdr, struct
450472 hdr -> seqid ++ ;
451473
452474 /* Write primary and secondary header */
453- r = hdr_write_disk (cd , device , hdr , json_area , 0 );
475+ r = hdr_write_disk (cd , device , hdr , json_area , json_area_write_len , 0 );
454476 if (!r )
455- r = hdr_write_disk (cd , device , hdr , json_area , 1 );
477+ r = hdr_write_disk (cd , device , hdr , json_area , json_area_write_len , 1 );
456478
457479 if (r )
458480 log_dbg (cd , "LUKS2 header write failed (%d)." , r );
459481
482+ /* store new json end pointer or reset it on error */
483+ hdr -> on_disk_json_end_offset = r ? 0 : json_data_len ;
484+
460485 device_write_unlock (cd , device );
461486
462487 free (json_area );
@@ -524,12 +549,15 @@ static int validate_luks2_json_object(struct crypt_device *cd, json_object *jobj
524549}
525550
526551static json_object * parse_and_validate_json (struct crypt_device * cd ,
527- const char * json_area , uint64_t hdr_size )
552+ const char * json_area , uint64_t hdr_size ,
553+ uint64_t * json_area_end )
528554{
529555 int json_len , r ;
530556 json_object * jobj ;
531557 uint64_t max_length ;
532558
559+ assert (json_area_end );
560+
533561 if (hdr_size <= LUKS2_HDR_BIN_LEN || hdr_size > LUKS2_HDR_OFFSET_MAX ) {
534562 log_dbg (cd , "LUKS2 header JSON has bogus size 0x%04" PRIx64 "." , hdr_size );
535563 return NULL ;
@@ -553,6 +581,8 @@ static json_object *parse_and_validate_json(struct crypt_device *cd,
553581 jobj = NULL ;
554582 }
555583
584+ * json_area_end = json_len ;
585+
556586 return jobj ;
557587}
558588
@@ -616,7 +646,7 @@ int LUKS2_disk_hdr_read(struct crypt_device *cd, struct luks2_hdr *hdr,
616646 json_object * jobj_hdr1 = NULL , * jobj_hdr2 = NULL ;
617647 unsigned int i ;
618648 int r ;
619- uint64_t hdr_size ;
649+ uint64_t hdr_size , json_area_end1 = 0 , json_area_end2 = 0 ;
620650 uint64_t hdr2_offsets [] = LUKS2_HDR2_OFFSETS ;
621651
622652 /* Skip auto-recovery if locks are disabled and we're not doing LUKS2 explicit repair */
@@ -631,7 +661,7 @@ int LUKS2_disk_hdr_read(struct crypt_device *cd, struct luks2_hdr *hdr,
631661 state_hdr1 = HDR_FAIL ;
632662 r = hdr_read_disk (cd , device , & hdr_disk1 , & json_area1 , 0 , 0 );
633663 if (r == 0 ) {
634- jobj_hdr1 = parse_and_validate_json (cd , json_area1 , be64_to_cpu (hdr_disk1 .hdr_size ));
664+ jobj_hdr1 = parse_and_validate_json (cd , json_area1 , be64_to_cpu (hdr_disk1 .hdr_size ), & json_area_end1 );
635665 state_hdr1 = jobj_hdr1 ? HDR_OK : HDR_OBSOLETE ;
636666 } else if (r == - EIO )
637667 state_hdr1 = HDR_FAIL_IO ;
@@ -643,7 +673,7 @@ int LUKS2_disk_hdr_read(struct crypt_device *cd, struct luks2_hdr *hdr,
643673 if (state_hdr1 != HDR_FAIL && state_hdr1 != HDR_FAIL_IO ) {
644674 r = hdr_read_disk (cd , device , & hdr_disk2 , & json_area2 , be64_to_cpu (hdr_disk1 .hdr_size ), 1 );
645675 if (r == 0 ) {
646- jobj_hdr2 = parse_and_validate_json (cd , json_area2 , be64_to_cpu (hdr_disk2 .hdr_size ));
676+ jobj_hdr2 = parse_and_validate_json (cd , json_area2 , be64_to_cpu (hdr_disk2 .hdr_size ), & json_area_end2 );
647677 state_hdr2 = jobj_hdr2 ? HDR_OK : HDR_OBSOLETE ;
648678 } else if (r == - EIO )
649679 state_hdr2 = HDR_FAIL_IO ;
@@ -656,7 +686,7 @@ int LUKS2_disk_hdr_read(struct crypt_device *cd, struct luks2_hdr *hdr,
656686 r = hdr_read_disk (cd , device , & hdr_disk2 , & json_area2 , hdr2_offsets [i ], 1 );
657687
658688 if (r == 0 ) {
659- jobj_hdr2 = parse_and_validate_json (cd , json_area2 , be64_to_cpu (hdr_disk2 .hdr_size ));
689+ jobj_hdr2 = parse_and_validate_json (cd , json_area2 , be64_to_cpu (hdr_disk2 .hdr_size ), & json_area_end2 );
660690 state_hdr2 = jobj_hdr2 ? HDR_OK : HDR_OBSOLETE ;
661691 } else if (r == - EIO )
662692 state_hdr2 = HDR_FAIL_IO ;
@@ -705,7 +735,7 @@ int LUKS2_disk_hdr_read(struct crypt_device *cd, struct luks2_hdr *hdr,
705735 log_dbg (cd , "Cannot generate header salt." );
706736 else {
707737 hdr_from_disk (& hdr_disk1 , & hdr_disk2 , hdr , 0 );
708- r = hdr_write_disk (cd , device , hdr , json_area1 , 1 );
738+ r = hdr_write_disk (cd , device , hdr , json_area1 , hdr -> hdr_size - LUKS2_HDR_BIN_LEN , 1 );
709739 }
710740 if (r )
711741 log_dbg (cd , "Secondary LUKS2 header recovery failed." );
@@ -726,7 +756,7 @@ int LUKS2_disk_hdr_read(struct crypt_device *cd, struct luks2_hdr *hdr,
726756 log_dbg (cd , "Cannot generate header salt." );
727757 else {
728758 hdr_from_disk (& hdr_disk2 , & hdr_disk1 , hdr , 1 );
729- r = hdr_write_disk (cd , device , hdr , json_area2 , 0 );
759+ r = hdr_write_disk (cd , device , hdr , json_area2 , hdr -> hdr_size - LUKS2_HDR_BIN_LEN , 0 );
730760 }
731761 if (r )
732762 log_dbg (cd , "Primary LUKS2 header recovery failed." );
@@ -755,6 +785,11 @@ int LUKS2_disk_hdr_read(struct crypt_device *cd, struct luks2_hdr *hdr,
755785 json_object_put (jobj_hdr1 );
756786 }
757787
788+ if (json_area_end1 > json_area_end2 )
789+ hdr -> on_disk_json_end_offset = json_area_end1 ;
790+ else
791+ hdr -> on_disk_json_end_offset = json_area_end2 ;
792+
758793 /*
759794 * FIXME: should this fail? At least one header was read correctly.
760795 * r = (state_hdr1 == HDR_FAIL_IO || state_hdr2 == HDR_FAIL_IO) ? -EIO : -EINVAL;
0 commit comments