asmlinkage int sunos_mount(char *type, char *dir, int flags, void *data) { int linux_flags = MS_MGC_MSK; /* new semantics */ int error; char *dev_fname = 0; /* We don't handle the integer fs type */ if ((flags & SMNT_NEWTYPE) == 0) return -EINVAL; /* Do not allow for those flags we don't support */ if (flags & (SMNT_GRPID|SMNT_NOSUB|SMNT_MULTI|SMNT_SYS5)) return -EINVAL; if(flags & SMNT_REMOUNT) linux_flags |= MS_REMOUNT; if(flags & SMNT_RDONLY) linux_flags |= MS_RDONLY; if(flags & SMNT_NOSUID) linux_flags |= MS_NOSUID; error = verify_area(VERIFY_READ, type, 16); if(error) return error; if(strcmp(type, "ext2") == 0) { dev_fname = (char *) data; } else if(strcmp(type, "iso9660") == 0) { dev_fname = (char *) data; } else if(strcmp(type, "minix") == 0) { dev_fname = (char *) data; } else if(strcmp(type, "ext") == 0) { dev_fname = (char *) data; } else if(strcmp(type, "xiafs") == 0) { dev_fname = (char *) data; } else if(strcmp(type, "nfs") == 0) { error = sunos_nfs_mount (dir, flags, data); return error; } else if(strcmp(type, "ufs") == 0) { printk("Warning: UFS filesystem mounts unsupported.\n"); return -ENODEV; } else if(strcmp(type, "proc")) { return -ENODEV; } if(error) return error; error = sys_mount(dev_fname, dir, type, linux_flags, NULL); return error; }
/* a basic put() operation. Note the avoidance of odd word boundaries and transfers sizes beyond what the hardware can deal with */ static inline int aplib_put(struct aplib_putget *put) { int error; struct aplib_struct *aplib = current->aplib; error = verify_area(VERIFY_WRITE,put,sizeof(*put)); if (error) return error; if (put->cid >= aplib->numcells) return -EINVAL; do { int n; if (put->size && (((unsigned)put->src_addr) & 4)) { n = 1; } else if (put->size > MAX_PUT_SIZE) { n = MAX_PUT_SIZE; } else { n = put->size; } put->size -= n; page_in((char *)put->src_addr,n<<2); _putget(MSC_PUT_QUEUE, aplib->rel_cid[put->cid], put->src_addr, n, put->dest_addr, put->size?0:put->dest_flag, put->size?0:put->src_flag); put->dest_addr += n; put->src_addr += n; } while (put->size); if (put->ack) { aplib->ack_request++; _putget(MSC_GET_QUEUE, aplib->rel_cid[put->cid], 0, 0, 0, &aplib->ack_flag, 0); } return 0; }
/* * bind a name to a socket. this is where much of the work is done. we * allocate a fresh page for the buffer, grab the appropriate inode and * set things up. * * XXX what should we do if an address is already bound? here we return * EINVAL, but it may be necessary to re-bind. i think thats what bsd does * in the case of datagram sockets */ static int unix_proto_bind(struct socket *sock, struct sockaddr *umyaddr, int sockaddr_len) { struct unix_proto_data *upd = UN_DATA(sock); char fname[sizeof(((struct sockaddr_un *)0)->sun_path) + 1]; int i; unsigned long old_fs; PRINTK("unix_proto_bind: socket 0x%x, len=%d\n", sock, sockaddr_len); if (sockaddr_len <= UN_PATH_OFFSET || sockaddr_len >= sizeof(struct sockaddr_un)) { PRINTK("unix_proto_bind: bad length %d\n", sockaddr_len); return -EINVAL; } if (upd->sockaddr_len || upd->inode) { printk("unix_proto_bind: already bound!\n"); return -EINVAL; } verify_area(umyaddr, sockaddr_len); memcpy_fromfs(&upd->sockaddr_un, umyaddr, sockaddr_len); if (upd->sockaddr_un.sun_family != AF_UNIX) { PRINTK("unix_proto_bind: family is %d, not AF_UNIX (%d)\n", upd->sockaddr_un.sun_family, AF_UNIX); return -EINVAL; } memcpy(fname, upd->sockaddr_un.sun_path, sockaddr_len-UN_PATH_OFFSET); fname[sockaddr_len-UN_PATH_OFFSET] = '\0'; old_fs = get_fs(); set_fs(get_ds()); i = do_mknod(fname, S_IFSOCK | 0777, 0); if (i == 0) i = open_namei(fname, 0, S_IFSOCK, &upd->inode, NULL); set_fs(old_fs); if (i < 0) { printk("unix_proto_bind: can't open socket %s\n", fname); return i; } upd->sockaddr_len = sockaddr_len; /* now its legal */ PRINTK("unix_proto_bind: bound socket address: "); #ifdef SOCK_DEBUG sockaddr_un_printk(&upd->sockaddr_un, upd->sockaddr_len); #endif return 0; }
// 获取系统名称等信息。其中utsname结构包含5个字段,分别是:当前运行系统的名称, // 网络节点名称(主机名)、当前操作系统发行级别、操作系统版本号以及系统运行的 // 硬件类型名称,该结构在include/sys/utsname.h中定义。 int sys_uname(struct utsname * name) { static struct utsname thisname = { // 这里给出了结构中的信息,这种编码肯定会改变。 "linux .0","nodename","release ","version ","machine " }; int i; // 首先判断参数的有效性。如果存放信息的缓冲区指针为空,则出错返回。在验证缓 // 冲区大小是否超限(若超出内核自动扩展)。然后将utsname中的信息逐字节复制到 // 用户缓冲区中。 if (!name) return -ERROR; verify_area(name,sizeof *name); for(i=0;i<sizeof *name;i++) put_fs_byte(((char *) &thisname)[i],i+(char *) name); return 0; }
/* * Due to some executables calling the wrong select we sometimes * get wrong args. This determines how the args are being passed * (a single ptr to them all args passed) then calls * sys_select() with the appropriate args. -- Cort */ int ppc_select(int n, fd_set *inp, fd_set *outp, fd_set *exp, struct timeval *tvp) { if ( (unsigned long)n >= 4096 ) { unsigned long *buffer = (unsigned long *)n; if (verify_area(VERIFY_READ, buffer, 5*sizeof(unsigned long)) || __get_user(n, buffer) || __get_user(inp, ((fd_set **)(buffer+1))) || __get_user(outp, ((fd_set **)(buffer+2))) || __get_user(exp, ((fd_set **)(buffer+3))) || __get_user(tvp, ((struct timeval **)(buffer+4)))) return -EFAULT; } return sys_select(n, inp, outp, exp, tvp); }
int sigreturn_common(struct pt_regs *regs,int framesize) { sigframe *frame = (sigframe *)regs->gprs[15]; sigset_t set; if (verify_area(VERIFY_READ, frame, sizeof(*frame))) return -1; if (restore_sigcontext(&frame->sc,regs,&frame->sregs,&set)) return -1; sigdelsetmask(&set, ~_BLOCKABLE); spin_lock_irq(¤t->sigmask_lock); current->blocked = set; recalc_sigpending(current); spin_unlock_irq(¤t->sigmask_lock); return 0; }
static ssize_t read_nvram(struct file *file, char *buf, size_t count, loff_t *ppos) { unsigned int i; char *p = buf; if (verify_area(VERIFY_WRITE, buf, count)) return -EFAULT; if (*ppos >= NVRAM_SIZE) return 0; for (i = *ppos; count > 0 && i < NVRAM_SIZE; ++i, ++p, --count) if (__put_user(nvram_read_byte(i), p)) return -EFAULT; *ppos = i; return p - buf; }
asmlinkage int sys_rt_sigreturn(struct pt_regs *regs) { struct rt_sigframe __user *frame; sigset_t set; /* Always make any pending restarted system calls return -EINTR */ current_thread_info()->restart_block.fn = do_no_restart_syscall; /* * Since we stacked the signal on a 64-bit boundary, * then 'sp' should be word aligned here. If it's * not, then the user is trying to mess with us. */ if (regs->ARM_sp & 7) goto badframe; frame = (struct rt_sigframe __user *)regs->ARM_sp; if (verify_area(VERIFY_READ, frame, sizeof (*frame))) goto badframe; if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set))) goto badframe; sigdelsetmask(&set, ~_BLOCKABLE); spin_lock_irq(¤t->sighand->siglock); current->blocked = set; recalc_sigpending(); spin_unlock_irq(¤t->sighand->siglock); if (restore_sigcontext(regs, &frame->uc.uc_mcontext)) goto badframe; if (do_sigaltstack(&frame->uc.uc_stack, NULL, regs->ARM_sp) == -EFAULT) goto badframe; /* Send SIGTRAP if we're single-stepping */ if (current->ptrace & PT_SINGLESTEP) { ptrace_cancel_bpt(current); send_sig(SIGTRAP, current, 1); } return regs->ARM_r0; badframe: force_sig(SIGSEGV, current); return 0; }
asmlinkage long osf_proplist_syscall (enum pl_code code, union pl_args *args) { long error; int *min_buf_size_ptr; switch (code) { case PL_SET: error = verify_area(VERIFY_READ, &args->set.nbytes, sizeof(args->set.nbytes)); if (error) return error; return args->set.nbytes; case PL_FSET: error = verify_area(VERIFY_READ, &args->fset.nbytes, sizeof(args->fset.nbytes)); if (error) return error; return args->fset.nbytes; case PL_GET: error = verify_area(VERIFY_READ, &args->get.min_buf_size, sizeof(args->get.min_buf_size)); if (error) return error; min_buf_size_ptr = get_user(&args->get.min_buf_size); error = verify_area(VERIFY_WRITE, min_buf_size_ptr, sizeof(*min_buf_size_ptr)); if (error) return error; put_user(0, min_buf_size_ptr); return 0; case PL_FGET: error = verify_area(VERIFY_READ, &args->fget.min_buf_size, sizeof(args->fget.min_buf_size)); if (error) return error; min_buf_size_ptr = get_user(&args->fget.min_buf_size); error = verify_area(VERIFY_WRITE, min_buf_size_ptr, sizeof(*min_buf_size_ptr)); if (error) return error; put_user(0, min_buf_size_ptr); return 0; case PL_DEL: case PL_FDEL: return 0; default: return -EOPNOTSUPP; } }
/* This will check if all events are logged, if they are then, we * know that we can safely clear the events in NVRAM. * Next we'll sit and wait for something else to log. */ static ssize_t rtas_log_read(struct file * file, char * buf, size_t count, loff_t *ppos) { int error; char *tmp; unsigned long s; unsigned long offset; if (!buf || count < rtas_error_log_buffer_max) return -EINVAL; count = rtas_error_log_buffer_max; error = verify_area(VERIFY_WRITE, buf, count); if (error) return -EFAULT; tmp = kmalloc(count, GFP_KERNEL); if (!tmp) return -ENOMEM; spin_lock_irqsave(&log_lock, s); /* if it's 0, then we know we got the last one (the one in NVRAM) */ if (rtas_log_size == 0 && !no_more_logging) nvram_clear_error_log(); spin_unlock_irqrestore(&log_lock, s); error = wait_event_interruptible(rtas_log_wait, rtas_log_size); if (error) goto out; spin_lock_irqsave(&log_lock, s); offset = rtas_error_log_buffer_max * (rtas_log_start & LOG_NUMBER_MASK); memcpy(tmp, &rtas_log_buf[offset], count); rtas_log_start += 1; rtas_log_size -= 1; spin_unlock_irqrestore(&log_lock, s); error = copy_to_user(buf, tmp, count) ? -EFAULT : count; out: kfree(tmp); return error; }
void do_signal(long signr, /* system_call()提供 */ long eax, long ebx, long ecx, long edx, long fs, long es, long ds, /* 中断自动进栈 */ long eip, long cs, long eflags, unsigned long * esp, long ss) { unsigned long sa_handler; long old_eip=eip; struct sigaction * sa = current->sigaction + signr - 1; int longs; unsigned long * tmp_esp; sa_handler = (unsigned long) sa->sa_handler; // 信号回调函数 if (sa_handler==1) // 忽略此信号 return; // 默认处理 if (!sa_handler) { if (signr==SIGCHLD) return; else do_exit(1<<(signr-1)); } // 如果只处理一次(signal) if (sa->sa_flags & SA_ONESHOT) sa->sa_handler = NULL; *(&eip) = sa_handler; // 修改堆栈中的eip longs = (sa->sa_flags & SA_NOMASK)?7:8; *(&esp) -= longs; verify_area(esp,longs*4); // 修改用户堆栈的数据 tmp_esp=esp; put_fs_long((long) sa->sa_restorer,tmp_esp++); put_fs_long(signr,tmp_esp++); if (!(sa->sa_flags & SA_NOMASK)) put_fs_long(current->blocked,tmp_esp++); put_fs_long(eax,tmp_esp++); put_fs_long(ecx,tmp_esp++); put_fs_long(edx,tmp_esp++); put_fs_long(eflags,tmp_esp++); put_fs_long(old_eip,tmp_esp++); // 这个是用户程序的中断点 current->blocked |= sa->sa_mask; }
int sys_readlink(const char * path, char * buf, int bufsiz) { struct inode * inode; int error; if (bufsiz <= 0) return -EINVAL; verify_area(buf,bufsiz); error = lnamei(path,&inode); if (error) return error; if (!inode->i_op || !inode->i_op->readlink) { iput(inode); return -EINVAL; } return inode->i_op->readlink(inode,buf,bufsiz); }
static int get_termio(struct tty_struct * tty, struct termio * termio) { int i; struct termio tmp_termio; verify_area(termio, sizeof (*termio)); tmp_termio.c_iflag = tty->termios->c_iflag; tmp_termio.c_oflag = tty->termios->c_oflag; tmp_termio.c_cflag = tty->termios->c_cflag; tmp_termio.c_lflag = tty->termios->c_lflag; tmp_termio.c_line = tty->termios->c_line; for(i=0 ; i < NCC ; i++) tmp_termio.c_cc[i] = tty->termios->c_cc[i]; for (i=0 ; i< (sizeof (*termio)) ; i++) put_fs_byte( ((char *)&tmp_termio)[i] , i+(char *)termio ); return 0; }
/* 读取目录文件的一个目录 */ asmlinkage int sys_readdir(unsigned int fd, struct dirent * dirent, unsigned int count) { int error; struct file * file; struct inode * inode; if (fd >= NR_OPEN || !(file = current->filp[fd]) || !(inode = file->f_inode)) return -EBADF; error = -ENOTDIR; if (file->f_op && file->f_op->readdir) { error = verify_area(VERIFY_WRITE, dirent, sizeof (*dirent)); if (!error) error = file->f_op->readdir(inode,file,dirent,count); } return error; }
static int ioctl_probe(struct Scsi_Host * host, void *buffer) { int temp; unsigned int len,slen; const char * string; if ((temp = host->hostt->present) && buffer) { len = get_fs_long ((unsigned long *) buffer); string = host->hostt->info(); slen = strlen(string); if (len > slen) len = slen + 1; verify_area(VERIFY_WRITE, buffer, len); memcpy_tofs (buffer, string, len); } return temp; }
static int sock_socketpair(int family, int type, int protocol, unsigned long usockvec[2]) { int fd1, fd2, i; struct socket *sock1, *sock2; int er; DPRINTF((net_debug, "NET: sock_socketpair: family = %d, type = %d, protocol = %d\n", family, type, protocol)); /* * Obtain the first socket and check if the underlying protocol * supports the socketpair call. */ if ((fd1 = sock_socket(family, type, protocol)) < 0) return(fd1); sock1 = sockfd_lookup(fd1, NULL); if (!sock1->ops->socketpair) { sys_close(fd1); return(-EINVAL); } /* Now grab another socket and try to connect the two together. */ if ((fd2 = sock_socket(family, type, protocol)) < 0) { sys_close(fd1); return(-EINVAL); } sock2 = sockfd_lookup(fd2, NULL); if ((i = sock1->ops->socketpair(sock1, sock2)) < 0) { sys_close(fd1); sys_close(fd2); return(i); } sock1->conn = sock2; sock2->conn = sock1; sock1->state = SS_CONNECTED; sock2->state = SS_CONNECTED; er=verify_area(VERIFY_WRITE, usockvec, 2 * sizeof(int)); if(er) return er; put_fs_long(fd1, &usockvec[0]); put_fs_long(fd2, &usockvec[1]); return(0); }
static ssize_t read_port(struct file * file, char * buf, size_t count, loff_t *ppos) { unsigned long i = *ppos; char *tmp = buf; if (verify_area(VERIFY_WRITE,buf,count)) return -EFAULT; while (count-- > 0 && i < 65536) { if (__put_user(inb(i),tmp) < 0) return -EFAULT; i++; tmp++; } *ppos = i; return tmp-buf; }
static int ioctl_probe(int dev, void *buffer) { int temp; unsigned int len,slen; const char * string; if ((temp = scsi_hosts[dev].present) && buffer) { len = get_fs_long ((int *) buffer); string = scsi_hosts[dev].info(); slen = strlen(string); if (len > slen) len = slen + 1; verify_area(VERIFY_WRITE, buffer, len); memcpy_tofs (buffer, string, len); } return temp; }
/* Read */ static ssize_t tun_chr_read(struct file * file, char * buf, size_t count, loff_t *pos) { struct tun_struct *tun = (struct tun_struct *)file->private_data; DECLARE_WAITQUEUE(wait, current); struct sk_buff *skb; ssize_t ret = 0; DBG(KERN_INFO "%s: tun_chr_read\n", tun->name); add_wait_queue(&tun->read_wait, &wait); while (count) { current->state = TASK_INTERRUPTIBLE; /* Read frames from device queue */ if (!(skb=skb_dequeue(&tun->txq))) { if (file->f_flags & O_NONBLOCK) { ret = -EAGAIN; break; } if (signal_pending(current)) { ret = -ERESTARTSYS; break; } /* Nothing to read, let's sleep */ schedule(); continue; } netif_start_queue(&tun->dev); if (!verify_area(VERIFY_WRITE, buf, count)) ret = tun_put_user(tun, skb, buf, count); else ret = -EFAULT; kfree_skb(skb); break; } current->state = TASK_RUNNING; remove_wait_queue(&tun->read_wait, &wait); return ret; }
static int sock_socketpair(int family, int type, int protocol, int usockvec[2]) { int fd1, fd2, i; struct socket *sock1, *sock2; PRINTK("sys_socketpair: family = %d, type = %d, protocol = %d\n", family, type, protocol); /* * obtain the first socket and check if the underlying protocol * supports the socketpair call */ if ((fd1 = sock_socket(family, type, protocol)) < 0) return fd1; sock1 = sockfd_lookup(fd1, NULL); if (!sock1->ops->socketpair) { sys_close(fd1); return -EINVAL; } /* * now grab another socket and try to connect the two together */ if ((fd2 = sock_socket(family, type, protocol)) < 0) { sys_close(fd1); return -EINVAL; } sock2 = sockfd_lookup(fd2, NULL); if ((i = sock1->ops->socketpair(sock1, sock2)) < 0) { sys_close(fd1); sys_close(fd2); return i; } sock1->conn = sock2; sock2->conn = sock1; sock1->state = SS_CONNECTED; sock2->state = SS_CONNECTED; verify_area(usockvec, 2 * sizeof(int)); put_fs_long(fd1, &usockvec[0]); put_fs_long(fd2, &usockvec[1]); return 0; }
/* the scsi_ioctl() function differs from most ioctls in that it does not take a major/minor number as the dev filed. Rather, it takes a pointer to a scsi_devices[] element, a structure. */ int scsi_ioctl (Scsi_Device *dev, int cmd, void *arg) { char scsi_cmd[10]; if ((cmd != 0 && dev->index > NR_SCSI_DEVICES)) return -ENODEV; if ((cmd == 0 && dev->host_no > max_scsi_hosts)) return -ENODEV; switch (cmd) { case SCSI_IOCTL_GET_IDLUN: verify_area(VERIFY_WRITE, (void *) arg, sizeof(int)); put_fs_long(dev->id + (dev->lun << 8) + (dev->host_no << 16), (long *) arg); return 0; case SCSI_IOCTL_PROBE_HOST: return ioctl_probe(dev->host_no, arg); case SCSI_IOCTL_SEND_COMMAND: return ioctl_command((Scsi_Device *) dev, arg); case SCSI_IOCTL_DOORLOCK: if (!dev->removable || !dev->lockable) return 0; scsi_cmd[0] = ALLOW_MEDIUM_REMOVAL; scsi_cmd[1] = dev->lun << 5; scsi_cmd[2] = scsi_cmd[3] = scsi_cmd[5] = 0; scsi_cmd[4] = SCSI_REMOVAL_PREVENT; return ioctl_internal_command((Scsi_Device *) dev, scsi_cmd); break; case SCSI_IOCTL_DOORUNLOCK: if (!dev->removable || !dev->lockable) return 0; scsi_cmd[0] = ALLOW_MEDIUM_REMOVAL; scsi_cmd[1] = dev->lun << 5; scsi_cmd[2] = scsi_cmd[3] = scsi_cmd[5] = 0; scsi_cmd[4] = SCSI_REMOVAL_ALLOW; return ioctl_internal_command((Scsi_Device *) dev, scsi_cmd); case SCSI_IOCTL_TEST_UNIT_READY: scsi_cmd[0] = TEST_UNIT_READY; scsi_cmd[1] = dev->lun << 5; scsi_cmd[2] = scsi_cmd[3] = scsi_cmd[5] = 0; scsi_cmd[4] = 0; return ioctl_internal_command((Scsi_Device *) dev, scsi_cmd); break; default : return -EINVAL; } }
asmlinkage int sys_write(unsigned int fd,char * buf,unsigned int count) { int error; struct file * file; struct inode * inode; int written; if (fd>=NR_OPEN || !(file=current->files->fd[fd]) || !(inode=file->f_inode)) return -EBADF; if (!(file->f_mode & 2)) return -EBADF; if (!file->f_op || !file->f_op->write) return -EINVAL; if (!count) return 0; error = locks_verify_area(FLOCK_VERIFY_WRITE,inode,file,file->f_pos,count); if (error) return error; error = verify_area(VERIFY_READ,buf,count); if (error) return error; /* * If data has been written to the file, remove the setuid and * the setgid bits. We do it anyway otherwise there is an * extremely exploitable race - does your OS get it right |-> * * Set ATTR_FORCE so it will always be changed. */ if (!suser() && (inode->i_mode & (S_ISUID | S_ISGID))) { struct iattr newattrs; /* * Don't turn off setgid if no group execute. This special * case marks candidates for mandatory locking. */ newattrs.ia_mode = inode->i_mode & ~(S_ISUID | ((inode->i_mode & S_IXGRP) ? S_ISGID : 0)); newattrs.ia_valid = ATTR_CTIME | ATTR_MODE | ATTR_FORCE; notify_change(inode, &newattrs); } down(&inode->i_sem); written = file->f_op->write(inode,file,buf,count); up(&inode->i_sem); return written; }
int abi_utsname(unsigned long addr) { int error; struct svr4_utsname *it = (struct svr4_utsname *)addr; down_read(&uts_sem); error = verify_area(VERIFY_WRITE, it, sizeof (struct svr4_utsname)); if (!error) { set_utsfield(it->sysname, system_utsname.sysname, 0); set_utsfield(it->nodename, system_utsname.nodename, 0); set_utsfield(it->release, system_utsname.release, 0); set_utsfield(it->version, system_utsname.version, 0); set_utsfield(it->machine, system_utsname.machine, 0); } up_read(&uts_sem); return error; }
/* * Clear the bytes in the last page of data. */ static int coff_clear_memory(u_long addr, u_long size) { int err = 0; if ((size = (PAGE_SIZE - (addr & ~PAGE_MASK)) & ~PAGE_MASK) == 0) goto out; if ((err = verify_area(VERIFY_WRITE, (void *)addr, size)) < 0) goto out; while (size-- != 0) { __put_user(0, (char *)addr); addr++; } out: return (err); }
asmlinkage int old_select(unsigned long *buffer) { int n; fd_set *inp; fd_set *outp; fd_set *exp; struct timeval *tvp; n = verify_area(VERIFY_READ, buffer, 5*sizeof(unsigned long)); if (n) return n; n = get_user(buffer); inp = (fd_set *) get_user(buffer+1); outp = (fd_set *) get_user(buffer+2); exp = (fd_set *) get_user(buffer+3); tvp = (struct timeval *) get_user(buffer+4); return sys_select(n, inp, outp, exp, tvp); }
asmlinkage int sys_setgroups(int gidsetsize, gid_t *grouplist) { int i; if (!suser()) return -EPERM; if (gidsetsize > NGROUPS) return -EINVAL; i = verify_area(VERIFY_READ, grouplist, sizeof(gid_t) * gidsetsize); if (i) return i; for (i = 0; i < gidsetsize; i++, grouplist++) { current->groups[i] = get_user(grouplist); } if (i < NGROUPS) current->groups[i] = NOGROUP; return 0; }
static int osf_procfs_mount(char * dirname, struct procfs_args * args, int flags) { kdev_t dev; int retval; struct procfs_args tmp; retval = verify_area(VERIFY_READ, args, sizeof(*args)); if (retval) return retval; memcpy_fromfs(&tmp, args, sizeof(tmp)); dev = get_unnamed_dev(); if (!dev) return -ENODEV; retval = do_mount(dev, "", dirname, "proc", flags, NULL); if (retval) put_unnamed_dev(dev); return retval; }
int wyse_getdomainname(char *name, int len) { int error; char *p; down_read(&uts_sem); error = verify_area(VERIFY_WRITE, name, len); if (!error) { --len; for (p = system_utsname.domainname; *p && len; p++,len--) { __put_user(*p, name); name++; } __put_user('\0', name); } up_read(&uts_sem); return error; }
static int get_termio(struct tty_struct * tty, struct termio * termio) { int i; struct termio tmp_termio; i = verify_area(VERIFY_WRITE, termio, sizeof (struct termio)); if (i) return i; tmp_termio.c_iflag = tty->termios->c_iflag; tmp_termio.c_oflag = tty->termios->c_oflag; tmp_termio.c_cflag = tty->termios->c_cflag; tmp_termio.c_lflag = tty->termios->c_lflag; tmp_termio.c_line = tty->termios->c_line; for(i=0 ; i < NCC ; i++) tmp_termio.c_cc[i] = tty->termios->c_cc[i]; memcpy_tofs(termio, &tmp_termio, sizeof (struct termio)); return 0; }
static ssize_t proc_mpc_write(struct file *file, const char *buff, size_t nbytes, loff_t *ppos) { int incoming, error, retval; char *page, c; const char *tmp; if (nbytes < 0) return -EINVAL; if (nbytes == 0) return 0; if (nbytes > PAGE_SIZE) nbytes = PAGE_SIZE-1; error = verify_area(VERIFY_READ, buff, nbytes); if (error) return error; page = (char *)__get_free_page(GFP_KERNEL); if (page == NULL) return -ENOMEM; incoming = 0; tmp = buff; while(incoming < nbytes){ if (get_user(c, tmp++)) return -EFAULT; incoming++; if (c == '\0' || c == '\n') break; } retval = copy_from_user(page, buff, incoming); if (retval != 0) { printk("mpoa: proc_mpc_write: copy_from_user() failed\n"); return -EFAULT; } *ppos += incoming; page[incoming] = '\0'; retval = parse_qos(page, incoming); if (retval == 0) printk("mpoa: proc_mpc_write: could not parse '%s'\n", page); free_page((unsigned long)page); return nbytes; }