Suppose setuid/setgid bits are of no concern. Why is there a separate permission for execution?

Philosophically, it feels to me that the write permission subsumes the read permission, and that the read permission subsumes the execute permission. Of course, things aren't this way in Linux, and this can sometimes be useful, but I would reckon that it rarely is. For instance, if a process can read a file that isn't executable, then as long as that process can write in some directory, it can simply copy the file there, set the execute bit, and then run that program. So truly, read subsumes execute in simple cases. Obviously this isn't going to work properly if the source file has the setuid bit, or if the process can only write in noexec mount points.

The reason that I ask is that I'm implementing a Linux syscall that would allow a process to exec an arbitrary chunk of its memory. (The specific use case is that I have a full program bundled within my main program, and I don't want to write it to disk in order to call execve.) Are there any serious concerns with such a syscall that I should be aware of?

  • 2
    write-but-not-read allows for "dropbox" type edits, so write permission does not subsume read
    – thrig
    Aug 13 '17 at 17:07

As you surmise, the execute permission is rarely useful as a permission. Having it as a permission rather than an attribute of the file is a bit of a historical accident. However, since it exists, it isn't going to go away. Having an execute permission that's distinct from the read permission matters in two cases.

  • If executing a file confers additional privileges, then it matters who can execute that particular file. A setuid or setgid or setcap executable may be world-readable but not world-executable (many distributions make setxid files world-readable even if they aren't world-executable because they aren't confidential — anybody can download the file from the distribution's archives).
  • Some accounts may be restricted in such a way that they aren't allowed to write any content to an executable file. For example, an account may only have access to a restricted shell without chmod, or may only be allowed to write to directories on a filesystem that's mounted with noexec. Such a user is restricted to the executable files that already exist.

Adding a system call to exec from memory allows restricted accounts to execute arbitrary code. It's equivalent to having a native code interpreter that's accessible from everywhere, even restricted accounts. This wouldn't be accepted in the mainstream kernel since it would break security restrictions. You can deploy it on your own machines but you should keep the implications in mind.

However, it's a lot of work and a lot of security baggage to carry for a feature that already exists. It is possible to execute code without writing to disk. You just have to write the code to a file on a non-disk filesystem such as tmpfs.

  1. Ignoring the setuid / setgid, the one purpose of the execute bit is:

    • To allow a file with mode execute-only - execute access to a file which isn't read-able.
  2. Regarding the second part of your question - regarding the linux syscall you implement:

It seems like creating a new source of attack.

If you would like to get serious answer, you should provide details (preferred in a new question):

  • Which logic will you implement?
  • How will the data be copied to RAM?
  • Which checks will the API perform before execution the code in RAM?
  • Will the API be executed also by root (hence might allow privileged escalation)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.