23

I am trying to create a write only file in C on Linux (Ubuntu). This is my code:

 int fd2 = open ("/tmp/test.svg", O_RDWR|O_CREAT);

 if (fd2 != -1) {
   //....
 }

But why do the files I created have 'xr' mode? How can I create it so that I can open it myself at command prompt?

------xr--  1 michael michael  55788 2010-03-06 21:57 test.txt*
------xr--  1 michael michael   9703 2010-03-06 22:41 test.svg*
2
  • 4
    Awesome example of unsafe code. Commented Mar 7, 2010 at 7:27
  • 2
    @Michael Foukarakis: temporarily, there are bigger problems to deal with, but you're right. O_EXCL should be added (to avoid following malicious broken symlinks, and to avoid clobbering other people's file when they're running the same program on the same machine); the fixed name will be problematic in production code, so it should be using 'mkstemp()' or a relative to create the file name. And the list goes on, no doubt. Commented Mar 7, 2010 at 7:30

2 Answers 2

37

You need the three-argument form of open() when you specify O_CREAT. When you omit the third argument, open() uses whatever value happens to be on the stack where the third argument was expected; this is seldom a coherent set of permissions (in your example, it appears that decimal 12 = octal 014 was on the stack).

The third argument is the permissions on the file - which will be modified by the umask() value.

int fd2 = open("/tmp/test.svg", O_RDWR | O_CREAT, S_IRUSR | S_IRGRP | S_IROTH);

Note that you can create a file without write permissions (to anyone else, or any other process) while still being able to write to it from the current process. There is seldom a need to use execute bits on files created from a program - unless you are writing a compiler (and '.svg' files are not normally executables!).

The S_xxxx flags come from <sys/stat.h> and <fcntl.h> — you can use either header to get the information (but open() itself is declared in <fcntl.h>).

Note that the fixed file name and the absence of protective options such as O_EXCL make even the revised open() call somewhat unsafe.

Sign up to request clarification or add additional context in comments.

6 Comments

If you have recent versions of both the glibc headers and gcc, gcc can warn you about leaving out that third argument to open.
@Jonathan: is there something wrong in what i have posted? You have mentioned about following malicious broken symlinks and problem with fixed name in production code. What/why are these problems?
@nvl: Let's say that two users, bill and joe, both run your program at the same time. Both create a file /tmp/test.svg...whose data is used? Let's say Mr Malicious works on your machine, and manages to do: ln -s /etc/passwd /tmp/test.svg. Now one of two things is going to happen when your program runs: (1) you get an open error because you can't write to /etc/passwd (you aren't root), or (2) you get a copy of your SVG image in /etc/passwd because you are root. Neither is normally considered desirable. And Mr Malicious can also do: ln -s /usr/lib/security/libmalpam.so /tmp/test.svg...
@nvl: ...where libmalpam.so doesn't yet exist; if your code leaves that publicly writable, then the bad guy has a chance to create a shared library in the PAM (pluggable authentication module) area, which can then, perhaps, be leveraged. Etc. So, not being careful with how you open files can lead to all sorts of problems. This assumes root is inveigled into running your code, of course. If it is someone else, then they won't be able to do any damage...probably.
@nvl The fopen is a buffered C Library "high-level" function, versus the open which is an OS syscall (man 2 intro). See Secure Programming for Linux and Unix HOWTO dwheeler.com/secure-programs for details about secure programming.
|
1

Give access permissions as the third parameter:

int fd2 = open("/tmp/test.svg", O_RDWR|O_CREAT, 0777);  // Originally 777 (see comments)

if (fd2 != -1) {
    // use file descriptor
    close(fd2);
}

By doing this, all read, write and execute permissions will be given to user, group and others. Modify the 3rd parameter according to your use.

2 Comments

777 is not the same as S_IRWXU | S_IRWXG | S_IRWXO. 0x777 does happen to be the same, but is poor coding practice.
Note that neither 777 (decimal) nor 0x777 (hex) is the same as the normal 0777 (octal) or S_IRWXU | S_IRWXG | S_IRWXO that provides user, group and others with read, write and execute access on a file. So, the previous comment that "0x777 does happen to be the same" is erroneous. It corresponds to: r-xrwSrwt (SGID bit set, SVTX bit set, plus 0567 permissions, and I don't have the patience to write that out symbolically — it requires 7 terms or'd together).

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.