Using the exec() family to run the "cd" command - c

I know that cd is a shell built-in ,and I can run it by using system().
But is that possible to run the cd command by the exec() family, like execvp()?
Edit: And I just noticed that system("cd") is also meaningless。Thanks for the help of everyone.

exec loads an executable file and replaces the current program image with it. As you rightly noted, cd is not an executable file, but rather a shell builtin. So the executable that you want to run is the shell itself. This is of course what system() does for you, but if you want to be explicit about it, you can use exec:
execl("/bin/sh", "-c", "cd", (const char *)0);
Since this replaces your current process image, you should do this after fork()ing off a new process.
However, this entire procedure has absolutely no effect. If you want to change the directory in your current process, use chdir().

You're better off using int chdir(const char *path); found in unistd.h.

No it is not, and it would be of no use. chdir (the function that changes a process's current directory) only affects the process that calls it (and its children). It does not affect its parent in particular.
So execing cd has no point, since the process would exit immediately after having changed directories.
(You could exec something like bash -c cd /tmp if you really want to, but as I said, this is fruitless.)

While, as already stated system("cd xxx") wouldn't change your application current directory, it is not completely useless.
You can still use system exit status to know if changing your current directory to the one stated would succeed or not.
Similarly, if you like complex solutions, you could also do the same with fork/exec, either with exec'ing /bin/sh -c cd xxx or simply /bin/cd xxx with OSes that provide an independent cd executable.
I would however recommend this non overkill faster equivalent access("xxx", X_OK|R_OK)
Note: All POSIX compliant OSes must provide an independent cd executable. This is at least the case with Solaris, AIX, HP-UX and Mac OS/X.

When a fork is done the environment variable CWD(current working directory) is inherited by the child from the parent.If fork and exec is done as usual then the child calls chdir() which simply changes the directory to the new directory and exits but this does not affect the parent.Hence, the new environment is lost..

Related

What does "/bin/sh" stand for in execlp command?

I want to execute a shell command with execlp, I tried with the following instruction :
execlp("sh", "sh", "-c", p_command, (char*)NULL);
p_command is a pointer to a const char representing a shell command line.
My minimal test tells me the program succeded as expected. I first choose to use "/bin/sh" instead of "sh" but I've learned that p(ath) in execlp allows us to avoid writing the full path, as if exec will complete the path for us ; so I removed "/bin/".
My concern is that I never saw a code using execlp with only "sh", as it effectively does for exemple for ls we can directly use "ls" instead of "/bin/ls".
As a beginner I am wondering what "/bin/sh" stands for, what is the difference between "sh" and "/bin/sh" in this situation and why we have to write the full path for execlp to execute a shell ?
When the path passed to execlp is sh, execlp searches for it in the directories listed in the PATH environment variable. If an attacker is able to modify the PATH variable in the environment that runs your program, they can set it to list a directory of their choosing, and they can place their own program named sh in that directory. Then your program will execute their program instead of executing the system sh program. In some cases (depending on a bit in the file’s mode bits), programs are executed with the permissions of their owners rather than the permissions of the user executing the program. Such programs must be written carefully to avoid situations like this, where an attacker would be able to exploit the program.
When the path passed to execlp is /bin/sh, execlp looks for it in the path that is /bin/sh starting from the root of the file system, called /. This will always use the sh program that the system administrator has put in the /bin directory (usually done as part of system installation).

How to execute commands in chroot?

In my source code I make chroot and then have some code doing some staff then I want to execute linux command. But the command does not work since I changed the root with chroot.
here after the source code:
int main(void)
{
if (chroot("/tmp") < 0)
printf("error in chroot\n");
/* some source code doing staffs */
system("ls > /logloglog.txt"); // command failed
return 0;
}
How to execute command in chroot?
Or is it possible to exit from chrood then execute the command and then back to the chroot again?
If you use chroot(), you have to consider the consequences of what you do. One of the major consequences is that many (most, all) of the commands normally available are not available unless you make them available in the chroot()'d environment.
Doing that job properly is non-trivial. You may need parts of /dev, /bin, /etc, /usr, /lib (and probably others too) installed appropriately under the new root directory. Symlinks back to 'outside the chroot() environment' won't work, in general. You have to make copies of what's important. One side effect of all this: /tmp is very rarely an appropriate place to create a fully operational chroot() environment. You might get away with a limited access sub-directory under /tmp, but putting a user in /tmp doesn't isolate them from other users, or other users from them, very well.
One other major possibility: you do not give the user access to other commands after you've done chroot(). That is, you do not try to use system() in your code; and you don't give the victim user access to a shell or shell utilities.
Using chroot() is not something you do casually, in other words. To do a good job takes quite a lot of careful thought and preparation.
Would you be better off with a container or virtual machine of some sort instead?
Do use Google or any other search engine to search for terms such as:
'chroot jail escape'
'chroot jail setup'
'chroot jail vs docker'
Is it possible to exit from chroot then execute the command and then back to the chroot again?
Not really. You might be able have a controlling program that forks a child that does chroot() and processes material and then terminates, so that the controlling program can do its job (execute the command) and then you could fork another child that goes back into the chroot() jail. But that's not the same as the current process getting out of jail — it would make chroot() totally ineffective if any program could cancel its jail time on a whim and resume unjailed activity.
What about:
system("chroot /tmp /bin/bash -c \"<COMMAND>\"");
You can just run chroot using system directly and with -c execute command inside /tmp environment

Need to get C program name inside shell script

I have an occasion where a C program invokes a shell script, which in-turn does some copying stuff from the CD mount location to an installation directory.
Now my question is that, is there a straightforward approach to get the absolute path of this C program inside this shell script ?.
I tried a couple of approaches that includes using "$(ps -o comm= $PPID)" from within the script, but nothing did work out till now. I know that I can create a temporary file from the C program which contains its own name (argv[0]) and then make the shell script to read that file, but I don't want to follow that approach here.
Of course, it can be passed as an argument to the script, but I was thinking why the bash built-in macros or something cannot be used here
On linux there is a /proc/self/exe path that points the absolute path of the current executed file. So you can push an environment variable that contains the path before spawning the shell. Something like:
readlink("/proc/self/exe",...,buf);
putenv("MYEXE",buf);
system("thescript");
and accessing the variable in the script:
echo $MYEXE
Before running a foo command you could use which like
fooprog=$(which foo)
to get the full path of the program (scanning your $PATH). For example which ls could give /bin/ls ....
On Linux specifically you could use proc(5).
In your shell process (running bash or some POSIX compliant shell) started by your C program, $PPID give the parent process id, hopefully the pid of the process running your C program.
Then the executable is /proc/$PPID/exe which is a symbolic link. Try for example the ls -l /proc/$PPID/exe command in some terminal.
(notice that you don't run C source files or stricto sensu C programs, you often run some ELF executable which was built by compiling C code)
You might have weird cases (you'll often ignore them, but you might decide to handle them). Someone might move or replace or remove your executable while it is running. Or the parent process (your executable) died prematurely, so the shell process becomes orphan. Or the executable removed itself.

Is that command valid in C?

I want to change directory in unix using code in a C file.I tried this:
char command[50];
strcpy( command, "cd newdirectory/" );
system(command);
but it didn't work.Other commands using "system" work.
To change directory try to use chdir. A related question is How to change the working directory in C?. About using system see Why can't we change directories through system() system call in Linux? and Changing the current directory in Linux using C++.
your command would work, but only within the system() call. e.g.: if you do system("cd newdirectory && rm foo");, rm foo will happen in newdirectory.
That's because the system() call does an fork() where you change the environment, but when it gets back to your calling program, you get back to your original environment.
To change the directory of your current process, you have to follow user1929959's answer: i.e. usinc the chdir() system call.

how to change directory using exec command from C program?

I have to change working directory from my C program. For this I have used the following command:
execl("/bin/cd","cd","..",(char*)0);
but this command is not changing the directory?
Is anything wrong in this command or is there any other way to change working directory from C program?
To change the current directory you should use chdir:
int chdir(const char *path);
On success it returns 0.
You can't use execl for several reasons:
cd is typically a shell builtin command;
on most systems /bin/cd does not exists; on the very very few systems that have it, it changes the current directory and then spawns a child shell process;
the current directory is a process' property: if you change the current directory using /bin/cd, you'd lose the directory change as soon as the process terminates;
if you use a function from the exec family, the current process image is replaced with a new process image - you could use system, but wouldn't fix the previous 3 problems.
What you are doing won't work because the exec family of calls will actually replace your current program in the current process. In other words, you will have been terminated so that, when cd is finished, your parent process will once again take over.
If you want to change the working directory for the current process, use chdir. If you want to change it on exit, you're out of luck because your program itself is running in a separate process from the parent that started it.
So, unless you have some form of communication with the parent, that's not going to work.
You need to use the chdir system call to change the working directory of the calling process.

Resources