my question is super beginner! In my C program, I want to set the SUID bit (root permission) before creating a raw socket and then I want to switch back to normal permission after I have created it. Before I used to run my code using command sudo ./client which gave the whole executable root permissions. I want to give root permissions only to the point where I create the socket, so that I can run my code using simply ./client.
EDIT: Realized that I have to set the SUID bit and not the sticky bit for how I want the executable to behave.
The original version of the question was confusing the sticky bit (S_ISVTX) with the SUID or set UID bit (S_ISUID). It has since been updated.
To make the program run with root privileges while creating the raw socket, you would create your executable by compiling it as normal, and then have root take ownership of the executable (chown root ./client) and set the permissions (chmod 4555 ./client). Note that the permissions are carefully chosen and do not allow either group or others to write to the program (modify the executable). The fact that the owner, root, has no write permission does not stop root from writing to the file — though root won't want to change it often. Normally, root would copy the program to some directory where ordinary users cannot make changes. That might conceivably be /usr/local/bin, or it might be somewhere else.
Note that the permissions are set on the executable, not the source code (see the original version of the question), and must be set before the program is run.
Inside the program, after creating the raw socket, you could remove the root privileges, thereby avoiding many security issues in the code after that, by executing: setuid(getuid()). This changes the effective UID back to the same as the real UID. Note that the POSIX specification for setuid()
says:
If the process has appropriate privileges, setuid() shall set the real user ID, effective user ID, and the saved set-user-ID of the calling process to uid.
A program that is SUID to root has 'appropriate privileges'; there is no going back. Using seteuid()
(as originally suggested) would not be as safe as using setuid().
Related
I am coding a small piece of C program. Basically, in the folder will have to file: secret.txt and code.c. I want my user cannot use any means to directly print out the secret.txt in terminal by 'cat', 'head', etc. but they can read it from a C program.
How they can read it (in my C code):
if (<some conditional>){
system("\bin\cat secret.txt");
}
I have tried to set the permissions of secret.txt as 440, the executable code as 4711. The file secret.txt is owned by root:root. And normal user can execute the code. However, in the program, it keeps saying permission denied.
How can I do this?
It would be very difficult (and wouldn't make that much sense usually) to deny a specific program from reading a file.
In Linux, permissions work per user, so if the c program and cat run with the same (effective) user-id, they will have the same permissions (generally).
The best way to solve it, if I correctly understood your intentions, is to compile your program, chown it to root, and make it a setuid binary (meaning that it will run with the permissions of "root" and not "user"). This way, it will run as root and be able to access the file.
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
I'm writing a program in C that will have to check a configuration file every time it starts to set some variables.
At the first start of the program I suppose there won't be any configuration file, so I need to create it (with default settings).
I've been said configurations files of program belongs to the folder /etc, more specifically to a particular folder created on purpose for the program itself (i.e. /etc/myprog). Here comes the first question I should have asked: is it true? Why /etc?
In any case I tried to create that file using this:
open("/etc/myprog/myprog.conf", O_WRONLY | O_CREAT, 0644);
the open returns -1 and sets errno global variable to 2 (i.e. folder does not exist).
If I try to create the file straight inside /etc (therefore "/etc/myprog.conf" as first argument of the open) I get instead an errno set to 13 (i.e. permission denied).
Is there a way to grant my program permissions to write in /etc?
EDIT: I see most users are suggesting to use sudo. If possible I would have preferred to avoid this option as this file has to be created just once (at the first start). Maybe I should make 2 different executables? (e.g. myprog_bootstrap and myprog, having to run only the first one with sudo)
You need root privileges to create a file in /etc. Run your executable with sudo in front:
sudo executable_name
Another possibility might be to make your executable setuid. Your program would then call very appropriately the setreuid(2) system call.
However, be very careful. Programs like /bin/login (or /usr/bin/sudo itself) are coded this way, but any subtle error in your program opens a can of worms of security holes. So please be paranoid when writing such a code, and get it reviewed by someone else.
Perhaps a better approach might be to have your installation procedure make /etc/yourfile some symlink (created once at installation time to some writable file elsewhere) ....
BTW, you might create a group for your program, and make -at installation time- the /etc/yourfile writable to the group, and make your program setgid.
Or even, dedicate a user for your program, and have this /etc/yourfile belonging to that user.
Or, at installation time, have the /etc/myprog/ directory created and belonging to the appropriate user (or group) and being writable to that user (or group).
PS. Read also Advanced Linux Programming, capabilities(7), credentials(7) and execve(2)
I am trying to have an almost idiotproof configurator for network and some other stuff for embedded device running on linux. Application is saving to /etc/network/interfaces without problem when run by root, but returns "segmentation fault" when run by standard user. strace returned:
open("/etc/network/interfaces", O_WRONLY|O_CREAT|O_TRUNC, 0666) = -1 EACCES (Permission denied)
--- SIGSEGV {si_signo=SIGSEGV, si_code=SEGV_MAPERR, si_addr=0} ---
How can I allow it to be launched by anyone and write to /etc/network/interfaces ?
Code for saving to file:
FILE *saveFile;
saveFile = fopen("/etc/network/interfaces","w");
// loopback
fprintf(saveFile, "auto lo \niface lo inet loopback\n\n");
// eth0
fprintf(saveFile, "auto eth0\niface eth0 inet static\n\taddress %s\n\tnetmask %s\n\tgateway %s\n",
address,netmask,gateway);
fclose(saveFile);
How can I allow it to be launched by anyone and write to /etc/network/interfaces ?
Mmmmm... By giving write permissions to anyone on /etc/network/interfaces ?
After your comment, your requirement is to allow a non root user to do a particular administrative tasks that would require root priviledge. The traditional way would be to make the program owned by root and setuid. This is now a throwned upon way, because a setuid program (su or sudo are) should be thoroughly scrutinized for any potential security problem: a buffer overflow or other would allow execution of arbitrary code as root.
For your example, if it is a simple program, it could make sense, but at least the return value of every operation (fopen and fwrite here) should be tested!
The recommended way for that will now be to use sudo and set specific entries in the /etc/sudoers file to allow any user (or a specific list of groups and/or users) to execute that specific command as root. To achieve almost the same that a setuid command but prompt the user for his/her password to notice him/her of an administrative task:
ALL local_host_name = (root) /full/path/to/command
But the sudoers syntax allow much finer grained authorizations.
(Beware: you still have to twice control your code)
you can try something like this :
install sudo
create a new user
Give sudo permission for the new user only on your program.
This way, when people will try to execute any command other than your program,it will be refused.
Now, your program will run with sudo rigth, so make sure that your program cannot be modified or replaced by another program (like chmod 700 and chown root) and make sure your program will not mess /etc/network/interface
I am using Ubuntu Lucid Lynx
is it possible to write data in a file through a C program which has read only permission. If it's not possible, then is there any way to give sudo access to the C program.
For files without permissions, I would save the data in a string. Then i would open the file with write option:
FILE *fp = fopen(file_path,"w")
fputs(string,fp);
fclose(fp);
No you cannot write to a read-only file, that would undermine the whole point of read-only. As for giving root access to a c program, you could always run it as root or as someone who has permissions to modify the file.
If you are the owner of the file you can change the permissions with chmod. If you are not the owner you can use setuid bit to acces the file, but this really should be avoided.
It is not possible to have the program elevate itself to sudo status while its running.
And that is a bloody good thing.
If that was possible every virus would have the ability to take over any system.
The program needs to be started with the proper access-rights from the start.
In Unix generally what you'd want to do is make the program's executable owned by root, world executable, then set the SUID bit on it.
chown root filename
chmod 4775 filename
See chomd docs for exactly what the bits mean, but all together this means that whenever someone runs this executable, they get the executable process' user ID set to the owner's (root).
You can, but not in a standard cross-platform way.
On Unix systems, use chmod. It should be in <sys/stat.h>
See this link.
If you need root privilage, try:
if(fp == NULL)
execvp("sudo", argv);