i would like to retrieve remote process input arguments programmatically,
so i used sysctl in the following manner (partial code) :
int mib[3]
mib = {CTL_KERN, KERN_ARGMAX,0,0}
size = sizeof(argmax);
if (sysctl(mib, 2, &argmax, &size, NULL, 0) == -1) {
goto ERROR_A;
}
procargs = (char *)malloc(argmax);
mib = {CTL_KERN,KERN_PROCARGS2,pid,0}
size = (size_t)argmax;
if (sysctl(mib, 3, procargs, &size, NULL, 0) == -1) {
printf("a");
goto ERROR_B;
}
however, i doesn't work for all processes.
here's is a working case :
/System/Library/Frameworks/CoreServices.framework/Frameworks/Metadata.framework/Versions/A/Support/mdworker -s mdworker -c MDSImporterWorker -m com.apple.mdworker.shared
but the case below failed on "sysctl(mib, 3, procargs, &size, NULL, 0)".
although, i successfully got the command line using 'ps ax PID' from terminal
0 655 501 0 10:55AM ttys008 0:00.02 login -pfl zohar81 /bin/bash -c exec -la bash /bin/bash
perhaps you can tell me why calling sysctl with KERN_PROCARGS2 failed in the second example ?
thanks
I discovered that on OS X, the process is granted access to KERN_PROCARGS2 for all processes when the owner of the executable is root and the the executable has the SUID (set-uid) flag enabled. The only exception is PID 0 (kernel_task) but that doesn't even have arguments.
You can make this work for your file using:
chmod u+s myprogram
sudo chown root:wheel myprogram
# now my program should be able to make get KERN_PROCARGS2 for all processes
./myprogram
Related
When I try to setuid in my program it creates 2 processes. One is a parent process and the other is a child process .
int isRoot()
{
if (getuid() != 0)
{
return 0;
}
else
{
return 1;
}
}
int main()
{
printf("%s \n \n",getUserName());
printf("%d\n",getuid());
if(!isRoot())
{
printf("This program must be run as root/sudo user!!");
exit(0);
}
seteuid(1000);
while (1) {}
printf("%s \n \n",getUserName());
}
When I check with ps command it show me two different processes:
sagar#sagar-desktop:~$ ps -aef | grep a.out
root 20293 18135 0 15:36 pts/7 00:00:00 sudo ./a.out
sagar 20294 20293 99 15:36 pts/7 00:00:17 ./a.out
Can anyone tell me why it is creating two process instead of one ?
You're mistaken. This is what sudo x does. It calls x as root in a new process and wait for it, hence the two processes.
No, there's only one copy of your process here.
root 20293 18135 0 15:36 pts/7 00:00:00 sudo ./a.out
This is sudo, not your process: the ./a.out is its command line args. It then spawns your process as a child process as you've noticed:
sagar 20294 20293 99 15:36 pts/7 00:00:17 ./a.out
My code(below) fails:
11:Resource temporarily unavailable
The code is running as root (in an abrt hook) but has seteuid to the user that the pid in question is running as.
Writing to /proc/self/coredump_filter from within the process works OK.
How can I write to the coredump_filter from the abrt hook?
void SetDumpFlags(pid_t pid, int dumpflags){
std::string c_filter_name = "/proc/" + std::to_string( pid ) + "/coredump_filter";
int f = open( c_filter_name.c_str(), O_WRONLY );
if (f < 0) {
fprintf( log, "Couldn't open %s\n", c_filter_name.c_str());
bail_out(1);
}
int wsz = write( f, &dumpflags, sizeof dumpflags);
if (wsz != sizeof dumpflags){
fprintf( log, "Couldn't write to %s, %d:%s\n", c_filter_name.c_str(),errno, strerror(errno));
close( f );
bail_out(1);
}
close( f );
fprintf( log, "Pid %d, dump filter set to 0x%x\n", pid, dumpflags);
}
I tried to replicate your problem with a C example
(I would use C++11 but I'm on an ancient netbook without C++11 and it'd be hard to get it here and aclimate in the language).
I got an EACCESS on the open (and my guess you might be getting it too but the errno could get overwritten elsewhere?).
It seems the coredump_filter (at least on this Linux 3.2) starts as owned by
root and the seteuid doesn't change it.
I tried chown before setuid to no avail.
What did work (as expected) was to open the fd while you're still root
and keep it open during the seteuid call.
Then I could write to the file again successfully even after my euid changed.
#include <unistd.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#define FLAGS "0x11"
#define FLAGSSZ (sizeof(FLAGS)-1)
int main()
{
pid_t pid = getpid();
char buf[sizeof("/proc/XXXXXXXXXXXXXX/coredump_filter")];
sprintf(buf,"/proc/%ld/coredump_filter",(long)pid);
int f;
if(0>(f=open(buf,O_WRONLY|O_TRUNC))) {perror("open");exit(1);}
if(FLAGSSZ != write(f,FLAGS,FLAGSSZ)){perror("write");exit(1);}
puts("ok");
char cat[sizeof("cat /proc/XXXXXXXXXXXXXX/coredump_filter")];
sprintf(cat,"cat /proc/%ld/coredump_filter", (long)pid);
system(cat);
char ls[sizeof("ls -l /proc/XXXXXXXXXXXXXX/coredump_filter")];
sprintf(ls,"ls -l /proc/%ld/coredump_filter", (long)pid);
system(ls); //owned by root, not writable by others
if(0>chown(buf,getuid(),getgid())){perror("chown"); exit(1); }
//chown returns success but ls -l doesn't agree
system(ls); //still owned by root
if(0>seteuid(getuid())){
perror("seteuid");
exit(1);
}
//can't reopen because of the perms but can still
//use the old fd if we kept it open
if(0>lseek(f,SEEK_SET,0)){perror("lseek"); exit(1);}
#define ALTFLAGS "0x22"
#define ALTFLAGSSZ (sizeof(ALTFLAGS)-1)
if(ALTFLAGSSZ != write(f,ALTFLAGS,ALTFLAGSSZ)){perror("write");exit(1);}
puts("ok");
system(cat);
}
I compiled with gcc c.c and made the a.out setuid root with sudo sh -c 'chown 0 $1 && chmod u+s $1' - a.out before running it.
I was trying to write data to the coredump_filter whereas I should have written a string! Doing it with a literal (e.g. #define FLAGS "0x11" as in the answer given by PSkocik ) fixes the problem.
The /proc/nnnnn/coredump_filter file is owned by the user that process nnnnn is running as. In my case this is root for some processes and another user for others. Switching user (in the abrt hook) to the appropriate user, before trying to write the coredump_filter, works OK.
Working on Linux am trying to build a Crash Handler function - so as before crashing we get stack trace in log file -
done some study and came to know,its done either using -g/-rdynamic Flags to generate debug info then use glibc backtrace / backtrace_symbols_fd functions to get stack trace ...
Its not much of use as in my app, am not allowed to use -g/-rdynamic flags ..
so reading further reading
I have build the following code which is not working as expected and in generated log file it ends in following error :
(gdb) Hangup detected on fd 0
error detected on stdin
A debugging session is active.
Inferior 1 [process 6625] will be detached.
Quit anyway? (y or n) [answered Y; input not from terminal]
Detaching from program: /u/vivek/demo/testprg, process 6625
Code:
Register a Crash Handler function at startup as -
struct sigaction act;
memset(&act, 0, sizeof (act));
act.sa_sigaction = ProcessCrash;
sigfillset (&act.sa_mask);
act.sa_flags = SA_SIGINFO;
sigaction (SIGSEGV, &act, NULL);
Following function called when my program receives SIGSEGV signal -
void ProcessCrash( int signal, siginfo_t * siginfo, void *context)
{
cerr <<"** ProcessCrash –Handler Function**" << endl;
ucontext_t *uc = (ucontext_t *)context;
if (signal == SIGSEGV)
fprintf(stderr, "\nGot signal %d, faulty address is %p, "
"from %p\n\n", signal, siginfo->si_addr,
uc->uc_mcontext.gregs[REG_RIP]); // REG_EIP is changed to REG_RIP for –m64 arch.
else
fprintf(stderr, "Got signal %d#92;\n", signal);
// [[ using GDB to pring the stack trace
char gdb[516];
// command 1
//sprintf(gdb, "echo 'where\ndetach' | gdb -q %.256s -pid %d > gdbTest.dump", program_invocation_name, getpid());
// command 2
sprintf(gdb, "(echo \"source Trace.txt\";cat) | gdb -q %.256s -pid %d > gdbTest.dump", program_invocation_name, getpid());
fprintf(stderr, "\n** GDB Command-> %s \n", gdb);
// output of above is
// ** GDB Command-> (echo "source Trace.txt";cat) | gdb -q /u/vivek/demo/testprg -pid 6625 > gdbTest.dump
// Run Either command 1 or command 2 but we get the same result
system(gdb);
// GDB test ]]
// Produce a core dump
abort();
return;
}
Trace.txt contents:
set logging on
where
detach
quit
Please let me know is there a way out of it ... as I am not getting ideas to overcome it ..
Not sure what you intended to do with the (echo \"source Trace.txt\";cat) | part.
Simply using gdb -batch -x Trace.txt -q %.256s -pid %d > gdbTest.dump works fine as far as I can tell.
I have the following code :
char command[256];
sprintf(command,"addr2line %p -e xcep_app", trace[i]);
addr2lineWriter = popen(command, "r");
if (addr2lineWriter == NULL)
flag = false;
if (flag == true) //execute parsing the output only if the command ran in the first place
{
while (fgets(addr2line_output, sizeof(addr2line_output)-1, addr2lineWriter) != NULL)
{
std::string addr2line_output_(addr2line_output);
complete_backtrace_.push_back(addr2line_output_);
}
pclose(addr2lineWriter);
}
Everything works fine, but I always get the following message :
sh: 1: Syntax error: word unexpected (expecting ")")
Why is it coming and how to stop it. also, what does it mean ?
I have the gnome terminal installed.
This is a guess based on the error message. trace[i] is NULL, so the command generated is:
addr2line (nil) -e xcep_app
And so the shell that is invoked to execute the command complains about the parentheses. #WumpusQ.Wumbley reports that ash will reproduce this message:
ash -c 'addr2line (nil) -e xcep_app'
I am trying to write a program in C (in Linux 64bit with GCC 4.1.2).
int program_instances(char *cmdname)
{
char buf[32], *ret;
char cmdbuf[512];
FILE *cmdpipe;
sprintf(cmdbuf, "/bin/ps -eo comm | /bin/grep -c '%s'",
cmdname);
cmdpipe = popen(cmdbuf, "r");
if (!cmdpipe)
{
return -1;
}
memset(buf, 0, sizeof(buf));
ret = fgets(buf, sizeof(buf), cmdpipe);
pclose(cmdpipe);
if (!ret)
{
return -1;
}
int nr = atoi(buf);
return nr;
}
Tried to debug the issue through gdb but after the line
sprintf(cmdbuf, "/bin/ps -eo comm | /bin/grep -c '%'",cmdname);
The programm is not crossing the above line , throwing the below lines..
Executing new program: /bin/bash
Error in re-setting breakpoint 1: No symbol table is loaded. Use the "file" command.
[New process 2437]
Executing new program: /bin/ps
Please help us to resolve this issue.
Try to compile your code with -g and remove -O [compiler flag]. When optimizing compiler(gcc) changes order of instructions to improve speed. After recompiling attach debugger again.