*/
-#include <linux/config.h>
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/fs.h>
#include <linux/resource.h>
#include <linux/times.h>
#include <linux/utsname.h>
-#include <linux/timex.h>
#include <linux/smp.h>
#include <linux/smp_lock.h>
#include <linux/sem.h>
#include <linux/syscalls.h>
#include <linux/sysctl.h>
#include <linux/binfmts.h>
+#include <linux/capability.h>
#include <linux/compat.h>
#include <linux/vfs.h>
#include <linux/ptrace.h>
+#include <linux/fadvise.h>
#include <asm/types.h>
#include <asm/ipc.h>
#define SET_STAT_UID(stat, uid) (stat).st_uid = high2lowuid(uid)
#define SET_STAT_GID(stat, gid) (stat).st_gid = high2lowgid(gid)
-asmlinkage long sys32_chown16(const char * filename, u16 user, u16 group)
+asmlinkage long sys32_chown16(const char __user * filename, u16 user, u16 group)
{
return sys_chown(filename, low2highuid(user), low2highgid(group));
}
-asmlinkage long sys32_lchown16(const char * filename, u16 user, u16 group)
+asmlinkage long sys32_lchown16(const char __user * filename, u16 user, u16 group)
{
return sys_lchown(filename, low2highuid(user), low2highgid(group));
}
low2highuid(suid));
}
-asmlinkage long sys32_getresuid16(u16 *ruid, u16 *euid, u16 *suid)
+asmlinkage long sys32_getresuid16(u16 __user *ruid, u16 __user *euid, u16 __user *suid)
{
int retval;
low2highgid(sgid));
}
-asmlinkage long sys32_getresgid16(u16 *rgid, u16 *egid, u16 *sgid)
+asmlinkage long sys32_getresgid16(u16 __user *rgid, u16 __user *egid, u16 __user *sgid)
{
int retval;
return sys_setfsgid((gid_t)gid);
}
-static int groups16_to_user(u16 *grouplist, struct group_info *group_info)
+static int groups16_to_user(u16 __user *grouplist, struct group_info *group_info)
{
int i;
u16 group;
return 0;
}
-static int groups16_from_user(struct group_info *group_info, u16 *grouplist)
+static int groups16_from_user(struct group_info *group_info, u16 __user *grouplist)
{
int i;
u16 group;
return 0;
}
-asmlinkage long sys32_getgroups16(int gidsetsize, u16 *grouplist)
+asmlinkage long sys32_getgroups16(int gidsetsize, u16 __user *grouplist)
{
int i;
return i;
}
-asmlinkage long sys32_setgroups16(int gidsetsize, u16 *grouplist)
+asmlinkage long sys32_setgroups16(int gidsetsize, u16 __user *grouplist)
{
struct group_info *group_info;
int retval;
/* 32-bit timeval and related flotsam. */
-static inline long get_tv32(struct timeval *o, struct compat_timeval *i)
+static inline long get_tv32(struct timeval *o, struct compat_timeval __user *i)
{
- return (!access_ok(VERIFY_READ, tv32, sizeof(*tv32)) ||
+ return (!access_ok(VERIFY_READ, o, sizeof(*o)) ||
(__get_user(o->tv_sec, &i->tv_sec) ||
__get_user(o->tv_usec, &i->tv_usec)));
}
-static inline long put_tv32(struct compat_timeval *o, struct timeval *i)
+static inline long put_tv32(struct compat_timeval __user *o, struct timeval *i)
{
return (!access_ok(VERIFY_WRITE, o, sizeof(*o)) ||
(__put_user(i->tv_sec, &o->tv_sec) ||
*
* This is really horribly ugly.
*/
+#ifdef CONFIG_SYSVIPC
asmlinkage long sys32_ipc(u32 call, int first, int second, int third, u32 ptr)
{
if (call >> 16) /* hack for backward compatibility */
case SHMDT:
return sys_shmdt(compat_ptr(ptr));
case SHMGET:
- return sys_shmget(first, second, third);
+ return sys_shmget(first, (unsigned)second, third);
case SHMCTL:
return compat_sys_shmctl(first, second, compat_ptr(ptr));
}
return -ENOSYS;
}
+#endif
-asmlinkage long sys32_truncate64(const char * path, unsigned long high, unsigned long low)
+asmlinkage long sys32_truncate64(const char __user * path, unsigned long high, unsigned long low)
{
if ((int)high < 0)
return -EINVAL;
return sys_ftruncate(fd, (high << 32) | low);
}
-/* readdir & getdents */
-
-#define NAME_OFFSET(de) ((int) ((de)->d_name - (char *) (de)))
-#define ROUND_UP(x) (((x)+sizeof(u32)-1) & ~(sizeof(u32)-1))
-
-struct old_linux_dirent32 {
- u32 d_ino;
- u32 d_offset;
- unsigned short d_namlen;
- char d_name[1];
-};
-
-struct readdir_callback32 {
- struct old_linux_dirent32 * dirent;
- int count;
-};
-
-static int fillonedir(void * __buf, const char * name, int namlen,
- loff_t offset, ino_t ino, unsigned int d_type)
-{
- struct readdir_callback32 * buf = (struct readdir_callback32 *) __buf;
- struct old_linux_dirent32 * dirent;
-
- if (buf->count)
- return -EINVAL;
- buf->count++;
- dirent = buf->dirent;
- put_user(ino, &dirent->d_ino);
- put_user(offset, &dirent->d_offset);
- put_user(namlen, &dirent->d_namlen);
- copy_to_user(dirent->d_name, name, namlen);
- put_user(0, dirent->d_name + namlen);
- return 0;
-}
-
-asmlinkage long old32_readdir(unsigned int fd, struct old_linux_dirent32 *dirent, unsigned int count)
-{
- int error = -EBADF;
- struct file * file;
- struct readdir_callback32 buf;
-
- file = fget(fd);
- if (!file)
- goto out;
-
- buf.count = 0;
- buf.dirent = dirent;
-
- error = vfs_readdir(file, fillonedir, &buf);
- if (error < 0)
- goto out_putf;
- error = buf.count;
-
-out_putf:
- fput(file);
-out:
- return error;
-}
-
-struct linux_dirent32 {
- u32 d_ino;
- u32 d_off;
- unsigned short d_reclen;
- char d_name[1];
-};
-
-struct getdents_callback32 {
- struct linux_dirent32 * current_dir;
- struct linux_dirent32 * previous;
- int count;
- int error;
-};
-
-static int filldir(void * __buf, const char * name, int namlen, loff_t offset, ino_t ino,
- unsigned int d_type)
-{
- struct linux_dirent32 * dirent;
- struct getdents_callback32 * buf = (struct getdents_callback32 *) __buf;
- int reclen = ROUND_UP(NAME_OFFSET(dirent) + namlen + 1);
-
- buf->error = -EINVAL; /* only used if we fail.. */
- if (reclen > buf->count)
- return -EINVAL;
- dirent = buf->previous;
- if (dirent)
- put_user(offset, &dirent->d_off);
- dirent = buf->current_dir;
- buf->previous = dirent;
- put_user(ino, &dirent->d_ino);
- put_user(reclen, &dirent->d_reclen);
- copy_to_user(dirent->d_name, name, namlen);
- put_user(0, dirent->d_name + namlen);
- buf->current_dir = ((void *)dirent) + reclen;
- buf->count -= reclen;
- return 0;
-}
-
-asmlinkage long sys32_getdents(unsigned int fd, struct linux_dirent32 *dirent, unsigned int count)
-{
- struct file * file;
- struct linux_dirent32 * lastdirent;
- struct getdents_callback32 buf;
- int error = -EBADF;
-
- file = fget(fd);
- if (!file)
- goto out;
-
- buf.current_dir = dirent;
- buf.previous = NULL;
- buf.count = count;
- buf.error = 0;
-
- error = vfs_readdir(file, filldir, &buf);
- if (error < 0)
- goto out_putf;
- lastdirent = buf.previous;
- error = buf.error;
- if(lastdirent) {
- put_user(file->f_pos, &lastdirent->d_off);
- error = count - buf.count;
- }
-out_putf:
- fput(file);
-out:
- return error;
-}
-
-/* end of readdir & getdents */
-
-int cp_compat_stat(struct kstat *stat, struct compat_stat *statbuf)
+int cp_compat_stat(struct kstat *stat, struct compat_stat __user *statbuf)
{
+ compat_ino_t ino;
int err;
if (!old_valid_dev(stat->dev) || !old_valid_dev(stat->rdev))
return -EOVERFLOW;
+ ino = stat->ino;
+ if (sizeof(ino) < sizeof(stat->ino) && ino != stat->ino)
+ return -EOVERFLOW;
+
err = put_user(old_encode_dev(stat->dev), &statbuf->st_dev);
err |= put_user(stat->ino, &statbuf->st_ino);
err |= put_user(stat->mode, &statbuf->st_mode);
mm_segment_t old_fs = get_fs ();
set_fs (KERNEL_DS);
- ret = sys_sysinfo(&s);
+ ret = sys_sysinfo((struct sysinfo __user *) &s);
set_fs (old_fs);
err = put_user (s.uptime, &info->uptime);
err |= __put_user (s.loads[0], &info->loads[0]);
mm_segment_t old_fs = get_fs ();
set_fs (KERNEL_DS);
- ret = sys_sched_rr_get_interval(pid, &t);
+ ret = sys_sched_rr_get_interval(pid, (struct timespec __user *) &t);
set_fs (old_fs);
if (put_compat_timespec(&t, interval))
return -EFAULT;
}
}
set_fs (KERNEL_DS);
- ret = sys_rt_sigprocmask(how, set ? &s : NULL, oset ? &s : NULL, sigsetsize);
+ ret = sys_rt_sigprocmask(how,
+ set ? (sigset_t __user *) &s : NULL,
+ oset ? (sigset_t __user *) &s : NULL,
+ sigsetsize);
set_fs (old_fs);
if (ret) return ret;
if (oset) {
mm_segment_t old_fs = get_fs();
set_fs (KERNEL_DS);
- ret = sys_rt_sigpending(&s, sigsetsize);
+ ret = sys_rt_sigpending((sigset_t __user *) &s, sigsetsize);
set_fs (old_fs);
if (!ret) {
switch (_NSIG_WORDS) {
return ret;
}
-extern int
-copy_siginfo_to_user32(siginfo_t32 *to, siginfo_t *from);
-
asmlinkage long
-sys32_rt_sigtimedwait(compat_sigset_t *uthese, siginfo_t32 *uinfo,
- struct compat_timespec *uts, size_t sigsetsize)
-{
- int ret, sig;
- sigset_t these;
- compat_sigset_t these32;
- struct timespec ts;
- siginfo_t info;
- long timeout = 0;
-
- /* XXX: Don't preclude handling different sized sigset_t's. */
- if (sigsetsize != sizeof(sigset_t))
- return -EINVAL;
-
- if (copy_from_user (&these32, uthese, sizeof(compat_sigset_t)))
- return -EFAULT;
-
- switch (_NSIG_WORDS) {
- case 4: these.sig[3] = these32.sig[6] | (((long)these32.sig[7]) << 32);
- case 3: these.sig[2] = these32.sig[4] | (((long)these32.sig[5]) << 32);
- case 2: these.sig[1] = these32.sig[2] | (((long)these32.sig[3]) << 32);
- case 1: these.sig[0] = these32.sig[0] | (((long)these32.sig[1]) << 32);
- }
-
- /*
- * Invert the set of allowed signals to get those we
- * want to block.
- */
- sigdelsetmask(&these, sigmask(SIGKILL)|sigmask(SIGSTOP));
- signotset(&these);
-
- if (uts) {
- if (get_compat_timespec(&ts, uts))
- return -EINVAL;
- if (ts.tv_nsec >= 1000000000L || ts.tv_nsec < 0
- || ts.tv_sec < 0)
- return -EINVAL;
- }
-
- spin_lock_irq(¤t->sighand->siglock);
- sig = dequeue_signal(current, &these, &info);
- if (!sig) {
- /* None ready -- temporarily unblock those we're interested
- in so that we'll be awakened when they arrive. */
- current->real_blocked = current->blocked;
- sigandsets(¤t->blocked, ¤t->blocked, &these);
- recalc_sigpending();
- spin_unlock_irq(¤t->sighand->siglock);
-
- timeout = MAX_SCHEDULE_TIMEOUT;
- if (uts)
- timeout = (timespec_to_jiffies(&ts)
- + (ts.tv_sec || ts.tv_nsec));
-
- current->state = TASK_INTERRUPTIBLE;
- timeout = schedule_timeout(timeout);
-
- spin_lock_irq(¤t->sighand->siglock);
- sig = dequeue_signal(current, &these, &info);
- current->blocked = current->real_blocked;
- siginitset(¤t->real_blocked, 0);
- recalc_sigpending();
- }
- spin_unlock_irq(¤t->sighand->siglock);
-
- if (sig) {
- ret = sig;
- if (uinfo) {
- if (copy_siginfo_to_user32(uinfo, &info))
- ret = -EFAULT;
- }
- } else {
- ret = -EAGAIN;
- if (timeout)
- ret = -EINTR;
- }
-
- return ret;
-}
-
-asmlinkage long
-sys32_rt_sigqueueinfo(int pid, int sig, siginfo_t32 __user *uinfo)
+sys32_rt_sigqueueinfo(int pid, int sig, compat_siginfo_t __user *uinfo)
{
siginfo_t info;
int ret;
mm_segment_t old_fs = get_fs();
- if (copy_from_user (&info, uinfo, 3*sizeof(int)) ||
- copy_from_user (info._sifields._pad, uinfo->_sifields._pad, SI_PAD_SIZE))
+ if (copy_siginfo_from_user32(&info, uinfo))
return -EFAULT;
set_fs (KERNEL_DS);
- ret = sys_rt_sigqueueinfo(pid, sig, &info);
+ ret = sys_rt_sigqueueinfo(pid, sig, (siginfo_t __user *) &info);
set_fs (old_fs);
return ret;
}
compat_ptr(regs.gprs[4]), ®s);
if (error == 0)
{
- current->ptrace &= ~PT_DTRACE;
current->thread.fp_regs.fpc=0;
- __asm__ __volatile__
- ("sr 0,0\n\t"
- "sfpc 0,0\n\t"
- : : :"0");
+ asm volatile("sfpc %0,0" : : "d" (0));
}
putname(filename);
out:
extern struct timezone sys_tz;
-asmlinkage long sys32_gettimeofday(struct compat_timeval *tv, struct timezone *tz)
+asmlinkage long sys32_gettimeofday(struct compat_timeval __user *tv, struct timezone __user *tz)
{
if (tv) {
struct timeval ktv;
- do_gettimeofday(&ktv);
+ vx_gettimeofday(&ktv);
if (put_tv32(tv, &ktv))
return -EFAULT;
}
return 0;
}
-static inline long get_ts32(struct timespec *o, struct compat_timeval *i)
+static inline long get_ts32(struct timespec *o, struct compat_timeval __user *i)
{
long usec;
return 0;
}
-asmlinkage long sys32_settimeofday(struct compat_timeval *tv, struct timezone *tz)
+asmlinkage long sys32_settimeofday(struct compat_timeval __user *tv, struct timezone __user *tz)
{
struct timespec kts;
struct timezone ktz;
return -ERESTARTNOHAND;
}
-asmlinkage long sys32_pread64(unsigned int fd, char *ubuf,
+asmlinkage long sys32_pread64(unsigned int fd, char __user *ubuf,
size_t count, u32 poshi, u32 poslo)
{
if ((compat_ssize_t) count < 0)
return sys_pread64(fd, ubuf, count, ((loff_t)AA(poshi) << 32) | AA(poslo));
}
-asmlinkage long sys32_pwrite64(unsigned int fd, const char *ubuf,
+asmlinkage long sys32_pwrite64(unsigned int fd, const char __user *ubuf,
size_t count, u32 poshi, u32 poslo)
{
if ((compat_ssize_t) count < 0)
return sys_readahead(fd, ((loff_t)AA(offhi) << 32) | AA(offlo), count);
}
-asmlinkage long sys32_sendfile(int out_fd, int in_fd, compat_off_t *offset, size_t count)
+asmlinkage long sys32_sendfile(int out_fd, int in_fd, compat_off_t __user *offset, size_t count)
{
mm_segment_t old_fs = get_fs();
int ret;
return -EFAULT;
set_fs(KERNEL_DS);
- ret = sys_sendfile(out_fd, in_fd, offset ? &of : NULL, count);
+ ret = sys_sendfile(out_fd, in_fd,
+ offset ? (off_t __user *) &of : NULL, count);
set_fs(old_fs);
- if (!ret && offset && put_user(of, offset))
+ if (offset && put_user(of, offset))
return -EFAULT;
return ret;
}
asmlinkage long sys32_sendfile64(int out_fd, int in_fd,
- compat_loff_t *offset, s32 count)
+ compat_loff_t __user *offset, s32 count)
{
mm_segment_t old_fs = get_fs();
int ret;
return -EFAULT;
set_fs(KERNEL_DS);
- ret = sys_sendfile64(out_fd, in_fd, offset ? &lof : NULL, count);
+ ret = sys_sendfile64(out_fd, in_fd,
+ offset ? (loff_t __user *) &lof : NULL, count);
set_fs(old_fs);
if (offset && put_user(lof, offset))
return ret;
}
-/* Handle adjtimex compatibility. */
-
-struct timex32 {
- u32 modes;
- s32 offset, freq, maxerror, esterror;
- s32 status, constant, precision, tolerance;
- struct compat_timeval time;
- s32 tick;
- s32 ppsfreq, jitter, shift, stabil;
- s32 jitcnt, calcnt, errcnt, stbcnt;
- s32 :32; s32 :32; s32 :32; s32 :32;
- s32 :32; s32 :32; s32 :32; s32 :32;
- s32 :32; s32 :32; s32 :32; s32 :32;
-};
-
-extern int do_adjtimex(struct timex *);
-
-asmlinkage long sys32_adjtimex(struct timex32 *utp)
-{
- struct timex txc;
- int ret;
-
- memset(&txc, 0, sizeof(struct timex));
-
- if(get_user(txc.modes, &utp->modes) ||
- __get_user(txc.offset, &utp->offset) ||
- __get_user(txc.freq, &utp->freq) ||
- __get_user(txc.maxerror, &utp->maxerror) ||
- __get_user(txc.esterror, &utp->esterror) ||
- __get_user(txc.status, &utp->status) ||
- __get_user(txc.constant, &utp->constant) ||
- __get_user(txc.precision, &utp->precision) ||
- __get_user(txc.tolerance, &utp->tolerance) ||
- __get_user(txc.time.tv_sec, &utp->time.tv_sec) ||
- __get_user(txc.time.tv_usec, &utp->time.tv_usec) ||
- __get_user(txc.tick, &utp->tick) ||
- __get_user(txc.ppsfreq, &utp->ppsfreq) ||
- __get_user(txc.jitter, &utp->jitter) ||
- __get_user(txc.shift, &utp->shift) ||
- __get_user(txc.stabil, &utp->stabil) ||
- __get_user(txc.jitcnt, &utp->jitcnt) ||
- __get_user(txc.calcnt, &utp->calcnt) ||
- __get_user(txc.errcnt, &utp->errcnt) ||
- __get_user(txc.stbcnt, &utp->stbcnt))
- return -EFAULT;
-
- ret = do_adjtimex(&txc);
-
- if(put_user(txc.modes, &utp->modes) ||
- __put_user(txc.offset, &utp->offset) ||
- __put_user(txc.freq, &utp->freq) ||
- __put_user(txc.maxerror, &utp->maxerror) ||
- __put_user(txc.esterror, &utp->esterror) ||
- __put_user(txc.status, &utp->status) ||
- __put_user(txc.constant, &utp->constant) ||
- __put_user(txc.precision, &utp->precision) ||
- __put_user(txc.tolerance, &utp->tolerance) ||
- __put_user(txc.time.tv_sec, &utp->time.tv_sec) ||
- __put_user(txc.time.tv_usec, &utp->time.tv_usec) ||
- __put_user(txc.tick, &utp->tick) ||
- __put_user(txc.ppsfreq, &utp->ppsfreq) ||
- __put_user(txc.jitter, &utp->jitter) ||
- __put_user(txc.shift, &utp->shift) ||
- __put_user(txc.stabil, &utp->stabil) ||
- __put_user(txc.jitcnt, &utp->jitcnt) ||
- __put_user(txc.calcnt, &utp->calcnt) ||
- __put_user(txc.errcnt, &utp->errcnt) ||
- __put_user(txc.stbcnt, &utp->stbcnt))
- ret = -EFAULT;
-
- return ret;
-}
-
+#ifdef CONFIG_SYSCTL_SYSCALL
struct __sysctl_args32 {
u32 name;
int nlen;
u32 __unused[4];
};
-asmlinkage long sys32_sysctl(struct __sysctl_args32 *args)
+asmlinkage long sys32_sysctl(struct __sysctl_args32 __user *args)
{
struct __sysctl_args32 tmp;
int error;
- size_t oldlen, *oldlenp = NULL;
- unsigned long addr = (((long)&args->__unused[0]) + 7) & ~7;
+ size_t oldlen;
+ size_t __user *oldlenp = NULL;
+ unsigned long addr = (((unsigned long)&args->__unused[0]) + 7) & ~7;
if (copy_from_user(&tmp, args, sizeof(tmp)))
return -EFAULT;
basically copy the whole sysctl.c here, and
glibc's __sysctl uses rw memory for the structure
anyway. */
- if (get_user(oldlen, (u32 *)A(tmp.oldlenp)) ||
- put_user(oldlen, (size_t *)addr))
+ if (get_user(oldlen, (u32 __user *)compat_ptr(tmp.oldlenp)) ||
+ put_user(oldlen, (size_t __user *)addr))
return -EFAULT;
- oldlenp = (size_t *)addr;
+ oldlenp = (size_t __user *)addr;
}
lock_kernel();
- error = do_sysctl((int *)A(tmp.name), tmp.nlen, (void *)A(tmp.oldval),
- oldlenp, (void *)A(tmp.newval), tmp.newlen);
+ error = do_sysctl(compat_ptr(tmp.name), tmp.nlen, compat_ptr(tmp.oldval),
+ oldlenp, compat_ptr(tmp.newval), tmp.newlen);
unlock_kernel();
if (oldlenp) {
if (!error) {
- if (get_user(oldlen, (size_t *)addr) ||
- put_user(oldlen, (u32 *)A(tmp.oldlenp)))
+ if (get_user(oldlen, (size_t __user *)addr) ||
+ put_user(oldlen, (u32 __user *)compat_ptr(tmp.oldlenp)))
error = -EFAULT;
}
- copy_to_user(args->__unused, tmp.__unused, sizeof(tmp.__unused));
+ if (copy_to_user(args->__unused, tmp.__unused,
+ sizeof(tmp.__unused)))
+ error = -EFAULT;
}
return error;
}
+#endif
struct stat64_emu31 {
unsigned long long st_dev;
unsigned long st_ino;
};
-static int cp_stat64(struct stat64_emu31 *ubuf, struct kstat *stat)
+static int cp_stat64(struct stat64_emu31 __user *ubuf, struct kstat *stat)
{
struct stat64_emu31 tmp;
return copy_to_user(ubuf,&tmp,sizeof(tmp)) ? -EFAULT : 0;
}
-asmlinkage long sys32_stat64(char * filename, struct stat64_emu31 * statbuf)
+asmlinkage long sys32_stat64(char __user * filename, struct stat64_emu31 __user * statbuf)
{
struct kstat stat;
int ret = vfs_stat(filename, &stat);
return ret;
}
-asmlinkage long sys32_lstat64(char * filename, struct stat64_emu31 * statbuf)
+asmlinkage long sys32_lstat64(char __user * filename, struct stat64_emu31 __user * statbuf)
{
struct kstat stat;
int ret = vfs_lstat(filename, &stat);
return ret;
}
-asmlinkage long sys32_fstat64(unsigned long fd, struct stat64_emu31 * statbuf)
+asmlinkage long sys32_fstat64(unsigned long fd, struct stat64_emu31 __user * statbuf)
{
struct kstat stat;
int ret = vfs_fstat(fd, &stat);
return ret;
}
+asmlinkage long sys32_fstatat64(unsigned int dfd, char __user *filename,
+ struct stat64_emu31 __user* statbuf, int flag)
+{
+ struct kstat stat;
+ int error = -EINVAL;
+
+ if ((flag & ~AT_SYMLINK_NOFOLLOW) != 0)
+ goto out;
+
+ if (flag & AT_SYMLINK_NOFOLLOW)
+ error = vfs_lstat_fd(dfd, filename, &stat);
+ else
+ error = vfs_stat_fd(dfd, filename, &stat);
+
+ if (!error)
+ error = cp_stat64(statbuf, &stat);
+out:
+ return error;
+}
+
/*
* Linux/i386 didn't use to be able to handle more than
* 4 system call parameters, so these system calls used a memory
asmlinkage unsigned long
-old32_mmap(struct mmap_arg_struct_emu31 *arg)
+old32_mmap(struct mmap_arg_struct_emu31 __user *arg)
{
struct mmap_arg_struct_emu31 a;
int error = -EFAULT;
}
asmlinkage long
-sys32_mmap2(struct mmap_arg_struct_emu31 *arg)
+sys32_mmap2(struct mmap_arg_struct_emu31 __user *arg)
{
struct mmap_arg_struct_emu31 a;
int error = -EFAULT;
return error;
}
-asmlinkage long sys32_read(unsigned int fd, char * buf, size_t count)
+asmlinkage long sys32_read(unsigned int fd, char __user * buf, size_t count)
{
if ((compat_ssize_t) count < 0)
return -EINVAL;
return sys_read(fd, buf, count);
}
-asmlinkage long sys32_write(unsigned int fd, char * buf, size_t count)
+asmlinkage long sys32_write(unsigned int fd, char __user * buf, size_t count)
{
if ((compat_ssize_t) count < 0)
return -EINVAL;
{
unsigned long clone_flags;
unsigned long newsp;
- int *parent_tidptr, *child_tidptr;
+ int __user *parent_tidptr, *child_tidptr;
clone_flags = regs.gprs[3] & 0xffffffffUL;
newsp = regs.orig_gpr2 & 0x7fffffffUL;
- parent_tidptr = (int *) (regs.gprs[4] & 0x7fffffffUL);
- child_tidptr = (int *) (regs.gprs[5] & 0x7fffffffUL);
+ parent_tidptr = compat_ptr(regs.gprs[4]);
+ child_tidptr = compat_ptr(regs.gprs[5]);
if (!newsp)
newsp = regs.gprs[15];
- return do_fork(clone_flags & ~CLONE_IDLETASK, newsp, ®s, 0,
+ return do_fork(clone_flags, newsp, ®s, 0,
parent_tidptr, child_tidptr);
}
/*
- * Wrapper function for sys_timer_create.
+ * 31 bit emulation wrapper functions for sys_fadvise64/fadvise64_64.
+ * These need to rewrite the advise values for POSIX_FADV_{DONTNEED,NOREUSE}
+ * because the 31 bit values differ from the 64 bit values.
*/
-extern asmlinkage long
-sys_timer_create(clockid_t, struct sigevent *, timer_t *);
asmlinkage long
-sys32_timer_create(clockid_t which_clock, struct sigevent32 *se32,
- timer_t *timer_id)
+sys32_fadvise64(int fd, loff_t offset, size_t len, int advise)
{
- struct sigevent se;
- timer_t ktimer_id;
- mm_segment_t old_fs;
- long ret;
-
- if (se32 == NULL)
- return sys_timer_create(which_clock, NULL, timer_id);
-
- /* XXX: converting se32 to se is filthy because of the
- * two union members. For now it is ok, because the pointers
- * are not touched in kernel.
- */
- memset(&se, 0, sizeof(se));
- if (get_user(se.sigev_value.sival_int, &se32->sigev_value.sival_int) ||
- get_user(se.sigev_signo, &se32->sigev_signo) ||
- get_user(se.sigev_notify, &se32->sigev_notify) ||
- copy_from_user(&se._sigev_un._pad, &se32->_sigev_un._pad,
- sizeof(se._sigev_un._pad)))
- return -EFAULT;
+ if (advise == 4)
+ advise = POSIX_FADV_DONTNEED;
+ else if (advise == 5)
+ advise = POSIX_FADV_NOREUSE;
+ return sys_fadvise64(fd, offset, len, advise);
+}
- old_fs = get_fs();
- set_fs(KERNEL_DS);
- ret = sys_timer_create(which_clock, &se, &ktimer_id);
- set_fs(old_fs);
+struct fadvise64_64_args {
+ int fd;
+ long long offset;
+ long long len;
+ int advice;
+};
- if (!ret)
- ret = put_user (ktimer_id, timer_id);
+asmlinkage long
+sys32_fadvise64_64(struct fadvise64_64_args __user *args)
+{
+ struct fadvise64_64_args a;
- return ret;
+ if ( copy_from_user(&a, args, sizeof(a)) )
+ return -EFAULT;
+ if (a.advice == 4)
+ a.advice = POSIX_FADV_DONTNEED;
+ else if (a.advice == 5)
+ a.advice = POSIX_FADV_NOREUSE;
+ return sys_fadvise64_64(a.fd, a.offset, a.len, a.advice);
}