Ver código fonte

Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs-2.6

* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs-2.6:
  [PATCH] fix sysctl_nr_open bugs
  [PATCH] sanitize anon_inode_getfd()
  [PATCH] split linux/file.h
  [PATCH] make osf_select() use core_sys_select()
  [PATCH] remove horrors with irix tty ioctls handling
  [PATCH] fix file and descriptor handling in perfmon
Linus Torvalds 17 anos atrás
pai
commit
b66e1f11eb

+ 4 - 65
arch/alpha/kernel/osf_sys.c

@@ -981,27 +981,18 @@ asmlinkage int
 osf_select(int n, fd_set __user *inp, fd_set __user *outp, fd_set __user *exp,
 osf_select(int n, fd_set __user *inp, fd_set __user *outp, fd_set __user *exp,
 	   struct timeval32 __user *tvp)
 	   struct timeval32 __user *tvp)
 {
 {
-	fd_set_bits fds;
-	char *bits;
-	size_t size;
-	long timeout;
-	int ret = -EINVAL;
-	struct fdtable *fdt;
-	int max_fds;
-
-	timeout = MAX_SCHEDULE_TIMEOUT;
+	s64 timeout = MAX_SCHEDULE_TIMEOUT;
 	if (tvp) {
 	if (tvp) {
 		time_t sec, usec;
 		time_t sec, usec;
 
 
 		if (!access_ok(VERIFY_READ, tvp, sizeof(*tvp))
 		if (!access_ok(VERIFY_READ, tvp, sizeof(*tvp))
 		    || __get_user(sec, &tvp->tv_sec)
 		    || __get_user(sec, &tvp->tv_sec)
 		    || __get_user(usec, &tvp->tv_usec)) {
 		    || __get_user(usec, &tvp->tv_usec)) {
-		    	ret = -EFAULT;
-			goto out_nofds;
+		    	return -EFAULT;
 		}
 		}
 
 
 		if (sec < 0 || usec < 0)
 		if (sec < 0 || usec < 0)
-			goto out_nofds;
+			return -EINVAL;
 
 
 		if ((unsigned long) sec < MAX_SELECT_SECONDS) {
 		if ((unsigned long) sec < MAX_SELECT_SECONDS) {
 			timeout = (usec + 1000000/HZ - 1) / (1000000/HZ);
 			timeout = (usec + 1000000/HZ - 1) / (1000000/HZ);
@@ -1009,60 +1000,8 @@ osf_select(int n, fd_set __user *inp, fd_set __user *outp, fd_set __user *exp,
 		}
 		}
 	}
 	}
 
 
-	rcu_read_lock();
-	fdt = files_fdtable(current->files);
-	max_fds = fdt->max_fds;
-	rcu_read_unlock();
-	if (n < 0 || n > max_fds)
-		goto out_nofds;
-
-	/*
-	 * We need 6 bitmaps (in/out/ex for both incoming and outgoing),
-	 * since we used fdset we need to allocate memory in units of
-	 * long-words. 
-	 */
-	ret = -ENOMEM;
-	size = FDS_BYTES(n);
-	bits = kmalloc(6 * size, GFP_KERNEL);
-	if (!bits)
-		goto out_nofds;
-	fds.in      = (unsigned long *)  bits;
-	fds.out     = (unsigned long *) (bits +   size);
-	fds.ex      = (unsigned long *) (bits + 2*size);
-	fds.res_in  = (unsigned long *) (bits + 3*size);
-	fds.res_out = (unsigned long *) (bits + 4*size);
-	fds.res_ex  = (unsigned long *) (bits + 5*size);
-
-	if ((ret = get_fd_set(n, inp->fds_bits, fds.in)) ||
-	    (ret = get_fd_set(n, outp->fds_bits, fds.out)) ||
-	    (ret = get_fd_set(n, exp->fds_bits, fds.ex)))
-		goto out;
-	zero_fd_set(n, fds.res_in);
-	zero_fd_set(n, fds.res_out);
-	zero_fd_set(n, fds.res_ex);
-
-	ret = do_select(n, &fds, &timeout);
-
 	/* OSF does not copy back the remaining time.  */
 	/* OSF does not copy back the remaining time.  */
-
-	if (ret < 0)
-		goto out;
-	if (!ret) {
-		ret = -ERESTARTNOHAND;
-		if (signal_pending(current))
-			goto out;
-		ret = 0;
-	}
-
-	if (set_fd_set(n, inp->fds_bits, fds.res_in) ||
-	    set_fd_set(n, outp->fds_bits, fds.res_out) ||
-	    set_fd_set(n, exp->fds_bits, fds.res_ex))
-		ret = -EFAULT;
-
- out:
-	kfree(bits);
- out_nofds:
-	return ret;
+	return core_sys_select(n, inp, outp, exp, &timeout);
 }
 }
 
 
 struct rusage32 {
 struct rusage32 {

+ 9 - 46
arch/mips/kernel/irixioctl.c

@@ -27,33 +27,6 @@ struct irix_termios {
 	cc_t c_cc[NCCS];
 	cc_t c_cc[NCCS];
 };
 };
 
 
-extern void start_tty(struct tty_struct *tty);
-static struct tty_struct *get_tty(int fd)
-{
-	struct file *filp;
-	struct tty_struct *ttyp = NULL;
-
-	rcu_read_lock();
-	filp = fcheck(fd);
-	if(filp && filp->private_data) {
-		ttyp = (struct tty_struct *) filp->private_data;
-
-		if(ttyp->magic != TTY_MAGIC)
-			ttyp =NULL;
-	}
-	rcu_read_unlock();
-	return ttyp;
-}
-
-static struct tty_struct *get_real_tty(struct tty_struct *tp)
-{
-	if (tp->driver->type == TTY_DRIVER_TYPE_PTY &&
-	   tp->driver->subtype == PTY_TYPE_MASTER)
-		return tp->link;
-	else
-		return tp;
-}
-
 asmlinkage int irix_ioctl(int fd, unsigned long cmd, unsigned long arg)
 asmlinkage int irix_ioctl(int fd, unsigned long cmd, unsigned long arg)
 {
 {
 	struct tty_struct *tp, *rtp;
 	struct tty_struct *tp, *rtp;
@@ -146,34 +119,24 @@ asmlinkage int irix_ioctl(int fd, unsigned long cmd, unsigned long arg)
 		error = sys_ioctl(fd, TIOCNOTTY, arg);
 		error = sys_ioctl(fd, TIOCNOTTY, arg);
 		break;
 		break;
 
 
-	case 0x00007416:
+	case 0x00007416: {
+		pid_t pid;
 #ifdef DEBUG_IOCTLS
 #ifdef DEBUG_IOCTLS
 		printk("TIOCGSID, %08lx) ", arg);
 		printk("TIOCGSID, %08lx) ", arg);
 #endif
 #endif
-		tp = get_tty(fd);
-		if(!tp) {
-			error = -EINVAL;
-			break;
-		}
-		rtp = get_real_tty(tp);
-#ifdef DEBUG_IOCTLS
-		printk("rtp->session=%d ", rtp->session);
-#endif
-		error = put_user(rtp->session, (unsigned long __user *) arg);
+		old_fs = get_fs(); set_fs(get_ds());
+		error = sys_ioctl(fd, TIOCGSID, (unsigned long)&pid);
+		set_fs(old_fs);
+		if (!error)
+			error = put_user(pid, (unsigned long __user *) arg);
 		break;
 		break;
-
+	}
 	case 0x746e:
 	case 0x746e:
 		/* TIOCSTART, same effect as hitting ^Q */
 		/* TIOCSTART, same effect as hitting ^Q */
 #ifdef DEBUG_IOCTLS
 #ifdef DEBUG_IOCTLS
 		printk("TIOCSTART, %08lx) ", arg);
 		printk("TIOCSTART, %08lx) ", arg);
 #endif
 #endif
-		tp = get_tty(fd);
-		if(!tp) {
-			error = -EINVAL;
-			break;
-		}
-		rtp = get_real_tty(tp);
-		start_tty(rtp);
+		error = sys_ioctl(fd, TCXONC, TCOON);
 		break;
 		break;
 
 
 	case 0x20006968:
 	case 0x20006968:

+ 1 - 0
arch/mips/kernel/kspd.c

@@ -20,6 +20,7 @@
 #include <linux/sched.h>
 #include <linux/sched.h>
 #include <linux/unistd.h>
 #include <linux/unistd.h>
 #include <linux/file.h>
 #include <linux/file.h>
+#include <linux/fdtable.h>
 #include <linux/fs.h>
 #include <linux/fs.h>
 #include <linux/syscalls.h>
 #include <linux/syscalls.h>
 #include <linux/workqueue.h>
 #include <linux/workqueue.h>

+ 1 - 0
arch/powerpc/platforms/cell/spufs/coredump.c

@@ -22,6 +22,7 @@
 
 
 #include <linux/elf.h>
 #include <linux/elf.h>
 #include <linux/file.h>
 #include <linux/file.h>
+#include <linux/fdtable.h>
 #include <linux/fs.h>
 #include <linux/fs.h>
 #include <linux/list.h>
 #include <linux/list.h>
 #include <linux/module.h>
 #include <linux/module.h>

+ 1 - 0
drivers/char/tty_audit.c

@@ -11,6 +11,7 @@
 
 
 #include <linux/audit.h>
 #include <linux/audit.h>
 #include <linux/file.h>
 #include <linux/file.h>
+#include <linux/fdtable.h>
 #include <linux/tty.h>
 #include <linux/tty.h>
 
 
 struct tty_audit_buf {
 struct tty_audit_buf {

+ 1 - 0
drivers/char/tty_io.c

@@ -78,6 +78,7 @@
 #include <linux/tty_flip.h>
 #include <linux/tty_flip.h>
 #include <linux/devpts_fs.h>
 #include <linux/devpts_fs.h>
 #include <linux/file.h>
 #include <linux/file.h>
+#include <linux/fdtable.h>
 #include <linux/console.h>
 #include <linux/console.h>
 #include <linux/timer.h>
 #include <linux/timer.h>
 #include <linux/ctype.h>
 #include <linux/ctype.h>

+ 3 - 10
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"
  *                    anonymous inode, and a dentry that describe the "class"
  *                    of the file
  *                    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
  * @name:    [in]    name of the "class" of the new file
  * @fops     [in]    file operations for 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)
  * @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.
  * 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,
  * 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
  * 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)
 		     void *priv)
 {
 {
 	struct qstr this;
 	struct qstr this;
@@ -125,10 +121,7 @@ int anon_inode_getfd(int *pfd, struct inode **pinode, struct file **pfile,
 
 
 	fd_install(fd, file);
 	fd_install(fd, file);
 
 
-	*pfd = fd;
-	*pinode = anon_inode_inode;
-	*pfile = file;
-	return 0;
+	return fd;
 
 
 err_dput:
 err_dput:
 	dput(dentry);
 	dput(dentry);

+ 1 - 0
fs/compat.c

@@ -24,6 +24,7 @@
 #include <linux/fcntl.h>
 #include <linux/fcntl.h>
 #include <linux/namei.h>
 #include <linux/namei.h>
 #include <linux/file.h>
 #include <linux/file.h>
+#include <linux/fdtable.h>
 #include <linux/vfs.h>
 #include <linux/vfs.h>
 #include <linux/ioctl.h>
 #include <linux/ioctl.h>
 #include <linux/init.h>
 #include <linux/init.h>

+ 1 - 1
fs/dnotify.c

@@ -20,7 +20,7 @@
 #include <linux/init.h>
 #include <linux/init.h>
 #include <linux/spinlock.h>
 #include <linux/spinlock.h>
 #include <linux/slab.h>
 #include <linux/slab.h>
-#include <linux/file.h>
+#include <linux/fdtable.h>
 
 
 int dir_notify_enable __read_mostly = 1;
 int dir_notify_enable __read_mostly = 1;
 
 

+ 5 - 10
fs/eventfd.c

@@ -200,10 +200,8 @@ struct file *eventfd_fget(int fd)
 
 
 asmlinkage long sys_eventfd(unsigned int count)
 asmlinkage long sys_eventfd(unsigned int count)
 {
 {
-	int error, fd;
+	int fd;
 	struct eventfd_ctx *ctx;
 	struct eventfd_ctx *ctx;
-	struct file *file;
-	struct inode *inode;
 
 
 	ctx = kmalloc(sizeof(*ctx), GFP_KERNEL);
 	ctx = kmalloc(sizeof(*ctx), GFP_KERNEL);
 	if (!ctx)
 	if (!ctx)
@@ -216,12 +214,9 @@ asmlinkage long sys_eventfd(unsigned int count)
 	 * When we call this, the initialization must be complete, since
 	 * When we call this, the initialization must be complete, since
 	 * anon_inode_getfd() will install the fd.
 	 * 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;
 }
 }
 
 

+ 8 - 15
fs/eventpoll.c

@@ -1050,8 +1050,6 @@ asmlinkage long sys_epoll_create(int size)
 {
 {
 	int error, fd = -1;
 	int error, fd = -1;
 	struct eventpoll *ep;
 	struct eventpoll *ep;
-	struct inode *inode;
-	struct file *file;
 
 
 	DNPRINTK(3, (KERN_INFO "[%p] eventpoll: sys_epoll_create(%d)\n",
 	DNPRINTK(3, (KERN_INFO "[%p] eventpoll: sys_epoll_create(%d)\n",
 		     current, size));
 		     current, size));
@@ -1061,29 +1059,24 @@ asmlinkage long sys_epoll_create(int size)
 	 * structure ( "struct eventpoll" ).
 	 * structure ( "struct eventpoll" ).
 	 */
 	 */
 	error = -EINVAL;
 	error = -EINVAL;
-	if (size <= 0 || (error = ep_alloc(&ep)) != 0)
+	if (size <= 0 || (error = ep_alloc(&ep)) < 0) {
+		fd = error;
 		goto error_return;
 		goto error_return;
+	}
 
 
 	/*
 	/*
 	 * Creates all the items needed to setup an eventpoll file. That is,
 	 * 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",
 	DNPRINTK(3, (KERN_INFO "[%p] eventpoll: sys_epoll_create(%d) = %d\n",
 		     current, size, fd));
 		     current, size, fd));
 
 
 	return 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;
 }
 }
 
 
 /*
 /*

+ 1 - 0
fs/exec.c

@@ -24,6 +24,7 @@
 
 
 #include <linux/slab.h>
 #include <linux/slab.h>
 #include <linux/file.h>
 #include <linux/file.h>
+#include <linux/fdtable.h>
 #include <linux/mman.h>
 #include <linux/mman.h>
 #include <linux/a.out.h>
 #include <linux/a.out.h>
 #include <linux/stat.h>
 #include <linux/stat.h>

+ 1 - 0
fs/fcntl.c

@@ -9,6 +9,7 @@
 #include <linux/mm.h>
 #include <linux/mm.h>
 #include <linux/fs.h>
 #include <linux/fs.h>
 #include <linux/file.h>
 #include <linux/file.h>
+#include <linux/fdtable.h>
 #include <linux/capability.h>
 #include <linux/capability.h>
 #include <linux/dnotify.h>
 #include <linux/dnotify.h>
 #include <linux/smp_lock.h>
 #include <linux/smp_lock.h>

+ 21 - 2
fs/file.c

@@ -12,6 +12,7 @@
 #include <linux/slab.h>
 #include <linux/slab.h>
 #include <linux/vmalloc.h>
 #include <linux/vmalloc.h>
 #include <linux/file.h>
 #include <linux/file.h>
+#include <linux/fdtable.h>
 #include <linux/bitops.h>
 #include <linux/bitops.h>
 #include <linux/interrupt.h>
 #include <linux/interrupt.h>
 #include <linux/spinlock.h>
 #include <linux/spinlock.h>
@@ -149,8 +150,16 @@ static struct fdtable * alloc_fdtable(unsigned int nr)
 	nr /= (1024 / sizeof(struct file *));
 	nr /= (1024 / sizeof(struct file *));
 	nr = roundup_pow_of_two(nr + 1);
 	nr = roundup_pow_of_two(nr + 1);
 	nr *= (1024 / sizeof(struct file *));
 	nr *= (1024 / sizeof(struct file *));
-	if (nr > sysctl_nr_open)
-		nr = sysctl_nr_open;
+	/*
+	 * Note that this can drive nr *below* what we had passed if sysctl_nr_open
+	 * had been set lower between the check in expand_files() and here.  Deal
+	 * with that in caller, it's cheaper that way.
+	 *
+	 * We make sure that nr remains a multiple of BITS_PER_LONG - otherwise
+	 * bitmaps handling below becomes unpleasant, to put it mildly...
+	 */
+	if (unlikely(nr > sysctl_nr_open))
+		nr = ((sysctl_nr_open - 1) | (BITS_PER_LONG - 1)) + 1;
 
 
 	fdt = kmalloc(sizeof(struct fdtable), GFP_KERNEL);
 	fdt = kmalloc(sizeof(struct fdtable), GFP_KERNEL);
 	if (!fdt)
 	if (!fdt)
@@ -198,6 +207,16 @@ static int expand_fdtable(struct files_struct *files, int nr)
 	spin_lock(&files->file_lock);
 	spin_lock(&files->file_lock);
 	if (!new_fdt)
 	if (!new_fdt)
 		return -ENOMEM;
 		return -ENOMEM;
+	/*
+	 * extremely unlikely race - sysctl_nr_open decreased between the check in
+	 * caller and alloc_fdtable().  Cheaper to catch it here...
+	 */
+	if (unlikely(new_fdt->max_fds <= nr)) {
+		free_fdarr(new_fdt);
+		free_fdset(new_fdt);
+		kfree(new_fdt);
+		return -EMFILE;
+	}
 	/*
 	/*
 	 * Check again since another task may have expanded the fd table while
 	 * Check again since another task may have expanded the fd table while
 	 * we dropped the lock
 	 * we dropped the lock

+ 1 - 0
fs/file_table.c

@@ -8,6 +8,7 @@
 #include <linux/string.h>
 #include <linux/string.h>
 #include <linux/slab.h>
 #include <linux/slab.h>
 #include <linux/file.h>
 #include <linux/file.h>
+#include <linux/fdtable.h>
 #include <linux/init.h>
 #include <linux/init.h>
 #include <linux/module.h>
 #include <linux/module.h>
 #include <linux/fs.h>
 #include <linux/fs.h>

+ 1 - 0
fs/locks.c

@@ -116,6 +116,7 @@
 
 
 #include <linux/capability.h>
 #include <linux/capability.h>
 #include <linux/file.h>
 #include <linux/file.h>
+#include <linux/fdtable.h>
 #include <linux/fs.h>
 #include <linux/fs.h>
 #include <linux/init.h>
 #include <linux/init.h>
 #include <linux/module.h>
 #include <linux/module.h>

+ 1 - 0
fs/open.c

@@ -7,6 +7,7 @@
 #include <linux/string.h>
 #include <linux/string.h>
 #include <linux/mm.h>
 #include <linux/mm.h>
 #include <linux/file.h>
 #include <linux/file.h>
+#include <linux/fdtable.h>
 #include <linux/quotaops.h>
 #include <linux/quotaops.h>
 #include <linux/fsnotify.h>
 #include <linux/fsnotify.h>
 #include <linux/module.h>
 #include <linux/module.h>

+ 1 - 0
fs/proc/array.c

@@ -73,6 +73,7 @@
 #include <linux/signal.h>
 #include <linux/signal.h>
 #include <linux/highmem.h>
 #include <linux/highmem.h>
 #include <linux/file.h>
 #include <linux/file.h>
+#include <linux/fdtable.h>
 #include <linux/times.h>
 #include <linux/times.h>
 #include <linux/cpuset.h>
 #include <linux/cpuset.h>
 #include <linux/rcupdate.h>
 #include <linux/rcupdate.h>

+ 1 - 0
fs/proc/base.c

@@ -56,6 +56,7 @@
 #include <linux/init.h>
 #include <linux/init.h>
 #include <linux/capability.h>
 #include <linux/capability.h>
 #include <linux/file.h>
 #include <linux/file.h>
+#include <linux/fdtable.h>
 #include <linux/string.h>
 #include <linux/string.h>
 #include <linux/seq_file.h>
 #include <linux/seq_file.h>
 #include <linux/namei.h>
 #include <linux/namei.h>

+ 2 - 1
fs/select.c

@@ -21,6 +21,7 @@
 #include <linux/poll.h>
 #include <linux/poll.h>
 #include <linux/personality.h> /* for STICKY_TIMEOUTS */
 #include <linux/personality.h> /* for STICKY_TIMEOUTS */
 #include <linux/file.h>
 #include <linux/file.h>
+#include <linux/fdtable.h>
 #include <linux/fs.h>
 #include <linux/fs.h>
 #include <linux/rcupdate.h>
 #include <linux/rcupdate.h>
 
 
@@ -298,7 +299,7 @@ int do_select(int n, fd_set_bits *fds, s64 *timeout)
 #define MAX_SELECT_SECONDS \
 #define MAX_SELECT_SECONDS \
 	((unsigned long) (MAX_SCHEDULE_TIMEOUT / HZ)-1)
 	((unsigned long) (MAX_SCHEDULE_TIMEOUT / HZ)-1)
 
 
-static int core_sys_select(int n, fd_set __user *inp, fd_set __user *outp,
+int core_sys_select(int n, fd_set __user *inp, fd_set __user *outp,
 			   fd_set __user *exp, s64 *timeout)
 			   fd_set __user *exp, s64 *timeout)
 {
 {
 	fd_set_bits fds;
 	fd_set_bits fds;

+ 4 - 13
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)
 asmlinkage long sys_signalfd(int ufd, sigset_t __user *user_mask, size_t sizemask)
 {
 {
-	int error;
 	sigset_t sigmask;
 	sigset_t sigmask;
 	struct signalfd_ctx *ctx;
 	struct signalfd_ctx *ctx;
-	struct file *file;
-	struct inode *inode;
 
 
 	if (sizemask != sizeof(sigset_t) ||
 	if (sizemask != sizeof(sigset_t) ||
 	    copy_from_user(&sigmask, user_mask, sizeof(sigmask)))
 	    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
 		 * When we call this, the initialization must be complete, since
 		 * anon_inode_getfd() will install the fd.
 		 * 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 {
 	} else {
-		file = fget(ufd);
+		struct file *file = fget(ufd);
 		if (!file)
 		if (!file)
 			return -EBADF;
 			return -EBADF;
 		ctx = file->private_data;
 		ctx = file->private_data;
@@ -252,9 +248,4 @@ asmlinkage long sys_signalfd(int ufd, sigset_t __user *user_mask, size_t sizemas
 	}
 	}
 
 
 	return ufd;
 	return ufd;
-
-err_fdalloc:
-	kfree(ctx);
-	return error;
 }
 }
-

+ 3 - 8
fs/timerfd.c

@@ -181,10 +181,8 @@ static struct file *timerfd_fget(int fd)
 
 
 asmlinkage long sys_timerfd_create(int clockid, int flags)
 asmlinkage long sys_timerfd_create(int clockid, int flags)
 {
 {
-	int error, ufd;
+	int ufd;
 	struct timerfd_ctx *ctx;
 	struct timerfd_ctx *ctx;
-	struct file *file;
-	struct inode *inode;
 
 
 	if (flags)
 	if (flags)
 		return -EINVAL;
 		return -EINVAL;
@@ -200,12 +198,9 @@ asmlinkage long sys_timerfd_create(int clockid, int flags)
 	ctx->clockid = clockid;
 	ctx->clockid = clockid;
 	hrtimer_init(&ctx->tmr, clockid, HRTIMER_MODE_ABS);
 	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);
 		kfree(ctx);
-		return error;
-	}
 
 
 	return ufd;
 	return ufd;
 }
 }

+ 1 - 2
include/linux/anon_inodes.h

@@ -8,8 +8,7 @@
 #ifndef _LINUX_ANON_INODES_H
 #ifndef _LINUX_ANON_INODES_H
 #define _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);
 		     void *priv);
 
 
 #endif /* _LINUX_ANON_INODES_H */
 #endif /* _LINUX_ANON_INODES_H */

+ 99 - 0
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 <asm/atomic.h>
+#include <linux/posix_types.h>
+#include <linux/compiler.h>
+#include <linux/spinlock.h>
+#include <linux/rcupdate.h>
+#include <linux/types.h>
+
+/*
+ * 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 */

+ 2 - 84
include/linux/file.h

@@ -5,59 +5,11 @@
 #ifndef __LINUX_FILE_H
 #ifndef __LINUX_FILE_H
 #define __LINUX_FILE_H
 #define __LINUX_FILE_H
 
 
-#include <asm/atomic.h>
-#include <linux/posix_types.h>
 #include <linux/compiler.h>
 #include <linux/compiler.h>
-#include <linux/spinlock.h>
-#include <linux/rcupdate.h>
 #include <linux/types.h>
 #include <linux/types.h>
+#include <linux/posix_types.h>
 
 
-/*
- * 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 *);
 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(void);
 extern int get_unused_fd_flags(int flags);
 extern int get_unused_fd_flags(int flags);
 extern void put_unused_fd(unsigned int fd);
 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);
 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 */
 #endif /* __LINUX_FILE_H */

+ 1 - 1
include/linux/init_task.h

@@ -1,7 +1,7 @@
 #ifndef _LINUX__INIT_TASK_H
 #ifndef _LINUX__INIT_TASK_H
 #define _LINUX__INIT_TASK_H
 #define _LINUX__INIT_TASK_H
 
 
-#include <linux/file.h>
+#include <linux/fdtable.h>
 #include <linux/rcupdate.h>
 #include <linux/rcupdate.h>
 #include <linux/irqflags.h>
 #include <linux/irqflags.h>
 #include <linux/utsname.h>
 #include <linux/utsname.h>

+ 2 - 0
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_select(int n, fd_set_bits *fds, s64 *timeout);
 extern int do_sys_poll(struct pollfd __user * ufds, unsigned int nfds,
 extern int do_sys_poll(struct pollfd __user * ufds, unsigned int nfds,
 		       s64 *timeout);
 		       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 */
 #endif /* KERNEL */
 
 

+ 1 - 0
kernel/exit.c

@@ -19,6 +19,7 @@
 #include <linux/acct.h>
 #include <linux/acct.h>
 #include <linux/tsacct_kern.h>
 #include <linux/tsacct_kern.h>
 #include <linux/file.h>
 #include <linux/file.h>
+#include <linux/fdtable.h>
 #include <linux/binfmts.h>
 #include <linux/binfmts.h>
 #include <linux/nsproxy.h>
 #include <linux/nsproxy.h>
 #include <linux/pid_namespace.h>
 #include <linux/pid_namespace.h>

+ 1 - 0
kernel/fork.c

@@ -22,6 +22,7 @@
 #include <linux/mempolicy.h>
 #include <linux/mempolicy.h>
 #include <linux/sem.h>
 #include <linux/sem.h>
 #include <linux/file.h>
 #include <linux/file.h>
+#include <linux/fdtable.h>
 #include <linux/key.h>
 #include <linux/key.h>
 #include <linux/binfmts.h>
 #include <linux/binfmts.h>
 #include <linux/mman.h>
 #include <linux/mman.h>

+ 1 - 0
kernel/kmod.c

@@ -27,6 +27,7 @@
 #include <linux/mnt_namespace.h>
 #include <linux/mnt_namespace.h>
 #include <linux/completion.h>
 #include <linux/completion.h>
 #include <linux/file.h>
 #include <linux/file.h>
+#include <linux/fdtable.h>
 #include <linux/workqueue.h>
 #include <linux/workqueue.h>
 #include <linux/security.h>
 #include <linux/security.h>
 #include <linux/mount.h>
 #include <linux/mount.h>

+ 1 - 0
security/selinux/hooks.c

@@ -39,6 +39,7 @@
 #include <linux/spinlock.h>
 #include <linux/spinlock.h>
 #include <linux/syscalls.h>
 #include <linux/syscalls.h>
 #include <linux/file.h>
 #include <linux/file.h>
+#include <linux/fdtable.h>
 #include <linux/namei.h>
 #include <linux/namei.h>
 #include <linux/mount.h>
 #include <linux/mount.h>
 #include <linux/ext2_fs.h>
 #include <linux/ext2_fs.h>

+ 5 - 16
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)
 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);
 		kvm_put_kvm(vcpu->kvm);
-		return r;
-	}
 	return fd;
 	return fd;
 }
 }
 
 
@@ -1168,19 +1161,15 @@ static const struct file_operations kvm_vm_fops = {
 
 
 static int kvm_dev_ioctl_create_vm(void)
 static int kvm_dev_ioctl_create_vm(void)
 {
 {
-	int fd, r;
-	struct inode *inode;
-	struct file *file;
+	int fd;
 	struct kvm *kvm;
 	struct kvm *kvm;
 
 
 	kvm = kvm_create_vm();
 	kvm = kvm_create_vm();
 	if (IS_ERR(kvm))
 	if (IS_ERR(kvm))
 		return PTR_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);
 		kvm_put_kvm(kvm);
-		return r;
-	}
 
 
 	return fd;
 	return fd;
 }
 }