diff options
| author | Tyler Hicks <tyhicks@canonical.com> | 2012-06-11 12:47:47 -0400 |
|---|---|---|
| committer | Tyler Hicks <tyhicks@canonical.com> | 2012-07-08 13:51:44 -0400 |
| commit | 2ecaf55db6dcf4dd25e1ef8d5eb6068e3286a20f (patch) | |
| tree | daa89105f89d64579d5ee04a376e4e31543871cf /fs/ecryptfs | |
| parent | 566968866555a19d0a78e0bfa845cd249a7eeae2 (diff) | |
eCryptfs: Make all miscdev functions use daemon ptr in file private_data
Now that a pointer to a valid struct ecryptfs_daemon is stored in the
private_data of an opened /dev/ecryptfs file, the remaining miscdev
functions can utilize the pointer rather than looking up the
ecryptfs_daemon at the beginning of each operation.
The security model of /dev/ecryptfs is simplified a little bit with this
patch. Upon opening /dev/ecryptfs, a per-user ecryptfs_daemon is
registered. Another daemon cannot be registered for that user until the
last file reference is released. During the lifetime of the
ecryptfs_daemon, access checks are not performed on the /dev/ecryptfs
operations because it is assumed that the application securely handles
the opened file descriptor and does not unintentionally leak it to
processes that are not trusted.
Signed-off-by: Tyler Hicks <tyhicks@canonical.com>
Cc: Sasha Levin <levinsasha928@gmail.com>
Diffstat (limited to 'fs/ecryptfs')
| -rw-r--r-- | fs/ecryptfs/ecryptfs_kernel.h | 16 | ||||
| -rw-r--r-- | fs/ecryptfs/messaging.c | 105 | ||||
| -rw-r--r-- | fs/ecryptfs/miscdev.c | 98 |
3 files changed, 47 insertions, 172 deletions
diff --git a/fs/ecryptfs/ecryptfs_kernel.h b/fs/ecryptfs/ecryptfs_kernel.h index 01a1f857595..0deb4f24957 100644 --- a/fs/ecryptfs/ecryptfs_kernel.h +++ b/fs/ecryptfs/ecryptfs_kernel.h | |||
| @@ -392,10 +392,7 @@ struct ecryptfs_daemon { | |||
| 392 | #define ECRYPTFS_DAEMON_MISCDEV_OPEN 0x00000008 | 392 | #define ECRYPTFS_DAEMON_MISCDEV_OPEN 0x00000008 |
| 393 | u32 flags; | 393 | u32 flags; |
| 394 | u32 num_queued_msg_ctx; | 394 | u32 num_queued_msg_ctx; |
| 395 | struct pid *pid; | 395 | struct file *file; |
| 396 | uid_t euid; | ||
| 397 | struct user_namespace *user_ns; | ||
| 398 | struct task_struct *task; | ||
| 399 | struct mutex mux; | 396 | struct mutex mux; |
| 400 | struct list_head msg_ctx_out_queue; | 397 | struct list_head msg_ctx_out_queue; |
| 401 | wait_queue_head_t wait; | 398 | wait_queue_head_t wait; |
| @@ -619,9 +616,8 @@ int | |||
| 619 | ecryptfs_setxattr(struct dentry *dentry, const char *name, const void *value, | 616 | ecryptfs_setxattr(struct dentry *dentry, const char *name, const void *value, |
| 620 | size_t size, int flags); | 617 | size_t size, int flags); |
| 621 | int ecryptfs_read_xattr_region(char *page_virt, struct inode *ecryptfs_inode); | 618 | int ecryptfs_read_xattr_region(char *page_virt, struct inode *ecryptfs_inode); |
| 622 | int ecryptfs_process_response(struct ecryptfs_message *msg, uid_t euid, | 619 | int ecryptfs_process_response(struct ecryptfs_daemon *daemon, |
| 623 | struct user_namespace *user_ns, struct pid *pid, | 620 | struct ecryptfs_message *msg, u32 seq); |
| 624 | u32 seq); | ||
| 625 | int ecryptfs_send_message(char *data, int data_len, | 621 | int ecryptfs_send_message(char *data, int data_len, |
| 626 | struct ecryptfs_msg_ctx **msg_ctx); | 622 | struct ecryptfs_msg_ctx **msg_ctx); |
| 627 | int ecryptfs_wait_for_response(struct ecryptfs_msg_ctx *msg_ctx, | 623 | int ecryptfs_wait_for_response(struct ecryptfs_msg_ctx *msg_ctx, |
| @@ -666,8 +662,7 @@ int ecryptfs_read_lower_page_segment(struct page *page_for_ecryptfs, | |||
| 666 | struct inode *ecryptfs_inode); | 662 | struct inode *ecryptfs_inode); |
| 667 | struct page *ecryptfs_get_locked_page(struct inode *inode, loff_t index); | 663 | struct page *ecryptfs_get_locked_page(struct inode *inode, loff_t index); |
| 668 | int ecryptfs_exorcise_daemon(struct ecryptfs_daemon *daemon); | 664 | int ecryptfs_exorcise_daemon(struct ecryptfs_daemon *daemon); |
| 669 | int ecryptfs_find_daemon_by_euid(struct ecryptfs_daemon **daemon, uid_t euid, | 665 | int ecryptfs_find_daemon_by_euid(struct ecryptfs_daemon **daemon); |
| 670 | struct user_namespace *user_ns); | ||
| 671 | int ecryptfs_parse_packet_length(unsigned char *data, size_t *size, | 666 | int ecryptfs_parse_packet_length(unsigned char *data, size_t *size, |
| 672 | size_t *length_size); | 667 | size_t *length_size); |
| 673 | int ecryptfs_write_packet_length(char *dest, size_t size, | 668 | int ecryptfs_write_packet_length(char *dest, size_t size, |
| @@ -679,8 +674,7 @@ int ecryptfs_send_miscdev(char *data, size_t data_size, | |||
| 679 | u16 msg_flags, struct ecryptfs_daemon *daemon); | 674 | u16 msg_flags, struct ecryptfs_daemon *daemon); |
| 680 | void ecryptfs_msg_ctx_alloc_to_free(struct ecryptfs_msg_ctx *msg_ctx); | 675 | void ecryptfs_msg_ctx_alloc_to_free(struct ecryptfs_msg_ctx *msg_ctx); |
| 681 | int | 676 | int |
| 682 | ecryptfs_spawn_daemon(struct ecryptfs_daemon **daemon, uid_t euid, | 677 | ecryptfs_spawn_daemon(struct ecryptfs_daemon **daemon, struct file *file); |
| 683 | struct user_namespace *user_ns, struct pid *pid); | ||
| 684 | int ecryptfs_init_kthread(void); | 678 | int ecryptfs_init_kthread(void); |
| 685 | void ecryptfs_destroy_kthread(void); | 679 | void ecryptfs_destroy_kthread(void); |
| 686 | int ecryptfs_privileged_open(struct file **lower_file, | 680 | int ecryptfs_privileged_open(struct file **lower_file, |
diff --git a/fs/ecryptfs/messaging.c b/fs/ecryptfs/messaging.c index c11911decdc..b29bb8bfa8d 100644 --- a/fs/ecryptfs/messaging.c +++ b/fs/ecryptfs/messaging.c | |||
| @@ -32,8 +32,8 @@ static struct mutex ecryptfs_msg_ctx_lists_mux; | |||
| 32 | static struct hlist_head *ecryptfs_daemon_hash; | 32 | static struct hlist_head *ecryptfs_daemon_hash; |
| 33 | struct mutex ecryptfs_daemon_hash_mux; | 33 | struct mutex ecryptfs_daemon_hash_mux; |
| 34 | static int ecryptfs_hash_bits; | 34 | static int ecryptfs_hash_bits; |
| 35 | #define ecryptfs_uid_hash(uid) \ | 35 | #define ecryptfs_current_euid_hash(uid) \ |
| 36 | hash_long((unsigned long)uid, ecryptfs_hash_bits) | 36 | hash_long((unsigned long)current_euid(), ecryptfs_hash_bits) |
| 37 | 37 | ||
| 38 | static u32 ecryptfs_msg_counter; | 38 | static u32 ecryptfs_msg_counter; |
| 39 | static struct ecryptfs_msg_ctx *ecryptfs_msg_ctx_arr; | 39 | static struct ecryptfs_msg_ctx *ecryptfs_msg_ctx_arr; |
| @@ -105,26 +105,24 @@ void ecryptfs_msg_ctx_alloc_to_free(struct ecryptfs_msg_ctx *msg_ctx) | |||
| 105 | 105 | ||
| 106 | /** | 106 | /** |
| 107 | * ecryptfs_find_daemon_by_euid | 107 | * ecryptfs_find_daemon_by_euid |
| 108 | * @euid: The effective user id which maps to the desired daemon id | ||
| 109 | * @user_ns: The namespace in which @euid applies | ||
| 110 | * @daemon: If return value is zero, points to the desired daemon pointer | 108 | * @daemon: If return value is zero, points to the desired daemon pointer |
| 111 | * | 109 | * |
| 112 | * Must be called with ecryptfs_daemon_hash_mux held. | 110 | * Must be called with ecryptfs_daemon_hash_mux held. |
| 113 | * | 111 | * |
| 114 | * Search the hash list for the given user id. | 112 | * Search the hash list for the current effective user id. |
| 115 | * | 113 | * |
| 116 | * Returns zero if the user id exists in the list; non-zero otherwise. | 114 | * Returns zero if the user id exists in the list; non-zero otherwise. |
| 117 | */ | 115 | */ |
| 118 | int ecryptfs_find_daemon_by_euid(struct ecryptfs_daemon **daemon, uid_t euid, | 116 | int ecryptfs_find_daemon_by_euid(struct ecryptfs_daemon **daemon) |
| 119 | struct user_namespace *user_ns) | ||
| 120 | { | 117 | { |
| 121 | struct hlist_node *elem; | 118 | struct hlist_node *elem; |
| 122 | int rc; | 119 | int rc; |
| 123 | 120 | ||
| 124 | hlist_for_each_entry(*daemon, elem, | 121 | hlist_for_each_entry(*daemon, elem, |
| 125 | &ecryptfs_daemon_hash[ecryptfs_uid_hash(euid)], | 122 | &ecryptfs_daemon_hash[ecryptfs_current_euid_hash()], |
| 126 | euid_chain) { | 123 | euid_chain) { |
| 127 | if ((*daemon)->euid == euid && (*daemon)->user_ns == user_ns) { | 124 | if ((*daemon)->file->f_cred->euid == current_euid() && |
| 125 | (*daemon)->file->f_cred->user_ns == current_user_ns()) { | ||
| 128 | rc = 0; | 126 | rc = 0; |
| 129 | goto out; | 127 | goto out; |
| 130 | } | 128 | } |
| @@ -137,9 +135,7 @@ out: | |||
| 137 | /** | 135 | /** |
| 138 | * ecryptfs_spawn_daemon - Create and initialize a new daemon struct | 136 | * ecryptfs_spawn_daemon - Create and initialize a new daemon struct |
| 139 | * @daemon: Pointer to set to newly allocated daemon struct | 137 | * @daemon: Pointer to set to newly allocated daemon struct |
| 140 | * @euid: Effective user id for the daemon | 138 | * @file: File used when opening /dev/ecryptfs |
| 141 | * @user_ns: The namespace in which @euid applies | ||
| 142 | * @pid: Process id for the daemon | ||
| 143 | * | 139 | * |
| 144 | * Must be called ceremoniously while in possession of | 140 | * Must be called ceremoniously while in possession of |
| 145 | * ecryptfs_sacred_daemon_hash_mux | 141 | * ecryptfs_sacred_daemon_hash_mux |
| @@ -147,8 +143,7 @@ out: | |||
| 147 | * Returns zero on success; non-zero otherwise | 143 | * Returns zero on success; non-zero otherwise |
| 148 | */ | 144 | */ |
| 149 | int | 145 | int |
| 150 | ecryptfs_spawn_daemon(struct ecryptfs_daemon **daemon, uid_t euid, | 146 | ecryptfs_spawn_daemon(struct ecryptfs_daemon **daemon, struct file *file) |
| 151 | struct user_namespace *user_ns, struct pid *pid) | ||
| 152 | { | 147 | { |
| 153 | int rc = 0; | 148 | int rc = 0; |
| 154 | 149 | ||
| @@ -159,16 +154,13 @@ ecryptfs_spawn_daemon(struct ecryptfs_daemon **daemon, uid_t euid, | |||
| 159 | "GFP_KERNEL memory\n", __func__, sizeof(**daemon)); | 154 | "GFP_KERNEL memory\n", __func__, sizeof(**daemon)); |
| 160 | goto out; | 155 | goto out; |
| 161 | } | 156 | } |
| 162 | (*daemon)->euid = euid; | 157 | (*daemon)->file = file; |
| 163 | (*daemon)->user_ns = get_user_ns(user_ns); | ||
| 164 | (*daemon)->pid = get_pid(pid); | ||
| 165 | (*daemon)->task = current; | ||
| 166 | mutex_init(&(*daemon)->mux); | 158 | mutex_init(&(*daemon)->mux); |
| 167 | INIT_LIST_HEAD(&(*daemon)->msg_ctx_out_queue); | 159 | INIT_LIST_HEAD(&(*daemon)->msg_ctx_out_queue); |
| 168 | init_waitqueue_head(&(*daemon)->wait); | 160 | init_waitqueue_head(&(*daemon)->wait); |
| 169 | (*daemon)->num_queued_msg_ctx = 0; | 161 | (*daemon)->num_queued_msg_ctx = 0; |
| 170 | hlist_add_head(&(*daemon)->euid_chain, | 162 | hlist_add_head(&(*daemon)->euid_chain, |
| 171 | &ecryptfs_daemon_hash[ecryptfs_uid_hash(euid)]); | 163 | &ecryptfs_daemon_hash[ecryptfs_current_euid_hash()]); |
| 172 | out: | 164 | out: |
| 173 | return rc; | 165 | return rc; |
| 174 | } | 166 | } |
| @@ -188,9 +180,6 @@ int ecryptfs_exorcise_daemon(struct ecryptfs_daemon *daemon) | |||
| 188 | if ((daemon->flags & ECRYPTFS_DAEMON_IN_READ) | 180 | if ((daemon->flags & ECRYPTFS_DAEMON_IN_READ) |
| 189 | || (daemon->flags & ECRYPTFS_DAEMON_IN_POLL)) { | 181 | || (daemon->flags & ECRYPTFS_DAEMON_IN_POLL)) { |
| 190 | rc = -EBUSY; | 182 | rc = -EBUSY; |
| 191 | printk(KERN_WARNING "%s: Attempt to destroy daemon with pid " | ||
| 192 | "[0x%p], but it is in the midst of a read or a poll\n", | ||
| 193 | __func__, daemon->pid); | ||
| 194 | mutex_unlock(&daemon->mux); | 183 | mutex_unlock(&daemon->mux); |
| 195 | goto out; | 184 | goto out; |
| 196 | } | 185 | } |
| @@ -203,12 +192,6 @@ int ecryptfs_exorcise_daemon(struct ecryptfs_daemon *daemon) | |||
| 203 | ecryptfs_msg_ctx_alloc_to_free(msg_ctx); | 192 | ecryptfs_msg_ctx_alloc_to_free(msg_ctx); |
| 204 | } | 193 | } |
| 205 | hlist_del(&daemon->euid_chain); | 194 | hlist_del(&daemon->euid_chain); |
| 206 | if (daemon->task) | ||
| 207 | wake_up_process(daemon->task); | ||
| 208 | if (daemon->pid) | ||
| 209 | put_pid(daemon->pid); | ||
| 210 | if (daemon->user_ns) | ||
| 211 | put_user_ns(daemon->user_ns); | ||
| 212 | mutex_unlock(&daemon->mux); | 195 | mutex_unlock(&daemon->mux); |
| 213 | kzfree(daemon); | 196 | kzfree(daemon); |
| 214 | out: | 197 | out: |
| @@ -219,8 +202,6 @@ out: | |||
| 219 | * ecryptfs_process_reponse | 202 | * ecryptfs_process_reponse |
| 220 | * @msg: The ecryptfs message received; the caller should sanity check | 203 | * @msg: The ecryptfs message received; the caller should sanity check |
| 221 | * msg->data_len and free the memory | 204 | * msg->data_len and free the memory |
| 222 | * @pid: The process ID of the userspace application that sent the | ||
| 223 | * message | ||
| 224 | * @seq: The sequence number of the message; must match the sequence | 205 | * @seq: The sequence number of the message; must match the sequence |
| 225 | * number for the existing message context waiting for this | 206 | * number for the existing message context waiting for this |
| 226 | * response | 207 | * response |
| @@ -239,16 +220,11 @@ out: | |||
| 239 | * | 220 | * |
| 240 | * Returns zero on success; non-zero otherwise | 221 | * Returns zero on success; non-zero otherwise |
| 241 | */ | 222 | */ |
| 242 | int ecryptfs_process_response(struct ecryptfs_message *msg, uid_t euid, | 223 | int ecryptfs_process_response(struct ecryptfs_daemon *daemon, |
| 243 | struct user_namespace *user_ns, struct pid *pid, | 224 | struct ecryptfs_message *msg, u32 seq) |
| 244 | u32 seq) | ||
| 245 | { | 225 | { |
| 246 | struct ecryptfs_daemon *uninitialized_var(daemon); | ||
| 247 | struct ecryptfs_msg_ctx *msg_ctx; | 226 | struct ecryptfs_msg_ctx *msg_ctx; |
| 248 | size_t msg_size; | 227 | size_t msg_size; |
| 249 | struct nsproxy *nsproxy; | ||
| 250 | struct user_namespace *tsk_user_ns; | ||
| 251 | uid_t ctx_euid; | ||
| 252 | int rc; | 228 | int rc; |
| 253 | 229 | ||
| 254 | if (msg->index >= ecryptfs_message_buf_len) { | 230 | if (msg->index >= ecryptfs_message_buf_len) { |
| @@ -261,51 +237,6 @@ int ecryptfs_process_response(struct ecryptfs_message *msg, uid_t euid, | |||
| 261 | } | 237 | } |
| 262 | msg_ctx = &ecryptfs_msg_ctx_arr[msg->index]; | 238 | msg_ctx = &ecryptfs_msg_ctx_arr[msg->index]; |
| 263 | mutex_lock(&msg_ctx->mux); | 239 | mutex_lock(&msg_ctx->mux); |
| 264 | mutex_lock(&ecryptfs_daemon_hash_mux); | ||
| 265 | rcu_read_lock(); | ||
| 266 | nsproxy = task_nsproxy(msg_ctx->task); | ||
| 267 | if (nsproxy == NULL) { | ||
| 268 | rc = -EBADMSG; | ||
| 269 | printk(KERN_ERR "%s: Receiving process is a zombie. Dropping " | ||
| 270 | "message.\n", __func__); | ||
| 271 | rcu_read_unlock(); | ||
| 272 | mutex_unlock(&ecryptfs_daemon_hash_mux); | ||
| 273 | goto wake_up; | ||
| 274 | } | ||
| 275 | tsk_user_ns = __task_cred(msg_ctx->task)->user_ns; | ||
| 276 | ctx_euid = task_euid(msg_ctx->task); | ||
| 277 | rc = ecryptfs_find_daemon_by_euid(&daemon, ctx_euid, tsk_user_ns); | ||
| 278 | rcu_read_unlock(); | ||
| 279 | mutex_unlock(&ecryptfs_daemon_hash_mux); | ||
| 280 | if (rc) { | ||
| 281 | rc = -EBADMSG; | ||
| 282 | printk(KERN_WARNING "%s: User [%d] received a " | ||
| 283 | "message response from process [0x%p] but does " | ||
| 284 | "not have a registered daemon\n", __func__, | ||
| 285 | ctx_euid, pid); | ||
| 286 | goto wake_up; | ||
| 287 | } | ||
| 288 | if (ctx_euid != euid) { | ||
| 289 | rc = -EBADMSG; | ||
| 290 | printk(KERN_WARNING "%s: Received message from user " | ||
| 291 | "[%d]; expected message from user [%d]\n", __func__, | ||
| 292 | euid, ctx_euid); | ||
| 293 | goto unlock; | ||
| 294 | } | ||
| 295 | if (tsk_user_ns != user_ns) { | ||
| 296 | rc = -EBADMSG; | ||
| 297 | printk(KERN_WARNING "%s: Received message from user_ns " | ||
| 298 | "[0x%p]; expected message from user_ns [0x%p]\n", | ||
| 299 | __func__, user_ns, tsk_user_ns); | ||
| 300 | goto unlock; | ||
| 301 | } | ||
| 302 | if (daemon->pid != pid) { | ||
| 303 | rc = -EBADMSG; | ||
| 304 | printk(KERN_ERR "%s: User [%d] sent a message response " | ||
| 305 | "from an unrecognized process [0x%p]\n", | ||
| 306 | __func__, ctx_euid, pid); | ||
| 307 | goto unlock; | ||
| 308 | } | ||
| 309 | if (msg_ctx->state != ECRYPTFS_MSG_CTX_STATE_PENDING) { | 240 | if (msg_ctx->state != ECRYPTFS_MSG_CTX_STATE_PENDING) { |
| 310 | rc = -EINVAL; | 241 | rc = -EINVAL; |
| 311 | printk(KERN_WARNING "%s: Desired context element is not " | 242 | printk(KERN_WARNING "%s: Desired context element is not " |
| @@ -328,9 +259,8 @@ int ecryptfs_process_response(struct ecryptfs_message *msg, uid_t euid, | |||
| 328 | } | 259 | } |
| 329 | memcpy(msg_ctx->msg, msg, msg_size); | 260 | memcpy(msg_ctx->msg, msg, msg_size); |
| 330 | msg_ctx->state = ECRYPTFS_MSG_CTX_STATE_DONE; | 261 | msg_ctx->state = ECRYPTFS_MSG_CTX_STATE_DONE; |
| 331 | rc = 0; | ||
| 332 | wake_up: | ||
| 333 | wake_up_process(msg_ctx->task); | 262 | wake_up_process(msg_ctx->task); |
| 263 | rc = 0; | ||
| 334 | unlock: | 264 | unlock: |
| 335 | mutex_unlock(&msg_ctx->mux); | 265 | mutex_unlock(&msg_ctx->mux); |
| 336 | out: | 266 | out: |
| @@ -352,14 +282,11 @@ ecryptfs_send_message_locked(char *data, int data_len, u8 msg_type, | |||
| 352 | struct ecryptfs_msg_ctx **msg_ctx) | 282 | struct ecryptfs_msg_ctx **msg_ctx) |
| 353 | { | 283 | { |
| 354 | struct ecryptfs_daemon *daemon; | 284 | struct ecryptfs_daemon *daemon; |
| 355 | uid_t euid = current_euid(); | ||
| 356 | int rc; | 285 | int rc; |
| 357 | 286 | ||
| 358 | rc = ecryptfs_find_daemon_by_euid(&daemon, euid, current_user_ns()); | 287 | rc = ecryptfs_find_daemon_by_euid(&daemon); |
| 359 | if (rc || !daemon) { | 288 | if (rc || !daemon) { |
| 360 | rc = -ENOTCONN; | 289 | rc = -ENOTCONN; |
| 361 | printk(KERN_ERR "%s: User [%d] does not have a daemon " | ||
| 362 | "registered\n", __func__, euid); | ||
| 363 | goto out; | 290 | goto out; |
| 364 | } | 291 | } |
| 365 | mutex_lock(&ecryptfs_msg_ctx_lists_mux); | 292 | mutex_lock(&ecryptfs_msg_ctx_lists_mux); |
diff --git a/fs/ecryptfs/miscdev.c b/fs/ecryptfs/miscdev.c index c0038f6566d..412e6eda25f 100644 --- a/fs/ecryptfs/miscdev.c +++ b/fs/ecryptfs/miscdev.c | |||
| @@ -33,7 +33,7 @@ static atomic_t ecryptfs_num_miscdev_opens; | |||
| 33 | 33 | ||
| 34 | /** | 34 | /** |
| 35 | * ecryptfs_miscdev_poll | 35 | * ecryptfs_miscdev_poll |
| 36 | * @file: dev file (ignored) | 36 | * @file: dev file |
| 37 | * @pt: dev poll table (ignored) | 37 | * @pt: dev poll table (ignored) |
| 38 | * | 38 | * |
| 39 | * Returns the poll mask | 39 | * Returns the poll mask |
| @@ -41,20 +41,10 @@ static atomic_t ecryptfs_num_miscdev_opens; | |||
| 41 | static unsigned int | 41 | static unsigned int |
| 42 | ecryptfs_miscdev_poll(struct file *file, poll_table *pt) | 42 | ecryptfs_miscdev_poll(struct file *file, poll_table *pt) |
| 43 | { | 43 | { |
| 44 | struct ecryptfs_daemon *daemon; | 44 | struct ecryptfs_daemon *daemon = file->private_data; |
| 45 | unsigned int mask = 0; | 45 | unsigned int mask = 0; |
| 46 | uid_t euid = current_euid(); | ||
| 47 | int rc; | ||
| 48 | 46 | ||
| 49 | mutex_lock(&ecryptfs_daemon_hash_mux); | ||
| 50 | /* TODO: Just use file->private_data? */ | ||
| 51 | rc = ecryptfs_find_daemon_by_euid(&daemon, euid, current_user_ns()); | ||
| 52 | if (rc || !daemon) { | ||
| 53 | mutex_unlock(&ecryptfs_daemon_hash_mux); | ||
| 54 | return -EINVAL; | ||
| 55 | } | ||
| 56 | mutex_lock(&daemon->mux); | 47 | mutex_lock(&daemon->mux); |
| 57 | mutex_unlock(&ecryptfs_daemon_hash_mux); | ||
| 58 | if (daemon->flags & ECRYPTFS_DAEMON_ZOMBIE) { | 48 | if (daemon->flags & ECRYPTFS_DAEMON_ZOMBIE) { |
| 59 | printk(KERN_WARNING "%s: Attempt to poll on zombified " | 49 | printk(KERN_WARNING "%s: Attempt to poll on zombified " |
| 60 | "daemon\n", __func__); | 50 | "daemon\n", __func__); |
| @@ -79,7 +69,7 @@ out_unlock_daemon: | |||
| 79 | /** | 69 | /** |
| 80 | * ecryptfs_miscdev_open | 70 | * ecryptfs_miscdev_open |
| 81 | * @inode: inode of miscdev handle (ignored) | 71 | * @inode: inode of miscdev handle (ignored) |
| 82 | * @file: file for miscdev handle (ignored) | 72 | * @file: file for miscdev handle |
| 83 | * | 73 | * |
| 84 | * Returns zero on success; non-zero otherwise | 74 | * Returns zero on success; non-zero otherwise |
| 85 | */ | 75 | */ |
| @@ -87,7 +77,6 @@ static int | |||
| 87 | ecryptfs_miscdev_open(struct inode *inode, struct file *file) | 77 | ecryptfs_miscdev_open(struct inode *inode, struct file *file) |
| 88 | { | 78 | { |
| 89 | struct ecryptfs_daemon *daemon = NULL; | 79 | struct ecryptfs_daemon *daemon = NULL; |
| 90 | uid_t euid = current_euid(); | ||
| 91 | int rc; | 80 | int rc; |
| 92 | 81 | ||
| 93 | mutex_lock(&ecryptfs_daemon_hash_mux); | 82 | mutex_lock(&ecryptfs_daemon_hash_mux); |
| @@ -98,30 +87,20 @@ ecryptfs_miscdev_open(struct inode *inode, struct file *file) | |||
| 98 | "count; rc = [%d]\n", __func__, rc); | 87 | "count; rc = [%d]\n", __func__, rc); |
| 99 | goto out_unlock_daemon_list; | 88 | goto out_unlock_daemon_list; |
| 100 | } | 89 | } |
| 101 | rc = ecryptfs_find_daemon_by_euid(&daemon, euid, current_user_ns()); | 90 | rc = ecryptfs_find_daemon_by_euid(&daemon); |
| 102 | if (rc || !daemon) { | 91 | if (!rc) { |
| 103 | rc = ecryptfs_spawn_daemon(&daemon, euid, current_user_ns(), | ||
| 104 | task_pid(current)); | ||
| 105 | if (rc) { | ||
| 106 | printk(KERN_ERR "%s: Error attempting to spawn daemon; " | ||
| 107 | "rc = [%d]\n", __func__, rc); | ||
| 108 | goto out_module_put_unlock_daemon_list; | ||
| 109 | } | ||
| 110 | } | ||
| 111 | mutex_lock(&daemon->mux); | ||
| 112 | if (daemon->pid != task_pid(current)) { | ||
| 113 | rc = -EINVAL; | 92 | rc = -EINVAL; |
| 114 | printk(KERN_ERR "%s: pid [0x%p] has registered with euid [%d], " | 93 | goto out_unlock_daemon_list; |
| 115 | "but pid [0x%p] has attempted to open the handle " | 94 | } |
| 116 | "instead\n", __func__, daemon->pid, daemon->euid, | 95 | rc = ecryptfs_spawn_daemon(&daemon, file); |
| 117 | task_pid(current)); | 96 | if (rc) { |
| 118 | goto out_unlock_daemon; | 97 | printk(KERN_ERR "%s: Error attempting to spawn daemon; " |
| 98 | "rc = [%d]\n", __func__, rc); | ||
| 99 | goto out_module_put_unlock_daemon_list; | ||
| 119 | } | 100 | } |
| 101 | mutex_lock(&daemon->mux); | ||
| 120 | if (daemon->flags & ECRYPTFS_DAEMON_MISCDEV_OPEN) { | 102 | if (daemon->flags & ECRYPTFS_DAEMON_MISCDEV_OPEN) { |
| 121 | rc = -EBUSY; | 103 | rc = -EBUSY; |
| 122 | printk(KERN_ERR "%s: Miscellaneous device handle may only be " | ||
| 123 | "opened once per daemon; pid [0x%p] already has this " | ||
| 124 | "handle open\n", __func__, daemon->pid); | ||
| 125 | goto out_unlock_daemon; | 104 | goto out_unlock_daemon; |
| 126 | } | 105 | } |
| 127 | daemon->flags |= ECRYPTFS_DAEMON_MISCDEV_OPEN; | 106 | daemon->flags |= ECRYPTFS_DAEMON_MISCDEV_OPEN; |
| @@ -140,7 +119,7 @@ out_unlock_daemon_list: | |||
| 140 | /** | 119 | /** |
| 141 | * ecryptfs_miscdev_release | 120 | * ecryptfs_miscdev_release |
| 142 | * @inode: inode of fs/ecryptfs/euid handle (ignored) | 121 | * @inode: inode of fs/ecryptfs/euid handle (ignored) |
| 143 | * @file: file for fs/ecryptfs/euid handle (ignored) | 122 | * @file: file for fs/ecryptfs/euid handle |
| 144 | * | 123 | * |
| 145 | * This keeps the daemon registered until the daemon sends another | 124 | * This keeps the daemon registered until the daemon sends another |
| 146 | * ioctl to fs/ecryptfs/ctl or until the kernel module unregisters. | 125 | * ioctl to fs/ecryptfs/ctl or until the kernel module unregisters. |
| @@ -150,20 +129,18 @@ out_unlock_daemon_list: | |||
| 150 | static int | 129 | static int |
| 151 | ecryptfs_miscdev_release(struct inode *inode, struct file *file) | 130 | ecryptfs_miscdev_release(struct inode *inode, struct file *file) |
| 152 | { | 131 | { |
| 153 | struct ecryptfs_daemon *daemon = NULL; | 132 | struct ecryptfs_daemon *daemon = file->private_data; |
| 154 | uid_t euid = current_euid(); | ||
| 155 | int rc; | 133 | int rc; |
| 156 | 134 | ||
| 157 | mutex_lock(&ecryptfs_daemon_hash_mux); | ||
| 158 | rc = ecryptfs_find_daemon_by_euid(&daemon, euid, current_user_ns()); | ||
| 159 | if (rc || !daemon) | ||
| 160 | daemon = file->private_data; | ||
| 161 | mutex_lock(&daemon->mux); | 135 | mutex_lock(&daemon->mux); |
| 162 | BUG_ON(!(daemon->flags & ECRYPTFS_DAEMON_MISCDEV_OPEN)); | 136 | BUG_ON(!(daemon->flags & ECRYPTFS_DAEMON_MISCDEV_OPEN)); |
| 163 | daemon->flags &= ~ECRYPTFS_DAEMON_MISCDEV_OPEN; | 137 | daemon->flags &= ~ECRYPTFS_DAEMON_MISCDEV_OPEN; |
| 164 | atomic_dec(&ecryptfs_num_miscdev_opens); | 138 | atomic_dec(&ecryptfs_num_miscdev_opens); |
| 165 | mutex_unlock(&daemon->mux); | 139 | mutex_unlock(&daemon->mux); |
| 140 | |||
| 141 | mutex_lock(&ecryptfs_daemon_hash_mux); | ||
| 166 | rc = ecryptfs_exorcise_daemon(daemon); | 142 | rc = ecryptfs_exorcise_daemon(daemon); |
| 143 | mutex_unlock(&ecryptfs_daemon_hash_mux); | ||
| 167 | if (rc) { | 144 | if (rc) { |
| 168 | printk(KERN_CRIT "%s: Fatal error whilst attempting to " | 145 | printk(KERN_CRIT "%s: Fatal error whilst attempting to " |
| 169 | "shut down daemon; rc = [%d]. Please report this " | 146 | "shut down daemon; rc = [%d]. Please report this " |
| @@ -171,7 +148,6 @@ ecryptfs_miscdev_release(struct inode *inode, struct file *file) | |||
| 171 | BUG(); | 148 | BUG(); |
| 172 | } | 149 | } |
| 173 | module_put(THIS_MODULE); | 150 | module_put(THIS_MODULE); |
| 174 | mutex_unlock(&ecryptfs_daemon_hash_mux); | ||
| 175 | return rc; | 151 | return rc; |
| 176 | } | 152 | } |
| 177 | 153 | ||
| @@ -248,7 +224,7 @@ int ecryptfs_send_miscdev(char *data, size_t data_size, | |||
| 248 | 224 | ||
| 249 | /** | 225 | /** |
| 250 | * ecryptfs_miscdev_read - format and send message from queue | 226 | * ecryptfs_miscdev_read - format and send message from queue |
| 251 | * @file: fs/ecryptfs/euid miscdevfs handle (ignored) | 227 | * @file: miscdevfs handle |
| 252 | * @buf: User buffer into which to copy the next message on the daemon queue | 228 | * @buf: User buffer into which to copy the next message on the daemon queue |
| 253 | * @count: Amount of space available in @buf | 229 | * @count: Amount of space available in @buf |
| 254 | * @ppos: Offset in file (ignored) | 230 | * @ppos: Offset in file (ignored) |
| @@ -262,43 +238,27 @@ static ssize_t | |||
| 262 | ecryptfs_miscdev_read(struct file *file, char __user *buf, size_t count, | 238 | ecryptfs_miscdev_read(struct file *file, char __user *buf, size_t count, |
| 263 | loff_t *ppos) | 239 | loff_t *ppos) |
| 264 | { | 240 | { |
| 265 | struct ecryptfs_daemon *daemon; | 241 | struct ecryptfs_daemon *daemon = file->private_data; |
| 266 | struct ecryptfs_msg_ctx *msg_ctx; | 242 | struct ecryptfs_msg_ctx *msg_ctx; |
| 267 | size_t packet_length_size; | 243 | size_t packet_length_size; |
| 268 | char packet_length[ECRYPTFS_MAX_PKT_LEN_SIZE]; | 244 | char packet_length[ECRYPTFS_MAX_PKT_LEN_SIZE]; |
| 269 | size_t i; | 245 | size_t i; |
| 270 | size_t total_length; | 246 | size_t total_length; |
| 271 | uid_t euid = current_euid(); | ||
| 272 | int rc; | 247 | int rc; |
| 273 | 248 | ||
| 274 | mutex_lock(&ecryptfs_daemon_hash_mux); | ||
| 275 | /* TODO: Just use file->private_data? */ | ||
| 276 | rc = ecryptfs_find_daemon_by_euid(&daemon, euid, current_user_ns()); | ||
| 277 | if (rc || !daemon) { | ||
| 278 | mutex_unlock(&ecryptfs_daemon_hash_mux); | ||
| 279 | return -EINVAL; | ||
| 280 | } | ||
| 281 | mutex_lock(&daemon->mux); | 249 | 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 | } | ||
| 287 | if (daemon->flags & ECRYPTFS_DAEMON_ZOMBIE) { | 250 | if (daemon->flags & ECRYPTFS_DAEMON_ZOMBIE) { |
| 288 | rc = 0; | 251 | rc = 0; |
| 289 | mutex_unlock(&ecryptfs_daemon_hash_mux); | ||
| 290 | printk(KERN_WARNING "%s: Attempt to read from zombified " | 252 | printk(KERN_WARNING "%s: Attempt to read from zombified " |
| 291 | "daemon\n", __func__); | 253 | "daemon\n", __func__); |
| 292 | goto out_unlock_daemon; | 254 | goto out_unlock_daemon; |
| 293 | } | 255 | } |
| 294 | if (daemon->flags & ECRYPTFS_DAEMON_IN_READ) { | 256 | if (daemon->flags & ECRYPTFS_DAEMON_IN_READ) { |
| 295 | rc = 0; | 257 | rc = 0; |
| 296 | mutex_unlock(&ecryptfs_daemon_hash_mux); | ||
| 297 | goto out_unlock_daemon; | 258 | goto out_unlock_daemon; |
| 298 | } | 259 | } |
| 299 | /* This daemon will not go away so long as this flag is set */ | 260 | /* This daemon will not go away so long as this flag is set */ |
| 300 | daemon->flags |= ECRYPTFS_DAEMON_IN_READ; | 261 | daemon->flags |= ECRYPTFS_DAEMON_IN_READ; |
| 301 | mutex_unlock(&ecryptfs_daemon_hash_mux); | ||
| 302 | check_list: | 262 | check_list: |
| 303 | if (list_empty(&daemon->msg_ctx_out_queue)) { | 263 | if (list_empty(&daemon->msg_ctx_out_queue)) { |
| 304 | mutex_unlock(&daemon->mux); | 264 | mutex_unlock(&daemon->mux); |
| @@ -382,16 +342,12 @@ out_unlock_daemon: | |||
| 382 | * ecryptfs_miscdev_response - miscdevess response to message previously sent to daemon | 342 | * ecryptfs_miscdev_response - miscdevess response to message previously sent to daemon |
| 383 | * @data: Bytes comprising struct ecryptfs_message | 343 | * @data: Bytes comprising struct ecryptfs_message |
| 384 | * @data_size: sizeof(struct ecryptfs_message) + data len | 344 | * @data_size: sizeof(struct ecryptfs_message) + data len |
| 385 | * @euid: Effective user id of miscdevess sending the miscdev response | ||
| 386 | * @user_ns: The namespace in which @euid applies | ||
| 387 | * @pid: Miscdevess id of miscdevess sending the miscdev response | ||
| 388 | * @seq: Sequence number for miscdev response packet | 345 | * @seq: Sequence number for miscdev response packet |
| 389 | * | 346 | * |
| 390 | * Returns zero on success; non-zero otherwise | 347 | * Returns zero on success; non-zero otherwise |
| 391 | */ | 348 | */ |
| 392 | static int ecryptfs_miscdev_response(char *data, size_t data_size, | 349 | static int ecryptfs_miscdev_response(struct ecryptfs_daemon *daemon, char *data, |
| 393 | uid_t euid, struct user_namespace *user_ns, | 350 | size_t data_size, u32 seq) |
| 394 | struct pid *pid, u32 seq) | ||
| 395 | { | 351 | { |
| 396 | struct ecryptfs_message *msg = (struct ecryptfs_message *)data; | 352 | struct ecryptfs_message *msg = (struct ecryptfs_message *)data; |
| 397 | int rc; | 353 | int rc; |
| @@ -403,7 +359,7 @@ static int ecryptfs_miscdev_response(char *data, size_t data_size, | |||
| 403 | rc = -EINVAL; | 359 | rc = -EINVAL; |
| 404 | goto out; | 360 | goto out; |
| 405 | } | 361 | } |
| 406 | rc = ecryptfs_process_response(msg, euid, user_ns, pid, seq); | 362 | rc = ecryptfs_process_response(daemon, msg, seq); |
| 407 | if (rc) | 363 | if (rc) |
| 408 | printk(KERN_ERR | 364 | printk(KERN_ERR |
| 409 | "Error processing response message; rc = [%d]\n", rc); | 365 | "Error processing response message; rc = [%d]\n", rc); |
| @@ -413,7 +369,7 @@ out: | |||
| 413 | 369 | ||
| 414 | /** | 370 | /** |
| 415 | * ecryptfs_miscdev_write - handle write to daemon miscdev handle | 371 | * ecryptfs_miscdev_write - handle write to daemon miscdev handle |
| 416 | * @file: File for misc dev handle (ignored) | 372 | * @file: File for misc dev handle |
| 417 | * @buf: Buffer containing user data | 373 | * @buf: Buffer containing user data |
| 418 | * @count: Amount of data in @buf | 374 | * @count: Amount of data in @buf |
| 419 | * @ppos: Pointer to offset in file (ignored) | 375 | * @ppos: Pointer to offset in file (ignored) |
| @@ -428,7 +384,6 @@ ecryptfs_miscdev_write(struct file *file, const char __user *buf, | |||
| 428 | u32 seq; | 384 | u32 seq; |
| 429 | size_t packet_size, packet_size_length; | 385 | size_t packet_size, packet_size_length; |
| 430 | char *data; | 386 | char *data; |
| 431 | uid_t euid = current_euid(); | ||
| 432 | unsigned char packet_size_peek[ECRYPTFS_MAX_PKT_LEN_SIZE]; | 387 | unsigned char packet_size_peek[ECRYPTFS_MAX_PKT_LEN_SIZE]; |
| 433 | ssize_t rc; | 388 | ssize_t rc; |
| 434 | 389 | ||
| @@ -488,10 +443,9 @@ memdup: | |||
| 488 | } | 443 | } |
| 489 | memcpy(&counter_nbo, &data[PKT_CTR_OFFSET], PKT_CTR_SIZE); | 444 | memcpy(&counter_nbo, &data[PKT_CTR_OFFSET], PKT_CTR_SIZE); |
| 490 | seq = be32_to_cpu(counter_nbo); | 445 | seq = be32_to_cpu(counter_nbo); |
| 491 | rc = ecryptfs_miscdev_response( | 446 | rc = ecryptfs_miscdev_response(file->private_data, |
| 492 | &data[PKT_LEN_OFFSET + packet_size_length], | 447 | &data[PKT_LEN_OFFSET + packet_size_length], |
| 493 | packet_size, euid, current_user_ns(), | 448 | packet_size, seq); |
| 494 | task_pid(current), seq); | ||
| 495 | if (rc) { | 449 | if (rc) { |
| 496 | printk(KERN_WARNING "%s: Failed to deliver miscdev " | 450 | printk(KERN_WARNING "%s: Failed to deliver miscdev " |
| 497 | "response to requesting operation; rc = [%zd]\n", | 451 | "response to requesting operation; rc = [%zd]\n", |
