brintos

brintos / linux-shallow public Read only

0
0
Text · 13.0 KiB · 6318f35 Raw
452 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * eCryptfs: Linux filesystem encryption layer4 *5 * Copyright (C) 2004-2008 International Business Machines Corp.6 *   Author(s): Michael A. Halcrow <mhalcrow@us.ibm.com>7 *		Tyler Hicks <code@tyhicks.com>8 */9#include <linux/sched.h>10#include <linux/slab.h>11#include <linux/user_namespace.h>12#include <linux/nsproxy.h>13#include "ecryptfs_kernel.h"14 15static LIST_HEAD(ecryptfs_msg_ctx_free_list);16static LIST_HEAD(ecryptfs_msg_ctx_alloc_list);17static DEFINE_MUTEX(ecryptfs_msg_ctx_lists_mux);18 19static struct hlist_head *ecryptfs_daemon_hash;20DEFINE_MUTEX(ecryptfs_daemon_hash_mux);21static int ecryptfs_hash_bits;22#define ecryptfs_current_euid_hash(uid) \23	hash_long((unsigned long)from_kuid(&init_user_ns, current_euid()), ecryptfs_hash_bits)24 25static u32 ecryptfs_msg_counter;26static struct ecryptfs_msg_ctx *ecryptfs_msg_ctx_arr;27 28/**29 * ecryptfs_acquire_free_msg_ctx30 * @msg_ctx: The context that was acquired from the free list31 *32 * Acquires a context element from the free list and locks the mutex33 * on the context.  Sets the msg_ctx task to current.  Returns zero on34 * success; non-zero on error or upon failure to acquire a free35 * context element.  Must be called with ecryptfs_msg_ctx_lists_mux36 * held.37 */38static int ecryptfs_acquire_free_msg_ctx(struct ecryptfs_msg_ctx **msg_ctx)39{40	struct list_head *p;41	int rc;42 43	if (list_empty(&ecryptfs_msg_ctx_free_list)) {44		printk(KERN_WARNING "%s: The eCryptfs free "45		       "context list is empty.  It may be helpful to "46		       "specify the ecryptfs_message_buf_len "47		       "parameter to be greater than the current "48		       "value of [%d]\n", __func__, ecryptfs_message_buf_len);49		rc = -ENOMEM;50		goto out;51	}52	list_for_each(p, &ecryptfs_msg_ctx_free_list) {53		*msg_ctx = list_entry(p, struct ecryptfs_msg_ctx, node);54		if (mutex_trylock(&(*msg_ctx)->mux)) {55			(*msg_ctx)->task = current;56			rc = 0;57			goto out;58		}59	}60	rc = -ENOMEM;61out:62	return rc;63}64 65/**66 * ecryptfs_msg_ctx_free_to_alloc67 * @msg_ctx: The context to move from the free list to the alloc list68 *69 * Must be called with ecryptfs_msg_ctx_lists_mux held.70 */71static void ecryptfs_msg_ctx_free_to_alloc(struct ecryptfs_msg_ctx *msg_ctx)72{73	list_move(&msg_ctx->node, &ecryptfs_msg_ctx_alloc_list);74	msg_ctx->state = ECRYPTFS_MSG_CTX_STATE_PENDING;75	msg_ctx->counter = ++ecryptfs_msg_counter;76}77 78/**79 * ecryptfs_msg_ctx_alloc_to_free80 * @msg_ctx: The context to move from the alloc list to the free list81 *82 * Must be called with ecryptfs_msg_ctx_lists_mux held.83 */84void ecryptfs_msg_ctx_alloc_to_free(struct ecryptfs_msg_ctx *msg_ctx)85{86	list_move(&(msg_ctx->node), &ecryptfs_msg_ctx_free_list);87	kfree(msg_ctx->msg);88	msg_ctx->msg = NULL;89	msg_ctx->state = ECRYPTFS_MSG_CTX_STATE_FREE;90}91 92/**93 * ecryptfs_find_daemon_by_euid94 * @daemon: If return value is zero, points to the desired daemon pointer95 *96 * Must be called with ecryptfs_daemon_hash_mux held.97 *98 * Search the hash list for the current effective user id.99 *100 * Returns zero if the user id exists in the list; non-zero otherwise.101 */102int ecryptfs_find_daemon_by_euid(struct ecryptfs_daemon **daemon)103{104	int rc;105 106	hlist_for_each_entry(*daemon,107			    &ecryptfs_daemon_hash[ecryptfs_current_euid_hash()],108			    euid_chain) {109		if (uid_eq((*daemon)->file->f_cred->euid, current_euid())) {110			rc = 0;111			goto out;112		}113	}114	rc = -EINVAL;115out:116	return rc;117}118 119/**120 * ecryptfs_spawn_daemon - Create and initialize a new daemon struct121 * @daemon: Pointer to set to newly allocated daemon struct122 * @file: File used when opening /dev/ecryptfs123 *124 * Must be called ceremoniously while in possession of125 * ecryptfs_sacred_daemon_hash_mux126 *127 * Returns zero on success; non-zero otherwise128 */129int130ecryptfs_spawn_daemon(struct ecryptfs_daemon **daemon, struct file *file)131{132	int rc = 0;133 134	(*daemon) = kzalloc(sizeof(**daemon), GFP_KERNEL);135	if (!(*daemon)) {136		rc = -ENOMEM;137		goto out;138	}139	(*daemon)->file = file;140	mutex_init(&(*daemon)->mux);141	INIT_LIST_HEAD(&(*daemon)->msg_ctx_out_queue);142	init_waitqueue_head(&(*daemon)->wait);143	(*daemon)->num_queued_msg_ctx = 0;144	hlist_add_head(&(*daemon)->euid_chain,145		       &ecryptfs_daemon_hash[ecryptfs_current_euid_hash()]);146out:147	return rc;148}149 150/*151 * ecryptfs_exorcise_daemon - Destroy the daemon struct152 *153 * Must be called ceremoniously while in possession of154 * ecryptfs_daemon_hash_mux and the daemon's own mux.155 */156int ecryptfs_exorcise_daemon(struct ecryptfs_daemon *daemon)157{158	struct ecryptfs_msg_ctx *msg_ctx, *msg_ctx_tmp;159	int rc = 0;160 161	mutex_lock(&daemon->mux);162	if ((daemon->flags & ECRYPTFS_DAEMON_IN_READ)163	    || (daemon->flags & ECRYPTFS_DAEMON_IN_POLL)) {164		rc = -EBUSY;165		mutex_unlock(&daemon->mux);166		goto out;167	}168	list_for_each_entry_safe(msg_ctx, msg_ctx_tmp,169				 &daemon->msg_ctx_out_queue, daemon_out_list) {170		list_del(&msg_ctx->daemon_out_list);171		daemon->num_queued_msg_ctx--;172		printk(KERN_WARNING "%s: Warning: dropping message that is in "173		       "the out queue of a dying daemon\n", __func__);174		ecryptfs_msg_ctx_alloc_to_free(msg_ctx);175	}176	hlist_del(&daemon->euid_chain);177	mutex_unlock(&daemon->mux);178	kfree_sensitive(daemon);179out:180	return rc;181}182 183/**184 * ecryptfs_process_response185 * @daemon: eCryptfs daemon object186 * @msg: The ecryptfs message received; the caller should sanity check187 *       msg->data_len and free the memory188 * @seq: The sequence number of the message; must match the sequence189 *       number for the existing message context waiting for this190 *       response191 *192 * Processes a response message after sending an operation request to193 * userspace. Some other process is awaiting this response. Before194 * sending out its first communications, the other process allocated a195 * msg_ctx from the ecryptfs_msg_ctx_arr at a particular index. The196 * response message contains this index so that we can copy over the197 * response message into the msg_ctx that the process holds a198 * reference to. The other process is going to wake up, check to see199 * that msg_ctx->state == ECRYPTFS_MSG_CTX_STATE_DONE, and then200 * proceed to read off and process the response message. Returns zero201 * upon delivery to desired context element; non-zero upon delivery202 * failure or error.203 *204 * Returns zero on success; non-zero otherwise205 */206int ecryptfs_process_response(struct ecryptfs_daemon *daemon,207			      struct ecryptfs_message *msg, u32 seq)208{209	struct ecryptfs_msg_ctx *msg_ctx;210	size_t msg_size;211	int rc;212 213	if (msg->index >= ecryptfs_message_buf_len) {214		rc = -EINVAL;215		printk(KERN_ERR "%s: Attempt to reference "216		       "context buffer at index [%d]; maximum "217		       "allowable is [%d]\n", __func__, msg->index,218		       (ecryptfs_message_buf_len - 1));219		goto out;220	}221	msg_ctx = &ecryptfs_msg_ctx_arr[msg->index];222	mutex_lock(&msg_ctx->mux);223	if (msg_ctx->state != ECRYPTFS_MSG_CTX_STATE_PENDING) {224		rc = -EINVAL;225		printk(KERN_WARNING "%s: Desired context element is not "226		       "pending a response\n", __func__);227		goto unlock;228	} else if (msg_ctx->counter != seq) {229		rc = -EINVAL;230		printk(KERN_WARNING "%s: Invalid message sequence; "231		       "expected [%d]; received [%d]\n", __func__,232		       msg_ctx->counter, seq);233		goto unlock;234	}235	msg_size = (sizeof(*msg) + msg->data_len);236	msg_ctx->msg = kmemdup(msg, msg_size, GFP_KERNEL);237	if (!msg_ctx->msg) {238		rc = -ENOMEM;239		goto unlock;240	}241	msg_ctx->state = ECRYPTFS_MSG_CTX_STATE_DONE;242	wake_up_process(msg_ctx->task);243	rc = 0;244unlock:245	mutex_unlock(&msg_ctx->mux);246out:247	return rc;248}249 250/**251 * ecryptfs_send_message_locked252 * @data: The data to send253 * @data_len: The length of data254 * @msg_type: Type of message255 * @msg_ctx: The message context allocated for the send256 *257 * Must be called with ecryptfs_daemon_hash_mux held.258 *259 * Returns zero on success; non-zero otherwise260 */261static int262ecryptfs_send_message_locked(char *data, int data_len, u8 msg_type,263			     struct ecryptfs_msg_ctx **msg_ctx)264{265	struct ecryptfs_daemon *daemon;266	int rc;267 268	rc = ecryptfs_find_daemon_by_euid(&daemon);269	if (rc) {270		rc = -ENOTCONN;271		goto out;272	}273	mutex_lock(&ecryptfs_msg_ctx_lists_mux);274	rc = ecryptfs_acquire_free_msg_ctx(msg_ctx);275	if (rc) {276		mutex_unlock(&ecryptfs_msg_ctx_lists_mux);277		printk(KERN_WARNING "%s: Could not claim a free "278		       "context element\n", __func__);279		goto out;280	}281	ecryptfs_msg_ctx_free_to_alloc(*msg_ctx);282	mutex_unlock(&(*msg_ctx)->mux);283	mutex_unlock(&ecryptfs_msg_ctx_lists_mux);284	rc = ecryptfs_send_miscdev(data, data_len, *msg_ctx, msg_type, 0,285				   daemon);286	if (rc)287		printk(KERN_ERR "%s: Error attempting to send message to "288		       "userspace daemon; rc = [%d]\n", __func__, rc);289out:290	return rc;291}292 293/**294 * ecryptfs_send_message295 * @data: The data to send296 * @data_len: The length of data297 * @msg_ctx: The message context allocated for the send298 *299 * Grabs ecryptfs_daemon_hash_mux.300 *301 * Returns zero on success; non-zero otherwise302 */303int ecryptfs_send_message(char *data, int data_len,304			  struct ecryptfs_msg_ctx **msg_ctx)305{306	int rc;307 308	mutex_lock(&ecryptfs_daemon_hash_mux);309	rc = ecryptfs_send_message_locked(data, data_len, ECRYPTFS_MSG_REQUEST,310					  msg_ctx);311	mutex_unlock(&ecryptfs_daemon_hash_mux);312	return rc;313}314 315/**316 * ecryptfs_wait_for_response317 * @msg_ctx: The context that was assigned when sending a message318 * @msg: The incoming message from userspace; not set if rc != 0319 *320 * Sleeps until awaken by ecryptfs_receive_message or until the amount321 * of time exceeds ecryptfs_message_wait_timeout.  If zero is322 * returned, msg will point to a valid message from userspace; a323 * non-zero value is returned upon failure to receive a message or an324 * error occurs. Callee must free @msg on success.325 */326int ecryptfs_wait_for_response(struct ecryptfs_msg_ctx *msg_ctx,327			       struct ecryptfs_message **msg)328{329	signed long timeout = ecryptfs_message_wait_timeout * HZ;330	int rc = 0;331 332sleep:333	timeout = schedule_timeout_interruptible(timeout);334	mutex_lock(&ecryptfs_msg_ctx_lists_mux);335	mutex_lock(&msg_ctx->mux);336	if (msg_ctx->state != ECRYPTFS_MSG_CTX_STATE_DONE) {337		if (timeout) {338			mutex_unlock(&msg_ctx->mux);339			mutex_unlock(&ecryptfs_msg_ctx_lists_mux);340			goto sleep;341		}342		rc = -ENOMSG;343	} else {344		*msg = msg_ctx->msg;345		msg_ctx->msg = NULL;346	}347	ecryptfs_msg_ctx_alloc_to_free(msg_ctx);348	mutex_unlock(&msg_ctx->mux);349	mutex_unlock(&ecryptfs_msg_ctx_lists_mux);350	return rc;351}352 353int __init ecryptfs_init_messaging(void)354{355	int i;356	int rc = 0;357 358	if (ecryptfs_number_of_users > ECRYPTFS_MAX_NUM_USERS) {359		ecryptfs_number_of_users = ECRYPTFS_MAX_NUM_USERS;360		printk(KERN_WARNING "%s: Specified number of users is "361		       "too large, defaulting to [%d] users\n", __func__,362		       ecryptfs_number_of_users);363	}364	mutex_lock(&ecryptfs_daemon_hash_mux);365	ecryptfs_hash_bits = 1;366	while (ecryptfs_number_of_users >> ecryptfs_hash_bits)367		ecryptfs_hash_bits++;368	ecryptfs_daemon_hash = kmalloc((sizeof(struct hlist_head)369					* (1 << ecryptfs_hash_bits)),370				       GFP_KERNEL);371	if (!ecryptfs_daemon_hash) {372		rc = -ENOMEM;373		mutex_unlock(&ecryptfs_daemon_hash_mux);374		goto out;375	}376	for (i = 0; i < (1 << ecryptfs_hash_bits); i++)377		INIT_HLIST_HEAD(&ecryptfs_daemon_hash[i]);378	mutex_unlock(&ecryptfs_daemon_hash_mux);379	ecryptfs_msg_ctx_arr = kmalloc((sizeof(struct ecryptfs_msg_ctx)380					* ecryptfs_message_buf_len),381				       GFP_KERNEL);382	if (!ecryptfs_msg_ctx_arr) {383		kfree(ecryptfs_daemon_hash);384		rc = -ENOMEM;385		goto out;386	}387	mutex_lock(&ecryptfs_msg_ctx_lists_mux);388	ecryptfs_msg_counter = 0;389	for (i = 0; i < ecryptfs_message_buf_len; i++) {390		INIT_LIST_HEAD(&ecryptfs_msg_ctx_arr[i].node);391		INIT_LIST_HEAD(&ecryptfs_msg_ctx_arr[i].daemon_out_list);392		mutex_init(&ecryptfs_msg_ctx_arr[i].mux);393		mutex_lock(&ecryptfs_msg_ctx_arr[i].mux);394		ecryptfs_msg_ctx_arr[i].index = i;395		ecryptfs_msg_ctx_arr[i].state = ECRYPTFS_MSG_CTX_STATE_FREE;396		ecryptfs_msg_ctx_arr[i].counter = 0;397		ecryptfs_msg_ctx_arr[i].task = NULL;398		ecryptfs_msg_ctx_arr[i].msg = NULL;399		list_add_tail(&ecryptfs_msg_ctx_arr[i].node,400			      &ecryptfs_msg_ctx_free_list);401		mutex_unlock(&ecryptfs_msg_ctx_arr[i].mux);402	}403	mutex_unlock(&ecryptfs_msg_ctx_lists_mux);404	rc = ecryptfs_init_ecryptfs_miscdev();405	if (rc)406		ecryptfs_release_messaging();407out:408	return rc;409}410 411void ecryptfs_release_messaging(void)412{413	if (ecryptfs_msg_ctx_arr) {414		int i;415 416		mutex_lock(&ecryptfs_msg_ctx_lists_mux);417		for (i = 0; i < ecryptfs_message_buf_len; i++) {418			mutex_lock(&ecryptfs_msg_ctx_arr[i].mux);419			kfree(ecryptfs_msg_ctx_arr[i].msg);420			mutex_unlock(&ecryptfs_msg_ctx_arr[i].mux);421		}422		kfree(ecryptfs_msg_ctx_arr);423		mutex_unlock(&ecryptfs_msg_ctx_lists_mux);424	}425	if (ecryptfs_daemon_hash) {426		struct ecryptfs_daemon *daemon;427		struct hlist_node *n;428		int i;429 430		mutex_lock(&ecryptfs_daemon_hash_mux);431		for (i = 0; i < (1 << ecryptfs_hash_bits); i++) {432			int rc;433 434			hlist_for_each_entry_safe(daemon, n,435						  &ecryptfs_daemon_hash[i],436						  euid_chain) {437				rc = ecryptfs_exorcise_daemon(daemon);438				if (rc)439					printk(KERN_ERR "%s: Error whilst "440					       "attempting to destroy daemon; "441					       "rc = [%d]. Dazed and confused, "442					       "but trying to continue.\n",443					       __func__, rc);444			}445		}446		kfree(ecryptfs_daemon_hash);447		mutex_unlock(&ecryptfs_daemon_hash_mux);448	}449	ecryptfs_destroy_ecryptfs_miscdev();450	return;451}452