projects/linux·blob assoc-array-fixes · refs

143 lines · 3.5 KiB

1// SPDX-License-Identifier: GPL-2.0
2
3/*
4 * Copyright (c) 2025, Google LLC.
5 * Pasha Tatashin <[email protected]>
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 if (!err)
110 liveupdate_flb_put_incoming(flb);
111 }
112 initialized = true;
113}
114
115void liveupdate_test_register(struct liveupdate_file_handler *fh)
116{
117 int err, i;
118
119 liveupdate_test_init();
120
121 for (i = 0; i < TEST_NFLBS; i++) {
122 struct liveupdate_flb *flb = &test_flbs[i];
123
124 err = liveupdate_register_flb(fh, flb);
125 if (err) {
126 pr_err("Failed to register %s %pe\n",
127 flb->compatible, ERR_PTR(err));
128 }
129 }
130
131 err = liveupdate_register_flb(fh, &test_flbs[0]);
132 if (!err || err != -EEXIST) {
133 pr_err("Failed: %s should be already registered, but got err: %pe\n",
134 test_flbs[0].compatible, ERR_PTR(err));
135 }
136
137 pr_info("Registered %d FLBs with file handler: [%s]\n",
138 TEST_NFLBS, fh->compatible);
139}
140
141MODULE_LICENSE("GPL");
142MODULE_AUTHOR("Pasha Tatashin <[email protected]>");
143MODULE_DESCRIPTION("In-kernel test for LUO mechanism");