How to execute shell command inside a chroot jail - c

I have a problem with the execution of shell commands inside a chroot jail. Here is an exemple:
#include <stdio.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
int main()
{
if (geteuid() == 0) // check root privileges
{
chroot("/bin");
chdir("/");
execl("/ls", "ls", "-l", (char *) NULL); // "/ls" should be equivalent to "/bin/ls"
perror(strerror(errno));
}
else
printf("Permission denied\n");
return 0;
}
The problem is the exec: according to errno, the error is "No such file or directory".
The same error appears if I use exec("/bin/ls", ...)
I think that "ls" cannot use the shared libraries he needs, because of chroot jail.
Any suggestion to solve this problem?

You're probably right regarding shared libraries being inaccessible. Setting up a chroot jail typically involves copying parts of /bin, /usr/bin, /lib, and /usr/lib into a parallel directory structure.
A simpler alternative is to use only statically linked executables. On many linux systems there will be a statically linked executable called busybox that provides the base functionality of many Unix commands including ls. Invoking it like busybox ls -l provides similar output to the regular ls program without needed to access addition shared libraries outside the chroot jail.

Related

compilation in temporary directory/file with gcc in C program

I recently discovered the mkstemp() function (see this link) but it does not fully meet my need which would be to compile temporary .o files (with gcc -c script.c for example) and can only be accessed by the PID of the current program (and destroyed once it is stopped). Do you know if that is possible ?
One of the solutions could also be to create a directory in /tmp only accessible by the program much like the systemd-private-* directories system.
the program starts like this:
#include <sys/types.h>
#include <unistd.h>
int main(int argc, char *argv[]){
printf("pid=%d\n", getpid());
/* for create .o in tmp file, but i dont know how to but
I don't know how to create/configure "systemd-***" directory
or if it is possible to directly create a temporary file*/
/* the ideal would be not to have to create a special user,
which would give rights specifically to the directory/file */
int ret = system("gcc -c script.c -o /tmp/systemd-private-script/script.o");
...
return(0);
}
Thanks for you help
On linux, yes. using open with the O_TMPFILE and O_EXCL flags, you use the posix_spawn api instead of system(). make gcc ouput to the stdout, which is connected to the open fd.
After you are done close the fd and it will vanish, it can never be accessed by anyone as it is not materialized on the filesystem.

Is there a way in C to copy all the files of a directory to another directory?

I'm hoping not to resort to reading and writing of every file. Isn't there any other approach to this which might be a little shorter and easier?
I'm looking to do this on a linux machine.
Use system()
system() is used to invoke an operating system command from a C/C++
program.
On windows:
#include <stdlib.h>
int main()
{
return system("copy .\\CopyFrom\\* .\\CopyTo");
}
Compile and run. VoilĂ !
On linux you'd do something like
return system("cp ./CopyFrom/* ./CopyTo");

Execlp vs Execl

Is there any occasion in which is better to use execl instead of execlp?
I think that maybe when a program is in two different folders using execlp could lead to confusion but I don't know if it is the only case.
I ask because one could think that writing execlp("ls", ...) is easier than writing execl("/bin/ls", ...).
Security
Looking programs up via PATH is convenient, but it can also be insecure. If a directory in a user's PATH is world writable, it's possible to inject a malicious program into the PATH lookup. This would affect execlp but not execl.
For example, if you had a PATH like /foo/bar/bin:/home/you/bin:/usr/bin:/bin and /foo/bar/bin was world writable, someone with access to that machine could copy a malicious program to /foo/bar/bin/ls. Then executing ls would run /foo/bar/bin/ls rather than /bin/ls. They'd be able to execute commands as you and gain greater access.
For this reason, it's often a good idea to refer to specific executables in known locations. Or to hard wire a secure PATH in the executable.
Compatibility
While there is a common set of Unix commands and features specified by POSIX, many programs rely on extensions. If your program uses those extensions, grabbing the first one in the PATH might not be a good idea.
For example, here on OS X the installed utilities in /bin and /usr/bin are BSD-flavored. But I have GNU versions installed earlier in my PATH. A program designed to run on OS X would want to explicitly use, for example, /bin/ls or /usr/bin/tar to be sure they get a known version of those utilities.
$ /usr/bin/tar --version
bsdtar 2.8.3 - libarchive 2.8.3
$ tar --version
tar (GNU tar) 1.29
Both execl() and execlp() work fine and similarly if your executables are in different folders or in the same folder, but you need to set the $PATH if different folders.
execl() is needed for executing executables (like ls) from command line as you can't go with execlp() in that case. I added a snapshot below.
#include <stdio.h>
#include <unistd.h>
int main(int argc, char *argv[]) {
if (argc != 2) {
printf("Usage Msg: ./a.out userdefined_executable\n");
return;
}
//execl(argv[1], argv[1], NULL); // it works
execlp(argv[1], argv[1], NULL); // it doesn't work
return 0;
}
// Input will be like this, here "p1" is an user-defined executable.
// xyz#xyz:~/stack_overflow$ ./a.out p1

Building a shell in C on Ubuntu using execvp

I'm about to write a simple shell in C on Ubuntu.
I thought about using the exevcp() function.
I'm only able to run the "ls" command, none of the other commands seems to work.
Can someone tell me why is it happening or give me an idea of a better way to build the shell?
My purpose is to build this shell; I don't understand why can't I just take the command line, and put it as it is, into the execvp() function.
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
#include <errno.h>
int main(int argc,char **argv,char **envp)
{
char* args[] = {"history" , NULL};
execvp(args[0],args);
}
Can you explain to me, please?
exec(3) can only be used to run external programs. history is a built-in in most shells, and cannot be run this way.
The execvp() system call has two arguments: the name of the program to be executed, and a pointer to a null-terminated list of strings that are the arguments to the command.
For example:
char *args[] = { "ls", "-l", "-t", "-r", ".", 0 };
execvp(args[0], args);
...report error...
You can't simply pass a whole string into execvp() and expect it to split it up; the invoking code must do that. Note that if string pointed at by the first argument to execvp() contains a slash, then the $PATH mechanism is not used to find the command. A plain name (as shown, "ls") is searched using $PATH.
You also have to remember that some commands, such as history and cd, are shell built-ins; there is no external executable that you can run to get the same effect You won't be able to run those. Other commands, such as test (aka [) are usually implemented as built-ins, but there's also usually a binary in /bin or /usr/bin that does (more or less) the same job, which you can therefore invoke.

How to use chroot function in C programming?

I know that use the command "chroot" in linux need some files or directories such as usr, bin and so on. But when I use the function chroot() in C, do I need these files?
Here is my code, which "hw.out" is a binary file which just print "Hello, world". I compiled it and run it as root, but it was failed to print "Hello, world". What else should I do? Thank you!
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
int result = chroot(".");
if(result == 0)
printf("Chroot Succese.\n");
char *arrays[]={"./hw.out",NULL};
execvp("./hw.out", arrays);
return 0;
}
execvp is most likely failing, probably with ENOENT: no such file or directory, if hw.out is a dynamically linked executable.
For that to work, all the libraries required by hw.out need to be findable in the chrooted environment.
Try linking hw.out statically, and it should work. (And add error checking after execvp to see what errno is set to after the call if it returns.)
Please test that your hw.out works with command line chroot.
Perhaps hw.out is dynamically linked and is missing some libraries or ld-linux.so in the chroot directory.
Nitpicks 1, what's the point of return 0 after execvp? it never gets executed unless there is an error. I would rather have perror("can't exec"); return 1;
Nitpick 2, chroot() doesn't change working directory, although it works in your case, as you are chrooting to ".", it won't work as you expect if you later change it to chroot("somedir").
Make sure that hw.out is in the correct direct. Perhaps it is easier to have it statically linked if it is using libraries. Otherwise need to enable after chroot that it can access the dynamic libraries.

Resources