The definition of the UNIX open() function when used with the O_CREAT flag is that it requires a third argument named mode in order to set the files' privileges.
What if that mode is not specified?
int file;
static const char filename[] = "test.test";
if ((file = open(filename, O_RDWR | O_CREAT | O_TRUNC)) == 1)
{
perror("Error opening file.");
exit(EXIT_FAILURE);
}
close(file);
What happens with the file that is created using those flags? On my system I get:
-r--r-s--- 1 hyperboreean hyperboreean 0 2009-02-25 01:40 test.test
A theory is that the open function looks on the stack and checks for the mode parameter and ends up using a random integer it finds.
What does the standard say about this?
O_CREAT. Indicates that the call to open() has a mode argument. If the file being opened already exists O_CREAT has no effect except when O_EXCL is also specified; see O_EXCL following. If the file being opened does not exist it is created.
Applications shall specify exactly one of the first three values (file access modes) below in the value of oflag: O_RDONLY. Open for reading only.
O_APPEND flag forces file pointer to point at the end of file only. so if you do lseek from start of the file, it takes the updated file pointer position as a start of file i.e. end position of old file.
The real meaning of O_EXCL is "error if create and file exists" but the name is derived from " EXCL usive", which is a bit misleading though and causes many people to misinterpret that flag. Opening a file with O_EXCL will not give you exclusive access to it as some people incorrectly assume.
The POSIX standard (IEEE 1003.1:2008) prototypes open()
as:
int open(const char *path, int oflag, ...);
The section describing the behaviour of O_CREAT
doesn't say what will happen if you omit the necessary third argument, which means the behaviour is undefined - anything is possible.
In practice, the use of part of the stack that was intended to be stack frame or return address or something similar is quite likely - unto a reasonable approximation, that can be considered a random integer.
The POSIX 2008 standard has some interesting new (and useful) flags for open()
, including:
O_FDCLOEXEC
to specify close-on-exec at open.O_DIRECTORY
to specify that the file must be a directory.O_NOFOLLOW
to specify not to chase symlinks.Good question. The mode
value will be modified by the umask
of the process. So if you don't pass a mode
explicitly to open
in an O_CREAT
operation, and if this results in random bits being used for the mode, those random bits will be modified by the umask
.
Wish I could be more definitive and precise, but I agree with cdonner that "random" values are being used, along with the umask
.
Edit: One thing you could try is to use dtruss or truss or some other facility to trace system calls, and look at the value of mode
at run-time to see if something sensible is used, or if it's just random bits modified by the umask
, for example.
hyperboreean, your suspicion may be not so far off the mark. I was hoping to find the answer in Kernighan Ritchie. Unfortunately, I did not. I think the permissions parameter is required with the O_CREAT flag, and if you don't provide it, open() will pull a random value from the stack, which of course goes unnoticed in C.
Edit: by "random" I mean not predictable. It probably is picking up part of the return address, which sits on top of the parameters on the stack.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With