This is related to:
Created
February 20, 2024 11:19
-
-
Save kwilczynski/284e21d2ea8cc4f924dd2ed31f4f36af to your computer and use it in GitHub Desktop.
Simple Linux kernel module to toggle running process state between "D" (uninterruptible) and interruptible
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
ccflags-y := -DDEBUG -Wfatal-errors | |
ifneq ($(KERNELRELEASE),) | |
obj-m += state-toggle.o | |
else | |
BUILD_KERNEL ?= /lib/modules/$(shell uname -r)/build | |
default: | |
$(MAKE) -C $(BUILD_KERNEL) M=$(CURDIR) modules | |
endif | |
all: default | |
clean: | |
$(MAKE) -C $(BUILD_KERNEL) M=$(CURDIR) clean | |
install: default | |
$(MAKE) -C $(BUILD_KERNEL) M=$(CURDIR) modules_install |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#define DEFAULT_NAME "state-toggle" | |
#define KMSG_COMPONENT DEFAULT_NAME | |
#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt | |
#include <linux/kernel.h> | |
#include <linux/module.h> | |
#include <linux/sched.h> | |
MODULE_AUTHOR(""); | |
MODULE_DESCRIPTION(""); | |
MODULE_VERSION("0.1.0"); | |
MODULE_LICENSE("GPL"); | |
static struct kobject *toggle_kobj; | |
static ssize_t pid_store(struct kobject *kobj, struct kobj_attribute *attr, | |
const char *buf, size_t count) | |
{ | |
pid_t pid; | |
struct task_struct *task; | |
int old_state, state; | |
if (count >= PAGE_SIZE) | |
return -EINVAL; | |
if (kstrtoint(buf, 0, &pid) < 0) | |
return -EINVAL; | |
task = get_pid_task(find_vpid(pid), PIDTYPE_PID); | |
if (!task) | |
return -ENOENT; | |
old_state = task->__state; | |
state = TASK_UNINTERRUPTIBLE; | |
if (old_state & TASK_UNINTERRUPTIBLE) | |
state = TASK_INTERRUPTIBLE; | |
task->__state = state; /* This is generally a no-no. */ | |
pr_info("%s(%d): %c (0x%02x) -> %c (0x%02x)\n", task->comm, task->pid, | |
task_index_to_char(old_state), old_state, task_index_to_char(state), | |
state); | |
/* Wake the task up so it can consume any pending signals. */ | |
if (state & TASK_INTERRUPTIBLE) | |
wake_up_process(task); | |
return count; | |
} | |
static struct kobj_attribute pid_attr = __ATTR_WO(pid); | |
static struct attribute *toggle_attrs[] = { | |
&pid_attr.attr, | |
NULL, | |
}; | |
static struct attribute_group toggle_group = { | |
.attrs = toggle_attrs, | |
}; | |
static int __init toggle_init(void) | |
{ | |
int ret; | |
/* Add an entry under /sys/kernel as /sys/kernel/state-toggle/pid. */ | |
toggle_kobj = kobject_create_and_add(DEFAULT_NAME, kernel_kobj); | |
if (IS_ERR(toggle_kobj)) | |
return -ENOMEM; | |
ret = sysfs_create_group(toggle_kobj, &toggle_group); | |
if (ret) | |
goto error; | |
return 0; | |
error: | |
kobject_put(toggle_kobj); | |
return -ENOSYS; | |
} | |
static void __exit toggle_exit(void) | |
{ | |
kobject_put(toggle_kobj); | |
} | |
module_init(toggle_init); | |
module_exit(toggle_exit); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment