aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorTyler Hicks <tyhicks@canonical.com>2012-06-11 12:24:11 -0400
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2012-07-16 11:47:49 -0400
commit542b7a372e617cf3db2f659378e1ed3342fdc31b (patch)
treeadd106b112943579294fde5357fc5d8b830bddae /fs
parente69325eb5e413816e25d3b8599f67644f4f49698 (diff)
eCryptfs: Gracefully refuse miscdev file ops on inherited/passed files
commit 8dc6780587c99286c0d3de747a2946a76989414a upstream. File operations on /dev/ecryptfs would BUG() when the operations were performed by processes other than the process that originally opened the file. This could happen with open files inherited after fork() or file descriptors passed through IPC mechanisms. Rather than calling BUG(), an error code can be safely returned in most situations. In ecryptfs_miscdev_release(), eCryptfs still needs to handle the release even if the last file reference is being held by a process that didn't originally open the file. ecryptfs_find_daemon_by_euid() will not be successful, so a pointer to the daemon is stored in the file's private_data. The private_data pointer is initialized when the miscdev file is opened and only used when the file is released. https://launchpad.net/bugs/994247 Signed-off-by: Tyler Hicks <tyhicks@canonical.com> Reported-by: Sasha Levin <levinsasha928@gmail.com> Tested-by: Sasha Levin <levinsasha928@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'fs')
-rw-r--r--fs/ecryptfs/miscdev.c23
1 files changed, 16 insertions, 7 deletions
diff --git a/fs/ecryptfs/miscdev.c b/fs/ecryptfs/miscdev.c
index 0dc5a3d554a..a050e4bad9a 100644
--- a/fs/ecryptfs/miscdev.c
+++ b/fs/ecryptfs/miscdev.c
@@ -49,7 +49,10 @@ ecryptfs_miscdev_poll(struct file *file, poll_table *pt)
49 mutex_lock(&ecryptfs_daemon_hash_mux); 49 mutex_lock(&ecryptfs_daemon_hash_mux);
50 /* TODO: Just use file->private_data? */ 50 /* TODO: Just use file->private_data? */
51 rc = ecryptfs_find_daemon_by_euid(&daemon, euid, current_user_ns()); 51 rc = ecryptfs_find_daemon_by_euid(&daemon, euid, current_user_ns());
52 BUG_ON(rc || !daemon); 52 if (rc || !daemon) {
53 mutex_unlock(&ecryptfs_daemon_hash_mux);
54 return -EINVAL;
55 }
53 mutex_lock(&daemon->mux); 56 mutex_lock(&daemon->mux);
54 mutex_unlock(&ecryptfs_daemon_hash_mux); 57 mutex_unlock(&ecryptfs_daemon_hash_mux);
55 if (daemon->flags & ECRYPTFS_DAEMON_ZOMBIE) { 58 if (daemon->flags & ECRYPTFS_DAEMON_ZOMBIE) {
@@ -122,6 +125,7 @@ ecryptfs_miscdev_open(struct inode *inode, struct file *file)
122 goto out_unlock_daemon; 125 goto out_unlock_daemon;
123 } 126 }
124 daemon->flags |= ECRYPTFS_DAEMON_MISCDEV_OPEN; 127 daemon->flags |= ECRYPTFS_DAEMON_MISCDEV_OPEN;
128 file->private_data = daemon;
125 atomic_inc(&ecryptfs_num_miscdev_opens); 129 atomic_inc(&ecryptfs_num_miscdev_opens);
126out_unlock_daemon: 130out_unlock_daemon:
127 mutex_unlock(&daemon->mux); 131 mutex_unlock(&daemon->mux);
@@ -152,9 +156,9 @@ ecryptfs_miscdev_release(struct inode *inode, struct file *file)
152 156
153 mutex_lock(&ecryptfs_daemon_hash_mux); 157 mutex_lock(&ecryptfs_daemon_hash_mux);
154 rc = ecryptfs_find_daemon_by_euid(&daemon, euid, current_user_ns()); 158 rc = ecryptfs_find_daemon_by_euid(&daemon, euid, current_user_ns());
155 BUG_ON(rc || !daemon); 159 if (rc || !daemon)
160 daemon = file->private_data;
156 mutex_lock(&daemon->mux); 161 mutex_lock(&daemon->mux);
157 BUG_ON(daemon->pid != task_pid(current));
158 BUG_ON(!(daemon->flags & ECRYPTFS_DAEMON_MISCDEV_OPEN)); 162 BUG_ON(!(daemon->flags & ECRYPTFS_DAEMON_MISCDEV_OPEN));
159 daemon->flags &= ~ECRYPTFS_DAEMON_MISCDEV_OPEN; 163 daemon->flags &= ~ECRYPTFS_DAEMON_MISCDEV_OPEN;
160 atomic_dec(&ecryptfs_num_miscdev_opens); 164 atomic_dec(&ecryptfs_num_miscdev_opens);
@@ -246,8 +250,16 @@ ecryptfs_miscdev_read(struct file *file, char __user *buf, size_t count,
246 mutex_lock(&ecryptfs_daemon_hash_mux); 250 mutex_lock(&ecryptfs_daemon_hash_mux);
247 /* TODO: Just use file->private_data? */ 251 /* TODO: Just use file->private_data? */
248 rc = ecryptfs_find_daemon_by_euid(&daemon, euid, current_user_ns()); 252 rc = ecryptfs_find_daemon_by_euid(&daemon, euid, current_user_ns());
249 BUG_ON(rc || !daemon); 253 if (rc || !daemon) {
254 mutex_unlock(&ecryptfs_daemon_hash_mux);
255 return -EINVAL;
256 }
250 mutex_lock(&daemon->mux); 257 mutex_lock(&daemon->mux);
258 if (task_pid(current) != daemon->pid) {
259 mutex_unlock(&daemon->mux);
260 mutex_unlock(&ecryptfs_daemon_hash_mux);
261 return -EPERM;
262 }
251 if (daemon->flags & ECRYPTFS_DAEMON_ZOMBIE) { 263 if (daemon->flags & ECRYPTFS_DAEMON_ZOMBIE) {
252 rc = 0; 264 rc = 0;
253 mutex_unlock(&ecryptfs_daemon_hash_mux); 265 mutex_unlock(&ecryptfs_daemon_hash_mux);
@@ -284,9 +296,6 @@ check_list:
284 * message from the queue; try again */ 296 * message from the queue; try again */
285 goto check_list; 297 goto check_list;
286 } 298 }
287 BUG_ON(euid != daemon->euid);
288 BUG_ON(current_user_ns() != daemon->user_ns);
289 BUG_ON(task_pid(current) != daemon->pid);
290 msg_ctx = list_first_entry(&daemon->msg_ctx_out_queue, 299 msg_ctx = list_first_entry(&daemon->msg_ctx_out_queue,
291 struct ecryptfs_msg_ctx, daemon_out_list); 300 struct ecryptfs_msg_ctx, daemon_out_list);
292 BUG_ON(!msg_ctx); 301 BUG_ON(!msg_ctx);