linux/arch/um/sys-i386/syscalls.c
<<
>>
Prefs
   1/* 
   2 * Copyright (C) 2000 - 2003 Jeff Dike (jdike@addtoit.com)
   3 * Licensed under the GPL
   4 */
   5
   6#include "linux/sched.h"
   7#include "linux/shm.h"
   8#include "linux/ipc.h"
   9#include "asm/mman.h"
  10#include "asm/uaccess.h"
  11#include "asm/unistd.h"
  12
  13/*
  14 * Perform the select(nd, in, out, ex, tv) and mmap() system
  15 * calls. Linux/i386 didn't use to be able to handle more than
  16 * 4 system call parameters, so these system calls used a memory
  17 * block for parameter passing..
  18 */
  19
  20struct mmap_arg_struct {
  21        unsigned long addr;
  22        unsigned long len;
  23        unsigned long prot;
  24        unsigned long flags;
  25        unsigned long fd;
  26        unsigned long offset;
  27};
  28
  29extern int old_mmap(unsigned long addr, unsigned long len,
  30                    unsigned long prot, unsigned long flags,
  31                    unsigned long fd, unsigned long offset);
  32
  33long old_mmap_i386(struct mmap_arg_struct __user *arg)
  34{
  35        struct mmap_arg_struct a;
  36        int err = -EFAULT;
  37
  38        if (copy_from_user(&a, arg, sizeof(a)))
  39                goto out;
  40
  41        err = old_mmap(a.addr, a.len, a.prot, a.flags, a.fd, a.offset);
  42 out:
  43        return err;
  44}
  45
  46struct sel_arg_struct {
  47        unsigned long n;
  48        fd_set __user *inp;
  49        fd_set __user *outp;
  50        fd_set __user *exp;
  51        struct timeval __user *tvp;
  52};
  53
  54long old_select(struct sel_arg_struct __user *arg)
  55{
  56        struct sel_arg_struct a;
  57
  58        if (copy_from_user(&a, arg, sizeof(a)))
  59                return -EFAULT;
  60        /* sys_select() does the appropriate kernel locking */
  61        return sys_select(a.n, a.inp, a.outp, a.exp, a.tvp);
  62}
  63
  64/*
  65 * The prototype on i386 is:
  66 *
  67 *     int clone(int flags, void * child_stack, int * parent_tidptr, struct user_desc * newtls, int * child_tidptr)
  68 *
  69 * and the "newtls" arg. on i386 is read by copy_thread directly from the
  70 * register saved on the stack.
  71 */
  72long sys_clone(unsigned long clone_flags, unsigned long newsp,
  73               int __user *parent_tid, void *newtls, int __user *child_tid)
  74{
  75        long ret;
  76
  77        if (!newsp)
  78                newsp = UPT_SP(&current->thread.regs.regs);
  79
  80        current->thread.forking = 1;
  81        ret = do_fork(clone_flags, newsp, &current->thread.regs, 0, parent_tid,
  82                      child_tid);
  83        current->thread.forking = 0;
  84        return ret;
  85}
  86
  87/*
  88 * sys_ipc() is the de-multiplexer for the SysV IPC calls..
  89 *
  90 * This is really horribly ugly.
  91 */
  92long sys_ipc (uint call, int first, int second,
  93             int third, void __user *ptr, long fifth)
  94{
  95        int version, ret;
  96
  97        version = call >> 16; /* hack for backward compatibility */
  98        call &= 0xffff;
  99
 100        switch (call) {
 101        case SEMOP:
 102                return sys_semtimedop(first, (struct sembuf __user *) ptr,
 103                                      second, NULL);
 104        case SEMTIMEDOP:
 105                return sys_semtimedop(first, (struct sembuf __user *) ptr,
 106                                      second,
 107                                      (const struct timespec __user *) fifth);
 108        case SEMGET:
 109                return sys_semget (first, second, third);
 110        case SEMCTL: {
 111                union semun fourth;
 112                if (!ptr)
 113                        return -EINVAL;
 114                if (get_user(fourth.__pad, (void __user * __user *) ptr))
 115                        return -EFAULT;
 116                return sys_semctl (first, second, third, fourth);
 117        }
 118
 119        case MSGSND:
 120                return sys_msgsnd (first, (struct msgbuf *) ptr,
 121                                   second, third);
 122        case MSGRCV:
 123                switch (version) {
 124                case 0: {
 125                        struct ipc_kludge tmp;
 126                        if (!ptr)
 127                                return -EINVAL;
 128
 129                        if (copy_from_user(&tmp,
 130                                           (struct ipc_kludge *) ptr,
 131                                           sizeof (tmp)))
 132                                return -EFAULT;
 133                        return sys_msgrcv (first, tmp.msgp, second,
 134                                           tmp.msgtyp, third);
 135                }
 136                default:
 137                        panic("msgrcv with version != 0");
 138                        return sys_msgrcv (first,
 139                                           (struct msgbuf *) ptr,
 140                                           second, fifth, third);
 141                }
 142        case MSGGET:
 143                return sys_msgget ((key_t) first, second);
 144        case MSGCTL:
 145                return sys_msgctl (first, second, (struct msqid_ds *) ptr);
 146
 147        case SHMAT:
 148                switch (version) {
 149                default: {
 150                        ulong raddr;
 151                        ret = do_shmat (first, (char *) ptr, second, &raddr);
 152                        if (ret)
 153                                return ret;
 154                        return put_user (raddr, (ulong *) third);
 155                }
 156                case 1: /* iBCS2 emulator entry point */
 157                        if (!segment_eq(get_fs(), get_ds()))
 158                                return -EINVAL;
 159                        return do_shmat (first, (char *) ptr, second, (ulong *) third);
 160                }
 161        case SHMDT:
 162                return sys_shmdt ((char *)ptr);
 163        case SHMGET:
 164                return sys_shmget (first, second, third);
 165        case SHMCTL:
 166                return sys_shmctl (first, second,
 167                                   (struct shmid_ds *) ptr);
 168        default:
 169                return -ENOSYS;
 170        }
 171}
 172
 173long sys_sigaction(int sig, const struct old_sigaction __user *act,
 174                         struct old_sigaction __user *oact)
 175{
 176        struct k_sigaction new_ka, old_ka;
 177        int ret;
 178
 179        if (act) {
 180                old_sigset_t mask;
 181                if (!access_ok(VERIFY_READ, act, sizeof(*act)) ||
 182                    __get_user(new_ka.sa.sa_handler, &act->sa_handler) ||
 183                    __get_user(new_ka.sa.sa_restorer, &act->sa_restorer))
 184                        return -EFAULT;
 185                __get_user(new_ka.sa.sa_flags, &act->sa_flags);
 186                __get_user(mask, &act->sa_mask);
 187                siginitset(&new_ka.sa.sa_mask, mask);
 188        }
 189
 190        ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL);
 191
 192        if (!ret && oact) {
 193                if (!access_ok(VERIFY_WRITE, oact, sizeof(*oact)) ||
 194                    __put_user(old_ka.sa.sa_handler, &oact->sa_handler) ||
 195                    __put_user(old_ka.sa.sa_restorer, &oact->sa_restorer))
 196                        return -EFAULT;
 197                __put_user(old_ka.sa.sa_flags, &oact->sa_flags);
 198                __put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask);
 199        }
 200
 201        return ret;
 202}
 203
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.