Precede each serialized file entry in a LUO file set KHO block set with struct kho_ser_hdr via DECLARE_KHO_SER so future per-file metadata features can append fields to struct luo_file_ser without breaking compatibility between adjacent kernels. Initialize file set block sets with kho_ser_size(luo_file_ser), initialize each entry feature header in luo_file_freeze(), and validate the incoming feature header in luo_file_deserialize_one() before accessing the struct luo_file_ser payload. Signed-off-by: Tarun Sahu --- include/linux/kho/abi/luo.h | 6 +++--- kernel/liveupdate/luo_file.c | 26 +++++++++++++++++++------- 2 files changed, 22 insertions(+), 10 deletions(-) diff --git a/include/linux/kho/abi/luo.h b/include/linux/kho/abi/luo.h index bd19211c64e1..38b4658183a2 100644 --- a/include/linux/kho/abi/luo.h +++ b/include/linux/kho/abi/luo.h @@ -92,6 +92,8 @@ DECLARE_KHO_SER(luo_ser, 24, 0, 0); * @compatible: File handler compatible string. * @data: Private data * @token: User provided token for this file + * + * Preceded by &struct kho_ser_hdr. */ struct luo_file_ser { char compatible[LIVEUPDATE_HNDL_COMPAT_LENGTH]; @@ -99,9 +101,7 @@ struct luo_file_ser { u64 token; }; -static_assert(sizeof(struct luo_file_ser) == 64); -static_assert(!IS_ENABLED(CONFIG_64BIT) || - __alignof__(struct luo_file_ser) == 8); +DECLARE_KHO_SER(luo_file_ser, 64, 0, 0); /** * struct luo_file_set_ser - Represents the serialized metadata for file set diff --git a/kernel/liveupdate/luo_file.c b/kernel/liveupdate/luo_file.c index 02d09a80d785..2da327f8bdae 100644 --- a/kernel/liveupdate/luo_file.c +++ b/kernel/liveupdate/luo_file.c @@ -486,10 +486,12 @@ int luo_file_freeze(struct luo_file_set *file_set, kho_block_set_it_init(&it, &file_set->block_set); list_for_each_entry(luo_file, &file_set->files_list, list) { - struct luo_file_ser *file_ser = kho_block_set_it_reserve_entry(&it); + DECLARE_KHO_SER_HDR(luo_file_ser, *fhdr) = + kho_block_set_it_reserve_entry(&it); + struct luo_file_ser *file_ser; /* This should not fail normally as blocks were pre-allocated */ - if (WARN_ON_ONCE(!file_ser)) { + if (WARN_ON_ONCE(!fhdr)) { err = -ENOSPC; goto err_unfreeze; } @@ -502,6 +504,8 @@ int luo_file_freeze(struct luo_file_set *file_set, goto err_unfreeze; } + kho_ser_init(fhdr, luo_file_ser); + file_ser = kho_ser_payload(fhdr, luo_file_ser); strscpy(file_ser->compatible, luo_file->fh->compatible, sizeof(file_ser->compatible)); file_ser->data = luo_file->serialized_data; @@ -742,11 +746,19 @@ int luo_file_finish(struct luo_file_set *file_set) } static int luo_file_deserialize_one(struct luo_file_set *file_set, - struct luo_file_ser *ser) + DECLARE_KHO_SER_HDR(luo_file_ser, *fhdr)) { struct liveupdate_file_handler *fh; bool handler_found = false; + struct luo_file_ser *ser; struct luo_file *luo_file; + int err; + + err = kho_ser_validate(fhdr, luo_file_ser); + if (err) + return err; + + ser = kho_ser_payload(fhdr, luo_file_ser); down_read(&luo_register_rwlock); list_private_for_each_entry(fh, &luo_file_handler_list, list) { @@ -810,7 +822,7 @@ int luo_file_deserialize(struct luo_file_set *file_set, DECLARE_KHO_SER_HDR(luo_file_set_ser, *file_set_fhdr)) { struct luo_file_set_ser *file_set_ser; - struct luo_file_ser *file_ser; + DECLARE_KHO_SER_HDR(luo_file_ser, *fhdr); struct kho_block_set_it it; int err; @@ -848,8 +860,8 @@ int luo_file_deserialize(struct luo_file_set *file_set, * reliably reset devices and reclaim memory. */ kho_block_set_it_init(&it, &file_set->block_set); - while ((file_ser = kho_block_set_it_read_entry(&it))) { - err = luo_file_deserialize_one(file_set, file_ser); + while ((fhdr = kho_block_set_it_read_entry(&it))) { + err = luo_file_deserialize_one(file_set, fhdr); if (err) goto err_destroy_blocks; file_set->count++; @@ -883,7 +895,7 @@ int luo_file_deserialize(struct luo_file_set *file_set, void luo_file_set_init(struct luo_file_set *file_set) { INIT_LIST_HEAD(&file_set->files_list); - kho_block_set_init(&file_set->block_set, sizeof(struct luo_file_ser)); + kho_block_set_init(&file_set->block_set, kho_ser_size(luo_file_ser)); } void luo_file_set_destroy(struct luo_file_set *file_set) -- 2.56.0.506.g506a7eabc5-goog