Skip to content

Commit

Permalink
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel…
Browse files Browse the repository at this point in the history
…/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
  • Loading branch information
torvalds committed May 2, 2008
2 parents 1be1d6b + 5c598b3 commit b66e1f1
Show file tree
Hide file tree
Showing 32 changed files with 186 additions and 274 deletions.
69 changes: 4 additions & 65 deletions arch/alpha/kernel/osf_sys.c
Original file line number Diff line number Diff line change
Expand Up @@ -981,88 +981,27 @@ asmlinkage int
osf_select(int n, fd_set __user *inp, fd_set __user *outp, fd_set __user *exp,
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) {
time_t sec, usec;

if (!access_ok(VERIFY_READ, tvp, sizeof(*tvp))
|| __get_user(sec, &tvp->tv_sec)
|| __get_user(usec, &tvp->tv_usec)) {
ret = -EFAULT;
goto out_nofds;
return -EFAULT;
}

if (sec < 0 || usec < 0)
goto out_nofds;
return -EINVAL;

if ((unsigned long) sec < MAX_SELECT_SECONDS) {
timeout = (usec + 1000000/HZ - 1) / (1000000/HZ);
timeout += sec * (unsigned long) HZ;
}
}

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. */

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 {
Expand Down
55 changes: 9 additions & 46 deletions arch/mips/kernel/irixioctl.c
Original file line number Diff line number Diff line change
Expand Up @@ -27,33 +27,6 @@ struct irix_termios {
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)
{
struct tty_struct *tp, *rtp;
Expand Down Expand Up @@ -146,34 +119,24 @@ asmlinkage int irix_ioctl(int fd, unsigned long cmd, unsigned long arg)
error = sys_ioctl(fd, TIOCNOTTY, arg);
break;

case 0x00007416:
case 0x00007416: {
pid_t pid;
#ifdef DEBUG_IOCTLS
printk("TIOCGSID, %08lx) ", arg);
#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;

}
case 0x746e:
/* TIOCSTART, same effect as hitting ^Q */
#ifdef DEBUG_IOCTLS
printk("TIOCSTART, %08lx) ", arg);
#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;

case 0x20006968:
Expand Down
1 change: 1 addition & 0 deletions arch/mips/kernel/kspd.c
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
#include <linux/sched.h>
#include <linux/unistd.h>
#include <linux/file.h>
#include <linux/fdtable.h>
#include <linux/fs.h>
#include <linux/syscalls.h>
#include <linux/workqueue.h>
Expand Down
1 change: 1 addition & 0 deletions arch/powerpc/platforms/cell/spufs/coredump.c
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@

#include <linux/elf.h>
#include <linux/file.h>
#include <linux/fdtable.h>
#include <linux/fs.h>
#include <linux/list.h>
#include <linux/module.h>
Expand Down
1 change: 1 addition & 0 deletions drivers/char/tty_audit.c
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@

#include <linux/audit.h>
#include <linux/file.h>
#include <linux/fdtable.h>
#include <linux/tty.h>

struct tty_audit_buf {
Expand Down
1 change: 1 addition & 0 deletions drivers/char/tty_io.c
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@
#include <linux/tty_flip.h>
#include <linux/devpts_fs.h>
#include <linux/file.h>
#include <linux/fdtable.h>
#include <linux/console.h>
#include <linux/timer.h>
#include <linux/ctype.h>
Expand Down
13 changes: 3 additions & 10 deletions fs/anon_inodes.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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;
Expand Down Expand Up @@ -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);
Expand Down
1 change: 1 addition & 0 deletions fs/compat.c
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
#include <linux/fcntl.h>
#include <linux/namei.h>
#include <linux/file.h>
#include <linux/fdtable.h>
#include <linux/vfs.h>
#include <linux/ioctl.h>
#include <linux/init.h>
Expand Down
2 changes: 1 addition & 1 deletion fs/dnotify.c
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
#include <linux/init.h>
#include <linux/spinlock.h>
#include <linux/slab.h>
#include <linux/file.h>
#include <linux/fdtable.h>

int dir_notify_enable __read_mostly = 1;

Expand Down
15 changes: 5 additions & 10 deletions fs/eventfd.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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;
}

23 changes: 8 additions & 15 deletions fs/eventpoll.c
Original file line number Diff line number Diff line change
Expand Up @@ -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));
Expand All @@ -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;
}

/*
Expand Down
1 change: 1 addition & 0 deletions fs/exec.c
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@

#include <linux/slab.h>
#include <linux/file.h>
#include <linux/fdtable.h>
#include <linux/mman.h>
#include <linux/a.out.h>
#include <linux/stat.h>
Expand Down
1 change: 1 addition & 0 deletions fs/fcntl.c
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#include <linux/mm.h>
#include <linux/fs.h>
#include <linux/file.h>
#include <linux/fdtable.h>
#include <linux/capability.h>
#include <linux/dnotify.h>
#include <linux/smp_lock.h>
Expand Down
23 changes: 21 additions & 2 deletions fs/file.c
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
#include <linux/slab.h>
#include <linux/vmalloc.h>
#include <linux/file.h>
#include <linux/fdtable.h>
#include <linux/bitops.h>
#include <linux/interrupt.h>
#include <linux/spinlock.h>
Expand Down Expand Up @@ -149,8 +150,16 @@ static struct fdtable * alloc_fdtable(unsigned int nr)
nr /= (1024 / sizeof(struct file *));
nr = roundup_pow_of_two(nr + 1);
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);
if (!fdt)
Expand Down Expand Up @@ -198,6 +207,16 @@ static int expand_fdtable(struct files_struct *files, int nr)
spin_lock(&files->file_lock);
if (!new_fdt)
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
* we dropped the lock
Expand Down
1 change: 1 addition & 0 deletions fs/file_table.c
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
#include <linux/string.h>
#include <linux/slab.h>
#include <linux/file.h>
#include <linux/fdtable.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/fs.h>
Expand Down
Loading

0 comments on commit b66e1f1

Please sign in to comment.