Deep dive into the Function Call API in Linux (security focused)

Draft

Did you ever wanted to know how core 0 reads core-specific registers from core 1 in Linux? If so, this blogpost will introduce it to you. We will dive into the Linux function call API and look into how a core can execute functions "remotely".

First of all the function call API is generic and the main source code can be found in /kernel/smp.c. As the location denotes, this is generic kernel code and can be used by different architectures. However, some code external functions, i.e., triggering IPIs, are architecture specific. The kernel exposes multiple external symbols to call functions remotely, denoted by the EXPORT_SYMBOL in the sourcecode.

Exposed Functions

  • smp_call_function_single
  • smp_call_function_many
  • smp_call_function_any

Execution Logic

We differentiate two cases: the single function call and the ones that target multiple CPUs. The latter functions call in the end the same low level function, __smp_call_function_many_cond. The internals work on a high level like the following:


// Pseudo-code logic representation
Check if we really need the complex logic (i.e., call it only on remote cores)
If we need the complex stuff:
    grab per_cpu data structure and add function and argument(s) to it
    enqueue the date structures in an execution queue of the target CPUs
    send IPI to the target CPUs to work through the queues
If local execution:
    execute the function locally
If we need the complex stuff:
    (optional) wait for completion of the target functions
                    
[email protected]