linux/fs/ecryptfs/miscdev.c
<<
>>
Prefs
   1/**
   2 * eCryptfs: Linux filesystem encryption layer
   3 *
   4 * Copyright (C) 2008 International Business Machines Corp.
   5 *   Author(s): Michael A. Halcrow <mhalcrow@us.ibm.com>
   6 *
   7 * This program is free software; you can redistribute it and/or
   8 * modify it under the terms of the GNU General Public License version
   9 * 2 as published by the Free Software Foundation.
  10 *
  11 * This program is distributed in the hope that it will be useful, but
  12 * WITHOUT ANY WARRANTY; without even the implied warranty of
  13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  14 * General Public License for more details.
  15 *
  16 * You should have received a copy of the GNU General Public License
  17 * along with this program; if not, write to the Free Software
  18 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
  19 * 02111-1307, USA.
  20 */
  21
  22#include <linux/fs.h>
  23#include <linux/hash.h>
  24#include <linux/random.h>
  25#include <linux/miscdevice.h>
  26#include <linux/poll.h>
  27#include <linux/slab.h>
  28#include <linux/wait.h>
  29#include <linux/module.h>
  30#include "ecryptfs_kernel.h"
  31
  32static atomic_t ecryptfs_num_miscdev_opens;
  33
  34/**
  35 * ecryptfs_miscdev_poll
  36 * @file: dev file (ignored)
  37 * @pt: dev poll table (ignored)
  38 *
  39 * Returns the poll mask
  40 */
  41static unsigned int
  42ecryptfs_miscdev_poll(struct file *file, poll_table *pt)
  43{
  44        struct ecryptfs_daemon *daemon;
  45        unsigned int mask = 0;
  46        uid_t euid = current_euid();
  47        int rc;
  48
  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        BUG_ON(rc || !daemon);
  53        mutex_lock(&daemon->mux);
  54        mutex_unlock(&ecryptfs_daemon_hash_mux);
  55        if (daemon->flags & ECRYPTFS_DAEMON_ZOMBIE) {
  56                printk(KERN_WARNING "%s: Attempt to poll on zombified "
  57                       "daemon\n", __func__);
  58                goto out_unlock_daemon;
  59        }
  60        if (daemon->flags & ECRYPTFS_DAEMON_IN_READ)
  61                goto out_unlock_daemon;
  62        if (daemon->flags & ECRYPTFS_DAEMON_IN_POLL)
  63                goto out_unlock_daemon;
  64        daemon->flags |= ECRYPTFS_DAEMON_IN_POLL;
  65        mutex_unlock(&daemon->mux);
  66        poll_wait(file, &daemon->wait, pt);
  67        mutex_lock(&daemon->mux);
  68        if (!list_empty(&daemon->msg_ctx_out_queue))
  69                mask |= POLLIN | POLLRDNORM;
  70out_unlock_daemon:
  71        daemon->flags &= ~ECRYPTFS_DAEMON_IN_POLL;
  72        mutex_unlock(&daemon->mux);
  73        return mask;
  74}
  75
  76/**
  77 * ecryptfs_miscdev_open
  78 * @inode: inode of miscdev handle (ignored)
  79 * @file: file for miscdev handle (ignored)
  80 *
  81 * Returns zero on success; non-zero otherwise
  82 */
  83static int
  84ecryptfs_miscdev_open(struct inode *inode, struct file *file)
  85{
  86        struct ecryptfs_daemon *daemon = NULL;
  87        uid_t euid = current_euid();
  88        int rc;
  89
  90        mutex_lock(&ecryptfs_daemon_hash_mux);
  91        rc = try_module_get(THIS_MODULE);
  92        if (rc == 0) {
  93                rc = -EIO;
  94                printk(KERN_ERR "%s: Error attempting to increment module use "
  95                       "count; rc = [%d]\n", __func__, rc);
  96                goto out_unlock_daemon_list;
  97        }
  98        rc = ecryptfs_find_daemon_by_euid(&daemon, euid, current_user_ns());
  99        if (rc || !daemon) {
 100                rc = ecryptfs_spawn_daemon(&daemon, euid, current_user_ns(),
 101                                           task_pid(current));
 102                if (rc) {
 103                        printk(KERN_ERR "%s: Error attempting to spawn daemon; "
 104                               "rc = [%d]\n", __func__, rc);
 105                        goto out_module_put_unlock_daemon_list;
 106                }
 107        }
 108        mutex_lock(&daemon->mux);
 109        if (daemon->pid != task_pid(current)) {
 110                rc = -EINVAL;
 111                printk(KERN_ERR "%s: pid [0x%p] has registered with euid [%d], "
 112                       "but pid [0x%p] has attempted to open the handle "
 113                       "instead\n", __func__, daemon->pid, daemon->euid,
 114                       task_pid(current));
 115                goto out_unlock_daemon;
 116        }
 117        if (daemon->flags & ECRYPTFS_DAEMON_MISCDEV_OPEN) {
 118                rc = -EBUSY;
 119                printk(KERN_ERR "%s: Miscellaneous device handle may only be "
 120                       "opened once per daemon; pid [0x%p] already has this "
 121                       "handle open\n", __func__, daemon->pid);
 122                goto out_unlock_daemon;
 123        }
 124        daemon->flags |= ECRYPTFS_DAEMON_MISCDEV_OPEN;
 125        atomic_inc(&ecryptfs_num_miscdev_opens);
 126out_unlock_daemon:
 127        mutex_unlock(&daemon->mux);
 128out_module_put_unlock_daemon_list:
 129        if (rc)
 130                module_put(THIS_MODULE);
 131out_unlock_daemon_list:
 132        mutex_unlock(&ecryptfs_daemon_hash_mux);
 133        return rc;
 134}
 135
 136/**
 137 * ecryptfs_miscdev_release
 138 * @inode: inode of fs/ecryptfs/euid handle (ignored)
 139 * @file: file for fs/ecryptfs/euid handle (ignored)
 140 *
 141 * This keeps the daemon registered until the daemon sends another
 142 * ioctl to fs/ecryptfs/ctl or until the kernel module unregisters.
 143 *
 144 * Returns zero on success; non-zero otherwise
 145 */
 146static int
 147ecryptfs_miscdev_release(struct inode *inode, struct file *file)
 148{
 149        struct ecryptfs_daemon *daemon = NULL;
 150        uid_t euid = current_euid();
 151        int rc;
 152
 153        mutex_lock(&ecryptfs_daemon_hash_mux);
 154        rc = ecryptfs_find_daemon_by_euid(&daemon, euid, current_user_ns());
 155        BUG_ON(rc || !daemon);
 156        mutex_lock(&daemon->mux);
 157        BUG_ON(daemon->pid != task_pid(current));
 158        BUG_ON(!(daemon->flags & ECRYPTFS_DAEMON_MISCDEV_OPEN));
 159        daemon->flags &= ~ECRYPTFS_DAEMON_MISCDEV_OPEN;
 160        atomic_dec(&ecryptfs_num_miscdev_opens);
 161        mutex_unlock(&daemon->mux);
 162        rc = ecryptfs_exorcise_daemon(daemon);
 163        if (rc) {
 164                printk(KERN_CRIT "%s: Fatal error whilst attempting to "
 165                       "shut down daemon; rc = [%d]. Please report this "
 166                       "bug.\n", __func__, rc);
 167                BUG();
 168        }
 169        module_put(THIS_MODULE);
 170        mutex_unlock(&ecryptfs_daemon_hash_mux);
 171        return rc;
 172}
 173
 174/**
 175 * ecryptfs_send_miscdev
 176 * @data: Data to send to daemon; may be NULL
 177 * @data_size: Amount of data to send to daemon
 178 * @msg_ctx: Message context, which is used to handle the reply. If
 179 *           this is NULL, then we do not expect a reply.
 180 * @msg_type: Type of message
 181 * @msg_flags: Flags for message
 182 * @daemon: eCryptfs daemon object
 183 *
 184 * Add msg_ctx to queue and then, if it exists, notify the blocked
 185 * miscdevess about the data being available. Must be called with
 186 * ecryptfs_daemon_hash_mux held.
 187 *
 188 * Returns zero on success; non-zero otherwise
 189 */
 190int ecryptfs_send_miscdev(char *data, size_t data_size,
 191                          struct ecryptfs_msg_ctx *msg_ctx, u8 msg_type,
 192                          u16 msg_flags, struct ecryptfs_daemon *daemon)
 193{
 194        int rc = 0;
 195
 196        mutex_lock(&msg_ctx->mux);
 197        msg_ctx->msg = kmalloc((sizeof(*msg_ctx->msg) + data_size),
 198                               GFP_KERNEL);
 199        if (!msg_ctx->msg) {
 200                rc = -ENOMEM;
 201                printk(KERN_ERR "%s: Out of memory whilst attempting "
 202                       "to kmalloc(%zd, GFP_KERNEL)\n", __func__,
 203                       (sizeof(*msg_ctx->msg) + data_size));
 204                goto out_unlock;
 205        }
 206        msg_ctx->msg->index = msg_ctx->index;
 207        msg_ctx->msg->data_len = data_size;
 208        msg_ctx->type = msg_type;
 209        memcpy(msg_ctx->msg->data, data, data_size);
 210        msg_ctx->msg_size = (sizeof(*msg_ctx->msg) + data_size);
 211        mutex_lock(&daemon->mux);
 212        list_add_tail(&msg_ctx->daemon_out_list, &daemon->msg_ctx_out_queue);
 213        daemon->num_queued_msg_ctx++;
 214        wake_up_interruptible(&daemon->wait);
 215        mutex_unlock(&daemon->mux);
 216out_unlock:
 217        mutex_unlock(&msg_ctx->mux);
 218        return rc;
 219}
 220
 221/*
 222 * miscdevfs packet format:
 223 *  Octet 0: Type
 224 *  Octets 1-4: network byte order msg_ctx->counter
 225 *  Octets 5-N0: Size of struct ecryptfs_message to follow
 226 *  Octets N0-N1: struct ecryptfs_message (including data)
 227 *
 228 *  Octets 5-N1 not written if the packet type does not include a message
 229 */
 230#define PKT_TYPE_SIZE           1
 231#define PKT_CTR_SIZE            4
 232#define MIN_NON_MSG_PKT_SIZE    (PKT_TYPE_SIZE + PKT_CTR_SIZE)
 233#define MIN_MSG_PKT_SIZE        (PKT_TYPE_SIZE + PKT_CTR_SIZE \
 234                                 + ECRYPTFS_MIN_PKT_LEN_SIZE)
 235/* 4 + ECRYPTFS_MAX_ENCRYPTED_KEY_BYTES comes from tag 65 packet format */
 236#define MAX_MSG_PKT_SIZE        (PKT_TYPE_SIZE + PKT_CTR_SIZE \
 237                                 + ECRYPTFS_MAX_PKT_LEN_SIZE \
 238                                 + sizeof(struct ecryptfs_message) \
 239                                 + 4 + ECRYPTFS_MAX_ENCRYPTED_KEY_BYTES)
 240#define PKT_TYPE_OFFSET         0
 241#define PKT_CTR_OFFSET          PKT_TYPE_SIZE
 242#define PKT_LEN_OFFSET          (PKT_TYPE_SIZE + PKT_CTR_SIZE)
 243
 244/**
 245 * ecryptfs_miscdev_read - format and send message from queue
 246 * @file: fs/ecryptfs/euid miscdevfs handle (ignored)
 247 * @buf: User buffer into which to copy the next message on the daemon queue
 248 * @count: Amount of space available in @buf
 249 * @ppos: Offset in file (ignored)
 250 *
 251 * Pulls the most recent message from the daemon queue, formats it for
 252 * being sent via a miscdevfs handle, and copies it into @buf
 253 *
 254 * Returns the number of bytes copied into the user buffer
 255 */
 256static ssize_t
 257ecryptfs_miscdev_read(struct file *file, char __user *buf, size_t count,
 258                      loff_t *ppos)
 259{
 260        struct ecryptfs_daemon *daemon;
 261        struct ecryptfs_msg_ctx *msg_ctx;
 262        size_t packet_length_size;
 263        char packet_length[ECRYPTFS_MAX_PKT_LEN_SIZE];
 264        size_t i;
 265        size_t total_length;
 266        uid_t euid = current_euid();
 267        int rc;
 268
 269        mutex_lock(&ecryptfs_daemon_hash_mux);
 270        /* TODO: Just use file->private_data? */
 271        rc = ecryptfs_find_daemon_by_euid(&daemon, euid, current_user_ns());
 272        BUG_ON(rc || !daemon);
 273        mutex_lock(&daemon->mux);
 274        if (daemon->flags & ECRYPTFS_DAEMON_ZOMBIE) {
 275                rc = 0;
 276                mutex_unlock(&ecryptfs_daemon_hash_mux);
 277                printk(KERN_WARNING "%s: Attempt to read from zombified "
 278                       "daemon\n", __func__);
 279                goto out_unlock_daemon;
 280        }
 281        if (daemon->flags & ECRYPTFS_DAEMON_IN_READ) {
 282                rc = 0;
 283                mutex_unlock(&ecryptfs_daemon_hash_mux);
 284                goto out_unlock_daemon;
 285        }
 286        /* This daemon will not go away so long as this flag is set */
 287        daemon->flags |= ECRYPTFS_DAEMON_IN_READ;
 288        mutex_unlock(&ecryptfs_daemon_hash_mux);
 289check_list:
 290        if (list_empty(&daemon->msg_ctx_out_queue)) {
 291                mutex_unlock(&daemon->mux);
 292                rc = wait_event_interruptible(
 293                        daemon->wait, !list_empty(&daemon->msg_ctx_out_queue));
 294                mutex_lock(&daemon->mux);
 295                if (rc < 0) {
 296                        rc = 0;
 297                        goto out_unlock_daemon;
 298                }
 299        }
 300        if (daemon->flags & ECRYPTFS_DAEMON_ZOMBIE) {
 301                rc = 0;
 302                goto out_unlock_daemon;
 303        }
 304        if (list_empty(&daemon->msg_ctx_out_queue)) {
 305                /* Something else jumped in since the
 306                 * wait_event_interruptable() and removed the
 307                 * message from the queue; try again */
 308                goto check_list;
 309        }
 310        BUG_ON(euid != daemon->euid);
 311        BUG_ON(current_user_ns() != daemon->user_ns);
 312        BUG_ON(task_pid(current) != daemon->pid);
 313        msg_ctx = list_first_entry(&daemon->msg_ctx_out_queue,
 314                                   struct ecryptfs_msg_ctx, daemon_out_list);
 315        BUG_ON(!msg_ctx);
 316        mutex_lock(&msg_ctx->mux);
 317        if (msg_ctx->msg) {
 318                rc = ecryptfs_write_packet_length(packet_length,
 319                                                  msg_ctx->msg_size,
 320                                                  &packet_length_size);
 321                if (rc) {
 322                        rc = 0;
 323                        printk(KERN_WARNING "%s: Error writing packet length; "
 324                               "rc = [%d]\n", __func__, rc);
 325                        goto out_unlock_msg_ctx;
 326                }
 327        } else {
 328                packet_length_size = 0;
 329                msg_ctx->msg_size = 0;
 330        }
 331        total_length = (PKT_TYPE_SIZE + PKT_CTR_SIZE + packet_length_size
 332                        + msg_ctx->msg_size);
 333        if (count < total_length) {
 334                rc = 0;
 335                printk(KERN_WARNING "%s: Only given user buffer of "
 336                       "size [%zd], but we need [%zd] to read the "
 337                       "pending message\n", __func__, count, total_length);
 338                goto out_unlock_msg_ctx;
 339        }
 340        rc = -EFAULT;
 341        if (put_user(msg_ctx->type, buf))
 342                goto out_unlock_msg_ctx;
 343        if (put_user(cpu_to_be32(msg_ctx->counter),
 344                     (__be32 __user *)(&buf[PKT_CTR_OFFSET])))
 345                goto out_unlock_msg_ctx;
 346        i = PKT_TYPE_SIZE + PKT_CTR_SIZE;
 347        if (msg_ctx->msg) {
 348                if (copy_to_user(&buf[i], packet_length, packet_length_size))
 349                        goto out_unlock_msg_ctx;
 350                i += packet_length_size;
 351                if (copy_to_user(&buf[i], msg_ctx->msg, msg_ctx->msg_size))
 352                        goto out_unlock_msg_ctx;
 353                i += msg_ctx->msg_size;
 354        }
 355        rc = i;
 356        list_del(&msg_ctx->daemon_out_list);
 357        kfree(msg_ctx->msg);
 358        msg_ctx->msg = NULL;
 359        /* We do not expect a reply from the userspace daemon for any
 360         * message type other than ECRYPTFS_MSG_REQUEST */
 361        if (msg_ctx->type != ECRYPTFS_MSG_REQUEST)
 362                ecryptfs_msg_ctx_alloc_to_free(msg_ctx);
 363out_unlock_msg_ctx:
 364        mutex_unlock(&msg_ctx->mux);
 365out_unlock_daemon:
 366        daemon->flags &= ~ECRYPTFS_DAEMON_IN_READ;
 367        mutex_unlock(&daemon->mux);
 368        return rc;
 369}
 370
 371/**
 372 * ecryptfs_miscdev_response - miscdevess response to message previously sent to daemon
 373 * @data: Bytes comprising struct ecryptfs_message
 374 * @data_size: sizeof(struct ecryptfs_message) + data len
 375 * @euid: Effective user id of miscdevess sending the miscdev response
 376 * @user_ns: The namespace in which @euid applies
 377 * @pid: Miscdevess id of miscdevess sending the miscdev response
 378 * @seq: Sequence number for miscdev response packet
 379 *
 380 * Returns zero on success; non-zero otherwise
 381 */
 382static int ecryptfs_miscdev_response(char *data, size_t data_size,
 383                                     uid_t euid, struct user_namespace *user_ns,
 384                                     struct pid *pid, u32 seq)
 385{
 386        struct ecryptfs_message *msg = (struct ecryptfs_message *)data;
 387        int rc;
 388
 389        if ((sizeof(*msg) + msg->data_len) != data_size) {
 390                printk(KERN_WARNING "%s: (sizeof(*msg) + msg->data_len) = "
 391                       "[%zd]; data_size = [%zd]. Invalid packet.\n", __func__,
 392                       (sizeof(*msg) + msg->data_len), data_size);
 393                rc = -EINVAL;
 394                goto out;
 395        }
 396        rc = ecryptfs_process_response(msg, euid, user_ns, pid, seq);
 397        if (rc)
 398                printk(KERN_ERR
 399                       "Error processing response message; rc = [%d]\n", rc);
 400out:
 401        return rc;
 402}
 403
 404/**
 405 * ecryptfs_miscdev_write - handle write to daemon miscdev handle
 406 * @file: File for misc dev handle (ignored)
 407 * @buf: Buffer containing user data
 408 * @count: Amount of data in @buf
 409 * @ppos: Pointer to offset in file (ignored)
 410 *
 411 * Returns the number of bytes read from @buf
 412 */
 413static ssize_t
 414ecryptfs_miscdev_write(struct file *file, const char __user *buf,
 415                       size_t count, loff_t *ppos)
 416{
 417        __be32 counter_nbo;
 418        u32 seq;
 419        size_t packet_size, packet_size_length;
 420        char *data;
 421        uid_t euid = current_euid();
 422        unsigned char packet_size_peek[ECRYPTFS_MAX_PKT_LEN_SIZE];
 423        ssize_t rc;
 424
 425        if (count == 0) {
 426                return 0;
 427        } else if (count == MIN_NON_MSG_PKT_SIZE) {
 428                /* Likely a harmless MSG_HELO or MSG_QUIT - no packet length */
 429                goto memdup;
 430        } else if (count < MIN_MSG_PKT_SIZE || count > MAX_MSG_PKT_SIZE) {
 431                printk(KERN_WARNING "%s: Acceptable packet size range is "
 432                       "[%d-%zu], but amount of data written is [%zu].",
 433                       __func__, MIN_MSG_PKT_SIZE, MAX_MSG_PKT_SIZE, count);
 434                return -EINVAL;
 435        }
 436
 437        if (copy_from_user(packet_size_peek, &buf[PKT_LEN_OFFSET],
 438                           sizeof(packet_size_peek))) {
 439                printk(KERN_WARNING "%s: Error while inspecting packet size\n",
 440                       __func__);
 441                return -EFAULT;
 442        }
 443
 444        rc = ecryptfs_parse_packet_length(packet_size_peek, &packet_size,
 445                                          &packet_size_length);
 446        if (rc) {
 447                printk(KERN_WARNING "%s: Error parsing packet length; "
 448                       "rc = [%zd]\n", __func__, rc);
 449                return rc;
 450        }
 451
 452        if ((PKT_TYPE_SIZE + PKT_CTR_SIZE + packet_size_length + packet_size)
 453            != count) {
 454                printk(KERN_WARNING "%s: Invalid packet size [%zu]\n", __func__,
 455                       packet_size);
 456                return -EINVAL;
 457        }
 458
 459memdup:
 460        data = memdup_user(buf, count);
 461        if (IS_ERR(data)) {
 462                printk(KERN_ERR "%s: memdup_user returned error [%ld]\n",
 463                       __func__, PTR_ERR(data));
 464                return PTR_ERR(data);
 465        }
 466        switch (data[PKT_TYPE_OFFSET]) {
 467        case ECRYPTFS_MSG_RESPONSE:
 468                if (count < (MIN_MSG_PKT_SIZE
 469                             + sizeof(struct ecryptfs_message))) {
 470                        printk(KERN_WARNING "%s: Minimum acceptable packet "
 471                               "size is [%zd], but amount of data written is "
 472                               "only [%zd]. Discarding response packet.\n",
 473                               __func__,
 474                               (MIN_MSG_PKT_SIZE
 475                                + sizeof(struct ecryptfs_message)), count);
 476                        rc = -EINVAL;
 477                        goto out_free;
 478                }
 479                memcpy(&counter_nbo, &data[PKT_CTR_OFFSET], PKT_CTR_SIZE);
 480                seq = be32_to_cpu(counter_nbo);
 481                rc = ecryptfs_miscdev_response(
 482                                &data[PKT_LEN_OFFSET + packet_size_length],
 483                                packet_size, euid, current_user_ns(),
 484                                task_pid(current), seq);
 485                if (rc) {
 486                        printk(KERN_WARNING "%s: Failed to deliver miscdev "
 487                               "response to requesting operation; rc = [%zd]\n",
 488                               __func__, rc);
 489                        goto out_free;
 490                }
 491                break;
 492        case ECRYPTFS_MSG_HELO:
 493        case ECRYPTFS_MSG_QUIT:
 494                break;
 495        default:
 496                ecryptfs_printk(KERN_WARNING, "Dropping miscdev "
 497                                "message of unrecognized type [%d]\n",
 498                                data[0]);
 499                rc = -EINVAL;
 500                goto out_free;
 501        }
 502        rc = count;
 503out_free:
 504        kfree(data);
 505        return rc;
 506}
 507
 508
 509static const struct file_operations ecryptfs_miscdev_fops = {
 510        .open    = ecryptfs_miscdev_open,
 511        .poll    = ecryptfs_miscdev_poll,
 512        .read    = ecryptfs_miscdev_read,
 513        .write   = ecryptfs_miscdev_write,
 514        .release = ecryptfs_miscdev_release,
 515        .llseek  = noop_llseek,
 516};
 517
 518static struct miscdevice ecryptfs_miscdev = {
 519        .minor = MISC_DYNAMIC_MINOR,
 520        .name  = "ecryptfs",
 521        .fops  = &ecryptfs_miscdev_fops
 522};
 523
 524/**
 525 * ecryptfs_init_ecryptfs_miscdev
 526 *
 527 * Messages sent to the userspace daemon from the kernel are placed on
 528 * a queue associated with the daemon. The next read against the
 529 * miscdev handle by that daemon will return the oldest message placed
 530 * on the message queue for the daemon.
 531 *
 532 * Returns zero on success; non-zero otherwise
 533 */
 534int __init ecryptfs_init_ecryptfs_miscdev(void)
 535{
 536        int rc;
 537
 538        atomic_set(&ecryptfs_num_miscdev_opens, 0);
 539        rc = misc_register(&ecryptfs_miscdev);
 540        if (rc)
 541                printk(KERN_ERR "%s: Failed to register miscellaneous device "
 542                       "for communications with userspace daemons; rc = [%d]\n",
 543                       __func__, rc);
 544        return rc;
 545}
 546
 547/**
 548 * ecryptfs_destroy_ecryptfs_miscdev
 549 *
 550 * All of the daemons must be exorcised prior to calling this
 551 * function.
 552 */
 553void ecryptfs_destroy_ecryptfs_miscdev(void)
 554{
 555        BUG_ON(atomic_read(&ecryptfs_num_miscdev_opens) != 0);
 556        misc_deregister(&ecryptfs_miscdev);
 557}
 558