ICS143A: Principles of Operating Systems. Lecture 14: System calls (part 2) Anton Burtsev November, 2017

Similar documents
CS3210: Isolation Mechanisms

Changes made in this version not seen in first lecture:

CS5460/6460: Operating Systems. Lecture 9: First process. Anton Burtsev January, 2014

ICS143A: Principles of Operating Systems. Midterm recap, sample questions. Anton Burtsev February, 2017

COP4610: Operating Systems Project 1

CS 4414 Operating System Introduction

OS Concepts and structure

Operating Systems, 142

6.828: Using Virtual Memory. Adam Belay

CS5460/6460: Operating Systems. Lecture 9: Finishing system boot, and system init. Anton Burtsev January, 2014

Processes (Intro) Yannis Smaragdakis, U. Athens

SYSTEM CALL IMPLEMENTATION. CS124 Operating Systems Fall , Lecture 14

W4118: interrupt and system call. Junfeng Yang

Project 1 System Calls

143A: Principles of Operating Systems. Lecture 09: First process. Anton Burtsev January, 2017

3. Process Management in xv6

EEE3052: Introduction to Operating Systems. Fall Project #1

143A: Principles of Operating Systems. Lecture 7: System boot. Anton Burtsev January, 2017

ICS143A: Principles of Operating Systems. Lecture 12: Starting other CPUs. Anton Burtsev February, 2017

CS 550 Operating Systems Spring System Call

Changes made in this version not seen in first lecture:

238P: Operating Systems. Lecture 9: Creating Processes. Anton Burtsev February, 2018

1 Programs and Processes

238P: Operating Systems. Lecture 7: System boot. Anton Burtsev January, 2017

Final exam. Scores. Fall term 2012 KAIST EE209 Programming Structures for EE. Thursday Dec 20, Student's name: Student ID:

This is an open book, open notes exam. But no online or in-class chatting.

CSC 2400: Computing Systems. X86 Assembly: Function Calls

CMSC 313 Lecture 12 [draft] How C functions pass parameters

143A: Principles of Operating Systems. Lecture 7: System boot. Anton Burtsev October, 2017

CS 537 Lecture 2 - Processes

Processes and Threads

This is an open book, open notes exam. But no online or in-class chatting.

Processes. q Process concept q Process model and implementation q Multiprocessing once again q Next Time: Scheduling

Function Calls COS 217. Reading: Chapter 4 of Programming From the Ground Up (available online from the course Web site)

CS 5460/6460 Operating Systems

COL331/COL633 Minor2 Exam Operating Systems Sem II, Answer all 8 questions Max. Marks: 25

Question 4.2 2: (Solution, p 5) Suppose that the HYMN CPU begins with the following in memory. addr data (translation) LOAD 11110

4. The Abstraction: The Process

Systems I. Machine-Level Programming V: Procedures

CSE 451 Section 2 XK Lab 1 Design. Wi18

MASSACHUSETTS INSTITUTE OF TECHNOLOGY Fall Quiz I

CMSC 313 Lecture 12. Project 3 Questions. How C functions pass parameters. UMBC, CMSC313, Richard Chang

Binghamton University. CS-220 Spring X86 Debug. Computer Systems Section 3.11

Assembly Language: Function Calls

CSC 2400: Computing Systems. X86 Assembly: Function Calls"

Processes. Chester Rebeiro IIT Madras

Assembly Language: Function Calls" Goals of this Lecture"

Assembly Language: Function Calls. Goals of this Lecture. Function Call Problems

Assembly Language: Function Calls" Goals of this Lecture"

CSC 8400: Computer Systems. Using the Stack for Function Calls

Section 4: Threads and Context Switching

THEORY OF COMPILATION

Department of Electrical Engineering and Computer Science MASSACHUSETTS INSTITUTE OF TECHNOLOGY Fall Quiz I

Section 4: Threads CS162. September 15, Warmup Hello World Vocabulary 2

CS238P: Operating Systems. Lecture 12: Synchronization. Anton Burtsev March, 2018

Problem Set: xv6. Lecture Notes on Operating Systems. 1. Consider the following lines of code in a program running on xv6.

Quiz I Solutions MASSACHUSETTS INSTITUTE OF TECHNOLOGY Fall Department of Electrical Engineering and Computer Science

by Marina Cholakyan, Hyduke Noshadi, Sepehr Sahba and Young Cha

Processes. Today. Next Time. Process concept Process model Implementing processes Multiprocessing once again. Scheduling processes

Shell Code For Beginners

MASSACHUSETTS INSTITUTE OF TECHNOLOGY Fall Quiz I

CSC369 Lecture 2. Larry Zhang

CS471 ASST2. System Calls

CSC369 Lecture 2. Larry Zhang, September 21, 2015

143A: Principles of Operating Systems. Lecture 5: Calling conventions. Anton Burtsev January, 2017

The Process Abstraction. CMPU 334 Operating Systems Jason Waterman

CSC 2400: Computer Systems. Using the Stack for Function Calls

1. A student is testing an implementation of a C function; when compiled with gcc, the following x86-32 assembly code is produced:

Buffer Overflow Attack

This is an open book, open notes exam. But no online or in-class chatting.

238P: Operating Systems. Lecture 3: Calling conventions. Anton Burtsev October, 2018

CPS104 Recitation: Assembly Programming

LAB 2: PROCESS SYNCHRONIZATION IN XV6

CSCI 350 Ch. 2 The Kernel Abstraction & Protection. Mark Redekopp

238P: Operating Systems. Lecture 7: Basic Architecture of a Program. Anton Burtsev January, 2018

CS354: Machine Organization and Programming

ANITA S SUPER AWESOME RECITATION SLIDES

CS , Fall 2004 Exam 1

Pebbles Kernel Specification September 26, 2004

MASSACHUSETTS INSTITUTE OF TECHNOLOGY Fall Quiz I Solutions. Mean 70.5 Median 72 Standard deviation 15.8 Kurtosis -0.

Goals of this Lecture

143A: Principles of Operating Systems. Lecture 11: Synchronization. Anton Burtsev November, 2018

143A: Principles of Operating Systems. Lecture 4: Calling conventions. Anton Burtsev October, 2017

I/O Management! Goals of this Lecture!

I/O Management! Goals of this Lecture!

Machine Programming 3: Procedures

Introduction. This project will focus primarily on processes.

Overview REWARDS TIE HOWARD Summary CS 6V Data Structure Reverse Engineering. Zhiqiang Lin

CMSC 313 COMPUTER ORGANIZATION & ASSEMBLY LANGUAGE PROGRAMMING PREVIEW SLIDES 16, SPRING 2013

18-600: Recitation #4 Exploits

Project 2-1 User Programs

Is stack overflow still a problem?

BUFFER OVERFLOW DEFENSES & COUNTERMEASURES

Stack -- Memory which holds register contents. Will keep the EIP of the next address after the call

Machine-Level Programming III: Procedures

Practical Malware Analysis

ASSEMBLY III: PROCEDURES. Jo, Heeseung

Processes often need to communicate. CSCB09: Software Tools and Systems Programming. Solution: Pipes. Recall: I/O mechanisms in C

Assembly III: Procedures. Jo, Heeseung

CS Lab 1 xv6 Introduction Setup and exercise

Transcription:

ICS143A: Principles of Operating Systems Lecture 14: System calls (part 2) Anton Burtsev November, 2017

System call path

3316 void 3317 tvinit(void) 3318 { 3319 Initialize IDT int i; tvinit() is called from main() 3320 3321 3322 3323 for(i = 0; i < 256; i++) SETGATE(idt[i], 0, SEG_KCODE<<3, vectors[i], 0); SETGATE(idt[T_SYSCALL], 1, SEG_KCODE<<3, vectors[t_syscall], DPL_USER); 3324 3325 3326 } main() initlock(&tickslock, "time"); tvinit()

3316 void 3317 tvinit(void) 3318 { 3319 Initialize IDT int i; A couple of important details 3320 3321 3322 3323 for(i = 0; i < 256; i++) SETGATE(idt[i], 0, SEG_KCODE<<3, vectors[i], 0); SETGATE(idt[T_SYSCALL], 1, SEG_KCODE<<3, vectors[t_syscall], DPL_USER); 3324 3325 3326 } main() initlock(&tickslock, "time"); tvinit()

3316 void 3317 tvinit(void) 3318 { 3319 Initialize IDT int i; 3320 3321 3322 3323 Only int T_SYSCALL can be called from user-level for(i = 0; i < 256; i++) SETGATE(idt[i], 0, SEG_KCODE<<3, vectors[i], 0); SETGATE(idt[T_SYSCALL], 1, SEG_KCODE<<3, vectors[t_syscall], DPL_USER); 3324 3325 3326 } main() initlock(&tickslock, "time"); tvinit()

Kernel stack after interrupt int 0x64 vector64

Kernel stack after interrupt int 0x64 vector64 alltraps

Syscall number System call number is passed in the %eax register To distinguish which syscall to invoke, e.g., sys_read, sys_exec, etc. alltrap() saves it along with all other registers

3625 syscall(void) 3626 { 3627 int num; 3628 syscall(): get the number from the trap frame 3629 num = proc >tf >eax; 3630 if(num > 0 && num < NELEM(syscalls) && syscalls[num]) { 3631 3632 proc >tf >eax = syscalls[num](); } else { 3633 cprintf("%d %s: unknown sys call %d\n", 3634 proc >pid, proc >name, num); 3635 proc >tf >eax = 1; 3636 3637 } } int 0x64 vector64 alltraps trap(*tf) syscall()

3625 syscall(void) 3626 { 3627 int num; syscall(): process a syscall from the table 3628 3629 num = proc >tf >eax; 3630 if(num > 0 && num < NELEM(syscalls) && syscalls[num]) { 3631 3632 proc >tf >eax = syscalls[num](); } else { 3633 cprintf("%d %s: unknown sys call %d\n", 3634 proc >pid, proc >name, num); 3635 proc >tf >eax = 1; 3636 3637 } }

3600 static int (*syscalls[])(void) = { 3601 [SYS_fork] sys_fork, 3602 [SYS_exit] sys_exit, 3603 [SYS_wait] sys_wait, 3604 [SYS_pipe] sys_pipe, 3605 [SYS_read] sys_read, 3606 [SYS_kill] sys_kill, 3607 [SYS_exec] sys_exec, 3608 [SYS_fstat] sys_fstat, 3609 [SYS_chdir] sys_chdir, 3610 [SYS_dup] sys_dup, 3611 [SYS_getpid] sys_getpid, 3612 [SYS_sbrk] sys_sbrk, 3613 [SYS_sleep] sys_sleep, 3614 [SYS_uptime] sys_uptime, 3615 [SYS_open] sys_open, 3616 [SYS_write] sys_write, 3617 [SYS_mknod] sys_mknod, 3618 [SYS_unlink] sys_unlink, 3619 [SYS_link] sys_link, 3620 [SYS_mkdir] sys_mkdir, 3621 [SYS_close] sys_close, 3622 }; System call table

What do you think is the first system call xv6 executes?

1317 main(void) 1318 { 1319 kinit1(end, P2V(4*1024*1024)); // phys page allocator 1320 kvmalloc(); // kernel page table 1321 mpinit(); // detect other processors... 1323 seginit(); // segment descriptors... 1330 tvinit(); // trap vectors... 1338 userinit(); // first user process 1339 mpmain(); // finish this processor s setup 1340 } main()

2502 userinit(void) 2503 { 2504 struct proc *p; 2505 extern char _binary_initcode_start[], _binary_initcode_size[];... 2509 p = allocproc(); 2510 initproc = p; 2511 if((p >pgdir = setupkvm()) == 0) 2512 2513 panic("userinit: out of memory?"); inituvm(p >pgdir, _binary_initcode_start, (int)_binary_initcode_size); 2514 p >sz = PGSIZE; 2515 memset(p >tf, 0, sizeof(*p >tf));... 2530 } main() userinit()

8409 start: initcode.s: call exec( /init, argv); 8410 pushl $argv 8411 pushl $init 8412 pushl $0 // where caller pc would be 8413 movl $SYS_exec, %eax 8414 int $T_SYSCALL 8415... 8422 # char init[] = "/init\0"; 8423 init: 8424.string "/init\0" 8425 8426 # char *argv[] = { init, 0 }; 8427.p2align 2 8428 argv: 8429.long init 8430.long 0 exec( /init, argv) has two arguemens Push arguments on the stack Invoke system call with int $T_SYSCALL

How do user programs access system calls? It would be weird to write 8410 pushl $argv 8411 pushl $init 8412 pushl $0 // where caller pc would be 8413 movl $SYS_exec, %eax 8414 int $T_SYSCALL every time we want to invoke a system call

// system calls user.h int fork(void); int exit(void) attribute ((noreturn)); int wait(void); int pipe(int*); int write(int, void*, int); int read(int, void*, int); int close(int); int kill(int); int exec(char*, char**); user.h defines system call prototypes Compiler can generate correct system call stacks int open(char*, int); int mknod(char*, short, short); int unlink(char*); int fstat(int fd, struct stat*); int link(char*, char*);... Remember calling conventions? Arguments on the stack

Example From cat.asm if (write(1, buf, n)!= n) A3: 53 push ebx a4: 68 00 0b 00 00 push 0xb00 a9: 6a 01 push 0x1 ab: e8 c2 02 00 00 call 372 <write>

Note, different versions of gcc and different optimization levels Will generate slightly different code

Example From cat.asm if (write(1, buf, n)!= n) a0: 89 5c 24 08 mov %ebx,0x8(%esp) a4: c7 44 24 04 00 0b 00 movl $0xb00,0x4(%esp) ab: 00 ac: c7 04 24 01 00 00 00 movl $0x1,(%esp) b3: e8 aa 02 00 00 call 362 <write>

Example From cat.asm if (write(1, buf, n)!= n) a0: 89 5c 24 08 mov %ebx,0x8(%esp) a4: c7 44 24 04 00 0b 00 movl $0xb00,0x4(%esp) ab: 00 ac: c7 04 24 01 00 00 00 movl $0x1,(%esp) b3: e8 aa 02 00 00 call 362 <write>

Example From cat.asm if (write(1, buf, n)!= n) a0: 89 5c 24 08 mov %ebx,0x8(%esp) a4: c7 44 24 04 00 0b 00 movl $0xb00,0x4(%esp) ab: 00 ac: c7 04 24 01 00 00 00 movl $0x1,(%esp) b3: e8 aa 02 00 00 call 362 <write>

Still not clear... The header file allows compiler to generate a call side invocation, e.g., push arguments on the stack But where is the system call invocation itself e.g., int $T_SYSCALL

8450 #include "syscall.h" usys.s 8451 #include "traps.h" 8452 8453 #define SYSCALL(name) \ 8454.globl name; \ 8455 name: \ 8456 movl $SYS_ ## name, %eax; \ 8457 int $T_SYSCALL; \ 8458 ret 8459 8460 SYSCALL(fork) 8461 SYSCALL(exit) 8462 SYSCALL(wait) 8463 SYSCALL(pipe) 8464 SYSCALL(read) Xv6 uses a SYSCALL macro to define a function for each system call invocation E.g., fork() to invoke the fork system call

Example Write system call from cat.asm 00000362 <write>: SYSCALL(write) 362: b8 10 00 00 00 mov $0x10,%eax 367: cd 40 int $0x40 369: c3 ret

System call arguments Where are the system call arguments? How does kernel access them? And returns results?

Example Write system call if (write(1, buf, n)!= n) 5876 int 5877 sys_write(void) 5878 { 5879 struct file *f; 5880 int n; 5881 char *p; 5882 5883 5884 5885 5886 } if(argfd(0, 0, &f) < 0 argint(2, &n) < 0 argptr(1, &p, n) < 0) return 1; return filewrite(f, p, n);

Example Write system call if (write(1, buf, n)!= n) 5876 int 5877 sys_write(void) 5878 { 5879 struct file *f; 5880 int n; 5881 char *p; 5882 5883 5884 5885 5886 } if(argfd(0, 0, &f) < 0 argint(2, &n) < 0 argptr(1, &p, n) < 0) return 1; return filewrite(f, p, n);

3543 // Fetch the nth 32 bit system call argument. 3544 int 3545 argint(int n, int *ip) 3546 { 3547 return fetchint(proc >tf >esp + 4 + 4*n, ip); 3548 } 3515 // Fetch the int at addr from the current process. 3516 int 3517 fetchint(uint addr, int *ip) 3518 { 3519 3520 if(addr >= proc >sz addr+4 > proc >sz) return 1; 3521 *ip = *(int*)(addr); 3522 return 0; 3523 } argint(int n, int *ip)

3543 // Fetch the nth 32 bit system call argument. 3544 int 3545 argint(int n, int *ip) 3546 { 3547 return fetchint(proc >tf >esp + 4 + 4*n, ip); 3548 } 3515 // Fetch the int at addr from the current process. 3516 int 3517 fetchint(uint addr, int *ip) 3518 { 3519 3520 if(addr >= proc >sz addr+4 > proc >sz) return 1; 3521 *ip = *(int*)(addr); 3522 return 0; 3523 } argint(int n, int *ip)

3543 // Fetch the nth 32 bit system call argument. 3544 int 3545 argint(int n, int *ip) 3546 { 3547 return fetchint(proc >tf >esp + 4 + 4*n, ip); 3548 } Start with the address where current user stack is (esp) 3515 // Fetch the int at addr from the current process. 3516 int 3517 fetchint(uint addr, int *ip) 3518 { 3519 3520 if(addr >= proc >sz addr+4 > proc >sz) return 1; 3521 *ip = *(int*)(addr); 3522 return 0; 3523 } argint(int n, int *ip)

3543 // Fetch the nth 32 bit system call argument. 3544 int 3545 argint(int n, int *ip) Skip return eip 3546 { 3547 return fetchint(proc >tf >esp + 4 + 4*n, ip); 3548 } 3515 // Fetch the int at addr from the current process. 3516 int 3517 fetchint(uint addr, int *ip) 3518 { 3519 3520 if(addr >= proc >sz addr+4 > proc >sz) return 1; 3521 *ip = *(int*)(addr); 3522 return 0; 3523 } argint(int n, int *ip)

3543 // Fetch the nth 32 bit system call argument. 3544 int 3545 argint(int n, int *ip) 3546 { 3547 Fetch n'th argument return fetchint(proc >tf >esp + 4 + 4*n, ip); 3548 } 3515 // Fetch the int at addr from the current process. 3516 int 3517 fetchint(uint addr, int *ip) 3518 { 3519 3520 if(addr >= proc >sz addr+4 > proc >sz) return 1; 3521 *ip = *(int*)(addr); 3522 return 0; 3523 } argint(int n, int *ip)

3543 // Fetch the nth 32 bit system call argument. 3544 int 3545 argint(int n, int *ip) 3546 { 3547 return fetchint(proc >tf >esp + 4 + 4*n, ip); 3548 } 3515 // Fetch the int at addr from the current process. 3516 int 3517 fetchint(uint addr, int *ip) 3518 { 3519 3520 if(addr >= proc >sz addr+4 > proc >sz) return 1; 3521 *ip = *(int*)(addr); 3522 return 0; 3523 } fetchint(uint addr, int *ip)

3543 // Fetch the nth 32 bit system call argument. 3544 int 3545 argint(int n, int *ip) 3546 { 3547 return fetchint(proc >tf >esp + 4 + 4*n, ip); 3548 } 3515 // Fetch the int at addr from the current process. 3516 int 3517 fetchint(uint addr, int *ip) 3518 { 3519 3520 if(addr >= proc >sz addr+4 > proc >sz) return 1; 3521 *ip = *(int*)(addr); 3522 return 0; 3523 } fetchint(uint addr, int *ip)

Any idea for what argptr() shall do? Write system call if (write(1, buf, n)!= n) 5876 int 5877 sys_write(void) Remember, buf is a pointer to a region of memory 5878 { 5879 struct file *f; 5880 int n; 5881 char *p; i.e., a buffer of size n 5882 5883 5884 5885 5886 } if(argfd(0, 0, &f) < 0 argint(2, &n) < 0 argptr(1, &p, n) < 0) return 1; return filewrite(f, p, n);

3550 // Fetch the nth word sized system call argument as a pointer 3551 // to a block of memory of size n bytes. Check that the pointer 3552 // lies within the process address space. 3553 int 3554 argptr(int n, char **pp, int size) 3555 { 3556 int i; Check that the pointer to the buffer is sound 3557 3558 3559 3560 if(argint(n, &i) < 0) return 1; if((uint)i >= proc >sz (uint)i+size > proc >sz) 3561 return 1; 3562 *pp = (char*)i; 3563 return 0; 3564 } argptr(uint addr, int *ip)

3550 // Fetch the nth word sized system call argument as a pointer 3551 // to a block of memory of size n bytes. Check that the pointer 3552 // lies within the process address space. 3553 int 3554 argptr(int n, char **pp, int size) 3555 { 3556 int i; Check that the buffer is in user memory 3557 3558 3559 3560 if(argint(n, &i) < 0) return 1; if((uint)i >= proc >sz (uint)i+size > proc >sz) 3561 return 1; 3562 *pp = (char*)i; 3563 return 0; 3564 } argptr(uint addr, int *ip)

Summary We've learned how system calls work

Thank you

6225 sys_exec(void) 6226 { 6227 char *path, *argv[maxarg]; 6228 int i; 6229 uint uargv, uarg; sys_exec() 6230 6231 if(argstr(0, &path) < 0 argint(1, (int*)&uargv) < 0){ 6232 return 1; 6233 } 6234 memset(argv, 0, sizeof(argv)); 6235 for(i=0;; i++){ 6236 if(i >= NELEM(argv)) 6237 return 1; 6238 if(fetchint(uargv+4*i, (int*)&uarg) < 0) 6239 return 1; 6240 if(uarg == 0){ 6241 argv[i] = 0; 6242 break; 6243 } 6244 if(fetchstr(uarg, &argv[i]) < 0) 6245 return 1; 6246 } 6247 return exec(path, argv); 6248 }

6225 sys_exec(void) 6226 { 6227 char *path, *argv[maxarg]; 6228 int i; 6229 uint uargv, uarg; 6230 6231 if(argstr(0, &path) < 0 argint(1, (int*)&uargv) < 0){ 6232 6233 return 1; }... 6247 6248 } return exec(path, argv); sys_exec()