Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
at master 158 lines 3.9 kB view raw
1// SPDX-License-Identifier: GPL-2.0 2 3/* 4 * Copyright (c) 2025, Google LLC. 5 * Pasha Tatashin <pasha.tatashin@soleen.com> 6 */ 7 8#define pr_fmt(fmt) KBUILD_MODNAME " test: " fmt 9 10#include <linux/cleanup.h> 11#include <linux/errno.h> 12#include <linux/init.h> 13#include <linux/liveupdate.h> 14#include <linux/module.h> 15#include "../../kernel/liveupdate/luo_internal.h" 16 17static const struct liveupdate_flb_ops test_flb_ops; 18#define DEFINE_TEST_FLB(i) { \ 19 .ops = &test_flb_ops, \ 20 .compatible = LIVEUPDATE_TEST_FLB_COMPATIBLE(i), \ 21} 22 23/* Number of Test FLBs to register with every file handler */ 24#define TEST_NFLBS 3 25static struct liveupdate_flb test_flbs[TEST_NFLBS] = { 26 DEFINE_TEST_FLB(0), 27 DEFINE_TEST_FLB(1), 28 DEFINE_TEST_FLB(2), 29}; 30 31#define TEST_FLB_MAGIC_BASE 0xFEEDF00DCAFEBEE0ULL 32 33static int test_flb_preserve(struct liveupdate_flb_op_args *argp) 34{ 35 ptrdiff_t index = argp->flb - test_flbs; 36 37 pr_info("%s: preserve was triggered\n", argp->flb->compatible); 38 argp->data = TEST_FLB_MAGIC_BASE + index; 39 40 return 0; 41} 42 43static void test_flb_unpreserve(struct liveupdate_flb_op_args *argp) 44{ 45 pr_info("%s: unpreserve was triggered\n", argp->flb->compatible); 46} 47 48static int test_flb_retrieve(struct liveupdate_flb_op_args *argp) 49{ 50 ptrdiff_t index = argp->flb - test_flbs; 51 u64 expected_data = TEST_FLB_MAGIC_BASE + index; 52 53 if (argp->data == expected_data) { 54 pr_info("%s: found flb data from the previous boot\n", 55 argp->flb->compatible); 56 argp->obj = (void *)argp->data; 57 } else { 58 pr_err("%s: ERROR - incorrect data handle: %llx, expected %llx\n", 59 argp->flb->compatible, argp->data, expected_data); 60 return -EINVAL; 61 } 62 63 return 0; 64} 65 66static void test_flb_finish(struct liveupdate_flb_op_args *argp) 67{ 68 ptrdiff_t index = argp->flb - test_flbs; 69 void *expected_obj = (void *)(TEST_FLB_MAGIC_BASE + index); 70 71 if (argp->obj == expected_obj) { 72 pr_info("%s: finish was triggered\n", argp->flb->compatible); 73 } else { 74 pr_err("%s: ERROR - finish called with invalid object\n", 75 argp->flb->compatible); 76 } 77} 78 79static const struct liveupdate_flb_ops test_flb_ops = { 80 .preserve = test_flb_preserve, 81 .unpreserve = test_flb_unpreserve, 82 .retrieve = test_flb_retrieve, 83 .finish = test_flb_finish, 84 .owner = THIS_MODULE, 85}; 86 87static void liveupdate_test_init(void) 88{ 89 static DEFINE_MUTEX(init_lock); 90 static bool initialized; 91 int i; 92 93 guard(mutex)(&init_lock); 94 95 if (initialized) 96 return; 97 98 for (i = 0; i < TEST_NFLBS; i++) { 99 struct liveupdate_flb *flb = &test_flbs[i]; 100 void *obj; 101 int err; 102 103 err = liveupdate_flb_get_incoming(flb, &obj); 104 if (err && err != -ENODATA && err != -ENOENT) { 105 pr_err("liveupdate_flb_get_incoming for %s failed: %pe\n", 106 flb->compatible, ERR_PTR(err)); 107 } 108 } 109 initialized = true; 110} 111 112void liveupdate_test_register(struct liveupdate_file_handler *fh) 113{ 114 int err, i; 115 116 liveupdate_test_init(); 117 118 for (i = 0; i < TEST_NFLBS; i++) { 119 struct liveupdate_flb *flb = &test_flbs[i]; 120 121 err = liveupdate_register_flb(fh, flb); 122 if (err) { 123 pr_err("Failed to register %s %pe\n", 124 flb->compatible, ERR_PTR(err)); 125 } 126 } 127 128 err = liveupdate_register_flb(fh, &test_flbs[0]); 129 if (!err || err != -EEXIST) { 130 pr_err("Failed: %s should be already registered, but got err: %pe\n", 131 test_flbs[0].compatible, ERR_PTR(err)); 132 } 133 134 pr_info("Registered %d FLBs with file handler: [%s]\n", 135 TEST_NFLBS, fh->compatible); 136} 137 138void liveupdate_test_unregister(struct liveupdate_file_handler *fh) 139{ 140 int err, i; 141 142 for (i = 0; i < TEST_NFLBS; i++) { 143 struct liveupdate_flb *flb = &test_flbs[i]; 144 145 err = liveupdate_unregister_flb(fh, flb); 146 if (err) { 147 pr_err("Failed to unregister %s %pe\n", 148 flb->compatible, ERR_PTR(err)); 149 } 150 } 151 152 pr_info("Unregistered %d FLBs from file handler: [%s]\n", 153 TEST_NFLBS, fh->compatible); 154} 155 156MODULE_LICENSE("GPL"); 157MODULE_AUTHOR("Pasha Tatashin <pasha.tatashin@soleen.com>"); 158MODULE_DESCRIPTION("In-kernel test for LUO mechanism");