6 #include <linux/types.h>
8 #include <sys/syscall.h>
12 #include "linux/ptrace.h"
14 static int sys_rt_sigqueueinfo(pid_t tgid
, int sig
, siginfo_t
*uinfo
)
16 return syscall(SYS_rt_sigqueueinfo
, tgid
, sig
, uinfo
);
19 static int sys_rt_tgsigqueueinfo(pid_t tgid
, pid_t tid
,
20 int sig
, siginfo_t
*uinfo
)
22 return syscall(SYS_rt_tgsigqueueinfo
, tgid
, tid
, sig
, uinfo
);
25 static int sys_ptrace(int request
, pid_t pid
, void *addr
, void *data
)
27 return syscall(SYS_ptrace
, request
, pid
, addr
, data
);
31 #define TEST_SICODE_PRIV -1
32 #define TEST_SICODE_SHARE -2
35 #define PAGE_SIZE sysconf(_SC_PAGESIZE)
38 #define err(fmt, ...) \
40 "Error (%s:%d): " fmt, \
41 __FILE__, __LINE__, ##__VA_ARGS__)
43 static int check_error_paths(pid_t child
)
45 struct ptrace_peeksiginfo_args arg
;
46 int ret
, exit_code
= -1;
47 void *addr_rw
, *addr_ro
;
50 * Allocate two contiguous pages. The first one is for read-write,
51 * another is for read-only.
53 addr_rw
= mmap(NULL
, 2 * PAGE_SIZE
, PROT_READ
| PROT_WRITE
,
54 MAP_PRIVATE
| MAP_ANONYMOUS
, -1, 0);
55 if (addr_rw
== MAP_FAILED
) {
56 err("mmap() failed: %m\n");
60 addr_ro
= mmap(addr_rw
+ PAGE_SIZE
, PAGE_SIZE
, PROT_READ
,
61 MAP_PRIVATE
| MAP_ANONYMOUS
| MAP_FIXED
, -1, 0);
62 if (addr_ro
== MAP_FAILED
) {
63 err("mmap() failed: %m\n");
70 /* Unsupported flags */
72 ret
= sys_ptrace(PTRACE_PEEKSIGINFO
, child
, &arg
, addr_rw
);
73 if (ret
!= -1 || errno
!= EINVAL
) {
74 err("sys_ptrace() returns %d (expected -1),"
75 " errno %d (expected %d): %m\n",
81 /* A part of the buffer is read-only */
82 ret
= sys_ptrace(PTRACE_PEEKSIGINFO
, child
, &arg
,
83 addr_ro
- sizeof(siginfo_t
) * 2);
85 err("sys_ptrace() returns %d (expected 2): %m\n", ret
);
89 /* Read-only buffer */
90 ret
= sys_ptrace(PTRACE_PEEKSIGINFO
, child
, &arg
, addr_ro
);
91 if (ret
!= -1 && errno
!= EFAULT
) {
92 err("sys_ptrace() returns %d (expected -1),"
93 " errno %d (expected %d): %m\n",
100 munmap(addr_rw
, 2 * PAGE_SIZE
);
104 int check_direct_path(pid_t child
, int shared
, int nr
)
106 struct ptrace_peeksiginfo_args arg
= {.flags
= 0, .nr
= nr
, .off
= 0};
107 int i
, j
, ret
, exit_code
= -1;
108 siginfo_t siginfo
[SIGNR
];
112 arg
.flags
= PTRACE_PEEKSIGINFO_SHARED
;
113 si_code
= TEST_SICODE_SHARE
;
116 si_code
= TEST_SICODE_PRIV
;
119 for (i
= 0; i
< SIGNR
; ) {
121 ret
= sys_ptrace(PTRACE_PEEKSIGINFO
, child
, &arg
, siginfo
);
123 err("ptrace() failed: %m\n");
130 for (j
= 0; j
< ret
; j
++, i
++) {
131 if (siginfo
[j
].si_code
== si_code
&&
132 siginfo
[j
].si_int
== i
)
135 err("%d: Wrong siginfo i=%d si_code=%d si_int=%d\n",
136 shared
, i
, siginfo
[j
].si_code
, siginfo
[j
].si_int
);
142 err("Only %d signals were read\n", i
);
151 int main(int argc
, char *argv
[])
153 siginfo_t siginfo
[SIGNR
];
154 int i
, exit_code
= 1;
158 sigemptyset(&blockmask
);
159 sigaddset(&blockmask
, SIGRTMIN
);
160 sigprocmask(SIG_BLOCK
, &blockmask
, NULL
);
164 err("fork() failed: %m");
166 } else if (child
== 0) {
167 pid_t ppid
= getppid();
169 if (ppid
!= getppid())
176 /* Send signals in process-wide and per-thread queues */
177 for (i
= 0; i
< SIGNR
; i
++) {
178 siginfo
->si_code
= TEST_SICODE_SHARE
;
180 sys_rt_sigqueueinfo(child
, SIGRTMIN
, siginfo
);
182 siginfo
->si_code
= TEST_SICODE_PRIV
;
184 sys_rt_tgsigqueueinfo(child
, child
, SIGRTMIN
, siginfo
);
187 if (sys_ptrace(PTRACE_ATTACH
, child
, NULL
, NULL
) == -1)
190 waitpid(child
, NULL
, 0);
192 /* Dump signals one by one*/
193 if (check_direct_path(child
, 0, 1))
195 /* Dump all signals for one call */
196 if (check_direct_path(child
, 0, SIGNR
))
200 * Dump signal from the process-wide queue.
201 * The number of signals is not multible to the buffer size
203 if (check_direct_path(child
, 1, 3))
206 if (check_error_paths(child
))
212 if (sys_ptrace(PTRACE_KILL
, child
, NULL
, NULL
) == -1)
215 waitpid(child
, NULL
, 0);