umask and chmod unexpected behaviour - c

I am trying to write simple program that changes file privileges using umask and chmod system-calls, but file privileges do not change as expected.
This is what I've tried:
Set umask to 0;
If the file doesn't exist, it is created by open system-call using O_CREAT flag, and then privileges are set to mode passed by command-line argument;
If the file already exists, change its privileges by chmod system-call.
#define _XOPEN_SOURCE 700
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define check_error(expr, userMsg) \
do { \
if (!(expr)) { \
perror(userMsg); \
exit(EXIT_FAILURE); \
} \
} while(0)
int main(int argc, char** argv)
{
check_error(3 == argc, "use: ./umask path mode");
mode_t oldUmask = umask(0);
long mode = strtol(argv[2], NULL, 8);
int fd = open(argv[1], O_WRONLY|O_CREAT|O_EXCL, mode);
if (-1 == fd) {
if (EEXIST == errno) {
printf("[file already exists]\n");
check_error(-1 != chmod(argv[1], mode), "chmod failed");
} else {
perror("open failed");
exit(EXIT_FAILURE);
}
} else {
close(fd);
}
umask(oldUmask);
exit(EXIT_SUCCESS);
}
After compiling i tried:
./umask 1.txt 0744
Expected privileges would be -rwxr--r--, but after
ls -l
I get:
-rwxrwxrwx 1 root root 0 окт 19 14:06 1.txt
Again, after
./umask 1.txt 0744
this time I expected that chmod would internally change the privileges on existing file, but after listing I get the same:
[file already exists]
-rwxrwxrwx 1 root root 0 окт 19 14:06 1.txt
Both umask and chmod failed to set privileges as expected. What's wrong?

Files that I've created and tested the program on were created in a shared folder between Windows host machine and Linux virtual machine. I've started the program from Linux, trying to change the privileges of the file which I am not the owner of - it's Windows host machine, and that's why it doesn't let me change the privileges.

Related

Why after load seccomp filter, PING will no work by normal user

I use seccomp record 'ping' used syscall. When I run it, it always notice
socket: Operation not permitted.
I can run ping in bash very well, but no work after load seccomp filter in program.
But if I run the same program by root, it will run very well.
This is running in Ubuntu 18.04 with 4.15.0-54-generic kernel.
I have tried use Root user to run the program, then in the child progress, I use setuid(1000) to set to a normal user, and it still no work.
If I not use fork, it still notice no premitted.
If I change the seccomp default action to SCMP_ACT_ALLOW, it still no work too.
Here is a simple code by C.
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/resource.h>
#include <sys/time.h>
#include <signal.h>
#include <seccomp.h>
#include <unistd.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/time.h>
#include <sys/resource.h>
#include <sys/stat.h>
#include <sys/wait.h>
void child() {
setuid(1000);
scmp_filter_ctx ctx = seccomp_init(SCMP_ACT_LOG);
if (seccomp_load(ctx) != 0) {
printf("SCMP LAOD ERR!");
} else {
seccomp_release(ctx);
}
execl("/bin/ping", "ping", "-c", "1", "172.16.1.1", NULL);
printf("EXEC FAIL");
}
int main(){
int p = fork();
if (p < 0) {
printf("Frok ERROR!");
exit(1);
}
if ( p == 0 ) {
child();
} else {
struct rusage usage;
int status;
if (wait4(p, &status, WSTOPPED, &usage) == -1) {
kill(p, SIGKILL);
}
}
}
I use gcc main.c -o main.out -lseccomp to compile it.
English is not my first Language, I'm sorry about my grammar.
ping only works as root. Normally it runs as root because it has the setuid bit set in its file permissions:
-rwsr-xr-x 1 root root 44168 May 8 2014 /bin/ping
^ ^^^^
|
this 's' is called 'setuid' and means it wants to run as the user which owns it, which is root
You cannot use seccomp unless you are root, or you set the no_new_privs flag. You are not using seccomp directly, but through a library. It appears the library is setting the flag for you.
The no_new_privs flag means that you cannot run setuid programs. Well, you can run them, but they won't be setuid. They'll run as your user. Which doesn't have permission to send special packets the way ping requires. So ping fails because it doesn't have permission to ping.

In C mmap the file for write: Permission denied. Linux

This is my code:
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/mman.h>
int main()
{
int fd=open("/home/victor/hello",O_WRONLY);
if(fd<0)
{
perror("Open");
exit(EXIT_FAILURE);
}
struct stat sbuf;
if(fstat(fd, &sbuf)==-1){
perror("stat");
close(fd);
exit(EXIT_FAILURE);
}
void* file_memory= mmap(NULL, sbuf.st_size, PROT_WRITE, MAP_SHARED,fd,0);
if (file_memory == MAP_FAILED ) {
perror("Error mmapping the file");
close(fd);
exit(EXIT_FAILURE);
}
return 0;
}
I tried this too
int fd=open("/home/victor/hello",O_WRONLY|0777);
but it's the same error:
Error mmapping the file: Permission denied
Doing ls -l | grep hola
-rwxrwxrwx 1 victor victor 24 oct 24 01:47 hello
What's wrong?
From the glibc manual, and as already pointed out by R.. and Iwillnotexist Idonotexist above:
Note that most hardware designs cannot support write permission
without read permission, and many do not distinguish read and execute
permission. Thus, you may receive wider permissions than you ask for,
and mappings of write-only files may be denied even if you do not use
PROT_READ.
http://www.gnu.org/software/libc/manual/html_node/Memory_002dmapped-I_002fO.html

mkdir -p equivalent in C that creates nested directories recursively

I want to create a new directory inside a new directory. Something like this:
#include <stdio.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <errno.h>
#include <string.h>
int main() {
const char * path = "/home/abc/testabc1/testabc2" ;
mode_t mode = 0777;
if (mkdir(path, mode) == -1) {
// printf("Error occurred : %s ", strerror(errno));
perror("abc");
}
else {
printf("Directory created\n");
}
}
When I do this I get this error:
abc: No such file or directory
If I remove testabc2 then I am able to create the directory with success. Why so ?
You can only create directories in existing directories. If you want to do the equivalent of mkdir -p you have to do the same thing it does, namely create one directory after another from the top of the path down.
In your case, that means mkdir of /home/abc/testabc1 before mkdir of /home/abc/testabc1/testabc2.
Your error message is also misleading since perror("abc"); will prepend any error with "abc:". It has nothing to do with the directory "abc".

open() function with denied permission

I am trying to create a 'test.txt' file in root directory. Currently I am not a root user. my code is as follows:
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
int main(){
int fd;
fd=open("/test.txt",O_CREAT|O_RDWR|O_TRUNC,0777);
perror("error: ");
close(fd);
return 0;
}
however, when I compile and execute it, I get the error:
error: : Permission denied
how can I make my code to have the permission to create a file in root directory?
P.S. I am trying to make this work so that I can use it later on to apply this method to my linux daemon program.
fd=open("/test.txt",O_CREAT|O_RDWR|O_TRUNC,0777);
In this line specify path correctly.(i.e) It is current working directory means, keep (dot) . before / like./test.txt

open() not setting file permissions correctly [duplicate]

This question already has answers here:
Why are the file permissions changed when creating a file with the open system call on Linux?
(3 answers)
Closed 3 years ago.
I create a file using the code below:
#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <errno.h>
#include <fcntl.h>
#include <unistd.h>
int main()
{
const char* filename = "./test.out";
int fd;
if(-1 == (fd = open(filename, O_CREAT|O_RDWR, 0666)))
{
perror("Error");
errno = 0;
}
else
puts("File opened");
if(-1 == (close(fd)))
{
perror("Error");
errno = 0;
}
else
puts("File closed");
return 0;
}
I specify the mode argument as 0666, which should grant read,write access to everyone. However, an ls -l shows
-rw-r--r-- 1 kmehta users 0 2012-01-29 16:29 test.out
As you can see, write permissions are only granted to the owner of the file. I do not know why everyone else is not granted permissions correctly. chmod a+w test.out sets the permissions correctly though.
Code compiled as gcc -Wall test.c
Specs: gcc v 4.5.0 on Opensuse 11.3 64 bit
The mode argument to open specifies the maximum allowed permissions. The umask setting is then applied to further restrict the permissions.
If you need to make the permissions be 0666 specifically you will need to use fchmod on the file handle after the open succeeds or use umask to set the process’ permissions mask before the open.
Executing this code :
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
int main(void)
{
int fd;
if((fd = open("new.file",O_CREAT,S_IRWXU | S_IRWXG | S_IRWXO)) == -1)
{
perror("open");
return 1;
}
close(fd);
return 0;
}
on my Linux box, where umask returns 0022, gives me a file with the following attributes :
-rwxr-xr-x 1 daniel daniel 0 Jan 29 23:46 new.file
So, as you can see, the umask masks out the write bits in my case. It looks like it's the same on your system, too.

Resources