Loading...
Note: File does not exist in v6.8.
1// SPDX-License-Identifier: GPL-2.0
2/*
3 * Copyright (C) 2017-2023 SUSE
4 * Authors: Libor Pechacek <lpechacek@suse.cz>
5 * Nicolai Stange <nstange@suse.de>
6 * Marcos Paulo de Souza <mpdesouza@suse.com>
7 */
8
9#include <linux/module.h>
10#include <linux/kernel.h>
11#include <linux/sched.h>
12#include <linux/slab.h>
13#include <linux/livepatch.h>
14
15#if defined(__x86_64__)
16#define FN_PREFIX __x64_
17#elif defined(__s390x__)
18#define FN_PREFIX __s390x_
19#elif defined(__aarch64__)
20#define FN_PREFIX __arm64_
21#else
22/* powerpc does not select ARCH_HAS_SYSCALL_WRAPPER */
23#define FN_PREFIX
24#endif
25
26/* Protects klp_pids */
27static DEFINE_MUTEX(kpid_mutex);
28
29static unsigned int npids, npids_pending;
30static int klp_pids[NR_CPUS];
31module_param_array(klp_pids, int, &npids_pending, 0);
32MODULE_PARM_DESC(klp_pids, "Array of pids to be transitioned to livepatched state.");
33
34static ssize_t npids_show(struct kobject *kobj, struct kobj_attribute *attr,
35 char *buf)
36{
37 return sprintf(buf, "%u\n", npids_pending);
38}
39
40static struct kobj_attribute klp_attr = __ATTR_RO(npids);
41static struct kobject *klp_kobj;
42
43static asmlinkage long lp_sys_getpid(void)
44{
45 int i;
46
47 mutex_lock(&kpid_mutex);
48 if (npids_pending > 0) {
49 for (i = 0; i < npids; i++) {
50 if (current->pid == klp_pids[i]) {
51 klp_pids[i] = 0;
52 npids_pending--;
53 break;
54 }
55 }
56 }
57 mutex_unlock(&kpid_mutex);
58
59 return task_tgid_vnr(current);
60}
61
62static struct klp_func vmlinux_funcs[] = {
63 {
64 .old_name = __stringify(FN_PREFIX) "sys_getpid",
65 .new_func = lp_sys_getpid,
66 }, {}
67};
68
69static struct klp_object objs[] = {
70 {
71 /* name being NULL means vmlinux */
72 .funcs = vmlinux_funcs,
73 }, {}
74};
75
76static struct klp_patch patch = {
77 .mod = THIS_MODULE,
78 .objs = objs,
79};
80
81static int livepatch_init(void)
82{
83 int ret;
84
85 klp_kobj = kobject_create_and_add("test_klp_syscall", kernel_kobj);
86 if (!klp_kobj)
87 return -ENOMEM;
88
89 ret = sysfs_create_file(klp_kobj, &klp_attr.attr);
90 if (ret) {
91 kobject_put(klp_kobj);
92 return ret;
93 }
94
95 /*
96 * Save the number pids to transition to livepatched state before the
97 * number of pending pids is decremented.
98 */
99 npids = npids_pending;
100
101 return klp_enable_patch(&patch);
102}
103
104static void livepatch_exit(void)
105{
106 kobject_put(klp_kobj);
107}
108
109module_init(livepatch_init);
110module_exit(livepatch_exit);
111MODULE_LICENSE("GPL");
112MODULE_INFO(livepatch, "Y");
113MODULE_AUTHOR("Libor Pechacek <lpechacek@suse.cz>");
114MODULE_AUTHOR("Nicolai Stange <nstange@suse.de>");
115MODULE_AUTHOR("Marcos Paulo de Souza <mpdesouza@suse.com>");
116MODULE_DESCRIPTION("Livepatch test: syscall transition");