Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 4e1e018e authored by Al Viro's avatar Al Viro
Browse files

[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: default avatarAl Viro <viro@zeniv.linux.org.uk>
parent 6c5d0512
Loading
Loading
Loading
Loading
+6 −12
Original line number Diff line number Diff line
@@ -64,11 +64,6 @@ static int locate_fd(unsigned int orig_start, int cloexec)
	struct fdtable *fdt;

	spin_lock(&files->file_lock);

	error = -EINVAL;
	if (orig_start >= current->signal->rlim[RLIMIT_NOFILE].rlim_cur)
		goto out;

repeat:
	fdt = files_fdtable(files);
	/*
@@ -84,10 +79,6 @@ repeat:
		newfd = find_next_zero_bit(fdt->open_fds->fds_bits,
					   fdt->max_fds, start);

	error = -EMFILE;
	if (newfd >= current->signal->rlim[RLIMIT_NOFILE].rlim_cur)
		goto out;

	error = expand_files(files, newfd);
	if (error < 0)
		goto out;
@@ -141,13 +132,14 @@ asmlinkage long sys_dup3(unsigned int oldfd, unsigned int newfd, int flags)
	spin_lock(&files->file_lock);
	if (!(file = fcheck(oldfd)))
		goto out_unlock;
	if (newfd >= current->signal->rlim[RLIMIT_NOFILE].rlim_cur)
		goto out_unlock;
	get_file(file);			/* We are now finished with oldfd */

	err = expand_files(files, newfd);
	if (err < 0)
	if (unlikely(err < 0)) {
		if (err == -EMFILE)
			err = -EBADF;
		goto out_fput;
	}

	/* To avoid races with open() and dup(), we will mark the fd as
	 * in-use in the open-file bitmap throughout the entire dup2()
@@ -328,6 +320,8 @@ static long do_fcntl(int fd, unsigned int cmd, unsigned long arg,
	switch (cmd) {
	case F_DUPFD:
	case F_DUPFD_CLOEXEC:
		if (arg >= current->signal->rlim[RLIMIT_NOFILE].rlim_cur)
			break;
		get_file(filp);
		err = dupfd(filp, arg, cmd == F_DUPFD_CLOEXEC);
		break;
+9 −0
Original line number Diff line number Diff line
@@ -250,9 +250,18 @@ int expand_files(struct files_struct *files, int nr)
	struct fdtable *fdt;

	fdt = files_fdtable(files);

	/*
	 * N.B. For clone tasks sharing a files structure, this test
	 * will limit the total number of files that can be opened.
	 */
	if (nr >= current->signal->rlim[RLIMIT_NOFILE].rlim_cur)
		return -EMFILE;

	/* Do we need to expand? */
	if (nr < fdt->max_fds)
		return 0;

	/* Can we expand? */
	if (nr >= sysctl_nr_open)
		return -EMFILE;
+0 −9
Original line number Diff line number Diff line
@@ -972,7 +972,6 @@ int get_unused_fd_flags(int flags)
	int fd, error;
	struct fdtable *fdt;

  	error = -EMFILE;
	spin_lock(&files->file_lock);

repeat:
@@ -980,13 +979,6 @@ repeat:
	fd = find_next_zero_bit(fdt->open_fds->fds_bits, fdt->max_fds,
				files->next_fd);

	/*
	 * N.B. For clone tasks sharing a files structure, this test
	 * will limit the total number of files that can be opened.
	 */
	if (fd >= current->signal->rlim[RLIMIT_NOFILE].rlim_cur)
		goto out;

	/* Do we need to expand the fd array or fd set?  */
	error = expand_files(files, fd);
	if (error < 0)
@@ -997,7 +989,6 @@ repeat:
	 	 * If we needed to expand the fs array we
		 * might have blocked - try again.
		 */
		error = -EMFILE;
		goto repeat;
	}