tkernel: make the code for the kill block feature cleaner

No functional changes, just making the code cleaner.

Signed-off-by: Yongliang Gao <leonylgao@tencent.com>
Reviewed-by: Jianping Liu <frankjpliu@tencent.com>
This commit is contained in:
Yongliang Gao 2024-11-07 16:51:01 +08:00
parent 3cc17b97d8
commit 757f8aaf97
2 changed files with 52 additions and 75 deletions

View File

@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0
/*
* linux/kernel/tkernel/killblock/kill_block.c
* kernel/tkernel/killblock/kill_block.c
*
* Copyright (C) 2023 Hongbo Li <herberthbli@tencent.com>
*/
@ -15,13 +15,25 @@
#include <linux/uaccess.h>
#include <linux/cgroup.h>
#include <linux/kill_hook.h>
#include "kill_block.h"
int sysctl_sig_kill_block;
#define KILL_BLOCK_DIR "kill_block"
#define KILL_BLOCK_CMD_LEN 128
#define KILL_BLOCK_CGRP_LEN 64
#define KILL_BLOCK_RULES_MAX_CNT 1024
struct kb_whitelist_rule {
struct list_head node;
char src_comm[TASK_COMM_LEN];
char dst_comm[TASK_COMM_LEN];
char dst_cgrp[KILL_BLOCK_CGRP_LEN];
};
static unsigned int two = 2;
static unsigned int sysctl_sig_kill_block;
static atomic64_t kb_cnt_root = ATOMIC64_INIT(0);
static atomic64_t kb_cnt_child = ATOMIC64_INIT(0);
static atomic_t kb_rule_cnt = ATOMIC_INIT(0);
static struct proc_dir_entry *kb_proc_dir;
static struct proc_dir_entry *kb_proc_dir;
static struct proc_dir_entry *whitelist_entry;
static struct proc_dir_entry *stat_entry;
static struct ctl_table_header *kb_sysctl_header;
@ -32,22 +44,19 @@ static struct kill_hook kill_block_hook;
static ssize_t whitelist_write(struct file *file, const char __user *ubuf,
size_t count, loff_t *ppos)
{
char cmd[KILL_BLOCK_CMD_LEN], _str[KILL_BLOCK_CMD_LEN];
char cmd[KILL_BLOCK_CMD_LEN] = {0};
char *token[4], *str;
int cnt, i = 0;
int cnt, i;
struct kb_whitelist_rule *rule, *tmp;
memset(cmd, 0, KILL_BLOCK_CMD_LEN);
cnt = min_t(size_t, count, KILL_BLOCK_CMD_LEN - 1);
if (strncpy_from_user(cmd, ubuf, cnt) < 0)
return -EINVAL;
return -EFAULT;
if (strlen(cmd) < 1)
return -EINVAL;
strcpy(_str, cmd);
str = _str;
str = cmd;
str[cnt - 1] = '\0';
i = 0;
@ -61,15 +70,14 @@ static ssize_t whitelist_write(struct file *file, const char __user *ubuf,
if (i == 1) {
if (!strcmp(token[0], "flush")) {
write_lock_bh(&whitelist_lock);
list_for_each_entry_safe(rule, tmp, &whitelist_list,
node) {
write_lock(&whitelist_lock);
list_for_each_entry_safe(rule, tmp, &whitelist_list, node) {
list_del(&rule->node);
kfree(rule);
}
write_unlock_bh(&whitelist_lock);
write_unlock(&whitelist_lock);
atomic_set(&kb_rule_cnt, 0);
return cnt;
return count;
}
return -EINVAL;
} else if (i != 4) {
@ -79,7 +87,7 @@ static ssize_t whitelist_write(struct file *file, const char __user *ubuf,
if (!strcmp(token[0], "add")) {
if (atomic_read(&kb_rule_cnt) >= KILL_BLOCK_RULES_MAX_CNT)
return -ENOMEM;
rule = kzalloc(sizeof(*rule), GFP_KERNEL);
rule = kzalloc(sizeof(struct kb_whitelist_rule), GFP_KERNEL);
if (!rule)
return -ENOMEM;
@ -92,32 +100,34 @@ static ssize_t whitelist_write(struct file *file, const char __user *ubuf,
cnt = min_t(size_t, KILL_BLOCK_CGRP_LEN - 1, strlen(token[3]));
strncpy(rule->dst_cgrp, token[3], cnt);
rule->dst_cgrp[cnt] = '\0';
write_lock_bh(&whitelist_lock);
write_lock(&whitelist_lock);
list_for_each_entry(tmp, &whitelist_list, node) {
if (!strcasecmp(tmp->src_comm, rule->src_comm) &&
!strcasecmp(tmp->dst_comm, rule->dst_comm) &&
!strcasecmp(tmp->dst_cgrp, rule->dst_cgrp)) {
write_unlock_bh(&whitelist_lock);
write_unlock(&whitelist_lock);
kfree(rule);
return -EEXIST;
}
}
list_add(&rule->node, &whitelist_list);
write_unlock_bh(&whitelist_lock);
write_unlock(&whitelist_lock);
atomic_inc(&kb_rule_cnt);
} else if (!strcmp(token[0], "del")) {
write_lock_bh(&whitelist_lock);
write_lock(&whitelist_lock);
list_for_each_entry_safe(rule, tmp, &whitelist_list, node) {
if (!strcasecmp(rule->src_comm, token[1]) &&
!strcasecmp(rule->dst_comm, token[2]) &&
!strcasecmp(rule->dst_cgrp, token[3])) {
list_del(&rule->node);
write_unlock(&whitelist_lock);
kfree(rule);
atomic_dec(&kb_rule_cnt);
break;
return count;
}
}
write_unlock_bh(&whitelist_lock);
write_unlock(&whitelist_lock);
return -ESRCH;
} else {
return -EINVAL;
}
@ -127,7 +137,7 @@ static ssize_t whitelist_write(struct file *file, const char __user *ubuf,
static void *whitelist_seq_start(struct seq_file *m, loff_t *pos)
{
read_lock_bh(&whitelist_lock);
read_lock(&whitelist_lock);
return seq_list_start_head(&whitelist_list, *pos);
}
@ -138,7 +148,7 @@ static void *whitelist_seq_next(struct seq_file *m, void *v, loff_t *pos)
static void whitelist_seq_stop(struct seq_file *m, void *v)
{
read_unlock_bh(&whitelist_lock);
read_unlock(&whitelist_lock);
}
static int whitelist_seq_show(struct seq_file *m, void *v)
@ -185,18 +195,6 @@ static int stat_proc_show(struct seq_file *m, void *v)
return 0;
}
static int stat_proc_open(struct inode *inode, struct file *file)
{
return single_open(file, stat_proc_show, NULL);
}
static const struct proc_ops stat_fops = {
.proc_open = stat_proc_open,
.proc_read = seq_read,
.proc_lseek = seq_lseek,
.proc_release = single_release,
};
/* get the length of podid, not include '\0' */
static unsigned int kill_block_get_podid_len(char *podid_start)
{
@ -215,19 +213,17 @@ static unsigned int kill_block_get_podid_len(char *podid_start)
return podid_len;
}
int kill_block_whitelist_match(struct task_struct *p, int sig,
bool kill_block_whitelist_match(struct task_struct *p, int sig,
char *src_cgrp_path, char *src_cgrp_name,
char *dst_cgrp_path, char *dst_cgrp_name)
{
struct kb_whitelist_rule *rule;
char *src_podid_start, *dst_podid_start;
unsigned int src_podid_len, dst_podid_len;
int match = 1;
bool match = true;
if (!sysctl_sig_kill_block) {
match = 0;
goto out;
}
if (sysctl_sig_kill_block == 0)
return false;
/* check whether the src and dst cgrp are pods */
if (glob_match("*kubepods*", src_cgrp_path) &&
@ -246,13 +242,13 @@ int kill_block_whitelist_match(struct task_struct *p, int sig,
/* src and dst are in a same pod */
if (!strncmp(src_podid_start, dst_podid_start, src_podid_len)) {
match = 0;
match = false;
goto out;
}
}
check_rule:
read_lock_bh(&whitelist_lock);
read_lock(&whitelist_lock);
if (list_empty(&whitelist_list))
goto out_unlock;
@ -261,12 +257,12 @@ check_rule:
glob_match(rule->dst_comm, p->comm) &&
(glob_match(rule->dst_cgrp, dst_cgrp_name) ||
glob_match(rule->dst_cgrp, dst_cgrp_path))) {
match = 0;
match = false;
break;
}
}
out_unlock:
read_unlock_bh(&whitelist_lock);
read_unlock(&whitelist_lock);
out:
if (match) {
if (glob_match("*kubepods*", dst_cgrp_path))
@ -295,7 +291,7 @@ static int kill_block_hook_func(int sig, struct kernel_siginfo *info, struct tas
char src_cgrp_name[KILL_BLOCK_CGRP_NAME_LEN];
char dst_cgrp_name[KILL_BLOCK_CGRP_NAME_LEN];
int ret = 0;
int block = 0;
bool block = false;
if (sig != SIGKILL && sig != SIGTERM)
return 0;
@ -330,16 +326,18 @@ static int register_kill_block_hook(void)
static void unregister_kill_block_hook(void)
{
unregister_kill_hook(&kill_block_hook);
(void)unregister_kill_hook(&kill_block_hook);
}
static struct ctl_table kb_sysctl_table[] = {
{
.procname = "sig_kill_block",
.data = &sysctl_sig_kill_block,
.maxlen = sizeof(int),
.maxlen = sizeof(unsigned int),
.mode = 0644,
.proc_handler = proc_dointvec_minmax,
.proc_handler = proc_douintvec_minmax,
.extra1 = SYSCTL_ZERO,
.extra2 = &two,
},
{ }
};
@ -367,7 +365,7 @@ static int __init kill_block_mod_init(void)
goto out_entry;
}
stat_entry = proc_create("stat", 0, kb_proc_dir, &stat_fops);
stat_entry = proc_create_single("stat", 0644, kb_proc_dir, stat_proc_show);
if (!stat_entry) {
pr_err("Couldn't create stat proc entry\n");
goto out_entry;
@ -397,12 +395,12 @@ static void __exit kill_block_mod_exit(void)
unregister_kill_block_hook();
remove_proc_subtree(KILL_BLOCK_DIR, NULL);
write_lock_bh(&whitelist_lock);
write_lock(&whitelist_lock);
list_for_each_entry_safe(rule, tmp, &whitelist_list, node) {
list_del(&rule->node);
kfree(rule);
}
write_unlock_bh(&whitelist_lock);
write_unlock(&whitelist_lock);
unregister_sysctl_table(kb_sysctl_header);
pr_info("signal kill block module exit\n");

View File

@ -1,21 +0,0 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef _LINUX_KILL_BLOCK_H
#define _LINUX_KILL_BLOCK_H
#include <linux/sched.h>
#define KILL_BLOCK_DIR "kill_block"
#define KILL_BLOCK_CMD_LEN 128
#define KILL_BLOCK_CGRP_LEN 64
#define KILL_BLOCK_RULES_MAX_CNT 1024
struct kb_whitelist_rule {
struct list_head node;
char src_comm[TASK_COMM_LEN];
char dst_comm[TASK_COMM_LEN];
char dst_cgrp[KILL_BLOCK_CGRP_LEN];
};
extern int sysctl_sig_kill_block;
#endif /*_LINUX_KILL_BLOCK_H*/