Linux SIGPIPE Crashing Server - linux

So at the start of my application I call
signal(SIGPIPE, SIG_IGN);
which I thought would have my application ignore SIGPIPE. However I still got a SIGPIPE crash with the following code:
write(fd, outgoingStr->c_str(), size);
where fd is an int (file descriptor) and size is the size of the string. What am I doing wrong here?
On a side note, I recently use to wrap that write inside an if to check for an error value returned and I believe I never had SIGPIPE crashes until that was removed. The if check did nothing but cout to the console if there was an error, so I'm not sure if it is relevant or not.

The problem ended up being that GDB will stop on SIGPIPE even if it is being ignored. When running the application normally it works as intended.

Related

printk() messages not appearing in console

So I'm trying to learn to write Linux modules and right now I'm experimenting with a basic "Hello World" module:
#include <linux/module.h>
#include <linux/init.h>
MODULE_LICENSE("Dual BSD/GPL");
static int hello_init(void){
printk(KERN_ALERT "Hello, world.\n");
return 0;
}
static void hello_exit(void){
printk(KERN_ALERT "goodbye.\n");
}
module_init(hello_init);
module_exit(hello_exit);
And I've finally gotten this module to work! When I add with insmod it prints "hello" to kernel.log and when I remove it with remmod it prints "goodbye" to kernel.log.
My trouble is that I decided I want to try and get the output to also print to the console. From what I understand about printk(), is that in order for messages to show up in the console, the console must be set to the appropriate message level in /proc/sys/kernel/printk. (This is all according to https://elinux.org/Debugging_by_printing). My console is set to level 4.
cat /proc/sys/kernel/printk:
4 4 1 7
Since KERN_ALERT is level 2 and my console is set to print out level 4 and below messages, why are the printk messages not appearing on my console? When I run dmesg I can see the messages are clearly in the buffer, but never go to the console. It's not I really need them to print to the console, but I really want to understand how this all works.
I hope i can answer to your question. I also faced same issue and tried my level best to print kernel message to console, but nothing works. Then I started searching for the reason...
The reason is, If klogd is not running, the message won’t reach user space unless you read /proc/kmsg. Reference: oreilly or /dev/kmsg. klogd reads kernel log messages and helps process and send those messages to the appropriate files, sockets or users. since absence of daemon, it won't send to standard output. Unless you read the message from ring buffer or buffer overflow, it will remains.

How can I create a testing script with GDB

I have a set of inputs that I want to use to test my program so see what input will hit a break point. I want to create a script to test these inputs one by one and if it hit the break point, print or save the result to a file.
Please let me know if it's possible and if yes, how can I do it. Thank you.
I'm not sure if I have exactly understood what you are asking for. But if I understood correctly, you want to write a program that:
Starts another program
Passes some pre-defined input to the other program
Checks if some breakpoint in the other program is hit
I don't know if this is possible using gdb, but it would be possible to write your own debugger:
Start the program to be tested using fork and one of the exec functions (such as execlp)
Before the exec function call ptrace(PTRACE_TRACEME,0,0,0)
Call waitpid; if exec succeeded, the program will be stopped immediately. The "status code" (second argument) returned by waitpid will be 0x57F (assuming an x86 CPU).
If waitpid returns another exit code, exec failed and you cannot continue.
Use ptrace(PTRACE_PEEKTEXT,...) and ptrace(PTRACE_POKETEXT,...) to modify the program: You place a break point to some address by replacing the instruction at that address by a "breakpoint" instruction (on x86 CPUs: int3 which is byte 0xCC)
This means:
You have to know the addresses (not the line numbers) of the break points and write 0xCC to each address using ptrace().
Because PTRACE_POKETEXT can only modify 4 bytes (x86_32) or 8 bytes (x86_64) at once, you first have to read the old values of these 4 or 8 bytes using PTRACE_PEEKTEXT, modify 1 of 4 or 8 bytes and write all 4 or 8 bytes back.
If your program is not always loading to the same address (due to ASLR etc.) you can read the program counter (using PTRACE_PEEKUSER): It should be the (actual) address of the entry point of the program.
Call ptrace(PTRACE_CONT,pid,0,0) to start the program being tested
Call waitpid to wait for the program to be stopped or to exit
If waitpid returns 0x57F as "status code", you are in the breakpoint. You may now use kill(pid, SIGKILL) to stop your program.
You may use PTRACE_PEEKUSER to check the value of the program counter (rip on x86-64) so you know which breakpoint has been hit. Note that the program counter may be the address of the breakpoint plus 1, so if a breakpoint at address 0x12340000 has been hit, rip may be 0x12340001.
If waitpid returns any other value with the low byte 0x7F, the program caused an exception. You should use kill(pid,SIGKILL) to finally stop it.
Otherwise (if the low byte returned by waitpid is not 0x7F), the program has finished without causing an exception and without hitting any breakpoint.
Here some example code:
int pid, code;
long tmpLong;
pid=fork();
if(!pid)
{
ptrace(PTRACE_TRACEME,0,0,0);
execlp("program_to_be_tested","program_to_be_tested",NULL);
exit(123);
}
waitpid(pid,&code,0);
if(code!=0x57F)
{
/* Starting the program failed ... */
}
else
{
/* Set breakpoints - here assuming x86-64 */
tmpLong=ptrace(PTRACE_PEEKDATA,pid,(void *)(address&~7),0);
((char *)&tmpLong)[address&7]=0xCC;
ptrace(PTRACE_POKEDATA,pid,(void *)(address&~7),(void *)tmpLong);
/* Continue the program */
ptrace(PTRACE_CONT,pid,0,0);
waitpid(pid,&code,0);
if((code&0xFF)!=0x7F)
{
/* Program did not hit a breakpoint
* and did not cause an exception */
}
else if(code==0x57F)
{
/* Breakpoint hit */
kill(pid,SIGKILL);
}
else
{
/* Program caused an exception */
kill(pid,SIGKILL);
}
}
To pass input to your program, you have two possible choices:
Run the debugger multiple times:
echo "Input to be tested" | ./myDebugger
Because your debugger does not read from STDIN, the input will be passed to the program to be tested.
Use pipe and dup2 when creating the child process:
...
pipe(pipes);
pid=fork();
if(!pid)
{
dup2(pipes[0],0);
close(pipes[0]);
close(pipes[1]);
...
}
close(pipes[0]);
write(pipes[1],"Input to be sent to program", ...);
...

how to figure out what NL messages are exchanged

Hi Linux kernel/net guru,
I'm looking for a way how to hook and print out NL(netlink) messages between wpa_supplicant and kernel. As of now I just inserted several printk messages to print those but it's very painful I think.
Please let me know if you have a better idea.
Thanks.
This is not a good answer given the OP is using wpa_supplicant specifically but might help people drawn here by accident.
If somebody is using libnl (wpa_supplicant doesn't), all you have to do is, in userspace, once the socket has been initialized,
error = nl_socket_modify_cb(sk, NL_CB_MSG_IN, NL_CB_DEBUG, NULL, NULL);
if (error < 0)
log_err("Could not register debug cb for incoming packets.");
error = nl_socket_modify_cb(sk, NL_CB_MSG_OUT, NL_CB_DEBUG, NULL, NULL);
if (error < 0)
log_err("Could not register debug cb for outgoing packets.");
The userspace client will print all messages whenever it sends or receives them.
(Also, you can alternatively call nl_msg_dump(msg, stderr) whenever you want.)
For stuff that doesn't use libnl, you can always copy the relevant functions from libnl and call them. See nl_msg_dump() in libnl's source code (libnl/lib/msg.c).

How to protect main-thread from errors caused by children (SBCL)

I am currently playing with sb-thread API, provided by SBCL, wondering what happens if an error is thrown inside a started thread and how to ensure that only that process is affected (and dies), and no other process is, as apparently the debugger will be entered even though not the main thread throws an error.
* (handler-case
(sb-thread:join-thread (sb-thread:make-thread #'(lambda()
(error 'simple-error))))
(sb-thread:join-thread-error (err)
(sb-thread:thread-error-thread err)
(FORMAT t "allemeineentchen~%")))
(A SIMPLE-ERROR was caught when trying to print *DEBUG-CONDITION* when entering
the debugger. Printing was aborted and the SIMPLE-ERROR was stored in
SB-DEBUG::*NESTED-DEBUG-CONDITION*.)
;after this sbcl just yields until str-c enters the debugger
My suggestion would be to make each thread function body starting with an (handler-case (body) (error (err) err) but this seems awfully non-standard/malpractice and only works with threads whose function body are created by me, and I am not sure that this will, in every case, prevent entering the debugger.
Is there some guideline/(unofficial)standard concerning this topic?
You need to be very clear about what is being signalled and what is being handled (and where): First, what error condition are you trying to handle? When you call #'error in your thread with 'simple-error, that is a problem, because sbcl will not be able to print the error which you have signalled, but otherwise things are working as they should. If I do this:
(handler-case
(sb-thread:join-thread
(sb-thread:make-thread #'(lambda()
(error "simple error"))))
(simple-error (c)
c)
(sb-thread:join-thread-error (c)
(sb-thread:thread-error-thread c)))
Sbcl correctly enters the debugger for the unhandled simple-error, however the join-thread-error which gets signalled after I use the abort restart from the debugger does get handled, and I think that is what you were asking about:
simple error
[Condition of type SIMPLE-ERROR]
Restarts:
0: [ABORT] Abort thread (#<THREAD RUNNING {DABCAD1}>) 0 ==> #<SB-THREAD:THREAD ABORTED {DABCAD1}>
Edit: I am adding this after reading Sim's comment:
If you just want to ignore any errors in the thread then do that:
(sb-thread:join-thread
(sb-thread:make-thread #'(lambda() (ignore-errors
(error "simple error")))))

How to create an execve() child process with the right tty settings to run 'vi' yet still redirect IO back to the parent process?

How do I get a forked, execve() child process that can run 'vi', etc. and redirect all IO to the parent process?
I'm trying to pass shells through from an embedded Linux process to the PC software interface connected over the network. The IO for the shell process is packaged into app-specific messages for network transport over our existing protocol.
First I was just redirecting IO using simply pipe2(), fork(), dup2(), and execve(). This didn't give me a tty on the remote side, so screen, etc. didn't work.
Now I'm using forkpty, and screen mostly works, but many many other don't (vi, stty, etc). It appears the current problem is that the child process doesn't control the tty.
I've been experimenting with TIOCSCTTY, but haven't had much luck.
Here's more or less what I've got:
bool ExternalProcess::launch(...)
{
...
winsize winSize;
winSize.ws_col = 80;
winSize.ws_row = 25;
winSize.ws_xpixel = 10;
winSize.ws_ypixel = 10;
_pid = forkpty(&_stdin, NULL, NULL, &winSize);
//ioctl(_stdin, TIOCNOTTY, NULL);
if (!_pid && (_pid != -1))
{
// this is the child process
char tty[4096];
strncpy(tty, ttyname(STDIN_FILENO), sizeof(tty));
tty[sizeof(tty)-1]=0;
FILE* fp = fopen("debug.txt", "wt"); // no error checking - temporary test code
fprintf(fp, "slave TTY %s", tty);
//if (ioctl(_stdin, TIOCSCTTY, NULL) < 0)
if (ioctl(STDIN_FILENO, TIOCSCTTY, NULL) < 0)
{
fprintf(fp, "ioctl() TIOCSCTTY %s\n", strerror(errno));
fflush(fp);
}
else
{
fprintf(fp, "SET CONTROLLING TTY!");
fflush(fp);
}
fclose(fp);
// command, args, env populated elsewhere
execve(command, args, env);
...
// fail path
_exit(-1);
return false;
}
_stdout = _stdin;
...
// enter select() loop reading/writing _stdin, _stdout
}
I am getting results in the debug file like:
slave TTY /dev/pts/5
SET CONTROLLING TTY!
but still many apps are failing with tcsetattr() errors. Am I right in thinking this is a controlling tty problem? How do I fix it?
EDIT
Minor correction. When I do the ioctl TIOCSCTTY on STDIN_FILENO, then it works as in the debug file above, but the IO redirection back to the parent process is disrupted.
EDIT 2
Okay, I'm starting to understand this better. Looking at the kernel source for the ioctl behind tcsetattr(), the processes I am calling are being sent SIGTTIN and SIGTTOU when trying to change the tty.
Only a foreground process can do that, and they're running as if they're background processes. I tried setting those signals to SIG_IGN after forking and before the execve(), but that didn't work. The semantics of this I understand, but it's safe in my redirection scenario for the execve()'d processes to act as if they're foreground processes. The question is... how to make it so? I will continue to search in the kernel code for clues.
Ugh! It's bash, the shell I was calling with execve().
If it detects that stderr is not attached to a tty, then it enters this special mode where child processes cause SIGTTOU.
I found a mention of this problem here.
When I stopped redirecting stderr away from the tty, then it now seems to work as planned.

Resources