/** * ecryptfs_miscdev_release * @inode: inode of fs/ecryptfs/euid handle (ignored) * @file: file for fs/ecryptfs/euid handle * * This keeps the daemon registered until the daemon sends another * ioctl to fs/ecryptfs/ctl or until the kernel module unregisters. * * Returns zero on success; non-zero otherwise
*/ staticint
ecryptfs_miscdev_release(struct inode *inode, struct file *file)
{ struct ecryptfs_daemon *daemon = file->private_data; int rc;
mutex_lock(&ecryptfs_daemon_hash_mux);
rc = ecryptfs_exorcise_daemon(daemon);
mutex_unlock(&ecryptfs_daemon_hash_mux); if (rc) {
printk(KERN_CRIT "%s: Fatal error whilst attempting to " "shut down daemon; rc = [%d]. Please report this " "bug.\n", __func__, rc);
BUG();
} return rc;
}
/** * ecryptfs_send_miscdev * @data: Data to send to daemon; may be NULL * @data_size: Amount of data to send to daemon * @msg_ctx: Message context, which is used to handle the reply. If * this is NULL, then we do not expect a reply. * @msg_type: Type of message * @msg_flags: Flags for message * @daemon: eCryptfs daemon object * * Add msg_ctx to queue and then, if it exists, notify the blocked * miscdevess about the data being available. Must be called with * ecryptfs_daemon_hash_mux held. * * Returns zero on success; non-zero otherwise
*/ int ecryptfs_send_miscdev(char *data, size_t data_size, struct ecryptfs_msg_ctx *msg_ctx, u8 msg_type,
u16 msg_flags, struct ecryptfs_daemon *daemon)
{ struct ecryptfs_message *msg;
msg = kmalloc((sizeof(*msg) + data_size), GFP_KERNEL); if (!msg) return -ENOMEM;
/* * miscdevfs packet format: * Octet 0: Type * Octets 1-4: network byte order msg_ctx->counter * Octets 5-N0: Size of struct ecryptfs_message to follow * Octets N0-N1: struct ecryptfs_message (including data) * * Octets 5-N1 not written if the packet type does not include a message
*/ #define PKT_TYPE_SIZE 1 #define PKT_CTR_SIZE 4 #define MIN_NON_MSG_PKT_SIZE (PKT_TYPE_SIZE + PKT_CTR_SIZE) #define MIN_MSG_PKT_SIZE (PKT_TYPE_SIZE + PKT_CTR_SIZE \
+ ECRYPTFS_MIN_PKT_LEN_SIZE) /* 4 + ECRYPTFS_MAX_ENCRYPTED_KEY_BYTES comes from tag 65 packet format */ #define MAX_MSG_PKT_SIZE (PKT_TYPE_SIZE + PKT_CTR_SIZE \
+ ECRYPTFS_MAX_PKT_LEN_SIZE \
+ sizeof(struct ecryptfs_message) \
+ 4 + ECRYPTFS_MAX_ENCRYPTED_KEY_BYTES) #define PKT_TYPE_OFFSET 0 #define PKT_CTR_OFFSET PKT_TYPE_SIZE #define PKT_LEN_OFFSET (PKT_TYPE_SIZE + PKT_CTR_SIZE)
/** * ecryptfs_miscdev_read - format and send message from queue * @file: miscdevfs handle * @buf: User buffer into which to copy the next message on the daemon queue * @count: Amount of space available in @buf * @ppos: Offset in file (ignored) * * Pulls the most recent message from the daemon queue, formats it for * being sent via a miscdevfs handle, and copies it into @buf * * Returns the number of bytes copied into the user buffer
*/ static ssize_t
ecryptfs_miscdev_read(struct file *file, char __user *buf, size_t count,
loff_t *ppos)
{ struct ecryptfs_daemon *daemon = file->private_data; struct ecryptfs_msg_ctx *msg_ctx;
size_t packet_length_size; char packet_length[ECRYPTFS_MAX_PKT_LEN_SIZE];
size_t i;
size_t total_length; int rc;
mutex_lock(&daemon->mux); if (daemon->flags & ECRYPTFS_DAEMON_ZOMBIE) {
rc = 0;
printk(KERN_WARNING "%s: Attempt to read from zombified " "daemon\n", __func__); goto out_unlock_daemon;
} if (daemon->flags & ECRYPTFS_DAEMON_IN_READ) {
rc = 0; goto out_unlock_daemon;
} /* This daemon will not go away so long as this flag is set */
daemon->flags |= ECRYPTFS_DAEMON_IN_READ;
check_list: if (list_empty(&daemon->msg_ctx_out_queue)) {
mutex_unlock(&daemon->mux);
rc = wait_event_interruptible(
daemon->wait, !list_empty(&daemon->msg_ctx_out_queue));
mutex_lock(&daemon->mux); if (rc < 0) {
rc = 0; goto out_unlock_daemon;
}
} if (daemon->flags & ECRYPTFS_DAEMON_ZOMBIE) {
rc = 0; goto out_unlock_daemon;
} if (list_empty(&daemon->msg_ctx_out_queue)) { /* Something else jumped in since the * wait_event_interruptable() and removed the
* message from the queue; try again */ goto check_list;
}
msg_ctx = list_first_entry(&daemon->msg_ctx_out_queue, struct ecryptfs_msg_ctx, daemon_out_list);
BUG_ON(!msg_ctx);
mutex_lock(&msg_ctx->mux); if (msg_ctx->msg) {
rc = ecryptfs_write_packet_length(packet_length,
msg_ctx->msg_size,
&packet_length_size); if (rc) {
rc = 0;
printk(KERN_WARNING "%s: Error writing packet length; " "rc = [%d]\n", __func__, rc); goto out_unlock_msg_ctx;
}
} else {
packet_length_size = 0;
msg_ctx->msg_size = 0;
}
total_length = (PKT_TYPE_SIZE + PKT_CTR_SIZE + packet_length_size
+ msg_ctx->msg_size); if (count < total_length) {
rc = 0;
printk(KERN_WARNING "%s: Only given user buffer of " "size [%zd], but we need [%zd] to read the " "pending message\n", __func__, count, total_length); goto out_unlock_msg_ctx;
}
rc = -EFAULT; if (put_user(msg_ctx->type, buf)) goto out_unlock_msg_ctx; if (put_user(cpu_to_be32(msg_ctx->counter),
(__be32 __user *)(&buf[PKT_CTR_OFFSET]))) goto out_unlock_msg_ctx;
i = PKT_TYPE_SIZE + PKT_CTR_SIZE; if (msg_ctx->msg) { if (copy_to_user(&buf[i], packet_length, packet_length_size)) goto out_unlock_msg_ctx;
i += packet_length_size; if (copy_to_user(&buf[i], msg_ctx->msg, msg_ctx->msg_size)) goto out_unlock_msg_ctx;
i += msg_ctx->msg_size;
}
rc = i;
list_del(&msg_ctx->daemon_out_list);
kfree(msg_ctx->msg);
msg_ctx->msg = NULL; /* We do not expect a reply from the userspace daemon for any
* message type other than ECRYPTFS_MSG_REQUEST */ if (msg_ctx->type != ECRYPTFS_MSG_REQUEST)
ecryptfs_msg_ctx_alloc_to_free(msg_ctx);
out_unlock_msg_ctx:
mutex_unlock(&msg_ctx->mux);
out_unlock_daemon:
daemon->flags &= ~ECRYPTFS_DAEMON_IN_READ;
mutex_unlock(&daemon->mux); return rc;
}
/** * ecryptfs_miscdev_response - miscdevess response to message previously sent to daemon * @daemon: eCryptfs daemon object * @data: Bytes comprising struct ecryptfs_message * @data_size: sizeof(struct ecryptfs_message) + data len * @seq: Sequence number for miscdev response packet * * Returns zero on success; non-zero otherwise
*/ staticint ecryptfs_miscdev_response(struct ecryptfs_daemon *daemon, char *data,
size_t data_size, u32 seq)
{ struct ecryptfs_message *msg = (struct ecryptfs_message *)data; int rc;
/** * ecryptfs_init_ecryptfs_miscdev * * Messages sent to the userspace daemon from the kernel are placed on * a queue associated with the daemon. The next read against the * miscdev handle by that daemon will return the oldest message placed * on the message queue for the daemon. * * Returns zero on success; non-zero otherwise
*/ int __init ecryptfs_init_ecryptfs_miscdev(void)
{ int rc;
atomic_set(&ecryptfs_num_miscdev_opens, 0);
rc = misc_register(&ecryptfs_miscdev); if (rc)
printk(KERN_ERR "%s: Failed to register miscellaneous device " "for communications with userspace daemons; rc = [%d]\n",
__func__, rc); return rc;
}
/** * ecryptfs_destroy_ecryptfs_miscdev * * All of the daemons must be exorcised prior to calling this * function.
*/ void ecryptfs_destroy_ecryptfs_miscdev(void)
{
BUG_ON(atomic_read(&ecryptfs_num_miscdev_opens) != 0);
misc_deregister(&ecryptfs_miscdev);
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.