diff options
Diffstat (limited to 'arch/sparc64/kernel/sys_sparc32.c')
-rw-r--r-- | arch/sparc64/kernel/sys_sparc32.c | 1090 |
1 files changed, 494 insertions, 596 deletions
diff --git a/arch/sparc64/kernel/sys_sparc32.c b/arch/sparc64/kernel/sys_sparc32.c index 59815b7a8..1f607da98 100644 --- a/arch/sparc64/kernel/sys_sparc32.c +++ b/arch/sparc64/kernel/sys_sparc32.c @@ -1,4 +1,4 @@ -/* $Id: sys_sparc32.c,v 1.26 1997/06/04 13:05:21 jj Exp $ +/* $Id: sys_sparc32.c,v 1.43 1997/07/17 02:20:45 davem Exp $ * sys_sparc32.c: Conversion between 32bit and 64bit native syscalls. * * Copyright (C) 1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz) @@ -8,6 +8,7 @@ * environment. */ +#include <linux/config.h> #include <linux/kernel.h> #include <linux/fs.h> #include <linux/signal.h> @@ -30,11 +31,13 @@ #include <linux/ncp_fs.h> #include <linux/quota.h> #include <linux/file.h> +#include <linux/module.h> #include <asm/types.h> #include <asm/poll.h> #include <asm/ipc.h> #include <asm/uaccess.h> +#include <asm/fpumacro.h> /* As gcc will warn about casting u32 to some ptr, we have to cast it to * unsigned long first, and that's what is A() for. @@ -372,11 +375,12 @@ asmlinkage int sys32_ipc (u32 call, int first, int second, int third, u32 ptr, u switch (version) { case 0: default: { unsigned long raddr; + u32 *uptr = (u32 *) A(((u32)third)); err = sys_shmat (first, (char *)A(ptr), second, &raddr); if (err) goto out; err = -EFAULT; - if(put_user (raddr, ((u32 *)A(third)))) + if(put_user (raddr, uptr)) goto out; err = 0; goto out; @@ -469,32 +473,6 @@ out: return err; } -extern asmlinkage unsigned long sys_mmap(unsigned long addr, unsigned long len, - unsigned long prot, unsigned long flags, - unsigned long fd, unsigned long off); - -asmlinkage unsigned long sys32_mmap(u32 addr, u32 len, u32 prot, - u32 flags, u32 fd, u32 off) -{ - return sys_mmap((unsigned long)addr, (unsigned long)len, - (unsigned long)prot, (unsigned long)flags, - (unsigned long)fd, (unsigned long)off); -} - -extern asmlinkage int sys_bdflush(int func, long data); - -asmlinkage int sys32_bdflush(int func, s32 data) -{ - return sys_bdflush(func, (long)data); -} - -extern asmlinkage int sys_uselib(const char * library); - -asmlinkage int sys32_uselib(u32 library) -{ - return sys_uselib((const char *)A(library)); -} - static inline int get_flock(struct flock *kfl, struct flock32 *ufl) { if(get_user(kfl->l_type, &ufl->l_type) || @@ -544,55 +522,6 @@ asmlinkage long sys32_fcntl(unsigned int fd, unsigned int cmd, u32 arg) } } -extern asmlinkage int sys_mknod(const char * filename, int mode, dev_t dev); - -asmlinkage int sys32_mknod(u32 filename, int mode, __kernel_dev_t32 dev) -{ - return sys_mknod((const char *)A(filename), mode, dev); -} - -extern asmlinkage int sys_mkdir(const char * pathname, int mode); - -asmlinkage int sys32_mkdir(u32 pathname, int mode) -{ - return sys_mkdir((const char *)A(pathname), mode); -} - -extern asmlinkage int sys_rmdir(const char * pathname); - -asmlinkage int sys32_rmdir(u32 pathname) -{ - return sys_rmdir((const char *)A(pathname)); -} - -extern asmlinkage int sys_unlink(const char * pathname); - -asmlinkage int sys32_unlink(u32 pathname) -{ - return sys_unlink((const char *)A(pathname)); -} - -extern asmlinkage int sys_symlink(const char * oldname, const char * newname); - -asmlinkage int sys32_symlink(u32 oldname, u32 newname) -{ - return sys_symlink((const char *)A(oldname), (const char *)A(newname)); -} - -extern asmlinkage int sys_link(const char * oldname, const char * newname); - -asmlinkage int sys32_link(u32 oldname, u32 newname) -{ - return sys_link((const char *)A(oldname), (const char *)A(newname)); -} - -extern asmlinkage int sys_rename(const char * oldname, const char * newname); - -asmlinkage int sys32_rename(u32 oldname, u32 newname) -{ - return sys_rename((const char *)A(oldname), (const char *)A(newname)); -} - struct dqblk32 { __u32 dqb_bhardlimit; __u32 dqb_bsoftlimit; @@ -701,20 +630,6 @@ asmlinkage int sys32_fstatfs(unsigned int fd, u32 buf) return ret; } -extern asmlinkage int sys_truncate(const char * path, unsigned long length); - -asmlinkage int sys32_truncate(u32 path, u32 length) -{ - return sys_truncate((const char *)A(path), (unsigned long)length); -} - -extern asmlinkage int sys_ftruncate(unsigned int fd, unsigned long length); - -asmlinkage int sys32_ftruncate(unsigned int fd, u32 length) -{ - return sys_ftruncate(fd, (unsigned long)length); -} - extern asmlinkage int sys_utime(char * filename, struct utimbuf * times); asmlinkage int sys32_utime(u32 filename, u32 times) @@ -741,96 +656,6 @@ asmlinkage int sys32_utime(u32 filename, u32 times) return ret; } -extern asmlinkage int sys_utimes(char * filename, struct timeval * utimes); - -asmlinkage int sys32_utimes(u32 filename, u32 utimes) -{ - /* struct timeval is the same :)) */ - return sys_utimes((char *)A(filename), (struct timeval *)A(utimes)); -} - -extern asmlinkage int sys_access(const char * filename, int mode); - -asmlinkage int sys32_access(u32 filename, int mode) -{ - return sys_access((const char *)A(filename), mode); -} - -extern asmlinkage int sys_chdir(const char * filename); - -asmlinkage int sys32_chdir(u32 filename) -{ - return sys_chdir((const char *)A(filename)); -} - -extern asmlinkage int sys_chroot(const char * filename); - -asmlinkage int sys32_chroot(u32 filename) -{ - return sys_chroot((const char *)A(filename)); -} - -extern asmlinkage int sys_chmod(const char * filename, mode_t mode); - -asmlinkage int sys32_chmod(u32 filename, __kernel_mode_t32 mode) -{ - return sys_chmod((const char *)A(filename), mode); -} - -extern asmlinkage int sys_chown(const char * filename, uid_t user, gid_t group); - -asmlinkage int sys32_chown(u32 filename, __kernel_uid_t32 user, __kernel_gid_t32 group) -{ - return sys_chown((const char *)A(filename), user, group); -} - -extern asmlinkage int sys_open(const char * filename,int flags,int mode); - -asmlinkage int sys32_open(u32 filename, int flags, int mode) -{ - return sys_open((const char *)A(filename), flags, mode); -} - -extern asmlinkage int sys_creat(const char * pathname, int mode); - -asmlinkage int sys32_creat(u32 pathname, int mode) -{ - return sys_creat((const char *)A(pathname), mode); -} - -extern asmlinkage long sys_lseek(unsigned int fd, off_t offset, unsigned int origin); - -asmlinkage long sys32_lseek(unsigned int fd, s32 offset, unsigned int origin) -{ - return sys_lseek(fd, (off_t)offset, origin); -} - -extern asmlinkage int sys_llseek(unsigned int fd, unsigned long offset_high, - unsigned long offset_low, - loff_t *result, unsigned int origin); - -asmlinkage int sys32_llseek(unsigned int fd, u32 offset_high, - u32 offset_low, u32 result, unsigned int origin) -{ - /* loff_t is the same :)) */ - return sys_llseek(fd, (unsigned long)offset_high, (unsigned long)offset_low, - (loff_t *)A(result), origin); -} - -extern asmlinkage long sys_read(unsigned int fd, char * buf, unsigned long count); - -asmlinkage long sys32_read(unsigned int fd, u32 buf, u32 count) -{ - return sys_read(fd, (char *)A(buf), (unsigned long)count); -} - -extern asmlinkage long sys_write(unsigned int fd, const char * buf, unsigned long count); - -asmlinkage long sys32_write(unsigned int fd, u32 buf, u32 count) -{ - return sys_write(fd, (const char *)A(buf), (unsigned long)count); -} - struct iovec32 { u32 iov_base; __kernel_size_t32 iov_len; }; typedef long (*IO_fn_t)(struct inode *, struct file *, char *, unsigned long); @@ -934,14 +759,29 @@ static long do_readv_writev32(int type, struct inode *inode, struct file *file, asmlinkage long sys32_readv(int fd, u32 vector, u32 count) { struct file *file; + struct dentry *dentry; struct inode *inode; long err = -EBADF; lock_kernel(); - if (fd >= NR_OPEN || !(file = current->files->fd[fd]) || !(inode=file->f_inode)) + if(fd >= NR_OPEN) + goto out; + + file = current->files->fd[fd]; + if(!file) + goto out; + + if(!(file->f_mode & 1)) + goto out; + + dentry = file->f_dentry; + if(!dentry) goto out; - if (!(file->f_mode & 1)) + + inode = dentry->d_inode; + if(!inode) goto out; + err = do_readv_writev32(VERIFY_WRITE, inode, file, (struct iovec32 *)A(vector), count); out: @@ -953,13 +793,28 @@ asmlinkage long sys32_writev(int fd, u32 vector, u32 count) { int error = -EBADF; struct file *file; + struct dentry *dentry; struct inode *inode; lock_kernel(); - if (fd >= NR_OPEN || !(file = current->files->fd[fd]) || !(inode=file->f_inode)) + if(fd >= NR_OPEN) + goto out; + + file = current->files->fd[fd]; + if(!file) + goto out; + + if(!(file->f_mode & 2)) + goto out; + + dentry = file->f_dentry; + if(!dentry) goto out; - if (!(file->f_mode & 2)) + + inode = dentry->d_inode; + if(!inode) goto out; + down(&inode->i_sem); error = do_readv_writev32(VERIFY_READ, inode, file, (struct iovec32 *)A(vector), count); @@ -1008,21 +863,34 @@ asmlinkage int old32_readdir(unsigned int fd, u32 dirent, unsigned int count) { int error = -EBADF; struct file * file; + struct dentry * dentry; + struct inode * inode; struct readdir_callback32 buf; lock_kernel(); - if (fd >= NR_OPEN || !(file = current->files->fd[fd])) + if(fd >= NR_OPEN) goto out; - error = -ENOTDIR; - if (!file->f_op || !file->f_op->readdir) + + file = current->files->fd[fd]; + if(!file) goto out; - error = verify_area(VERIFY_WRITE, (void *)A(dirent), - sizeof(struct old_linux_dirent32)); - if (error) + + dentry = file->f_dentry; + if(!dentry) + goto out; + + inode = dentry->d_inode; + if(!inode) goto out; + buf.count = 0; buf.dirent = (struct old_linux_dirent32 *)A(dirent); - error = file->f_op->readdir(file->f_inode, file, &buf, fillonedir); + + error = -ENOTDIR; + if (!file->f_op || !file->f_op->readdir) + goto out; + + error = file->f_op->readdir(inode, file, &buf, fillonedir); if (error < 0) goto out; error = buf.count; @@ -1072,30 +940,43 @@ static int filldir(void * __buf, const char * name, int namlen, off_t offset, in asmlinkage int sys32_getdents(unsigned int fd, u32 dirent, unsigned int count) { struct file * file; + struct dentry * dentry; + struct inode *inode; struct linux_dirent32 * lastdirent; struct getdents_callback32 buf; int error = -EBADF; lock_kernel(); - if (fd >= NR_OPEN || !(file = current->files->fd[fd])) + if(fd >= NR_OPEN) goto out; - error = -ENOTDIR; - if (!file->f_op || !file->f_op->readdir) + + file = current->files->fd[fd]; + if(!file) + goto out; + + dentry = file->f_dentry; + if(!dentry) goto out; - error = verify_area(VERIFY_WRITE, (void *)A(dirent), count); - if (error) + + inode = dentry->d_inode; + if(!inode) goto out; + buf.current_dir = (struct linux_dirent32 *) A(dirent); buf.previous = NULL; buf.count = count; buf.error = 0; - error = file->f_op->readdir(file->f_inode, file, &buf, filldir); + + error = -ENOTDIR; + if (!file->f_op || !file->f_op->readdir) + goto out; + + error = file->f_op->readdir(inode, file, &buf, filldir); if (error < 0) goto out; lastdirent = buf.previous; - if (!lastdirent) { - error = buf.error; - } else { + error = buf.error; + if(lastdirent) { put_user(file->f_pos, &lastdirent->d_off); error = count - buf.count; } @@ -1196,13 +1077,6 @@ out: return ret; } -extern asmlinkage int sys_poll(struct pollfd * ufds, unsigned int nfds, int timeout); - -asmlinkage int sys32_poll(u32 ufds, unsigned int nfds, int timeout) -{ - return sys_poll((struct pollfd *)A(ufds), nfds, timeout); -} - static inline int putstat(struct stat32 *ubuf, struct stat *kbuf) { if (put_user (kbuf->st_dev, &ubuf->st_dev) || @@ -1280,13 +1154,6 @@ asmlinkage int sys32_newfstat(unsigned int fd, u32 statbuf) return ret; } -extern asmlinkage int sys_readlink(const char * path, char * buf, int bufsiz); - -asmlinkage int sys32_readlink(u32 path, u32 buf, int bufsiz) -{ - return sys_readlink((const char *)A(path), (char *)A(buf), bufsiz); -} - extern asmlinkage int sys_sysfs(int option, ...); asmlinkage int sys32_sysfs(int option, ...) @@ -1312,42 +1179,162 @@ asmlinkage int sys32_sysfs(int option, ...) return ret; } -extern asmlinkage int sys_ustat(dev_t dev, struct ustat * ubuf); +struct ncp_mount_data32 { + int version; + unsigned int ncp_fd; + __kernel_uid_t32 mounted_uid; + __kernel_pid_t32 wdog_pid; + unsigned char mounted_vol[NCP_VOLNAME_LEN + 1]; + unsigned int time_out; + unsigned int retry_count; + unsigned int flags; + __kernel_uid_t32 uid; + __kernel_gid_t32 gid; + __kernel_mode_t32 file_mode; + __kernel_mode_t32 dir_mode; +}; -asmlinkage int sys32_ustat(dev_t dev, u32 ubuf) +static void *do_ncp_super_data_conv(void *raw_data) { - /* ustat is the same :)) */ - return sys_ustat(dev, (struct ustat *)A(ubuf)); + struct ncp_mount_data *n = (struct ncp_mount_data *)raw_data; + struct ncp_mount_data32 *n32 = (struct ncp_mount_data32 *)raw_data; + + n->dir_mode = n32->dir_mode; + n->file_mode = n32->file_mode; + n->gid = n32->gid; + n->uid = n32->uid; + memmove (n->mounted_vol, n32->mounted_vol, (sizeof (n32->mounted_vol) + 3 * sizeof (unsigned int))); + n->wdog_pid = n32->wdog_pid; + n->mounted_uid = n32->mounted_uid; + return raw_data; } -extern asmlinkage int sys_umount(char * name); +struct smb_mount_data32 { + int version; + unsigned int fd; + __kernel_uid_t32 mounted_uid; + struct sockaddr_in addr; + char server_name[17]; + char client_name[17]; + char service[64]; + char root_path[64]; + char username[64]; + char password[64]; + char domain[64]; + unsigned short max_xmit; + __kernel_uid_t32 uid; + __kernel_gid_t32 gid; + __kernel_mode_t32 file_mode; + __kernel_mode_t32 dir_mode; +}; -asmlinkage int sys32_umount(u32 name) +static void *do_smb_super_data_conv(void *raw_data) { - return sys_umount((char *)A(name)); -} + struct smb_mount_data *s = (struct smb_mount_data *)raw_data; + struct smb_mount_data32 *s32 = (struct smb_mount_data32 *)raw_data; -extern asmlinkage int sys_mount(char * dev_name, char * dir_name, char * type, - unsigned long new_flags, void *data); + s->dir_mode = s32->dir_mode; + s->file_mode = s32->file_mode; + s->gid = s32->gid; + s->uid = s32->uid; + memmove (&s->addr, &s32->addr, (((long)&s->uid) - ((long)&s->addr))); + s->mounted_uid = s32->mounted_uid; + return raw_data; +} -asmlinkage int sys32_mount(u32 dev_name, u32 dir_name, u32 type, u32 new_flags, u32 data) +static int copy_mount_stuff_to_kernel(const void *user, unsigned long *kernel) { - return sys_mount((char *)A(dev_name), (char *)A(dir_name), (char *)A(type), - (unsigned long)new_flags, (void *)A(data)); + int i; + unsigned long page; + struct vm_area_struct *vma; + + *kernel = 0; + if(!user) + return 0; + vma = find_vma(current->mm, (unsigned long)user); + if(!vma || (unsigned long)user < vma->vm_start) + return -EFAULT; + if(!(vma->vm_flags & VM_READ)) + return -EFAULT; + i = vma->vm_end - (unsigned long) user; + if(PAGE_SIZE <= (unsigned long) i) + i = PAGE_SIZE - 1; + if(!(page = __get_free_page(GFP_KERNEL))) + return -ENOMEM; + if(copy_from_user((void *) page, user, i)) { + free_page(page); + return -EFAULT; + } + *kernel = page; + return 0; } -extern asmlinkage int sys_syslog(int type, char * bug, int count); +extern asmlinkage int sys_mount(char * dev_name, char * dir_name, char * type, + unsigned long new_flags, void *data); + +#define SMBFS_NAME "smbfs" +#define NCPFS_NAME "ncpfs" -asmlinkage int sys32_syslog(int type, u32 bug, int count) +asmlinkage int sys32_mount(u32 dev_name, u32 dir_name, u32 type, u32 new_flags, u32 data) { - return sys_syslog(type, (char *)A(bug), count); -} + unsigned long type_page; + int err, is_smb, is_ncp; -extern asmlinkage int sys_personality(unsigned long personality); + if(!suser()) + return -EPERM; + is_smb = is_ncp = 0; + err = copy_mount_stuff_to_kernel((const void *)A(type), &type_page); + if(err) + return err; + if(type_page) { + is_smb = !strcmp((char *)type_page, SMBFS_NAME); + is_ncp = !strcmp((char *)type_page, NCPFS_NAME); + } + if(!is_smb && !is_ncp) { + if(type_page) + free_page(type_page); + return sys_mount((char *)A(dev_name), (char *)A(dir_name), + (char *)A(type), (unsigned long)new_flags, + (void *)A(data)); + } else { + unsigned long dev_page, dir_page, data_page; + int old_fs; -asmlinkage int sys32_personality(u32 personality) -{ - return sys_personality((unsigned long)personality); + err = copy_mount_stuff_to_kernel((const void *)A(dev_name), &dev_page); + if(err) + goto out; + err = copy_mount_stuff_to_kernel((const void *)A(dir_name), &dir_page); + if(err) + goto dev_out; + err = copy_mount_stuff_to_kernel((const void *)A(data), &data_page); + if(err) + goto dir_out; + if(is_ncp) + do_ncp_super_data_conv((void *)data_page); + else if(is_smb) + do_smb_super_data_conv((void *)data_page); + else + panic("Tell DaveM he fucked up..."); + old_fs = get_fs(); + set_fs(KERNEL_DS); + err = sys_mount((char *)dev_page, (char *)dir_page, + (char *)type_page, (unsigned long)new_flags, + (void *)data_page); + set_fs(old_fs); + + if(data_page) + free_page(data_page); + dir_out: + if(dir_page) + free_page(dir_page); + dev_out: + if(dev_page) + free_page(dev_page); + out: + if(type_page) + free_page(type_page); + return err; + } } struct rusage32 { @@ -1416,13 +1403,6 @@ asmlinkage int sys32_wait4(__kernel_pid_t32 pid, u32 stat_addr, int options, u32 } } -extern asmlinkage int sys_waitpid(pid_t pid,unsigned int * stat_addr, int options); - -asmlinkage int sys32_waitpid(__kernel_pid_t32 pid, u32 stat_addr, int options) -{ - return sys_waitpid(pid, (unsigned int *)A(stat_addr), options); -} - struct sysinfo32 { s32 uptime; u32 loads[3]; @@ -1462,46 +1442,6 @@ asmlinkage int sys32_sysinfo(u32 info) return ret; } -extern asmlinkage int sys_getitimer(int which, struct itimerval *value); - -asmlinkage int sys32_getitimer(int which, u32 value) -{ - /* itimerval is the same :)) */ - return sys_getitimer(which, (struct itimerval *)A(value)); -} - -extern asmlinkage int sys_setitimer(int which, struct itimerval *value, - struct itimerval *ovalue); - -asmlinkage int sys32_setitimer(int which, u32 value, u32 ovalue) -{ - return sys_setitimer(which, (struct itimerval *)A(value), - (struct itimerval *)A(ovalue)); -} - -extern asmlinkage int sys_sched_setscheduler(pid_t pid, int policy, - struct sched_param *param); - -asmlinkage int sys32_sched_setscheduler(__kernel_pid_t32 pid, int policy, u32 param) -{ - /* sched_param is the same :)) */ - return sys_sched_setscheduler(pid, policy, (struct sched_param *)A(param)); -} - -extern asmlinkage int sys_sched_setparam(pid_t pid, struct sched_param *param); - -asmlinkage int sys32_sched_setparam(__kernel_pid_t32 pid, u32 param) -{ - return sys_sched_setparam(pid, (struct sched_param *)A(param)); -} - -extern asmlinkage int sys_sched_getparam(pid_t pid, struct sched_param *param); - -asmlinkage int sys32_sched_getparam(__kernel_pid_t32 pid, u32 param) -{ - return sys_sched_getparam(pid, (struct sched_param *)A(param)); -} - struct timespec32 { s32 tv_sec; s32 tv_nsec; @@ -1577,25 +1517,29 @@ asmlinkage int sys32_sigpending(u32 set) return ret; } -extern asmlinkage unsigned long sys_signal(int signum, __sighandler_t handler); +extern asmlinkage int sys_setreuid(uid_t ruid, uid_t euid); -asmlinkage unsigned long sys32_signal(int signum, u32 handler) +asmlinkage int sys32_setreuid(__kernel_uid_t32 ruid, __kernel_uid_t32 euid) { - return sys_signal(signum, (__sighandler_t)A(handler)); -} - -extern asmlinkage int sys_reboot(int magic1, int magic2, int cmd, void * arg); + uid_t sruid, seuid; -asmlinkage int sys32_reboot(int magic1, int magic2, int cmd, u32 arg) -{ - return sys_reboot(magic1, magic2, cmd, (void *)A(arg)); + sruid = (ruid == (__kernel_uid_t32)-1) ? ((uid_t)-1) : ((uid_t)ruid); + seuid = (euid == (__kernel_uid_t32)-1) ? ((uid_t)-1) : ((uid_t)euid); + return sys_setreuid(sruid, seuid); } -extern asmlinkage int sys_acct(const char *name); +extern asmlinkage int sys_setresuid(uid_t ruid, uid_t euid, uid_t suid); -asmlinkage int sys32_acct(u32 name) +asmlinkage int sys32_setresuid(__kernel_uid_t32 ruid, + __kernel_uid_t32 euid, + __kernel_uid_t32 suid) { - return sys_acct((const char *)A(name)); + uid_t sruid, seuid, ssuid; + + sruid = (ruid == (__kernel_uid_t32)-1) ? ((uid_t)-1) : ((uid_t)ruid); + seuid = (euid == (__kernel_uid_t32)-1) ? ((uid_t)-1) : ((uid_t)euid); + ssuid = (suid == (__kernel_uid_t32)-1) ? ((uid_t)-1) : ((uid_t)suid); + return sys_setresuid(sruid, seuid, ssuid); } extern asmlinkage int sys_getresuid(uid_t *ruid, uid_t *euid, uid_t *suid); @@ -1654,7 +1598,7 @@ asmlinkage int sys32_getgroups(int gidsetsize, u32 grouplist) set_fs (KERNEL_DS); ret = sys_getgroups(gidsetsize, gl); set_fs (old_fs); - if (ret > 0 && ret <= NGROUPS) + if (gidsetsize && ret > 0 && ret <= NGROUPS) for (i = 0; i < ret; i++, grouplist += sizeof(__kernel_gid_t32)) if (__put_user (gl[i], (__kernel_gid_t32 *)A(grouplist))) return -EFAULT; @@ -1680,41 +1624,8 @@ asmlinkage int sys32_setgroups(int gidsetsize, u32 grouplist) return ret; } -extern asmlinkage int sys_newuname(struct new_utsname * name); - -asmlinkage int sys32_newuname(u32 name) -{ - /* utsname is the same :)) */ - return sys_newuname((struct new_utsname *)A(name)); -} - -extern asmlinkage int sys_olduname(struct oldold_utsname * name); - -asmlinkage int sys32_olduname(u32 name) -{ - return sys_olduname((struct oldold_utsname *)A(name)); -} - -extern asmlinkage int sys_sethostname(char *name, int len); - -asmlinkage int sys32_sethostname(u32 name, int len) -{ - return sys_sethostname((char *)A(name), len); -} - -extern asmlinkage int sys_gethostname(char *name, int len); - -asmlinkage int sys32_gethostname(u32 name, int len) -{ - return sys_gethostname((char *)A(name), len); -} - -extern asmlinkage int sys_setdomainname(char *name, int len); - -asmlinkage int sys32_setdomainname(u32 name, int len) -{ - return sys_setdomainname((char *)A(name), len); -} +#define RLIM_INFINITY32 0x7fffffff +#define RESOURCE32(x) ((x > RLIM_INFINITY32) ? RLIM_INFINITY32 : x) struct rlimit32 { s32 rlim_cur; @@ -1733,8 +1644,8 @@ asmlinkage int sys32_getrlimit(unsigned int resource, u32 rlim) ret = sys_getrlimit(resource, &r); set_fs (old_fs); if (!ret && ( - put_user (r.rlim_cur, &(((struct rlimit32 *)A(rlim))->rlim_cur)) || - __put_user (r.rlim_max, &(((struct rlimit32 *)A(rlim))->rlim_max)))) + put_user (RESOURCE32(r.rlim_cur), &(((struct rlimit32 *)A(rlim))->rlim_cur)) || + __put_user (RESOURCE32(r.rlim_max), &(((struct rlimit32 *)A(rlim))->rlim_max)))) return -EFAULT; return ret; } @@ -1751,6 +1662,10 @@ asmlinkage int sys32_setrlimit(unsigned int resource, u32 rlim) if (get_user (r.rlim_cur, &(((struct rlimit32 *)A(rlim))->rlim_cur)) || __get_user (r.rlim_max, &(((struct rlimit32 *)A(rlim))->rlim_max))) return -EFAULT; + if (r.rlim_cur == RLIM_INFINITY32) + r.rlim_cur = RLIM_INFINITY; + if (r.rlim_max == RLIM_INFINITY32) + r.rlim_max = RLIM_INFINITY; set_fs (KERNEL_DS); ret = sys_setrlimit(resource, &r); set_fs (old_fs); @@ -1772,28 +1687,6 @@ asmlinkage int sys32_getrusage(int who, u32 ru) return ret; } -extern asmlinkage int sys_time(int * tloc); - -asmlinkage int sys32_time(u32 tloc) -{ - return sys_time((int *)A(tloc)); -} - -extern asmlinkage int sys_gettimeofday(struct timeval *tv, struct timezone *tz); - -asmlinkage int sys32_gettimeofday(u32 tv, u32 tz) -{ - /* both timeval and timezone are ok :)) */ - return sys_gettimeofday((struct timeval *)A(tv), (struct timezone *)A(tz)); -} - -extern asmlinkage int sys_settimeofday(struct timeval *tv, struct timezone *tz); - -asmlinkage int sys32_settimeofday(u32 tv, u32 tz) -{ - return sys_settimeofday((struct timeval *)A(tv), (struct timezone *)A(tz)); -} - struct timex32 { unsigned int modes; s32 offset; @@ -1865,170 +1758,6 @@ asmlinkage int sys32_adjtimex(u32 txc_p) return ret; } -extern asmlinkage int sys_msync(unsigned long start, size_t len, int flags); - -asmlinkage int sys32_msync(u32 start, __kernel_size_t32 len, int flags) -{ - return sys_msync((unsigned long)start, (size_t)len, flags); -} - -extern asmlinkage int sys_mlock(unsigned long start, size_t len); - -asmlinkage int sys32_mlock(u32 start, __kernel_size_t32 len) -{ - return sys_mlock((unsigned long)start, (size_t)len); -} - -extern asmlinkage int sys_munlock(unsigned long start, size_t len); - -asmlinkage int sys32_munlock(u32 start, __kernel_size_t32 len) -{ - return sys_munlock((unsigned long)start, (size_t)len); -} - -extern asmlinkage unsigned long sys_brk(unsigned long brk); - -asmlinkage unsigned long sparc32_brk(u32 brk) -{ - return sys_brk((unsigned long)brk); -} - -extern asmlinkage int sys_munmap(unsigned long addr, size_t len); - -asmlinkage int sys32_munmap(u32 addr, __kernel_size_t32 len) -{ - return sys_munmap((unsigned long)addr, (size_t)len); -} - -extern asmlinkage int sys_mprotect(unsigned long start, size_t len, unsigned long prot); - -asmlinkage int sys32_mprotect(u32 start, __kernel_size_t32 len, u32 prot) -{ - return sys_mprotect((unsigned long)start, (size_t)len, (unsigned long)prot); -} - -extern asmlinkage unsigned long sys_mremap(unsigned long addr, unsigned long old_len, - unsigned long new_len, unsigned long flags); - -asmlinkage unsigned long sys32_mremap(u32 addr, u32 old_len, u32 new_len, u32 flags) -{ - return sys_mremap((unsigned long)addr, (unsigned long)old_len, - (unsigned long)new_len, (unsigned long)flags); -} - -extern asmlinkage int sys_swapoff(const char * specialfile); - -asmlinkage int sys32_swapoff(u32 specialfile) -{ - return sys_swapoff((const char *)A(specialfile)); -} - -extern asmlinkage int sys_swapon(const char * specialfile, int swap_flags); - -asmlinkage int sys32_swapon(u32 specialfile, int swap_flags) -{ - return sys_swapon((const char *)A(specialfile), swap_flags); -} - -extern asmlinkage int sys_bind(int fd, struct sockaddr *umyaddr, int addrlen); - -asmlinkage inline int sys32_bind(int fd, u32 umyaddr, int addrlen) -{ - /* sockaddr is the same :)) */ - return sys_bind(fd, (struct sockaddr *)A(umyaddr), addrlen); -} - -extern asmlinkage int sys_accept(int fd, struct sockaddr *upeer_sockaddr, - int *upeer_addrlen); - -asmlinkage inline int sys32_accept(int fd, u32 upeer_sockaddr, u32 upeer_addrlen) -{ - return sys_accept(fd, (struct sockaddr *)A(upeer_sockaddr), - (int *)A(upeer_addrlen)); -} - -extern asmlinkage int sys_connect(int fd, struct sockaddr *uservaddr, int addrlen); - -asmlinkage inline int sys32_connect(int fd, u32 uservaddr, int addrlen) -{ - return sys_connect(fd, (struct sockaddr *)A(uservaddr), addrlen); -} - -extern asmlinkage int sys_getsockname(int fd, struct sockaddr *usockaddr, - int *usockaddr_len); - -asmlinkage int sys32_getsockname(int fd, u32 usockaddr, u32 usockaddr_len) -{ - return sys_getsockname(fd, (struct sockaddr *)A(usockaddr), - (int *)A(usockaddr_len)); -} - -extern asmlinkage int sys_getpeername(int fd, struct sockaddr *usockaddr, - int *usockaddr_len); - -asmlinkage int sys32_getpeername(int fd, u32 usockaddr, u32 usockaddr_len) -{ - return sys_getpeername(fd, (struct sockaddr *)A(usockaddr), - (int *)A(usockaddr_len)); -} - -extern asmlinkage int sys_send(int fd, void * buff, size_t len, unsigned flags); - -asmlinkage inline int sys32_send(int fd, u32 buff, - __kernel_size_t32 len, unsigned flags) -{ - return sys_send(fd, (void *)A(buff), (size_t)len, flags); -} - -extern asmlinkage int sys_sendto(int fd, void * buff, size_t len, unsigned flags, - struct sockaddr *addr, int addr_len); - -asmlinkage inline int sys32_sendto(int fd, u32 buff, __kernel_size_t32 len, - unsigned flags, u32 addr, int addr_len) -{ - return sys_sendto(fd, (void *)A(buff), (size_t)len, flags, - (struct sockaddr *)A(addr), addr_len); -} - -extern asmlinkage int sys_recv(int fd, void * ubuf, size_t size, unsigned flags); - -asmlinkage inline int sys32_recv(int fd, u32 ubuf, - __kernel_size_t32 size, unsigned flags) -{ - return sys_recv(fd, (void *)A(ubuf), (size_t)size, flags); -} - -extern asmlinkage int sys_recvfrom(int fd, void * ubuf, size_t size, unsigned flags, - struct sockaddr *addr, int *addr_len); - -asmlinkage inline int sys32_recvfrom(int fd, u32 ubuf, __kernel_size_t32 size, - unsigned flags, u32 addr, u32 addr_len) -{ - return sys_recvfrom(fd, (void *)A(ubuf), (size_t)size, flags, - (struct sockaddr *)A(addr), (int *)A(addr_len)); -} - -extern asmlinkage int sys_setsockopt(int fd, int level, int optname, - char *optval, int optlen); - -asmlinkage inline int sys32_setsockopt(int fd, int level, int optname, - u32 optval, int optlen) -{ - /* XXX handle ip_fw32->ip_fw conversion for IP firewalling and accounting. - Do it using some macro in ip_sockglue.c - Other optval arguments are mostly just ints or 32<->64bit transparent */ - return sys_setsockopt(fd, level, optname, (char *)A(optval), optlen); -} - -extern asmlinkage int sys_getsockopt(int fd, int level, int optname, - char *optval, int *optlen); - -asmlinkage inline int sys32_getsockopt(int fd, int level, int optname, - u32 optval, u32 optlen) -{ - return sys_getsockopt(fd, level, optname, (char *)A(optval), (int *)A(optlen)); -} - /* XXX This really belongs in some header file... -DaveM */ #define MAX_SOCK_ADDR 128 /* 108 for Unix domain - 16 for IP, 16 for IPX, @@ -2052,11 +1781,11 @@ extern __inline__ struct socket *sockfd_lookup(int fd, int *err) return NULL; } - inode = file->f_inode; + inode = file->f_dentry->d_inode; if (!inode || !inode->i_sock || !socki_lookup(inode)) { *err = -ENOTSOCK; - fput(file,inode); + fput(file); return NULL; } @@ -2065,7 +1794,7 @@ extern __inline__ struct socket *sockfd_lookup(int fd, int *err) extern __inline__ void sockfd_put(struct socket *sock) { - fput(sock->file,sock->inode); + fput(sock->file); } struct msghdr32 { @@ -2293,6 +2022,24 @@ static unsigned char nargs[18]={AL(0),AL(3),AL(3),AL(3),AL(2),AL(3), AL(6),AL(2),AL(5),AL(5),AL(3),AL(3)}; #undef AL +extern asmlinkage int sys32_bind(int fd, u32 umyaddr, int addrlen); +extern asmlinkage int sys32_connect(int fd, u32 uservaddr, int addrlen); +extern asmlinkage int sys32_accept(int fd, u32 upeer_sockaddr, u32 upeer_addrlen); +extern asmlinkage int sys32_getsockname(int fd, u32 usockaddr, u32 usockaddr_len); +extern asmlinkage int sys32_getpeername(int fd, u32 usockaddr, u32 usockaddr_len); +extern asmlinkage int sys32_send(int fd, u32 buff, __kernel_size_t32 len, + unsigned flags); +extern asmlinkage int sys32_sendto(int fd, u32 buff, __kernel_size_t32 len, + unsigned flags, u32 addr, int addr_len); +extern asmlinkage int sys32_recv(int fd, u32 ubuf, __kernel_size_t32 size, + unsigned flags); +extern asmlinkage int sys32_recvfrom(int fd, u32 ubuf, __kernel_size_t32 size, + unsigned flags, u32 addr, u32 addr_len); +extern asmlinkage int sys32_setsockopt(int fd, int level, int optname, + u32 optval, int optlen); +extern asmlinkage int sys32_getsockopt(int fd, int level, int optname, + u32 optval, u32 optlen); + extern asmlinkage int sys_socket(int family, int type, int protocol); extern asmlinkage int sys_socketpair(int family, int type, int protocol, int usockvec[2]); @@ -2389,7 +2136,7 @@ asmlinkage int sparc32_sigaction (int signum, u32 action, u32 oldaction) old_sa.sa_mask = (sigset_t32)(p->sa_mask); old_sa.sa_flags = (unsigned)(p->sa_flags); old_sa.sa_restorer = (unsigned)(u64)(p->sa_restorer); - if (copy_to_user(A(oldaction), p, sizeof(struct sigaction32))) + if (copy_to_user(A(oldaction), &old_sa, sizeof(struct sigaction32))) goto out; } @@ -2407,14 +2154,6 @@ out: return err; } -extern asmlinkage int sys_nfsservctl(int cmd, void *argp, void *resp); - -asmlinkage int sys32_nfsservctl(int cmd, u32 argp, u32 resp) -{ - /* XXX handle argp and resp args */ - return sys_nfsservctl(cmd, (void *)A(argp), (void *)A(resp)); -} - /* * count32() counts the number of arguments/envelopes */ @@ -2485,25 +2224,33 @@ static inline int do_execve32(char * filename, u32 * argv, u32 * envp, struct pt_regs * regs) { struct linux_binprm bprm; + struct dentry * dentry; int retval; int i; bprm.p = PAGE_SIZE*MAX_ARG_PAGES-sizeof(void *); for (i=0 ; i<MAX_ARG_PAGES ; i++) /* clear page-table */ bprm.page[i] = 0; - retval = open_namei(filename, 0, 0, &bprm.inode, NULL); - if (retval) + + dentry = open_namei(filename, 0, 0); + retval = PTR_ERR(dentry); + if (IS_ERR(dentry)) return retval; + + bprm.dentry = dentry; bprm.filename = filename; bprm.sh_bang = 0; bprm.java = 0; bprm.loader = 0; bprm.exec = 0; - bprm.dont_iput = 0; - if ((bprm.argc = count32(argv)) < 0) + if ((bprm.argc = count32(argv)) < 0) { + dput(dentry); return bprm.argc; - if ((bprm.envc = count32(envp)) < 0) + } + if ((bprm.envc = count32(envp)) < 0) { + dput(dentry); return bprm.envc; + } retval = prepare_binprm(&bprm); @@ -2523,8 +2270,9 @@ do_execve32(char * filename, u32 * argv, u32 * envp, struct pt_regs * regs) return retval; /* Something went wrong, return the inode and free the argument pages*/ - if(!bprm.dont_iput) - iput(bprm.inode); + if(bprm.dentry) + dput(bprm.dentry); + for (i=0 ; i<MAX_ARG_PAGES ; i++) free_page(bprm.page[i]); return(retval); @@ -2543,81 +2291,231 @@ asmlinkage int sparc32_execve(struct pt_regs *regs) if((u32)regs->u_regs[UREG_G1] == 0) base = 1; - error = getname((char *)(unsigned long)(u32)regs->u_regs[base + UREG_I0], &filename); - if(error) - return error; + lock_kernel(); + filename = getname((char *)(unsigned long)(u32)regs->u_regs[base + UREG_I0]); + error = PTR_ERR(filename); + if(IS_ERR(filename)) + goto out; error = do_execve32(filename, (u32 *)A((u32)regs->u_regs[base + UREG_I1]), (u32 *)A((u32)regs->u_regs[base + UREG_I2]), regs); putname(filename); + + if(!error) { + fprs_write(0); + regs->fprs = 0; + } +out: + unlock_kernel(); return error; } -/* Modules will be supported with 64bit modutils only */ -asmlinkage int sys32_no_modules(void) +#ifdef CONFIG_MODULES + +extern asmlinkage unsigned long sys_create_module(const char *name_user, size_t size); + +asmlinkage unsigned long sys32_create_module(u32 name_user, __kernel_size_t32 size) { - return -ENOSYS; + return sys_create_module((const char *)A(name_user), (size_t)size); } -struct ncp_mount_data32 { - int version; - unsigned int ncp_fd; - __kernel_uid_t32 mounted_uid; - __kernel_pid_t32 wdog_pid; - unsigned char mounted_vol[NCP_VOLNAME_LEN + 1]; - unsigned int time_out; - unsigned int retry_count; - unsigned int flags; - __kernel_uid_t32 uid; - __kernel_gid_t32 gid; - __kernel_mode_t32 file_mode; - __kernel_mode_t32 dir_mode; -}; +extern asmlinkage int sys_init_module(const char *name_user, struct module *mod_user); -void *do_ncp_super_data_conv(void *raw_data) +/* Hey, when you're trying to init module, take time and prepare us a nice 64bit + * module structure, even if from 32bit modutils... Why to pollute kernel... :)) + */ +asmlinkage int sys32_init_module(u32 nameuser, u32 mod_user) { - struct ncp_mount_data *n = (struct ncp_mount_data *)raw_data; - struct ncp_mount_data32 *n32 = (struct ncp_mount_data32 *)raw_data; + return sys_init_module((const char *)A(nameuser), (struct module *)A(mod_user)); +} - n->dir_mode = n32->dir_mode; - n->file_mode = n32->file_mode; - n->gid = n32->gid; - n->uid = n32->uid; - memmove (n->mounted_vol, n32->mounted_vol, (sizeof (n32->mounted_vol) + 3 * sizeof (unsigned int))); - n->wdog_pid = n32->wdog_pid; - n->mounted_uid = n32->mounted_uid; - return raw_data; +extern asmlinkage int sys_delete_module(const char *name_user); + +asmlinkage int sys32_delete_module(u32 name_user) +{ + return sys_delete_module((const char *)A(name_user)); } -struct smb_mount_data32 { - int version; - unsigned int fd; - __kernel_uid_t32 mounted_uid; - struct sockaddr_in addr; - char server_name[17]; - char client_name[17]; - char service[64]; - char root_path[64]; - char username[64]; - char password[64]; - char domain[64]; - unsigned short max_xmit; - __kernel_uid_t32 uid; - __kernel_gid_t32 gid; - __kernel_mode_t32 file_mode; - __kernel_mode_t32 dir_mode; +struct module_info32 { + u32 addr; + u32 size; + u32 flags; + s32 usecount; }; -void *do_smb_super_data_conv(void *raw_data) +extern asmlinkage int sys_query_module(const char *name_user, int which, char *buf, size_t bufsize, size_t *ret); + +asmlinkage int sys32_query_module(u32 name_user, int which, u32 buf, __kernel_size_t32 bufsize, u32 retv) { - struct smb_mount_data *s = (struct smb_mount_data *)raw_data; - struct smb_mount_data32 *s32 = (struct smb_mount_data32 *)raw_data; + char *buff; + unsigned long old_fs = get_fs(); + size_t val; + int ret, i, j; + unsigned long *p; + char *usernam = NULL; + int bufsiz = bufsize; + struct module_info mi; + + switch (which) { + case 0: return sys_query_module ((const char *)A(name_user), which, (char *)A(buf), (size_t)bufsize, (size_t *)A(retv)); + case QM_SYMBOLS: + bufsiz <<= 1; + case QM_MODULES: + case QM_REFS: + case QM_DEPS: + if (name_user && (ret = getname32 (name_user, &usernam))) + return ret; + buff = kmalloc (bufsiz, GFP_KERNEL); + if (!buff) { + if (name_user) putname32 (usernam); + return -ENOMEM; + } +qmsym_toshort: + set_fs (KERNEL_DS); + ret = sys_query_module (usernam, which, buff, bufsiz, &val); + set_fs (old_fs); + if (which != QM_SYMBOLS) { + if (ret == -ENOSPC || !ret) { + if (put_user (val, (__kernel_size_t32 *)A(retv))) + ret = -EFAULT; + } + if (!ret) { + if (copy_to_user ((char *)A(buf), buff, bufsize)) + ret = -EFAULT; + } + } else { + if (ret == -ENOSPC) { + if (put_user (2 * val, (__kernel_size_t32 *)A(retv))) + ret = -EFAULT; + } + p = (unsigned long *)buff; + if (!ret) { + if (put_user (val, (__kernel_size_t32 *)A(retv))) + ret = -EFAULT; + } + if (!ret) { + j = val * 8; + for (i = 0; i < val; i++, p += 2) { + if (bufsize < (2 * sizeof (u32))) { + bufsiz = 0; + goto qmsym_toshort; + } + if (put_user (p[0], (u32 *)A(buf)) || + __put_user (p[1] - j, (((u32 *)A(buf))+1))) { + ret = -EFAULT; + break; + } + bufsize -= (2 * sizeof (u32)); + buf += (2 * sizeof (u32)); + } + } + if (!ret && val) { + char *strings = buff + ((unsigned long *)buff)[1]; + j = *(p - 1) - ((unsigned long *)buff)[1]; + j = j + strlen (buff + j) + 1; + if (bufsize < j) { + bufsiz = 0; + goto qmsym_toshort; + } + if (copy_to_user ((char *)A(buf), strings, j)) + ret = -EFAULT; + } + } + kfree (buff); + if (name_user) putname32 (usernam); + return ret; + case QM_INFO: + if (name_user && (ret = getname32 (name_user, &usernam))) + return ret; + set_fs (KERNEL_DS); + ret = sys_query_module (usernam, which, (char *)&mi, sizeof (mi), &val); + set_fs (old_fs); + if (!ret) { + if (put_user (sizeof (struct module_info32), (__kernel_size_t32 *)A(retv))) + ret = -EFAULT; + else if (bufsize < sizeof (struct module_info32)) + ret = -ENOSPC; + } + if (!ret) { + if (put_user (mi.addr, &(((struct module_info32 *)A(buf))->addr)) || + __put_user (mi.size, &(((struct module_info32 *)A(buf))->size)) || + __put_user (mi.flags, &(((struct module_info32 *)A(buf))->flags)) || + __put_user (mi.usecount, &(((struct module_info32 *)A(buf))->usecount))) + ret = -EFAULT; + } + if (name_user) putname32 (usernam); + return ret; + default: + return -EINVAL; + } +} - s->dir_mode = s32->dir_mode; - s->file_mode = s32->file_mode; - s->gid = s32->gid; - s->uid = s32->uid; - memmove (&s->addr, &s32->addr, (((long)&s->uid) - ((long)&s->addr))); - s->mounted_uid = s32->mounted_uid; - return raw_data; +struct kernel_sym32 { + u32 value; + char name[60]; +}; + +extern asmlinkage int sys_get_kernel_syms(struct kernel_sym *table); + +asmlinkage int sys32_get_kernel_syms(u32 table) +{ + int len, i; + struct kernel_sym *tbl; + unsigned long old_fs; + + len = sys_get_kernel_syms(NULL); + if (!table) return len; + tbl = kmalloc (len * sizeof (struct kernel_sym), GFP_KERNEL); + if (!tbl) return -ENOMEM; + old_fs = get_fs(); + set_fs (KERNEL_DS); + sys_get_kernel_syms(tbl); + set_fs (old_fs); + for (i = 0; i < len; i++, table += sizeof (struct kernel_sym32)) { + if (put_user (tbl[i].value, &(((struct kernel_sym32 *)A(table))->value)) || + copy_to_user (((struct kernel_sym32 *)A(table))->name, tbl[i].name, 60)) + break; + } + kfree (tbl); + return i; +} + +#else /* CONFIG_MODULES */ + +asmlinkage unsigned long +sys_create_module(const char *name_user, size_t size) +{ + return -ENOSYS; +} + +asmlinkage int +sys_init_module(const char *name_user, struct module *mod_user) +{ + return -ENOSYS; } + +asmlinkage int +sys_delete_module(const char *name_user) +{ + return -ENOSYS; +} + +asmlinkage int +sys_query_module(const char *name_user, int which, char *buf, size_t bufsize, + size_t *ret) +{ + /* Let the program know about the new interface. Not that + it'll do them much good. */ + if (which == 0) + return 0; + + return -ENOSYS; +} + +asmlinkage int +sys_get_kernel_syms(struct kernel_sym *table) +{ + return -ENOSYS; +} + +#endif /* CONFIG_MODULES */ |