I would like to execute one of my sudo commands through one of my C demon.
I use the command system(echo MYPASSWORD | sudo -v -S); in my C code.
It runs fine when I execute the demon. However, when I exit from the terminal it fails with a return value of 256.
Please suggest to me some alternate way to pass the password when the process is running in the backend.
Some SUDO versions use open("/dev/tty") to ensure that the password cannot be sent this way. You could do the following to avoid this:
int ptm=open("/dev/ptmx"....);
int pid=fork();
if(!pid)
{
close(0);
close(1);
close(2);
setsid();
unlockpt(...); grantpt(...);
pts=open(ptsname...);
execl(getenv("SHELL"),"sh","-c","sudo any_command",NULL);
exit(1);
}
// now the ptm file handle is used to send data
// to the process and to receive output from the process
waitpid(...);
When all ttys are closed, setsid() is called and a new tty is opened (here the /dev/ptsn) then the new tty becomes the /dev/tty for the process. This means: sudo will read the password from the pseudo-terminal.
EDIT
I just fixed a bug in my example: open("/dev/ptmx" ...) should be called before fork().
Another option is to execute sudo commands without a password. To do that you can open the file /etc/sudoers with your favourite editor and add this line at the end. Remember to change the yourname with the user name.
yourname ALL = (ALL) NOPASSWD: ALL
Related
I have a script where I launch a shell command. The problem is that the script doesn't wait until the command is finished and continues right away.
I have tried WAIT but it doesn't work as the shell command turns the source off and on (ignition off/on) and I get the error that WAIT cannot be executed because power is off.
Is there any command I can use for program to wait until the command is executed?
My script looks like this:
OS.COMMAND echo OUTP OFF > COM1
OS.COMMAND echo OUTP ON > COM1
System.up
If I would want to execute a shell command without redirecting I would use OS.Area instead of OS.Command, because OS.Area is blocking and will wait until the shell command has finished. However OS.Area does not support redirecting I think.
If I would want to execute a shell command and redirect the output to a file I would first delete the file and then wait until it gets accessible. Like this:
IF OS.FILE.EXIST("myfile.txt")
RM "myfile.txt"
OS.Command ECHO "Hello World" > "myfile.txt"
WAIT OS.FILE.readable("myfile.txt")
However it looks like you want to write via a shell command to a COM port on Windows. But I don't think it is possible to wait in TRACE32 until this write to the COM port has been done when using OS.Command...
So I suggest to do this task with the TERM commands instead:
TERM.METHOD #1 COM COM1 115200. 8 NONE 1STOP NONE
TERM.view #1
TERM.Out #1 "OUTP OFF" 0x0A
TERM.Out #1 "OUTP ON" 0x0A
Of course you have to set the correct baud rate, bits, parity and stop bits. The 0x0A after each TERM.Out is simply the line-feed character.
Does you terminal show any output as a reaction to OUTP ON? If yes you can also wait for this output with e.g. SCREEN.WAIT TERM.LINE(#1,-1)=="OUTP is now ON" 5.s
Otherwise I assume that a simple WAIT 50.ms before SYStem.Up will probably do the trick too.
The goal of this code is to create a stack trace whenever a sigterm/sigint/sigsegv/etc is caught. In order to not rely on memory management inside of the C++ code in the case of a sigsegv, I have decided to write a bash script that will receive the PID and memory addresses in the trace array.
The Sig events are being caught.
Below is where I generate the call to the bash script
trace_size = backtrace(trace, 16);
trace[1] = (void *)ctx->rsi;
messages = backtrace_symbols(trace, trace_size);
char syscom[356] = {0};
sprintf(syscom,"bash_crash_supp.sh %d", getpid());
for (i=1; i<(trace_size-1) && i < 10; ++i)
{
sprintf(syscom,"%s %p",syscom,trace[i]);
}
Below is where my issue arises. The command in syscom is generating correctly. I can stop the code before the following popen, run the command in a terminal, and it functions correctly.
However running the script directly from the c++ code does not seem to work.
setuid(0);
FILE *bashCommand = popen(syscom,"r");
char buf[256] = {0};
while(fgets(buf,sizeof(buf),bashCommand) != 0) {
LogMessage(LOG_WARNING, "%s\n", buf);
}
pclose(bashCommand);
exit(sig);
The purpose of the bash script is to get the offset from /proc/pid/maps, and then use that to run addr2line to get the file name/line number.
strResult=$(sudo cat /proc/"$1"/maps | grep "target_file" | grep -m 1 '[0-9a-fA-F]')
offset=$( cut -d '-' -f 1 <<< "$strResult");
However offset is getting 0 when I run from the c++ code, but when I run the exact same command (that is stored in syscom in the c++ code) in a terminal, I get the expected output.
I have been trying to fix this for a while. Permissions are most likely the issue, but I've tried to work around these with every way I know of/have seen via google. The user trying to run the script (currently running the c++ code) is apache.
The fix does not need to worry about the security of the box. If something as simple as "chmod 777 /proc -r" worked, that would have been the solution (sadly the OS doesn't let me mess do such commands with /proc).
Things I've already tried:
Adding `` around the command that's stored in syscom from the c++ code
chown the script to apache
chmod 4755 on the bash_crash_supp.sh script, allowing it to always fire as root.
I have added apache to sudoers (visudo), allowing them to run sudo without using a password
I have added a sub file to sudoers.d (just in case) that does the same as above
I have looked into objdump, however it does not give me either the offset or the file/line num for an addr (from what I can see)
I have setuid(0) in the c++ code to set the current user to root
Command generated in C++
bash_crash_supp.sh 25817 0x7f4bfe600ec8 0x7f4bf28f7400 0x7f4bf28f83c6 0x7f4bf2904f02 0x7f4bfdf0fbb0 0x7f4bfdf1346e 0x7f4bfdf1eb30 0x7f4bfdf1b9a8 0x7f4bfdf176b8
Params in bash:
25817 0x7f4bfe600ec8 0x7f4bf28f7400 0x7f4bf28f83c6 0x7f4bf2904f02 0x7f4bfdf0fbb0 0x7f4bfdf1346e 0x7f4bfdf1eb30 0x7f4bfdf1b9a8 0x7f4bfdf176b8
Can anyone think of any other ways to solve this?
Long story short, almost all Unix-based systems ignore setuid on any interpreted script (anything with a shebang #!) as a security precaution.
You may use setuid on actual executables, but not the shell scripts themselves. If you're willing to take a massive security risk, you can make a wrapper executable to run the shell script and give the executable setuid.
For more information, see this question on the Unix StackExchange: https://unix.stackexchange.com/a/2910
I'm working in a project with a quadrotor and mavlink. I have successfully installed mavproxy in my Ubuntu PC and and ran it without problems from terminal. When I run mavproxy.py from the terminal and connected a quadrotor with support for mavlink (APM autopilot), mavproxy detects the quadrotor and everything is ok.
When you execute mavproxy.py the program in the terminal begin to send and receive several parameters. You can write in the terminal some parameter to access for any configuration. For example, the command help in the terminal:
$ mavlink.py
.
.data beging
.
STABILIZE> "when the program finish the configuration, allowed to you for doing an input any parameter, for example help"
STABILIZE>help
show all helps.
I have a code to execute mavlink.py from C++
include <iostream>
include <stdio.h>
using namespace std;
int main() {
FILE *in;
char buff[512];
if(!(in = popen("mavlink.py", "r"))){
return 1;
}
while(fgets(buff, sizeof(buff), in)!=NULL){
cout << buff;
}
pclose(in);
return 0;
}
When I run this C++ program the terminal shows the same things that would appear if I were running mavproxy.py from the terminal, but I donĀ“t know how can I send a command such as help in the C++ code.
If you read the program, the while statement allows me to capture the parameters generated from the program mavproxy.py and cout in the terminal, but mavlink.py never ends until you write something in the terminal exit or press CTRL + C so the while loop never ends.
I have been reading about the Popen function, but I haven't found the correct form to do this.
I know that I can use the mavlink.h library in my program and send parameters to the quadrotor, but don't want do this with mavlink.h.
I am not sure I understand your question, but I think you want to send commands to mavlink.py as well as read its output.
If that is the case, you must change the open mode of popen() from "r" to "w" so you can write, then you can send commands to it like this:
FILE *fp;
char *command="HELP";
if(!(fp = popen("mavlink.py", "w"))){
return 1;
fwrite(command, sizeof(char), strlen(command), fp);
i have an interface where i use to execute the mml command in my solaris unix like below:
> eaw 0004
<RLTYP;
BSC SYSTEM TYPE DATA
GSYSTYPE
GSM1800
END
<
As soon as i do eaw <name> on the command line.It will start an interface where in i can execute mml commands and i can see the output of those commands executed.
My idea here is to parse the command output in c++.
I can do away with some logic for parsing.But to start with How can get the command to be executed inside c++ ? Is there any predefined way to do this.
This should be similar to executing sql queries inside c++.But we use other libraries to execute sql queries.I also donot want to run a shell script or create temporary files in between.
what i want is to execute the command inside c++ and get the output and even that in c++.
could anybody give me the right directions?
You have several options. From easiest and simplest to hardest and most complex to use:
Use the system() call to spawn a shell to run a command
Use the popen() call to spawn a subprocess and either write to its standard input stream or read from its standard output stream (but not both)
Use a combination of pipe(), fork(), dup()/dup2(), and exec*() to spawn a child process and set up pipes for a child process's standard input and output.
The below code is done with the sh command. This redirects stdout to a file named "out" which can be read later to process the output. Each command to the process can be written through the pipe.
#include <stdio.h>
int main()
{
FILE *fp;
fp = popen("sh > out", "w");
if (fp) {
fprintf(fp, "date\n");
fprintf(fp, "exit\n");
fclose(fp);
}
return 0;
}
I've got a GUI C++ program that takes a shell command from the user, calls forkpty() and execvp() to execute that command in a child process, while the parent (GUI) process reads the child process's stdout/stderr output and displays it in the GUI.
This all works nicely (under Linux and MacOS/X). For example, if the user enters "ls -l /foo", the GUI will display the contents of the /foo folder.
However, bash niceties like output redirection aren't handled. For example, if the user enters "echo bar > /foo/bar.txt", the child process will output the text "bar > /foo/bar.txt", instead of writing the text "bar" to the file "/foo/bar.txt".
Presumably this is because execvp() is running the executable command "echo" directly, instead of running /bin/bash and handing it the user's command to massage/preprocess.
My question is, what is the correct child process invocation to use, in order to make the system behave exactly as if the user had typed in his string at the bash prompt? I tried wrapping the user's command with a /bin/bash invocation, like this: /bin/bash -c the_string_the_user_entered, but that didn't seem to work. Any hints?
ps Just calling system() isn't a good option, since it would cause my GUI to block until the child process exits, and some child processes may not exit for a long time (if ever!)
If you want the shell to do the I/O redirection, you need to invoke the shell so it does the I/O redirection.
char *args[4];
args[0] = "bash";
args[1] = "-c";
args[2] = ...string containing command line with I/O redirection...;
args[4] = 0;
execv("/bin/bash", args);
Note the change from execvp() to execv(); you know where the shell is - at least, I gave it an absolute path - so the path-search is not relevant any more.