diff options
author | Rusty Russell <rusty@rustcorp.com.au> | 2007-07-26 13:41:03 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-07-26 14:35:17 -0400 |
commit | dde797899ac17ebb812b7566044124d785e98dc7 (patch) | |
tree | 531ae7fd415d267e49acfedbbf4f03cf86e5eac1 /drivers/lguest/core.c | |
parent | e2c9784325490c878b7f69aeec1bed98b288bd97 (diff) |
lguest: documentation IV: Launcher
Documentation: The Launcher
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'drivers/lguest/core.c')
-rw-r--r-- | drivers/lguest/core.c | 24 |
1 files changed, 22 insertions, 2 deletions
diff --git a/drivers/lguest/core.c b/drivers/lguest/core.c index 2cea0c80c992..1eb05f9a56b6 100644 --- a/drivers/lguest/core.c +++ b/drivers/lguest/core.c | |||
@@ -208,24 +208,39 @@ static int emulate_insn(struct lguest *lg) | |||
208 | return 1; | 208 | return 1; |
209 | } | 209 | } |
210 | 210 | ||
211 | /*L:305 | ||
212 | * Dealing With Guest Memory. | ||
213 | * | ||
214 | * When the Guest gives us (what it thinks is) a physical address, we can use | ||
215 | * the normal copy_from_user() & copy_to_user() on that address: remember, | ||
216 | * Guest physical == Launcher virtual. | ||
217 | * | ||
218 | * But we can't trust the Guest: it might be trying to access the Launcher | ||
219 | * code. We have to check that the range is below the pfn_limit the Launcher | ||
220 | * gave us. We have to make sure that addr + len doesn't give us a false | ||
221 | * positive by overflowing, too. */ | ||
211 | int lguest_address_ok(const struct lguest *lg, | 222 | int lguest_address_ok(const struct lguest *lg, |
212 | unsigned long addr, unsigned long len) | 223 | unsigned long addr, unsigned long len) |
213 | { | 224 | { |
214 | return (addr+len) / PAGE_SIZE < lg->pfn_limit && (addr+len >= addr); | 225 | return (addr+len) / PAGE_SIZE < lg->pfn_limit && (addr+len >= addr); |
215 | } | 226 | } |
216 | 227 | ||
217 | /* Just like get_user, but don't let guest access lguest binary. */ | 228 | /* This is a convenient routine to get a 32-bit value from the Guest (a very |
229 | * common operation). Here we can see how useful the kill_lguest() routine we | ||
230 | * met in the Launcher can be: we return a random value (0) instead of needing | ||
231 | * to return an error. */ | ||
218 | u32 lgread_u32(struct lguest *lg, unsigned long addr) | 232 | u32 lgread_u32(struct lguest *lg, unsigned long addr) |
219 | { | 233 | { |
220 | u32 val = 0; | 234 | u32 val = 0; |
221 | 235 | ||
222 | /* Don't let them access lguest binary */ | 236 | /* Don't let them access lguest binary. */ |
223 | if (!lguest_address_ok(lg, addr, sizeof(val)) | 237 | if (!lguest_address_ok(lg, addr, sizeof(val)) |
224 | || get_user(val, (u32 __user *)addr) != 0) | 238 | || get_user(val, (u32 __user *)addr) != 0) |
225 | kill_guest(lg, "bad read address %#lx", addr); | 239 | kill_guest(lg, "bad read address %#lx", addr); |
226 | return val; | 240 | return val; |
227 | } | 241 | } |
228 | 242 | ||
243 | /* Same thing for writing a value. */ | ||
229 | void lgwrite_u32(struct lguest *lg, unsigned long addr, u32 val) | 244 | void lgwrite_u32(struct lguest *lg, unsigned long addr, u32 val) |
230 | { | 245 | { |
231 | if (!lguest_address_ok(lg, addr, sizeof(val)) | 246 | if (!lguest_address_ok(lg, addr, sizeof(val)) |
@@ -233,6 +248,9 @@ void lgwrite_u32(struct lguest *lg, unsigned long addr, u32 val) | |||
233 | kill_guest(lg, "bad write address %#lx", addr); | 248 | kill_guest(lg, "bad write address %#lx", addr); |
234 | } | 249 | } |
235 | 250 | ||
251 | /* This routine is more generic, and copies a range of Guest bytes into a | ||
252 | * buffer. If the copy_from_user() fails, we fill the buffer with zeroes, so | ||
253 | * the caller doesn't end up using uninitialized kernel memory. */ | ||
236 | void lgread(struct lguest *lg, void *b, unsigned long addr, unsigned bytes) | 254 | void lgread(struct lguest *lg, void *b, unsigned long addr, unsigned bytes) |
237 | { | 255 | { |
238 | if (!lguest_address_ok(lg, addr, bytes) | 256 | if (!lguest_address_ok(lg, addr, bytes) |
@@ -243,6 +261,7 @@ void lgread(struct lguest *lg, void *b, unsigned long addr, unsigned bytes) | |||
243 | } | 261 | } |
244 | } | 262 | } |
245 | 263 | ||
264 | /* Similarly, our generic routine to copy into a range of Guest bytes. */ | ||
246 | void lgwrite(struct lguest *lg, unsigned long addr, const void *b, | 265 | void lgwrite(struct lguest *lg, unsigned long addr, const void *b, |
247 | unsigned bytes) | 266 | unsigned bytes) |
248 | { | 267 | { |
@@ -250,6 +269,7 @@ void lgwrite(struct lguest *lg, unsigned long addr, const void *b, | |||
250 | || copy_to_user((void __user *)addr, b, bytes) != 0) | 269 | || copy_to_user((void __user *)addr, b, bytes) != 0) |
251 | kill_guest(lg, "bad write address %#lx len %u", addr, bytes); | 270 | kill_guest(lg, "bad write address %#lx len %u", addr, bytes); |
252 | } | 271 | } |
272 | /* (end of memory access helper routines) :*/ | ||
253 | 273 | ||
254 | static void set_ts(void) | 274 | static void set_ts(void) |
255 | { | 275 | { |