diff options
| -rw-r--r-- | fs/file.c | 22 |
1 files changed, 20 insertions, 2 deletions
| @@ -150,8 +150,16 @@ static struct fdtable * alloc_fdtable(unsigned int nr) | |||
| 150 | nr /= (1024 / sizeof(struct file *)); | 150 | nr /= (1024 / sizeof(struct file *)); |
| 151 | nr = roundup_pow_of_two(nr + 1); | 151 | nr = roundup_pow_of_two(nr + 1); |
| 152 | nr *= (1024 / sizeof(struct file *)); | 152 | nr *= (1024 / sizeof(struct file *)); |
| 153 | if (nr > sysctl_nr_open) | 153 | /* |
| 154 | nr = sysctl_nr_open; | 154 | * Note that this can drive nr *below* what we had passed if sysctl_nr_open |
| 155 | * had been set lower between the check in expand_files() and here. Deal | ||
| 156 | * with that in caller, it's cheaper that way. | ||
| 157 | * | ||
| 158 | * We make sure that nr remains a multiple of BITS_PER_LONG - otherwise | ||
| 159 | * bitmaps handling below becomes unpleasant, to put it mildly... | ||
| 160 | */ | ||
| 161 | if (unlikely(nr > sysctl_nr_open)) | ||
| 162 | nr = ((sysctl_nr_open - 1) | (BITS_PER_LONG - 1)) + 1; | ||
| 155 | 163 | ||
| 156 | fdt = kmalloc(sizeof(struct fdtable), GFP_KERNEL); | 164 | fdt = kmalloc(sizeof(struct fdtable), GFP_KERNEL); |
| 157 | if (!fdt) | 165 | if (!fdt) |
| @@ -200,6 +208,16 @@ static int expand_fdtable(struct files_struct *files, int nr) | |||
| 200 | if (!new_fdt) | 208 | if (!new_fdt) |
| 201 | return -ENOMEM; | 209 | return -ENOMEM; |
| 202 | /* | 210 | /* |
| 211 | * extremely unlikely race - sysctl_nr_open decreased between the check in | ||
| 212 | * caller and alloc_fdtable(). Cheaper to catch it here... | ||
| 213 | */ | ||
| 214 | if (unlikely(new_fdt->max_fds <= nr)) { | ||
| 215 | free_fdarr(new_fdt); | ||
| 216 | free_fdset(new_fdt); | ||
| 217 | kfree(new_fdt); | ||
| 218 | return -EMFILE; | ||
| 219 | } | ||
| 220 | /* | ||
| 203 | * Check again since another task may have expanded the fd table while | 221 | * Check again since another task may have expanded the fd table while |
| 204 | * we dropped the lock | 222 | * we dropped the lock |
| 205 | */ | 223 | */ |
