-
-#if defined(CONFIG_NFSD) || defined(CONFIG_NFSD_MODULE)
-/* Stuff for NFS server syscalls... */
-struct nfsctl_svc32 {
- u16 svc32_port;
- s32 svc32_nthreads;
-};
-
-struct nfsctl_client32 {
- s8 cl32_ident[NFSCLNT_IDMAX+1];
- s32 cl32_naddr;
- struct in_addr cl32_addrlist[NFSCLNT_ADDRMAX];
- s32 cl32_fhkeytype;
- s32 cl32_fhkeylen;
- u8 cl32_fhkey[NFSCLNT_KEYMAX];
-};
-
-struct nfsctl_export32 {
- s8 ex32_client[NFSCLNT_IDMAX+1];
- s8 ex32_path[NFS_MAXPATHLEN+1];
- compat_dev_t ex32_dev;
- compat_ino_t ex32_ino;
- s32 ex32_flags;
- compat_pid_t ex32_anon_uid;
- compat_gid_t ex32_anon_gid;
-};
-
-struct nfsctl_fdparm32 {
- struct sockaddr gd32_addr;
- s8 gd32_path[NFS_MAXPATHLEN+1];
- s32 gd32_version;
-};
-
-struct nfsctl_fsparm32 {
- struct sockaddr gd32_addr;
- s8 gd32_path[NFS_MAXPATHLEN+1];
- s32 gd32_maxlen;
-};
-
-struct nfsctl_arg32 {
- s32 ca32_version; /* safeguard */
- union {
- struct nfsctl_svc32 u32_svc;
- struct nfsctl_client32 u32_client;
- struct nfsctl_export32 u32_export;
- struct nfsctl_fdparm32 u32_getfd;
- struct nfsctl_fsparm32 u32_getfs;
- } u;
-#define ca32_svc u.u32_svc
-#define ca32_client u.u32_client
-#define ca32_export u.u32_export
-#define ca32_getfd u.u32_getfd
-#define ca32_getfs u.u32_getfs
-};
-
-union nfsctl_res32 {
- __u8 cr32_getfh[NFS_FHSIZE];
- struct knfsd_fh cr32_getfs;
-};
-
-static int nfs_svc32_trans(struct nfsctl_arg *karg, struct nfsctl_arg32 *arg32)
-{
- int err;
-
- err = get_user(karg->ca_version, &arg32->ca32_version);
- err |= __get_user(karg->ca_svc.svc_port, &arg32->ca32_svc.svc32_port);
- err |= __get_user(karg->ca_svc.svc_nthreads, &arg32->ca32_svc.svc32_nthreads);
- return err;
-}
-
-static int nfs_clnt32_trans(struct nfsctl_arg *karg, struct nfsctl_arg32 *arg32)
-{
- int err;
-
- err = get_user(karg->ca_version, &arg32->ca32_version);
- err |= copy_from_user(&karg->ca_client.cl_ident[0],
- &arg32->ca32_client.cl32_ident[0],
- NFSCLNT_IDMAX);
- err |= __get_user(karg->ca_client.cl_naddr, &arg32->ca32_client.cl32_naddr);
- err |= copy_from_user(&karg->ca_client.cl_addrlist[0],
- &arg32->ca32_client.cl32_addrlist[0],
- (sizeof(struct in_addr) * NFSCLNT_ADDRMAX));
- err |= __get_user(karg->ca_client.cl_fhkeytype,
- &arg32->ca32_client.cl32_fhkeytype);
- err |= __get_user(karg->ca_client.cl_fhkeylen,
- &arg32->ca32_client.cl32_fhkeylen);
- err |= copy_from_user(&karg->ca_client.cl_fhkey[0],
- &arg32->ca32_client.cl32_fhkey[0],
- NFSCLNT_KEYMAX);
- return err;
-}
-
-static int nfs_exp32_trans(struct nfsctl_arg *karg, struct nfsctl_arg32 *arg32)
-{
- int err;
-
- err = get_user(karg->ca_version, &arg32->ca32_version);
- err |= copy_from_user(&karg->ca_export.ex_client[0],
- &arg32->ca32_export.ex32_client[0],
- NFSCLNT_IDMAX);
- err |= copy_from_user(&karg->ca_export.ex_path[0],
- &arg32->ca32_export.ex32_path[0],
- NFS_MAXPATHLEN);
- err |= __get_user(karg->ca_export.ex_dev,
- &arg32->ca32_export.ex32_dev);
- err |= __get_user(karg->ca_export.ex_ino,
- &arg32->ca32_export.ex32_ino);
- err |= __get_user(karg->ca_export.ex_flags,
- &arg32->ca32_export.ex32_flags);
- err |= __get_user(karg->ca_export.ex_anon_uid,
- &arg32->ca32_export.ex32_anon_uid);
- err |= __get_user(karg->ca_export.ex_anon_gid,
- &arg32->ca32_export.ex32_anon_gid);
- SET_UID(karg->ca_export.ex_anon_uid, karg->ca_export.ex_anon_uid);
- SET_GID(karg->ca_export.ex_anon_gid, karg->ca_export.ex_anon_gid);
- return err;
-}
-
-
-static int nfs_getfd32_trans(struct nfsctl_arg *karg, struct nfsctl_arg32 *arg32)
-{
- int err;
-
- err = get_user(karg->ca_version, &arg32->ca32_version);
- err |= copy_from_user(&karg->ca_getfd.gd_addr,
- &arg32->ca32_getfd.gd32_addr,
- (sizeof(struct sockaddr)));
- err |= copy_from_user(&karg->ca_getfd.gd_path,
- &arg32->ca32_getfd.gd32_path,
- (NFS_MAXPATHLEN+1));
- err |= get_user(karg->ca_getfd.gd_version,
- &arg32->ca32_getfd.gd32_version);
- return err;
-}
-
-static int nfs_getfs32_trans(struct nfsctl_arg *karg, struct nfsctl_arg32 *arg32)
-{
- int err;
-
- err = get_user(karg->ca_version, &arg32->ca32_version);
- err |= copy_from_user(&karg->ca_getfs.gd_addr,
- &arg32->ca32_getfs.gd32_addr,
- (sizeof(struct sockaddr)));
- err |= copy_from_user(&karg->ca_getfs.gd_path,
- &arg32->ca32_getfs.gd32_path,
- (NFS_MAXPATHLEN+1));
- err |= get_user(karg->ca_getfs.gd_maxlen,
- &arg32->ca32_getfs.gd32_maxlen);
- return err;
-}
-
-/* This really doesn't need translations, we are only passing
- * back a union which contains opaque nfs file handle data.
- */
-static int nfs_getfh32_res_trans(union nfsctl_res *kres, union nfsctl_res32 *res32)
-{
- return copy_to_user(res32, kres, sizeof(*res32)) ? -EFAULT : 0;
-}
-
-long asmlinkage sys32_nfsservctl(int cmd, struct nfsctl_arg32 *arg32, union nfsctl_res32 *res32)
-{
- struct nfsctl_arg *karg = NULL;
- union nfsctl_res *kres = NULL;
- mm_segment_t oldfs;
- int err;
-
- karg = kmalloc(sizeof(*karg), GFP_USER);
- if(!karg)
- return -ENOMEM;
- if(res32) {
- kres = kmalloc(sizeof(*kres), GFP_USER);
- if(!kres) {
- kfree(karg);
- return -ENOMEM;
- }
- }
- switch(cmd) {
- case NFSCTL_SVC:
- err = nfs_svc32_trans(karg, arg32);
- break;
- case NFSCTL_ADDCLIENT:
- err = nfs_clnt32_trans(karg, arg32);
- break;
- case NFSCTL_DELCLIENT:
- err = nfs_clnt32_trans(karg, arg32);
- break;
- case NFSCTL_EXPORT:
- case NFSCTL_UNEXPORT:
- err = nfs_exp32_trans(karg, arg32);
- break;
- case NFSCTL_GETFD:
- err = nfs_getfd32_trans(karg, arg32);
- break;
- case NFSCTL_GETFS:
- err = nfs_getfs32_trans(karg, arg32);
- break;
- default:
- err = -EINVAL;
- break;
- }
- if(err)
- goto done;
- oldfs = get_fs();
- set_fs(KERNEL_DS);
- err = sys_nfsservctl(cmd, karg, kres);
- set_fs(oldfs);
-
- if (err)
- goto done;
-
- if((cmd == NFSCTL_GETFD) ||
- (cmd == NFSCTL_GETFS))
- err = nfs_getfh32_res_trans(kres, res32);
-
-done:
- if(karg)
- kfree(karg);
- if(kres)
- kfree(kres);
- return err;
-}
-#else /* !NFSD */
-long asmlinkage sys32_nfsservctl(int cmd, void *notused, void *notused2)
-{
- return sys_ni_syscall();
-}
-#endif
-
-long sys32_io_setup(unsigned nr_reqs, u32 *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 *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_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 *events,
- struct compat_timespec *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 * filename, int flags, int mode)
-{
- char * tmp;
- int fd, error;
-
- /* don't force O_LARGEFILE */
- tmp = getname(filename);
- fd = PTR_ERR(tmp);
- if (!IS_ERR(tmp)) {
- fd = get_unused_fd();
- if (fd >= 0) {
- struct file *f = filp_open(tmp, flags, mode);
- error = PTR_ERR(f);
- if (unlikely(IS_ERR(f))) {
- put_unused_fd(fd);
- fd = error;
- } else
- fd_install(fd, f);
- }
- putname(tmp);
- }
- return fd;
-}
-
-struct sigevent32 {
- u32 sigev_value;
- u32 sigev_signo;
- u32 sigev_notify;
- u32 payload[(64 / 4) - 3];
-};
-
-extern asmlinkage long
-sys_timer_create(clockid_t which_clock,
- struct sigevent __user *timer_event_spec,
- timer_t __user * created_timer_id);
-
-long
-sys32_timer_create(u32 clock, struct sigevent32 *se32, timer_t *timer_id)
-{
- struct sigevent se;
- mm_segment_t oldfs;
- long err;
-
- if (se32) {
- memset(&se, 0, sizeof(struct sigevent));
- if (get_user(se.sigev_value.sival_int, &se32->sigev_value) ||
- __get_user(se.sigev_signo, &se32->sigev_signo) ||
- __get_user(se.sigev_notify, &se32->sigev_notify) ||
- __copy_from_user(&se._sigev_un._pad, &se32->payload,
- sizeof(se32->payload)))
- return -EFAULT;
- }
- if (!access_ok(VERIFY_WRITE,timer_id,sizeof(timer_t)))
- return -EFAULT;
-
- oldfs = get_fs();
- set_fs(KERNEL_DS);
- err = sys_timer_create(clock, se32 ? &se : NULL, timer_id);
- set_fs(oldfs);
-
- return err;
-}
-