1

Understanding the Linux Kernel says about the implementation of execve():

do_execve( ) performs the following operations:

  1. Dynamically allocates a linux_binprm data structure, which will be filled with data concerning the new executable file.

  2. Invokes path_lookup(), dentry_open(), and path_release() to get the dentry object, the file object, and the inode object associated with the executable file. On failure, it returns the proper error code.

  3. Verifies that the file is executable by the current process; also, checks that the file is not being written by looking at the i_writecount field of the inode; stores –1 in that field to forbid further write accesses.

  4. In multiprocessor systems, it invokes the sched_exec() function to determine the least loaded CPU that can execute the new program and to migrate the current process to it (see Chapter 7).

  5. Invokes init_new_context() to check whether the current process was using a custom Local Descriptor Table (see the section “The Linux LDTs” in Chapter 2); in this case, the function allocates and fills a new LDT to be used by the new program.

  6. Invokes the prepare_binprm( ) function to fill the linux_binprm data structure. This function, in turn, performs the following operations:

    a. Checks again whether the file is executable (at least one execute access right is set); if not, returns an error code. (The previous check in step 3 is not sufficient because a process with the CAP_DAC_OVERRIDE capability set always satisfies the check; see the section “Process Credentials and Capabilities” earlier in this chapter).

...

Do step 3 and step 6a both perform verification check that the execution permission bit of the executable file is set for the process?

What are their differences and relations?

Does step 3 not take into account the CAP_DAC_OVERRIDE capacity of the process, while step 6a does? Is this the only difference between the two steps?

Why do we need the two-step check, instead of one-step check by lumping all the check into step 3 or step 6a?

Thanks.

Tim
  • 1
  • 141
  • 372
  • 590

1 Answers1

0

You can and should read the kernel source itself (this is in fs/exec.c). Steps 2 and 3 are basically invoking the common open function with special EXEC flags "open file with intent to execute", whereas the second check is part of a series of checks "what rights should the new process have".

so to the more specific bits:

  • what is this supposed to prevent? => probably root executing non-executable binaries by mistake
  • why not do the check in 3? => this is reusing a more general operation -open with flags-, that operation should succeed if you have the capability for it
  • why not do all the checking in 6? => 3 does many additional checks that would be impractical here, like "are we on a noexec mounted fs?"

Anyway, your question is a bit too open, not sure my answer will satisfy you. Do go and read the kernel source instead. :-)