Skip to content

Commit c35e7fb

Browse files
committed
kernel/cpu: Re-write shadow stack initialization
Make the shadow stack initialization more readable by introducing an initializer struct with push semantics. Signed-off-by: Joerg Roedel <joerg.roedel@amd.com>
1 parent 06fc81e commit c35e7fb

1 file changed

Lines changed: 46 additions & 46 deletions

File tree

kernel/src/cpu/shadow_stack.rs

Lines changed: 46 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -112,69 +112,69 @@ pub enum ShadowStackInit {
112112
Exception,
113113
}
114114

115+
struct ShadowStackInitializer<'a> {
116+
page: &'a PageRef,
117+
top_of_stack: VirtAddr,
118+
stack_ptr: usize,
119+
}
120+
121+
impl<'a> ShadowStackInitializer<'a> {
122+
fn new(page: &'a PageRef, top_of_stack: VirtAddr) -> Self {
123+
Self {
124+
page,
125+
top_of_stack,
126+
stack_ptr: PAGE_SIZE,
127+
}
128+
}
129+
130+
fn push(&mut self, value: usize) {
131+
let buf = value.to_ne_bytes();
132+
self.stack_ptr -= buf.len();
133+
self.page.write(self.stack_ptr, &buf);
134+
}
135+
136+
fn push_token(&mut self, offset: usize, mask: usize) -> VirtAddr {
137+
let token_offset = PAGE_SIZE - self.stack_ptr + size_of::<usize>();
138+
let token_addr = self.top_of_stack - token_offset;
139+
let token = (token_addr + offset).bits() | mask;
140+
self.push(token);
141+
token_addr
142+
}
143+
}
144+
115145
pub fn init_shadow_stack(
116146
page: &PageRef,
117147
top_of_sstack: VirtAddr,
118148
init: ShadowStackInit,
119149
) -> (Option<VirtAddr>, VirtAddr) {
120150
// Initialize the shadow stack.
121-
let mut chunk = [0; 32];
122-
let (base_token_addr, ssp, len) = match init {
151+
let mut shadow_stack = ShadowStackInitializer::new(page, top_of_sstack);
152+
match init {
123153
ShadowStackInit::Normal {
124154
entry_return,
125155
exit_return,
126156
iret_frame,
127157
} => {
128-
let base_token_addr = top_of_sstack - 8;
129-
let (token_bytes, rip_bytes) = chunk.split_at_mut(8);
158+
let base_token_addr = match iret_frame {
159+
true => Some(shadow_stack.push_token(0, BUSY)),
160+
false => Some(top_of_sstack - 8),
161+
};
130162

131-
let len: usize = if iret_frame { 32 } else { 24 };
163+
shadow_stack.push(exit_return);
164+
shadow_stack.push(entry_return);
132165

133-
// Create a shadow stack restore token.
134-
let token_addr = top_of_sstack - len;
135-
let token = (token_addr + 8).bits() + MODE_64BIT;
136-
token_bytes.copy_from_slice(&token.to_ne_bytes());
166+
let token_addr = shadow_stack.push_token(size_of::<usize>(), MODE_64BIT);
137167

138-
let (entry_bytes, base_bytes) = rip_bytes.split_at_mut(8);
139-
entry_bytes.copy_from_slice(&entry_return.to_ne_bytes());
140-
141-
let (exit_bytes, bottom_bytes) = base_bytes.split_at_mut(8);
142-
exit_bytes.copy_from_slice(&exit_return.to_ne_bytes());
143-
144-
if iret_frame {
145-
// If iret_frame is true, then this thread will be used as a
146-
// user task stack. In that case, place a busy token at the
147-
// base of the shadow stack.
148-
let base_token = base_token_addr.bits() + BUSY;
149-
bottom_bytes.copy_from_slice(&base_token.to_ne_bytes());
150-
}
151-
152-
(Some(base_token_addr), token_addr, len)
168+
(base_token_addr, token_addr)
153169
}
154170
ShadowStackInit::ContextSwitch => {
155-
let (_, token_bytes) = chunk.split_at_mut(24);
156-
157-
// Create a shadow stack restore token.
158-
let token_addr = top_of_sstack - 8;
159-
let token = (token_addr + 8).bits() + MODE_64BIT;
160-
token_bytes.copy_from_slice(&token.to_ne_bytes());
161-
162-
(None, token_addr, 32)
171+
let token_addr = shadow_stack.push_token(size_of::<usize>(), MODE_64BIT);
172+
(None, token_addr)
163173
}
164174
ShadowStackInit::Exception => {
165-
let (_, token_bytes) = chunk.split_at_mut(24);
166-
167-
// Create a supervisor shadow stack token.
168-
let token_addr = top_of_sstack - 8;
169-
let token = token_addr.bits();
170-
token_bytes.copy_from_slice(&token.to_ne_bytes());
171-
172-
(None, token_addr, 32)
175+
let token_addr = shadow_stack.push_token(0, 0);
176+
(None, token_addr)
173177
}
174-
ShadowStackInit::Init => (None, top_of_sstack - 8, 24),
175-
};
176-
177-
page.write(PAGE_SIZE - len, &chunk[..len]);
178-
179-
(base_token_addr, ssp)
178+
ShadowStackInit::Init => (None, top_of_sstack - 8),
179+
}
180180
}

0 commit comments

Comments
 (0)