1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
|
/** @file syscall_misc.c
*
* @brief miscellaneous syscalls.
*
* @author Hanjie Wu (hanjiew)
* @bug No functional bugs
*/
#include <simics.h>
#include <stdio.h>
#include <string.h>
#include <common_kern.h>
#include <elf/elf_410.h>
#include <malloc_internal.h>
#include <ureg.h>
#include <x86/asm.h>
#include <x86/cr.h>
#include <x86/eflags.h>
#include <x86/seg.h>
#include <asm_instr.h>
#include <assert.h>
#include <loader.h>
#include <malloc.h>
#include <mm.h>
#include <paging.h>
#include <sched.h>
#include <sync.h>
#include <timer.h>
#include <toad.h>
#include <usermem.h>
/**
* @brief misbehave() syscall handler
* @param f saved regs
*/
void sys_misbehave_real(stack_frame_t* f) {
f->eax = 0;
}
/**
* @brief halt() syscall handler
* @param f saved regs
*/
void sys_halt_real(stack_frame_t* f) {
sim_halt();
hlt();
panic("Halted");
}
/**
* @brief read the "." file to user buf
* @param buf buffer
* @param count size
* @param offset offset
* @return number of bytes read, or -1 on failure
*/
static reg_t read_dot_file(va_t buf, int count, int offset);
/**
* @brief readfile() syscall handler
* @param f saved regs
*/
void sys_readfile_real(stack_frame_t* f) {
reg_t esi = f->esi;
va_t pfilename, buf;
int count, offset;
if (copy_from_user((va_t)esi, sizeof(va_t), &pfilename) != 0) {
goto read_arg_fail;
}
if (copy_from_user((va_t)(esi + sizeof(va_t)), sizeof(va_t), &buf) != 0) {
goto read_arg_fail;
}
if (copy_from_user((va_t)(esi + 2 * sizeof(va_t)), sizeof(int), &count) !=
0) {
goto read_arg_fail;
}
if (copy_from_user((va_t)(esi + 3 * sizeof(va_t)), sizeof(int), &offset) !=
0) {
goto read_arg_fail;
}
if (count < 0 || offset < 0) {
goto read_arg_fail;
}
char* filename = copy_string_from_user(pfilename, MAX_EXECNAME_LEN);
if (filename == NULL) {
goto read_arg_fail;
}
if (strcmp(filename, ".") == 0) {
free(filename);
f->eax = read_dot_file(buf, count, offset);
return;
}
file_t* fp = find_file(filename);
if (fp == NULL) {
goto no_such_file;
}
free(filename);
if (offset > fp->execlen) {
goto offset_too_big;
}
int size = fp->execlen - offset;
if (count < size) {
size = count;
}
if (copy_to_user(buf, size, (void*)(fp->execbytes + offset)) != 0) {
goto bad_buffer;
}
f->eax = (reg_t)size;
return;
bad_buffer:
offset_too_big:
no_such_file:
free(filename);
read_arg_fail:
f->eax = (reg_t)-1;
return;
}
static reg_t read_dot_file(va_t buf, int count, int offset) {
file_t* fp;
int i = 0;
int cur = 0;
int written = 0, left = count;
while (i < exec2obj_userapp_count && left > 0) {
fp = &exec2obj_userapp_TOC[i];
int len = strlen(fp->execname) + 1;
if (cur + len <= offset) {
/* before offset */
cur += len;
i++;
continue;
}
int size = len;
const char* start = fp->execname;
/* write this entry to buffer */
if (cur < offset) {
size -= (offset - cur);
start += (offset - cur);
}
if (left < size) {
size = left;
}
if (copy_to_user((va_t)buf + written, size, (void*)start) != 0) {
return (reg_t)-1;
}
cur += len;
written += size;
left -= size;
i++;
}
/* write extra null byte */
if (left != 0 && cur == offset) {
char nul = '\0';
if (copy_to_user((va_t)buf + written, 1, &nul) != 0) {
return (reg_t)-1;
}
written++;
}
return (reg_t)written;
}
void sys_new_console_real(stack_frame_t* f) {
thread_t* t = get_current();
pts_t* old_pts = t->pts;
pts_t* pts = smalloc(sizeof(pts_t));
if (pts == NULL) {
f->eax = (reg_t)-1;
return;
}
pts_init(pts);
pts->refcount++;
t->pts = pts;
mutex_lock(&old_pts->lock);
old_pts->refcount--;
mutex_unlock(&old_pts->lock);
switch_pts(pts);
print_toad();
}
|