open() not setting file permissions correctly [duplicate] - c

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.

Related

umask and chmod unexpected behaviour

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.

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.

Linux C how to open a directory and get a file descriptor

#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <fcntl.h>
int main()
{
int fd;
if ((fd = open("/home/zhangke", O_DIRECTORY | O_RDWR)) ==-1)
{
printf("error %s\n", strerror(errno));
return -1;
}
return 0;
}
/home/zhangke is a directory and it exists. I get error Is a directory, so, how can I use open() to get a fd of a directory correctly?
Use O_RDONLY instead of O_RDWR as the access mode. From the open(2) error list:
EISDIR pathname refers to a directory and the access requested involved writing (that is, O_WRONLY or O_RDWR is set).
As far as I can tell, there's no way to create and open a directory atomically. The O_CREAT flag always creates a regular file. O_DIRECTORY is only meaningful when opening an existing name, it checks that the name refers to a directory.

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

Using MinGW how can I create a file without the read-only file attribute?

When I attempt to overwrite an existing file, I get a "permission denied" error.
I noticed that the file which is created has the "Read-only" attribute set. When I manually unset this I can then overwrite the file. Is there some flag I can pass to open() which will automatically unset this when I create a file?
Below is a bare bones example which illustrates the problem. The first run works, but the second produces the "permission denied" error.
Thanks,
Zach (New to MingW/Windows 7)
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <fcntl.h>
#include <errno.h>
int main(int argc, char ** argv) {
int fid;
double data = 12.0;
if ( (fid = open("junk.data", O_WRONLY | O_CREAT | O_BINARY)) == -1 ) {
printf("ERROR opening.\n\terror is:%s\n", strerror(errno));
return 1;
}
write(fid, &data, sizeof(double));
close(fid);
return 0;
}
I tried both 0644 and S_IRUSR | S_IWUSR (with sys/stat.h included) and either works.
Make sure that you actually add it as third argument of open, instead as new term into the surrounding parentheses (as happened for me first, and compiles just fine)
open has a three-parameter variant:
int open(const char *pathname, int flags, mode_t mode);
That third parameter allows you to specify the mode bits on Unix-type systems, but should be enough to set minimal r/w permissions on windows. (Check out the man page for details.)

Resources