Commit 8dc6780587c99286c0d3de747a2946a76989414a

Authored by Tyler Hicks
1 parent 60d65f1f07

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>

Showing 1 changed file with 16 additions and 7 deletions Side-by-side Diff

fs/ecryptfs/miscdev.c
... ... @@ -49,7 +49,10 @@
49 49 mutex_lock(&ecryptfs_daemon_hash_mux);
50 50 /* TODO: Just use file->private_data? */
51 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 56 mutex_lock(&daemon->mux);
54 57 mutex_unlock(&ecryptfs_daemon_hash_mux);
55 58 if (daemon->flags & ECRYPTFS_DAEMON_ZOMBIE) {
... ... @@ -122,6 +125,7 @@
122 125 goto out_unlock_daemon;
123 126 }
124 127 daemon->flags |= ECRYPTFS_DAEMON_MISCDEV_OPEN;
  128 + file->private_data = daemon;
125 129 atomic_inc(&ecryptfs_num_miscdev_opens);
126 130 out_unlock_daemon:
127 131 mutex_unlock(&daemon->mux);
128 132  
... ... @@ -152,9 +156,9 @@
152 156  
153 157 mutex_lock(&ecryptfs_daemon_hash_mux);
154 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 161 mutex_lock(&daemon->mux);
157   - BUG_ON(daemon->pid != task_pid(current));
158 162 BUG_ON(!(daemon->flags & ECRYPTFS_DAEMON_MISCDEV_OPEN));
159 163 daemon->flags &= ~ECRYPTFS_DAEMON_MISCDEV_OPEN;
160 164 atomic_dec(&ecryptfs_num_miscdev_opens);
161 165  
... ... @@ -270,8 +274,16 @@
270 274 mutex_lock(&ecryptfs_daemon_hash_mux);
271 275 /* TODO: Just use file->private_data? */
272 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 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 287 if (daemon->flags & ECRYPTFS_DAEMON_ZOMBIE) {
276 288 rc = 0;
277 289 mutex_unlock(&ecryptfs_daemon_hash_mux);
... ... @@ -308,9 +320,6 @@
308 320 * message from the queue; try again */
309 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 323 msg_ctx = list_first_entry(&daemon->msg_ctx_out_queue,
315 324 struct ecryptfs_msg_ctx, daemon_out_list);
316 325 BUG_ON(!msg_ctx);