My very simple C program just hangs and I don’t know why.
I am trying to make a simple executable to handle multiple monotonous actions for me every time I start a new programming session.
So I decided with something simple (below) yet every time I run it, the app just hangs, never returns. So I have to Ctrl-C out of it. I have added printf commands to see if it goes anywhere, but those never appear.
My build command returns no error messages:
gcc -o tail tail.c
Just curious what I am missing.
#include <stdio.h>
#include <unistd.h>
int main() {
chdir("\\var\\www");
return 0;
}
There are at least two problems with the source code:
It is unlikely that you have a sub-directory called \var\www in your current directory — Ubuntu uses / and not \ for path separators.
Even if there was a sub-directory with the right name, your program would change directory to it but that wouldn't affect the calling program.
You should check the return value from chdir() — at minimum:
if (chdir("/var/www") != 0)
{
perror("chdir");
exit(EXIT_FAILURE);
}
And, as Max pointed out, calling your program by the name of a well-known utility such as tail is likely to lead to confusion. Use a different name.
Incidentally, don't use test as a program name either. That, too, will lead to confusion as it is a shell built-in as well as an executable in either /bin or /usr/bin. There is also a program /bin/cd or /usr/bin/cd on your machine — it will check that it can change directory, but won't affect the current directory of your shell. You have to invoke it explicitly by the full pathname to get it to run at all because cd is another shell built-in.
Two things:
First, that's not what Linux paths look like
Second, check the return value from chdir()
ie
if (chdir("/var/www") != 0)
printf("failed to change directory");
Finally, the effect of chdir() lasts for the duration of the program. It will not change the current directory of your shell once this program finishes.
The other answers adequately cover the issues in your C code. However, the reason you are seeing it hang is because you chose the name tail for your program.
In Linux, tail is a command in /usr/bin in most setups, and if you just type tail at the command line, the shell searches the $PATH first, and runs this. Without any parameters, it waits for input on its stdin. You can end it by pressing control-d to mark the end of file.
You can bypass the $PATH lookup by typing ./tail instead.
$ tail
[system tail]
$ ./tail
[tail in your current directory]
It is a good idea to use ./ as a habit, but you can also avoid confusion by not naming your program the same as common commands. Another name to avoid is test which is a shell built-in for testing various aspects of files, but appears to do nothing as it reports results in its system return code.
Related
I am wondering how to make a CLI app in C that "constantly runs". What i mean by that us for example i want to just open terminal and type a keyword and a function in a program executes. Like what "ls" is.
When you type ls it lists contents of the current dir. Likewise i want to make a program that when compiled it executes a certant stuff given the keyword is invoken. I dont want to run the executable with ./example, but rather have the command always available.The compiler i use is gcc. I have read that object file needs to be created but i dont know how to use that.
Thanks
What i mean by that us for example i want to just open terminal and type a keyword and a function in a program executes.
Your program doesn't have to "constantly run" in order for you to be able to invoke it without specifying the path... you just have to make sure that the program is located in one of the directories in your PATH, or conversely, that your PATH environment variable includes the directory where your program is located.
So let's say you want to compile hello.c into a command called hello. Here's the code:
#include <stdio.h>
int main(void)
{
printf("Hello, world!\n");
return 0;
}
So you'd compile that like:
> gcc -o hello hello.c
Now you should have an executable file called hello in your current directory, and you can run it like:
> ./hello
But you just want to type hello anywhere, right? So, you can add the current directory to your PATH environment variable, e.g.:
> export PATH=$PATH:$PWD
That adds the value of PWD, an environment variable that contains the current directory, to PATH, which is an environment variable that contains a list of directories where the shell will look for executable programs.
If you want to make that change permanent, you'll need to modify one of the scripts that runs when you start up whatever shell you're using. That's a little beyond the scope of this answer, and there's plenty of advice about how to set up your PATH online, so I'll leave that to you.
Another option, instead of adding the directory that contains hello to your PATH, is to move hello to one of the directories already listed in PATH. You can see the full list by doing this:
> echo $PATH
You haven't said what OS you're using, but if it's anything Unix-like there's probably a /usr/local/bin listed in there. .../bin directories generally hold executable programs, and /usr/local is the directory sub-tree where local additions to the OS go. So you could put your program in /usr/local/bin, and then (assuming /usr/local/bin is in your PATH), hello would always be available.
i have a C program that opens an mp3 and extract the jpg artwork in the same folder. If i execute this program with no root privileges i get a crash. If i execute it with sudo it works normally.
Now, i need another C programs who launch the previous program when it needs a jpg artwork for the selected mp3.
I tried to call popen("./firstProgram test.mp3" , "r") function or system("/(absolute path)/firstProgram test.mp3") function by calling them even with sudo in the command or not and either with relative or absolute paths. But no version seems to work.
How can i launch the first program from the second one with success?
Thanks!
fork and then use execl
char sudo[]="/usr/bin/sudo";
char pbin[]="/usr/local/bin/puppet";
NOTICE("running puppet: %s %s",sudo,pbin);
errno=0;
execl(sudo,sudo,pbin,(char *)NULL);
/* we should never get as far as this */
obviously I recommend reading man execl for further info
Unix (Linux) systems have contained a C Programming Manual in them since possibly forever. Look in Section 2, "System Calls".
This Wikipedia Page explains the Unix Manual "sections"
It is section 2 of the manual you can read about "System Calls"
Try the command: man 2 setuid
This will give you the manual for the setuid() system call which I think is what you want.
That manual page will also list references to other related system calls that may be what you want.
Remember when compiling C programs and using system calls that do low-level hardware access, to use the -O2, or -O3 option to gcc. There is a mention of it in the manual.
Ultimately the setuid() system call makes a running process started by one user change the UID of that running process to be running as some other user. (For example, you may see the Apache running as "apache", even though it was started by root).
setuid(0) lets you be root.
I have a C program that needs to run when I turn on my machine (Red Pitaya).
the beginning of the program presented here:
//my_test program
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include "redpitaya/rp.h"
int main(int argc, char **argv){
int jj=1;
while(1) {
printf("Ready for experiment number %i\n",jj);
int i, D;
int32_t TrigDly;
and so on...
the program is executable with a run.sh file called uri_test.sh, that contains the following:
cat /opt/redpitaya/fpga/fpga_0.94.bit>/dev/xdevcfg
LD_LIBRARY_PATH=/opt/redpitaya/lib ./my_test
both files are located in a directory under /root. the program is working perfectly when run manually on PuTTY terminal-
/RedPitaya/Examples/C/Uri# ./my_test
or
/RedPitaya/Examples/C/Uri# ./uri_test.sh
I tried to follow the solution presented here :
https://askubuntu.com/questions/9853/how-can-i-make-rc-local-run-on-startup
without success.
any suggestions? Thank you.
There are several ways to have a program running at startup, and it depends upon your init subsystem (are you using systemd or a SysV-style init?).
BTW, a source program in C is not a script and you generally compile it (using gcc -Wall -Wextra -g) into some executable. In your case, you probably want to set up its rpath at build time (in particular to avoid the LD_LIBRARY_PATH madness), perhaps by passing something like -Wl,-rpath,/opt/redpitaya/lib to your linking gcc command.
Perhaps a crontab(5) entry with #reboot could be enough.
Whatever way you are starting your program at startup time, it generally is the case that its stdin, stdout, stderr streams are redirected (e.g. to /dev/null, see null(4)) or not available. So it is likely that your printf output go nowhere. You might redirect stdout in your script, and I would recommend using syslog(3) in your C program, and logger(1) in your shell script (then look also into some *.log file under /var/log/). BTW, its environment is not the same as in some interactive shell (see environ(7)...), so your program is probably failing very early (perhaps at dynamic linking time, see ld-linux.so(8), since LD_LIBRARY_PATH might not be set to what you want it to be...).
You should consider handing program arguments in your C program (perhaps with getopt_long(3)) and might perhaps have some option (e.g. --daemonize) which would call daemon(3).
You certainly should read Advanced Linux Programming or something similar.
I recommend to first be able to successfully build then run some "hello-world" like program at startup which uses syslog(3). Later on, you could improve that program to make it work with your Red Pitaya thing.
I've been reading about IFS exploitation and LD_PRELOAD Privilege escalation by overriding functions. Although these are two completely different questions, I've decided to post them together and hope that isn't a problem. Though both of these are very old, I've been told that they can both still be used for privilege escalation and I would love to look into that. However, I've ran into some problems.
So, let's begin by making the SUID file, /tmp/suid.
#include <unistd.h>
int main() {
system("/bin/date");
}
This calls /bin/date. The idea is that we can change the internal field separator and deceive the file into running something else with the privileges that it currently holds. This can be done (or can it?) by making a new file called bin contain the malicious code that the attacker put in a custom location. Then we change the $PATH variable and make it so that locations are first searched inside our custom path, where our malicious fake binary is located. Then by changing the internal field separator to '/', instead of running /bin/date the program will run /tmp/fakepath/bin with argument date, which can potentially trigger privilege escalation.
When I attempt the method described dankalia.com, it fails. /bin/date gets executed instead. If I just type bin date into the console the malicious binary does get started, but it doesn't when it's being invoked through /tmp/suid.
I thought that the vulnerability is patched and that it simply ignores the IFS variable, but then a post on stackoverflow got me interested. (C: IFS System() Vulnerability). Can anyone confirm to me if this works or not, and what I am doing wrong? Thanks.
As for the LD_PRELOAD, I'll keep it rather simple.
define _GNU_SOURCE
#include <stdio.h>
int puts(const char *str) {
printf("lel");
}
Use the following command line to compile:
gcc –Wall –fPIC –shared –o puts.so puts.c –ldl
Then, override the function puts with preload tricks:
LD_PRELOAD=./puts.so ./vuln_program_that_uses_puts
This works quite well. However, when dealing with a SUID file and when we're talking about privilege escalation, this ain't happening. LD_PRELOAD doesn't work well with SUID files and for a good reason. I've been told that "you can get it to work but that it's hard". Ideas?
Thanks in advance, and sorry for the long questions.
I've been told that "you can get it to work but that it's hard". Ideas?
The operating system is wise to these sorts of tricks, and most are remediated now. Te general idea is setuid, sudo and friends don't use an unprivileged user's environment.
The following offers more reading:
suid-binary vulnerabilities
Breaking the links: Exploiting the linker
If all you want is a setuid binary to break into the system:
shutdown the computer
mount the hard drive
rename ls (or other program like date)
copy sudo to ls (or other program like date)
unmount and reboot
I'm just starting programming and going through K&R to try and learn C. I've gotten to the section on command line arguments (5.10) but now I'm stumped. Every time I try and open a program I've written with command line arguments I'm told that file X, X being the argument, doesn't exist.
`gcc -o find find.c
open find test
The file /Documents/Learning_C/test does not exist.`
Any suggestions? Thanks
What system are you on? In Unix/Linux you compile & run your executable via:
gcc -o find find.c
./find test
As others have noted, when you prefix your binary with "./", there wont be any naming conflicts. However, if you made find accessible in your $PATH, you might have some conflicts with find and test--standard programs with most *nix distributions... Maybe you could choose more specific names (i.e. ./myFind testArg)
Try giving your output executable a different name.
I suspect your executing the system find command which is looking for a directory called 'test'.
Or try forcing it by executing
./find toto
Edit: Prepending the ./ to the command is important because it tells the shell to execute the find in the current directory as opposed to the first 'find' that exists in your PATH. It is normally recommended that you don't have . (the current directory) in your PATH for security reasons.
HTH
P.S. Forgot to say good one for working through K&R. I just finished doing the same after working in C for thirty years and it was good to get back and refresh the mind!
Instead of making us all individually guess what exactly you're doing wrong, perhaps you should paste the program you're using for the illustration mentioned ?