Signal tracking under linux: Jprobe? Signal

Problem Description: in linux environment, sometimes the process exits abnormally. At this time, strace can be used to track the running of the process. If it is an internal error of the process, the strace log can see the abnormal error points of the process. But if it is killed by another person or process, only the killed information can be seen in strace log: "+ + + killed by SIGKILL + + +". In order to find the "killer" process, we need to track the semaphore and find out who sent the semaphore to the target process.

/*jprobe_signal.c, based on jprobe, registers the hook function. At the place where the signal is sent, print the process of sending the signal, the amount of signal sent, and the target process of signal receiving as required.

*/

#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/kprobes.h>
#include <linux/sched.h>

static int g_pid=0; //-1=all process
static int g_sig=9; //SIGKILL, 0=all signal 
module_param_named(pid,g_pid,int,S_IRUGO|S_IWUSR);
module_param_named(signal,g_sig,int,S_IRUGO|S_IWUSR);
MODULE_PARM_DESC(pid, "The specified process PID,-1 Reprensent all processes. 0 Represent no processes be traced. default is 0");
MODULE_PARM_DESC(signal, "The signal that needs to be tracked,0 represent all signal. default is 9");

static int jsend_signal(int sig,struct siginfo *info,struct task_struct *t,int group)
{
        struct task_struct *parent=NULL;
        int prev_pid=0;
        if(((g_pid < 0) ||(t->pid==g_pid))&&((g_sig==0)||(sig==g_sig))){
                printk(KERN_INFO "jprobe_signal:PID %d name:%s send SIG %d to PID=%d,name=%s\n",current->pid,current->comm,sig,t->pid,t->comm);
                parent=current->parent;
                prev_pid=current->pid;
                while(parent&&(parent->pid >= 1)){
                        printk(KERN_INFO"jprobe_signal:PID %d create by Parent Pid:%d,name:%s\n",prev_pid,parent->pid,parent->comm);
                        prev_pid=parent->pid;
                        parent=parent->parent;
                }
        }
        /* Always end with a call to jprobe_return(). */
        jprobe_return();
        return 0;
}
static struct jprobe my_jprobe = {
        .entry                  = jsend_signal,
        .kp = {
                .symbol_name    = "send_signal",
        },
};

static int __init jprobe_init(void)
{
        int ret;

        ret = register_jprobe(&my_jprobe);
        if (ret < 0) {
                printk(KERN_INFO "register_jprobe failed, returned %d\n", ret);
                return -1;
        }
        printk(KERN_INFO "Planted jprobe at %p, handler addr %p\n",
               my_jprobe.kp.addr, my_jprobe.entry);
        return 0;
}

static void __exit jprobe_exit(void)
{
        unregister_jprobe(&my_jprobe);
        printk(KERN_INFO "jprobe at %p unregistered\n", my_jprobe.kp.addr);
}

module_init(jprobe_init)
module_exit(jprobe_exit)
MODULE_LICENSE("Dual BSD/GPL");

Makefile file:

ifneq ($(KERNELRELEASE),)
        obj-m := jprobe_signal.o
else
  KERNELDIR ?=/usr/src/$(shell uname -r)/
  PWD := $(shell pwd)
default:   
    $(MAKE) -C $(KERNELDIR) M=$(PWD) modules   
endif

.PHONY: clean
clean:   
    -rm -rf *.mod.c *.o *.order *.sym .j* .tmp*

 

Tags: Linux shell Makefile

Posted on Sun, 09 Feb 2020 10:18:43 -0800 by fr0mat