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; - if ((off_t) m_in.flength < 0) return(EINVAL); + scratch(fp).file.fd_nr = job_m_in.fd; + length = (off_t) job_m_in.flength; + + 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; + + if (vname1_length <= 1) return(ENOENT); + if (vname1_length >= SYMLINK_MAX) return(ENAMETOOLONG); /* Get dir inode of 'name2' */ - 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); 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); + { + endpoint_t proc_e; + vir_bytes exec_path, stack_frame; + size_t exec_path_len, stack_frame_len; - /* 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; + 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. - */ + { + endpoint_t proc_e, traced_proc_e; + int term_signal; + vir_bytes core_path; - r = pm_dumpcore(m_in.PM_PROC, m_in.PM_TERM_SIG, - (vir_bytes) m_in.PM_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; - /* 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; + 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; - m_out.m_type = PM_SETUID_REPLY; - m_out.PM_PROC = m_in.PM_PROC; + proc_e = job_m_in.PM_PROC; + euid = job_m_in.PM_EID; + ruid = job_m_in.PM_RID; + 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; - m_out.m_type = PM_SETGID_REPLY; - m_out.PM_PROC = m_in.PM_PROC; + proc_e = job_m_in.PM_PROC; + egid = job_m_in.PM_EID; + rgid = job_m_in.PM_RID; + 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]; + { + 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. + 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. */ - assert(fp->fp_job.j_m_in.m_source != PM_PROC_NR); + 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; + } + + fp->fp_job.j_m_in = job_m_in; + fp->fp_flags |= FP_PM_PENDING; + + return; } - - /* 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; - } - - fp->fp_job.j_m_in = 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; - 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); + 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); + } + + 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; - m_out.m_type = PM_UNPAUSE_REPLY; - m_out.PM_PROC = m_in.PM_PROC; + proc_e = job_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; + /* 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); + /* 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; - 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 */ + new_umask = job_m_in.co_mode; + + 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,9 +52,40 @@ 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; + + vname = (vir_bytes) job_m_in.name; + vname_length = (size_t) 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); + } + + /* 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); } /*===========================================================================* @@ -61,51 +93,51 @@ int do_chdir() *===========================================================================*/ int do_chroot() { -/* Perform the chroot(name) system call. */ - - if (!super_user) return(EPERM); /* only su may chroot() */ - return change(&fp->fp_rd, m_in.name, m_in.name_length); -} - -/*===========================================================================* - * change * - *===========================================================================*/ -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 */ -{ -/* 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; - if (call_nr == PREV_FSTAT) + statbuf = (vir_bytes) job_m_in.buffer; + rfd = job_m_in.fd; + + 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; + + rfd = job_m_in.fd; + statbuf = (vir_bytes) job_m_in.name2; /* Is the file descriptor valid? */ - if ((rfilp = get_filp(m_in.FSTATVFS_FD, VNODE_READ)) == NULL) - return(err_code); - - r = req_statvfs(rfilp->filp_vno->v_fs_e, who_e, m_in.FSTATVFS_BUF); + 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; + + 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 = 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; - /* 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; - /* 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,22 @@ 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') { @@ -67,7 +60,41 @@ char *dest; /* pointer to where path is to be stored */ return(EGENERIC); } - return(r); + 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') { + err_code = ENAMETOOLONG; + return(EGENERIC); + } + + 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 * *===========================================================================*/