Newer
Older
#include "types.h"
#include "param.h"
#include "mmu.h"
#include "proc.h"
#include "defs.h"
#include "x86.h"
#include "traps.h"
#include "syscall.h"
/*
* User code makes a system call with INT T_SYSCALL.
* System call number in %eax.
* Arguments on the stack, from the user call to the C
* library system call function. The saved user %esp points
* to a saved program counter, and then the first argument.
*
* Return value? Error indication? Errno?
*/
fetchint(struct proc *p, uint addr, int *ip)
*ip = *(int*)(p->mem + addr);
return 0;
}
// Fetch byte from a user-supplied pointer.
// Returns 0 on success, -1 if pointer is illegal.
int
fetchbyte(struct proc *p, uint addr, char* c)
{
if(addr >= p->sz)
return -1;
*c = *(p->mem + addr);
esp = (uint) curproc[cpu()]->tf->esp;
return fetchint(curproc[cpu()], esp + 4 + 4*argno, ip);
// check that an entire string is valid in user space
int
checkstring(uint s)
{
char c;
while(1){
if(fetchbyte(curproc[cpu()], s, &c) < 0)
return -1;
if(c == '\0')
return 0;
s++;
}
}
putint(struct proc *p, uint addr, int x)
{
struct fd *rfd = 0, *wfd = 0;
int f1 = -1, f2 = -1;
struct proc *p = curproc[cpu()];
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
if(pipe_alloc(&rfd, &wfd) < 0)
goto oops;
if((f1 = fd_ualloc()) < 0)
goto oops;
p->fds[f1] = rfd;
if((f2 = fd_ualloc()) < 0)
goto oops;
p->fds[f2] = wfd;
if(fetcharg(0, &fdp) < 0)
goto oops;
if(putint(p, fdp, f1) < 0)
goto oops;
if(putint(p, fdp+4, f2) < 0)
goto oops;
return 0;
oops:
cprintf("sys_pipe failed\n");
if(rfd)
fd_close(rfd);
if(wfd)
fd_close(wfd);
if(f1 >= 0)
p->fds[f1] = 0;
if(f2 >= 0)
p->fds[f2] = 0;
return -1;
}
int
struct proc *p = curproc[cpu()];
if(fetcharg(0, &fd) < 0 || fetcharg(1, &addr) < 0 || fetcharg(2, &n) < 0)
return -1;
if(fd < 0 || fd >= NOFILE)
return -1;
if(p->fds[fd] == 0)
return -1;
if(addr + n > p->sz)
return -1;
ret = fd_write(p->fds[fd], p->mem + addr, n);
return ret;
struct proc *p = curproc[cpu()];
if(fetcharg(0, &fd) < 0 || fetcharg(1, &addr) < 0 || fetcharg(2, &n) < 0)
return -1;
if(fd < 0 || fd >= NOFILE)
return -1;
if(p->fds[fd] == 0)
return -1;
if(addr + n > p->sz)
return -1;
ret = fd_read(p->fds[fd], p->mem + addr, n);
return ret;
}
int
{
int fd;
struct proc *p = curproc[cpu()];
if(fetcharg(0, &fd) < 0)
return -1;
if(fd < 0 || fd >= NOFILE)
return -1;
if(p->fds[fd] == 0)
return -1;
fd_close(p->fds[fd]);
p->fds[fd] = 0;
return 0;
return 0; // not reached
return proc_wait();
}
int
sys_kill(void)
{
int pid;
if(fetcharg(0, &pid) < 0)
return -1;
return proc_kill(pid);
char buf[2];
if(fetcharg(0, &c) < 0)
return -1;
buf[0] = c;
buf[1] = 0;
cprintf("%s", buf);
return 0;
}
int
sys_cons_puts(void)
{
char buf[256];
int i;
struct proc *cp = curproc[cpu()];
if(fetcharg(0, &addr) < 0)
return -1;
for(i=0; i<sizeof buf-1 && fetchbyte(cp, addr+i, &buf[i]) >= 0; i++)
if(buf[i] == 0)
break;
buf[i] = 0;
cprintf("%s", buf);
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
int
sys_exec(void)
{
struct proc *cp = curproc[cpu()];
uint arg0, sz;
int i;
struct inode *ip;
struct elfhdr elf;
struct proghdr ph;
if(fetcharg(0, &arg0) < 0)
return -1;
if(checkstring(arg0) < 0)
return -1;
ip = namei(cp->mem + arg0);
if(ip == 0)
return -1;
if(readi(ip, &elf, 0, sizeof(elf)) < sizeof(elf))
goto bad;
if(elf.magic != ELF_MAGIC)
goto bad;
sz = 0;
for(i = 0; i < elf.phnum; i++){
if(readi(ip, &ph, elf.phoff + i * sizeof(ph), sizeof(ph)) != sizeof(ph))
goto bad;
if(ph.type != ELF_PROG_LOAD)
continue;
if(ph.memsz < ph.filesz)
goto bad;
sz += ph.memsz;
}
sz += 4096 - (sz % 4096);
sz += 4096;
// commit to the new image.
kfree(cp->mem, cp->sz);
cp->sz = sz;
cp->mem = kalloc(cp->sz);
for(i = 0; i < elf.phnum; i++){
if(readi(ip, &ph, elf.phoff + i * sizeof(ph), sizeof(ph)) != sizeof(ph))
goto bad;
if(ph.type != ELF_PROG_LOAD)
continue;
if(ph.va + ph.memsz > sz)
goto bad2;
if(readi(ip, cp->mem + ph.va, ph.offset, ph.filesz) != ph.filesz)
goto bad2;
memset(cp->mem + ph.va + ph.filesz, 0, ph.memsz - ph.filesz);
}
iput(ip);
cp->tf->eip = elf.entry;
cp->tf->esp = cp->sz;
setupsegs(cp);
return 0;
bad:
cprintf("exec failed early\n");
iput(ip);
return -1;
bad2:
cprintf("exec failed late\n");
iput(ip);
proc_exit();
return 0;
}
struct buf *b;
struct inode *ip;
for (i = 0; i < 2; i++) {
b = bread(1, i);
cprintf("disk 1 sector %d: ", i);
for (j = 0; j < 4; j++)
cprintf("%x ", b->data[j] & 0xff);
ip->dev, ip->inum, ip->count, ip->busy,
ip->type, ip->nlink, ip->size, ip->addrs[0]);
iput(ip);
ip->dev, ip->inum, ip->count, ip->busy,
ip->type, ip->nlink, ip->size, ip->addrs[0]);
iput(ip);
} else {
if(fetcharg(0, &addr) < 0)
return -1;
case SYS_pipe:
ret = sys_pipe();
break;
case SYS_write:
ret = sys_write();
break;
case SYS_read:
ret = sys_read();
break;
case SYS_close:
ret = sys_close();
break;
case SYS_block:
ret = sys_block();
break;
case SYS_kill:
ret = sys_kill();
break;
case SYS_cons_puts:
ret = sys_cons_puts();
break;
default:
cprintf("unknown sys call %d\n", num);
// XXX fault
break;
}