| From 1117f72ea0217ba0cc19f05adbbd8b9a397f5ab7 Mon Sep 17 00:00:00 2001 |
| From: Linus Torvalds <torvalds@linux-foundation.org> |
| Date: Sat, 6 Aug 2011 11:51:33 -0700 |
| Subject: vfs: show O_CLOEXE bit properly in /proc/<pid>/fdinfo/<fd> files |
| |
| From: Linus Torvalds <torvalds@linux-foundation.org> |
| |
| commit 1117f72ea0217ba0cc19f05adbbd8b9a397f5ab7 upstream. |
| |
| The CLOEXE bit is magical, and for performance (and semantic) reasons we |
| don't actually maintain it in the file descriptor itself, but in a |
| separate bit array. Which means that when we show f_flags, the CLOEXE |
| status is shown incorrectly: we show the status not as it is now, but as |
| it was when the file was opened. |
| |
| Fix that by looking up the bit properly in the 'fdt->close_on_exec' bit |
| array. |
| |
| Uli needs this in order to re-implement the pfiles program: |
| |
| "For normal file descriptors (not sockets) this was the last piece of |
| information which wasn't available. This is all part of my 'give |
| Solaris users no reason to not switch' effort. I intend to offer the |
| code to the util-linux-ng maintainers." |
| |
| Requested-by: Ulrich Drepper <drepper@akkadia.org> |
| Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> |
| |
| --- |
| fs/proc/base.c | 10 +++++++++- |
| 1 file changed, 9 insertions(+), 1 deletion(-) |
| |
| --- a/fs/proc/base.c |
| +++ b/fs/proc/base.c |
| @@ -1920,6 +1920,14 @@ static int proc_fd_info(struct inode *in |
| spin_lock(&files->file_lock); |
| file = fcheck_files(files, fd); |
| if (file) { |
| + unsigned int f_flags; |
| + struct fdtable *fdt; |
| + |
| + fdt = files_fdtable(files); |
| + f_flags = file->f_flags & ~O_CLOEXEC; |
| + if (FD_ISSET(fd, fdt->close_on_exec)) |
| + f_flags |= O_CLOEXEC; |
| + |
| if (path) { |
| *path = file->f_path; |
| path_get(&file->f_path); |
| @@ -1929,7 +1937,7 @@ static int proc_fd_info(struct inode *in |
| "pos:\t%lli\n" |
| "flags:\t0%o\n", |
| (long long) file->f_pos, |
| - file->f_flags); |
| + f_flags); |
| spin_unlock(&files->file_lock); |
| put_files_struct(files); |
| return 0; |