From 8f5576761954ce92b44c15284309baf45a27a4d6 Mon Sep 17 00:00:00 2001 From: Thomas Veerman Date: Fri, 13 Apr 2012 12:50:38 +0000 Subject: [PATCH] VFS: make m_in job local By making m_in job local (i.e., each job has its own copy of m_in instead of refering to the global m_in) we don't have to store and restore m_in on every thread yield. This reduces overhead. Moreover, remove the assumption that m_in is preserved. Do_XXX functions have to copy the system call parameters as soon as possible and only pass those copies to other functions. Furthermore, this patch cleans up some code and uses better types in a lot of places. --- servers/vfs/Makefile | 1 + servers/vfs/comm.c | 2 - servers/vfs/device.c | 51 +++--- servers/vfs/dmap.c | 16 +- servers/vfs/exec.c | 44 +++--- servers/vfs/filedes.c | 37 +++-- servers/vfs/fs.h | 14 -- servers/vfs/fscall.c | 8 +- servers/vfs/gcov.c | 13 +- servers/vfs/glo.h | 11 +- servers/vfs/link.c | 117 +++++++++----- servers/vfs/main.c | 359 +++++++++++++++++++++++++----------------- servers/vfs/misc.c | 94 ++++++----- servers/vfs/mount.c | 44 ++++-- servers/vfs/open.c | 153 +++++++++++------- servers/vfs/path.c | 10 +- servers/vfs/pipe.c | 61 ++----- servers/vfs/protect.c | 108 ++++++++----- servers/vfs/proto.h | 95 +++++------ servers/vfs/read.c | 19 ++- servers/vfs/request.c | 57 +++---- servers/vfs/select.c | 22 +-- servers/vfs/stadir.c | 170 +++++++++++++------- servers/vfs/time.c | 34 ++-- servers/vfs/utility.c | 72 ++++++--- servers/vfs/vmnt.c | 4 +- servers/vfs/vnode.c | 85 +--------- servers/vfs/worker.c | 35 ++-- 28 files changed, 951 insertions(+), 785 deletions(-) diff --git a/servers/vfs/Makefile b/servers/vfs/Makefile index 1abbfb7b1..e76b02655 100644 --- a/servers/vfs/Makefile +++ b/servers/vfs/Makefile @@ -14,6 +14,7 @@ SRCS+= gcov.c CPPFLAGS+= -DUSE_COVERAGE .endif +CFLAGS+= -Wall -Wextra DPADD+= ${LIBSYS} ${LIBTIMERS} ${LIBEXEC} LDADD+= -lsys -ltimers -lexec -lmthread diff --git a/servers/vfs/comm.c b/servers/vfs/comm.c index 17aec50ba..7a96875ec 100644 --- a/servers/vfs/comm.c +++ b/servers/vfs/comm.c @@ -19,9 +19,7 @@ struct fproc *rfp; */ int r, transid; - if (vmp->m_fs_e == rfp->fp_endpoint) return(EDEADLK); vmp->m_comm.c_cur_reqs++; /* One more request awaiting a reply */ - transid = rfp->fp_wtid + VFS_TRANSID; rfp->fp_sendrec->m_type = TRNS_ADD_ID(rfp->fp_sendrec->m_type, transid); rfp->fp_task = vmp->m_fs_e; diff --git a/servers/vfs/device.c b/servers/vfs/device.c index 4b6f7be2c..01ee494cb 100644 --- a/servers/vfs/device.c +++ b/servers/vfs/device.c @@ -267,8 +267,8 @@ void dev_status(message *m) * synchronous character driver */ endpt = st.REP_ENDPT; if (endpt == VFS_PROC_NR) { - endpt = find_suspended_ep(m->m_source,st.REP_IO_GRANT); - if(endpt == NONE) { + endpt = find_suspended_ep(m->m_source, st.REP_IO_GRANT); + if (endpt == NONE) { printf("VFS: proc with grant %d from %d not found\n", st.REP_IO_GRANT, st.m_source); continue; @@ -323,12 +323,14 @@ u32_t *pos_lo; case VFS_DEV_IOCTL: *pos_lo = *io_ept; /* Old endpoint in POSITION field. */ *op = DEV_IOCTL_S; - if(_MINIX_IOCTL_IOR(m_in.REQUEST)) access |= CPF_WRITE; - if(_MINIX_IOCTL_IOW(m_in.REQUEST)) access |= CPF_READ; - if(_MINIX_IOCTL_BIG(m_in.REQUEST)) - size = _MINIX_IOCTL_SIZE_BIG(m_in.REQUEST); + /* For IOCTLs, the bytes parameter encodes requested access method + * and buffer size */ + if(_MINIX_IOCTL_IOR(bytes)) access |= CPF_WRITE; + if(_MINIX_IOCTL_IOW(bytes)) access |= CPF_READ; + if(_MINIX_IOCTL_BIG(bytes)) + size = _MINIX_IOCTL_SIZE_BIG(bytes); else - size = _MINIX_IOCTL_SIZE(m_in.REQUEST); + size = _MINIX_IOCTL_SIZE(bytes); /* Grant access to the buffer even if no I/O happens with the ioctl, in * order to disambiguate requests with DEV_IOCTL_S. @@ -482,7 +484,7 @@ int dev_io( if (ret == SUSPEND) { if ((flags & O_NONBLOCK) && !is_asyn) { /* Not supposed to block. */ - ret = cancel_nblock(dp, minor_dev, call_nr, ioproc, gid); + ret = cancel_nblock(dp, minor_dev, job_call_nr, ioproc, gid); if (ret == EINTR) ret = EAGAIN; } else { @@ -497,7 +499,7 @@ int dev_io( if ((flags & O_NONBLOCK) && !is_asyn) { /* Not supposed to block, send cancel message */ - cancel_nblock(dp, minor_dev, call_nr, ioproc, gid); + cancel_nblock(dp, minor_dev, job_call_nr, ioproc, gid); /* * FIXME Should do something about EINTR -> EAGAIN * mapping @@ -630,8 +632,7 @@ int ctty_opcl( /*===========================================================================* * pm_setsid * *===========================================================================*/ -void pm_setsid(proc_e) -int proc_e; +void pm_setsid(endpoint_t proc_e) { /* Perform the VFS side of the SETSID call, i.e. get rid of the controlling * terminal of a process, and make the process a session leader. @@ -652,14 +653,17 @@ int proc_e; *===========================================================================*/ int do_ioctl() { -/* Perform the ioctl(ls_fd, request, argx) system call (uses m2 fmt). */ +/* Perform the ioctl(ls_fd, request, argx) system call */ - int r = OK, suspend_reopen; + int r = OK, suspend_reopen, ioctlrequest; struct filp *f; register struct vnode *vp; dev_t dev; + void *argx; - scratch(fp).file.fd_nr = m_in.ls_fd; + scratch(fp).file.fd_nr = job_m_in.ls_fd; + ioctlrequest = job_m_in.REQUEST; + argx = job_m_in.ADDRESS; if ((f = get_filp(scratch(fp).file.fd_nr, VNODE_READ)) == NULL) return(err_code); @@ -674,10 +678,10 @@ int do_ioctl() dev = (dev_t) vp->v_sdev; if ((vp->v_mode & I_TYPE) == I_BLOCK_SPECIAL) - r = bdev_ioctl(dev, who_e, m_in.REQUEST, m_in.ADDRESS); + r = bdev_ioctl(dev, who_e, ioctlrequest, argx); else - r = dev_io(VFS_DEV_IOCTL, dev, who_e, m_in.ADDRESS, cvu64(0), - m_in.REQUEST, f->filp_flags, suspend_reopen); + r = dev_io(VFS_DEV_IOCTL, dev, who_e, argx, cvu64(0), + ioctlrequest, f->filp_flags, suspend_reopen); } unlock_filp(f); @@ -1038,11 +1042,12 @@ void open_reply(void) endpoint_t proc_e; int slot; - proc_e = m_in.REP_ENDPT; + proc_e = job_m_in.REP_ENDPT; if (isokendpt(proc_e, &slot) != OK) return; rfp = &fproc[slot]; - *rfp->fp_sendrec = m_in; - worker_signal(worker_get(rfp->fp_wtid)); /* Continue open */ + *rfp->fp_sendrec = job_m_in; + if (rfp->fp_wtid != invalid_thread_id) + worker_signal(worker_get(rfp->fp_wtid)); /* Continue open */ } /*===========================================================================* @@ -1146,9 +1151,9 @@ void reopen_reply() struct vnode *vp; struct dmap *dp; - driver_e = m_in.m_source; - filp_no = m_in.REP_ENDPT; - status = m_in.REP_STATUS; + driver_e = job_m_in.m_source; + filp_no = job_m_in.REP_ENDPT; + status = job_m_in.REP_STATUS; if (filp_no < 0 || filp_no >= NR_FILPS) { printf("VFS: reopen_reply: bad filp number %d from driver %d\n", diff --git a/servers/vfs/dmap.c b/servers/vfs/dmap.c index 763ae85ff..54235e29d 100644 --- a/servers/vfs/dmap.c +++ b/servers/vfs/dmap.c @@ -35,7 +35,7 @@ int do_mapdriver() * etc), and its label. This label is registered with DS, and allows us to * retrieve the driver's endpoint. */ - int r, flags, major; + int r, flags, major, style; endpoint_t endpoint; vir_bytes label_vir; size_t label_len; @@ -44,10 +44,13 @@ int do_mapdriver() /* Only RS can map drivers. */ if (who_e != RS_PROC_NR) return(EPERM); - /* Get the label */ - label_vir = (vir_bytes) m_in.md_label; - label_len = (size_t) m_in.md_label_len; + label_vir = (vir_bytes) job_m_in.md_label; + label_len = (size_t) job_m_in.md_label_len; + major = job_m_in.md_major; + flags = job_m_in.md_flags; + style = job_m_in.md_style; + /* Get the label */ if (label_len+1 > sizeof(label)) { /* Can we store this label? */ printf("VFS: do_mapdriver: label too long\n"); return(EINVAL); @@ -67,10 +70,7 @@ int do_mapdriver() } /* Try to update device mapping. */ - major = m_in.md_major; - flags = m_in.md_flags; - - return map_driver(label, major, endpoint, m_in.md_style, flags); + return map_driver(label, major, endpoint, style, flags); } /*===========================================================================* diff --git a/servers/vfs/exec.c b/servers/vfs/exec.c index b3baa67e0..de0c22983 100644 --- a/servers/vfs/exec.c +++ b/servers/vfs/exec.c @@ -37,16 +37,16 @@ static void lock_exec(void); static void unlock_exec(void); -static int exec_newmem(int proc_e, vir_bytes text_addr, vir_bytes - text_bytes, vir_bytes data_addr, vir_bytes data_bytes, vir_bytes - tot_bytes, vir_bytes frame_len, int sep_id, int is_elf, dev_t st_dev, +static int exec_newmem(int proc_e, vir_bytes text_addr, vir_bytes text_bytes, + vir_bytes data_addr, vir_bytes data_bytes, vir_bytes tot_bytes, + vir_bytes frame_len, int sep_id, int is_elf, dev_t st_dev, ino_t st_ino, time_t ctime, char *progname, int new_uid, int new_gid, vir_bytes *stack_topp, int *load_textp, int *setugidp); static int is_script(const char *exec_hdr, size_t exec_len); -static int patch_stack(struct vnode *vp, char stack[ARG_MAX], vir_bytes - *stk_bytes, char path[PATH_MAX]); -static int insert_arg(char stack[ARG_MAX], vir_bytes *stk_bytes, char - *arg, int replace); +static int patch_stack(struct vnode *vp, char stack[ARG_MAX], + size_t *stk_bytes, char path[PATH_MAX]); +static int insert_arg(char stack[ARG_MAX], size_t *stk_bytes, char *arg, + int replace); static void patch_ptr(char stack[ARG_MAX], vir_bytes base); static void clo_exec(struct fproc *rfp); static int read_seg(struct vnode *vp, off_t off, int proc_e, int seg, @@ -75,7 +75,6 @@ static char hdr[PAGE_SIZE]; /* Assume that header is not larger than a page */ *===========================================================================*/ static void lock_exec(void) { - message org_m_in; struct fproc *org_fp; struct worker_thread *org_self; @@ -83,14 +82,12 @@ static void lock_exec(void) if (mutex_trylock(&exec_lock) == 0) return; - org_m_in = m_in; org_fp = fp; org_self = self; if (mutex_lock(&exec_lock) != 0) panic("Could not obtain lock on exec"); - m_in = org_m_in; fp = org_fp; self = org_self; } @@ -107,8 +104,8 @@ static void unlock_exec(void) /*===========================================================================* * pm_exec * *===========================================================================*/ -int pm_exec(int proc_e, char *path, vir_bytes path_len, char *frame, - vir_bytes frame_len, vir_bytes *pc) +int pm_exec(endpoint_t proc_e, vir_bytes path, size_t path_len, + vir_bytes frame, size_t frame_len, vir_bytes *pc) { /* Perform the execve(name, argv, envp) call. The user library builds a * complete stack image, including pointers, args, environ, etc. The stack @@ -137,7 +134,7 @@ int pm_exec(int proc_e, char *path, vir_bytes path_len, char *frame, resolve.l_vnode_lock = VNODE_READ; /* Get the exec file name. */ - if ((r = fetch_name(path, path_len, 0, fullpath)) != OK) + if ((r = fetch_name(path, path_len, fullpath)) != OK) goto pm_execfinal; /* Fetch the stack from the user before destroying the old core image. */ @@ -146,7 +143,7 @@ int pm_exec(int proc_e, char *path, vir_bytes path_len, char *frame, goto pm_execfinal; } r = sys_datacopy(proc_e, (vir_bytes) frame, SELF, (vir_bytes) mbuf, - (phys_bytes) frame_len); + (size_t) frame_len); if (r != OK) { /* can't fetch stack (e.g. bad virtual addr) */ printf("VFS: pm_exec: sys_datacopy failed\n"); goto pm_execfinal; @@ -179,7 +176,7 @@ int pm_exec(int proc_e, char *path, vir_bytes path_len, char *frame, r = r1; else r = req_stat(vp->v_fs_e, vp->v_inode_nr, VFS_PROC_NR, - (char *) &(execi.sb), 0, 0); + (vir_bytes) &(execi.sb), 0, 0); if (r != OK) goto pm_execfinal; if (round == 0) { @@ -201,7 +198,7 @@ int pm_exec(int proc_e, char *path, vir_bytes path_len, char *frame, break; /* Get fresh copy of the file name. */ - if ((r = fetch_name(path, path_len, 0, fullpath)) != OK) + if ((r = fetch_name(path, path_len, fullpath)) != OK) printf("VFS pm_exec: 2nd fetch_name failed\n"); else r = patch_stack(vp, mbuf, &frame_len, fullpath); @@ -287,9 +284,9 @@ static int load_aout(struct exec_info *execi) r = exec_newmem(proc_e, 0 /* text_addr */, text_bytes, 0 /* data_addr */, data_bytes + bss_bytes, tot_bytes, - execi->frame_len, sep_id, 0 /* is_elf */, vp->v_dev, vp->v_inode_nr, - execi->sb.st_ctime, - execi->progname, execi->new_uid, execi->new_gid, + execi->frame_len, sep_id, 0 /* is_elf */, vp->v_dev, + vp->v_inode_nr, execi->sb.st_ctime, execi->progname, + execi->new_uid, execi->new_gid, &execi->stack_top, &execi->load_text, &execi->setugid); if (r != OK) { @@ -441,7 +438,7 @@ static int is_script(const char *exec_hdr, size_t exec_len) static int patch_stack(vp, stack, stk_bytes, path) struct vnode *vp; /* pointer for open script file */ char stack[ARG_MAX]; /* pointer to stack image within VFS */ -vir_bytes *stk_bytes; /* size of initial stack */ +size_t *stk_bytes; /* size of initial stack */ char path[PATH_MAX]; /* path to script file */ { /* Patch the argument vector to include the path name of the script to be @@ -514,7 +511,7 @@ char path[PATH_MAX]; /* path to script file */ *===========================================================================*/ static int insert_arg( char stack[ARG_MAX], /* pointer to stack image within PM */ -vir_bytes *stk_bytes, /* size of initial stack */ +size_t *stk_bytes, /* size of initial stack */ char *arg, /* argument to prepend/replace as new argv[0] */ int replace ) @@ -526,7 +523,8 @@ int replace * pointers are really offsets from the start of stack. * Return true iff the operation succeeded. */ - int offset, a0, a1, old_bytes = *stk_bytes; + int offset, a0, a1; + size_t old_bytes = *stk_bytes; /* Prepending arg adds at least one string and a zero byte. */ offset = strlen(arg) + 1; @@ -668,7 +666,7 @@ phys_bytes seg_bytes /* how much is to be transferred? */ } if (r == OK && cum_io != seg_bytes) - printf("VFS: read_seg segment has not been read properly by exec()\n"); + printf("VFS: read_seg segment has not been read properly\n"); return(r); } diff --git a/servers/vfs/filedes.c b/servers/vfs/filedes.c index 64a41629c..b681ee8f4 100644 --- a/servers/vfs/filedes.c +++ b/servers/vfs/filedes.c @@ -41,7 +41,7 @@ void check_filp_locks_by_me(void) r = mutex_trylock(&f->filp_lock); if (r == -EDEADLK) panic("Thread %d still holds filp lock on filp %p call_nr=%d\n", - mthread_self(), f, call_nr); + mthread_self(), f, job_call_nr); else if (r == 0) { /* We just obtained the lock, release it */ mutex_unlock(&f->filp_lock); @@ -243,7 +243,6 @@ void lock_filp(filp, locktype) struct filp *filp; tll_access_t locktype; { - message org_m_in; struct fproc *org_fp; struct worker_thread *org_self; struct vnode *vp; @@ -269,14 +268,12 @@ tll_access_t locktype; if (mutex_trylock(&filp->filp_lock) != 0) { /* Already in use, let's wait for our turn */ - org_m_in = m_in; org_fp = fp; org_self = self; if (mutex_lock(&filp->filp_lock) != 0) panic("unable to obtain lock on filp"); - m_in = org_m_in; fp = org_fp; self = org_self; } @@ -369,7 +366,13 @@ int fd; int do_verify_fd(void) { struct filp *rfilp; - rfilp = (struct filp *) verify_fd(m_in.USER_ENDPT, m_in.COUNT); + endpoint_t proc_e; + int fd; + + proc_e = job_m_in.USER_ENDPT; + fd = job_m_in.COUNT; + + rfilp = (struct filp *) verify_fd(proc_e, fd); m_out.ADDRESS = (void *) rfilp; if (rfilp != NULL) unlock_filp(rfilp); return (rfilp != NULL) ? OK : EINVAL; @@ -395,7 +398,9 @@ filp_id_t sfilp; *===========================================================================*/ int do_set_filp(void) { - return set_filp((filp_id_t) m_in.ADDRESS); + filp_id_t f; + f = (filp_id_t) job_m_in.ADDRESS; + return set_filp(f); } /*===========================================================================* @@ -434,7 +439,13 @@ filp_id_t cfilp; *===========================================================================*/ int do_copy_filp(void) { - return copy_filp(m_in.USER_ENDPT, (filp_id_t) m_in.ADDRESS); + endpoint_t proc_e; + filp_id_t f; + + proc_e = job_m_in.USER_ENDPT; + f = (filp_id_t) job_m_in.ADDRESS; + + return copy_filp(proc_e, f); } /*===========================================================================* @@ -457,7 +468,9 @@ filp_id_t pfilp; *===========================================================================*/ int do_put_filp(void) { - return put_filp((filp_id_t) m_in.ADDRESS); + filp_id_t f; + f = (filp_id_t) job_m_in.ADDRESS; + return put_filp(f); } /*===========================================================================* @@ -500,7 +513,13 @@ int fd; *===========================================================================*/ int do_cancel_fd(void) { - return cancel_fd(m_in.USER_ENDPT, m_in.COUNT); + endpoint_t proc_e; + int fd; + + proc_e = job_m_in.USER_ENDPT; + fd = job_m_in.COUNT; + + return cancel_fd(proc_e, fd); } /*===========================================================================* diff --git a/servers/vfs/fs.h b/servers/vfs/fs.h index d3fc953b3..125692131 100644 --- a/servers/vfs/fs.h +++ b/servers/vfs/fs.h @@ -8,20 +8,6 @@ #define _MINIX 1 /* tell headers to include MINIX stuff */ #define _SYSTEM 1 /* tell headers that this is the kernel */ -#define DO_SANITYCHECKS 0 - -#if DO_SANITYCHECKS -#define SANITYCHECK do { \ - if(!check_vrefs() || !check_pipe()) { \ - printf("VFS:%s:%d: call_nr %d who_e %d\n", \ - __FILE__, __LINE__, call_nr, who_e); \ - panic("sanity check failed"); \ - } \ -} while(0) -#else -#define SANITYCHECK -#endif - /* The following are so basic, all the *.c files get them automatically. */ #include /* MUST be first */ #include diff --git a/servers/vfs/fscall.c b/servers/vfs/fscall.c index dd40089ec..ca812b150 100644 --- a/servers/vfs/fscall.c +++ b/servers/vfs/fscall.c @@ -48,7 +48,7 @@ static int push_globals() return(EPERM); globals[depth].g_fp = fp; - globals[depth].g_m_in = m_in; + globals[depth].g_m_in = job_m_in; globals[depth].g_m_out = m_out; globals[depth].g_super_user = super_user; @@ -71,7 +71,7 @@ static void pop_globals() depth--; fp = globals[depth].g_fp; - m_in = globals[depth].g_m_in; + job_m_in = globals[depth].g_m_in; m_out = globals[depth].g_m_out; } @@ -113,10 +113,10 @@ message *m; /* request/reply message pointer */ set_globals(m); /* Perform the nested call - only getsysinfo() is allowed right now */ - if (call_nr == COMMON_GETSYSINFO) { + if (job_call_nr == COMMON_GETSYSINFO) { r = do_getsysinfo(); } else { - printf("VFS: invalid nested call %d from FS %d\n", call_nr, + printf("VFS: invalid nested call %d from FS %d\n", job_call_nr, who_e); r = ENOSYS; diff --git a/servers/vfs/gcov.c b/servers/vfs/gcov.c index 5e8e5ac37..683a2bf82 100644 --- a/servers/vfs/gcov.c +++ b/servers/vfs/gcov.c @@ -22,9 +22,11 @@ int do_gcov_flush() int r, n; pid_t target; message m; + vir_bytes buf; - size = m_in.GCOV_BUFF_SZ; - target = m_in.GCOV_PID; + size = job_m_in.GCOV_BUFF_SZ; + target = job_m_in.GCOV_PID; + buf = (vir_bytes) job_m_in.GCOV_BUFF_P; /* If the wrong process is sent to, the system hangs; so make this root-only. */ @@ -43,14 +45,13 @@ int do_gcov_flush() rfp = &fproc[n]; /* Grant target process to requestor's buffer. */ - if ((grantid = cpf_grant_magic(rfp->fp_endpoint, who_e, - (vir_bytes) m_in.GCOV_BUFF_P, size, - CPF_WRITE)) < 0) { + if ((grantid = cpf_grant_magic(rfp->fp_endpoint, who_e, buf, + size, CPF_WRITE)) < 0) { printf("VFS: gcov_flush: grant failed\n"); return(ENOMEM); } - if(rfp->fp_endpoint == VFS_PROC_NR) { + if (rfp->fp_endpoint == VFS_PROC_NR) { /* Request is for VFS itself. */ r = gcov_flush(grantid, size); } else { diff --git a/servers/vfs/glo.h b/servers/vfs/glo.h index 94586e8b4..e2603ae62 100644 --- a/servers/vfs/glo.h +++ b/servers/vfs/glo.h @@ -25,13 +25,11 @@ EXTERN message m_out; /* the output message used for reply */ # define who_p ((int) (fp - fproc)) # define isokslot(p) (p >= 0 && \ p < (int)(sizeof(fproc) / sizeof(struct fproc))) -#if 0 -# define who_e (isokslot(who_p) ? fp->fp_endpoint : m_in.m_source) -#else -# define who_e (isokslot(who_p) && fp->fp_endpoint != NONE ? \ - fp->fp_endpoint : m_in.m_source) -#endif +# define who_e (self != NULL && fp != NULL ? fp->fp_endpoint : \ + m_in.m_source) # define call_nr (m_in.m_type) +# define job_m_in (self->w_job.j_m_in) +# define job_call_nr (job_m_in.m_type) # define super_user (fp->fp_effuid == SU_UID ? 1 : 0) # define scratch(p) (scratchpad[((int) ((p) - fproc))]) EXTERN struct worker_thread *self; @@ -42,6 +40,7 @@ EXTERN mutex_t bsf_lock;/* Global lock for access to block special files */ EXTERN struct worker_thread workers[NR_WTHREADS]; EXTERN struct worker_thread sys_worker; EXTERN struct worker_thread dl_worker; +EXTERN thread_t invalid_thread_id; EXTERN char mount_label[LABEL_MAX]; /* label of file system to mount */ /* The following variables are used for returning results to the caller. */ diff --git a/servers/vfs/link.c b/servers/vfs/link.c index a110b7058..e6bfeb253 100644 --- a/servers/vfs/link.c +++ b/servers/vfs/link.c @@ -24,6 +24,7 @@ #include "path.h" #include "vnode.h" #include "param.h" +#include "scratchpad.h" /*===========================================================================* * do_link * @@ -36,21 +37,27 @@ int do_link() struct vmnt *vmp1 = NULL, *vmp2 = NULL; char fullpath[PATH_MAX]; struct lookup resolve; + vir_bytes vname1, vname2; + size_t vname1_length, vname2_length; + + vname1 = (vir_bytes) job_m_in.name1; + vname1_length = job_m_in.name1_length; + vname2 = (vir_bytes) job_m_in.name2; + vname2_length = job_m_in.name2_length; lookup_init(&resolve, fullpath, PATH_NOFLAGS, &vmp1, &vp); resolve.l_vmnt_lock = VMNT_WRITE; resolve.l_vnode_lock = VNODE_READ; /* See if 'name1' (file to be linked to) exists. */ - if (fetch_name(m_in.name1, m_in.name1_length, M1, fullpath) != OK) - return(err_code); + if (fetch_name(vname1, vname1_length, fullpath) != OK) return(err_code); if ((vp = eat_path(&resolve, fp)) == NULL) return(err_code); /* Does the final directory of 'name2' exist? */ lookup_init(&resolve, fullpath, PATH_NOFLAGS, &vmp2, &dirp); resolve.l_vmnt_lock = VMNT_READ; resolve.l_vnode_lock = VNODE_READ; - if (fetch_name(m_in.name2, m_in.name2_length, M1, fullpath) != OK) + if (fetch_name(vname2, vname2_length, fullpath) != OK) r = err_code; else if ((dirp = last_dir(&resolve, fp)) == NULL) r = err_code; @@ -81,7 +88,6 @@ int do_link() return(r); } - /*===========================================================================* * do_unlink * *===========================================================================*/ @@ -90,23 +96,31 @@ int do_unlink() /* Perform the unlink(name) or rmdir(name) system call. The code for these two * is almost the same. They differ only in some condition testing. Unlink() * may be used by the superuser to do dangerous things; rmdir() may not. + * The syscall might provide 'name' embedded in the message. */ struct vnode *dirp, *vp; struct vmnt *vmp, *vmp2; int r; char fullpath[PATH_MAX]; struct lookup resolve; + vir_bytes vname; + size_t vname_length; + + vname = (vir_bytes) job_m_in.name; + vname_length = job_m_in.name_length; + if (copy_name(vname_length, fullpath) != OK) { + /* Direct copy failed, try fetching from user space */ + if (fetch_name(vname, vname_length, fullpath) != OK) + return(err_code); + } lookup_init(&resolve, fullpath, PATH_RET_SYMLINK, &vmp, &dirp); resolve.l_vmnt_lock = VMNT_WRITE; resolve.l_vnode_lock = VNODE_READ; /* Get the last directory in the path. */ - if (fetch_name(m_in.name, m_in.name_length, M3, fullpath) != OK) - return(err_code); - if ((dirp = last_dir(&resolve, fp)) == NULL) return(err_code); - assert(vmp != NULL); + assert(vmp != NULL); /* We must have locked the vmnt */ /* Make sure that the object is a directory */ if ((dirp->v_mode & I_TYPE) != I_DIRECTORY) { @@ -153,7 +167,7 @@ int do_unlink() assert(vmp != NULL); tll_upgrade(&vmp->m_lock); - if (call_nr == UNLINK) + if (job_call_nr == UNLINK) r = req_unlink(dirp->v_fs_e, dirp->v_inode_nr, fullpath); else r = req_rmdir(dirp->v_fs_e, dirp->v_inode_nr, fullpath); @@ -175,6 +189,13 @@ int do_rename() char old_name[PATH_MAX]; char fullpath[PATH_MAX]; struct lookup resolve; + vir_bytes vname1, vname2; + size_t vname1_length, vname2_length; + + vname1 = (vir_bytes) job_m_in.name1; + vname1_length = job_m_in.name1_length; + vname2 = (vir_bytes) job_m_in.name2; + vname2_length = job_m_in.name2_length; lookup_init(&resolve, fullpath, PATH_NOFLAGS, &oldvmp, &old_dirp); /* Do not yet request exclusive lock on vmnt to prevent deadlocks later on */ @@ -182,10 +203,8 @@ int do_rename() resolve.l_vnode_lock = VNODE_READ; /* See if 'name1' (existing file) exists. Get dir and file inodes. */ - if (fetch_name(m_in.name1, m_in.name1_length, M1, fullpath) != OK) - return(err_code); - if ((old_dirp = last_dir(&resolve, fp)) == NULL) - return(err_code); + if (fetch_name(vname1, vname1_length, fullpath) != OK) return(err_code); + if ((old_dirp = last_dir(&resolve, fp)) == NULL) return(err_code); /* If the sticky bit is set, only the owner of the file or a privileged user is allowed to rename */ @@ -212,7 +231,7 @@ int do_rename() } /* Save the last component of the old name */ - if(strlen(fullpath) >= sizeof(old_name)) { + if (strlen(fullpath) >= sizeof(old_name)) { unlock_vnode(old_dirp); unlock_vmnt(oldvmp); put_vnode(old_dirp); @@ -224,10 +243,8 @@ int do_rename() lookup_init(&resolve, fullpath, PATH_NOFLAGS, &newvmp, &new_dirp); resolve.l_vmnt_lock = VMNT_READ; resolve.l_vnode_lock = VNODE_READ; - if (fetch_name(m_in.name2, m_in.name2_length, M1, fullpath) != OK) - r = err_code; - else if ((new_dirp = last_dir(&resolve, fp)) == NULL) - r = err_code; + if (fetch_name(vname2, vname2_length, fullpath) != OK) r = err_code; + else if ((new_dirp = last_dir(&resolve, fp)) == NULL) r = err_code; if (r != OK) { unlock_vnode(old_dirp); @@ -274,20 +291,27 @@ int do_truncate() int r; char fullpath[PATH_MAX]; struct lookup resolve; + off_t length; + vir_bytes vname; + size_t vname_length; + + vname = (vir_bytes) job_m_in.m2_p1; + vname_length = job_m_in.m2_i1; lookup_init(&resolve, fullpath, PATH_NOFLAGS, &vmp, &vp); resolve.l_vmnt_lock = VMNT_EXCL; resolve.l_vnode_lock = VNODE_WRITE; - if ((off_t) m_in.flength < 0) return(EINVAL); + length = (off_t) job_m_in.flength; + if (length < 0) return(EINVAL); /* Temporarily open file */ - if (fetch_name(m_in.m2_p1, m_in.m2_i1, M1, fullpath) != OK) return(err_code); + if (fetch_name(vname, vname_length, fullpath) != OK) return(err_code); if ((vp = eat_path(&resolve, fp)) == NULL) return(err_code); /* Ask FS to truncate the file */ if ((r = forbidden(fp, vp, W_BIT)) == OK) - r = truncate_vnode(vp, m_in.flength); + r = truncate_vnode(vp, length); unlock_vnode(vp); unlock_vmnt(vmp); @@ -303,16 +327,21 @@ int do_ftruncate() /* As with do_truncate(), truncate_vnode() does the actual work. */ struct filp *rfilp; int r; + off_t length; + + scratch(fp).file.fd_nr = job_m_in.fd; + length = (off_t) job_m_in.flength; - if ((off_t) m_in.flength < 0) return(EINVAL); + if (length < 0) return(EINVAL); /* File is already opened; get a vnode pointer from filp */ - if ((rfilp = get_filp(m_in.m2_i1, VNODE_WRITE)) == NULL) return(err_code); + if ((rfilp = get_filp(scratch(fp).file.fd_nr, VNODE_WRITE)) == NULL) + return(err_code); if (!(rfilp->filp_mode & W_BIT)) r = EBADF; else - r = truncate_vnode(rfilp->filp_vno, m_in.flength); + r = truncate_vnode(rfilp->filp_vno, length); unlock_filp(rfilp); return(r); @@ -349,23 +378,27 @@ int do_slink() struct vmnt *vmp; char fullpath[PATH_MAX]; struct lookup resolve; + vir_bytes vname1, vname2; + size_t vname1_length, vname2_length; lookup_init(&resolve, fullpath, PATH_NOFLAGS, &vmp, &vp); resolve.l_vmnt_lock = VMNT_WRITE; resolve.l_vnode_lock = VNODE_READ; - if (m_in.name1_length <= 1) return(ENOENT); - if (m_in.name1_length >= SYMLINK_MAX) return(ENAMETOOLONG); + vname1 = (vir_bytes) job_m_in.name1; + vname1_length = job_m_in.name1_length; + vname2 = (vir_bytes) job_m_in.name2; + vname2_length = job_m_in.name2_length; - /* Get dir inode of 'name2' */ - if (fetch_name(m_in.name2, m_in.name2_length, M1, fullpath) != OK) - return(err_code); + if (vname1_length <= 1) return(ENOENT); + if (vname1_length >= SYMLINK_MAX) return(ENAMETOOLONG); + /* Get dir inode of 'name2' */ + if (fetch_name(vname2, vname2_length, fullpath) != OK) return(err_code); if ((vp = last_dir(&resolve, fp)) == NULL) return(err_code); - if ((r = forbidden(fp, vp, W_BIT|X_BIT)) == OK) { r = req_slink(vp->v_fs_e, vp->v_inode_nr, fullpath, who_e, - m_in.name1, m_in.name1_length - 1, fp->fp_effuid, + vname1, vname1_length - 1, fp->fp_effuid, fp->fp_effgid); } @@ -404,7 +437,7 @@ struct fproc *rfp; if ((vp->v_mode & I_TYPE) != I_SYMBOLIC_LINK) r = EINVAL; else - r = req_rdlink(vp->v_fs_e, vp->v_inode_nr, NONE, link_path, + r = req_rdlink(vp->v_fs_e, vp->v_inode_nr, NONE, (vir_bytes) link_path, PATH_MAX - 1, 1); if (r > 0) link_path[r] = '\0'; /* Terminate string when succesful */ @@ -422,30 +455,34 @@ struct fproc *rfp; int do_rdlink() { /* Perform the readlink(name, buf, bufsize) system call. */ - int r, copylen; + int r; struct vnode *vp; struct vmnt *vmp; char fullpath[PATH_MAX]; struct lookup resolve; + vir_bytes vname; + size_t vname_length, buf_size; + vir_bytes buf; + + vname = (vir_bytes) job_m_in.name1; + vname_length = job_m_in.name1_length; + buf = (vir_bytes) job_m_in.name2; + buf_size = (size_t) job_m_in.nbytes; + if (buf_size > SSIZE_MAX) return(EINVAL); lookup_init(&resolve, fullpath, PATH_RET_SYMLINK, &vmp, &vp); resolve.l_vmnt_lock = VMNT_READ; resolve.l_vnode_lock = VNODE_READ; - copylen = m_in.nbytes; - if (copylen < 0) return(EINVAL); - /* Temporarily open the file containing the symbolic link */ - if (fetch_name(m_in.name1, m_in.name1_length, M1, fullpath) != OK) - return(err_code); + if (fetch_name(vname, vname_length, fullpath) != OK) return(err_code); if ((vp = eat_path(&resolve, fp)) == NULL) return(err_code); /* Make sure this is a symbolic link */ if ((vp->v_mode & I_TYPE) != I_SYMBOLIC_LINK) r = EINVAL; else - r = req_rdlink(vp->v_fs_e, vp->v_inode_nr, who_e, m_in.name2, - copylen, 0); + r = req_rdlink(vp->v_fs_e, vp->v_inode_nr, who_e, buf, buf_size, 0); unlock_vnode(vp); unlock_vmnt(vmp); diff --git a/servers/vfs/main.c b/servers/vfs/main.c index 65cda8217..56eb1b84c 100644 --- a/servers/vfs/main.c +++ b/servers/vfs/main.c @@ -40,8 +40,7 @@ EXTERN unsigned long calls_stats[NCALLS]; #endif /* Thread related prototypes */ -static void thread_cleanup_f(struct fproc *rfp, char *f, int l); -#define thread_cleanup(x) thread_cleanup_f(x, __FILE__, __LINE__) +static void thread_cleanup(struct fproc *rfp); static void *do_async_dev_result(void *arg); static void *do_control_msgs(void *arg); static void *do_fs_reply(struct job *job); @@ -83,6 +82,7 @@ int main(void) /* This is the main loop that gets work, processes it, and sends replies. */ while (TRUE) { yield_all(); /* let other threads run */ + self = NULL; send_work(); get_work(); @@ -141,8 +141,11 @@ static void handle_work(void *(*func)(void *arg)) /* Handle asynchronous device replies and new system calls. If the originating * endpoint is an FS endpoint, take extra care not to get in deadlock. */ struct vmnt *vmp = NULL; + endpoint_t proc_e; - if ((vmp = find_vmnt(who_e)) != NULL) { + proc_e = m_in.m_source; + + if ((vmp = find_vmnt(proc_e)) != NULL) { /* A call back or dev result from an FS endpoint */ /* Set call back flag. We assume that an FS does only one call back @@ -162,7 +165,7 @@ static void handle_work(void *(*func)(void *arg)) /* Already trying to resolve a deadlock, can't * handle more, sorry */ vmp->m_flags &= ~VMNT_CALLBACK; - reply(who_e, EAGAIN); + reply(proc_e, EAGAIN); return; } deadlock_resolving = 1; @@ -175,7 +178,7 @@ static void handle_work(void *(*func)(void *arg)) } /*===========================================================================* - * do_async_dev_result * + * do_async_dev_result * *===========================================================================*/ static void *do_async_dev_result(void *arg) { @@ -184,29 +187,31 @@ static void *do_async_dev_result(void *arg) my_job = *((struct job *) arg); fp = my_job.j_fp; - m_in = my_job.j_m_in; /* An asynchronous character driver has results for us */ - if (call_nr == DEV_REVIVE) { - endpt = m_in.REP_ENDPT; + if (job_call_nr == DEV_REVIVE) { + endpt = job_m_in.REP_ENDPT; if (endpt == VFS_PROC_NR) - endpt = find_suspended_ep(m_in.m_source, m_in.REP_IO_GRANT); + endpt = find_suspended_ep(job_m_in.m_source, + job_m_in.REP_IO_GRANT); if (endpt == NONE) { printf("VFS: proc with grant %d from %d not found\n", - m_in.REP_IO_GRANT, m_in.m_source); - } else if (m_in.REP_STATUS == SUSPEND) { + job_m_in.REP_IO_GRANT, job_m_in.m_source); + } else if (job_m_in.REP_STATUS == SUSPEND) { printf("VFS: got SUSPEND on DEV_REVIVE: not reviving proc\n"); } else - revive(endpt, m_in.REP_STATUS); + revive(endpt, job_m_in.REP_STATUS); } - else if (call_nr == DEV_OPEN_REPL) open_reply(); - else if (call_nr == DEV_REOPEN_REPL) reopen_reply(); - else if (call_nr == DEV_CLOSE_REPL) close_reply(); - else if (call_nr == DEV_SEL_REPL1) - select_reply1(m_in.m_source, m_in.DEV_MINOR, m_in.DEV_SEL_OPS); - else if (call_nr == DEV_SEL_REPL2) - select_reply2(m_in.m_source, m_in.DEV_MINOR, m_in.DEV_SEL_OPS); + else if (job_call_nr == DEV_OPEN_REPL) open_reply(); + else if (job_call_nr == DEV_REOPEN_REPL) reopen_reply(); + else if (job_call_nr == DEV_CLOSE_REPL) close_reply(); + else if (job_call_nr == DEV_SEL_REPL1) + select_reply1(job_m_in.m_source, job_m_in.DEV_MINOR, + job_m_in.DEV_SEL_OPS); + else if (job_call_nr == DEV_SEL_REPL2) + select_reply2(job_m_in.m_source, job_m_in.DEV_MINOR, + job_m_in.DEV_SEL_OPS); if (deadlock_resolving) { if (fp != NULL && fp->fp_wtid == dl_worker.w_tid) @@ -233,18 +238,17 @@ static void *do_control_msgs(void *arg) my_job = *((struct job *) arg); fp = my_job.j_fp; - m_in = my_job.j_m_in; /* Check for special control messages. */ - if (who_e == CLOCK) { + if (job_m_in.m_source == CLOCK) { /* Alarm timer expired. Used only for select(). Check it. */ - expire_timers(m_in.NOTIFY_TIMESTAMP); - } else if (who_e == DS_PROC_NR) { + expire_timers(job_m_in.NOTIFY_TIMESTAMP); + } else if (job_m_in.m_source == DS_PROC_NR) { /* DS notifies us of an event. */ ds_event(); } else { /* Device notifies us of an event. */ - dev_status(&m_in); + dev_status(&job_m_in); } thread_cleanup(NULL); @@ -273,8 +277,9 @@ static void *do_fs_reply(struct job *job) printf("VFS: expected %d to reply, not %d\n", rfp->fp_task, who_e); *rfp->fp_sendrec = m_in; rfp->fp_task = NONE; - vmp->m_comm.c_cur_reqs--; /* We've got our reply, make room for others */ - worker_signal(worker_get(rfp->fp_wtid));/* Continue this worker thread */ + vmp->m_comm.c_cur_reqs--; /* We've got our reply, make room for others */ + if (rfp->fp_wtid != invalid_thread_id) + worker_signal(worker_get(rfp->fp_wtid)); /* Continue this thread */ return(NULL); } @@ -283,7 +288,6 @@ static void *do_fs_reply(struct job *job) *===========================================================================*/ static void lock_pm(void) { - message org_m_in; struct fproc *org_fp; struct worker_thread *org_self; @@ -291,14 +295,12 @@ static void lock_pm(void) if (mutex_trylock(&pm_lock) == 0) return; - org_m_in = m_in; org_fp = fp; org_self = self; if (mutex_lock(&pm_lock) != 0) panic("Could not obtain lock on pm\n"); - m_in = org_m_in; fp = org_fp; self = org_self; } @@ -322,7 +324,6 @@ static void *do_pm(void *arg) my_job = *((struct job *) arg); rfp = fp = my_job.j_fp; - m_in = my_job.j_m_in; lock_pm(); service_pm(); @@ -333,7 +334,7 @@ static void *do_pm(void *arg) } /*===========================================================================* - * do_pending_pipe * + * do_pending_pipe * *===========================================================================*/ static void *do_pending_pipe(void *arg) { @@ -344,7 +345,6 @@ static void *do_pending_pipe(void *arg) my_job = *((struct job *) arg); fp = my_job.j_fp; - m_in = my_job.j_m_in; lock_proc(fp, 1 /* force lock */); @@ -352,14 +352,14 @@ static void *do_pending_pipe(void *arg) assert(f != NULL); scratch(fp).file.filp = NULL; - locktype = (call_nr == READ) ? VNODE_READ : VNODE_WRITE; - op = (call_nr == READ) ? READING : WRITING; + locktype = (job_call_nr == READ) ? VNODE_READ : VNODE_WRITE; + op = (job_call_nr == READ) ? READING : WRITING; lock_filp(f, locktype); r = rw_pipe(op, who_e, f, scratch(fp).io.io_buffer, scratch(fp).io.io_nbytes); if (r != SUSPEND) /* Do we have results to report? */ - reply(who_e, r); + reply(fp->fp_endpoint, r); unlock_filp(f); @@ -377,7 +377,6 @@ void *do_dummy(void *arg) my_job = *((struct job *) arg); fp = my_job.j_fp; - m_in = my_job.j_m_in; if ((r = mutex_trylock(&fp->fp_lock)) == 0) { thread_cleanup(fp); @@ -398,29 +397,29 @@ static void *do_work(void *arg) my_job = *((struct job *) arg); fp = my_job.j_fp; - m_in = my_job.j_m_in; lock_proc(fp, 0); /* This proc is busy */ - if (call_nr == MAPDRIVER) { + if (job_call_nr == MAPDRIVER) { error = do_mapdriver(); - } else if (call_nr == COMMON_GETSYSINFO) { + } else if (job_call_nr == COMMON_GETSYSINFO) { error = do_getsysinfo(); - } else if (IS_PFS_VFS_RQ(call_nr)) { + } else if (IS_PFS_VFS_RQ(job_call_nr)) { if (who_e != PFS_PROC_NR) { printf("VFS: only PFS is allowed to make nested VFS calls\n"); error = ENOSYS; - } else if (call_nr <= PFS_BASE || call_nr >= PFS_BASE + PFS_NREQS) { + } else if (job_call_nr <= PFS_BASE || + job_call_nr >= PFS_BASE + PFS_NREQS) { error = ENOSYS; } else { - call_nr -= PFS_BASE; - error = (*pfs_call_vec[call_nr])(); + job_call_nr -= PFS_BASE; + error = (*pfs_call_vec[job_call_nr])(); } } else { /* We're dealing with a POSIX system call from a normal * process. Call the internal function that does the work. */ - if (call_nr < 0 || call_nr >= NCALLS) { + if (job_call_nr < 0 || job_call_nr >= NCALLS) { error = ENOSYS; } else if (fp->fp_pid == PID_FREE) { /* Process vanished before we were able to handle request. @@ -428,9 +427,9 @@ static void *do_work(void *arg) error = SUSPEND; } else { #if ENABLE_SYSCALL_STATS - calls_stats[call_nr]++; + calls_stats[job_call_nr]++; #endif - error = (*call_vec[call_nr])(); + error = (*call_vec[job_call_nr])(); } } @@ -448,7 +447,8 @@ static void *do_work(void *arg) if (fp->fp_wtid == dl_worker.w_tid) deadlock_resolving = 0; } - reply(who_e, error); + + reply(fp->fp_endpoint, error); } thread_cleanup(fp); @@ -483,6 +483,7 @@ static int sef_cb_init_fresh(int UNUSED(type), sef_init_info_t *info) force_sync = 0; receive_from = ANY; + self = NULL; /* Initialize proc endpoints to NONE */ for (rfp = &fproc[0]; rfp < &fproc[NR_PROCS]; rfp++) { @@ -542,10 +543,6 @@ static int sef_cb_init_fresh(int UNUSED(type), sef_init_info_t *info) s = ds_subscribe("drv\\.[bc]..\\..*", DSF_INITIAL | DSF_OVERWRITE); if (s != OK) panic("VFS: can't subscribe to driver events (%d)", s); -#if DO_SANITYCHECKS - FIXME("VFS: DO_SANITYCHECKS is on"); -#endif - /* Initialize worker threads */ for (i = 0; i < NR_WTHREADS; i++) { worker_init(&workers[i]); @@ -578,6 +575,7 @@ static int sef_cb_init_fresh(int UNUSED(type), sef_init_info_t *info) mount_pfs(); /* mount Pipe File Server */ worker_start(do_init_root); /* mount initial ramdisk as file system root */ yield(); /* force do_init_root to start */ + self = NULL; return(OK); } @@ -622,7 +620,6 @@ static void *do_init_root(void *arg) void lock_proc(struct fproc *rfp, int force_lock) { int r; - message org_m_in; struct fproc *org_fp; struct worker_thread *org_self; @@ -636,12 +633,12 @@ void lock_proc(struct fproc *rfp, int force_lock) if (r == 0) return; - org_m_in = m_in; org_fp = fp; org_self = self; + if ((r = mutex_lock(&rfp->fp_lock)) != 0) panic("unable to lock fproc lock: %d", r); - m_in = org_m_in; + fp = org_fp; self = org_self; } @@ -660,13 +657,11 @@ void unlock_proc(struct fproc *rfp) /*===========================================================================* * thread_cleanup * *===========================================================================*/ -static void thread_cleanup_f(struct fproc *rfp, char *f, int l) +static void thread_cleanup(struct fproc *rfp) { /* Clean up worker thread. Skip parts if this thread is not associated * with a particular process (i.e., rfp is NULL) */ - assert(mthread_self() != -1); - #if LOCK_DEBUG if (rfp != NULL) { check_filp_locks_by_me(); @@ -676,7 +671,7 @@ static void thread_cleanup_f(struct fproc *rfp, char *f, int l) #endif if (rfp != NULL && rfp->fp_flags & FP_PM_PENDING) { /* Postponed PM call */ - m_in = rfp->fp_job.j_m_in; + job_m_in = rfp->fp_job.j_m_in; rfp->fp_flags &= ~FP_PM_PENDING; service_pm_postponed(); } @@ -693,10 +688,6 @@ static void thread_cleanup_f(struct fproc *rfp, char *f, int l) rfp->fp_flags &= ~FP_DROP_WORK; unlock_proc(rfp); } - -#if 0 - mthread_exit(NULL); -#endif } /*===========================================================================* @@ -744,7 +735,7 @@ static void get_work() if (who_p >= (int)(sizeof(fproc) / sizeof(struct fproc))) panic("receive process out of range: %d", who_p); if (who_p >= 0 && fproc[who_p].fp_endpoint == NONE) { - printf("VFS: ignoring request from %d, endpointless slot %d (%d)\n", + printf("VFS: ignoring request from %d: NONE endpoint %d (%d)\n", m_in.m_source, who_p, m_in.m_type); continue; } @@ -766,13 +757,10 @@ static void get_work() } } - /*===========================================================================* * reply * *===========================================================================*/ -void reply(whom, result) -int whom; /* process to reply to */ -int result; /* result of the call (usually OK or error #) */ +void reply(endpoint_t whom, int result) { /* Send a reply to a user process. If the send fails, just ignore it. */ int r; @@ -780,7 +768,9 @@ int result; /* result of the call (usually OK or error #) */ m_out.reply_type = result; r = sendnb(whom, &m_out); if (r != OK) { - printf("VFS: couldn't send reply %d to %d: %d\n", result, whom, r); + printf("VFS: %d couldn't send reply %d to %d: %d\n", mthread_self(), + result, whom, r); + util_stacktrace(); } } @@ -792,46 +782,66 @@ static void service_pm_postponed(void) int r; vir_bytes pc; - switch(call_nr) { + switch(job_call_nr) { case PM_EXEC: - r = pm_exec(m_in.PM_PROC, m_in.PM_PATH, m_in.PM_PATH_LEN, - m_in.PM_FRAME, m_in.PM_FRAME_LEN, &pc); - - /* Reply status to PM */ - m_out.m_type = PM_EXEC_REPLY; - m_out.PM_PROC = m_in.PM_PROC; - m_out.PM_PC = (void*)pc; - m_out.PM_STATUS = r; - + { + endpoint_t proc_e; + vir_bytes exec_path, stack_frame; + size_t exec_path_len, stack_frame_len; + + proc_e = job_m_in.PM_PROC; + exec_path = (vir_bytes) job_m_in.PM_PATH; + exec_path_len = (size_t) job_m_in.PM_PATH_LEN; + stack_frame = (vir_bytes) job_m_in.PM_FRAME; + stack_frame_len = (size_t) job_m_in.PM_FRAME_LEN; + + r = pm_exec(proc_e, exec_path, exec_path_len, stack_frame, + stack_frame_len, &pc); + + /* Reply status to PM */ + m_out.m_type = PM_EXEC_REPLY; + m_out.PM_PROC = proc_e; + m_out.PM_PC = (void*) pc; + m_out.PM_STATUS = r; + } break; case PM_EXIT: - pm_exit(m_in.PM_PROC); + { + endpoint_t proc_e; + proc_e = job_m_in.PM_PROC; - /* Reply dummy status to PM for synchronization */ - m_out.m_type = PM_EXIT_REPLY; - m_out.PM_PROC = m_in.PM_PROC; + pm_exit(proc_e); + /* Reply dummy status to PM for synchronization */ + m_out.m_type = PM_EXIT_REPLY; + m_out.PM_PROC = proc_e; + } break; case PM_DUMPCORE: - /* Copy parameters first. m_in gets overwritten when creating core - * file. - */ - - r = pm_dumpcore(m_in.PM_PROC, m_in.PM_TERM_SIG, - (vir_bytes) m_in.PM_PATH); - - /* Reply status to PM */ - m_out.m_type = PM_CORE_REPLY; - m_out.PM_PROC = m_in.PM_PROC; - m_out.PM_TRACED_PROC = m_in.PM_TRACED_PROC; - m_out.PM_STATUS = r; - + { + endpoint_t proc_e, traced_proc_e; + int term_signal; + vir_bytes core_path; + + proc_e = job_m_in.PM_PROC; + traced_proc_e = job_m_in.PM_TRACED_PROC; + term_signal = job_m_in.PM_TERM_SIG; + core_path = (vir_bytes) job_m_in.PM_PATH; + + r = pm_dumpcore(proc_e, term_signal, core_path); + + /* Reply status to PM */ + m_out.m_type = PM_CORE_REPLY; + m_out.PM_PROC = proc_e; + m_out.PM_TRACED_PROC = traced_proc_e; + m_out.PM_STATUS = r; + } break; default: - panic("Unhandled postponed PM call %d", m_in.m_type); + panic("Unhandled postponed PM call %d", job_m_in.m_type); } r = send(PM_PROC_NR, &m_out); @@ -846,90 +856,139 @@ static void service_pm() { int r, slot; - switch (call_nr) { + switch (job_call_nr) { case PM_SETUID: - pm_setuid(m_in.PM_PROC, m_in.PM_EID, m_in.PM_RID); + { + endpoint_t proc_e; + uid_t euid, ruid; + + proc_e = job_m_in.PM_PROC; + euid = job_m_in.PM_EID; + ruid = job_m_in.PM_RID; - m_out.m_type = PM_SETUID_REPLY; - m_out.PM_PROC = m_in.PM_PROC; + pm_setuid(proc_e, euid, ruid); + m_out.m_type = PM_SETUID_REPLY; + m_out.PM_PROC = proc_e; + } break; case PM_SETGID: - pm_setgid(m_in.PM_PROC, m_in.PM_EID, m_in.PM_RID); + { + endpoint_t proc_e; + gid_t egid, rgid; + + proc_e = job_m_in.PM_PROC; + egid = job_m_in.PM_EID; + rgid = job_m_in.PM_RID; - m_out.m_type = PM_SETGID_REPLY; - m_out.PM_PROC = m_in.PM_PROC; + pm_setgid(proc_e, egid, rgid); + m_out.m_type = PM_SETGID_REPLY; + m_out.PM_PROC = proc_e; + } break; case PM_SETSID: - pm_setsid(m_in.PM_PROC); + { + endpoint_t proc_e; - m_out.m_type = PM_SETSID_REPLY; - m_out.PM_PROC = m_in.PM_PROC; + proc_e = job_m_in.PM_PROC; + pm_setsid(proc_e); + m_out.m_type = PM_SETSID_REPLY; + m_out.PM_PROC = proc_e; + } break; case PM_EXEC: case PM_EXIT: case PM_DUMPCORE: - okendpt(m_in.PM_PROC, &slot); - fp = &fproc[slot]; - - if (fp->fp_flags & FP_PENDING) { - /* This process has a request pending, but PM wants it gone. - * Forget about the pending request and satisfy PM's request - * instead. Note that a pending request AND an EXEC request - * are mutually exclusive. Also, PM should send only one - * request/process at a time. - */ - assert(fp->fp_job.j_m_in.m_source != PM_PROC_NR); - } - - /* PM requests on behalf of a proc are handled after the system call - * that might be in progress for that proc has finished. If the proc - * is not busy, we start a dummy call */ - if (!(fp->fp_flags & FP_PENDING) && mutex_trylock(&fp->fp_lock) == 0) { - mutex_unlock(&fp->fp_lock); - worker_start(do_dummy); - fp->fp_flags |= FP_DROP_WORK; - } + { + endpoint_t proc_e = job_m_in.PM_PROC; + okendpt(proc_e, &slot); + fp = &fproc[slot]; + + if (fp->fp_flags & FP_PENDING) { + /* This process has a request pending, but PM wants it + * gone. Forget about the pending request and satisfy + * PM's request instead. Note that a pending request + * AND an EXEC request are mutually exclusive. Also, PM + * should send only one request/process at a time. + */ + assert(fp->fp_job.j_m_in.m_source != PM_PROC_NR); + } - fp->fp_job.j_m_in = m_in; - fp->fp_flags |= FP_PM_PENDING; + /* PM requests on behalf of a proc are handled after the + * system call that might be in progress for that proc has + * finished. If the proc is not busy, we start a dummy call. + */ + if (!(fp->fp_flags & FP_PENDING) && + mutex_trylock(&fp->fp_lock) == 0) { + mutex_unlock(&fp->fp_lock); + worker_start(do_dummy); + fp->fp_flags |= FP_DROP_WORK; + } - return; + fp->fp_job.j_m_in = job_m_in; + fp->fp_flags |= FP_PM_PENDING; + return; + } case PM_FORK: case PM_SRV_FORK: - pm_fork(m_in.PM_PPROC, m_in.PM_PROC, m_in.PM_CPID); - m_out.m_type = PM_FORK_REPLY; + { + endpoint_t pproc_e, proc_e; + pid_t child_pid; + uid_t reuid; + gid_t regid; + + pproc_e = job_m_in.PM_PPROC; + proc_e = job_m_in.PM_PROC; + child_pid = job_m_in.PM_CPID; + reuid = job_m_in.PM_REUID; + regid = job_m_in.PM_REGID; + + pm_fork(pproc_e, proc_e, child_pid); + m_out.m_type = PM_FORK_REPLY; + + if (job_call_nr == PM_SRV_FORK) { + m_out.m_type = PM_SRV_FORK_REPLY; + pm_setuid(proc_e, reuid, reuid); + pm_setgid(proc_e, regid, regid); + } - if (call_nr == PM_SRV_FORK) { - m_out.m_type = PM_SRV_FORK_REPLY; - pm_setuid(m_in.PM_PROC, m_in.PM_REUID, m_in.PM_REUID); - pm_setgid(m_in.PM_PROC, m_in.PM_REGID, m_in.PM_REGID); + m_out.PM_PROC = proc_e; } - - m_out.PM_PROC = m_in.PM_PROC; - break; case PM_SETGROUPS: - pm_setgroups(m_in.PM_PROC, m_in.PM_GROUP_NO, - (gid_t *) m_in.PM_GROUP_ADDR); + { + endpoint_t proc_e; + int group_no; + gid_t *group_addr; - m_out.m_type = PM_SETGROUPS_REPLY; - m_out.PM_PROC = m_in.PM_PROC; + proc_e = job_m_in.PM_PROC; + group_no = job_m_in.PM_GROUP_NO; + group_addr = (gid_t *) job_m_in.PM_GROUP_ADDR; + pm_setgroups(proc_e, group_no, group_addr); + + m_out.m_type = PM_SETGROUPS_REPLY; + m_out.PM_PROC = proc_e; + } break; case PM_UNPAUSE: - unpause(m_in.PM_PROC); + { + endpoint_t proc_e; + + proc_e = job_m_in.PM_PROC; - m_out.m_type = PM_UNPAUSE_REPLY; - m_out.PM_PROC = m_in.PM_PROC; + unpause(proc_e); + m_out.m_type = PM_UNPAUSE_REPLY; + m_out.PM_PROC = proc_e; + } break; case PM_REBOOT: @@ -941,7 +1000,7 @@ static void service_pm() break; default: - printf("VFS: don't know how to handle PM request %d\n", call_nr); + printf("VFS: don't know how to handle PM request %d\n", job_call_nr); return; } @@ -963,7 +1022,12 @@ struct fproc *rfp; fp = rfp; blocked_on = rfp->fp_blocked_on; + m_in.m_source = rfp->fp_endpoint; m_in.m_type = rfp->fp_block_callnr; + if (call_nr == 6) { /* close() */ + if (m_in.fd != scratch(fp).file.fd_nr) + printf("VFS: would've done something weird\n"); + } m_in.fd = scratch(fp).file.fd_nr; m_in.buffer = scratch(fp).io.io_buffer; m_in.nbytes = scratch(fp).io.io_nbytes; @@ -982,6 +1046,7 @@ struct fproc *rfp; if (blocked_on == FP_BLOCKED_ON_PIPE) { worker_start(do_pending_pipe); yield(); /* Give thread a chance to run */ + self = NULL; return(0); /* Retrieve more work */ } diff --git a/servers/vfs/misc.c b/servers/vfs/misc.c index 6fd10e6da..e4aaf181c 100644 --- a/servers/vfs/misc.c +++ b/servers/vfs/misc.c @@ -62,7 +62,12 @@ static int write_seg(struct inode *rip, off_t off, int proc_e, int seg, int do_getsysinfo() { vir_bytes src_addr, dst_addr; - size_t len; + size_t len, buf_size; + int what; + + what = job_m_in.SI_WHAT; + dst_addr = (vir_bytes) job_m_in.SI_WHERE; + buf_size = (size_t) job_m_in.SI_SIZE; /* Only su may call do_getsysinfo. This call may leak information (and is not * stable enough to be part of the API/ABI). In the future, requests from @@ -71,7 +76,7 @@ int do_getsysinfo() if (!super_user) return(EPERM); - switch(m_in.SI_WHAT) { + switch(what) { case SI_PROC_TAB: src_addr = (vir_bytes) fproc; len = sizeof(struct fproc) * NR_PROCS; @@ -90,10 +95,9 @@ int do_getsysinfo() return(EINVAL); } - if (len != m_in.SI_SIZE) + if (len != buf_size) return(EINVAL); - dst_addr = (vir_bytes) m_in.SI_WHERE; return sys_datacopy(SELF, src_addr, who_e, dst_addr, len); } @@ -108,29 +112,31 @@ int do_dup() * provided to permit old binary programs to continue to run. */ - register int rfd; - register struct filp *f; + int rfd, rfd2; + struct filp *f; int r = OK; + scratch(fp).file.fd_nr = job_m_in.fd; + rfd2 = job_m_in.fd2; + /* Is the file descriptor valid? */ - rfd = m_in.fd & ~DUP_MASK; /* kill off dup2 bit, if on */ + rfd = scratch(fp).file.fd_nr & ~DUP_MASK; /* kill off dup2 bit, if on */ if ((f = get_filp(rfd, VNODE_READ)) == NULL) return(err_code); /* Distinguish between dup and dup2. */ - if (m_in.fd == rfd) { /* bit not on */ + if (!(scratch(fp).file.fd_nr & DUP_MASK)) { /* bit not on */ /* dup(fd) */ - r = get_fd(0, 0, &m_in.fd2, NULL); + r = get_fd(0, 0, &rfd2, NULL); } else { /* dup2(old_fd, new_fd) */ - if (m_in.fd2 < 0 || m_in.fd2 >= OPEN_MAX) { + if (rfd2 < 0 || rfd2 >= OPEN_MAX) { r = EBADF; - } else if (rfd == m_in.fd2) { /* ignore the call: dup2(x, x) */ - r = m_in.fd2; + } else if (rfd == rfd2) { /* ignore the call: dup2(x, x) */ + r = rfd2; } else { /* All is fine, close new_fd if necessary */ - m_in.fd = m_in.fd2; /* prepare to close fd2 */ unlock_filp(f); /* or it might deadlock on do_close */ - (void) do_close(); /* cannot fail */ + (void) close_fd(fp, rfd2); /* cannot fail */ f = get_filp(rfd, VNODE_READ); /* lock old_fd again */ } } @@ -138,9 +144,9 @@ int do_dup() if (r == OK) { /* Success. Set up new file descriptors. */ f->filp_count++; - fp->fp_filp[m_in.fd2] = f; - FD_SET(m_in.fd2, &fp->fp_filp_inuse); - r = m_in.fd2; + fp->fp_filp[rfd2] = f; + FD_SET(rfd2, &fp->fp_filp_inuse); + r = rfd2; } unlock_filp(f); @@ -155,23 +161,25 @@ int do_fcntl() /* Perform the fcntl(fd, request, ...) system call. */ register struct filp *f; - int new_fd, fl, r = OK; + int new_fd, fl, r = OK, fcntl_req, fcntl_argx; tll_access_t locktype; - scratch(fp).file.fd_nr = m_in.fd; - scratch(fp).io.io_buffer = m_in.buffer; - scratch(fp).io.io_nbytes = m_in.nbytes; /* a.k.a. m_in.request */ + scratch(fp).file.fd_nr = job_m_in.fd; + scratch(fp).io.io_buffer = job_m_in.buffer; + scratch(fp).io.io_nbytes = job_m_in.nbytes; /* a.k.a. m_in.request */ + fcntl_req = job_m_in.request; + fcntl_argx = job_m_in.addr; /* Is the file descriptor valid? */ - locktype = (m_in.request == F_FREESP) ? VNODE_WRITE : VNODE_READ; + locktype = (fcntl_req == F_FREESP) ? VNODE_WRITE : VNODE_READ; if ((f = get_filp(scratch(fp).file.fd_nr, locktype)) == NULL) return(err_code); - switch (m_in.request) { + switch (fcntl_req) { case F_DUPFD: /* This replaces the old dup() system call. */ - if (m_in.addr < 0 || m_in.addr >= OPEN_MAX) r = EINVAL; - else if ((r = get_fd(m_in.addr, 0, &new_fd, NULL)) == OK) { + if (fcntl_argx < 0 || fcntl_argx >= OPEN_MAX) r = EINVAL; + else if ((r = get_fd(fcntl_argx, 0, &new_fd, NULL)) == OK) { f->filp_count++; fp->fp_filp[new_fd] = f; FD_SET(new_fd, &fp->fp_filp_inuse); @@ -188,7 +196,7 @@ int do_fcntl() case F_SETFD: /* Set close-on-exec flag (FD_CLOEXEC in POSIX Table 6-2). */ - if(m_in.addr & FD_CLOEXEC) + if (fcntl_argx & FD_CLOEXEC) FD_SET(scratch(fp).file.fd_nr, &fp->fp_cloexec_set); else FD_CLR(scratch(fp).file.fd_nr, &fp->fp_cloexec_set); @@ -203,14 +211,14 @@ int do_fcntl() case F_SETFL: /* Set file status flags (O_NONBLOCK and O_APPEND). */ fl = O_NONBLOCK | O_APPEND | O_REOPEN; - f->filp_flags = (f->filp_flags & ~fl) | (m_in.addr & fl); + f->filp_flags = (f->filp_flags & ~fl) | (fcntl_argx & fl); break; case F_GETLK: case F_SETLK: case F_SETLKW: /* Set or clear a file lock. */ - r = lock_op(f, m_in.request); + r = lock_op(f, fcntl_req); break; case F_FREESP: @@ -225,9 +233,9 @@ int do_fcntl() else if (!(f->filp_mode & W_BIT)) r = EBADF; else /* Copy flock data from userspace. */ - r = sys_datacopy(who_e, (vir_bytes) m_in.name1, SELF, - (vir_bytes) &flock_arg, - (phys_bytes) sizeof(flock_arg)); + r = sys_datacopy(who_e, (vir_bytes) scratch(fp).io.io_buffer, + SELF, (vir_bytes) &flock_arg, + sizeof(flock_arg)); if (r != OK) break; @@ -313,7 +321,10 @@ int do_fsync() dev_t dev; int r = OK; - if ((rfilp = get_filp(m_in.m1_i1, VNODE_READ)) == NULL) return(err_code); + scratch(fp).file.fd_nr = job_m_in.fd; + + if ((rfilp = get_filp(scratch(fp).file.fd_nr, VNODE_READ)) == NULL) + return(err_code); dev = rfilp->filp_vno->v_dev; for (vmp = &vmnt[0]; vmp < &vmnt[NR_MNTS]; ++vmp) { if (vmp->m_dev != NO_DEV && vmp->m_dev == dev && @@ -364,10 +375,7 @@ void pm_reboot() /*===========================================================================* * pm_fork * *===========================================================================*/ -void pm_fork(pproc, cproc, cpid) -int pproc; /* Parent process */ -int cproc; /* Child process */ -int cpid; /* Child process id */ +void pm_fork(endpoint_t pproc, endpoint_t cproc, pid_t cpid) { /* Perform those aspects of the fork() system call that relate to files. * In particular, let the child inherit its parent's file descriptors. @@ -375,7 +383,7 @@ int cpid; /* Child process id */ * system uses the same slot numbers as the kernel. Only PM makes this call. */ - register struct fproc *cp, *pp; + struct fproc *cp, *pp; int i, parentno, childno; mutex_t c_fp_lock; @@ -388,7 +396,7 @@ int cpid; /* Child process id */ */ childno = _ENDPOINT_P(cproc); if (childno < 0 || childno >= NR_PROCS) - panic("VFS: bogus child for forking: %d", m_in.child_endpt); + panic("VFS: bogus child for forking: %d", cproc); if (fproc[childno].fp_pid != PID_FREE) panic("VFS: forking on top of in-use child: %d", childno); @@ -411,11 +419,11 @@ int cpid; /* Child process id */ /* A forking process never has an outstanding grant, as it isn't blocking on * I/O. */ - if(GRANT_VALID(pp->fp_grant)) { + if (GRANT_VALID(pp->fp_grant)) { panic("VFS: fork: pp (endpoint %d) has grant %d\n", pp->fp_endpoint, pp->fp_grant); } - if(GRANT_VALID(cp->fp_grant)) { + if (GRANT_VALID(cp->fp_grant)) { panic("VFS: fork: cp (endpoint %d) has grant %d\n", cp->fp_endpoint, cp->fp_grant); } @@ -586,7 +594,11 @@ int ruid; *===========================================================================*/ int do_svrctl() { - switch (m_in.svrctl_req) { + int svrctl; + + svrctl = m_in.svrctl_req; + + switch (svrctl) { /* No control request implemented yet. */ default: return(EINVAL); diff --git a/servers/vfs/mount.c b/servers/vfs/mount.c index 2922a6f63..ebf0d1f1e 100644 --- a/servers/vfs/mount.c +++ b/servers/vfs/mount.c @@ -103,15 +103,26 @@ int do_mount() char fullpath[PATH_MAX]; char mount_label[LABEL_MAX]; dev_t dev; + int mflags; + vir_bytes label, vname1, vname2; + size_t vname1_length, vname2_length; + + mflags = job_m_in.mount_flags; + label = (vir_bytes) job_m_in.fs_label; + vname1 = (vir_bytes) job_m_in.name1; + vname1_length = (size_t) job_m_in.name1_length; + vname2 = (vir_bytes) job_m_in.name2; + vname2_length = (size_t) job_m_in.name2_length; /* Only the super-user may do MOUNT. */ if (!super_user) return(EPERM); + /* FS process' endpoint number */ - if (m_in.mount_flags & MS_LABEL16) { + if (mflags & MS_LABEL16) { /* Get the label from the caller, and ask DS for the endpoint. */ - r = sys_datacopy(who_e, (vir_bytes) m_in.fs_label, SELF, - (vir_bytes) mount_label, (phys_bytes) sizeof(mount_label)); + r = sys_datacopy(who_e, label, SELF, (vir_bytes) mount_label, + sizeof(mount_label)); if (r != OK) return(r); mount_label[sizeof(mount_label)-1] = 0; @@ -120,7 +131,7 @@ int do_mount() if (r != OK) return(r); } else { /* Legacy support: get the endpoint from the request itself. */ - fs_e = (endpoint_t) m_in.fs_label; + fs_e = (endpoint_t) label; mount_label[0] = 0; } @@ -128,13 +139,13 @@ int do_mount() if (isokendpt(fs_e, &slot) != OK) return(EINVAL); /* Should the file system be mounted read-only? */ - rdonly = (m_in.mount_flags & MS_RDONLY); + rdonly = (mflags & MS_RDONLY); /* A null string for block special device means don't use a device at all. */ - nodev = (m_in.name1_length == 0); + nodev = (vname1_length == 0); if (!nodev) { /* If 'name' is not for a block special file, return error. */ - if (fetch_name(m_in.name1, m_in.name1_length, M1, fullpath) != OK) + if (fetch_name(vname1, vname1_length, fullpath) != OK) return(err_code); if ((dev = name_to_dev(FALSE /*allow_mountpt*/, fullpath)) == NO_DEV) return(err_code); @@ -145,8 +156,7 @@ int do_mount() } /* Fetch the name of the mountpoint */ - if (fetch_name(m_in.name2, m_in.name2_length, M1, fullpath) != OK) - return(err_code); + if (fetch_name(vname2, vname2_length, fullpath) != OK) return(err_code); /* Do the actual job */ return mount_fs(dev, fullpath, fs_e, rdonly, mount_label); @@ -408,18 +418,28 @@ void mount_pfs(void) *===========================================================================*/ int do_umount(void) { -/* Perform the umount(name) system call. */ +/* Perform the umount(name) system call. + * syscall might provide 'name' embedded in the message. + */ char label[LABEL_MAX]; dev_t dev; int r; char fullpath[PATH_MAX]; + vir_bytes vname; + size_t vname_length; + + vname = (vir_bytes) job_m_in.name; + vname_length = (size_t) job_m_in.name_length; /* Only the super-user may do umount. */ if (!super_user) return(EPERM); /* If 'name' is not for a block special file or mountpoint, return error. */ - if (fetch_name(m_in.name, m_in.name_length, M3, fullpath) != OK) - return(err_code); + if (copy_name(vname_length, fullpath) != OK) { + /* Direct copy failed, try fetching from user space */ + if (fetch_name(vname, vname_length, fullpath) != OK) + return(err_code); + } if ((dev = name_to_dev(TRUE /*allow_mountpt*/, fullpath)) == NO_DEV) return(err_code); diff --git a/servers/vfs/open.c b/servers/vfs/open.c index 4ce4c29b5..267c2bb4e 100644 --- a/servers/vfs/open.c +++ b/servers/vfs/open.c @@ -44,38 +44,64 @@ static int pipe_open(struct vnode *vp, mode_t bits, int oflags); *===========================================================================*/ int do_creat() { -/* Perform the creat(name, mode) system call. */ - int r; +/* Perform the creat(name, mode) system call. + * syscall might provide 'name' embedded in the message. + */ + char fullpath[PATH_MAX]; + vir_bytes vname; + size_t vname_length; + mode_t open_mode; - if (fetch_name(m_in.name, m_in.name_length, M3, fullpath) != OK) - return(err_code); - r = common_open(fullpath, O_WRONLY | O_CREAT | O_TRUNC, (mode_t) m_in.mode); - return(r); -} + vname = (vir_bytes) job_m_in.name; + vname_length = (size_t) job_m_in.name_length; + open_mode = (mode_t) job_m_in.mode; + + if (copy_name(vname_length, fullpath) != OK) { + /* Direct copy failed, try fetching from user space */ + if (fetch_name(vname, vname_length, fullpath) != OK) + return(err_code); + } + return common_open(fullpath, O_WRONLY | O_CREAT | O_TRUNC, open_mode); +} /*===========================================================================* * do_open * *===========================================================================*/ int do_open() { -/* Perform the open(name, flags,...) system call. */ - int create_mode = 0; /* is really mode_t but this gives problems */ - int r; +/* Perform the open(name, flags,...) system call. + * syscall might provide 'name' embedded in message when not creating file */ + + int create_mode; /* is really mode_t but this gives problems */ + int open_mode = 0; /* is really mode_t but this gives problems */ + int r = OK; char fullpath[PATH_MAX]; + vir_bytes vname; + size_t vname_length; + + open_mode = (mode_t) job_m_in.mode; + create_mode = job_m_in.c_mode; /* If O_CREAT is set, open has three parameters, otherwise two. */ - if (m_in.mode & O_CREAT) { - create_mode = m_in.c_mode; - r = fetch_name(m_in.c_name, m_in.name1_length, M1, fullpath); + if (open_mode & O_CREAT) { + vname = (vir_bytes) job_m_in.name1; + vname_length = (size_t) job_m_in.name1_length; + r = fetch_name(vname, vname_length, fullpath); } else { - r = fetch_name(m_in.name, m_in.name_length, M3, fullpath); + vname = (vir_bytes) job_m_in.name; + vname_length = (size_t) job_m_in.name_length; + create_mode = 0; + if (copy_name(vname_length, fullpath) != OK) { + /* Direct copy failed, try fetching from user space */ + if (fetch_name(vname, vname_length, fullpath) != OK) + r = err_code; + } } if (r != OK) return(err_code); /* name was bad */ - r = common_open(fullpath, m_in.mode, create_mode); - return(r); + return common_open(fullpath, open_mode, create_mode); } @@ -241,24 +267,23 @@ int common_open(char path[PATH_MAX], int oflags, mode_t omode) b = (bits & R_BIT ? R_BIT : W_BIT); filp->filp_count = 0; /* don't find self */ if ((filp2 = find_filp(vp, b)) != NULL) { - /* Co-reader or writer found. Use it.*/ - fp->fp_filp[scratch(fp).file.fd_nr] = filp2; - filp2->filp_count++; - filp2->filp_vno = vp; - filp2->filp_flags = oflags; - - /* v_count was incremented after the - * vnode has been found. i_count was - * incremented incorrectly in FS, not - * knowing that we were going to use an - * existing filp entry. Correct this - * error. - */ - unlock_vnode(vp); - put_vnode(vp); + /* Co-reader or writer found. Use it.*/ + fp->fp_filp[scratch(fp).file.fd_nr] = filp2; + filp2->filp_count++; + filp2->filp_vno = vp; + filp2->filp_flags = oflags; + + /* v_count was incremented after the vnode + * has been found. i_count was incremented + * incorrectly in FS, not knowing that we + * were going to use an existing filp + * entry. Correct this error. + */ + unlock_vnode(vp); + put_vnode(vp); } else { - /* Nobody else found. Restore filp. */ - filp->filp_count = 1; + /* Nobody else found. Restore filp. */ + filp->filp_count = 1; } } break; @@ -371,7 +396,7 @@ static struct vnode *new_node(struct lookup *resolve, int oflags, mode_t bits) r = req_rdlink(slp->v_fs_e, slp->v_inode_nr, VFS_PROC_NR, - path, + (vir_bytes) path, PATH_MAX - 1, 0); if (r < 0) { /* Failed to read link */ @@ -508,13 +533,20 @@ int do_mknod() struct vmnt *vmp; char fullpath[PATH_MAX]; struct lookup resolve; + vir_bytes vname1; + size_t vname1_length; + dev_t dev; + + vname1 = (vir_bytes) job_m_in.name1; + vname1_length = (size_t) job_m_in.name1_length; + mode_bits = (mode_t) job_m_in.mk_mode; /* mode of the inode */ + dev = job_m_in.m1_i3; lookup_init(&resolve, fullpath, PATH_NOFLAGS, &vmp, &vp); resolve.l_vmnt_lock = VMNT_WRITE; resolve.l_vnode_lock = VNODE_READ; /* Only the super_user may make nodes other than fifos. */ - mode_bits = (mode_t) m_in.mk_mode; /* mode of the inode */ if (!super_user && (((mode_bits & I_TYPE) != I_NAMED_PIPE) && ((mode_bits & I_TYPE) != I_UNIX_SOCKET))) { return(EPERM); @@ -522,8 +554,7 @@ int do_mknod() bits = (mode_bits & I_TYPE) | (mode_bits & ALL_MODES & fp->fp_umask); /* Open directory that's going to hold the new node. */ - if (fetch_name(m_in.name1, m_in.name1_length, M1, fullpath) != OK) - return(err_code); + if (fetch_name(vname1, vname1_length, fullpath) != OK) return(err_code); if ((vp = last_dir(&resolve, fp)) == NULL) return(err_code); /* Make sure that the object is a directory */ @@ -531,7 +562,7 @@ int do_mknod() r = ENOTDIR; } else if ((r = forbidden(fp, vp, W_BIT|X_BIT)) == OK) { r = req_mknod(vp->v_fs_e, vp->v_inode_nr, fullpath, fp->fp_effuid, - fp->fp_effgid, bits, m_in.mk_z0); + fp->fp_effgid, bits, dev); } unlock_vnode(vp); @@ -552,14 +583,20 @@ int do_mkdir() struct vmnt *vmp; char fullpath[PATH_MAX]; struct lookup resolve; + vir_bytes vname1; + size_t vname1_length; + mode_t dirmode; + + vname1 = (vir_bytes) job_m_in.name1; + vname1_length = (size_t) job_m_in.name1_length; + dirmode = (mode_t) job_m_in.mode; lookup_init(&resolve, fullpath, PATH_NOFLAGS, &vmp, &vp); resolve.l_vmnt_lock = VMNT_WRITE; resolve.l_vnode_lock = VNODE_READ; - if (fetch_name(m_in.name1, m_in.name1_length, M1, fullpath) != OK) - return(err_code); - bits = I_DIRECTORY | (m_in.mode & RWX_MODES & fp->fp_umask); + if (fetch_name(vname1, vname1_length, fullpath) != OK) return(err_code); + bits = I_DIRECTORY | (dirmode & RWX_MODES & fp->fp_umask); if ((vp = last_dir(&resolve, fp)) == NULL) return(err_code); /* Make sure that the object is a directory */ @@ -583,12 +620,16 @@ int do_lseek() { /* Perform the lseek(ls_fd, offset, whence) system call. */ register struct filp *rfilp; - int r = OK; - long offset; + int r = OK, seekfd, seekwhence; + off_t offset; u64_t pos, newpos; + seekfd = job_m_in.ls_fd; + seekwhence = job_m_in.whence; + offset = (off_t) job_m_in.offset_lo; + /* Check to see if the file descriptor is valid. */ - if ( (rfilp = get_filp(m_in.ls_fd, VNODE_READ)) == NULL) return(err_code); + if ( (rfilp = get_filp(seekfd, VNODE_READ)) == NULL) return(err_code); /* No lseek on pipes. */ if (rfilp->filp_vno->v_pipe == I_PIPE) { @@ -597,14 +638,13 @@ int do_lseek() } /* The value of 'whence' determines the start position to use. */ - switch(m_in.whence) { + switch(seekwhence) { case SEEK_SET: pos = cvu64(0); break; case SEEK_CUR: pos = rfilp->filp_pos; break; case SEEK_END: pos = cvul64(rfilp->filp_vno->v_size); break; default: unlock_filp(rfilp); return(EINVAL); } - offset = m_in.offset_lo; if (offset >= 0) newpos = add64ul(pos, offset); else @@ -640,10 +680,16 @@ int do_llseek() /* Perform the llseek(ls_fd, offset, whence) system call. */ register struct filp *rfilp; u64_t pos, newpos; - int r = OK; + int r = OK, seekfd, seekwhence; + long off_hi, off_lo; + + seekfd = job_m_in.ls_fd; + seekwhence = job_m_in.whence; + off_hi = job_m_in.offset_high; + off_lo = job_m_in.offset_lo; /* Check to see if the file descriptor is valid. */ - if ( (rfilp = get_filp(m_in.ls_fd, VNODE_READ)) == NULL) return(err_code); + if ( (rfilp = get_filp(seekfd, VNODE_READ)) == NULL) return(err_code); /* No lseek on pipes. */ if (rfilp->filp_vno->v_pipe == I_PIPE) { @@ -652,19 +698,19 @@ int do_llseek() } /* The value of 'whence' determines the start position to use. */ - switch(m_in.whence) { + switch(seekwhence) { case SEEK_SET: pos = cvu64(0); break; case SEEK_CUR: pos = rfilp->filp_pos; break; case SEEK_END: pos = cvul64(rfilp->filp_vno->v_size); break; default: unlock_filp(rfilp); return(EINVAL); } - newpos = add64(pos, make64(m_in.offset_lo, m_in.offset_high)); + newpos = add64(pos, make64(off_lo, off_hi)); /* Check for overflow. */ - if (( (long) m_in.offset_high > 0) && cmp64(newpos, pos) < 0) + if ((off_hi > 0) && cmp64(newpos, pos) < 0) r = EINVAL; - else if (( (long) m_in.offset_high < 0) && cmp64(newpos, pos) > 0) + else if ((off_hi < 0) && cmp64(newpos, pos) > 0) r = EINVAL; else { rfilp->filp_pos = newpos; @@ -691,7 +737,8 @@ int do_close() { /* Perform the close(fd) system call. */ - return close_fd(fp, m_in.fd); + scratch(fp).file.fd_nr = job_m_in.fd; + return close_fd(fp, scratch(fp).file.fd_nr); } diff --git a/servers/vfs/path.c b/servers/vfs/path.c index aaf1eb501..7ecdb2895 100644 --- a/servers/vfs/path.c +++ b/servers/vfs/path.c @@ -263,7 +263,7 @@ struct fproc *rfp; } r = req_rdlink(sym_vp->v_fs_e, sym_vp->v_inode_nr, NONE, - resolve->l_path, PATH_MAX - 1, 1); + (vir_bytes) resolve->l_path, PATH_MAX - 1, 1); if (r < 0) { /* Failed to read link */ @@ -382,8 +382,8 @@ struct fproc *rfp; root_ino = 0; /* Set user and group ids according to the system call */ - uid = (call_nr == ACCESS ? rfp->fp_realuid : rfp->fp_effuid); - gid = (call_nr == ACCESS ? rfp->fp_realgid : rfp->fp_effgid); + uid = (job_call_nr == ACCESS ? rfp->fp_realuid : rfp->fp_effuid); + gid = (job_call_nr == ACCESS ? rfp->fp_realgid : rfp->fp_effgid); symloop = 0; /* Number of symlinks seen so far */ @@ -786,6 +786,6 @@ size_t pathlen; *===========================================================================*/ int do_check_perms(void) { - return check_perms(m_in.USER_ENDPT, (cp_grant_id_t) m_in.IO_GRANT, - (size_t) m_in.COUNT); + return check_perms(job_m_in.USER_ENDPT, (cp_grant_id_t) job_m_in.IO_GRANT, + (size_t) job_m_in.COUNT); } diff --git a/servers/vfs/pipe.c b/servers/vfs/pipe.c index 8519747ae..54274154c 100644 --- a/servers/vfs/pipe.c +++ b/servers/vfs/pipe.c @@ -283,21 +283,13 @@ void suspend(int why) * The SUSPEND pseudo error should be returned after calling suspend(). */ -#if DO_SANITYCHECKS - if(fp_is_blocked(fp)) - panic("suspend: called for suspended process"); - - if(why == FP_BLOCKED_ON_NONE) - panic("suspend: called for FP_BLOCKED_ON_NONE"); -#endif - if (why == FP_BLOCKED_ON_POPEN || why == FP_BLOCKED_ON_PIPE) /* #procs susp'ed on pipe*/ susp_count++; fp->fp_blocked_on = why; assert(fp->fp_grant == GRANT_INVALID || !GRANT_VALID(fp->fp_grant)); - fp->fp_block_callnr = call_nr; + fp->fp_block_callnr = job_call_nr; fp->fp_flags &= ~FP_SUSP_REOPEN; /* Clear this flag. The caller * can set it when needed. */ @@ -316,7 +308,7 @@ void wait_for(endpoint_t who) /*===========================================================================* - * pipe_suspend * + * pipe_suspend * *===========================================================================*/ void pipe_suspend(filp, buf, size) struct filp *filp; @@ -326,10 +318,6 @@ size_t size; /* Take measures to suspend the processing of the present system call. * Store the parameters to be used upon resuming in the process table. */ -#if DO_SANITYCHECKS - if(fp_is_blocked(fp)) - panic("pipe_suspend: called for suspended process"); -#endif scratch(fp).file.filp = filp; scratch(fp).io.io_buffer = buf; @@ -434,19 +422,17 @@ int count; /* max number of processes to release */ /*===========================================================================* * revive * *===========================================================================*/ -void revive(proc_nr_e, returned) -int proc_nr_e; /* process to revive */ -int returned; /* if hanging on task, how many bytes read */ +void revive(endpoint_t proc_e, int returned) { /* Revive a previously blocked process. When a process hangs on tty, this * is the way it is eventually released. */ - register struct fproc *rfp; + struct fproc *rfp; int blocked_on; int fd_nr, slot; struct filp *fil_ptr; - if (proc_nr_e == NONE || isokendpt(proc_nr_e, &slot) != OK) return; + if (proc_e == NONE || isokendpt(proc_e, &slot) != OK) return; rfp = &fproc[slot]; if (!fp_is_blocked(rfp) || (rfp->fp_flags & FP_REVIVED)) return; @@ -478,18 +464,18 @@ int returned; /* if hanging on task, how many bytes read */ unlock_filp(fil_ptr); put_vnode(fil_ptr->filp_vno); fil_ptr->filp_vno = NULL; - reply(proc_nr_e, returned); + reply(proc_e, returned); } else { - reply(proc_nr_e, fd_nr); + reply(proc_e, fd_nr); } } else { rfp->fp_blocked_on = FP_BLOCKED_ON_NONE; scratch(rfp).file.fd_nr = 0; if (blocked_on == FP_BLOCKED_ON_POPEN) { /* process blocked in open or create */ - reply(proc_nr_e, fd_nr); + reply(proc_e, fd_nr); } else if (blocked_on == FP_BLOCKED_ON_SELECT) { - reply(proc_nr_e, returned); + reply(proc_e, returned); } else { /* Revive a process suspended on TTY or other device. * Pretend it wants only what there is. @@ -505,7 +491,7 @@ int returned; /* if hanging on task, how many bytes read */ } rfp->fp_grant = GRANT_INVALID; } - reply(proc_nr_e, returned); /* unblock the process */ + reply(proc_e, returned);/* unblock the process */ } } } @@ -615,30 +601,3 @@ void unpause(endpoint_t proc_e) reply(proc_e, status); /* signal interrupted call */ } -#if DO_SANITYCHECKS -/*===========================================================================* - * check_pipe * - *===========================================================================*/ -int check_pipe(void) -{ -/* Integrity check; verify that susp_count equals what the fproc table thinks - * is suspended on a pipe */ - struct fproc *rfp; - int count = 0; - for (rfp = &fproc[0]; rfp < &fproc[NR_PROCS]; rfp++) { - if (rfp->fp_pid == PID_FREE) continue; - if ( !(rfp->fp_flags & FP_REVIVED) && - (rfp->fp_blocked_on == FP_BLOCKED_ON_PIPE || - rfp->fp_blocked_on == FP_BLOCKED_ON_POPEN)) { - count++; - } - } - - if (count != susp_count) { - printf("check_pipe: count %d susp_count %d\n", count, susp_count); - return(0); - } - - return(l); -} -#endif diff --git a/servers/vfs/protect.c b/servers/vfs/protect.c index 6bc9cff13..90c77ebb0 100644 --- a/servers/vfs/protect.c +++ b/servers/vfs/protect.c @@ -24,31 +24,42 @@ *===========================================================================*/ int do_chmod() { -/* Perform the chmod(name, mode) and fchmod(fd, mode) system calls. */ +/* Perform the chmod(name, mode) and fchmod(fd, mode) system calls. + * syscall might provide 'name' embedded in the message. + */ struct filp *flp; struct vnode *vp; struct vmnt *vmp; - int r; - mode_t new_mode; + int r, rfd; + mode_t result_mode; char fullpath[PATH_MAX]; struct lookup resolve; + vir_bytes vname; + size_t vname_length; + mode_t new_mode; flp = NULL; + vname = (vir_bytes) job_m_in.name; + vname_length = (size_t) job_m_in.name_length; + rfd = job_m_in.fd; + new_mode = (mode_t) job_m_in.mode; lookup_init(&resolve, fullpath, PATH_NOFLAGS, &vmp, &vp); resolve.l_vmnt_lock = VMNT_WRITE; resolve.l_vnode_lock = VNODE_WRITE; - if (call_nr == CHMOD) { + if (job_call_nr == CHMOD) { /* Temporarily open the file */ - if (fetch_name(m_in.name, m_in.name_length, M3, fullpath) != OK) - return(err_code); + if (copy_name(vname_length, fullpath) != OK) { + /* Direct copy failed, try fetching from user space */ + if (fetch_name(vname, vname_length, fullpath) != OK) + return(err_code); + } if ((vp = eat_path(&resolve, fp)) == NULL) return(err_code); } else { /* call_nr == FCHMOD */ /* File is already opened; get a pointer to vnode from filp. */ - if ((flp = get_filp(m_in.fd, VNODE_WRITE)) == NULL) - return(err_code); + if ((flp = get_filp(rfd, VNODE_WRITE)) == NULL) return(err_code); vp = flp->filp_vno; dup_vnode(vp); } @@ -65,14 +76,14 @@ int do_chmod() /* Now make the change. Clear setgid bit if file is not in caller's * group */ if (fp->fp_effuid != SU_UID && vp->v_gid != fp->fp_effgid) - m_in.mode &= ~I_SET_GID_BIT; + new_mode &= ~I_SET_GID_BIT; - r = req_chmod(vp->v_fs_e, vp->v_inode_nr, m_in.mode, &new_mode); + r = req_chmod(vp->v_fs_e, vp->v_inode_nr, new_mode, &result_mode); if (r == OK) - vp->v_mode = new_mode; + vp->v_mode = result_mode; } - if (call_nr == CHMOD) { + if (job_call_nr == CHMOD) { unlock_vnode(vp); unlock_vmnt(vmp); } else { /* FCHMOD */ @@ -94,27 +105,34 @@ int do_chown() struct filp *flp; struct vnode *vp; struct vmnt *vmp; - int r; - uid_t uid; - gid_t gid; + int r, rfd; + uid_t uid, new_uid; + gid_t gid, new_gid; mode_t new_mode; char fullpath[PATH_MAX]; struct lookup resolve; + vir_bytes vname1; + size_t vname1_length; flp = NULL; + vname1 = (vir_bytes) job_m_in.name1; + vname1_length = (size_t) job_m_in.name1_length; + rfd = job_m_in.fd; + uid = job_m_in.owner; + gid = job_m_in.group; lookup_init(&resolve, fullpath, PATH_NOFLAGS, &vmp, &vp); resolve.l_vmnt_lock = VMNT_WRITE; resolve.l_vnode_lock = VNODE_WRITE; - if (call_nr == CHOWN) { + if (job_call_nr == CHOWN) { /* Temporarily open the file. */ - if (fetch_name(m_in.name1, m_in.name1_length, M1, fullpath) != OK) + if (fetch_name(vname1, vname1_length, fullpath) != OK) return(err_code); if ((vp = eat_path(&resolve, fp)) == NULL) return(err_code); } else { /* call_nr == FCHOWN */ /* File is already opened; get a pointer to the vnode from filp. */ - if ((flp = get_filp(m_in.fd, VNODE_WRITE)) == NULL) + if ((flp = get_filp(rfd, VNODE_WRITE)) == NULL) return(err_code); vp = flp->filp_vno; dup_vnode(vp); @@ -128,27 +146,27 @@ int do_chown() if (fp->fp_effuid != SU_UID) { /* Regular users can only change groups of their own files. */ if (vp->v_uid != fp->fp_effuid) r = EPERM; - if (vp->v_uid != m_in.owner) r = EPERM; /* no giving away */ - if (fp->fp_effgid != m_in.group) r = EPERM; + if (vp->v_uid != uid) r = EPERM; /* no giving away */ + if (fp->fp_effgid != gid) r = EPERM; } } if (r == OK) { /* Do not change uid/gid if new uid/gid is -1. */ - uid = (m_in.owner == (uid_t)-1 ? vp->v_uid : m_in.owner); - gid = (m_in.group == (gid_t)-1 ? vp->v_gid : m_in.group); + new_uid = (uid == (uid_t)-1 ? vp->v_uid : uid); + new_gid = (gid == (gid_t)-1 ? vp->v_gid : gid); - if (uid > UID_MAX || gid > GID_MAX) + if (new_uid > UID_MAX || new_gid > GID_MAX) r = EINVAL; - else if ((r = req_chown(vp->v_fs_e, vp->v_inode_nr, uid, gid, + else if ((r = req_chown(vp->v_fs_e, vp->v_inode_nr, new_uid, new_gid, &new_mode)) == OK) { - vp->v_uid = uid; - vp->v_gid = gid; + vp->v_uid = new_uid; + vp->v_gid = new_gid; vp->v_mode = new_mode; } } - if (call_nr == CHOWN) { + if (job_call_nr == CHOWN) { unlock_vnode(vp); unlock_vmnt(vmp); } else { /* FCHOWN */ @@ -165,11 +183,13 @@ int do_chown() int do_umask() { /* Perform the umask(co_mode) system call. */ - register mode_t r; + mode_t complement, new_umask; + + new_umask = job_m_in.co_mode; - r = ~fp->fp_umask; /* set 'r' to complement of old mask */ - fp->fp_umask = ~(m_in.co_mode & RWX_MODES); - return(r); /* return complement of old mask */ + complement = ~fp->fp_umask; /* set 'r' to complement of old mask */ + fp->fp_umask = ~(new_umask & RWX_MODES); + return(complement); /* return complement of old mask */ } @@ -178,27 +198,39 @@ int do_umask() *===========================================================================*/ int do_access() { -/* Perform the access(name, mode) system call. */ +/* Perform the access(name, mode) system call. + * syscall might provide 'name' embedded in the message. + */ int r; struct vnode *vp; struct vmnt *vmp; char fullpath[PATH_MAX]; struct lookup resolve; + vir_bytes vname; + size_t vname_length; + mode_t access; + + vname = (vir_bytes) job_m_in.name; + vname_length = (size_t) job_m_in.name_length; + access = job_m_in.mode; lookup_init(&resolve, fullpath, PATH_NOFLAGS, &vmp, &vp); resolve.l_vmnt_lock = VMNT_READ; resolve.l_vnode_lock = VNODE_READ; /* First check to see if the mode is correct. */ - if ( (m_in.mode & ~(R_OK | W_OK | X_OK)) != 0 && m_in.mode != F_OK) + if ( (access & ~(R_OK | W_OK | X_OK)) != 0 && access != F_OK) return(EINVAL); /* Temporarily open the file. */ - if (fetch_name(m_in.name, m_in.name_length, M3, fullpath) != OK) - return(err_code); + if (copy_name(vname_length, fullpath) != OK) { + /* Direct copy failed, try fetching from user space */ + if (fetch_name(vname, vname_length, fullpath) != OK) + return(err_code); + } if ((vp = eat_path(&resolve, fp)) == NULL) return(err_code); - r = forbidden(fp, vp, m_in.mode); + r = forbidden(fp, vp, access); unlock_vnode(vp); unlock_vmnt(vmp); @@ -228,8 +260,8 @@ int forbidden(struct fproc *rfp, struct vnode *vp, mode_t access_desired) /* Isolate the relevant rwx bits from the mode. */ bits = vp->v_mode; - uid = (call_nr == ACCESS ? rfp->fp_realuid : rfp->fp_effuid); - gid = (call_nr == ACCESS ? rfp->fp_realgid : rfp->fp_effgid); + uid = (job_call_nr == ACCESS ? rfp->fp_realuid : rfp->fp_effuid); + gid = (job_call_nr == ACCESS ? rfp->fp_realgid : rfp->fp_effgid); if (uid == SU_UID) { /* Grant read and write permission. Grant search permission for diff --git a/servers/vfs/proto.h b/servers/vfs/proto.h index 5625c88ad..4091438c2 100644 --- a/servers/vfs/proto.h +++ b/servers/vfs/proto.h @@ -44,8 +44,8 @@ int ctty_opcl(int op, dev_t dev, endpoint_t proc, int flags); int clone_opcl(int op, dev_t dev, int proc, int flags); int ctty_io(int task_nr, message *mess_ptr); int do_ioctl(void); -void pm_setsid(int proc_e); -void dev_status(message *); +void pm_setsid(endpoint_t proc_e); +void dev_status(message *m); void bdev_up(int major); void cdev_up(int major); endpoint_t find_suspended_ep(endpoint_t driver, cp_grant_id_t g); @@ -71,8 +71,8 @@ int map_service(struct rprocpub *rpub); void write_elf_core_file(struct filp *f, int csig, char *exe_name); /* exec.c */ -int pm_exec(int proc_e, char *path, vir_bytes path_len, char *frame, - vir_bytes frame_len, vir_bytes *pc); +int pm_exec(int proc_e, vir_bytes path, size_t path_len, vir_bytes frame, + size_t frame_len, vir_bytes *pc); #define check_bsf_lock() do { \ assert(mutex_trylock(&bsf_lock) == 0); \ unlock_bsf(); \ @@ -121,7 +121,7 @@ void lock_revive(void); /* main.c */ int main(void); -void reply(int whom, int result); +void reply(endpoint_t whom, int result); void lock_proc(struct fproc *rfp, int force_lock); void unlock_proc(struct fproc *rfp); void *do_dummy(void *arg); @@ -182,18 +182,15 @@ int do_check_perms(void); /* pipe.c */ int do_pipe(void); int map_vnode(struct vnode *vp, endpoint_t fs_e); -void unpause(int proc_nr_e); +void unpause(endpoint_t proc_e); int pipe_check(struct vnode *vp, int rw_flag, int oflags, int bytes, u64_t position, int notouch); -void release(struct vnode *vp, int call_nr, int count); -void revive(int proc_nr, int bytes); -void suspend(int task); +void release(struct vnode *vp, int op, int count); +void revive(endpoint_t proc_e, int returned); +void suspend(int why); void pipe_suspend(struct filp *rfilp, char *buf, size_t size); -void unsuspend_by_endpt(endpoint_t); -void wait_for(endpoint_t); -#if DO_SANITYCHECKS -int check_pipe(void); -#endif +void unsuspend_by_endpt(endpoint_t proc_e); +void wait_for(endpoint_t proc_e); /* protect.c */ int do_access(void); @@ -216,55 +213,52 @@ int rw_pipe(int rw_flag, endpoint_t usr, struct filp *f, char *buf, size_t req_size); /* request.c */ -int req_breadwrite(endpoint_t fs_e, endpoint_t user_e, dev_t dev, u64_t - pos, unsigned int num_of_bytes, char *user_addr, int rw_flag, u64_t - *new_posp, unsigned int *cum_iop); -int req_chmod(int fs_e, ino_t inode_nr, mode_t rmode, mode_t - *new_modep); -int req_chown(endpoint_t fs_e, ino_t inode_nr, uid_t newuid, gid_t - newgid, mode_t *new_modep); -int req_create(int fs_e, ino_t inode_nr, int omode, uid_t uid, gid_t - gid, char *path, node_details_t *res); +int req_breadwrite(endpoint_t fs_e, endpoint_t user_e, dev_t dev, u64_t pos, + unsigned int num_of_bytes, char *user_addr, int rw_flag, + u64_t *new_posp, unsigned int *cum_iop); +int req_chmod(int fs_e, ino_t inode_nr, mode_t rmode, mode_t *new_modep); +int req_chown(endpoint_t fs_e, ino_t inode_nr, uid_t newuid, gid_t newgid, + mode_t *new_modep); +int req_create(int fs_e, ino_t inode_nr, int omode, uid_t uid, gid_t gid, + char *path, node_details_t *res); int req_flush(endpoint_t fs_e, dev_t dev); -int req_fstatfs(int fs_e, int who_e, char *buf); -int req_statvfs(int fs_e, int who_e, char *buf); +int req_fstatfs(endpoint_t fs_e, endpoint_t proc_e, vir_bytes buf); +int req_statvfs(endpoint_t fs_e, endpoint_t proc_e, vir_bytes buf); int req_ftrunc(endpoint_t fs_e, ino_t inode_nr, off_t start, off_t end); int req_getdents(endpoint_t fs_e, ino_t inode_nr, u64_t pos, char *buf, size_t size, u64_t *new_pos, int direct); int req_inhibread(endpoint_t fs_e, ino_t inode_nr); -int req_link(endpoint_t fs_e, ino_t link_parent, char *lastc, ino_t - linked_file); -int req_lookup(endpoint_t fs_e, ino_t dir_ino, ino_t root_ino, uid_t - uid, gid_t gid, struct lookup *resolve, lookup_res_t *res, struct fproc - *rfp); +int req_link(endpoint_t fs_e, ino_t link_parent, char *lastc, + ino_t linked_file); +int req_lookup(endpoint_t fs_e, ino_t dir_ino, ino_t root_ino, uid_t uid, + gid_t gid, struct lookup *resolve, lookup_res_t *res, + struct fproc *rfp); int req_mkdir(endpoint_t fs_e, ino_t inode_nr, char *lastc, uid_t uid, gid_t gid, mode_t dmode); int req_mknod(endpoint_t fs_e, ino_t inode_nr, char *lastc, uid_t uid, gid_t gid, mode_t dmode, dev_t dev); int req_mountpoint(endpoint_t fs_e, ino_t inode_nr); -int req_newnode(endpoint_t fs_e, uid_t uid, gid_t gid, mode_t dmode, - dev_t dev, struct node_details *res); +int req_newnode(endpoint_t fs_e, uid_t uid, gid_t gid, mode_t dmode, dev_t dev, + struct node_details *res); int req_putnode(int fs_e, ino_t inode_nr, int count); -int req_rdlink(endpoint_t fs_e, ino_t inode_nr, endpoint_t who_e, char - *buf, size_t len, int direct); -int req_readsuper(endpoint_t fs_e, char *driver_name, dev_t dev, int - readonly, int isroot, struct node_details *res_nodep, int *con_reqs); -int req_readwrite(endpoint_t fs_e, ino_t inode_nr, u64_t pos, int - rw_flag, endpoint_t user_e, char *user_addr, unsigned int num_of_bytes, +int req_rdlink(endpoint_t fs_e, ino_t inode_nr, endpoint_t proc_e, + vir_bytes buf, size_t len, int direct); +int req_readsuper(endpoint_t fs_e, char *driver_name, dev_t dev, int readonly, + int isroot, struct node_details *res_nodep, int *con_reqs); +int req_readwrite(endpoint_t fs_e, ino_t inode_nr, u64_t pos, int rw_flag, + endpoint_t user_e, char *user_addr, unsigned int num_of_bytes, u64_t *new_posp, unsigned int *cum_iop); -int req_rename(endpoint_t fs_e, ino_t old_dir, char *old_name, ino_t - new_dir, char *new_name); +int req_rename(endpoint_t fs_e, ino_t old_dir, char *old_name, ino_t new_dir, + char *new_name); int req_rmdir(endpoint_t fs_e, ino_t inode_nr, char *lastc); -int req_slink(endpoint_t fs_e, ino_t inode_nr, char *lastc, endpoint_t - who_e, char *path_addr, unsigned short path_length, uid_t uid, gid_t - gid); -int req_stat(int fs_e, ino_t inode_nr, int who_e, char *buf, int pos, - int stat_version); +int req_slink(endpoint_t fs_e, ino_t inode_nr, char *lastc, endpoint_t proc_e, + vir_bytes path_addr, size_t path_length, uid_t uid, gid_t gid); +int req_stat(endpoint_t fs_e, ino_t inode_nr, endpoint_t proc_e, vir_bytes buf, + int pos, int stat_version); int req_sync(endpoint_t fs_e); int req_unlink(endpoint_t fs_e, ino_t inode_nr, char *lastc); int req_unmount(endpoint_t fs_e); -int req_utime(endpoint_t fs_e, ino_t inode_nr, time_t actime, time_t - modtime); +int req_utime(endpoint_t fs_e, ino_t inode_nr, time_t actime, time_t modtime); int req_newdriver(endpoint_t fs_e, dev_t dev, char *label); /* stadir.c */ @@ -297,7 +291,8 @@ void tll_upgrade(tll_t *tllp); time_t clock_time(void); unsigned conv2(int norm, int w); long conv4(int norm, long x); -int fetch_name(char *path, int len, int flag, char *dest); +int copy_name(size_t len, char *dest); +int fetch_name(vir_bytes path, size_t len, char *dest); int no_sys(void); int isokendpt_f(char *f, int l, endpoint_t e, int *p, int ft); int in_group(struct fproc *rfp, gid_t grp); @@ -329,9 +324,6 @@ void unlock_vnode(struct vnode *vp); void dup_vnode(struct vnode *vp); void put_vnode(struct vnode *vp); void vnode_clean_refs(struct vnode *vp); -#if DO_SANITYCHECKS -int check_vrefs(void); -#endif /* write.c */ int do_write(void); @@ -357,7 +349,6 @@ int worker_available(void); struct worker_thread *worker_get(thread_t worker_tid); struct job *worker_getjob(thread_t worker_tid); void worker_init(struct worker_thread *worker); -struct worker_thread *worker_self(void); void worker_signal(struct worker_thread *worker); void worker_start(void *(*func)(void *arg)); void worker_stop(struct worker_thread *worker); diff --git a/servers/vfs/read.c b/servers/vfs/read.c index 43abe60d4..7e72cbe04 100644 --- a/servers/vfs/read.c +++ b/servers/vfs/read.c @@ -40,21 +40,18 @@ int do_read() *===========================================================================*/ void lock_bsf(void) { - message org_m_in; struct fproc *org_fp; struct worker_thread *org_self; if (mutex_trylock(&bsf_lock) == 0) return; - org_m_in = m_in; org_fp = fp; org_self = self; if (mutex_lock(&bsf_lock) != 0) panic("unable to lock block special file lock"); - m_in = org_m_in; fp = org_fp; self = org_self; } @@ -79,9 +76,9 @@ int rw_flag; /* READING or WRITING */ tll_access_t locktype; int r; - scratch(fp).file.fd_nr = m_in.fd; - scratch(fp).io.io_buffer = m_in.buffer; - scratch(fp).io.io_nbytes = (size_t) m_in.nbytes; + scratch(fp).file.fd_nr = job_m_in.fd; + scratch(fp).io.io_buffer = job_m_in.buffer; + scratch(fp).io.io_nbytes = (size_t) job_m_in.nbytes; locktype = (rw_flag == READING) ? VNODE_READ : VNODE_WRITE; if ((f = get_filp(scratch(fp).file.fd_nr, locktype)) == NULL) @@ -216,8 +213,13 @@ int do_getdents() u64_t new_pos; register struct filp *rfilp; + scratch(fp).file.fd_nr = job_m_in.fd; + scratch(fp).io.io_buffer = job_m_in.buffer; + scratch(fp).io.io_nbytes = (size_t) job_m_in.nbytes; + /* Is the file descriptor valid? */ - if ( (rfilp = get_filp(m_in.fd, VNODE_READ)) == NULL) return(err_code); + if ( (rfilp = get_filp(scratch(fp).file.fd_nr, VNODE_READ)) == NULL) + return(err_code); if (!(rfilp->filp_mode & R_BIT)) r = EBADF; @@ -229,7 +231,8 @@ int do_getdents() panic("do_getdents: can't handle large offsets"); r = req_getdents(rfilp->filp_vno->v_fs_e, rfilp->filp_vno->v_inode_nr, - rfilp->filp_pos, m_in.buffer, m_in.nbytes,&new_pos,0); + rfilp->filp_pos, scratch(fp).io.io_buffer, + scratch(fp).io.io_nbytes, &new_pos,0); if (r > 0) rfilp->filp_pos = new_pos; } diff --git a/servers/vfs/request.c b/servers/vfs/request.c index f3790def5..a311256b1 100644 --- a/servers/vfs/request.c +++ b/servers/vfs/request.c @@ -200,16 +200,16 @@ int req_flush(endpoint_t fs_e, dev_t dev) /*===========================================================================* * req_fstatfs * *===========================================================================*/ -int req_fstatfs(int fs_e, int proc_e, char *buf) +int req_fstatfs(endpoint_t fs_e, endpoint_t proc_e, vir_bytes buf) { int r; cp_grant_id_t grant_id; message m; - grant_id = cpf_grant_magic(fs_e, proc_e, (vir_bytes) buf, sizeof(struct statfs), - CPF_WRITE); - if(grant_id == -1) - panic("req_fstatfs: cpf_grant_magic failed"); + grant_id = cpf_grant_magic(fs_e, proc_e, buf, sizeof(struct statfs), + CPF_WRITE); + if (grant_id == GRANT_INVALID) + panic("req_fstatfs: cpf_grant_magic failed"); /* Fill in request message */ m.m_type = REQ_FSTATFS; @@ -226,16 +226,16 @@ int req_fstatfs(int fs_e, int proc_e, char *buf) /*===========================================================================* * req_statvfs * *===========================================================================*/ -int req_statvfs(int fs_e, int proc_e, char *buf) +int req_statvfs(endpoint_t fs_e, endpoint_t proc_e, vir_bytes buf) { int r; cp_grant_id_t grant_id; message m; - grant_id = cpf_grant_magic(fs_e, proc_e, (vir_bytes) buf, sizeof(struct statvfs), + grant_id = cpf_grant_magic(fs_e, proc_e, buf, sizeof(struct statvfs), CPF_WRITE); - if(grant_id == -1) - panic("req_statvfs: cpf_grant_magic failed"); + if(grant_id == GRANT_INVALID) + panic("req_statvfs: cpf_grant_magic failed"); /* Fill in request message */ m.m_type = REQ_STATVFS; @@ -663,7 +663,7 @@ int req_rdlink(fs_e, inode_nr, proc_e, buf, len, direct) endpoint_t fs_e; ino_t inode_nr; endpoint_t proc_e; -char *buf; +vir_bytes buf; size_t len; int direct; /* set to 1 to use direct grants instead of magic grants */ { @@ -672,12 +672,11 @@ int direct; /* set to 1 to use direct grants instead of magic grants */ cp_grant_id_t grant_id; if (direct) { - grant_id = cpf_grant_direct(fs_e, (vir_bytes) buf, len, CPF_WRITE); + grant_id = cpf_grant_direct(fs_e, buf, len, CPF_WRITE); } else { - grant_id = cpf_grant_magic(fs_e, proc_e, (vir_bytes) buf, len, - CPF_WRITE); + grant_id = cpf_grant_magic(fs_e, proc_e, buf, len, CPF_WRITE); } - if(grant_id == -1) + if (grant_id == -1) panic("req_rdlink: cpf_grant_magic failed"); /* Fill in request message */ @@ -690,7 +689,7 @@ int direct; /* set to 1 to use direct grants instead of magic grants */ r = fs_sendrec(fs_e, &m); cpf_revoke(grant_id); - if(r == OK) r = m.RES_NBYTES; + if (r == OK) r = m.RES_NBYTES; return(r); } @@ -879,8 +878,8 @@ int req_slink( ino_t inode_nr, char *lastc, endpoint_t proc_e, - char *path_addr, - unsigned short path_length, + vir_bytes path_addr, + size_t path_length, uid_t uid, gid_t gid ) @@ -892,12 +891,11 @@ int req_slink( len = strlen(lastc) + 1; gid_name = cpf_grant_direct(fs_e, (vir_bytes) lastc, len, CPF_READ); - if(gid_name == -1) + if (gid_name == GRANT_INVALID) panic("req_slink: cpf_grant_direct failed"); - gid_buf = cpf_grant_magic(fs_e, proc_e, (vir_bytes) path_addr, path_length, - CPF_READ); - if(gid_buf == -1) { + gid_buf = cpf_grant_magic(fs_e, proc_e, path_addr, path_length, CPF_READ); + if (gid_buf == GRANT_INVALID) { cpf_revoke(gid_name); panic("req_slink: cpf_grant_magic failed"); } @@ -924,13 +922,8 @@ int req_slink( /*===========================================================================* * req_stat * *===========================================================================*/ -int req_stat(fs_e, inode_nr, proc_e, buf, pos, stat_version) -int fs_e; -ino_t inode_nr; -int proc_e; -char *buf; -int pos; -int stat_version; +int req_stat(endpoint_t fs_e, ino_t inode_nr, endpoint_t proc_e, vir_bytes buf, + int pos, int stat_version) { cp_grant_id_t grant_id; int r; @@ -942,8 +935,8 @@ int stat_version; grant_id = cpf_grant_direct(fs_e, (vir_bytes) &sb, sizeof(struct stat), CPF_WRITE); else - grant_id = cpf_grant_magic(fs_e, proc_e, (vir_bytes) buf, - sizeof(struct stat), CPF_WRITE); + grant_id = cpf_grant_magic(fs_e, proc_e, buf, sizeof(struct stat), + CPF_WRITE); if (grant_id < 0) panic("req_stat: cpf_grant_* failed"); @@ -963,7 +956,7 @@ int stat_version; if (pos != 0) sb.st_size -= pos; if (stat_version == 0) { - r = sys_vircopy(SELF, D, (vir_bytes) &sb, proc_e, D, (vir_bytes) buf, + r = sys_vircopy(SELF, D, (vir_bytes) &sb, proc_e, D, buf, sizeof(struct stat)); return(r); } @@ -1000,7 +993,7 @@ int stat_version; old_sb.st_ctime = sb.st_ctime; #endif - r = sys_vircopy(SELF, D, (vir_bytes) &old_sb, proc_e, D, (vir_bytes) buf, + r = sys_vircopy(SELF, D, (vir_bytes) &old_sb, proc_e, D, buf, sizeof(struct minix_prev_stat)); return(r); diff --git a/servers/vfs/select.c b/servers/vfs/select.c index e6bd6a1b3..86dcb6880 100644 --- a/servers/vfs/select.c +++ b/servers/vfs/select.c @@ -80,7 +80,7 @@ static int select_majors[] = { /* List of majors that support selecting on */ #define SEL_MAJORS (sizeof(select_majors) / sizeof(select_majors[0])) /*===========================================================================* - * do_select * + * do_select * *===========================================================================*/ int do_select(void) { @@ -95,8 +95,10 @@ int do_select(void) int r, nfds, do_timeout = 0, fd, s; struct timeval timeout; struct selectentry *se; + vir_bytes vtimeout; - nfds = m_in.SEL_NFDS; + nfds = job_m_in.SEL_NFDS; + vtimeout = (vir_bytes) job_m_in.SEL_TIMEOUT; /* Sane amount of file descriptors? */ if (nfds < 0 || nfds > OPEN_MAX) return(EINVAL); @@ -110,17 +112,17 @@ int do_select(void) se = &selecttab[s]; wipe_select(se); /* Clear results of previous usage */ se->req_endpt = who_e; - se->vir_readfds = (fd_set *) m_in.SEL_READFDS; - se->vir_writefds = (fd_set *) m_in.SEL_WRITEFDS; - se->vir_errorfds = (fd_set *) m_in.SEL_ERRORFDS; + se->vir_readfds = (fd_set *) job_m_in.SEL_READFDS; + se->vir_writefds = (fd_set *) job_m_in.SEL_WRITEFDS; + se->vir_errorfds = (fd_set *) job_m_in.SEL_ERRORFDS; /* Copy fdsets from the process */ if ((r = copy_fdsets(se, nfds, FROM_PROC)) != OK) return(r); /* Did the process set a timeout value? If so, retrieve it. */ - if (m_in.SEL_TIMEOUT != NULL) { + if (vtimeout != 0) { do_timeout = 1; - r = sys_vircopy(who_e, D, (vir_bytes) m_in.SEL_TIMEOUT, SELF, D, + r = sys_vircopy(who_e, D, (vir_bytes) vtimeout, SELF, D, (vir_bytes) &timeout, sizeof(timeout)); if (r != OK) return(r); } @@ -304,7 +306,7 @@ static int is_pipe(struct filp *f) } /*===========================================================================* - * is_supported_major * + * is_supported_major * *===========================================================================*/ static int is_supported_major(struct filp *f) { @@ -782,7 +784,7 @@ int status; /* Find vnode and check we got a reply from the device we expected */ vp = f->filp_vno; assert(vp != NULL); - assert((vp->v_mode & I_TYPE) == I_CHAR_SPECIAL); /* Must be char. special */ + assert((vp->v_mode & I_TYPE) == I_CHAR_SPECIAL); if (vp->v_sdev != dev) { printf("VFS (%s:%d): expected reply from dev %d not %d\n", __FILE__, __LINE__, vp->v_sdev, dev); @@ -1037,7 +1039,7 @@ static void wipe_select(struct selectentry *se) } /*===========================================================================* - * select_lock_filp * + * select_lock_filp * *===========================================================================*/ static void select_lock_filp(struct filp *f, int ops) { diff --git a/servers/vfs/stadir.c b/servers/vfs/stadir.c index d0692624d..5f8003f01 100644 --- a/servers/vfs/stadir.c +++ b/servers/vfs/stadir.c @@ -27,7 +27,6 @@ #include "vnode.h" #include "vmnt.h" -static int change(struct vnode **iip, char *name_ptr, int len); static int change_into(struct vnode **iip, struct vnode *vp); /*===========================================================================* @@ -37,10 +36,12 @@ int do_fchdir() { /* Change directory on already-opened fd. */ struct filp *rfilp; - int r; + int r, rfd; + + rfd = job_m_in.fd; /* Is the file descriptor valid? */ - if ((rfilp = get_filp(m_in.fd, VNODE_READ)) == NULL) return(err_code); + if ((rfilp = get_filp(rfd, VNODE_READ)) == NULL) return(err_code); r = change_into(&fp->fp_wd, rfilp->filp_vno); unlock_filp(rfilp); return(r); @@ -51,61 +52,92 @@ int do_fchdir() *===========================================================================*/ int do_chdir() { -/* Perform the chdir(name) system call. */ +/* Perform the chdir(name) system call. + * syscall might provide 'name' embedded in the message. + */ - return change(&fp->fp_wd, m_in.name, m_in.name_length); -} + int r; + struct vnode *vp; + struct vmnt *vmp; + char fullpath[PATH_MAX]; + struct lookup resolve; + vir_bytes vname; + size_t vname_length; -/*===========================================================================* - * do_chroot * - *===========================================================================*/ -int do_chroot() -{ -/* Perform the chroot(name) system call. */ + vname = (vir_bytes) job_m_in.name; + vname_length = (size_t) job_m_in.name_length; - if (!super_user) return(EPERM); /* only su may chroot() */ - return change(&fp->fp_rd, m_in.name, m_in.name_length); + if (copy_name(vname_length, fullpath) != OK) { + /* Direct copy failed, try fetching from user space */ + if (fetch_name(vname, vname_length, fullpath) != OK) + return(err_code); + } + + /* Try to open the directory */ + lookup_init(&resolve, fullpath, PATH_NOFLAGS, &vmp, &vp); + resolve.l_vmnt_lock = VMNT_READ; + resolve.l_vnode_lock = VNODE_READ; + if ((vp = eat_path(&resolve, fp)) == NULL) return(err_code); + + r = change_into(&fp->fp_wd, vp); + + unlock_vnode(vp); + unlock_vmnt(vmp); + put_vnode(vp); + + return(r); } /*===========================================================================* - * change * + * do_chroot * *===========================================================================*/ -static int change(iip, name_ptr, len) -struct vnode **iip; /* pointer to the inode pointer for the dir */ -char *name_ptr; /* pointer to the directory name to change to */ -int len; /* length of the directory name string */ +int do_chroot() { -/* Do the actual work for chdir() and chroot(). */ +/* Perform the chroot(name) system call. + * syscall might provide 'name' embedded in the message. + */ + int r; struct vnode *vp; struct vmnt *vmp; char fullpath[PATH_MAX]; struct lookup resolve; - int r; + vir_bytes vname; + size_t vname_length; + + vname = (vir_bytes) job_m_in.name; + vname_length = (size_t) job_m_in.name_length; + + if (!super_user) return(EPERM); /* only su may chroot() */ + + if (copy_name(vname_length, fullpath) != OK) { + /* Direct copy failed, try fetching from user space */ + if (fetch_name(vname, vname_length, fullpath) != OK) + return(err_code); + } + /* Try to open the directory */ lookup_init(&resolve, fullpath, PATH_NOFLAGS, &vmp, &vp); resolve.l_vmnt_lock = VMNT_READ; resolve.l_vnode_lock = VNODE_READ; - - /* Try to open the directory */ - if (fetch_name(name_ptr, len, M3, fullpath) != OK) return(err_code); if ((vp = eat_path(&resolve, fp)) == NULL) return(err_code); - r = change_into(iip, vp); + + r = change_into(&fp->fp_rd, vp); + unlock_vnode(vp); unlock_vmnt(vmp); put_vnode(vp); + return(r); } /*===========================================================================* * change_into * *===========================================================================*/ -static int change_into(iip, vp) -struct vnode **iip; /* pointer to the inode pointer for the dir */ -struct vnode *vp; /* this is what the inode has to become */ +static int change_into(struct vnode **result, struct vnode *vp) { int r; - if (*iip == vp) return(OK); /* Nothing to do */ + if (*result == vp) return(OK); /* Nothing to do */ /* It must be a directory and also be searchable */ if ((vp->v_mode & I_TYPE) != I_DIRECTORY) @@ -115,9 +147,9 @@ struct vnode *vp; /* this is what the inode has to become */ if (r != OK) return(r); /* Everything is OK. Make the change. */ - put_vnode(*iip); /* release the old directory */ + put_vnode(*result); /* release the old directory */ dup_vnode(vp); - *iip = vp; /* acquire the new one */ + *result = vp; /* acquire the new one */ return(OK); } @@ -133,18 +165,23 @@ int do_stat() char fullpath[PATH_MAX]; struct lookup resolve; int old_stat = 0; + vir_bytes vname1, statbuf; + size_t vname1_length; + + vname1 = (vir_bytes) job_m_in.name1; + vname1_length = (size_t) job_m_in.name1_length; + statbuf = (vir_bytes) job_m_in.m1_p2; lookup_init(&resolve, fullpath, PATH_NOFLAGS, &vmp, &vp); resolve.l_vmnt_lock = VMNT_READ; resolve.l_vnode_lock = VNODE_READ; - if (call_nr == PREV_STAT) + if (job_call_nr == PREV_STAT) old_stat = 1; - if (fetch_name(m_in.name1, m_in.name1_length, M1, fullpath) != OK) - return(err_code); + if (fetch_name(vname1, vname1_length, fullpath) != OK) return(err_code); if ((vp = eat_path(&resolve, fp)) == NULL) return(err_code); - r = req_stat(vp->v_fs_e, vp->v_inode_nr, who_e, m_in.name2, 0, old_stat); + r = req_stat(vp->v_fs_e, vp->v_inode_nr, who_e, statbuf, 0, old_stat); unlock_vnode(vp); unlock_vmnt(vmp); @@ -160,15 +197,17 @@ int do_fstat() { /* Perform the fstat(fd, buf) system call. */ register struct filp *rfilp; - int r; - int pipe_pos = 0; - int old_stat = 0; + int r, pipe_pos = 0, old_stat = 0, rfd; + vir_bytes statbuf; + + statbuf = (vir_bytes) job_m_in.buffer; + rfd = job_m_in.fd; - if (call_nr == PREV_FSTAT) + if (job_call_nr == PREV_FSTAT) old_stat = 1; /* Is the file descriptor valid? */ - if ((rfilp = get_filp(m_in.fd, VNODE_READ)) == NULL) return(err_code); + if ((rfilp = get_filp(rfd, VNODE_READ)) == NULL) return(err_code); /* If we read from a pipe, send position too */ if (rfilp->filp_vno->v_pipe == I_PIPE) { @@ -180,7 +219,7 @@ int do_fstat() } r = req_stat(rfilp->filp_vno->v_fs_e, rfilp->filp_vno->v_inode_nr, - who_e, m_in.buffer, pipe_pos, old_stat); + who_e, statbuf, pipe_pos, old_stat); unlock_filp(rfilp); @@ -194,12 +233,16 @@ int do_fstatfs() { /* Perform the fstatfs(fd, buf) system call. */ struct filp *rfilp; - int r; + int r, rfd; + vir_bytes statbuf; + + rfd = job_m_in.fd; + statbuf = (vir_bytes) job_m_in.buffer; /* Is the file descriptor valid? */ - if( (rfilp = get_filp(m_in.fd, VNODE_READ)) == NULL) return(err_code); + if( (rfilp = get_filp(rfd, VNODE_READ)) == NULL) return(err_code); - r = req_fstatfs(rfilp->filp_vno->v_fs_e, who_e, m_in.buffer); + r = req_fstatfs(rfilp->filp_vno->v_fs_e, who_e, statbuf); unlock_filp(rfilp); @@ -207,7 +250,7 @@ int do_fstatfs() } /*===========================================================================* - * do_statvfs * + * do_statvfs * *===========================================================================*/ int do_statvfs() { @@ -217,15 +260,20 @@ int do_statvfs() struct vmnt *vmp; char fullpath[PATH_MAX]; struct lookup resolve; + vir_bytes vname1, statbuf; + size_t vname1_length; + + vname1 = (vir_bytes) job_m_in.name1; + vname1_length = (size_t) job_m_in.name1_length; + statbuf = (vir_bytes) job_m_in.name2; lookup_init(&resolve, fullpath, PATH_NOFLAGS, &vmp, &vp); resolve.l_vmnt_lock = VMNT_READ; resolve.l_vnode_lock = VNODE_READ; - if (fetch_name(m_in.STATVFS_NAME, m_in.STATVFS_LEN, M1, fullpath) != OK) - return(err_code); + if (fetch_name(vname1, vname1_length, fullpath) != OK) return(err_code); if ((vp = eat_path(&resolve, fp)) == NULL) return(err_code); - r = req_statvfs(vp->v_fs_e, who_e, m_in.STATVFS_BUF); + r = req_statvfs(vp->v_fs_e, who_e, statbuf); unlock_vnode(vp); unlock_vmnt(vmp); @@ -241,13 +289,15 @@ int do_fstatvfs() { /* Perform the fstat(fd, buf) system call. */ register struct filp *rfilp; - int r; + int r, rfd; + vir_bytes statbuf; - /* Is the file descriptor valid? */ - if ((rfilp = get_filp(m_in.FSTATVFS_FD, VNODE_READ)) == NULL) - return(err_code); + rfd = job_m_in.fd; + statbuf = (vir_bytes) job_m_in.name2; - r = req_statvfs(rfilp->filp_vno->v_fs_e, who_e, m_in.FSTATVFS_BUF); + /* Is the file descriptor valid? */ + if ((rfilp = get_filp(rfd, VNODE_READ)) == NULL) return(err_code); + r = req_statvfs(rfilp->filp_vno->v_fs_e, who_e, statbuf); unlock_filp(rfilp); @@ -266,18 +316,22 @@ int do_lstat() char fullpath[PATH_MAX]; struct lookup resolve; int old_stat = 0; + vir_bytes vname1, statbuf; + size_t vname1_length; + + vname1 = (vir_bytes) job_m_in.name1; + vname1_length = (size_t) job_m_in.name1_length; + statbuf = (vir_bytes) job_m_in.name2; lookup_init(&resolve, fullpath, PATH_RET_SYMLINK, &vmp, &vp); resolve.l_vmnt_lock = VMNT_READ; resolve.l_vnode_lock = VNODE_READ; - if (call_nr == PREV_LSTAT) + if (job_call_nr == PREV_LSTAT) old_stat = 1; - if (fetch_name(m_in.name1, m_in.name1_length, M1, fullpath) != OK) - return(err_code); - + if (fetch_name(vname1, vname1_length, fullpath) != OK) return(err_code); if ((vp = eat_path(&resolve, fp)) == NULL) return(err_code); - r = req_stat(vp->v_fs_e, vp->v_inode_nr, who_e, m_in.name2, 0, old_stat); + r = req_stat(vp->v_fs_e, vp->v_inode_nr, who_e, statbuf, 0, old_stat); unlock_vnode(vp); unlock_vmnt(vmp); diff --git a/servers/vfs/time.c b/servers/vfs/time.c index ed8d2d47e..dffbded57 100644 --- a/servers/vfs/time.c +++ b/servers/vfs/time.c @@ -21,41 +21,47 @@ int do_utime() { /* Perform the utime(name, timep) system call. */ - register int len; int r; - time_t actime, modtime; + time_t actime, modtime, newactime, newmodtime; struct vnode *vp; struct vmnt *vmp; char fullpath[PATH_MAX]; struct lookup resolve; + vir_bytes vname; + size_t vname_length, len; - lookup_init(&resolve, fullpath, PATH_NOFLAGS, &vmp, &vp); - resolve.l_vmnt_lock = VMNT_WRITE; - resolve.l_vnode_lock = VNODE_READ; + vname = (vir_bytes) job_m_in.utime_file; + vname_length = (size_t) job_m_in.utime_length; + actime = job_m_in.utime_actime; + modtime = job_m_in.utime_modtime; /* Adjust for case of 'timep' being NULL; * utime_strlen then holds the actual size: strlen(name)+1 */ - len = m_in.utime_length; - if (len == 0) len = m_in.utime_strlen; + len = vname_length; + if (len == 0) len = (size_t) job_m_in.utime_strlen; + + lookup_init(&resolve, fullpath, PATH_NOFLAGS, &vmp, &vp); + resolve.l_vmnt_lock = VMNT_WRITE; + resolve.l_vnode_lock = VNODE_READ; /* Temporarily open the file */ - if (fetch_name(m_in.utime_file, len, M1, fullpath) != OK) return(err_code); + if (fetch_name(vname, len, fullpath) != OK) return(err_code); if ((vp = eat_path(&resolve, fp)) == NULL) return(err_code); /* Only the owner of a file or the super user can change its name. */ r = OK; if (vp->v_uid != fp->fp_effuid && fp->fp_effuid != SU_UID) r = EPERM; - if (m_in.utime_length == 0 && r != OK) r = forbidden(fp, vp, W_BIT); + if (vname_length == 0 && r != OK) r = forbidden(fp, vp, W_BIT); if (read_only(vp) != OK) r = EROFS; /* Not even su can touch if R/O */ if (r == OK) { /* Issue request */ - if(m_in.utime_length == 0) { - actime = modtime = clock_time(); + if (vname_length == 0) { + newactime = newmodtime = clock_time(); } else { - actime = m_in.utime_actime; - modtime = m_in.utime_modtime; + newactime = actime; + newmodtime = modtime; } - r = req_utime(vp->v_fs_e, vp->v_inode_nr, actime, modtime); + r = req_utime(vp->v_fs_e, vp->v_inode_nr, newactime, newmodtime); } unlock_vnode(vp); diff --git a/servers/vfs/utility.c b/servers/vfs/utility.c index fb8fd9f11..46a578264 100644 --- a/servers/vfs/utility.c +++ b/servers/vfs/utility.c @@ -23,20 +23,13 @@ #include "vmnt.h" /*===========================================================================* - * fetch_name * + * copy_name * *===========================================================================*/ -int fetch_name(path, len, flag, dest) -char *path; /* pointer to the path in user space */ -int len; /* path length, including 0 byte */ -int flag; /* M3 means path may be in message */ -char *dest; /* pointer to where path is to be stored */ +inline int copy_name( size_t len, char *dest) { -/* Go get path and put it in 'user_fullpath'. - * If 'flag' = M3 and 'len' <= M3_STRING, the path is present in 'message'. - * If it is not, go copy it from user space. +/* Go get path and put it in 'dest'. */ register char *rpu, *rpm; - int r, count; if (len > PATH_MAX) { /* 'len' includes terminating-nul */ err_code = ENAMETOOLONG; @@ -44,22 +37,56 @@ char *dest; /* pointer to where path is to be stored */ } /* Check name length for validity. */ - if (len <= 0) { + if (len > SSIZE_MAX) { err_code = EINVAL; return(EGENERIC); } - if (flag == M3 && len <= M3_STRING) { - /* Just copy the path from the message to 'user_fullpath'. */ + if (len <= M3_STRING) { + /* Just copy the path from the message */ + int count = 0; rpu = &dest[0]; - rpm = m_in.pathname; /* contained in input message */ - count = len; - do { *rpu++ = *rpm++; } while (--count); - r = OK; + rpm = job_m_in.pathname; /* contained in input message */ + for (count = 0; count <= len; count++) + *rpu++ = *rpm++; } else { - /* String is not contained in the message. Get it from user space. */ - r = sys_datacopy(who_e, (vir_bytes) path, - VFS_PROC_NR, (vir_bytes) dest, (phys_bytes) len); + /* String is not contained in the message. */ + err_code = EINVAL; + return(EGENERIC); + } + + if (dest[len - 1] != '\0') { + err_code = ENAMETOOLONG; + return(EGENERIC); + } + + return(OK); +} + +/*===========================================================================* + * fetch_name * + *===========================================================================*/ +int fetch_name(vir_bytes path, size_t len, char *dest) +{ +/* Go get path and put it in 'dest'. */ + int r; + + if (len > PATH_MAX) { /* 'len' includes terminating-nul */ + err_code = ENAMETOOLONG; + return(EGENERIC); + } + + /* Check name length for validity. */ + if (len > SSIZE_MAX) { + err_code = EINVAL; + return(EGENERIC); + } + + /* String is not contained in the message. Get it from user space. */ + r = sys_datacopy(who_e, path, VFS_PROC_NR, (vir_bytes) dest, len); + if (r != OK) { + err_code = EINVAL; + return(r); } if (dest[len - 1] != '\0') { @@ -67,7 +94,7 @@ char *dest; /* pointer to where path is to be stored */ return(EGENERIC); } - return(r); + return(OK); } @@ -84,7 +111,8 @@ int no_sys() /*===========================================================================* * isokendpt_f * *===========================================================================*/ -int isokendpt_f(char *file, int line, endpoint_t endpoint, int *proc, int fatal) +int isokendpt_f(char *file, int line, endpoint_t endpoint, int *proc, + int fatal) { int failed = 0; endpoint_t ke; diff --git a/servers/vfs/vmnt.c b/servers/vfs/vmnt.c index 294b2a3aa..5813e5435 100644 --- a/servers/vfs/vmnt.c +++ b/servers/vfs/vmnt.c @@ -30,12 +30,12 @@ void check_vmnt_locks_by_me(struct fproc *rfp) for (vmp = &vmnt[0]; vmp < &vmnt[NR_MNTS]; vmp++) { if (tll_locked_by_me(&vmp->m_lock)) panic("Thread %d still holds vmnt lock on vmp %p call_nr=%d\n", - mthread_self(), vmp, call_nr); + mthread_self(), vmp, job_call_nr); } if (rfp->fp_vmnt_rdlocks != 0) panic("Thread %d still holds read locks on a vmnt (%d) call_nr=%d\n", - mthread_self(), rfp->fp_vmnt_rdlocks, call_nr); + mthread_self(), rfp->fp_vmnt_rdlocks, job_call_nr); } #endif diff --git a/servers/vfs/vnode.c b/servers/vfs/vnode.c index d7d14e4ab..4a9b00efd 100644 --- a/servers/vfs/vnode.c +++ b/servers/vfs/vnode.c @@ -50,13 +50,13 @@ void check_vnode_locks_by_me(struct fproc *rfp) for (vp = &vnode[0]; vp < &vnode[NR_VNODES]; vp++) { if (tll_locked_by_me(&vp->v_lock)) { panic("Thread %d still holds vnode lock on vp %x call_nr=%d\n", - mthread_self(), vp, call_nr); + mthread_self(), vp, job_call_nr); } } if (rfp->fp_vp_rdlocks != 0) panic("Thread %d still holds read locks on a vnode (%d) call_nr=%d\n", - mthread_self(), rfp->fp_vp_rdlocks, call_nr); + mthread_self(), rfp->fp_vp_rdlocks, job_call_nr); } #endif @@ -306,84 +306,3 @@ void vnode_clean_refs(struct vnode *vp) vp->v_fs_count = 1; } - -#define REFVP(v) { vp = (v); CHECKVN(v); vp->v_ref_check++; } - -#if DO_SANITYCHECKS -/*===========================================================================* - * check_vrefs * - *===========================================================================*/ -int check_vrefs() -{ - int i, bad; - int ispipe_flag, ispipe_mode; - struct vnode *vp; - struct vmnt *vmp; - struct fproc *rfp; - struct filp *f; - - /* Clear v_ref_check */ - for (vp = &vnode[0]; vp < &vnode[NR_VNODES]; ++vp) - vp->v_ref_check= 0; - - /* Count reference for processes */ - for (rfp=&fproc[0]; rfp < &fproc[NR_PROCS]; rfp++) { - if (rfp->fp_pid == PID_FREE) - continue; - if(rfp->fp_rd) REFVP(rfp->fp_rd); - if(rfp->fp_wd) REFVP(rfp->fp_wd); - } - - /* Count references from filedescriptors */ - for (f = &filp[0]; f < &filp[NR_FILPS]; f++) - { - if (f->filp_count == 0) - continue; - REFVP(f->filp_vno); - } - - /* Count references to mount points */ - for (vmp = &vmnt[0]; vmp < &vmnt[NR_MNTS]; ++vmp) - { - if (vmp->m_dev == NO_DEV) - continue; - REFVP(vmp->m_root_node); - if(vmp->m_mounted_on) - REFVP(vmp->m_mounted_on); - } - - /* Check references */ - bad= 0; - for (vp = &vnode[0]; vp < &vnode[NR_VNODES]; ++vp) - { - if (vp->v_ref_count != vp->v_ref_check) - { - printf( -"Bad reference count for inode %d on device 0x%x: found %d, listed %d\n", - vp->v_inode_nr, vp->v_dev, vp->v_ref_check, - vp->v_ref_count); - printf("last marked at %s, %d\n", - vp->v_file, vp->v_line); - bad= 1; - } - - /* Also check v_pipe */ - if (vp->v_ref_count != 0) - { - ispipe_flag= (vp->v_pipe == I_PIPE); - ispipe_mode= ((vp->v_mode & I_TYPE) == I_NAMED_PIPE); - if (ispipe_flag != ispipe_mode) - { - printf( -"Bad v_pipe for inode %d on device 0x%x: found %d, mode 0%o\n", - vp->v_inode_nr, vp->v_dev, vp->v_pipe, - vp->v_mode); - printf("last marked at %s, %d\n", - vp->v_file, vp->v_line); - bad= 1; - } - } - } - return !bad; -} -#endif diff --git a/servers/vfs/worker.c b/servers/vfs/worker.c index d380608a7..f5eaa29cf 100644 --- a/servers/vfs/worker.c +++ b/servers/vfs/worker.c @@ -38,6 +38,7 @@ void worker_init(struct worker_thread *wp) panic("couldn't set default thread stack size"); if (mthread_attr_setdetachstate(&tattr, MTHREAD_CREATE_DETACHED) != 0) panic("couldn't set default thread detach state"); + invalid_thread_id = mthread_self(); /* Assuming we're the main thread*/ pending = 0; init = 1; } @@ -131,8 +132,14 @@ static void *worker_main(void *arg) /* Carry out work */ me->w_job.j_func(&me->w_job); + /* Deregister if possible */ + if (me->w_job.j_fp != NULL) { + me->w_job.j_fp->fp_wtid = invalid_thread_id; + } + /* Mark ourselves as done */ me->w_job.j_func = NULL; + me->w_job.j_fp = NULL; } return(NULL); /* Unreachable */ @@ -283,18 +290,13 @@ static void worker_wake(struct worker_thread *worker) *===========================================================================*/ void worker_wait(void) { - struct worker_thread *worker; - - worker = worker_self(); - worker->w_job.j_m_in = m_in; /* Store important global data */ - worker->w_job.j_err_code = err_code; - assert(fp == worker->w_job.j_fp); - worker_sleep(worker); + self->w_job.j_err_code = err_code; + assert(fp == self->w_job.j_fp); + worker_sleep(self); /* We continue here after waking up */ - fp = worker->w_job.j_fp; /* Restore global data */ - m_in = worker->w_job.j_m_in; - err_code = worker->w_job.j_err_code; - assert(worker->w_next == NULL); + fp = self->w_job.j_fp; /* Restore global data */ + err_code = self->w_job.j_err_code; + assert(self->w_next == NULL); } /*===========================================================================* @@ -339,17 +341,6 @@ void worker_stop_by_endpt(endpoint_t proc_e) } } -/*===========================================================================* - * worker_self * - *===========================================================================*/ -struct worker_thread *worker_self(void) -{ - struct worker_thread *worker; - worker = worker_get(mthread_self()); - assert(worker != NULL); - return(worker); -} - /*===========================================================================* * worker_get * *===========================================================================*/ -- 2.44.0