This is the mail archive of the systemtap@sourceware.org mailing list for the systemtap project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH] Fix bug of signal.stp


Hi, all
	There are some problems with si_code in signal.send and signal.checkperm.

	First, test a pointer whether it's negative does not make any sense.
So the si_code can not be correct.

-----old code--------
    if (sinfo == 2)
        si_code ="SIGSTOP or SIGKILL"
    else if (sinfo > 0)
        si_code="SI_KERNEL (SIGFPE, SIGSEGV, SIGTRAP, SIGCHLD, SIGPOLL)"
    else if (sinfo <= 0)
        si_code="SI_USER or SI_TIMER or SI_ASYNCIO"
---------------------

	Second, si_code should be the value of info->si_code. If not,
it will make user confused.

	In my patch, 2 variables are added and another one modified:
si_code is the value of info->si_code, indicates why this signal was sent.
si_code_name is a string representation of the si_code.
sig_type is new name for old si_code, indicates the signal type.

	and 2 functions are added:
__get_sigqueue_info - get addr of info from struct sigqueue
signal_si_code_name - figure out si_code_name from sig and si_code

Patch:

Signed-off-by: Lai Jiangshan <laijs@cn.fujitsu.com>

--- systemtap-20071110/tapset/signal.stp	2007-09-26 10:10:43.000000000 +0800
+++ tapset/signal.stp	2007-11-12 07:00:35.000000000 +0800
@@ -27,7 +27,9 @@
  *  sig_name - a string representation of the signal
  *  sig_pid - pid of the signal recipient process
  *  pid_name - name of the signal recipient process
- *  si_code - indicates the signal type.
+ *  si_code - indicates why this signal was sent. See sigaction(2).
+ *  si_code_name - a string representation of the si_code.
+ *  sig_type - indicates the signal type.
  *  task - a task handle to the signal recipient
  *  sinfo - the address of siginfo struct.
  *  shared - indicates whether this signal is shared by the thread group
@@ -40,13 +42,15 @@ probe signal.send = _signal.send.*
     sig_name = _signal_name($sig)
     sig_pid = task_pid(task)
     pid_name = task_execname(task)
+    si_code_name = signal_si_code_name(sig, si_code)
 
     if (sinfo == 2)
-        si_code ="SIGSTOP or SIGKILL"
-    else if (sinfo > 0)
-        si_code="SI_KERNEL (SIGFPE, SIGSEGV, SIGTRAP, SIGCHLD, SIGPOLL)"
-    else if (sinfo <= 0)
-        si_code="SI_USER or SI_TIMER or SI_ASYNCIO"
+        sig_type = "SIGSTOP or SIGKILL"
+    else if (si_code > 0)
+        sig_type = "SI_KERNEL (SIGILL, SIGFPE, SIGSEGV, SIGBUS, SIGTRAP, SIGCHLD, SIGPOLL)"
+    else if (si_code <= 0)
+        sig_type = si_code_name # SI_USER, SI_QUEUE, SI_TIMER, SI_MESGQ,
+                                # SI_ASYNCIO, SI_SIGIO, SI_TKILL, SI_DETHREAD
 }
 
 probe _signal.send.part1 = kernel.function("__group_send_sig_info")
@@ -54,6 +58,12 @@ probe _signal.send.part1 = kernel.functi
     name = "__group_send_sig_info"
     task = $p
     sinfo = $info
+    if (sinfo == 1)      # SEND_SIG_PRIV, when signal is delivered, si_code is
+        si_code = 0x80   # SI_KERNEL
+    else if (sinfo == 2) # SEND_SIG_FORCED, when signal is delivered, si_code is
+        si_code = 0      # SI_USER, but signo is SIGSTOP or SIGKILL
+    else
+        si_code = $info->si_code
     shared = 1
     send2queue = 0
 }
@@ -62,7 +72,8 @@ probe _signal.send.part2 = kernel.functi
 {
     name = "send_group_sigqueue"
     task = $p
-    # sinfo = $q->info
+    sinfo = __get_sigqueue_info($q)
+    si_code = $q->info->si_code
     shared = 1
     send2queue = 1
 }
@@ -71,7 +82,8 @@ probe _signal.send.part3 = kernel.functi
 {
     name = "send_sigqueue"
     task = $p
-    # sinfo = $q->info
+    sinfo = __get_sigqueue_info($q)
+    si_code = $q->info->si_code
     shared = 0
     send2queue = 1
 }
@@ -81,10 +93,21 @@ probe _signal.send.part4 = kernel.functi
     name = "specific_send_sig_info"
     task = $t
     sinfo = $info
+    if (sinfo == 1)      # SEND_SIG_PRIV, when signal is delivered, si_code is
+        si_code = 0x80   # SI_KERNEL
+    else if (sinfo == 2) # SEND_SIG_FORCED, when signal is delivered, si_code is
+        si_code = 0      # SI_USER, but signo is SIGSTOP or SIGKILL
+    else
+        si_code = $info->si_code
     shared = 0
     send2queue = 0
 }
 
+function __get_sigqueue_info:long(q:long) %{
+    struct sigqueue *q = (struct sigqueue *)((long)THIS->q);
+    THIS->__retvalue = (uint64_t)(&q->info);
+%}
+
 /* probe signal.send.return
  */
 probe signal.send.return = _signal.send.*.return
@@ -170,12 +193,21 @@ probe signal.checkperm = kernel.function
     sig_pid = task_pid(task)
     pid_name = task_execname(task)
 
+    if (sinfo == 1)      # SEND_SIG_PRIV, when signal is delivered, si_code is
+        si_code = 0x80   # SI_KERNEL
+    else if (sinfo == 2) # SEND_SIG_FORCED, when signal is delivered, si_code is
+        si_code = 0      # SI_USER, but signo is SIGSTOP or SIGKILL
+    else
+        si_code = $info->si_code
+    si_code_name = signal_si_code_name(sig, si_code)
+
     if (sinfo == 2)
-        si_code ="SIGSTOP or SIGKILL"
-    else if (sinfo > 0)
-        si_code="SI_KERNEL (SIGFPE, SIGSEGV, SIGTRAP, SIGCHLD, SIGPOLL)"
-    else if (sinfo <= 0)
-        si_code="SI_USER or SI_TIMER or SI_ASYNCIO"
+        sig_type = "SIGSTOP or SIGKILL"
+    else if (si_code > 0)
+        sig_type = "SI_KERNEL (SIGILL, SIGFPE, SIGSEGV, SIGBUS, SIGTRAP, SIGCHLD, SIGPOLL)"
+    else if (si_code <= 0)
+        sig_type = si_code_name # SI_USER, SI_QUEUE, SI_TIMER, SI_MESGQ,
+                                # SI_ASYNCIO, SI_SIGIO, SI_TKILL, SI_DETHREAD
 }  
 
 probe signal.checkperm.return = kernel.function("check_kill_permission").return
@@ -493,3 +525,105 @@ probe signal.flush = kernel.function("fl
     sig_pid = $t->pid
     pid_name = kernel_string($t->comm)
 } 
+
+function signal_si_code_name:string(sig:long, si_code:long)
+%{ /* pure */
+	int sig = (int)THIS->sig;
+	int si_code = (int)THIS->si_code;
+	const char *si_code_name = NULL;
+	switch(si_code) {
+	case SI_USER:    si_code_name = "SI_USER"; break;
+	case SI_KERNEL:  si_code_name = "SI_KERNEL"; break;
+	case SI_QUEUE:   si_code_name = "SI_QUEUE"; break;
+	case SI_TIMER:   si_code_name = "SI_TIMER"; break;
+	case SI_MESGQ:   si_code_name = "SI_MESGQ"; break;
+	case SI_ASYNCIO: si_code_name = "SI_ASYNCIO"; break;
+	case SI_SIGIO:   si_code_name = "SI_SIGIO"; break;
+	case SI_TKILL:   si_code_name = "SI_TKILL"; break;
+	case SI_DETHREAD:si_code_name = "SI_DETHREAD"; break;
+	default:break;
+	}
+	if (si_code_name != NULL) {
+		strlcpy (THIS->__retvalue, si_code_name, MAXSTRINGLEN);
+		return;
+	}
+	switch(sig) {
+	default:break;
+	case SIGILL:
+		switch(si_code){
+		case ILL_ILLOPC:si_code_name = "ILL_ILLOPC"; break;
+		case ILL_ILLOPN:si_code_name = "ILL_ILLOPN"; break;
+		case ILL_ILLADR:si_code_name = "ILL_ILLADR"; break;
+		case ILL_ILLTRP:si_code_name = "ILL_ILLTRP"; break;
+		case ILL_PRVOPC:si_code_name = "ILL_PRVOPC"; break;
+		case ILL_PRVREG:si_code_name = "ILL_PRVREG"; break;
+		case ILL_COPROC:si_code_name = "ILL_COPROC"; break;
+		case ILL_BADSTK:si_code_name = "ILL_BADSTK"; break;
+		default:break;
+		}
+		break;
+	case SIGFPE:
+		switch(si_code){
+		case FPE_INTDIV:si_code_name = "FPE_INTDIV"; break;
+		case FPE_INTOVF:si_code_name = "FPE_INTOVF"; break;
+		case FPE_FLTDIV:si_code_name = "FPE_FLTDIV"; break;
+		case FPE_FLTOVF:si_code_name = "FPE_FLTOVF"; break;
+		case FPE_FLTUND:si_code_name = "FPE_FLTUND"; break;
+		case FPE_FLTRES:si_code_name = "FPE_FLTRES"; break;
+		case FPE_FLTINV:si_code_name = "FPE_FLTINV"; break;
+		case FPE_FLTSUB:si_code_name = "FPE_FLTSUB"; break;
+		default:break;
+		}
+		break;
+	case SIGSEGV:
+		switch(si_code){
+		case SEGV_MAPERR:si_code_name = "SEGV_MAPERR"; break;
+		case SEGV_ACCERR:si_code_name = "SEGV_ACCERR"; break;
+		default:break;
+		}
+		break;
+	case SIGBUS:
+		switch(si_code){
+		case BUS_ADRALN:si_code_name = "BUS_ADRALN"; break;
+		case BUS_ADRERR:si_code_name = "BUS_ADRERR"; break;
+		case BUS_OBJERR:si_code_name = "BUS_OBJERR"; break;
+		default:break;
+		}
+		break;
+	case SIGTRAP:
+		switch(si_code){
+		case TRAP_BRKPT:si_code_name = "TRAP_BRKPT"; break;
+		case TRAP_TRACE:si_code_name = "TRAP_TRACE"; break;
+		default:break;
+		}
+		break;
+	case SIGCHLD:
+		switch(si_code){
+		case CLD_EXITED   :si_code_name = "CLD_EXITED"; break;
+		case CLD_KILLED   :si_code_name = "CLD_KILLED"; break;
+		case CLD_DUMPED   :si_code_name = "CLD_DUMPED"; break;
+		case CLD_TRAPPED  :si_code_name = "CLD_TRAPPED"; break;
+		case CLD_STOPPED  :si_code_name = "CLD_STOPPED"; break;
+		case CLD_CONTINUED:si_code_name = "CLD_CONTINUED"; break;
+		default:break;
+		}
+		break;
+	case SIGPOLL:
+		switch(si_code){
+		case POLL_IN :si_code_name = "POLL_IN "; break;
+		case POLL_OUT:si_code_name = "POLL_OUT"; break;
+		case POLL_MSG:si_code_name = "POLL_MSG"; break;
+		case POLL_ERR:si_code_name = "POLL_ERR"; break;
+		case POLL_PRI:si_code_name = "POLL_PRI"; break;
+		case POLL_HUP:si_code_name = "POLL_HUP"; break;
+		default:break;
+		}
+		break;
+	}
+	if (si_code_name != NULL) {
+		strlcpy (THIS->__retvalue, si_code_name, MAXSTRINGLEN);
+	} else {
+		strlcpy (THIS->__retvalue, "UNKNOWN", MAXSTRINGLEN);
+	}
+%}
+


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]