Following program generates SIGSEGV from within SIGUSR1 signal handler.
#include <signal.h>
#include <unistd.h>
#include <iostream>
void sigusr_handler(int sig_number)
{
std::cout << "hallo" << "\n";
char *a = (char*)0x0;
char b = *a;
std::cout << b << "\n";
}
struct sigaction my_action;
int main(int argc, char *argv[])
{
my_action.sa_handler = sigusr_handler;
sigaction(SIGUSR1, &my_action, nullptr);
sleep(1000);
return 0;
}
Let's run program in gdb then send SIGUSR1 to the program.
siginfo looks like following
(gdb) p $_siginfo
$8 = {
si_signo = 11,
si_errno = 0,
si_code = 1,
_sifields = {
_pad = {0, 0, -1814214640, 21880, -1601342336, 32766, -1848922720, 21880, -1811928400, 21880, 0, 0, -1811928400, 21880, 176, 0, -1840786848, 21880, -1847783957, 21880, -1811928400, 21880, -1840786848, 21880, -1814214640, 21880, -1845891081, 21880},
_kill = {
si_pid = 0,
si_uid = 0
},
_timer = {
si_tid = 0,
si_overrun = 0,
si_sigval = {
sival_int = -1814214640,
sival_ptr = 0x557893dd4810
}
},
_rt = {
si_pid = 0,
si_uid = 0,
si_sigval = {
sival_int = -1814214640,
sival_ptr = 0x557893dd4810
}
},
_sigchld = {
si_pid = 0,
si_uid = 0,
si_status = -1814214640,
si_utime = -6877712962820221576,
si_stime = -7941062615231332354
},
_sigfault = {
si_addr = 0x0,
_addr_lsb = 93976365189136,
_addr_bnd = {
_lower = 0x7ffea08d7480,
_upper = 0x557891cbada0
}
},
_sigpoll = {
si_band = 0,
si_fd = -1814214640
}
}
}
Question: is it possible to "guess" from gdb session, that outer signal was SIGUSR1?
regards,
Mat
NOTE TO STACKOVEFLOW: I have no idea what usefull notes I need to add to the above in order to have the question more usefull - IMO: more text makes the question blurred, but I'm adding some notes because I'm getting information:
"It looks like your post is mostly code; please add some more details" otherwise.
READERS OF POST: PLEASE FORGIVE ME.
END OF NOTE TO STACKOVERFLOW
is it possible to "guess" from gdb session, that outer signal was SIGUSR1
Yes:
hallo
Program received signal SIGSEGV, Segmentation fault.
0x00005555555551be in sigusr_handler (sig_number=10) at t.c:9
9 char b = *a;
(gdb) bt
#0 0x00005555555551be in sigusr_handler (sig_number=10) at t.c:9
#1 <signal handler called>
#2 0x00007ffff775cff4 in __GI___nanosleep (requested_time=requested_time#entry=0x7fffffffdb70, remaining=remaining#entry=0x7fffffffdb70)
at ../sysdeps/unix/sysv/linux/nanosleep.c:28
#3 0x00007ffff775cf2a in __sleep (seconds=0) at ../sysdeps/posix/sleep.c:55
#4 0x0000555555555225 in main (argc=1, argv=0x7fffffffdca8) at t.c:20
From this, you can clearly see that the program received SIGSEGV while in the handler for signal 10, which is SIGUSR1.
P.S. It's unclear how this question even arises: GDB should have earlier stopped and told you that SIGUSR1 was received, like so:
Program received signal SIGUSR1, User defined signal 1.
0x00007ffff775cff4 in __GI___nanosleep (requested_time=requested_time#entry=0x7fffffffdb70, remaining=remaining#entry=0x7fffffffdb70) at ../sysdeps/unix/sysv/linux/nanosleep.c:28
28 ../sysdeps/unix/sysv/linux/nanosleep.c: No such file or directory.
Related
I want to insert a timestamp into the packets I receive in my XDP program. The only way I know how to get a timestamp is by calling bpf_ktime_get_ns.
But what would be the user-space equivalent function which creates comparable timestamps? As far as I know, ktime_get_ns returns the time since system start (in nanoseconds). There is
$ uptime
11:45:35 up 2 days, 3:15, 3 users, load average: 0.19, 0.29, 0.27
but this only returns the time since system start in seconds. So no precise measurement possible here (microsecond-level would be nice).
Edit: It was purely my fault. #Qeole and #tuilagio are completely right. I made a mistake in pointer arithmetic in my user space code where I was obtaining the pointer of the timestamp.
You can use clock_gettime() :
static unsigned long get_nsecs(void)
{
struct timespec ts;
clock_gettime(CLOCK_MONOTONIC, &ts);
return ts.tv_sec * 1000000000UL + ts.tv_nsec;
}
and call it with unsigned long now = get_nsecs(); or uint64_t now = get_nsecs();
This return timestamp in nsec resolution.
Source: https://github.com/torvalds/linux/blob/master/samples/bpf/xdpsock_user.c#L114
This is probably not the canonical way to do this, but at least it's fun: We can retrieve the kernel timestamp... from BPF itself!
BPF subsystem has a “test-run” feature that allows to test some types for programs with user-provided data, the run being triggered with a bpf() system call. Here is a sample application doing just so:
It loads a BPF program (XDP, but type does not matter much) and gets a FD.
It reuses the FD for triggering a “test-run” of that BPF program.
When it runs, the program calls bpf_ktime_get_ns(), copies the value to the data output buffer (data_out), and we just have to read that to get the timestamp.
#define _GNU_SOURCE
#include <errno.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/syscall.h>
#include <unistd.h>
#include <linux/bpf.h>
int main(__attribute__((unused))int argc,
__attribute__((unused))char **argv)
{
union bpf_attr load_attr = { }, run_attr = { };
const struct bpf_insn insns[] = {
/* w0 = 1 | r0 = XDP_DROP */
{ .code = 0xb4, .src_reg = 0, .dst_reg = 0, .off = 0, .imm = 1, },
/* r2 = *(u32 *)(r1 + 4) | r2 = ctx->data_end */
{ .code = 0x61, .src_reg = 1, .dst_reg = 2, .off = 4, .imm = 0, },
/* r6 = *(u32 *)(r1 + 0) | r6 = ctx->data */
{ .code = 0x61, .src_reg = 1, .dst_reg = 6, .off = 0, .imm = 0, },
/* r1 = r6 | r1 = ctx->data */
{ .code = 0xbf, .src_reg = 6, .dst_reg = 1, .off = 0, .imm = 0, },
/* r1 += 8 | r1 += sizeof(uint64_t) */
{ .code = 0x07, .src_reg = 0, .dst_reg = 1, .off = 0, .imm = 8, },
/* if r1 > r2 goto +3 | if (data + 8 > data_end) return */
{ .code = 0x2d, .src_reg = 2, .dst_reg = 1, .off = 3, .imm = 0, },
/* call bpf_ktime_get_ns() */
{ .code = 0x85, .src_reg = 0, .dst_reg = 0, .off = 0, .imm = BPF_FUNC_ktime_get_ns, },
/* *(u64 *)(r6 + 0) = r0 | *(ctx->data) = bpf_ktime_get_ns() */
{ .code = 0x7b, .src_reg = 0, .dst_reg = 6, .off = 0, .imm = 0, },
/* w0 = 2 | r0 = XDP_PASS */
{ .code = 0xb4, .src_reg = 0, .dst_reg = 0, .off = 0, .imm = 2, },
/* exit | return r0 */
{ .code = 0x95, .src_reg = 0, .dst_reg = 0, .off = 0, .imm = 0, },
};
const char license[] = "GPL"; /* required for bpf_ktime_get_ns() */
/*
* Data buffers data_in/data_out must be at least the minimal size for
* an Ethernet frame: 14 header bytes
*/
const uint8_t data_out[14];
const uint8_t data_in[14];
int fd, res;
/* Load program */
load_attr.prog_type = BPF_PROG_TYPE_XDP;
load_attr.insn_cnt = sizeof(insns) / sizeof(insns[0]);
load_attr.insns = (uint64_t)insns;
load_attr.license = (uint64_t)license;
fd = syscall(__NR_bpf, BPF_PROG_LOAD, &load_attr, sizeof(load_attr));
if (fd < 0) {
fprintf(stderr, "failed to load BPF program: %s\n",
strerror(errno));
return EXIT_FAILURE;
}
/* Run program */
run_attr.test.prog_fd = fd;
run_attr.test.data_size_in = sizeof(data_in);
run_attr.test.data_size_out = sizeof(data_out);
run_attr.test.data_in = (uint64_t)data_in;
run_attr.test.data_out = (uint64_t)data_out;
res = syscall(__NR_bpf, BPF_PROG_TEST_RUN, &run_attr, sizeof(run_attr));
if (res) {
fprintf(stderr, "failed to run BPF program: %s\n",
strerror(errno));
close(fd);
return EXIT_FAILURE;
}
/* Extract result */
fprintf(stdout, "%lu\n", (uint64_t)run_attr.test.data_out);
close(fd);
return EXIT_SUCCESS;
}
Note that we could also extract data from the return value of the program (run_attr.test.retval), but this is a 32-bit integer so you would not get the full timestamp. This could be used to retrieve e.g. only the number of the seconds for that timestamp, with a right shift r0 >>= 32, to avoid doing data/data_end length check and copying to data_out. Not that it should change much in performance.
Running the whole application (load + run) will obviously take longer than subsequent runs, because of the verification step done in the kernel when loading the program.
Addendum: The BPF program was generated from the following code:
#include <linux/bpf.h>
static unsigned long long (*bpf_ktime_get_ns)(void) =
(void *)BPF_FUNC_ktime_get_ns;
int xdp(struct xdp_md *ctx)
{
void *data_end = (void *) (long) ctx->data_end;
void *data = (void *) (long) ctx->data;
if (data + sizeof(unsigned long long) > data_end)
return XDP_DROP;
*(unsigned long long *)data = bpf_ktime_get_ns();
return XDP_PASS;
}
Since my last system upgrade on Gentoo, I'm not able to run some code of mine: window_management.c which was working without any warnings nor errors before the upgrade.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <X11/X.h>
#include <X11/Xatom.h>
#include <X11/Xlib.h>
#include <X11/XKBlib.h>
#include "common.h"
#include "extensions.h"
#include "text_pointer.h"
#include "window_management.h"
static void (*cursor_position_callback)(int xpos, int ypos) = 0;
void (*mouse_button_callback)(int xpos, int ypos, int button, int action) = 0;
#ifdef DSTUDIO_RELY_ON_X11
#define DSTUDIO_X11_INPUT_MASKS \
ExposureMask | \
KeyPressMask | \
KeyReleaseMask | \
ButtonPressMask | \
ButtonReleaseMask | \
VisibilityChangeMask
#define GLX_CONTEXT_MAJOR_VERSION_ARB 0x2091
#define GLX_CONTEXT_MINOR_VERSION_ARB 0x2092
typedef GLXContext (*glXCreateContextAttribsARBProc)(Display*, GLXFBConfig, GLXContext, Bool, const int*);
static int ctx_error_occurred = 0;
static int window_alive = 1;
static int refresh_all = 1;
static Display *display = NULL;
static Window window;
static XVisualInfo * visual_info;
static Colormap color_map;
static XEvent x_event;
static XEvent x_sent_expose_event;
static GLXContext opengl_context;
static int visual_attribs[] = {
GLX_X_RENDERABLE , True,
GLX_DRAWABLE_TYPE , GLX_WINDOW_BIT,
GLX_RENDER_TYPE , GLX_RGBA_BIT,
GLX_X_VISUAL_TYPE , GLX_TRUE_COLOR,
GLX_RED_SIZE , 8,
GLX_GREEN_SIZE , 8,
GLX_BLUE_SIZE , 8,
GLX_ALPHA_SIZE , 8,
GLX_DEPTH_SIZE , 24,
GLX_STENCIL_SIZE , 8,
GLX_DOUBLEBUFFER , True,
None
};
static int glx_major, glx_minor;
static unsigned int keyboard_chars_map_mode = 0;
static int ctx_error_handler( Display *dpy, XErrorEvent *ev ) {
(void) dpy;
(void) ev;
ctx_error_occurred = 1;
return 0;
}
static void creating_color_map(XVisualInfo * vi, Window * root_window, XSetWindowAttributes * swa) {
color_map = XCreateColormap(display, *root_window, vi->visual, AllocNone);
swa->colormap = color_map;
swa->background_pixmap = None ;
swa->border_pixel = 0;
swa->event_mask = ExposureMask | StructureNotifyMask |PointerMotionMask;
}
void destroy_context() {
glXDestroyContext(display, opengl_context);
XDestroyWindow(display, window);
XCloseDisplay(display);
}
static void get_visual_info(GLXFBConfig * best_frame_buffer_config) {
int fbcount;
int best_frame_buffer_config_index = -1;
int worst_fbc = -1;
int best_num_samp = -1;
int worst_num_samp = 999;
GLXFBConfig * frame_buffer_config = glXChooseFBConfig(display, DefaultScreen(display), visual_attribs, &fbcount);
DSTUDIO_EXIT_IF_NULL(frame_buffer_config)
for (int i=0; i<fbcount; ++i) {
visual_info = glXGetVisualFromFBConfig( display, frame_buffer_config[i] );
if (visual_info) {
int samp_buf, samples;
glXGetFBConfigAttrib( display, frame_buffer_config[i], GLX_SAMPLE_BUFFERS, &samp_buf );
glXGetFBConfigAttrib( display, frame_buffer_config[i], GLX_SAMPLES , &samples );
#ifdef DSTUDIO_DEBUG
printf("Matching fbconfig %d, visual ID 0x%2lux: SAMPLE_BUFFERS = %d, SAMPLES = %d\n", i, visual_info->visualid, samp_buf, samples );
#endif
if ( best_frame_buffer_config_index < 0 || (samp_buf && samples > best_num_samp)) {
best_frame_buffer_config_index = i;
best_num_samp = samples;
}
if ( worst_fbc < 0 || !samp_buf || samples < worst_num_samp ) {
worst_fbc = i;
worst_num_samp = samples;
}
}
XFree(visual_info);
}
*best_frame_buffer_config = frame_buffer_config[ best_frame_buffer_config_index ];
XFree( frame_buffer_config );
// Get a visual
visual_info = glXGetVisualFromFBConfig( display, *best_frame_buffer_config );
#ifdef DSTUDIO_DEBUG
printf( "Chosen visual ID = 0x%lux\n", visual_info->visualid );
#endif
}
void init_context(const char * window_name, int width, int height) {
DSTUDIO_EXIT_IF_NULL(XInitThreads());
int (*old_handler)(Display*, XErrorEvent*) = XSetErrorHandler(&ctx_error_handler);
Window root_window;
XSetWindowAttributes swa;
XSizeHints * size_hints;
display = XOpenDisplay(NULL);
DSTUDIO_EXIT_IF_NULL(display)
DSTUDIO_EXIT_IF_NULL(glXQueryVersion( display, &glx_major, &glx_minor ))
DSTUDIO_EXIT_IF_FAILURE( glx_major == 1 && (glx_minor < 3))
DSTUDIO_EXIT_IF_FAILURE( glx_major < 1 )
GLXFBConfig best_frame_buffer_config;
get_visual_info(&best_frame_buffer_config);
DSTUDIO_EXIT_IF_NULL(visual_info)
root_window = RootWindow(display, visual_info->screen);
creating_color_map(visual_info, &root_window, &swa);
window = XCreateWindow(display, root_window, 0, 0, width, height, 0, visual_info->depth, InputOutput, visual_info->visual, CWBorderPixel|CWColormap|CWEventMask, &swa);
DSTUDIO_EXIT_IF_NULL(window)
size_hints = XAllocSizeHints();
size_hints->flags = PMinSize | PMaxSize;
size_hints->min_width = width;
size_hints->min_height = height;
size_hints->max_width = width;
size_hints->max_height = height;
XSetWMSizeHints(display, window, size_hints, XA_WM_NORMAL_HINTS);
Atom delWindow = XInternAtom(display, "WM_DELETE_WINDOW", 0);
XSetWMProtocols(display , window, &delWindow, 1);
XSelectInput(display, window, DSTUDIO_X11_INPUT_MASKS | ButtonMotionMask);
XkbSetDetectableAutoRepeat (display, 1, NULL);
XFree(visual_info);
XMapWindow(display, window);
XStoreName(display, window, window_name);
// Begin OpenGL context creation
const char *glx_exts = glXQueryExtensionsString(display, DefaultScreen( display ));
glXCreateContextAttribsARBProc glXCreateContextAttribsARB = 0;
glXCreateContextAttribsARB = (glXCreateContextAttribsARBProc) glXGetProcAddressARB( (const GLubyte *) "glXCreateContextAttribsARB" );
if ( !is_extension_supported( glx_exts, "GLX_ARB_create_context" ) || !glXCreateContextAttribsARB ) {
#ifdef DSTUDIO_DEBUG
printf("glXCreateContextAttribsARB() not found. Using old-style GLX context.\n");
#endif
opengl_context = glXCreateNewContext( display, best_frame_buffer_config, GLX_RGBA_TYPE, 0, 1);
}
else {
int context_attribs[] = {
GLX_CONTEXT_MAJOR_VERSION_ARB, 3,
GLX_CONTEXT_MINOR_VERSION_ARB, 3,
GLX_CONTEXT_PROFILE_MASK_ARB, GLX_CONTEXT_CORE_PROFILE_BIT_ARB,
//GLX_CONTEXT_FLAGS_ARB , GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB,
None
};
opengl_context = glXCreateContextAttribsARB(display, best_frame_buffer_config, 0, 1, context_attribs);
}
// Sync to ensure any errors generated are processed.
XSync(display, 0);
DSTUDIO_EXIT_IF_FAILURE( ctx_error_occurred && opengl_context == 0)
XSetErrorHandler(old_handler);
#ifdef DSTUDIO_DEBUG
if (!glXIsDirect(display, opengl_context)) {
printf("Indirect GLX rendering context obtained\n");
}
else {
printf("Direct GLX rendering context obtained\n");
}
#endif
glXMakeCurrent( display, window, opengl_context );
}
void send_expose_event() {
memset(&x_sent_expose_event, 0, sizeof(x_sent_expose_event));
x_sent_expose_event.xexpose.serial = clock();
x_sent_expose_event.type = Expose;
x_sent_expose_event.xexpose.send_event = 1;
x_sent_expose_event.xexpose.display = display;
XSendEvent(display, window, 1, ExposureMask, &x_sent_expose_event);
XFlush(display);
}
void swap_window_buffer() {
glXSwapBuffers(display, window);
}
#endif
My code crash when calling glXSwapBuffers() with the following output:
X Error of failed request: BadMatch (invalid parameter attributes)
Major opcode of failed request: 130 (MIT-SHM)
Minor opcode of failed request: 3 (X_ShmPutImage)
Serial number of failed request: 52
Current serial number in output stream: 53
I noticed that glxgears have similar issue on my box, but doesn't crash. The error came out only when exiting glxgears and produce the following:
X Error of failed request: BadDrawable (invalid Pixmap or Window parameter)
Major opcode of failed request: 130 (MIT-SHM)
Minor opcode of failed request: 3 (X_ShmPutImage)
Resource id in failed request: 0x2600002
Serial number of failed request: 912
Current serial number in output stream: 913
I first tried to recompile my kernel, xorg-drivers, xorg-server, mesa and xf86-video-intel (Yeah I'm on an Intel third generation) without any progress.
Since glxgears run "fine" and even if it might be a bug in the above packages, maybe there is something i'm doing wrong here.
EDIT 1: As suggested in comments, I've compiled my code with -fsanitize=address and got the following output:
=================================================================
==8391==ERROR: LeakSanitizer: detected memory leaks
Direct leak of 2048 byte(s) in 1 object(s) allocated from:
#0 0x7fa74669d878 in __interceptor_malloc (/usr/lib/gcc/x86_64-pc-linux-gnu/9.2.0/libasan.so.5+0x10c878)
#1 0x55c7722b61e1 in load_shader /home/http/dev/github/DStudio/src/ui.c:357
#2 0x55c7722b3fb9 in create_shader_program /home/http/dev/github/DStudio/src/ui.c:113
#3 0x55c7722ab509 in ui_thread /home/http/dev/github/DStudio/src/dsandgrains/ui.c:305
#4 0x7fa7462bf457 in start_thread (/lib64/libpthread.so.0+0x8457)
Direct leak of 600 byte(s) in 5 object(s) allocated from:
#0 0x7fa74669d878 in __interceptor_malloc (/usr/lib/gcc/x86_64-pc-linux-gnu/9.2.0/libasan.so.5+0x10c878)
#1 0x7fa745c9371e in __getdelim (/lib64/libc.so.6+0x7571e)
#2 0x55c7722af580 in get_proc_memory_usage /home/http/dev/github/DStudio/src/fileutils.c:119
#3 0x55c7722b1a42 in update_system_usage /home/http/dev/github/DStudio/src/system_usage.c:71
#4 0x7fa7462bf457 in start_thread (/lib64/libpthread.so.0+0x8457)
Direct leak of 600 byte(s) in 5 object(s) allocated from:
#0 0x7fa74669d878 in __interceptor_malloc (/usr/lib/gcc/x86_64-pc-linux-gnu/9.2.0/libasan.so.5+0x10c878)
#1 0x7fa745c9371e in __getdelim (/lib64/libc.so.6+0x7571e)
#2 0x55c7722af580 in get_proc_memory_usage /home/http/dev/github/DStudio/src/fileutils.c:119
#3 0x55c7722b196f in update_system_usage /home/http/dev/github/DStudio/src/system_usage.c:56
#4 0x7fa7462bf457 in start_thread (/lib64/libpthread.so.0+0x8457)
Direct leak of 120 byte(s) in 1 object(s) allocated from:
#0 0x7fa74669d878 in __interceptor_malloc (/usr/lib/gcc/x86_64-pc-linux-gnu/9.2.0/libasan.so.5+0x10c878)
#1 0x7fa745c9371e in __getdelim (/lib64/libc.so.6+0x7571e)
#2 0x55c7722afa87 in set_physical_memory /home/http/dev/github/DStudio/src/fileutils.c:169
#3 0x55c7722a693b in main /home/http/dev/github/DStudio/src/dsandgrains/main.c:36
#4 0x7fa745c41e6a in __libc_start_main (/lib64/libc.so.6+0x23e6a)
Direct leak of 80 byte(s) in 1 object(s) allocated from:
#0 0x7fa74669da68 in __interceptor_calloc (/usr/lib/gcc/x86_64-pc-linux-gnu/9.2.0/libasan.so.5+0x10ca68)
#1 0x55c7722b7e7b in init_context /home/http/dev/github/DStudio/src/window_management.c:172
#2 0x55c7722ab4b5 in ui_thread /home/http/dev/github/DStudio/src/dsandgrains/ui.c:295
#3 0x7fa7462bf457 in start_thread (/lib64/libpthread.so.0+0x8457)
Direct leak of 16 byte(s) in 1 object(s) allocated from:
#0 0x7fa74669d878 in __interceptor_malloc (/usr/lib/gcc/x86_64-pc-linux-gnu/9.2.0/libasan.so.5+0x10c878)
#1 0x55c7722b5242 in init_ui_elements /home/http/dev/github/DStudio/src/ui.c:246
#2 0x55c7722a96a0 in init_ui /home/http/dev/github/DStudio/src/dsandgrains/ui.c:154
#3 0x55c7722ab513 in ui_thread /home/http/dev/github/DStudio/src/dsandgrains/ui.c:307
#4 0x7fa7462bf457 in start_thread (/lib64/libpthread.so.0+0x8457)
SUMMARY: AddressSanitizer: 3464 byte(s) leaked in 14 allocation(s).
Why won't my shellcode (int3) be hit with the signal handler?
Apart from not like to have printf() in the handler, I care
for how to deliver the shellcode (as not inline assembler)
within the signal handler, being executed at runtime.
However, I present here a longer gdb session, that shows register
state and backtrace.
<code> Pid 19750 waiting for SIGUSR1 Program received signal SIGUSR1,
User defined signal 1. 0x0e5f9f89 in nanosleep () at <stdin>:2 2
<stdin>: No such file or directory.
in <stdin> Current language: auto; currently asm (gdb) bt
#0 0x0e5f9f89 in nanosleep () at <stdin>:2
#1 0x0e650348 in sleep (seconds=10) at /usr/src/lib/libc/gen/sleep.c:45
#2 0x18cb3d5b in main () at sig5.c:37 (gdb) i r eax 0x5b 91 ecx 0x0 0 edx 0xa 10 ebx
0x2e5df594 777909652 esp 0xcfbf73fc 0xcfbf73fc
ebp 0xcfbf7438 0xcfbf7438 esi 0x38cb62df
952853215 edi 0x38cb61e0 952852960 eip
0xe5f9f89 0xe5f9f89 eflags 0x206 518 cs
0x2b 43 ss 0x33 51 ds 0x33 51 es
0x33 51 fs 0x5b 91 gs 0x63 99
(gdb) c Continuing.
Program received signal SIGUSR1, User defined signal 1. 0x0e5f9f89 in
nanosleep () at <stdin>:2 2 in <stdin> (gdb) c Continuing.
Signal 30 from pid 0, should int3
Program received signal SIGSEGV, Segmentation fault. 0x18cb3c7a in
sigusr1 (signo=30, si=0xcfbf737c, data=0xcfbf7328) at sig5.c:23 23
ret(); Current language: auto; currently c (gdb) bt
#0 0x18cb3c7a in sigusr1 (signo=30, si=0xcfbf737c, data=0xcfbf7328) at sig5.c:23
#1 <signal handler called>
#2 0x0e5f9f89 in nanosleep () at <stdin>:2
#3 0x0e650348 in sleep (seconds=10) at /usr/src/lib/libc/gen/sleep.c:45
#4 0x18cb3d5b in main () at sig5.c:37 (gdb) i r eax 0xcfbf7305 -809536763 ecx 0x0 0 edx
0x0 0 ebx 0x38cb5124 952848676 esp
0xcfbf72e8 0xcfbf72e8 ebp 0xcfbf7310 0xcfbf7310
esi 0x38cb62df 952853215 edi 0x38cb61e0
952852960 eip 0x18cb3c7a 0x18cb3c7a eflags
0x10282 66178 cs 0x2b 43 ss 0x33 51
ds 0x33 51 es 0x33 51 fs
0x5b 91 gs 0x63 99 (gdb) bt full
#0 0x18cb3c7a in sigusr1 (signo=30, si=0xcfbf737c, data=0xcfbf7328) at sig5.c:23
code = "ëÌ"
ret = (int (*)()) 0xcfbf7305
#1 <signal handler called> No symbol table info available.
#2 0x0e5f9f89 in nanosleep () at <stdin>:2 No locals.
#3 0x0e650348 in sleep (seconds=10) at /usr/src/lib/libc/gen/sleep.c:45
rqt = {tv_sec = 10, tv_nsec = 0}
rmt = {tv_sec = 0, tv_nsec = 0}
#4 0x18cb3d5b in main () at sig5.c:37
sa = {__sigaction_u = {__sa_handler = 0x18cb3c04 <sigusr1>,
__sa_sigaction = 0x18cb3c04 <sigusr1>}, sa_mask = 0, sa_flags = 64}
-bash-4.3$ cat sig5.c
#include <errno.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
void sigusr1(int signo, siginfo_t *si, void *data) {
(void)signo;
(void)data;
unsigned char code[] = \
"\xeb\xcc";
int (*ret)() = (int(*)())code;
printf("Signal %d from pid %lu, should int3\n", (int)si->si_signo,
(unsigned long)si->si_pid);
sleep (1);
ret();
exit(0); }
int main(void) {
struct sigaction sa;
memset(&sa, 0, sizeof(sa));
sa.sa_flags = SA_SIGINFO;
sa.sa_sigaction = sigusr1;
if (sigaction(SIGUSR1, &sa, 0) == -1) {
fprintf(stderr, "%s: %s\n", "sigaction", strerror(errno));
}
printf("Pid %lu waiting for SIGUSR1\n", (unsigned long)getpid());
for (;;) {
sleep(10);
}
return 0; } </code>
Any Ideas?
So this uses mprotect(), but still does not lead to the shell. We really need to update
radare2 shellcode sources :)
<code>
#include "errno.h"
#include "signal.h"
#include "stdio.h"
#include "stdlib.h"
#include "string.h"
#include "unistd.h"
#include "sys/mman.h"
void sigusr1(int signo, siginfo_t *si, void *data) {
(void)signo;
(void)data;
unsigned char sc[] = \
"\xcc";
mprotect(sc,strlen(sc),PROT_EXEC|PROT_READ|PROT_WRITE);
int (*r)() = (int(*)())sc; /* Thanks, maybe change to define? */
r();
}
int main(void) {
struct sigaction sa;
memset(&sa, 0, sizeof(sa));
sa.sa_flags = 5; /* SIGTRAP via Sil... */
sa.sa_sigaction = sigusr1;
if (sigaction(SIGUSR1, &sa, 0) == -1) {
fprintf(stderr, "%s: %s\n", "sigaction", strerror(errno));
}
printf("Pid %lu waiting for SIGUSR1\n", (unsigned long)getpid());
for (;;) {
sleep(10);
}
return 0;
}
</code>
I try to get the backtrace of all threads of a process.
I wrote a test program:
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
int func_a(int *a)
{
*a++;
return 0;
}
void* test_thread(void* args)
{
int a = 0;
while(1) {
func_a(&a);
//sleep(1);
}
fprintf(stdout, "%d\n", a);
return NULL;
}
int main(int argc, char **argv)
{
pthread_t pid = 0;
pthread_create(&pid, NULL, test_thread, NULL);
pthread_create(&pid, NULL, test_thread, NULL);
pthread_create(&pid, NULL, test_thread, NULL);
pause();
return 0;
}
then i ran the program,and execute
pidof ./1|xargs -n1 sudo gdb --batch -ex "thread apply all bt full" -p
I saw the backtrace.(too many output i just pick some)
Thread 2 (Thread 0xb459db40 (LWP 25272)):
#0 func_a (a=0xb459d354) at 1.c:6
No locals.
#1 0x0804871f in test_thread (args=0x0) at 1.c:21
a = 382337846
#2 0xb775bf72 in start_thread (arg=0xb459db40) at pthread_create.c:312
__res = <optimized out>
pd = 0xb459db40
now = <optimized out>
unwind_buf = {cancel_jmp_buf = {{jmp_buf = {-1216946176, -1269179584, 4001536, -1269181400, -56721544, -1538858626}, mask_was_saved = 0}}, priv = {pad = {0x0, 0x0, 0x0, 0x0}, data = {prev = 0x0, cleanup = 0x0, canceltype = 0}}}
not_first_call = <optimized out>
pagesize_m1 = <optimized out>
sp = <optimized out>
freesize = <optimized out>
__PRETTY_FUNCTION__ = "start_thread"
#3 0xb7691f8e in clone () at ../sysdeps/unix/sysv/linux/i386/clone.S:129
No locals.
But when I enable the sleep statement in test_thread function,it can't get the backtrace.
Thread 3 (Thread 0xb4d29b40 (LWP 26045)):
#0 0xb7716cf9 in ?? ()
No symbol table info available.
#1 0x00000000 in ?? ()
No symbol table info available.
Thread 2 (Thread 0xb4528b40 (LWP 26046)):
#0 0xb7716cf9 in ?? ()
No symbol table info available.
#1 0x00000000 in ?? ()
No symbol table info available.
does anyone know why
thanks #Employed Russian to point out the defects.The enviroment is as follow:
gcc version: 4.8.4
gdb version: 7.7.1
compile command: gcc -g 1.c -o 1 -lpthread -rdynamic
~/.gdbinit is not exist
I use ubuntu 14.04
I have a code written in Allegro 4 and am converting it to Allegro 5, but I'm having serious problems with functions that no longer exist in allegro 5, one of them is "blit"
BITMAP *bTile; // Bitmap do tile;
BITMAP *bMapa; // Bitmap do mapa;
BITMAP *bTexturas[20]; // Vetor de bitmap das texturas;
BITMAP *bChar; // Bitmap do personagem;
BITMAP *bMario[3];
// ##########################################################
int main()
{
int vResolucao_x = 640;
int vResolucao_y = 480;
init(vResolucao_x, vResolucao_y);
BITMAP *buffer = create_bitmap(vResolucao_x, vResolucao_y);
bTile = load_bitmap("Tiles/tile.bmp", NULL);
bChar = load_bitmap("Tiles/mario.bmp", NULL);
bMapa = create_bitmap(vResolucao_x, vResolucao_y);
// ############# - Carrega imagens do mario - ############
bMario[0] = create_bitmap(vTile,vTile);
bMario[1] = create_bitmap(vTile,vTile);
bMario[2] = create_bitmap(vTile,vTile);
blit(bChar, bMario[0], 0, 0, 0, 0, vTile, vTile);
blit(bChar, bMario[1], 33, 0, 0, 0, vTile, vTile);
blit(bChar, bMario[2], 66, 0, 0, 0, vTile, vTile);
// #######################################################
install_int(fGravidade,5);
fCarrega_Sprites_Mapa();
fCarrega_Mapa();
fMostra_Mapa();
draw_sprite(screen, bMapa, 0, 0 );
while (!key[KEY_ESC]) {
Virtually nothing of this my old code works with Allegro 5, so I'm doing the conversion as I can learn, but this blit function, can not find its like in allegro 5, another function that I can not find your simulate is: install_int (...)
Allegro 5 is essentially a completely new library. Here's a line-by-line translation, as best as can be done. Note that Allegro 5 uses a fundamentally different concept (event loop) and you should really take the time to learn how that works before diving into trying to convert your code.
ALLEGRO_BITMAP *bMario[3];
// ##########################################################
int main()
{
int vResolucao_x = 640;
int vResolucao_y = 480;
init(vResolucao_x, vResolucao_y);
ALLEGRO_BITMAP *buffer = al_create_bitmap(vResolucao_x, vResolucao_y);
bTile = al_load_bitmap("Tiles/tile.bmp");
bChar = al_load_bitmap("Tiles/mario.bmp");
bMapa = al_create_bitmap(vResolucao_x, vResolucao_y);
// ############# - Carrega imagens do mario - ############
bMario[0] = al_create_bitmap(vTile,vTile);
bMario[1] = al_create_bitmap(vTile,vTile);
bMario[2] = al_create_bitmap(vTile,vTile);
al_set_target_bitmap(bMario[0]);
al_draw_bitmap(bchar, 0, 0, 0);
al_set_target_bitmap(bMario[1]);
al_draw_bitmap(bchar, 33, 0, 0);
al_set_target_bitmap(bMario[2]);
al_draw_bitmap(bchar, 66, 0, 0);
al_set_target_backbuffer(display);
// #######################################################
fGravidade = al_create_timer(5 / 1000.0); // ALLEGRO_TIMER*
ALLEGRO_EVENT_QUEUE *queue = al_create_event_queue();
al_register_event_source(queue, al_get_timer_event_source(gfGravidade));
al_register_event_source(queue, al_get_keyboard_event_source());
fCarrega_Sprites_Mapa();
fCarrega_Mapa();
fMostra_Mapa();
al_draw_bitmap(bMapa, 0, 0, 0);
al_flip_display();
while (true) {
ALLEGRO_EVENT event;
al_wait_for_event(queue, &event);
if (event.type == ALLEGRO_EVENT_TIMER) {
// fGravidade ticked
}
else if (event.type == ALLEGRO_EVENT_KEY_CHAR) {
if (event.keyboard.keycode == ALLEGRO_KEY_ESCAPE) {
break;
}
}
}