#include <linux/rwsem.h>
#include <linux/tsacct_kern.h>
#include <linux/highmem.h>
+#include <linux/poll.h>
#include <linux/mm.h>
+#include <linux/eventpoll.h>
#include <net/sock.h> /* siocdevprivate_ioctl */
file = fget(fd);
if (!file)
goto out;
- error = vfs_statfs(file->f_dentry, &tmp);
+ error = vfs_statfs(file->f_path.dentry, &tmp);
if (!error)
error = put_compat_statfs(buf, &tmp);
fput(file);
file = fget(fd);
if (!file)
goto out;
- error = vfs_statfs(file->f_dentry, &tmp);
+ error = vfs_statfs(file->f_path.dentry, &tmp);
if (!error)
error = put_compat_statfs64(buf, &tmp);
fput(file);
/* find the name of the device. */
path = (char *)__get_free_page(GFP_KERNEL);
if (path) {
- fn = d_path(filp->f_dentry, filp->f_vfsmnt, path, PAGE_SIZE);
+ fn = d_path(filp->f_path.dentry, filp->f_path.mnt, path, PAGE_SIZE);
if (IS_ERR(fn))
fn = "?";
}
case FIBMAP:
case FIGETBSZ:
case FIONREAD:
- if (S_ISREG(filp->f_dentry->d_inode->i_mode))
+ if (S_ISREG(filp->f_path.dentry->d_inode->i_mode))
break;
/*FALL THROUGH*/
goto found_handler;
}
- if (S_ISSOCK(filp->f_dentry->d_inode->i_mode) &&
+ if (S_ISSOCK(filp->f_path.dentry->d_inode->i_mode) &&
cmd >= SIOCDEVPRIVATE && cmd <= (SIOCDEVPRIVATE + 15)) {
error = siocdevprivate_ioctl(fd, cmd, arg);
} else {
retval = -EINVAL;
- if (type_page) {
+ if (type_page && data_page) {
if (!strcmp((char *)type_page, SMBFS_NAME)) {
do_smb_super_data_conv((void *)data_page);
} else if (!strcmp((char *)type_page, NCPFS_NAME)) {
lastdirent = buf.previous;
if (lastdirent) {
typeof(lastdirent->d_off) d_off = file->f_pos;
- __put_user_unaligned(d_off, &lastdirent->d_off);
+ error = -EFAULT;
+ if (__put_user_unaligned(d_off, &lastdirent->d_off))
+ goto out_putf;
error = count - buf.count;
}
if (iov != iovstack)
kfree(iov);
if ((ret + (type == READ)) > 0) {
- struct dentry *dentry = file->f_dentry;
+ struct dentry *dentry = file->f_path.dentry;
if (type == READ)
fsnotify_access(dentry);
else
nr &= ~1UL;
while (nr) {
unsigned long h, l;
- __get_user(l, ufdset);
- __get_user(h, ufdset+1);
+ if (__get_user(l, ufdset) || __get_user(h, ufdset+1))
+ return -EFAULT;
ufdset += 2;
*fdset++ = h << 32 | l;
nr -= 2;
}
- if (odd)
- __get_user(*fdset, ufdset);
+ if (odd && __get_user(*fdset, ufdset))
+ return -EFAULT;
} else {
/* Tricky, must clear full unsigned long in the
* kernel fdset at the end, this makes sure that
}
static
-void compat_set_fd_set(unsigned long nr, compat_ulong_t __user *ufdset,
- unsigned long *fdset)
+int compat_set_fd_set(unsigned long nr, compat_ulong_t __user *ufdset,
+ unsigned long *fdset)
{
unsigned long odd;
nr = ROUND_UP(nr, __COMPAT_NFDBITS);
if (!ufdset)
- return;
+ return 0;
odd = nr & 1UL;
nr &= ~1UL;
unsigned long h, l;
l = *fdset++;
h = l >> 32;
- __put_user(l, ufdset);
- __put_user(h, ufdset+1);
+ if (__put_user(l, ufdset) || __put_user(h, ufdset+1))
+ return -EFAULT;
ufdset += 2;
nr -= 2;
}
- if (odd)
- __put_user(*fdset, ufdset);
+ if (odd && __put_user(*fdset, ufdset))
+ return -EFAULT;
+ return 0;
}
{
fd_set_bits fds;
char *bits;
- int size, max_fdset, ret = -EINVAL;
+ int size, max_fds, ret = -EINVAL;
struct fdtable *fdt;
if (n < 0)
goto out_nofds;
- /* max_fdset can increase, so grab it once to avoid race */
+ /* max_fds can increase, so grab it once to avoid race */
rcu_read_lock();
fdt = files_fdtable(current->files);
- max_fdset = fdt->max_fdset;
+ max_fds = fdt->max_fds;
rcu_read_unlock();
- if (n > max_fdset)
- n = max_fdset;
+ if (n > max_fds)
+ n = max_fds;
/*
* We need 6 bitmaps (in/out/ex for both incoming and outgoing),
ret = 0;
}
- compat_set_fd_set(n, inp, fds.res_in);
- compat_set_fd_set(n, outp, fds.res_out);
- compat_set_fd_set(n, exp, fds.res_ex);
-
+ if (compat_set_fd_set(n, inp, fds.res_in) ||
+ compat_set_fd_set(n, outp, fds.res_out) ||
+ compat_set_fd_set(n, exp, fds.res_ex))
+ ret = -EFAULT;
out:
kfree(bits);
out_nofds:
return sys_ni_syscall();
}
#endif
+
+#ifdef CONFIG_EPOLL
+
+#ifdef CONFIG_HAS_COMPAT_EPOLL_EVENT
+asmlinkage long compat_sys_epoll_ctl(int epfd, int op, int fd,
+ struct compat_epoll_event __user *event)
+{
+ long err = 0;
+ struct compat_epoll_event user;
+ struct epoll_event __user *kernel = NULL;
+
+ if (event) {
+ if (copy_from_user(&user, event, sizeof(user)))
+ return -EFAULT;
+ kernel = compat_alloc_user_space(sizeof(struct epoll_event));
+ err |= __put_user(user.events, &kernel->events);
+ err |= __put_user(user.data, &kernel->data);
+ }
+
+ return err ? err : sys_epoll_ctl(epfd, op, fd, kernel);
+}
+
+
+asmlinkage long compat_sys_epoll_wait(int epfd,
+ struct compat_epoll_event __user *events,
+ int maxevents, int timeout)
+{
+ long i, ret, err = 0;
+ struct epoll_event __user *kbuf;
+ struct epoll_event ev;
+
+ if ((maxevents <= 0) ||
+ (maxevents > (INT_MAX / sizeof(struct epoll_event))))
+ return -EINVAL;
+ kbuf = compat_alloc_user_space(sizeof(struct epoll_event) * maxevents);
+ ret = sys_epoll_wait(epfd, kbuf, maxevents, timeout);
+ for (i = 0; i < ret; i++) {
+ err |= __get_user(ev.events, &kbuf[i].events);
+ err |= __get_user(ev.data, &kbuf[i].data);
+ err |= __put_user(ev.events, &events->events);
+ err |= __put_user_unaligned(ev.data, &events->data);
+ events++;
+ }
+
+ return err ? -EFAULT: ret;
+}
+#endif /* CONFIG_HAS_COMPAT_EPOLL_EVENT */
+
+#ifdef TIF_RESTORE_SIGMASK
+asmlinkage long compat_sys_epoll_pwait(int epfd,
+ struct compat_epoll_event __user *events,
+ int maxevents, int timeout,
+ const compat_sigset_t __user *sigmask,
+ compat_size_t sigsetsize)
+{
+ long err;
+ compat_sigset_t csigmask;
+ sigset_t ksigmask, sigsaved;
+
+ /*
+ * If the caller wants a certain signal mask to be set during the wait,
+ * we apply it here.
+ */
+ if (sigmask) {
+ if (sigsetsize != sizeof(compat_sigset_t))
+ return -EINVAL;
+ if (copy_from_user(&csigmask, sigmask, sizeof(csigmask)))
+ return -EFAULT;
+ sigset_from_compat(&ksigmask, &csigmask);
+ sigdelsetmask(&ksigmask, sigmask(SIGKILL) | sigmask(SIGSTOP));
+ sigprocmask(SIG_SETMASK, &ksigmask, &sigsaved);
+ }
+
+#ifdef CONFIG_HAS_COMPAT_EPOLL_EVENT
+ err = compat_sys_epoll_wait(epfd, events, maxevents, timeout);
+#else
+ err = sys_epoll_wait(epfd, events, maxevents, timeout);
+#endif
+
+ /*
+ * If we changed the signal mask, we need to restore the original one.
+ * In case we've got a signal while waiting, we do not restore the
+ * signal mask yet, and we allow do_signal() to deliver the signal on
+ * the way back to userspace, before the signal mask is restored.
+ */
+ if (sigmask) {
+ if (err == -EINTR) {
+ memcpy(¤t->saved_sigmask, &sigsaved,
+ sizeof(sigsaved));
+ set_thread_flag(TIF_RESTORE_SIGMASK);
+ } else
+ sigprocmask(SIG_SETMASK, &sigsaved, NULL);
+ }
+
+ return err;
+}
+#endif /* TIF_RESTORE_SIGMASK */
+
+#endif /* CONFIG_EPOLL */