From a2dcb44c3c5a8151d2d9f6ac8ad0789efcdbe184 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Wed, 23 Apr 2008 14:05:15 -0400 Subject: [PATCH] make osf_select() use core_sys_select() ... instead of open-coding it Signed-off-by: Al Viro --- include/linux/poll.h | 2 ++ 1 file changed, 2 insertions(+) (limited to 'include') diff --git a/include/linux/poll.h b/include/linux/poll.h index 16d813b364ef..ef453828877a 100644 --- a/include/linux/poll.h +++ b/include/linux/poll.h @@ -117,6 +117,8 @@ void zero_fd_set(unsigned long nr, unsigned long *fdset) extern int do_select(int n, fd_set_bits *fds, s64 *timeout); extern int do_sys_poll(struct pollfd __user * ufds, unsigned int nfds, s64 *timeout); +extern int core_sys_select(int n, fd_set __user *inp, fd_set __user *outp, + fd_set __user *exp, s64 *timeout); #endif /* KERNEL */ -- cgit v1.2.3 From 9f3acc3140444a900ab280de942291959f0f615d Mon Sep 17 00:00:00 2001 From: Al Viro Date: Thu, 24 Apr 2008 07:44:08 -0400 Subject: [PATCH] split linux/file.h Initial splitoff of the low-level stuff; taken to fdtable.h Signed-off-by: Al Viro --- arch/mips/kernel/kspd.c | 1 + arch/powerpc/platforms/cell/spufs/coredump.c | 1 + drivers/char/tty_audit.c | 1 + drivers/char/tty_io.c | 1 + fs/compat.c | 1 + fs/dnotify.c | 2 +- fs/exec.c | 1 + fs/fcntl.c | 1 + fs/file.c | 1 + fs/file_table.c | 1 + fs/locks.c | 1 + fs/open.c | 1 + fs/proc/array.c | 1 + fs/proc/base.c | 1 + fs/select.c | 1 + include/linux/fdtable.h | 99 ++++++++++++++++++++++++++++ include/linux/file.h | 86 +----------------------- include/linux/init_task.h | 2 +- kernel/exit.c | 1 + kernel/fork.c | 1 + kernel/kmod.c | 1 + security/selinux/hooks.c | 1 + 22 files changed, 121 insertions(+), 86 deletions(-) create mode 100644 include/linux/fdtable.h (limited to 'include') diff --git a/arch/mips/kernel/kspd.c b/arch/mips/kernel/kspd.c index 998c4efcce88..ceb62dce1c9c 100644 --- a/arch/mips/kernel/kspd.c +++ b/arch/mips/kernel/kspd.c @@ -20,6 +20,7 @@ #include #include #include +#include #include #include #include diff --git a/arch/powerpc/platforms/cell/spufs/coredump.c b/arch/powerpc/platforms/cell/spufs/coredump.c index b962c3ab470c..af116aadba10 100644 --- a/arch/powerpc/platforms/cell/spufs/coredump.c +++ b/arch/powerpc/platforms/cell/spufs/coredump.c @@ -22,6 +22,7 @@ #include #include +#include #include #include #include diff --git a/drivers/char/tty_audit.c b/drivers/char/tty_audit.c index 6342b0534f4d..3582f43345a8 100644 --- a/drivers/char/tty_audit.c +++ b/drivers/char/tty_audit.c @@ -11,6 +11,7 @@ #include #include +#include #include struct tty_audit_buf { diff --git a/drivers/char/tty_io.c b/drivers/char/tty_io.c index 1d298c2cf930..49c1a2267a55 100644 --- a/drivers/char/tty_io.c +++ b/drivers/char/tty_io.c @@ -78,6 +78,7 @@ #include #include #include +#include #include #include #include diff --git a/fs/compat.c b/fs/compat.c index 139dc93c092d..332a869d2c53 100644 --- a/fs/compat.c +++ b/fs/compat.c @@ -24,6 +24,7 @@ #include #include #include +#include #include #include #include diff --git a/fs/dnotify.c b/fs/dnotify.c index eaecc4cfe540..676073b8dda5 100644 --- a/fs/dnotify.c +++ b/fs/dnotify.c @@ -20,7 +20,7 @@ #include #include #include -#include +#include int dir_notify_enable __read_mostly = 1; diff --git a/fs/exec.c b/fs/exec.c index 9f9f931ef949..aeaa9791d8be 100644 --- a/fs/exec.c +++ b/fs/exec.c @@ -24,6 +24,7 @@ #include #include +#include #include #include #include diff --git a/fs/fcntl.c b/fs/fcntl.c index 3f3ac630ccde..bfd776509a72 100644 --- a/fs/fcntl.c +++ b/fs/fcntl.c @@ -9,6 +9,7 @@ #include #include #include +#include #include #include #include diff --git a/fs/file.c b/fs/file.c index 5110acb1c9ef..f6fbcb49faf7 100644 --- a/fs/file.c +++ b/fs/file.c @@ -12,6 +12,7 @@ #include #include #include +#include #include #include #include diff --git a/fs/file_table.c b/fs/file_table.c index 7a0a9b872251..83084225b4c3 100644 --- a/fs/file_table.c +++ b/fs/file_table.c @@ -8,6 +8,7 @@ #include #include #include +#include #include #include #include diff --git a/fs/locks.c b/fs/locks.c index 44d9a6a7ec50..663c069b59b3 100644 --- a/fs/locks.c +++ b/fs/locks.c @@ -116,6 +116,7 @@ #include #include +#include #include #include #include diff --git a/fs/open.c b/fs/open.c index 7af1f05d5978..a1450086e92f 100644 --- a/fs/open.c +++ b/fs/open.c @@ -7,6 +7,7 @@ #include #include #include +#include #include #include #include diff --git a/fs/proc/array.c b/fs/proc/array.c index c135cbdd9127..dca997a93bff 100644 --- a/fs/proc/array.c +++ b/fs/proc/array.c @@ -73,6 +73,7 @@ #include #include #include +#include #include #include #include diff --git a/fs/proc/base.c b/fs/proc/base.c index fcf02f2deeba..808cbdc193d3 100644 --- a/fs/proc/base.c +++ b/fs/proc/base.c @@ -56,6 +56,7 @@ #include #include #include +#include #include #include #include diff --git a/fs/select.c b/fs/select.c index 80d70387e790..8dda969614a9 100644 --- a/fs/select.c +++ b/fs/select.c @@ -21,6 +21,7 @@ #include #include /* for STICKY_TIMEOUTS */ #include +#include #include #include diff --git a/include/linux/fdtable.h b/include/linux/fdtable.h new file mode 100644 index 000000000000..a118f3c0b240 --- /dev/null +++ b/include/linux/fdtable.h @@ -0,0 +1,99 @@ +/* + * descriptor table internals; you almost certainly want file.h instead. + */ + +#ifndef __LINUX_FDTABLE_H +#define __LINUX_FDTABLE_H + +#include +#include +#include +#include +#include +#include + +/* + * The default fd array needs to be at least BITS_PER_LONG, + * as this is the granularity returned by copy_fdset(). + */ +#define NR_OPEN_DEFAULT BITS_PER_LONG + +/* + * The embedded_fd_set is a small fd_set, + * suitable for most tasks (which open <= BITS_PER_LONG files) + */ +struct embedded_fd_set { + unsigned long fds_bits[1]; +}; + +struct fdtable { + unsigned int max_fds; + struct file ** fd; /* current fd array */ + fd_set *close_on_exec; + fd_set *open_fds; + struct rcu_head rcu; + struct fdtable *next; +}; + +/* + * Open file table structure + */ +struct files_struct { + /* + * read mostly part + */ + atomic_t count; + struct fdtable *fdt; + struct fdtable fdtab; + /* + * written part on a separate cache line in SMP + */ + spinlock_t file_lock ____cacheline_aligned_in_smp; + int next_fd; + struct embedded_fd_set close_on_exec_init; + struct embedded_fd_set open_fds_init; + struct file * fd_array[NR_OPEN_DEFAULT]; +}; + +#define files_fdtable(files) (rcu_dereference((files)->fdt)) + +extern struct kmem_cache *filp_cachep; + +struct file_operations; +struct vfsmount; +struct dentry; + +extern int expand_files(struct files_struct *, int nr); +extern void free_fdtable_rcu(struct rcu_head *rcu); +extern void __init files_defer_init(void); + +static inline void free_fdtable(struct fdtable *fdt) +{ + call_rcu(&fdt->rcu, free_fdtable_rcu); +} + +static inline struct file * fcheck_files(struct files_struct *files, unsigned int fd) +{ + struct file * file = NULL; + struct fdtable *fdt = files_fdtable(files); + + if (fd < fdt->max_fds) + file = rcu_dereference(fdt->fd[fd]); + return file; +} + +/* + * Check whether the specified fd has an open file. + */ +#define fcheck(fd) fcheck_files(current->files, fd) + +struct task_struct; + +struct files_struct *get_files_struct(struct task_struct *); +void put_files_struct(struct files_struct *fs); +void reset_files_struct(struct files_struct *); +int unshare_files(struct files_struct **); + +extern struct kmem_cache *files_cachep; + +#endif /* __LINUX_FDTABLE_H */ diff --git a/include/linux/file.h b/include/linux/file.h index 69baf5a4f0a5..27c64bdc68c9 100644 --- a/include/linux/file.h +++ b/include/linux/file.h @@ -5,59 +5,11 @@ #ifndef __LINUX_FILE_H #define __LINUX_FILE_H -#include -#include #include -#include -#include #include +#include -/* - * The default fd array needs to be at least BITS_PER_LONG, - * as this is the granularity returned by copy_fdset(). - */ -#define NR_OPEN_DEFAULT BITS_PER_LONG - -/* - * The embedded_fd_set is a small fd_set, - * suitable for most tasks (which open <= BITS_PER_LONG files) - */ -struct embedded_fd_set { - unsigned long fds_bits[1]; -}; - -struct fdtable { - unsigned int max_fds; - struct file ** fd; /* current fd array */ - fd_set *close_on_exec; - fd_set *open_fds; - struct rcu_head rcu; - struct fdtable *next; -}; - -/* - * Open file table structure - */ -struct files_struct { - /* - * read mostly part - */ - atomic_t count; - struct fdtable *fdt; - struct fdtable fdtab; - /* - * written part on a separate cache line in SMP - */ - spinlock_t file_lock ____cacheline_aligned_in_smp; - int next_fd; - struct embedded_fd_set close_on_exec_init; - struct embedded_fd_set open_fds_init; - struct file * fd_array[NR_OPEN_DEFAULT]; -}; - -#define files_fdtable(files) (rcu_dereference((files)->fdt)) - -extern struct kmem_cache *filp_cachep; +struct file; extern void __fput(struct file *); extern void fput(struct file *); @@ -85,41 +37,7 @@ extern void put_filp(struct file *); extern int get_unused_fd(void); extern int get_unused_fd_flags(int flags); extern void put_unused_fd(unsigned int fd); -struct kmem_cache; - -extern int expand_files(struct files_struct *, int nr); -extern void free_fdtable_rcu(struct rcu_head *rcu); -extern void __init files_defer_init(void); - -static inline void free_fdtable(struct fdtable *fdt) -{ - call_rcu(&fdt->rcu, free_fdtable_rcu); -} - -static inline struct file * fcheck_files(struct files_struct *files, unsigned int fd) -{ - struct file * file = NULL; - struct fdtable *fdt = files_fdtable(files); - - if (fd < fdt->max_fds) - file = rcu_dereference(fdt->fd[fd]); - return file; -} - -/* - * Check whether the specified fd has an open file. - */ -#define fcheck(fd) fcheck_files(current->files, fd) extern void fd_install(unsigned int fd, struct file *file); -struct task_struct; - -struct files_struct *get_files_struct(struct task_struct *); -void put_files_struct(struct files_struct *fs); -void reset_files_struct(struct files_struct *); -int unshare_files(struct files_struct **); - -extern struct kmem_cache *files_cachep; - #endif /* __LINUX_FILE_H */ diff --git a/include/linux/init_task.h b/include/linux/init_task.h index bf6b8a61f8db..b24c2875aa05 100644 --- a/include/linux/init_task.h +++ b/include/linux/init_task.h @@ -1,7 +1,7 @@ #ifndef _LINUX__INIT_TASK_H #define _LINUX__INIT_TASK_H -#include +#include #include #include #include diff --git a/kernel/exit.c b/kernel/exit.c index d3ad54677f9c..1510f78a0ffa 100644 --- a/kernel/exit.c +++ b/kernel/exit.c @@ -19,6 +19,7 @@ #include #include #include +#include #include #include #include diff --git a/kernel/fork.c b/kernel/fork.c index 2bb675af4de3..933e60ebccae 100644 --- a/kernel/fork.c +++ b/kernel/fork.c @@ -22,6 +22,7 @@ #include #include #include +#include #include #include #include diff --git a/kernel/kmod.c b/kernel/kmod.c index e2764047ec03..8df97d3dfda8 100644 --- a/kernel/kmod.c +++ b/kernel/kmod.c @@ -27,6 +27,7 @@ #include #include #include +#include #include #include #include diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 1b50a6ebc55f..1c864c0efe2b 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -39,6 +39,7 @@ #include #include #include +#include #include #include #include -- cgit v1.2.3 From 2030a42cecd4dd1985a2ab03e25f3cd6106a5ca8 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Sat, 23 Feb 2008 06:46:49 -0500 Subject: [PATCH] sanitize anon_inode_getfd() a) none of the callers even looks at inode or file returned by anon_inode_getfd() b) any caller that would try to look at those would be racy, since by the time it returns we might have raced with close() from another thread and that file would be pining for fjords. Signed-off-by: Al Viro --- fs/anon_inodes.c | 13 +++---------- fs/eventfd.c | 15 +++++---------- fs/eventpoll.c | 23 ++++++++--------------- fs/signalfd.c | 17 ++++------------- fs/timerfd.c | 11 +++-------- include/linux/anon_inodes.h | 3 +-- virt/kvm/kvm_main.c | 21 +++++---------------- 7 files changed, 29 insertions(+), 74 deletions(-) (limited to 'include') diff --git a/fs/anon_inodes.c b/fs/anon_inodes.c index f42be069e085..977ef208c051 100644 --- a/fs/anon_inodes.c +++ b/fs/anon_inodes.c @@ -57,9 +57,6 @@ static struct dentry_operations anon_inodefs_dentry_operations = { * anonymous inode, and a dentry that describe the "class" * of the file * - * @pfd: [out] pointer to the file descriptor - * @dpinode: [out] pointer to the inode - * @pfile: [out] pointer to the file struct * @name: [in] name of the "class" of the new file * @fops [in] file operations for the new file * @priv [in] private data for the new file (will be file's private_data) @@ -68,10 +65,9 @@ static struct dentry_operations anon_inodefs_dentry_operations = { * that do not need to have a full-fledged inode in order to operate correctly. * All the files created with anon_inode_getfd() will share a single inode, * hence saving memory and avoiding code duplication for the file/inode/dentry - * setup. + * setup. Returns new descriptor or -error. */ -int anon_inode_getfd(int *pfd, struct inode **pinode, struct file **pfile, - const char *name, const struct file_operations *fops, +int anon_inode_getfd(const char *name, const struct file_operations *fops, void *priv) { struct qstr this; @@ -125,10 +121,7 @@ int anon_inode_getfd(int *pfd, struct inode **pinode, struct file **pfile, fd_install(fd, file); - *pfd = fd; - *pinode = anon_inode_inode; - *pfile = file; - return 0; + return fd; err_dput: dput(dentry); diff --git a/fs/eventfd.c b/fs/eventfd.c index a9f130cd50ac..343942deeec1 100644 --- a/fs/eventfd.c +++ b/fs/eventfd.c @@ -200,10 +200,8 @@ struct file *eventfd_fget(int fd) asmlinkage long sys_eventfd(unsigned int count) { - int error, fd; + int fd; struct eventfd_ctx *ctx; - struct file *file; - struct inode *inode; ctx = kmalloc(sizeof(*ctx), GFP_KERNEL); if (!ctx) @@ -216,12 +214,9 @@ asmlinkage long sys_eventfd(unsigned int count) * When we call this, the initialization must be complete, since * anon_inode_getfd() will install the fd. */ - error = anon_inode_getfd(&fd, &inode, &file, "[eventfd]", - &eventfd_fops, ctx); - if (!error) - return fd; - - kfree(ctx); - return error; + fd = anon_inode_getfd("[eventfd]", &eventfd_fops, ctx); + if (fd < 0) + kfree(ctx); + return fd; } diff --git a/fs/eventpoll.c b/fs/eventpoll.c index 221086fef174..990c01d2d66b 100644 --- a/fs/eventpoll.c +++ b/fs/eventpoll.c @@ -1050,8 +1050,6 @@ asmlinkage long sys_epoll_create(int size) { int error, fd = -1; struct eventpoll *ep; - struct inode *inode; - struct file *file; DNPRINTK(3, (KERN_INFO "[%p] eventpoll: sys_epoll_create(%d)\n", current, size)); @@ -1061,29 +1059,24 @@ asmlinkage long sys_epoll_create(int size) * structure ( "struct eventpoll" ). */ error = -EINVAL; - if (size <= 0 || (error = ep_alloc(&ep)) != 0) + if (size <= 0 || (error = ep_alloc(&ep)) < 0) { + fd = error; goto error_return; + } /* * Creates all the items needed to setup an eventpoll file. That is, - * a file structure, and inode and a free file descriptor. + * a file structure and a free file descriptor. */ - error = anon_inode_getfd(&fd, &inode, &file, "[eventpoll]", - &eventpoll_fops, ep); - if (error) - goto error_free; + fd = anon_inode_getfd("[eventpoll]", &eventpoll_fops, ep); + if (fd < 0) + ep_free(ep); +error_return: DNPRINTK(3, (KERN_INFO "[%p] eventpoll: sys_epoll_create(%d) = %d\n", current, size, fd)); return fd; - -error_free: - ep_free(ep); -error_return: - DNPRINTK(3, (KERN_INFO "[%p] eventpoll: sys_epoll_create(%d) = %d\n", - current, size, error)); - return error; } /* diff --git a/fs/signalfd.c b/fs/signalfd.c index 8ead0db35933..619725644c75 100644 --- a/fs/signalfd.c +++ b/fs/signalfd.c @@ -207,11 +207,8 @@ static const struct file_operations signalfd_fops = { asmlinkage long sys_signalfd(int ufd, sigset_t __user *user_mask, size_t sizemask) { - int error; sigset_t sigmask; struct signalfd_ctx *ctx; - struct file *file; - struct inode *inode; if (sizemask != sizeof(sigset_t) || copy_from_user(&sigmask, user_mask, sizeof(sigmask))) @@ -230,12 +227,11 @@ asmlinkage long sys_signalfd(int ufd, sigset_t __user *user_mask, size_t sizemas * When we call this, the initialization must be complete, since * anon_inode_getfd() will install the fd. */ - error = anon_inode_getfd(&ufd, &inode, &file, "[signalfd]", - &signalfd_fops, ctx); - if (error) - goto err_fdalloc; + ufd = anon_inode_getfd("[signalfd]", &signalfd_fops, ctx); + if (ufd < 0) + kfree(ctx); } else { - file = fget(ufd); + struct file *file = fget(ufd); if (!file) return -EBADF; ctx = file->private_data; @@ -252,9 +248,4 @@ asmlinkage long sys_signalfd(int ufd, sigset_t __user *user_mask, size_t sizemas } return ufd; - -err_fdalloc: - kfree(ctx); - return error; } - diff --git a/fs/timerfd.c b/fs/timerfd.c index 5400524e9cb1..d87d354ec424 100644 --- a/fs/timerfd.c +++ b/fs/timerfd.c @@ -181,10 +181,8 @@ static struct file *timerfd_fget(int fd) asmlinkage long sys_timerfd_create(int clockid, int flags) { - int error, ufd; + int ufd; struct timerfd_ctx *ctx; - struct file *file; - struct inode *inode; if (flags) return -EINVAL; @@ -200,12 +198,9 @@ asmlinkage long sys_timerfd_create(int clockid, int flags) ctx->clockid = clockid; hrtimer_init(&ctx->tmr, clockid, HRTIMER_MODE_ABS); - error = anon_inode_getfd(&ufd, &inode, &file, "[timerfd]", - &timerfd_fops, ctx); - if (error) { + ufd = anon_inode_getfd("[timerfd]", &timerfd_fops, ctx); + if (ufd < 0) kfree(ctx); - return error; - } return ufd; } diff --git a/include/linux/anon_inodes.h b/include/linux/anon_inodes.h index b2e1ba325b9a..6129e58ca7c9 100644 --- a/include/linux/anon_inodes.h +++ b/include/linux/anon_inodes.h @@ -8,8 +8,7 @@ #ifndef _LINUX_ANON_INODES_H #define _LINUX_ANON_INODES_H -int anon_inode_getfd(int *pfd, struct inode **pinode, struct file **pfile, - const char *name, const struct file_operations *fops, +int anon_inode_getfd(const char *name, const struct file_operations *fops, void *priv); #endif /* _LINUX_ANON_INODES_H */ diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c index c82cf15730a1..e89338e2b043 100644 --- a/virt/kvm/kvm_main.c +++ b/virt/kvm/kvm_main.c @@ -834,16 +834,9 @@ static const struct file_operations kvm_vcpu_fops = { */ static int create_vcpu_fd(struct kvm_vcpu *vcpu) { - int fd, r; - struct inode *inode; - struct file *file; - - r = anon_inode_getfd(&fd, &inode, &file, - "kvm-vcpu", &kvm_vcpu_fops, vcpu); - if (r) { + int fd = anon_inode_getfd("kvm-vcpu", &kvm_vcpu_fops, vcpu); + if (fd < 0) kvm_put_kvm(vcpu->kvm); - return r; - } return fd; } @@ -1168,19 +1161,15 @@ static const struct file_operations kvm_vm_fops = { static int kvm_dev_ioctl_create_vm(void) { - int fd, r; - struct inode *inode; - struct file *file; + int fd; struct kvm *kvm; kvm = kvm_create_vm(); if (IS_ERR(kvm)) return PTR_ERR(kvm); - r = anon_inode_getfd(&fd, &inode, &file, "kvm-vm", &kvm_vm_fops, kvm); - if (r) { + fd = anon_inode_getfd("kvm-vm", &kvm_vm_fops, kvm); + if (fd < 0) kvm_put_kvm(kvm); - return r; - } return fd; } -- cgit v1.2.3