Skip to content

Commit 8dc6780

Browse files
committed
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 <[email protected]> Reported-by: Sasha Levin <[email protected]> Tested-by: Sasha Levin <[email protected]>
1 parent 60d65f1 commit 8dc6780

File tree

1 file changed

+16
-7
lines changed

1 file changed

+16
-7
lines changed

fs/ecryptfs/miscdev.c

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,10 @@ ecryptfs_miscdev_poll(struct file *file, poll_table *pt)
4949
mutex_lock(&ecryptfs_daemon_hash_mux);
5050
/* TODO: Just use file->private_data? */
5151
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+
}
5356
mutex_lock(&daemon->mux);
5457
mutex_unlock(&ecryptfs_daemon_hash_mux);
5558
if (daemon->flags & ECRYPTFS_DAEMON_ZOMBIE) {
@@ -122,6 +125,7 @@ ecryptfs_miscdev_open(struct inode *inode, struct file *file)
122125
goto out_unlock_daemon;
123126
}
124127
daemon->flags |= ECRYPTFS_DAEMON_MISCDEV_OPEN;
128+
file->private_data = daemon;
125129
atomic_inc(&ecryptfs_num_miscdev_opens);
126130
out_unlock_daemon:
127131
mutex_unlock(&daemon->mux);
@@ -152,9 +156,9 @@ ecryptfs_miscdev_release(struct inode *inode, struct file *file)
152156

153157
mutex_lock(&ecryptfs_daemon_hash_mux);
154158
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;
156161
mutex_lock(&daemon->mux);
157-
BUG_ON(daemon->pid != task_pid(current));
158162
BUG_ON(!(daemon->flags & ECRYPTFS_DAEMON_MISCDEV_OPEN));
159163
daemon->flags &= ~ECRYPTFS_DAEMON_MISCDEV_OPEN;
160164
atomic_dec(&ecryptfs_num_miscdev_opens);
@@ -270,8 +274,16 @@ ecryptfs_miscdev_read(struct file *file, char __user *buf, size_t count,
270274
mutex_lock(&ecryptfs_daemon_hash_mux);
271275
/* TODO: Just use file->private_data? */
272276
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+
}
274281
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+
}
275287
if (daemon->flags & ECRYPTFS_DAEMON_ZOMBIE) {
276288
rc = 0;
277289
mutex_unlock(&ecryptfs_daemon_hash_mux);
@@ -308,9 +320,6 @@ ecryptfs_miscdev_read(struct file *file, char __user *buf, size_t count,
308320
* message from the queue; try again */
309321
goto check_list;
310322
}
311-
BUG_ON(euid != daemon->euid);
312-
BUG_ON(current_user_ns() != daemon->user_ns);
313-
BUG_ON(task_pid(current) != daemon->pid);
314323
msg_ctx = list_first_entry(&daemon->msg_ctx_out_queue,
315324
struct ecryptfs_msg_ctx, daemon_out_list);
316325
BUG_ON(!msg_ctx);

0 commit comments

Comments
 (0)