aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTyler Hicks <tyhicks@canonical.com>2012-06-11 12:24:11 -0400
committerTyler Hicks <tyhicks@canonical.com>2012-07-06 16:51:12 -0400
commit8dc6780587c99286c0d3de747a2946a76989414a (patch)
treed553ed49a104387f898bc93bc226821b83d49583
parent60d65f1f07a7d81d3eb3b91fc13fca80f2fdbb12 (diff)
eCryptfs: Gracefully refuse miscdev file ops on inherited/passed files
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>
-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 3c632ec412ec..c0038f6566d4 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);
@@ -270,8 +274,16 @@ ecryptfs_miscdev_read(struct file *file, char __user *buf, size_t count,
270 mutex_lock(&ecryptfs_daemon_hash_mux); 274 mutex_lock(&ecryptfs_daemon_hash_mux);
271 /* TODO: Just use file->private_data? */ 275 /* TODO: Just use file->private_data? */
272 rc = ecryptfs_find_daemon_by_euid(&daemon, euid, current_user_ns()); 276 rc = ecryptfs_find_daemon_by_euid(&daemon, euid, current_user_ns());
273 BUG_ON(rc || !daemon); 277 if (rc || !daemon) {
278 mutex_unlock(&ecryptfs_daemon_hash_mux);
279 return -EINVAL;
280 }
274 mutex_lock(&daemon->mux); 281 mutex_lock(&daemon->mux);
282 if (task_pid(current) != daemon->pid) {
283 mutex_unlock(&daemon->mux);
284 mutex_unlock(&ecryptfs_daemon_hash_mux);
285 return -EPERM;
286 }
275 if (daemon->flags & ECRYPTFS_DAEMON_ZOMBIE) { 287 if (daemon->flags & ECRYPTFS_DAEMON_ZOMBIE) {
276 rc = 0; 288 rc = 0;
277 mutex_unlock(&ecryptfs_daemon_hash_mux); 289 mutex_unlock(&ecryptfs_daemon_hash_mux);
@@ -308,9 +320,6 @@ check_list:
308 * message from the queue; try again */ 320 * message from the queue; try again */
309 goto check_list; 321 goto check_list;
310 } 322 }
311 BUG_ON(euid != daemon->euid);
312 BUG_ON(current_user_ns() != daemon->user_ns);
313 BUG_ON(task_pid(current) != daemon->pid);
314 msg_ctx = list_first_entry(&daemon->msg_ctx_out_queue, 323 msg_ctx = list_first_entry(&daemon->msg_ctx_out_queue,
315 struct ecryptfs_msg_ctx, daemon_out_list); 324 struct ecryptfs_msg_ctx, daemon_out_list);
316 BUG_ON(!msg_ctx); 325 BUG_ON(!msg_ctx);