unable to write /proc/sys/kernel/ns_last_pid file - c++

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.

Related

read and write doesn't work in named pipes c++

Please excuse my English, its not the best. Thank you.
I am suppose to write 2 simple programs, which are suppose to enable two communication between processes in/with named pipes(C++).
Each code search through the directory and (name of the directory is suppose to be inputed by a user) search for FIFO file type. After finding a file, first code opens to read, second code opens to write. If process can't find a file, then it will ask user to input a new path.
First code write the message in the terminal(stdin) and send it through the pipe to second process. Second process read the message from the pipe and shows it in terminal(stdout). Both processes are suppose to end after reading message from stdin and sending a statement 'END';
I am still learning and trying to find more about named pipes so for now I could only write some basics programs(just to read and write) but still I don't understand why both of them doesn't work.
Can You tell me what is wrong with my codes? Thank You.
here is my code for read
#include <stdio.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
int main(void)
{
char sentence [256];
int fp, numr ,numop;
umask(0);
fp = mkfifo("myfifo", S_IFIFO|0666);
if(fp < 0)
{
printf("Cant make a file\n");
return 1;
}
numop = open("myfifo",O_RDONLY);
if(numop < 0)
{
printf("Cant open the file\n");
return 1;
}
numr = read(fp,&sentence,sizeof(sentence));
if( numr < 0)
{
printf("Cant read the message\n");
return 1;
}
fgets(sentence,256,stdin);
printf("Message: %s\n",sentence);
close(fp);
return 0;
}
here is for write
#include <stdio.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
int fd , numw;
char sentence [256];
fd = open("myfifo", O_WRONLY);
if(fd < 0)
{
printf("Can't open a file\n");
return 1;
}
printf ("Enter the message : ");
fgets(sentence,250,stdin);
numw = write(fd,sentence,strlen(sentence)+1);
if(numw < 0)
{
printf("Can write the message");
return 1;
}
close(fd);
return 0;
}
can you tell me what am I doing wrong?

Does daemon() have any disadvantages?

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.

Checking user permissions in C++

I have some code to create a directory using the sys/stat.h header. However, when trying to create a directory that the user does not have the correct permissions for (such as a non-root user creating a folder in /), no error is thrown, and no output is given, even though the folder is not created. Is there a way to check if a user has the correct permissions before creating a directory? My code is below.
//Defines the mkdir command
#include <iostream>
#include <string>
#include <sys/stat.h>
//C headers
#include <cerrno>
#include <cstring>
#include <cstdio>
//Custom headers
#include "string_algorithms.hpp"
#include "chdir.hpp"
//Defines current working directory
#define GetCurrentDir getcwd
using namespace std;
void mkdirFunc(string path)
{
try
{
//Find how many directories need to be created
vector<string> numberOfDirectories = strSplitter(path, "\\");
int count=0;
char cCurrentPath[FILENAME_MAX];
if (!GetCurrentDir(cCurrentPath, sizeof(cCurrentPath)))
{
printf("ERROR: %s\n", strerror(errno));
}
for(int i=0; i<numberOfDirectories.size(); i++)
{
mkdir(string(numberOfDirectories[i]).c_str(), S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
chdirFunc(string(numberOfDirectories[i]));
}
chdirFunc(cCurrentPath);
}
catch(int e)
{
printf("ERROR: %s\n", strerror(errno));
}
}

simple client/server program using named pipes in linux

I am trying to write a program that has two separate process that talk via named pipes. The client which sends a message to a server, and the server which needs to broadcast that message to all clients attached to it. So far, I can get a connection between the two, but I cannot get more than one message to work no matter what I have tried. Below is the code I have written that will allow a connection and transmission of a single message.
server.cpp:
#include <fcntl.h>
#include <stdio.h>
#include <sys/stat.h>
#include <unistd.h>
#include <string.h>
#define FIFO_FILE_1 "/tmp/client_to_server_fifo"
#define FIFO_FILE_2 "/tmp/server_to_client_fifo"
int main()
{
int client_to_server;
int server_to_client;
char buf[BUFSIZ];
/* create the FIFO (named pipe) */
mkfifo(FIFO_FILE_1, 0666);
mkfifo(FIFO_FILE_2, 0666);
printf("Server ON.\n");
while (1)
{
/* open, read, and display the message from the FIFO */
client_to_server = open(FIFO_FILE_1, O_RDONLY);
server_to_client = open(FIFO_FILE_2, O_WRONLY);
read(client_to_server, buf, BUFSIZ);
if (strcmp("exit",buf)==0)
{
printf("Server OFF.\n");
break;
}
else if (strcmp("",buf)!=0)
{
printf("Received: %s\n", buf);
printf("Sending back...\n");
write(server_to_client,buf,BUFSIZ);
}
/* clean buf from any data */
memset(buf, 0, sizeof(buf));
close(client_to_server);
close(server_to_client);
}
close(client_to_server);
close(server_to_client);
unlink(FIFO_FILE_1);
unlink(FIFO_FILE_2);
return 0;
}
client.cpp:
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#include <wait.h>
#include <string.h>
#define FIFO_FILE_1 "/tmp/client_to_server_fifo"
#define FIFO_FILE_2 "/tmp/server_to_client_fifo"
int main()
{
system("clear");
int client_to_server;
int server_to_client;
char str[140];
printf("Input message to server: ");
scanf("%139[^\r\n]", str);
/* write str to the FIFO */
client_to_server = open(FIFO_FILE_1, O_WRONLY);
server_to_client = open(FIFO_FILE_2, O_RDONLY);
if(write(client_to_server, str, sizeof(str)) < 0){
perror("Write:");//print error
exit(-1);
}
if(read(server_to_client,str,sizeof(str)) < 0){
perror("Read:"); //error check
exit(-1);
}
printf("\n...received from the server: %s\n\n\n",str);
close(client_to_server);
close(server_to_client);
/* remove the FIFO */
return 0;
}
close(client_to_server);
close(server_to_client);
Remove these lines from while loop because when server has done its work for the first time it will close the pipe and you cant be able to proceed further in pipes.

Using pipe in Eclipse

I'm trying to compile my code in Eclipse
But it wouldnt compile my pipe use.
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <syslog.h>
#include <signal.h>
#include <map>
#include <string>
#include <iostream>
#include <sstream>
#include <fstream>
#include <sys/wait.h>
using namespace std;
int OpenPipeRead(string sinterface)
{
int ret_val,errno;
string lpipename="",lpipepath="";
lpipepath = mconfig[C_PIPEPATH];
lpipename.append(lpipepath); //Its not empty only when there is argument for parallal telepath_sniff instances.
lpipename.append(mconfig[C_PIPENAME]);
if(strcmp(sinterface.c_str(), "") != 0)
lpipename.append("_" + sinterface);
printf("Trying to open Pipe for reading\n");
syslog(LOG_INFO, "Try to open Pipe for reading\n");
/* Create the named - pipe */
ret_val = mkfifo(lpipename.c_str(), 0666);
if ((ret_val == -1) && (errno != EEXIST)) {
perror("Error creating the named pipe");
syslog(LOG_ERR, "Error creating the named pipe");
exit(1);
}
if((pipehandler = open(lpipename.c_str(), O_RDWR)) < 1) /* Open the pipe for reading and writing , in append mode */
{
perror("Failed to open pipe file");
syslog(LOG_ERR, "Failed to open pipe file");
exit(1);
}
printf("Pipe opened.\n");
syslog(LOG_INFO, "Pipe opened.\n");
}
int main(){
OpenPipeRead("arg");
}
errors are :
../src/main.cpp:325: error: ‘EEXIST’ was not declared in this scope
../src/main.cpp:330: error: ‘O_RDWR’ was not declared in this scope
../src/main.cpp:330: error: ‘open’ was not declared in this scope
It does compile outside of Eclipse
Any includes or flags I need to compile with on Eclipse?
Thanks
The EEXIST MACRO is defined in asm-generic/errno-base.h and the O_RDWR Flag is defined in fcntl.h.
Add :
#include <asm-generic/errno-base.h>
#include <fcntl.h>
To the file containing OpenPipeRead definition and it should compile.