Skip to content

Instantly share code, notes, and snippets.

@kwilczynski
Created February 20, 2024 11:19
Show Gist options
  • Save kwilczynski/284e21d2ea8cc4f924dd2ed31f4f36af to your computer and use it in GitHub Desktop.
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
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
#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