85 lines
3.3 KiB
Diff
85 lines
3.3 KiB
Diff
This patch fixes elogind not starting with this error on 3.4 kernels:
|
|
|
|
elogind-daemon: Failed to determine whether /sys/fs/cgroup is a mount point: Symbolic link loop
|
|
elogind-daemon: Failed to mount cgroup at /sys/fs/cgroup/elogind: No such file or directory
|
|
|
|
From cf9ab4c62be7837c2f007cd51ab3604ca0620070 Mon Sep 17 00:00:00 2001
|
|
From: Linus Torvalds <torvalds@linux-foundation.org>
|
|
Date: Mon, 4 Jun 2012 11:00:45 -0700
|
|
Subject: [PATCH] vfs: Fix /proc/<tid>/fdinfo/<fd> file handling
|
|
|
|
commit 0640113be25d283e0ff77a9f041e1242182387f0 upstream.
|
|
|
|
Cyrill Gorcunov reports that I broke the fdinfo files with commit
|
|
30a08bf2d31d ("proc: move fd symlink i_mode calculations into
|
|
tid_fd_revalidate()"), and he's quite right.
|
|
|
|
The tid_fd_revalidate() function is not just used for the <tid>/fd
|
|
symlinks, it's also used for the <tid>/fdinfo/<fd> files, and the
|
|
permission model for those are different.
|
|
|
|
So do the dynamic symlink permission handling just for symlinks, making
|
|
the fdinfo files once more appear as the proper regular files they are.
|
|
|
|
Of course, Al Viro argued (probably correctly) that we shouldn't do the
|
|
symlink permission games at all, and make the symlinks always just be
|
|
the normal 'lrwxrwxrwx'. That would have avoided this issue too, but
|
|
since somebody noticed that the permissions had changed (which was the
|
|
reason for that original commit 30a08bf2d31d in the first place), people
|
|
do apparently use this feature.
|
|
|
|
[ Basically, you can use the symlink permission data as a cheap "fdinfo"
|
|
replacement, since you see whether the file is open for reading and/or
|
|
writing by just looking at st_mode of the symlink. So the feature
|
|
does make sense, even if the pain it has caused means we probably
|
|
shouldn't have done it to begin with. ]
|
|
|
|
Reported-and-tested-by: Cyrill Gorcunov <gorcunov@openvz.org>
|
|
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
|
|
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
|
|
---
|
|
fs/proc/base.c | 17 ++++++++++-------
|
|
1 file changed, 10 insertions(+), 7 deletions(-)
|
|
|
|
diff --git a/fs/proc/base.c b/fs/proc/base.c
|
|
index 57b8159f26f3..9fc77b412ac4 100644
|
|
--- a/fs/proc/base.c
|
|
+++ b/fs/proc/base.c
|
|
@@ -1803,7 +1803,7 @@ static int tid_fd_revalidate(struct dentry *dentry, struct nameidata *nd)
|
|
rcu_read_lock();
|
|
file = fcheck_files(files, fd);
|
|
if (file) {
|
|
- unsigned i_mode, f_mode = file->f_mode;
|
|
+ unsigned f_mode = file->f_mode;
|
|
|
|
rcu_read_unlock();
|
|
put_files_struct(files);
|
|
@@ -1819,12 +1819,14 @@ static int tid_fd_revalidate(struct dentry *dentry, struct nameidata *nd)
|
|
inode->i_gid = 0;
|
|
}
|
|
|
|
- i_mode = S_IFLNK;
|
|
- if (f_mode & FMODE_READ)
|
|
- i_mode |= S_IRUSR | S_IXUSR;
|
|
- if (f_mode & FMODE_WRITE)
|
|
- i_mode |= S_IWUSR | S_IXUSR;
|
|
- inode->i_mode = i_mode;
|
|
+ if (S_ISLNK(inode->i_mode)) {
|
|
+ unsigned i_mode = S_IFLNK;
|
|
+ if (f_mode & FMODE_READ)
|
|
+ i_mode |= S_IRUSR | S_IXUSR;
|
|
+ if (f_mode & FMODE_WRITE)
|
|
+ i_mode |= S_IWUSR | S_IXUSR;
|
|
+ inode->i_mode = i_mode;
|
|
+ }
|
|
|
|
security_task_to_inode(task, inode);
|
|
put_task_struct(task);
|
|
@@ -1859,6 +1861,7 @@ static struct dentry *proc_fd_instantiate(struct inode *dir,
|
|
ei = PROC_I(inode);
|
|
ei->fd = fd;
|
|
|
|
+ inode->i_mode = S_IFLNK;
|
|
inode->i_op = &proc_pid_link_inode_operations;
|
|
inode->i_size = 64;
|
|
ei->op.proc_get_link = proc_fd_link;
|