Does daemon() have any disadvantages? - c++

Does using the C function daemon() have any security or stability disadvantages for a linux daemon compared to using explicit functions like fork(), setsid(), umask(), etc. (beside being unable to set all daemon parameters)?
I was wondering why I should write
#include <sys/types.h>
#include <sys/stat.h>
#include <cstdio>
#include <cstdlib>
#include <fcntl.h>
#include <cerrno>
#include <unistd.h>
#include <syslog.h>
#include <string>
int main()
{
//Set our Logging Mask and open the Log
setlogmask(LOG_UPTO(LOG_NOTICE));
openlog(DAEMON_NAME, LOG_CONS | LOG_NDELAY | LOG_PERROR | LOG_PID, LOG_USER);
syslog(LOG_INFO, "Entering Daemon");
pid_t pid, sid;
//Fork the Parent Process
pid = fork();
if (pid < 0)
exit(EXIT_FAILURE);
//We got a good pid, Close the Parent Process
if (pid > 0)
exit(EXIT_SUCCESS);
//Change File Mask
umask(0);
//Create a new Signature Id for our child
sid = setsid();
if (sid < 0)
exit(EXIT_FAILURE);
//Change Directory
//If we cant find the directory we exit with failure.
if ((chdir("/")) < 0)
exit(EXIT_FAILURE);
//Close Standard File Descriptors
close(STDIN_FILENO);
close(STDOUT_FILENO);
close(STDERR_FILENO);
while (true)
{
sleep(5);
//Do something
}
closelog ();
}
instead of
#include <unistd.h>
int main()
{
daemon(0, 0);
while (true)
{
//Do something
sleep(5);
}
}

Per the manpage, it's not in POSIX so you're always taking a risk regarding its existence.
Otherwise, no.

Related

unable to write /proc/sys/kernel/ns_last_pid file

I want to edit the ns_last_pid file present in /proc/sys/kernel, but i'm getting the error of Read-only file system. How to resolve this?
This is what i've written to open the file.
int fd = open("/proc/sys/kernel/ns_last_pid", O_RDWR | O_CREAT, 0644);
if (fd < 0) {
cout<<strerror(errno)<<"\n";
return 1;
}
I've to write this file, change it's value. This file contains a single number represnting the last pid allocated to any process. I've to edit this so that i can get desired pid number for a process. like these guys are doing for their project CRIU(see first link).
Pid_restore(criu.org),
How to set process ID in Linux for a specific program(stackoverflow answer)
EDIT 1: Smallest reproducible example
#include <fstream>
#include <bits/stdc++.h>
#include <sys/types.h>
#define _GNU_SOURCE /* See feature_test_macros(7) */
#include <sched.h>
#include <sys/wait.h>
#include <sys/stat.h>
#include <sys/file.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/syscall.h>
using namespace std;
int main(){
printf("Opening ns_last_pid...\n");
int fd = open("/proc/sys/kernel/ns_last_pid", O_RDWR | O_CREAT, 0644);
if (fd < 0) {
cout<<strerror(errno)<<"\n";
return 1;
}
printf("Locking ns_last_pid...\n");
if (flock(fd, LOCK_EX)) {
close(fd);
printf("Can't lock ns_last_pid\n");
return 1;
}
printf("Done\n");
char buf[100];
int pid_max = 30000;
snprintf(buf, sizeof(buf), "%d", pid_max-1);
printf("Writing pid-1 to ns_last_pid...\n");
cout<<fd<<"\n";
if (write(fd, buf, strlen(buf)) != strlen(buf)) {
cout<<strerror(errno)<<"\n";
printf("Can't write to buf\n");
return 1;
}
printf("Done\n");
printf("Cleaning up...");
if (flock(fd, LOCK_UN)) {
printf("Can't unlock");
}
close(fd);
printf("Done\n");
return 0;
}
For a program to change kernel files, it should be owned by root
sudo chown root program // program is the executable(the binary)
set the setuid bit on the executable to execute a program with superuser access.
with this it will run as root even if we execute it as any user on our machine.
sudo chmod u+s program
Compile the source code and run the program with sudo to prevent other permission access errors.
Thanks to TedLyngmo for suggesting this solution.

c++ pipe buffering disable

How to disable buffering in pipe. I'm creating a simple recorder/player for I/O. To do this I need record output witch time delays.
To record delays, I need something like this
example tekst
"wait 1s"
example tekst
"wait 1s"
example tekst
...
but if I use
pipe2(in, O_DIRECT );
i see something like this
"wait 100s"
"100 times" example tekst
"wait 100s"
"100 times" example tekst
...
man7 tells:
O_DIRECT (since Linux 3.4)
Create a pipe that performs I/O in "packet" mode. Each
write(2) to the pipe is dealt with as a separate packet, and
read(2)s from the pipe will read one packet at a time.
I tried to disable buffering, by:
fcntl(in[1], F_SETPIPE_SZ, 1);
but it's still not working.
read.cpp
#define _GNU_SOURCE
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
#include <unistd.h>
#include <signal.h>
#include <sys/types.h>
#include <stdlib.h>
#include <string.h>
#include <sys/ioctl.h>
#include <poll.h>
#include <assert.h>
bool keep = true;
void intHandler(int dummy) {
keep = 0;
}
int main(void) {
signal(SIGINT, intHandler);
int in[2];
int out[2];
int pid;
int fo;
char buf[1024];
pipe2(in, O_DIRECT );
pipe2(out, O_DIRECT );
pid = fork();
if (pid == -1) {
perror("fork");
exit(1);
}
if (pid == 0) {
close(in[0]);
close(out[1]);
close(0);
close(1);
dup2(in[1], 1);
dup2(out[0], 0);
close(in[1]);
close(out[0]);
sleep(1);
char *newargv[] = {"/root/Pulpit/a1", NULL, NULL, NULL};
char *newenviron[] = {NULL};
int ret = execve("/root/Pulpit/a1", newargv, newenviron);
printf("%d", ret);
return 0;
} else {
close(out[0]);
close(in[1]);
int n = 0;
while (keep) {
int wyn = read(in[0], buf, 1024);
if (wyn > 0) {
char aa[1024];
write(1, buf, wyn);
fsync(1);
}
}
}
return (0);
}
a1.cpp
#include <cstdlib>
#include <unistd.h>
#include "stdio.h"
using namespace std;
/*
*
*/
int main(int argc, char** argv) {
while(true){
printf("example text\n");
usleep(100000);
}
return 0;
}

Why isn't execlp() printing output to the terminal?

I am trying to link the output of a child process into the input of a parent process; the parent process is to execute a system call or command using the child's output.
I have looked to the following threads for answer; however, I didn't quite get the answer I am looking for.
Pipe - C++ piping issue
Linux Pipes as Input and Output
The problem I am having is that the command in the parent process is not being printed to the terminal.
Why isn't the output being printed to the terminal? I have closed the ends of my pipe in both the parent and child processes. Furthermore, the parent's std_out isn't being modified.
Here is my code.
#include <sys/types.h>
#include <sys/wait.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <iostream>
using namespace std;
int main(int argc, const char * argv[])
{
enum {RD, WR};
int fd[2];
pid_t pid;
if (pipe(fd) < 0)
perror("pipe error");
else if ((pid = fork()) < 0)
perror("fork error");
else if (pid == 0) { //In child process
close(fd[RD]);
dup2(fd[WR], STDOUT_FILENO);
close(fd[WR]);
execlp("/bin/ps", "ps", "-A", NULL);
}
else { //In parent process
close(fd[WR]);
dup2(fd[RD], STDIN_FILENO);
close(fd[RD]);
wait(NULL);
execlp("/bin/wc", "wc", "-l", NULL);
}
return 0;
}
You don't check for the failure of execlp.
Are you sure all of your programs are where you think they are? Your program works for me if I just change "/bin/wc" to "/usr/bin/wc".

terminate a thread in C++ along with any process(es) it has spawned

I'm writing a fuzzer in C++ on linux. It spawns multiple threads and has a timeout function if the thread hangs for whatever reason. I cannot figure out the correct way to kill the thread off after it's timer runs out. What I am doing now is something along the lines of:
`
#include <signal.h>
#include <string.h>
#include <sys/wait.h>
#include <errno.h>
#include <iostream>
#include <fstream>
#include <cstdlib>
#include <chrono>
#include <thread>
#include <stdlib.h>
#include <sys/wait.h>
#include <stdio.h>
#include <vector>
#include <iostream>
#include <sys/time.h>
#include <random>
#include <cstdlib>
#include <climits>
#include <sstream>
#include <iomanip>
#include <unistd.h>
#include <cstring>
#define READ 0
#define WRITE 1
void reaper (int c_pid, int t_timeout) {
std::this_thread::sleep_for(std::chrono::milliseconds(t_timeout));
kill (c_pid, 9);
}
FILE * popen2 (std::string command, std::string type, int & pid, std::string low_lvl_user) {
pid_t child_pid;
int fd[2];
pipe(fd);
if((child_pid = fork()) == -1) {
perror("fork");
exit(1);
}
if (child_pid == 0) { // child begins
if (type == "r") {
close(fd[READ]); //Close the READ
dup2(fd[WRITE], 1); //Redirect stdout to pipe
}
else {
close(fd[WRITE]); //Close the WRITE
dup2(fd[READ], 0); //Redirect stdin to pipe
}
if (getuid() == 0) {
execl("/bin/su", "su", "-c", "/bin/sh", "-c", command.c_str(), low_lvl_user.c_str(), NULL); // fixes not being able to reap suid 0 processes
}
else {
execl("/bin/sh", "/bin/sh", "-c", command.c_str(), NULL); // runs it all
}
exit(0);
}
else {
if (type == "r") {
close(fd[WRITE]); //Close the WRITE
}
else {
close(fd[READ]); //Close the READ
}
}
pid = child_pid;
if (type == "r") {
return fdopen(fd[READ], "r");
}
return fdopen(fd[WRITE], "w");
}
int pclose2(FILE * fp, pid_t pid) // close it so we don't fuck outselves
{
int stat;
fclose(fp);
while (waitpid(pid, &stat, 0) == -1) {
if (errno != EINTR) {
stat = -1;
break;
}
}
return stat;
}
int spawn_ch (std::string out_str) {
std::string low_lvl_user = "nobody";
int t_timeout = 500;
int pid; // initializes child
FILE * fp = popen2(out_str, "r", pid, low_lvl_user); // opens child process fork
char command_out[4096] = {0};
std::stringstream output;
std::thread reaper_thread(reaper, pid, t_timeout); // takes care of killing it off if it takes too long
reaper_thread.join();
while (read(fileno(fp), command_out, sizeof(command_out)-1) != 0) {
output << std::string(command_out);
memset(&command_out, 0, sizeof(command_out));
}
pclose2(fp, pid);
std::string token;
}
int main () {
std::string command = "HOME=AAAAAAAAA MAIL=AA /usr/sbin/exim4 -Ac AAAAAA -G -MCP,9,-Mar -Mf -Mset b -S 999999 -X,,-bF 999 -bdf -bpc -bpr -bpru,,-bt -exim4,AAA, -f,AAAAAAAAA,-oA -oMa,5Mu^i, -oMaa,, -oMas,,-oMs -oX isotanr -odb -oee -oem,999, -oo,99999999 -r 999999999 -t -ti 999999";
std::vector<std::thread> threads;
int num_threads = 2;
for (int cur_thread=1; cur_thread <= num_threads; ++cur_thread) threads.push_back(std::thread(spawn_ch, command)); // Thrift Shop
for (auto& all_thread : threads) all_thread.join(); // is that your grandma's coat?
exit(0);
}
But as the processes are spawned as suid 101 in this example (or 0, or whatever else), the kill function can be run as root to reap the processes it spawned... which would work, except exim4 apparently tries to spawn multiple processes, and when one dies the others don't. Is there a way to let the program know what processes were spawned to kill them, or preferably, a way to just terminate the entire thread that spawned them (which I think should work, as if you ctrl+c my program it will kill off what it spawned)?
The whole codebase is on github.
Thanks in advance.
The std::thread class provides no means to arbitrary terminate an active execution thread. This functionality is not implemented in the current C++ standard.
The sample code you posted is pretty much the only thing that can be done using purely the functionality in the C++ and C libraries.
The POSIX thread API is an alternative option. It does provide the means to terminate an active thread; however that comes with many important caveats, and it's very difficult to avoid undefined behavior, when terminating an execution thread using pthread_cancel(), since this will not properly unwind the terminated thread's stack, and invoke all the needed destructors; furthermore the executing thread must reach a cancellation point, in order for pthread_cancel() to take effect.
Additionally, if the executing thread execs another process, the new process is going to replace the thread's entire process, not just the executing thread's context. If this was your intent all along, trying to cancel the thread won't do much good anyway, and you pretty much have to do what you are already doing.

C++ character array not being read right through pipe

I'm trying to check that the cmd variable is set to "LISTALL" but it isn't when I try printing it out.
#include <stdio.h>
#include <unistd.h>
#include <cstring>
#include <stdlib.h>
#include <iostream>
#include <sys/wait.h>
int main(int argc, char **argv)
{
pid_t cPid = fork();
int P2C[2];
int C2P[2];
pipe(P2C);
pipe(C2P);
char cmd[50];
char* listOfProcesses = new char[1024];
if (cPid == 0)
{
...
read(P2C[0], cmd, 50);
printf("%s\n", cmd);
if(strcmp(cmd,"LISTALL") == 0)
{
//printf("Executing the command: %s", cmd);
write(C2P[1], getlistOfProcesses("ps -ax -o pid,cmd"), 1024);
...
}
}
else if (cPid > 0)
{
...
write(P2C[1], "LISTALL", 50);
wait(NULL);
read(C2P[0], listOfProcesses,1024);
...
}
else
{
// fork failed
printf("Forking failed!\n");
exit(1);
}
return 0;
}
What I get from that is a mini box symbol with 00 at the top and 01 or 02 at the bottom. I tried pasting the symbol here but it doesn't show.
You create 4 pipes: two in the parent process and two in the child process.
Create the pipes before forking! Then fork, then check whether you are in the parent process or in the child process.
That way you have only two pipes, both processes know about these pipes and can communicate by reading or writing to the appropriate file descriptors of the pipes.