forked from Imagelibrary/seL4
SELFOUR-1016: Require auth cap to set prio/mcp
This fixes confused deputy problem when setting priorities/mcps.
This commit is contained in:
13
CHANGES
13
CHANGES
@@ -9,6 +9,8 @@ changes are added the compatibility information should be updated.
|
||||
|
||||
upcoming release BREAKING
|
||||
|
||||
BREAKING CHANGE
|
||||
|
||||
= Changes =
|
||||
* Debugging option on x86 for syscall interface to read/write MSRs (this is an, equally dangerous, alternative to
|
||||
dangerous code injection)
|
||||
@@ -27,6 +29,17 @@ upcoming release BREAKING
|
||||
* x86 TSC frequency exported in extended bootinfo header
|
||||
* `archInfo` is no longer a member of the bootinfo struct. Its only use was for TSC frequency on x86, which
|
||||
can now be retrieved through the extended bootinfo
|
||||
* Invocations to set thread priority and maximum control priority (MCP) have changed.
|
||||
- For both invocations, users must now provide a TCB capability `auth`
|
||||
- The requested MCP/priority is checked against the MCP of the `auth` capability.
|
||||
- Previous behavior checked against the invoked TCB, which could be subject to the confused deputy
|
||||
problem.
|
||||
* seL4_TCB_Configure no longer takes prio, mcp as an argument. Instead these fields must be set separately
|
||||
with seL4_TCB_SetPriority and seL4_TCB_SetMCPriority.
|
||||
|
||||
= Upgrade notes =
|
||||
* seL4_TCB_Configure calls that set priority should be changed to explicitly call seL4_TCB_SetPriority
|
||||
* seL4_TCB_Configure calls that set MCP should be changed to explicitly call seL4_TCB_SetMCPriority
|
||||
|
||||
---
|
||||
8.0.0 2018-01-17
|
||||
|
||||
@@ -99,15 +99,6 @@ wordFromMessageInfo(seL4_MessageInfo_t mi)
|
||||
return mi.words[0];
|
||||
}
|
||||
|
||||
static inline seL4_PrioProps_t CONST
|
||||
prioPropsFromWord(word_t w)
|
||||
{
|
||||
seL4_PrioProps_t pp;
|
||||
pp.words[0] = w;
|
||||
|
||||
return pp;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PRINTING
|
||||
#ifdef CONFIG_COLOUR_PRINTING
|
||||
#define ANSI_RESET "\033[0m"
|
||||
|
||||
@@ -96,8 +96,8 @@ exception_t decodeReadRegisters(cap_t cap, word_t length, bool_t call,
|
||||
exception_t decodeWriteRegisters(cap_t cap, word_t length, word_t *buffer);
|
||||
exception_t decodeTCBConfigure(cap_t cap, word_t length,
|
||||
cte_t* slot, extra_caps_t rootCaps, word_t *buffer);
|
||||
exception_t decodeSetPriority(cap_t cap, word_t length, word_t *buffer);
|
||||
exception_t decodeSetMCPriority(cap_t cap, word_t length, word_t *buffer);
|
||||
exception_t decodeSetPriority(cap_t cap, word_t length, extra_caps_t excaps, word_t *buffer);
|
||||
exception_t decodeSetMCPriority(cap_t cap, word_t length, extra_caps_t excaps, word_t *buffer);
|
||||
exception_t decodeSetIPCBuffer(cap_t cap, word_t length,
|
||||
cte_t* slot, extra_caps_t excaps, word_t *buffer);
|
||||
exception_t decodeSetSpace(cap_t cap, word_t length,
|
||||
@@ -112,7 +112,6 @@ enum thread_control_flag {
|
||||
thread_control_update_ipc_buffer = 0x2,
|
||||
thread_control_update_space = 0x4,
|
||||
thread_control_update_mcp = 0x8,
|
||||
thread_control_update_all = 0xF,
|
||||
};
|
||||
|
||||
typedef word_t thread_control_flag_t;
|
||||
|
||||
@@ -125,8 +125,6 @@
|
||||
</description>
|
||||
<param dir="in" name="fault_ep" type="seL4_Word"
|
||||
description="CPTR to the endpoint which receives IPCs when this thread faults. This capability is in the CSpace of the thread being configured."/>
|
||||
<param dir="in" name="priority" type="seL4_PrioProps_t"
|
||||
description="The thread's new priority properties: the maximum control priority and priority."/>
|
||||
<param dir="in" name="cspace_root" type="seL4_CNode"
|
||||
description="The new CSpace root."/>
|
||||
<param dir="in" name="cspace_root_data" type="seL4_Word"
|
||||
@@ -148,6 +146,8 @@
|
||||
<description>
|
||||
See <autoref label="sec:sched"/>
|
||||
</description>
|
||||
<param dir="in" name="authority" type="seL4_CPtr"
|
||||
description="Capability to the TCB to use the MCP from when setting the priority."/>
|
||||
<param dir="in" name="priority" type="seL4_Uint8"
|
||||
description="The thread's new priority."/>
|
||||
</method>
|
||||
@@ -159,6 +159,8 @@
|
||||
<description>
|
||||
See <autoref label="sec:sched"/>
|
||||
</description>
|
||||
<param dir="in" name="authority" type="seL4_CPtr"
|
||||
description="Capability to the TCB to use the MCP from when setting the MCP."/>
|
||||
<param dir="in" name="mcp" type="seL4_Uint8"
|
||||
description="The thread's new maximum controlled priority."/>
|
||||
</method>
|
||||
|
||||
@@ -21,12 +21,6 @@ block seL4_MessageInfo {
|
||||
field length 7
|
||||
}
|
||||
|
||||
block seL4_PrioProps {
|
||||
padding 16
|
||||
field mcp 8
|
||||
field prio 8
|
||||
}
|
||||
|
||||
-- Cap rights
|
||||
block seL4_CapRights {
|
||||
padding 29
|
||||
|
||||
@@ -22,13 +22,6 @@ block seL4_MessageInfo {
|
||||
field length 7
|
||||
}
|
||||
|
||||
block seL4_PrioProps {
|
||||
padding 32
|
||||
padding 16
|
||||
field mcp 8
|
||||
field prio 8
|
||||
}
|
||||
|
||||
block seL4_CapRights {
|
||||
padding 32
|
||||
|
||||
|
||||
@@ -230,7 +230,6 @@ def init_data_types(wordsize):
|
||||
Type("seL4_Bool", 1, wordsize, native_size_bits=8),
|
||||
|
||||
# seL4 Structures
|
||||
BitFieldType("seL4_PrioProps_t", wordsize, wordsize),
|
||||
BitFieldType("seL4_CapRights_t", wordsize, wordsize),
|
||||
|
||||
# Object types
|
||||
|
||||
@@ -63,10 +63,12 @@ deleted.
|
||||
seL4 uses a preemptive round-robin scheduler with 256 priority levels.
|
||||
All threads have a maximum controlled priority (MCP) and a priority, the latter being the effective
|
||||
priority of the thread.
|
||||
When a thread creates or modifies a thread (including itself), it can only set the
|
||||
other thread's priority and MCP to be less than or equal to its own MCP. Thread priority and MCP can be
|
||||
set with \apifunc{seL4\_TCB\_Configure}{tcb_configure} and
|
||||
\apifunc{seL4\_TCB\_SetPriority}{tcb_setpriority}, \apifunc{seL4\_TCB\_SetMCPriority}{tcb_setmcpriority} methods.
|
||||
When a thread modifies a another threads priority (including itself) it must provide a
|
||||
thread capability from which to use the MCP from. Threads can only set priorities and MCPs
|
||||
to be less than or equal to the provided thread's MCP.
|
||||
The initial task starts with an MCP and priority as the highest priority in the system (\texttt{seL4\_MaxPrio}).
|
||||
Thread priority and MCP can be set with \apifunc{seL4\_TCB\_SetPriority}{tcb_setpriority}
|
||||
and \apifunc{seL4\_TCB\_SetMCPriority}{tcb_setmcpriority} methods.
|
||||
|
||||
\subsection{Exceptions}
|
||||
|
||||
|
||||
@@ -31,11 +31,11 @@
|
||||
#define NULL_PRIO 0
|
||||
|
||||
static exception_t
|
||||
checkPrio(prio_t prio)
|
||||
checkPrio(prio_t prio, tcb_t *auth)
|
||||
{
|
||||
prio_t mcp;
|
||||
|
||||
mcp = NODE_STATE(ksCurThread)->tcbMCP;
|
||||
mcp = auth->tcbMCP;
|
||||
|
||||
/* system invariant: existing MCPs are bounded */
|
||||
assert(mcp <= seL4_MaxPrio);
|
||||
@@ -698,10 +698,10 @@ decodeTCBInvocation(word_t invLabel, word_t length, cap_t cap,
|
||||
return decodeTCBConfigure(cap, length, slot, excaps, buffer);
|
||||
|
||||
case TCBSetPriority:
|
||||
return decodeSetPriority(cap, length, buffer);
|
||||
return decodeSetPriority(cap, length, excaps, buffer);
|
||||
|
||||
case TCBSetMCPriority:
|
||||
return decodeSetMCPriority(cap, length, buffer);
|
||||
return decodeSetMCPriority(cap, length, excaps, buffer);
|
||||
|
||||
case TCBSetIPCBuffer:
|
||||
return decodeSetIPCBuffer(cap, length, slot, excaps, buffer);
|
||||
@@ -884,9 +884,8 @@ decodeWriteRegisters(cap_t cap, word_t length, word_t *buffer)
|
||||
w, transferArch, buffer);
|
||||
}
|
||||
|
||||
/* SetPriority, SetMCPriority, SetIPCParams and SetSpace are all
|
||||
/* SetPriority, SetMCPriority, SetIPCBuffer and SetSpace are all
|
||||
* specialisations of TCBConfigure. */
|
||||
|
||||
exception_t
|
||||
decodeTCBConfigure(cap_t cap, word_t length, cte_t* slot,
|
||||
extra_caps_t rootCaps, word_t *buffer)
|
||||
@@ -895,12 +894,9 @@ decodeTCBConfigure(cap_t cap, word_t length, cte_t* slot,
|
||||
cap_t bufferCap, cRootCap, vRootCap;
|
||||
deriveCap_ret_t dc_ret;
|
||||
cptr_t faultEP;
|
||||
seL4_PrioProps_t props;
|
||||
prio_t prio, mcp;
|
||||
word_t cRootData, vRootData, bufferAddr;
|
||||
exception_t status;
|
||||
|
||||
if (length < 5 || rootCaps.excaprefs[0] == NULL
|
||||
if (length < 4 || rootCaps.excaprefs[0] == NULL
|
||||
|| rootCaps.excaprefs[1] == NULL
|
||||
|| rootCaps.excaprefs[2] == NULL) {
|
||||
userError("TCB Configure: Truncated message.");
|
||||
@@ -909,10 +905,9 @@ decodeTCBConfigure(cap_t cap, word_t length, cte_t* slot,
|
||||
}
|
||||
|
||||
faultEP = getSyscallArg(0, buffer);
|
||||
props = prioPropsFromWord(getSyscallArg(1, buffer));
|
||||
cRootData = getSyscallArg(2, buffer);
|
||||
vRootData = getSyscallArg(3, buffer);
|
||||
bufferAddr = getSyscallArg(4, buffer);
|
||||
cRootData = getSyscallArg(1, buffer);
|
||||
vRootData = getSyscallArg(2, buffer);
|
||||
bufferAddr = getSyscallArg(3, buffer);
|
||||
|
||||
cRootSlot = rootCaps.excaprefs[0];
|
||||
cRootCap = rootCaps.excaprefs[0]->cap;
|
||||
@@ -921,23 +916,6 @@ decodeTCBConfigure(cap_t cap, word_t length, cte_t* slot,
|
||||
bufferSlot = rootCaps.excaprefs[2];
|
||||
bufferCap = rootCaps.excaprefs[2]->cap;
|
||||
|
||||
prio = seL4_PrioProps_get_prio(props);
|
||||
mcp = seL4_PrioProps_get_mcp(props);
|
||||
|
||||
status = checkPrio(prio);
|
||||
if (status != EXCEPTION_NONE) {
|
||||
userError("TCB Configure: Requested priority %lu too high (max %lu).",
|
||||
(unsigned long) prio, (unsigned long) NODE_STATE(ksCurThread)->tcbMCP);
|
||||
return status;
|
||||
}
|
||||
|
||||
status = checkPrio(mcp);
|
||||
if (status != EXCEPTION_NONE) {
|
||||
userError("TCB Configure: Requested maximum controlled priority %lu too high (max %lu),",
|
||||
(unsigned long) mcp, (unsigned long) NODE_STATE(ksCurThread)->tcbMCP);
|
||||
return status;
|
||||
}
|
||||
|
||||
if (bufferAddr == 0) {
|
||||
bufferSlot = NULL;
|
||||
} else {
|
||||
@@ -997,31 +975,38 @@ decodeTCBConfigure(cap_t cap, word_t length, cte_t* slot,
|
||||
setThreadState(NODE_STATE(ksCurThread), ThreadState_Restart);
|
||||
return invokeTCB_ThreadControl(
|
||||
TCB_PTR(cap_thread_cap_get_capTCBPtr(cap)), slot,
|
||||
faultEP, mcp, prio,
|
||||
faultEP, NULL_PRIO, NULL_PRIO,
|
||||
cRootCap, cRootSlot,
|
||||
vRootCap, vRootSlot,
|
||||
bufferAddr, bufferCap,
|
||||
bufferSlot, thread_control_update_all);
|
||||
bufferSlot, thread_control_update_space |
|
||||
thread_control_update_ipc_buffer);
|
||||
}
|
||||
|
||||
exception_t
|
||||
decodeSetPriority(cap_t cap, word_t length, word_t *buffer)
|
||||
decodeSetPriority(cap_t cap, word_t length, extra_caps_t excaps, word_t *buffer)
|
||||
{
|
||||
prio_t newPrio;
|
||||
exception_t status;
|
||||
|
||||
if (length < 1) {
|
||||
if (length < 1 || excaps.excaprefs[0] == NULL) {
|
||||
userError("TCB SetPriority: Truncated message.");
|
||||
current_syscall_error.type = seL4_TruncatedMessage;
|
||||
return EXCEPTION_SYSCALL_ERROR;
|
||||
}
|
||||
|
||||
newPrio = getSyscallArg(0, buffer);
|
||||
prio_t newPrio = getSyscallArg(0, buffer);
|
||||
cap_t authCap = excaps.excaprefs[0]->cap;
|
||||
|
||||
status = checkPrio(newPrio);
|
||||
if (cap_get_capType(authCap) != cap_thread_cap) {
|
||||
userError("Set priority: authority cap not a TCB.");
|
||||
current_syscall_error.type = seL4_InvalidCapability;
|
||||
current_syscall_error.invalidCapNumber = 1;
|
||||
return EXCEPTION_SYSCALL_ERROR;
|
||||
}
|
||||
|
||||
tcb_t *authTCB = TCB_PTR(cap_thread_cap_get_capTCBPtr(authCap));
|
||||
exception_t status = checkPrio(newPrio, authTCB);
|
||||
if (status != EXCEPTION_NONE) {
|
||||
userError("TCB SetPriority: Requested priority %lu too high (max %lu).",
|
||||
(unsigned long) newPrio, (unsigned long) NODE_STATE(ksCurThread)->tcbMCP);
|
||||
(unsigned long) newPrio, (unsigned long) authTCB->tcbMCP);
|
||||
return status;
|
||||
}
|
||||
|
||||
@@ -1036,23 +1021,29 @@ decodeSetPriority(cap_t cap, word_t length, word_t *buffer)
|
||||
}
|
||||
|
||||
exception_t
|
||||
decodeSetMCPriority(cap_t cap, word_t length, word_t *buffer)
|
||||
decodeSetMCPriority(cap_t cap, word_t length, extra_caps_t excaps, word_t *buffer)
|
||||
{
|
||||
prio_t newMcp;
|
||||
exception_t status;
|
||||
|
||||
if (length < 1) {
|
||||
if (length < 1 || excaps.excaprefs[0] == NULL) {
|
||||
userError("TCB SetMCPriority: Truncated message.");
|
||||
current_syscall_error.type = seL4_TruncatedMessage;
|
||||
return EXCEPTION_SYSCALL_ERROR;
|
||||
}
|
||||
|
||||
newMcp = getSyscallArg(0, buffer);
|
||||
prio_t newMcp = getSyscallArg(0, buffer);
|
||||
cap_t authCap = excaps.excaprefs[0]->cap;
|
||||
|
||||
status = checkPrio(newMcp);
|
||||
if (cap_get_capType(authCap) != cap_thread_cap) {
|
||||
userError("TCB SetMCPriority: authority cap not a TCB.");
|
||||
current_syscall_error.type = seL4_InvalidCapability;
|
||||
current_syscall_error.invalidCapNumber = 1;
|
||||
return EXCEPTION_SYSCALL_ERROR;
|
||||
}
|
||||
|
||||
tcb_t *authTCB = TCB_PTR(cap_thread_cap_get_capTCBPtr(authCap));
|
||||
exception_t status = checkPrio(newMcp, authTCB);
|
||||
if (status != EXCEPTION_NONE) {
|
||||
userError("TCB SetMCPriority: Requested maximum controlled priority %lu too high (max %lu).",
|
||||
(unsigned long) newMcp, (unsigned long) NODE_STATE(ksCurThread)->tcbMCP);
|
||||
(unsigned long) newMcp, (unsigned long) authTCB->tcbMCP);
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user