When restoring an incoming block set via kho_block_set_restore(), the
physical chain of blocks is already linked and bs->head_pa is already
set. However, kho_block_add() unconditionally rewrites last->ser->next
and bs->head_pa, and kho_block_set_shrink_one() clears
new_last->ser->next even when operating on an incoming block set.

In the upcoming KHO read-only mode, incoming serialized blocks are
mapped read-only and must not be modified. Guard the ser->next and
bs->head_pa updates in kho_block_add() and kho_block_set_shrink_one()
with !bs->incoming.

Signed-off-by: Pasha Tatashin <[email protected]>
---
 kernel/liveupdate/kho_block.c | 16 +++++++++-------
 1 file changed, 9 insertions(+), 7 deletions(-)

diff --git a/kernel/liveupdate/kho_block.c b/kernel/liveupdate/kho_block.c
index 0d2a342ef422..a4e945f28fad 100644
--- a/kernel/liveupdate/kho_block.c
+++ b/kernel/liveupdate/kho_block.c
@@ -93,10 +93,12 @@ static int kho_block_add(struct kho_block_set *bs,
        list_add_tail(&block->list, &bs->blocks);
        bs->nblocks++;
 
-       if (last)
-               last->ser->next = virt_to_phys(ser);
-       else
-               bs->head_pa = virt_to_phys(ser);
+       if (!bs->incoming) {
+               if (last)
+                       last->ser->next = virt_to_phys(ser);
+               else
+                       bs->head_pa = virt_to_phys(ser);
+       }
 
        return 0;
 }
@@ -133,10 +135,10 @@ static void kho_block_set_shrink_one(struct kho_block_set 
*bs)
        kfree(last);
 
        new_last = list_last_entry_or_null(&bs->blocks, struct kho_block, list);
-       if (new_last)
-               new_last->ser->next = 0;
-       else
+       if (!new_last)
                bs->head_pa = 0;
+       else if (!bs->incoming)
+               new_last->ser->next = 0;
 }
 
 /**
-- 
2.56.0.176.g3575e65682-goog


Reply via email to