SELFOUR-1016: Require auth cap to set prio/mcp

This fixes confused deputy problem when setting priorities/mcps.
This commit is contained in:
Anna Lyons
2017-12-15 15:50:16 +11:00
parent ce2efb33c8
commit 05b83acd95
9 changed files with 65 additions and 81 deletions

13
CHANGES
View File

@@ -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

View File

@@ -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"

View File

@@ -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;

View File

@@ -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>

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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}

View File

@@ -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;
}