Linux Audio

Check our new training course

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");