static int compat_drm_addbufs(struct file *file, unsigned int cmd, unsigned long arg) { drm_buf_desc32_t __user *argp = (void __user *)arg; struct drm_buf_desc __user *buf; int err; unsigned long agp_start; buf = compat_alloc_user_space(sizeof(*buf)); if (!access_ok(VERIFY_WRITE, buf, sizeof(*buf)) || !access_ok(VERIFY_WRITE, argp, sizeof(*argp))) return -EFAULT; if (__copy_in_user(buf, argp, offsetof(drm_buf_desc32_t, agp_start)) || __get_user(agp_start, &argp->agp_start) || __put_user(agp_start, &buf->agp_start)) return -EFAULT; err = drm_ioctl(file, DRM_IOCTL_ADD_BUFS, (unsigned long)buf); if (err) return err; if (__copy_in_user(argp, buf, offsetof(drm_buf_desc32_t, agp_start)) || __get_user(agp_start, &buf->agp_start) || __put_user(agp_start, &argp->agp_start)) return -EFAULT; return 0; }
static int compat_drm_infobufs(struct file *file, unsigned int cmd, unsigned long arg) { drm_buf_info32_t req32; drm_buf_info32_t __user *argp = (void __user *)arg; drm_buf_desc32_t __user *to; drm_buf_info_t __user *request; drm_buf_desc_t __user *list; size_t nbytes; int i, err; int count, actual; if (copy_from_user(&req32, argp, sizeof(req32))) return -EFAULT; count = req32.count; to = (drm_buf_desc32_t __user *) (unsigned long)req32.list; if (count < 0) count = 0; if (count > 0 && !access_ok(VERIFY_WRITE, to, count * sizeof(drm_buf_desc32_t))) return -EFAULT; nbytes = sizeof(*request) + count * sizeof(drm_buf_desc_t); request = compat_alloc_user_space(nbytes); if (!access_ok(VERIFY_WRITE, request, nbytes)) return -EFAULT; list = (drm_buf_desc_t *) (request + 1); if (__put_user(count, &request->count) || __put_user(list, &request->list)) return -EFAULT; err = drm_ioctl(file->f_dentry->d_inode, file, DRM_IOCTL_INFO_BUFS, (unsigned long)request); if (err) return err; if (__get_user(actual, &request->count)) return -EFAULT; if (count >= actual) for (i = 0; i < actual; ++i) if (__copy_in_user(&to[i], &list[i], offsetof(drm_buf_desc_t, flags))) return -EFAULT; if (__put_user(actual, &argp->count)) return -EFAULT; return 0; }
static int do_netfilter_replace(int fd, int level, int optname, char __user *optval, int optlen) { struct compat_ipt_replace __user *urepl; struct ipt_replace __user *repl_nat; char name[IPT_TABLE_MAXNAMELEN]; u32 origsize, tmp32, num_counters; unsigned int repl_nat_size; int ret; int i; compat_uptr_t ucntrs; urepl = (struct compat_ipt_replace __user *)optval; if (get_user(origsize, &urepl->size)) return -EFAULT; /* Hack: Causes ipchains to give correct error msg --RR */ if (optlen != sizeof(*urepl) + origsize) return -ENOPROTOOPT; /* XXX Assumes that size of ipt_entry is the same both in * native and compat environments. */ repl_nat_size = sizeof(*repl_nat) + origsize; repl_nat = compat_alloc_user_space(repl_nat_size); ret = -EFAULT; if (put_user(origsize, &repl_nat->size)) goto out; if (!access_ok(VERIFY_READ, urepl, optlen) || !access_ok(VERIFY_WRITE, repl_nat, optlen)) goto out; if (__copy_from_user(name, urepl->name, sizeof(urepl->name)) || __copy_to_user(repl_nat->name, name, sizeof(repl_nat->name))) goto out; if (__get_user(tmp32, &urepl->valid_hooks) || __put_user(tmp32, &repl_nat->valid_hooks)) goto out; if (__get_user(tmp32, &urepl->num_entries) || __put_user(tmp32, &repl_nat->num_entries)) goto out; if (__get_user(num_counters, &urepl->num_counters) || __put_user(num_counters, &repl_nat->num_counters)) goto out; if (__get_user(ucntrs, &urepl->counters) || __put_user(compat_ptr(ucntrs), &repl_nat->counters)) goto out; if (__copy_in_user(&repl_nat->entries[0], &urepl->entries[0], origsize)) goto out; for (i = 0; i < NF_IP_NUMHOOKS; i++) { if (__get_user(tmp32, &urepl->hook_entry[i]) || __put_user(tmp32, &repl_nat->hook_entry[i]) || __get_user(tmp32, &urepl->underflow[i]) || __put_user(tmp32, &repl_nat->underflow[i])) goto out; } /* * Since struct ipt_counters just contains two u_int64_t members * we can just do the access_ok check here and pass the (converted) * pointer into the standard syscall. We hope that the pointer is * not misaligned ... */ if (!access_ok(VERIFY_WRITE, compat_ptr(ucntrs), num_counters * sizeof(struct ipt_counters))) goto out; ret = sys_setsockopt(fd, level, optname, (char __user *)repl_nat, repl_nat_size); out: return ret; }