[PATCH] fix RLIM_NOFILE handling

* dup2() should return -EBADF on exceeded sysctl_nr_open
* dup() should *not* return -EINVAL even if you have rlimit set to 0;
it should get -EMFILE instead.

Check for orig_start exceeding rlimit taken to sys_fcntl().
Failing expand_files() in dup{2,3}() now gets -EMFILE remapped to -EBADF.
Consequently, remaining checks for rlimit are taken to expand_files().

Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>

Al Viro 4e1e018e 6c5d0512

+15 -21
+6 -12
fs/fcntl.c
··· 64 64 struct fdtable *fdt; 65 65 66 66 spin_lock(&files->file_lock); 67 - 68 - error = -EINVAL; 69 - if (orig_start >= current->signal->rlim[RLIMIT_NOFILE].rlim_cur) 70 - goto out; 71 - 72 67 repeat: 73 68 fdt = files_fdtable(files); 74 69 /* ··· 78 83 if (start < fdt->max_fds) 79 84 newfd = find_next_zero_bit(fdt->open_fds->fds_bits, 80 85 fdt->max_fds, start); 81 - 82 - error = -EMFILE; 83 - if (newfd >= current->signal->rlim[RLIMIT_NOFILE].rlim_cur) 84 - goto out; 85 86 86 87 error = expand_files(files, newfd); 87 88 if (error < 0) ··· 132 141 spin_lock(&files->file_lock); 133 142 if (!(file = fcheck(oldfd))) 134 143 goto out_unlock; 135 - if (newfd >= current->signal->rlim[RLIMIT_NOFILE].rlim_cur) 136 - goto out_unlock; 137 144 get_file(file); /* We are now finished with oldfd */ 138 145 139 146 err = expand_files(files, newfd); 140 - if (err < 0) 147 + if (unlikely(err < 0)) { 148 + if (err == -EMFILE) 149 + err = -EBADF; 141 150 goto out_fput; 151 + } 142 152 143 153 /* To avoid races with open() and dup(), we will mark the fd as 144 154 * in-use in the open-file bitmap throughout the entire dup2() ··· 320 328 switch (cmd) { 321 329 case F_DUPFD: 322 330 case F_DUPFD_CLOEXEC: 331 + if (arg >= current->signal->rlim[RLIMIT_NOFILE].rlim_cur) 332 + break; 323 333 get_file(filp); 324 334 err = dupfd(filp, arg, cmd == F_DUPFD_CLOEXEC); 325 335 break;
+9
fs/file.c
··· 250 250 struct fdtable *fdt; 251 251 252 252 fdt = files_fdtable(files); 253 + 254 + /* 255 + * N.B. For clone tasks sharing a files structure, this test 256 + * will limit the total number of files that can be opened. 257 + */ 258 + if (nr >= current->signal->rlim[RLIMIT_NOFILE].rlim_cur) 259 + return -EMFILE; 260 + 253 261 /* Do we need to expand? */ 254 262 if (nr < fdt->max_fds) 255 263 return 0; 264 + 256 265 /* Can we expand? */ 257 266 if (nr >= sysctl_nr_open) 258 267 return -EMFILE;
-9
fs/open.c
··· 972 972 int fd, error; 973 973 struct fdtable *fdt; 974 974 975 - error = -EMFILE; 976 975 spin_lock(&files->file_lock); 977 976 978 977 repeat: 979 978 fdt = files_fdtable(files); 980 979 fd = find_next_zero_bit(fdt->open_fds->fds_bits, fdt->max_fds, 981 980 files->next_fd); 982 - 983 - /* 984 - * N.B. For clone tasks sharing a files structure, this test 985 - * will limit the total number of files that can be opened. 986 - */ 987 - if (fd >= current->signal->rlim[RLIMIT_NOFILE].rlim_cur) 988 - goto out; 989 981 990 982 /* Do we need to expand the fd array or fd set? */ 991 983 error = expand_files(files, fd); ··· 989 997 * If we needed to expand the fs array we 990 998 * might have blocked - try again. 991 999 */ 992 - error = -EMFILE; 993 1000 goto repeat; 994 1001 } 995 1002