int os_process_parent(int pid) { char stat[STAT_PATH_LEN]; char data[256]; int parent, n, fd; if(pid == -1) return(-1); snprintf(stat, sizeof(stat), "/proc/%d/stat", pid); fd = os_open_file(stat, of_read(OPENFLAGS()), 0); if(fd < 0){ printk("Couldn't open '%s', err = %d\n", stat, -fd); return(FAILURE_PID); } n = os_read_file(fd, data, sizeof(data)); os_close_file(fd); if(n < 0){ printk("Couldn't read '%s', err = %d\n", stat, -n); return(FAILURE_PID); } parent = FAILURE_PID; n = sscanf(data, "%*d " COMM_SCANF " %*c %d", &parent); if(n != 1) printk("Failed to scan '%s'\n", data); return(parent); }
static ssize_t hostaudio_read(struct file *file, char __user *buffer, size_t count, loff_t *ppos) { struct hostaudio_state *state = file->private_data; void *kbuf; int err; #ifdef DEBUG printk(KERN_DEBUG "hostaudio: read called, count = %d\n", count); #endif kbuf = kmalloc(count, GFP_KERNEL); if (kbuf == NULL) return -ENOMEM; err = os_read_file(state->fd, kbuf, count); if (err < 0) goto out; if (copy_to_user(buffer, kbuf, err)) err = -EFAULT; out: kfree(kbuf); return err; }
unsigned long os_process_pc(int pid) { char proc_stat[STAT_PATH_LEN], buf[256]; unsigned long pc; int fd, err; sprintf(proc_stat, "/proc/%d/stat", pid); fd = os_open_file(proc_stat, of_read(OPENFLAGS()), 0); if(fd < 0){ printk("os_process_pc - couldn't open '%s', err = %d\n", proc_stat, -fd); return(ARBITRARY_ADDR); } err = os_read_file(fd, buf, sizeof(buf)); if(err < 0){ printk("os_process_pc - couldn't read '%s', err = %d\n", proc_stat, -err); os_close_file(fd); return(ARBITRARY_ADDR); } os_close_file(fd); pc = ARBITRARY_ADDR; if(sscanf(buf, "%*d " COMM_SCANF " %*c %*d %*d %*d %*d %*d %*d %*d " "%*d %*d %*d %*d %*d %*d %*d %*d %*d %*d %*d %*d %*d %*d " "%*d %*d %*d %*d %*d %lu", &pc) != 1){ printk("os_process_pc - couldn't find pc in '%s'\n", buf); } return(pc); }
static irqreturn_t sigio_interrupt(int irq, void *data) { char c; os_read_file(sigio_irq_fd, &c, sizeof(c)); reactivate_fd(sigio_irq_fd, SIGIO_WRITE_IRQ); return IRQ_HANDLED; }
void switch_to_tt(void *prev, void *next) { struct task_struct *from, *to, *prev_sched; unsigned long flags; int err, vtalrm, alrm, prof, cpu; char c; from = prev; to = next; cpu = from->thread_info->cpu; if(cpu == 0) forward_interrupts(to->thread.mode.tt.extern_pid); #ifdef CONFIG_SMP forward_ipi(cpu_data[cpu].ipi_pipe[0], to->thread.mode.tt.extern_pid); #endif local_irq_save(flags); vtalrm = change_sig(SIGVTALRM, 0); alrm = change_sig(SIGALRM, 0); prof = change_sig(SIGPROF, 0); forward_pending_sigio(to->thread.mode.tt.extern_pid); c = 0; err = os_write_file(to->thread.mode.tt.switch_pipe[1], &c, sizeof(c)); if(err != sizeof(c)) panic("write of switch_pipe failed, err = %d", -err); if(from->thread.mode.tt.switch_pipe[0] == -1) os_kill_process(os_getpid(), 0); err = os_read_file(from->thread.mode.tt.switch_pipe[0], &c, sizeof(c)); if(err != sizeof(c)) panic("read of switch_pipe failed, errno = %d", -err); /* If the process that we have just scheduled away from has exited, * then it needs to be killed here. The reason is that, even though * it will kill itself when it next runs, that may be too late. Its * stack will be freed, possibly before then, and if that happens, * we have a use-after-free situation. So, it gets killed here * in case it has not already killed itself. */ prev_sched = current->thread.prev_sched; if(prev_sched->thread.mode.tt.switch_pipe[0] == -1) os_kill_process(prev_sched->thread.mode.tt.extern_pid, 1); change_sig(SIGVTALRM, vtalrm); change_sig(SIGALRM, alrm); change_sig(SIGPROF, prof); arch_switch(); flush_tlb_all(); local_irq_restore(flags); }
void suspend_new_thread(int fd) { int err; char c; os_stop_process(os_getpid()); err = os_read_file(fd, &c, sizeof(c)); if(err != sizeof(c)) panic("read failed in suspend_new_thread, err = %d", -err); }
int net_read(int fd, void *buf, int len) { int n; n = os_read_file(fd, buf, len); if(n == -EAGAIN) return 0; else if(n == 0) return -ENOTCONN; return n; }
int generic_read(int fd, char *c_out, void *unused) { int n; n = os_read_file(fd, c_out, sizeof(*c_out)); if(n == -EAGAIN) return 0; else if(n == 0) return -EIO; return n; }
int net_read(int fd, void *buf, int len) { int n; n = os_read_file(fd, buf, len); if(n == -EAGAIN) return(0); else if(n == 0) return(-ENOTCONN); return(n); }
/* Do reliable error handling as this fails frequently enough. */ void read_output(int fd, char *output, int len) { int remain, ret, expected; char c; char *str; if(output == NULL){ output = &c; len = sizeof(c); } *output = '\0'; ret = os_read_file(fd, &remain, sizeof(remain)); if (ret != sizeof(remain)) { expected = sizeof(remain); str = "length"; goto err; } while(remain != 0){ expected = (remain < len) ? remain : len; ret = os_read_file(fd, output, expected); if (ret != expected) { str = "data"; goto err; } remain -= ret; } return; err: if (ret < 0) printk("read_output - read of %s failed, errno = %d\n", str, -ret); else printk("read_output - read of %s failed, read only %d of %d bytes\n", str, ret, expected); }
static irqreturn_t test_interrupt(int irq, void *data) { char buff[1024]; printk("Test Interrupt occurred!!!\n"); memset(buff, 0, 1024); os_read_file(fd, buff, 1023); printk("Test: read %s\n", buff); reactivate_fd(fd, MAPPER_IRQ); return IRQ_HANDLED; }
static int etap_tramp(char *dev, char *gate, int control_me, int control_remote, int data_me, int data_remote) { struct etap_pre_exec_data pe_data; int pid, status, err, n; char version_buf[sizeof("nnnnn\0")]; char data_fd_buf[sizeof("nnnnnn\0")]; char gate_buf[sizeof("nnn.nnn.nnn.nnn\0")]; char *setup_args[] = { "uml_net", version_buf, "ethertap", dev, data_fd_buf, gate_buf, NULL }; char *nosetup_args[] = { "uml_net", version_buf, "ethertap", dev, data_fd_buf, NULL }; char **args, c; sprintf(data_fd_buf, "%d", data_remote); sprintf(version_buf, "%d", UML_NET_VERSION); if(gate != NULL){ strcpy(gate_buf, gate); args = setup_args; } else args = nosetup_args; err = 0; pe_data.control_remote = control_remote; pe_data.control_me = control_me; pe_data.data_me = data_me; pid = run_helper(etap_pre_exec, &pe_data, args, NULL); if(pid < 0) err = pid; os_close_file(data_remote); os_close_file(control_remote); n = os_read_file(control_me, &c, sizeof(c)); if(n != sizeof(c)){ printk("etap_tramp : read of status failed, err = %d\n", -n); return(-EINVAL); } if(c != 1){ printk("etap_tramp : uml_net failed\n"); err = -EINVAL; CATCH_EINTR(n = waitpid(pid, &status, 0)); if(n < 0) err = -errno; else if(!WIFEXITED(status) || (WEXITSTATUS(status) != 1)) printk("uml_net didn't exit with status 1\n"); } return(err); }
int os_read_file_line(file_desc_t file, void *buff, int len) { int nLen = 0; char *p = (char*)buff; while (nLen < len) { if (1 == os_read_file(file, p, 1)) { nLen ++; if ((*p) == '\n') return nLen; } else return -1; p ++; } return nLen; }
static ssize_t rng_dev_read (struct file *filp, char __user *buf, size_t size, loff_t *offp) { u32 data; int n, ret = 0, have_data; while (size) { n = os_read_file(random_fd, &data, sizeof(data)); if (n > 0) { have_data = n; while (have_data && size) { if (put_user((u8) data, buf++)) { ret = ret ? : -EFAULT; break; } size--; ret++; have_data--; data >>= 8; } }
static int load_initrd(char *filename, void *buf, int size) { int fd, n; fd = os_open_file(filename, of_read(OPENFLAGS()), 0); if (fd < 0) { printk(KERN_ERR "Opening '%s' failed - err = %d\n", filename, -fd); return -1; } n = os_read_file(fd, buf, size); if (n != size) { printk(KERN_ERR "Read of %d bytes from '%s' failed, " "err = %d\n", size, filename, -n); return -1; } os_close_file(fd); return 0; }
int not_dead_yet(char *dir) { char file[strlen(uml_dir) + UMID_LEN + sizeof("/pid\0")]; char pid[sizeof("nnnnn\0")], *end; int dead, fd, p, n; sprintf(file, "%s/pid", dir); dead = 0; fd = os_open_file(file, of_read(OPENFLAGS()), 0); if(fd < 0){ if(fd != -ENOENT){ printk("not_dead_yet : couldn't open pid file '%s', " "err = %d\n", file, -fd); return(1); } dead = 1; } if(fd > 0){ n = os_read_file(fd, pid, sizeof(pid)); if(n < 0){ printk("not_dead_yet : couldn't read pid file '%s', " "err = %d\n", file, -n); return(1); } p = strtoul(pid, &end, 0); if(end == pid){ printk("not_dead_yet : couldn't parse pid file '%s', " "errno = %d\n", file, errno); dead = 1; } if(((kill(p, 0) < 0) && (errno == ESRCH)) || (p == CHOOSE_MODE(tracing_pid, os_getpid()))) dead = 1; } if(!dead) return(1); return(actually_do_remove(dir)); }
static ssize_t hppfs_read_file(int fd, char *buf, ssize_t count) { ssize_t n; int cur, err; char *new_buf; n = -ENOMEM; new_buf = kmalloc(PAGE_SIZE, GFP_KERNEL); if(new_buf == NULL){ printk("hppfs_read_file : kmalloc failed\n"); goto out; } n = 0; while(count > 0){ cur = min_t(ssize_t, count, PAGE_SIZE); err = os_read_file(fd, new_buf, cur); if(err < 0){ printk("hppfs_read : read failed, err = %d\n", -err); n = err; goto out_free; } else if(err == 0) break; if(copy_to_user(buf, new_buf, err)){ n = -EFAULT; goto out_free; } n += err; count -= err; } out_free: kfree(new_buf); out: return(n); }
static int connect_to_switch(struct daemon_data *pri) { struct sockaddr_un *ctl_addr = pri->ctl_addr; struct sockaddr_un *local_addr = pri->local_addr; struct sockaddr_un *sun; struct request_v3 req; int fd, n, err; pri->control = socket(AF_UNIX, SOCK_STREAM, 0); if(pri->control < 0){ printk("daemon_open : control socket failed, errno = %d\n", errno); return(-errno); } if(connect(pri->control, (struct sockaddr *) ctl_addr, sizeof(*ctl_addr)) < 0){ printk("daemon_open : control connect failed, errno = %d\n", errno); err = -errno; goto out; } fd = socket(AF_UNIX, SOCK_DGRAM, 0); if(fd < 0){ printk("daemon_open : data socket failed, errno = %d\n", errno); err = -errno; goto out; } if(bind(fd, (struct sockaddr *) local_addr, sizeof(*local_addr)) < 0){ printk("daemon_open : data bind failed, errno = %d\n", errno); err = -errno; goto out_close; } sun = um_kmalloc(sizeof(struct sockaddr_un)); if(sun == NULL){ printk("new_addr: allocation of sockaddr_un failed\n"); err = -ENOMEM; goto out_close; } req.magic = SWITCH_MAGIC; req.version = SWITCH_VERSION; req.type = REQ_NEW_CONTROL; req.sock = *local_addr; n = os_write_file(pri->control, &req, sizeof(req)); if(n != sizeof(req)){ printk("daemon_open : control setup request failed, err = %d\n", -n); err = -ENOTCONN; goto out_free; } n = os_read_file(pri->control, sun, sizeof(*sun)); if(n != sizeof(*sun)){ printk("daemon_open : read of data socket failed, err = %d\n", -n); err = -ENOTCONN; goto out_free; } pri->data_addr = sun; return(fd); out_free: kfree(sun); out_close: os_close_file(fd); out: os_close_file(pri->control); return(err); }
void switch_to_tt(void *prev, void *next) { struct task_struct *from, *to, *prev_sched; unsigned long flags; int err, vtalrm, alrm, prof, cpu; char c; from = prev; to = next; cpu = task_thread_info(from)->cpu; if(cpu == 0) forward_interrupts(to->thread.mode.tt.extern_pid); #ifdef CONFIG_SMP forward_ipi(cpu_data[cpu].ipi_pipe[0], to->thread.mode.tt.extern_pid); #endif local_irq_save(flags); vtalrm = change_sig(SIGVTALRM, 0); alrm = change_sig(SIGALRM, 0); prof = change_sig(SIGPROF, 0); forward_pending_sigio(to->thread.mode.tt.extern_pid); c = 0; /* Notice that here we "up" the semaphore on which "to" is waiting, and * below (the read) we wait on this semaphore (which is implemented by * switch_pipe) and go sleeping. Thus, after that, we have resumed in * "to", and can't use any more the value of "from" (which is outdated), * nor the value in "to" (since it was the task which stole us the CPU, * which we don't care about). */ err = os_write_file(to->thread.mode.tt.switch_pipe[1], &c, sizeof(c)); if(err != sizeof(c)) panic("write of switch_pipe failed, err = %d", -err); if(from->thread.mode.tt.switch_pipe[0] == -1) os_kill_process(os_getpid(), 0); err = os_read_file(from->thread.mode.tt.switch_pipe[0], &c, sizeof(c)); if(err != sizeof(c)) panic("read of switch_pipe failed, errno = %d", -err); /* If the process that we have just scheduled away from has exited, * then it needs to be killed here. The reason is that, even though * it will kill itself when it next runs, that may be too late. Its * stack will be freed, possibly before then, and if that happens, * we have a use-after-free situation. So, it gets killed here * in case it has not already killed itself. */ prev_sched = current->thread.prev_sched; if(prev_sched->thread.mode.tt.switch_pipe[0] == -1) os_kill_process(prev_sched->thread.mode.tt.extern_pid, 1); change_sig(SIGVTALRM, vtalrm); change_sig(SIGALRM, alrm); change_sig(SIGPROF, prof); arch_switch_to_tt(prev_sched, current); flush_tlb_all(); local_irq_restore(flags); }
void *switch_to_tt(void *prev, void *next, void *last) { struct task_struct *from, *to, *prev_sched; unsigned long flags; int err, vtalrm, alrm, prof, cpu; char c; /* jailing and SMP are incompatible, so this doesn't need to be * made per-cpu */ static int reading; from = prev; to = next; to->thread.prev_sched = from; cpu = from->thread_info->cpu; if(cpu == 0) forward_interrupts(to->thread.mode.tt.extern_pid); #ifdef CONFIG_SMP forward_ipi(cpu_data[cpu].ipi_pipe[0], to->thread.mode.tt.extern_pid); #endif local_irq_save(flags); vtalrm = change_sig(SIGVTALRM, 0); alrm = change_sig(SIGALRM, 0); prof = change_sig(SIGPROF, 0); forward_pending_sigio(to->thread.mode.tt.extern_pid); c = 0; set_current(to); reading = 0; err = os_write_file(to->thread.mode.tt.switch_pipe[1], &c, sizeof(c)); if(err != sizeof(c)) panic("write of switch_pipe failed, err = %d", -err); reading = 1; if((from->exit_state == EXIT_ZOMBIE) || (from->exit_state == EXIT_DEAD)) os_kill_process(os_getpid(), 0); err = os_read_file(from->thread.mode.tt.switch_pipe[0], &c, sizeof(c)); if(err != sizeof(c)) panic("read of switch_pipe failed, errno = %d", -err); /* If the process that we have just scheduled away from has exited, * then it needs to be killed here. The reason is that, even though * it will kill itself when it next runs, that may be too late. Its * stack will be freed, possibly before then, and if that happens, * we have a use-after-free situation. So, it gets killed here * in case it has not already killed itself. */ prev_sched = current->thread.prev_sched; if((prev_sched->exit_state == EXIT_ZOMBIE) || (prev_sched->exit_state == EXIT_DEAD)) os_kill_ptraced_process(prev_sched->thread.mode.tt.extern_pid, 1); /* This works around a nasty race with 'jail'. If we are switching * between two threads of a threaded app and the incoming process * runs before the outgoing process reaches the read, and it makes * it all the way out to userspace, then it will have write-protected * the outgoing process stack. Then, when the outgoing process * returns from the write, it will segfault because it can no longer * write its own stack. So, in order to avoid that, the incoming * thread sits in a loop yielding until 'reading' is set. This * isn't entirely safe, since there may be a reschedule from a timer * happening between setting 'reading' and sleeping in read. But, * it should get a whole quantum in which to reach the read and sleep, * which should be enough. */ if(jail){ while(!reading) sched_yield(); } change_sig(SIGVTALRM, vtalrm); change_sig(SIGALRM, alrm); change_sig(SIGPROF, prof); arch_switch(); flush_tlb_all(); local_irq_restore(flags); return(current->thread.prev_sched); }
int run_helper(void (*pre_exec)(void *), void *pre_data, char **argv, unsigned long *stack_out) { struct helper_data data; unsigned long stack, sp; int pid, fds[2], err, n; if((stack_out != NULL) && (*stack_out != 0)) stack = *stack_out; else stack = alloc_stack(0, um_in_interrupt()); if(stack == 0) return(-ENOMEM); err = os_pipe(fds, 1, 0); if(err < 0){ printk("run_helper : pipe failed, err = %d\n", -err); goto out_free; } err = os_set_exec_close(fds[1], 1); if(err < 0){ printk("run_helper : setting FD_CLOEXEC failed, err = %d\n", -err); goto out_close; } sp = stack + page_size() - sizeof(void *); data.pre_exec = pre_exec; data.pre_data = pre_data; data.argv = argv; data.fd = fds[1]; pid = clone(helper_child, (void *) sp, CLONE_VM | SIGCHLD, &data); if(pid < 0){ printk("run_helper : clone failed, errno = %d\n", errno); err = -errno; goto out_close; } os_close_file(fds[1]); n = os_read_file(fds[0], &err, sizeof(err)); if(n < 0){ printk("run_helper : read on pipe failed, err = %d\n", -n); err = n; goto out_kill; } else if(n != 0){ CATCH_EINTR(n = waitpid(pid, NULL, 0)); pid = -errno; } if(stack_out == NULL) free_stack(stack, 0); else *stack_out = stack; return(pid); out_kill: os_kill_process(pid, 1); out_close: os_close_file(fds[0]); os_close_file(fds[1]); out_free: free_stack(stack, 0); return(err); }
int start_watchdog(int *in_fd_ret, int *out_fd_ret, char *sock) { struct dog_data data; int in_fds[2], out_fds[2], pid, n, err; char pid_buf[sizeof("nnnnn\0")], c; char *pid_args[] = { "/usr/bin/uml_watchdog", "-pid", pid_buf, NULL }; char *mconsole_args[] = { "/usr/bin/uml_watchdog", "-mconsole", NULL, NULL }; char **args = NULL; err = os_pipe(in_fds, 1, 0); if(err < 0){ printk("harddog_open - os_pipe failed, err = %d\n", -err); goto out; } err = os_pipe(out_fds, 1, 0); if(err < 0){ printk("harddog_open - os_pipe failed, err = %d\n", -err); goto out_close_in; } data.stdin = out_fds[0]; data.stdout = in_fds[1]; data.close_me[0] = out_fds[1]; data.close_me[1] = in_fds[0]; if(sock != NULL){ mconsole_args[2] = sock; args = mconsole_args; } else { /* XXX The os_getpid() is not SMP correct */ sprintf(pid_buf, "%d", CHOOSE_MODE(tracing_pid, os_getpid())); args = pid_args; } pid = run_helper(pre_exec, &data, args, NULL); os_close_file(out_fds[0]); os_close_file(in_fds[1]); if(pid < 0){ err = -pid; printk("harddog_open - run_helper failed, errno = %d\n", -err); goto out_close_out; } n = os_read_file(in_fds[0], &c, sizeof(c)); if(n == 0){ printk("harddog_open - EOF on watchdog pipe\n"); helper_wait(pid); err = -EIO; goto out_close_out; } else if(n < 0){ printk("harddog_open - read of watchdog pipe failed, " "err = %d\n", -n); helper_wait(pid); err = n; goto out_close_out; } *in_fd_ret = in_fds[0]; *out_fd_ret = out_fds[1]; return 0; out_close_in: os_close_file(in_fds[0]); os_close_file(in_fds[1]); out_close_out: os_close_file(out_fds[0]); os_close_file(out_fds[1]); out: return err; }