[PATCH] fix sysctl_nr_open bugs
* if luser with root sets it to something that is not a multiple of BITS_PER_LONG, the system is screwed. * if it gets decreased at the wrong time, we can get expand_files() returning success and _not_ increasing the size of table as asked. Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
This commit is contained in:
parent
2030a42cec
commit
5c598b3428
22
fs/file.c
22
fs/file.c
|
@ -150,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)
|
||||||
|
@ -199,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
|
||||||
|
|
Loading…
Reference in New Issue