/*===========================================================================* * vcarry * *===========================================================================*/ static int vcarry(int grants, iovec_t *iov, int flag_rw, size_t size) { /* Carry data between caller proc and filter, through grant-vector. */ char *bufp; int i, r; size_t bytes; bufp = buffer; for(i = 0; i < grants && size > 0; i++) { bytes = MIN(size, iov[i].iov_size); if (flag_rw == FLT_WRITE) r = sys_safecopyfrom(proc_e, (vir_bytes) iov[i].iov_addr, 0, (vir_bytes) bufp, bytes, D); else r = sys_safecopyto(proc_e, (vir_bytes) iov[i].iov_addr, 0, (vir_bytes) bufp, bytes, D); if(r != OK) return r; bufp += bytes; size -= bytes; } return OK; }
static int fb_do_write(endpoint_t ep, iovec_t *iov, int minor, u64_t pos, size_t *io_bytes) { struct device dev; arch_get_device(minor, &dev); if (pos >= dev.dv_size) { return EINVAL; } if (dev.dv_size - pos < iov->iov_size) { *io_bytes = dev.dv_size - pos; } else { *io_bytes = iov->iov_size; } if (*io_bytes <= 0) { return OK; } if (has_restarted && keep_displaying_restarted()) { return EAGAIN; } return sys_safecopyfrom(ep, (cp_grant_id_t) iov->iov_addr, 0, (vir_bytes) (dev.dv_base + ex64lo(pos)), *io_bytes); }
int do_setsockopt_rcvbuf(message *dev_m_in, message *dev_m_out) { int rc; size_t rcvbuf; #if DEBUG == 1 static int call_count = 0; printf("(uds) [%d] do_setsockopt_rcvbuf() call_count=%d\n", uds_minor(dev_m_in), ++call_count); #endif rc = sys_safecopyfrom(VFS_PROC_NR, (cp_grant_id_t) dev_m_in->IO_GRANT, (vir_bytes) 0, (vir_bytes) &rcvbuf, sizeof(size_t)); if (rc != OK) { return EIO; } if (rcvbuf > PIPE_BUF) { /* The send buffer is limited to 32K at the moment. */ return ENOSYS; } /* There is no way to reduce the send buffer, do we have to * let this call fail for smaller buffers? */ return OK; }
/*===========================================================================* * fs_mknod * *===========================================================================*/ PUBLIC int fs_mknod() { struct inode *ip, *ldirp; char lastc[NAME_MAX]; phys_bytes len; /* Copy the last component and set up caller's user and group id */ len = min( (unsigned) fs_m_in.REQ_PATH_LEN, sizeof(lastc)); err_code = sys_safecopyfrom(VFS_PROC_NR, (cp_grant_id_t) fs_m_in.REQ_GRANT, (vir_bytes) 0, (vir_bytes) lastc, (size_t) len, D); if (err_code != OK) return err_code; NUL(lastc, len, sizeof(lastc)); caller_uid = (uid_t) fs_m_in.REQ_UID; caller_gid = (gid_t) fs_m_in.REQ_GID; /* Get last directory inode */ if((ldirp = get_inode(fs_dev, (ino_t) fs_m_in.REQ_INODE_NR)) == NULL) return(ENOENT); /* Try to create the new node */ ip = new_node(ldirp, lastc, (mode_t) fs_m_in.REQ_MODE, (zone_t) fs_m_in.REQ_DEV); put_inode(ip); put_inode(ldirp); return(err_code); }
/*===========================================================================* * fs_mknod * *===========================================================================*/ int fs_mknod() { struct minix_inode *ip, *ldirp; char lastc[MINIXFS_NAME_MAX]; phys_bytes len; /* Copy the last component and set up caller's user and group id */ len = MFS_MIN(fs_m_in.REQ_PATH_LEN, sizeof(lastc)); err_code = sys_safecopyfrom(VFS_PROC_NR, fs_m_in.REQ_GRANT, 0, (vir_bytes) lastc, (phys_bytes) len, D); if (err_code != 0) return err_code; MFS_NUL(lastc, len, sizeof(lastc)); caller_uid = fs_m_in.REQ_UID; caller_gid = fs_m_in.REQ_GID; /* Get last directory inode */ if((ldirp = get_inode(fs_dev, fs_m_in.REQ_INODE_NR)) == NIL_INODE) return(-ENOENT); /* Try to create the new node */ ip = new_node(ldirp, lastc, fs_m_in.REQ_MODE, (zone_t) fs_m_in.REQ_DEV); put_inode(ip); put_inode(ldirp); return(err_code); }
int do_shutdown(message *dev_m_in, message *dev_m_out) { int minor; int rc, how; #if DEBUG == 1 static int call_count = 0; printf("(uds) [%d] do_shutdown() call_count=%d\n", uds_minor(dev_m_in), ++call_count); #endif minor = uds_minor(dev_m_in); if (uds_fd_table[minor].type != SOCK_STREAM && uds_fd_table[minor].type != SOCK_SEQPACKET) { /* socket must be a connection oriented socket */ return EINVAL; } if (uds_fd_table[minor].peer == -1) { /* shutdown(2) is only valid for connected sockets */ if (uds_fd_table[minor].err == ECONNRESET) { return ECONNRESET; } else { return ENOTCONN; } } /* get the 'how' parameter from the process */ rc = sys_safecopyfrom(VFS_PROC_NR, (cp_grant_id_t) dev_m_in->IO_GRANT, (vir_bytes) 0, (vir_bytes) &how, sizeof(int)); if (rc != OK) { return EIO; } switch (how) { case SHUT_RD: /* take away read permission */ uds_fd_table[minor].mode &= ~S_IRUSR; break; case SHUT_WR: /* take away write permission */ uds_fd_table[minor].mode &= ~S_IWUSR; break; case SHUT_RDWR: /* completely shutdown */ uds_fd_table[minor].mode = 0; break; default: /* the 'how' parameter is invalid */ return EINVAL; } return OK; }
static int do_rs_init(message *m) { int s, i; static struct rprocpub rprocpub[NR_BOOT_PROCS]; /* Map all the services in the boot image. */ if((s = sys_safecopyfrom(RS_PROC_NR, m->RS_INIT_RPROCTAB_GID, 0, (vir_bytes) rprocpub, sizeof(rprocpub))) != OK) { panic("vm: sys_safecopyfrom (rs) failed: %d", s); } for(i=0;i < NR_BOOT_PROCS;i++) { if(rprocpub[i].in_use) { if((s = map_service(&rprocpub[i])) != OK) { panic("unable to map service: %d", s); } } } /* RS expects this response that it then again wants to reply to: */ m->RS_INIT_RESULT = OK; sendrec(RS_PROC_NR, m); return(SUSPEND); }
static int do_request(message *m) { struct vumap_vir vvec[MAPVEC_NR + 3]; struct vumap_phys pvec[MAPVEC_NR + 3]; int r, r2, access, vcount, pcount; size_t offset; assert(m->m_type == VTR_RELAY); vcount = m->VTR_VCOUNT; pcount = m->VTR_PCOUNT; offset = m->VTR_OFFSET; access = m->VTR_ACCESS; r2 = sys_safecopyfrom(m->m_source, m->VTR_VGRANT, 0, (vir_bytes) vvec, sizeof(vvec[0]) * vcount); assert(r2 == OK); r = sys_vumap(m->m_source, vvec, vcount, offset, access, pvec, &pcount); if (pcount >= 1 && pcount <= MAPVEC_NR + 3) { r2 = sys_safecopyto(m->m_source, m->VTR_PGRANT, 0, (vir_bytes) pvec, sizeof(pvec[0]) * pcount); assert(r2 == OK); } m->VTR_PCOUNT = pcount; return r; }
/* ** Name: void user2mem(dpeth_t *dep, buff_t *txbuff) ** Function: Copies a packet from user area to local buffer. */ void user2mem(dpeth_t *dep, buff_t *txbuff) { int bytes, ix = 0; iovec_dat_s_t *iovp = &dep->de_write_iovec; int r, pktsize = txbuff->size; char *buffer = txbuff->buffer; do { /* Reads chuncks of packet from user buffers */ bytes = iovp->iod_iovec[ix].iov_size; /* Size of buffer */ if (bytes > pktsize) bytes = pktsize; r= sys_safecopyfrom(iovp->iod_proc_nr, iovp->iod_iovec[ix].iov_grant, 0, (vir_bytes)buffer, bytes); if (r != OK) panic("user2mem: sys_safecopyfrom failed: %d", r); buffer += bytes; if (++ix >= IOVEC_NR) { /* Next buffer of IO vector */ dp_next_iovec(iovp); ix = 0; } /* Till packet done */ } while ((pktsize -= bytes) > 0); return; }
/*===========================================================================* * fs_new_driver * *===========================================================================*/ int fs_new_driver(void) { /* Set a new driver endpoint for this device. */ dev_t dev; cp_grant_id_t label_gid; size_t label_len; char label[sizeof(fs_dev_label)]; int r; dev = (dev_t) fs_m_in.REQ_DEV; label_gid = (cp_grant_id_t) fs_m_in.REQ_GRANT; label_len = (size_t) fs_m_in.REQ_PATH_LEN; if (label_len > sizeof(label)) return(EINVAL); r = sys_safecopyfrom(fs_m_in.m_source, label_gid, (vir_bytes) 0, (vir_bytes) label, label_len); if (r != OK) { printf("ext2: fs_new_driver safecopyfrom failed (%d)\n", r); return(EINVAL); } bdev_driver(dev, label); return(OK); }
/*===========================================================================* * fs_unlink * *===========================================================================*/ int fs_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. */ register struct inode *rip; struct inode *rldirp; int r; char string[NAME_MAX + 1]; phys_bytes len; /* Copy the last component */ len = fs_m_in.REQ_PATH_LEN; /* including trailing '\0' */ if (len > NAME_MAX + 1 || len > EXT2_NAME_MAX + 1) return(ENAMETOOLONG); r = sys_safecopyfrom(VFS_PROC_NR, (cp_grant_id_t) fs_m_in.REQ_GRANT, (vir_bytes) 0, (vir_bytes) string, (size_t) len); if (r != OK) return r; NUL(string, len, sizeof(string)); /* Temporarily open the dir. */ if( (rldirp = get_inode(fs_dev, (ino_t) fs_m_in.REQ_INODE_NR)) == NULL) return(EINVAL); /* The last directory exists. Does the file also exist? */ rip = advance(rldirp, string, IGN_PERM); r = err_code; /* If error, return inode. */ if(r != OK) { /* Mount point? */ if (r == EENTERMOUNT || r == ELEAVEMOUNT) { put_inode(rip); r = EBUSY; } put_inode(rldirp); return(r); } /* Now test if the call is allowed, separately for unlink() and rmdir(). */ if(fs_m_in.m_type == REQ_UNLINK) { /* Only the su may unlink directories, but the su can unlink any * dir.*/ if( (rip->i_mode & I_TYPE) == I_DIRECTORY) r = EPERM; /* Actually try to unlink the file; fails if parent is mode 0 etc. */ if (r == OK) r = unlink_file(rldirp, rip, string); } else { r = remove_dir(rldirp, rip, string); /* call is RMDIR */ } /* If unlink was possible, it has been done, otherwise it has not. */ put_inode(rip); put_inode(rldirp); return(r); }
/*===========================================================================* * do_vrdwt * *===========================================================================*/ static int do_vrdwt(int flag_rw) { size_t size, size_ret; int grants; int r, i; u64_t pos; iovec_t iov_proc[NR_IOREQS]; /* Extract informations. */ grants = m_in.BDEV_COUNT; if((r = sys_safecopyfrom(who_e, grant_id, 0, (vir_bytes) iov_proc, grants * sizeof(iovec_t))) != OK) { panic("copying in grant vector failed: %d", r); } pos = make64(m_in.BDEV_POS_LO, m_in.BDEV_POS_HI); for(size = 0, i = 0; i < grants; i++) size += iov_proc[i].iov_size; if (rem64u(pos, SECTOR_SIZE) != 0 || size % SECTOR_SIZE != 0) { printf("Filter: unaligned request from caller!\n"); return EINVAL; } buffer = flt_malloc(size, buf_array, BUF_SIZE); if(flag_rw == FLT_WRITE) vcarry(grants, iov_proc, flag_rw, size); reset_kills(); for (;;) { size_ret = size; r = transfer(pos, buffer, &size_ret, flag_rw); if(r != RET_REDO) break; #if DEBUG printf("Filter: transfer yielded RET_REDO, checking drivers\n"); #endif if((r = check_driver(DRIVER_MAIN)) != OK) break; if((r = check_driver(DRIVER_BACKUP)) != OK) break; } if(r != OK) { flt_free(buffer, size, buf_array); return r; } if(flag_rw == FLT_READ) vcarry(grants, iov_proc, flag_rw, size_ret); flt_free(buffer, size, buf_array); return size_ret; }
static void virtio_net_fetch_iovec(iovec_s_t *iov, message *m, cp_grant_id_t grant, size_t count) { int r; r = sys_safecopyfrom(m->m_source, grant, 0, (vir_bytes)iov, count * sizeof(iov[0])); if (r != OK) panic("%s: iovec fail for %d (%d)", name, m->m_source, r); }
int fs_lookup_credentials(vfs_ucred_t *credentials, uid_t *caller_uid, gid_t *caller_gid, cp_grant_id_t grant2, size_t cred_size) { vfs_ucred_old_t old_cred; int r; memset(credentials, 0, sizeof(*credentials)); if(cred_size == sizeof(*credentials)) { r = sys_safecopyfrom(VFS_PROC_NR, grant2, (vir_bytes) 0, (vir_bytes) credentials, cred_size); if (r != OK) { printf("FS: cred copy (regular) failed.\n"); return(r); } } else if(cred_size == sizeof(old_cred)) { int g; r = sys_safecopyfrom(VFS_PROC_NR, grant2, (vir_bytes) 0, (vir_bytes) &old_cred, sizeof(old_cred)); if (r != OK) { printf("FS: cred copy (fallback) failed.\n"); return(r); } credentials->vu_ngroups = old_cred.vu_ngroups; credentials->vu_uid = old_cred.vu_uid; credentials->vu_gid = old_cred.vu_gid; for(g = 0; g < NGROUPS_MAX_OLD; g++) { assert(g < NGROUPS_MAX); credentials->vu_sgroups[g] = old_cred.vu_sgroups[g]; } } else { static int w = 0; if(!w) { printf("FS: cred size incompatible with VFS.\n"); w = 1; } return(EINVAL); /* Wrong size. */ } assert(credentials->vu_ngroups <= NGROUPS_MAX); *caller_uid = credentials->vu_uid; *caller_gid = credentials->vu_gid; return OK; }
static void virtio_net_fetch_iovec(iovec_s_t *iov, message *m) { int r; r = sys_safecopyfrom(m->m_source, m->DL_GRANT, 0, (vir_bytes)iov, m->DL_COUNT * sizeof(iov[0])); if (r != OK) panic("%s: iovec fail for %d (%d)", name, m->m_source, r); }
/*===========================================================================* * fs_readsuper * *===========================================================================*/ PUBLIC int fs_readsuper() { cp_grant_id_t label_gid; size_t label_len; int r = OK; endpoint_t driver_e; int readonly; fs_dev = fs_m_in.REQ_DEV; label_gid = fs_m_in.REQ_GRANT; label_len = fs_m_in.REQ_PATH_LEN; readonly = 1; /* Always mount devices read only. */ if (label_len > sizeof(fs_dev_label)) return(EINVAL); r = sys_safecopyfrom(fs_m_in.m_source, label_gid, 0, (vir_bytes)fs_dev_label, label_len, D); if (r != OK) { printf("ISOFS %s:%d safecopyfrom failed: %d\n", __FILE__, __LINE__, r); return(EINVAL); } r = ds_retrieve_label_endpt(fs_dev_label, &driver_e); if (r != OK) { printf("ISOFS %s:%d ds_retrieve_label_endpt failed for '%s': %d\n", __FILE__, __LINE__, fs_dev_label, r); return(EINVAL); } /* Map the driver endpoint for this major */ driver_endpoints[(fs_dev >> MAJOR) & BYTE].driver_e = driver_e; /* Open the device the file system lives on */ if (dev_open(driver_e, fs_dev, driver_e, readonly ? R_BIT : (R_BIT|W_BIT)) != OK) { return(EINVAL); } /* Read the superblock */ r = read_vds(&v_pri, fs_dev); if (r != OK) return(r); /* Return some root inode properties */ fs_m_out.RES_INODE_NR = ID_DIR_RECORD(v_pri.dir_rec_root); fs_m_out.RES_MODE = v_pri.dir_rec_root->d_mode; fs_m_out.RES_FILE_SIZE_LO = v_pri.dir_rec_root->d_file_size; fs_m_out.RES_UID = SYS_UID; /* Always root */ fs_m_out.RES_GID = SYS_GID; /* operator */ fs_m_out.RES_CONREQS = 1; /* We can handle only 1 request at a time */ return(r); }
/*===========================================================================* * fs_create * *===========================================================================*/ int fs_create() { phys_bytes len; int r; struct inode *ldirp; struct inode *rip; mode_t omode; char lastc[NAME_MAX + 1]; /* Read request message */ omode = (mode_t) fs_m_in.REQ_MODE; caller_uid = (uid_t) fs_m_in.REQ_UID; caller_gid = (gid_t) fs_m_in.REQ_GID; /* Try to make the file. */ /* Copy the last component (i.e., file name) */ len = fs_m_in.REQ_PATH_LEN; /* including trailing '\0' */ if (len > NAME_MAX + 1 || len > EXT2_NAME_MAX + 1) return(ENAMETOOLONG); err_code = sys_safecopyfrom(VFS_PROC_NR, (cp_grant_id_t) fs_m_in.REQ_GRANT, (vir_bytes) 0, (vir_bytes) lastc, (size_t) len); if (err_code != OK) return err_code; NUL(lastc, len, sizeof(lastc)); /* Get last directory inode (i.e., directory that will hold the new inode) */ if ((ldirp = get_inode(fs_dev, (ino_t) fs_m_in.REQ_INODE_NR)) == NULL) return(ENOENT); /* Create a new inode by calling new_node(). */ rip = new_node(ldirp, lastc, omode, NO_BLOCK); r = err_code; /* If an error occurred, release inode. */ if (r != OK) { put_inode(ldirp); put_inode(rip); return(r); } /* Reply message */ fs_m_out.RES_INODE_NR = rip->i_num; fs_m_out.RES_MODE = rip->i_mode; fs_m_out.RES_FILE_SIZE_LO = rip->i_size; /* This values are needed for the execution */ fs_m_out.RES_UID = rip->i_uid; fs_m_out.RES_GID = rip->i_gid; /* Drop parent dir */ put_inode(ldirp); return(OK); }
/* ** Name: void get_userdata_s(int user_proc, vir_bytes user_addr, int count, void *loc_addr) ** Function: Copies data from user area. */ static void get_userdata_s(int user_proc, cp_grant_id_t grant, vir_bytes offset, int count, void *loc_addr) { int rc; vir_bytes len; len = (count > IOVEC_NR ? IOVEC_NR : count) * sizeof(iovec_t); if ((rc = sys_safecopyfrom(user_proc, grant, 0, (vir_bytes)loc_addr, len, D)) != OK) panic(CopyErrMsg, rc); return; }
/*===========================================================================* * fs_create * *===========================================================================*/ int fs_create() { phys_bytes len; int r, b; struct minix_inode *ldirp; struct minix_inode *rip; mode_t omode; char lastc[MINIXFS_NAME_MAX]; /* Read request message */ omode = fs_m_in.REQ_MODE; caller_uid = fs_m_in.REQ_UID; caller_gid = fs_m_in.REQ_GID; /* Try to make the file. */ /* Copy the last component (i.e., file name) */ len = MFS_MIN(fs_m_in.REQ_PATH_LEN, sizeof(lastc)); err_code = sys_safecopyfrom(VFS_PROC_NR, fs_m_in.REQ_GRANT, 0, (vir_bytes) lastc, (phys_bytes) len, D); if (err_code != 0) return err_code; MFS_NUL(lastc, len, sizeof(lastc)); /* Get last directory inode (i.e., directory that will hold the new inode) */ if ((ldirp = get_inode(fs_dev, fs_m_in.REQ_INODE_NR)) == NIL_INODE) return(-ENOENT); /* Create a new inode by calling new_node(). */ rip = new_node(ldirp, lastc, omode, NO_ZONE); r = err_code; /* If an error occurred, release inode. */ if (r != 0) { put_inode(ldirp); put_inode(rip); return(r); } /* Reply message */ fs_m_out.m_source = rip->i_dev; /* filled with FS endpoint by the system */ fs_m_out.RES_INODE_NR = rip->i_num; fs_m_out.RES_MODE = rip->i_mode; fs_m_out.RES_FILE_SIZE_LO = rip->i_size; /* This values are needed for the execution */ fs_m_out.RES_UID = rip->i_uid; fs_m_out.RES_GID = rip->i_gid; /* Drop parent dir */ put_inode(ldirp); return(0); }
/*===========================================================================* * carry * *===========================================================================*/ static int carry(size_t size, int flag_rw) { /* Carry data between caller proc and filter. */ if (flag_rw == FLT_WRITE) return sys_safecopyfrom(proc_e, grant_id, 0, (vir_bytes) buffer, size, D); else return sys_safecopyto(proc_e, grant_id, 0, (vir_bytes) buffer, size, D); }
static int hello_transfer(endpoint_t endpt, int opcode, u64_t position, iovec_t *iov, unsigned nr_req, endpoint_t user_endpt, unsigned int UNUSED(flags)) { int bytes, ret; // printf("hello_transfer()\n"); if (nr_req != 1) { /* This should never trigger for character drivers at the moment. */ printf("HELLO: vectored transfer request, using first element only\n"); } bytes = SECRET_SIZE - ex64lo(position) < iov->iov_size ? SECRET_SIZE - ex64lo(position) : iov->iov_size; // printf("iov->iov_size: %lu, transfer() bytes: %d\n", iov->iov_size, bytes); if (bytes <= 0) { return OK; } switch (opcode) { case DEV_SCATTER_S: printf("transfer() WRITE...\n"); ret = sys_safecopyfrom(user_endpt, (cp_grant_id_t) iov->iov_addr, 0, (vir_bytes) (the_secret + ex64lo(position)), bytes); iov->iov_size += bytes; printf("the secret: %s\n", the_secret); break; case DEV_GATHER_S: printf("transfer() READ...\n"); ret = sys_safecopyto(endpt, (cp_grant_id_t) iov->iov_addr, 0, (vir_bytes) (the_secret + ex64lo(position)), bytes); iov->iov_size -= bytes; printf("the secret: %s\n", the_secret); break; default: fprintf(stderr, "Unknown opcode: %d\n", opcode); return EINVAL; } return ret; }
static int copyfrom(endpoint_t src_e, cp_grant_id_t gr_id, vir_bytes offset, vir_bytes address, size_t bytes) { /* Helper function that used memcpy to copy data when the endpoint == * SELF */ if (src_e == SELF) { memcpy((char *) address, (char *) gr_id + offset, bytes); return OK; } else { return sys_safecopyfrom(src_e, gr_id, offset, address, bytes); } }
int do_socket(message *dev_m_in, message *dev_m_out) { int rc; int minor; #if DEBUG == 1 static int call_count = 0; printf("(uds) [%d] do_socket() call_count=%d\n", uds_minor(dev_m_in), ++call_count); #endif minor = uds_minor(dev_m_in); /* see if this socket already has a type */ if (uds_fd_table[minor].type != -1) { /* socket type can only be set once */ return EINVAL; } /* get the requested type */ rc = sys_safecopyfrom(VFS_PROC_NR, (cp_grant_id_t) dev_m_in->IO_GRANT, (vir_bytes) 0, (vir_bytes) &(uds_fd_table[minor].type), sizeof(int)); if (rc != OK) { /* something went wrong and we couldn't get the type */ return EIO; } /* validate the type */ switch (uds_fd_table[minor].type) { case SOCK_STREAM: case SOCK_DGRAM: case SOCK_SEQPACKET: /* the type is one of the 3 valid socket types */ return OK; default: /* if the type isn't one of the 3 valid socket * types, then it must be invalid. */ /* set the type back to '-1' (no type set) */ uds_fd_table[minor].type = -1; return EINVAL; } }
static int fetch_t(endpoint_t ep, cp_grant_id_t gid, struct tm *t) { int r; r = sys_safecopyfrom(ep, gid, (vir_bytes) 0, (vir_bytes) t, sizeof(struct tm)); if (r != OK) { log_warn(&log, "sys_safecopyfrom() failed (r=%d)\n", r); return r; } return OK; }
int do_socketpair(message *dev_m_in, message *dev_m_out) { int rc; dev_t minorin; int minorx, minory; struct sockaddr_un addr; #if DEBUG == 1 static int call_count = 0; printf("(uds) [%d] do_socketpair() call_count=%d\n", uds_minor(dev_m_in), ++call_count); #endif /* first ioctl param is the first socket */ minorx = uds_minor(dev_m_in); /* third ioctl param is the minor number of the second socket */ rc = sys_safecopyfrom(VFS_PROC_NR, (cp_grant_id_t) dev_m_in->IO_GRANT, (vir_bytes) 0, (vir_bytes) &minorin, sizeof(dev_t)); if (rc != OK) { return EIO; } minory = minor(minorin); #if DEBUG == 1 printf("socketpair() %d - %d\n", minorx, minory); #endif /* security check - both sockets must have the same endpoint (owner) */ if (uds_fd_table[minorx].owner != uds_fd_table[minory].owner) { /* we won't allow you to magically connect your socket to * someone elses socket */ return EPERM; } addr.sun_family = AF_UNIX; addr.sun_path[0] = 'X'; addr.sun_path[1] = '\0'; uds_fd_table[minorx].syscall_done = 1; return perform_connection(dev_m_in, dev_m_out, &addr, minorx, minory); }
/*===========================================================================* * do_dioctl * *===========================================================================*/ static int do_dioctl(struct blockdriver *bdp, dev_t minor, unsigned long request, endpoint_t endpt, cp_grant_id_t grant) { /* Carry out a disk-specific I/O control request. */ struct device *dv; struct part_geom entry; int r = EINVAL; switch (request) { case DIOCSETP: /* Copy just this one partition table entry. */ r = sys_safecopyfrom(endpt, grant, 0, (vir_bytes) &entry, sizeof(entry)); if (r != OK) return r; if ((dv = (*bdp->bdr_part)(minor)) == NULL) return ENXIO; dv->dv_base = entry.base; dv->dv_size = entry.size; break; case DIOCGETP: /* Return a partition table entry and the geometry of the drive. */ if ((dv = (*bdp->bdr_part)(minor)) == NULL) return ENXIO; entry.base = dv->dv_base; entry.size = dv->dv_size; if (bdp->bdr_geometry) { (*bdp->bdr_geometry)(minor, &entry); } else { /* The driver doesn't care -- make up fake geometry. */ entry.cylinders = (unsigned long)(entry.size / SECTOR_SIZE) / (64 * 32); entry.heads = 64; entry.sectors = 32; } r = sys_safecopyto(endpt, grant, 0, (vir_bytes) &entry, sizeof(entry)); break; } return r; }
static int do_pan_display(int minor, endpoint_t ep, cp_grant_id_t gid) { int r; struct fb_var_screeninfo fbvs_copy; if (has_restarted && keep_displaying_restarted()) { return EAGAIN; } if ((r = sys_safecopyfrom(ep, gid, 0, (vir_bytes) &fbvs_copy, sizeof(fbvs_copy))) != OK) { return r; } return arch_pan_display(minor, &fbvs_copy); }
/*==========================================================================* * prepare_output * *==========================================================================*/ static void prepare_output() { /* Start next chunk of printer output. Fetch the data from user space. */ int s; register int chunk; if ( (chunk = user_left) > sizeof obuf) chunk = sizeof obuf; s=sys_safecopyfrom(caller, grant_nr, user_vir_d, (vir_bytes) obuf, chunk); if(s != OK) { done_status = EFAULT; output_done(); return; } optr = obuf; oleft = chunk; }
int do_sendto(message *dev_m_in, message *dev_m_out) { int minor; int rc; struct sockaddr_un addr; #if DEBUG == 1 static int call_count = 0; printf("(uds) [%d] do_sendto() call_count=%d\n", uds_minor(dev_m_in), ++call_count); #endif minor = uds_minor(dev_m_in); if (uds_fd_table[minor].type != SOCK_DGRAM) { /* This IOCTL is only for SOCK_DGRAM sockets */ return EINVAL; } rc = sys_safecopyfrom(VFS_PROC_NR, (cp_grant_id_t) dev_m_in->IO_GRANT, (vir_bytes) 0, (vir_bytes) &addr, sizeof(struct sockaddr_un), D); if (rc != OK) { return EIO; } /* do some basic sanity checks on the address */ if (addr.sun_family != AF_UNIX || addr.sun_path[0] == '\0') { /* bad address */ return EINVAL; } rc = check_perms(minor, &addr); if (rc != OK) { return rc; } memcpy(&(uds_fd_table[minor].target), &addr, sizeof(struct sockaddr_un)); return OK; }
/*===========================================================================* * do_vrdwt * *===========================================================================*/ static int do_vrdwt(struct chardriver *cdp, message *mp) { /* Carry out an device read or write to/from a vector of user addresses. * The "user addresses" are assumed to be safe, i.e. FS transferring to/from * its own buffers, so they are not checked. */ iovec_t iovec[NR_IOREQS]; phys_bytes iovec_size; unsigned nr_req; int r, opcode; u64_t position; nr_req = mp->COUNT; /* Length of I/O vector */ /* Copy the vector from the caller to kernel space. */ if (nr_req > NR_IOREQS) nr_req = NR_IOREQS; iovec_size = (phys_bytes) (nr_req * sizeof(iovec[0])); if (OK != sys_safecopyfrom(mp->m_source, (vir_bytes) mp->IO_GRANT, 0, (vir_bytes) iovec, iovec_size)) { printf("bad I/O vector by: %d\n", mp->m_source); return(EINVAL); } /* Prepare for I/O. */ if ((*cdp->cdr_prepare)(mp->DEVICE) == NULL) return(ENXIO); /* Transfer bytes from/to the device. */ opcode = mp->m_type; position= (u64_t)mp->POSITION | ((u64_t)mp->HIGHPOS<<32); r = (*cdp->cdr_transfer)(mp->m_source, opcode, position, iovec, nr_req, mp->USER_ENDPT, mp->FLAGS); /* Copy the I/O vector back to the caller. */ if (OK != sys_safecopyto(mp->m_source, (vir_bytes) mp->IO_GRANT, 0, (vir_bytes) iovec, iovec_size)) { printf("couldn't return I/O vector: %d\n", mp->m_source); return(EINVAL); } return(r); }