if (!file)
return -EBADF;
}
-
+
+ if (a.prot & PROT_READ)
+ a.prot |= vm_force_exec32;
+
mm = current->mm;
down_write(&mm->mmap_sem);
retval = do_mmap_pgoff(file, a.addr, a.len, a.prot, a.flags, a.offset>>PAGE_SHIFT);
{
if ((start + PAGE_ALIGN(len)) >> 32)
return -ENOMEM;
+ if (prot & PROT_READ)
+ prot |= vm_force_exec32;
return sys_mprotect(start,len,prot);
}
+asmlinkage long
sys32_brk(unsigned long brk)
{
if (brk > IA32_PAGE_OFFSET)
}
extern unsigned long do_mremap(unsigned long addr,
- unsigned long old_len, unsigned long new_len,
- unsigned long flags, unsigned long new_addr);
+ unsigned long old_len, unsigned long new_len,
+ unsigned long flags, unsigned long new_addr);
asmlinkage unsigned long sys32_mremap(unsigned long addr,
- unsigned long old_len, unsigned long new_len,
- unsigned long flags, unsigned long new_addr)
+ unsigned long old_len, unsigned long new_len,
+ unsigned long flags, unsigned long new_addr)
{
struct vm_area_struct *vma;
unsigned long ret = -EINVAL;
/* MREMAP_FIXED checked above. */
new_addr = get_unmapped_area(file, addr, new_len,
- vma ? vma->vm_pgoff : 0, map_flags);
+ vma ? vma->vm_pgoff : 0,
+ map_flags);
ret = new_addr;
if (new_addr & ~PAGE_MASK)
goto out_sem;
out_sem:
up_write(¤t->mm->mmap_sem);
out:
-return ret;
+ return ret;
}
-
asmlinkage long
sys32_pipe(int __user *fd)
{
return do_sys_settimeofday(tv ? &kts : NULL, tz ? &ktz : NULL);
}
+struct linux32_dirent {
+ u32 d_ino;
+ u32 d_off;
+ u16 d_reclen;
+ char d_name[1];
+};
+
+struct old_linux32_dirent {
+ u32 d_ino;
+ u32 d_offset;
+ u16 d_namlen;
+ char d_name[1];
+};
+
+struct getdents32_callback {
+ struct linux32_dirent __user * current_dir;
+ struct linux32_dirent __user * previous;
+ int count;
+ int error;
+};
+
+struct readdir32_callback {
+ struct old_linux32_dirent __user * dirent;
+ int count;
+};
+
+static int
+filldir32 (void *__buf, const char *name, int namlen, loff_t offset, ino_t ino,
+ unsigned int d_type)
+{
+ struct linux32_dirent __user * dirent;
+ struct getdents32_callback * buf = (struct getdents32_callback *) __buf;
+ int reclen = ROUND_UP(NAME_OFFSET(dirent) + namlen + 2, 4);
+
+ 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);
+ put_user(d_type, (char __user *)dirent + reclen - 1);
+ dirent = ((void __user *)dirent) + reclen;
+ buf->current_dir = dirent;
+ buf->count -= reclen;
+ return 0;
+}
+
+asmlinkage long
+sys32_getdents (unsigned int fd, void __user * dirent, unsigned int count)
+{
+ struct file * file;
+ struct linux32_dirent __user * lastdirent;
+ struct getdents32_callback buf;
+ int error;
+
+ error = -EBADF;
+ file = fget(fd);
+ if (!file)
+ goto out;
+
+ buf.current_dir = (struct linux32_dirent __user *) dirent;
+ buf.previous = NULL;
+ buf.count = count;
+ buf.error = 0;
+
+ error = vfs_readdir(file, filldir32, &buf);
+ if (error < 0)
+ goto out_putf;
+ error = buf.error;
+ lastdirent = buf.previous;
+ if (lastdirent) {
+ put_user(file->f_pos, &lastdirent->d_off);
+ error = count - buf.count;
+ }
+
+out_putf:
+ fput(file);
+out:
+ return error;
+}
+
+static int
+fillonedir32 (void * __buf, const char * name, int namlen, loff_t offset, ino_t ino, unsigned d_type)
+{
+ struct readdir32_callback * buf = (struct readdir32_callback *) __buf;
+ struct old_linux32_dirent __user * 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
+sys32_oldreaddir (unsigned int fd, void __user * dirent, unsigned int count)
+{
+ int error;
+ struct file * file;
+ struct readdir32_callback buf;
+
+ error = -EBADF;
+ file = fget(fd);
+ if (!file)
+ goto out;
+
+ buf.count = 0;
+ buf.dirent = dirent;
+
+ error = vfs_readdir(file, fillonedir32, &buf);
+ if (error >= 0)
+ error = buf.count;
+ fput(file);
+out:
+ return error;
+}
+
struct sel_arg_struct {
unsigned int n;
unsigned int inp;
return -EBADF;
}
+ if (prot & PROT_READ)
+ prot |= vm_force_exec32;
+
down_write(&mm->mmap_sem);
error = do_mmap_pgoff(file, addr, len, prot, flags, pgoff);
up_write(&mm->mmap_sem);
if (IS_ERR(filename))
return error;
error = compat_do_execve(filename, argv, envp, regs);
- if (error == 0) {
- task_lock(current);
+ if (error == 0)
current->ptrace &= ~PT_DTRACE;
- task_unlock(current);
- }
putname(filename);
return error;
}
return sys_kill(pid, sig);
}
+
+long sys32_io_setup(unsigned nr_reqs, u32 __user *ctx32p)
+{
+ long ret;
+ aio_context_t ctx64;
+ mm_segment_t oldfs = get_fs();
+ set_fs(KERNEL_DS);
+ ret = sys_io_setup(nr_reqs, &ctx64);
+ set_fs(oldfs);
+ /* truncating is ok because it's a user address */
+ if (!ret)
+ ret = put_user((u32)ctx64, ctx32p);
+ return ret;
+}
+
+asmlinkage long sys32_io_submit(aio_context_t ctx_id, int nr,
+ compat_uptr_t __user *iocbpp)
+{
+ struct kioctx *ctx;
+ long ret = 0;
+ int i;
+
+ if (unlikely(nr < 0))
+ return -EINVAL;
+
+ if (unlikely(!access_ok(VERIFY_READ, iocbpp, (nr*sizeof(*iocbpp)))))
+ return -EFAULT;
+
+ ctx = lookup_ioctx(ctx_id);
+ if (unlikely(!ctx)) {
+ pr_debug("EINVAL: io_submit: invalid context id\n");
+ return -EINVAL;
+ }
+
+ for (i=0; i<nr; i++) {
+ compat_uptr_t p32;
+ struct iocb __user *user_iocb;
+ struct iocb tmp;
+
+ if (unlikely(__get_user(p32, iocbpp + i))) {
+ ret = -EFAULT;
+ break;
+ }
+ user_iocb = compat_ptr(p32);
+
+ if (unlikely(copy_from_user(&tmp, user_iocb, sizeof(tmp)))) {
+ ret = -EFAULT;
+ break;
+ }
+
+ ret = io_submit_one(ctx, user_iocb, &tmp);
+ if (ret)
+ break;
+ }
+
+ put_ioctx(ctx);
+ return i ? i : ret;
+}
+
+
+asmlinkage long sys32_io_getevents(aio_context_t ctx_id,
+ unsigned long min_nr,
+ unsigned long nr,
+ struct io_event __user *events,
+ struct compat_timespec __user *timeout)
+{
+ long ret;
+ mm_segment_t oldfs;
+ struct timespec t;
+ /* Harden against bogus ptrace */
+ if (nr >= 0xffffffff ||
+ !access_ok(VERIFY_WRITE, events, nr * sizeof(struct io_event)))
+ return -EFAULT;
+ if (timeout && get_compat_timespec(&t, timeout))
+ return -EFAULT;
+ oldfs = get_fs();
+ set_fs(KERNEL_DS);
+ ret = sys_io_getevents(ctx_id,min_nr,nr,events,timeout ? &t : NULL);
+ set_fs(oldfs);
+ if (!ret && timeout && put_compat_timespec(&t, timeout))
+ return -EFAULT;
+ return ret;
+}
+
asmlinkage long sys32_open(const char __user * filename, int flags, int mode)
{
char * tmp;
if (strncmp(lastcomm, me->comm, sizeof(lastcomm))) {
printk(KERN_INFO "%s: vm86 mode not supported on 64 bit kernel\n",
me->comm);
- strncpy(lastcomm, me->comm, sizeof(lastcomm));
+ strncpy(lastcomm, me->comm, sizeof(lastcomm));
+ }
+ return -ENOSYS;
+}
+
+long sys32_quotactl(void)
+{
+ struct task_struct *me = current;
+ static char lastcomm[8];
+ if (strcmp(lastcomm, me->comm)) {
+ printk(KERN_INFO "%s: 32bit quotactl not supported on 64 bit kernel\n",
+ me->comm);
+ strcpy(lastcomm, me->comm);
}
return -ENOSYS;
}