Commit 8dc6780587c99286c0d3de747a2946a76989414a
1 parent
60d65f1f07
Exists in
smarc-l5.0.0_1.0.0-ga
and in
5 other branches
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); |