Ejemplo n.º 1
0
/**
 * aa_create_aafs - create the apparmor security filesystem
 *
 * dentries created here are released by aa_destroy_aafs
 *
 * Returns: error on failure
 */
static int __init aa_create_aafs(void)
{
	int error;

	if (!apparmor_initialized)
		return 0;

	if (aa_fs_dentry) {
		AA_ERROR("%s: AppArmor securityfs already exists\n", __func__);
		return -EEXIST;
	}

	aa_fs_dentry = securityfs_create_dir("apparmor", NULL);
	if (IS_ERR(aa_fs_dentry)) {
		error = PTR_ERR(aa_fs_dentry);
		aa_fs_dentry = NULL;
		goto error;
	}
#ifdef CONFIG_SECURITY_APPARMOR_COMPAT_24
	error = aafs_create("matching", 0444, &aa_fs_matching_fops);
	if (error)
		goto error;
	error = aafs_create("features", 0444, &aa_fs_features_fops);
	if (error)
		goto error;
#endif
	error = aafs_create("profiles", 0440, &aa_fs_profiles_fops);
	if (error)
		goto error;
	error = aafs_create(".load", 0640, &aa_fs_profile_load);
	if (error)
		goto error;
	error = aafs_create(".replace", 0640, &aa_fs_profile_replace);
	if (error)
		goto error;
	error = aafs_create(".remove", 0640, &aa_fs_profile_remove);
	if (error)
		goto error;

	/* TODO: add support for apparmorfs_null and apparmorfs_mnt */

	/* Report that AppArmor fs is enabled */
	aa_info_message("AppArmor Filesystem Enabled");
	return 0;

error:
	aa_destroy_aafs();
	AA_ERROR("Error creating AppArmor securityfs\n");
	return error;
}
Ejemplo n.º 2
0
static struct aa_ns *__aa_create_ns(struct aa_ns *parent, const char *name,
				    struct dentry *dir)
{
	struct aa_ns *ns;
	int error;

	AA_BUG(!parent);
	AA_BUG(!name);
	AA_BUG(!mutex_is_locked(&parent->lock));

	ns = alloc_ns(parent->base.hname, name);
	if (!ns)
		return NULL;
	mutex_lock(&ns->lock);
	error = __aa_fs_ns_mkdir(ns, ns_subns_dir(parent), name);
	if (error) {
		AA_ERROR("Failed to create interface for ns %s\n",
			 ns->base.name);
		mutex_unlock(&ns->lock);
		aa_free_ns(ns);
		return ERR_PTR(error);
	}
	ns->parent = aa_get_ns(parent);
	ns->level = parent->level + 1;
	list_add_rcu(&ns->base.list, &parent->sub_ns);
	/* add list ref */
	aa_get_ns(ns);
	mutex_unlock(&ns->lock);

	return ns;
}
Ejemplo n.º 3
0
/**
 * policy_destroy - free the elements referenced by @policy
 * @policy: policy that is to have its elements freed  (NOT NULL)
 */
static void policy_destroy(struct aa_policy *policy)
{
	/* still contains profiles -- invalid */
	if (!list_empty(&policy->profiles)) {
		AA_ERROR("%s: internal error, "
			 "policy '%s' still contains profiles\n",
			 __func__, policy->name);
		BUG();
	}
	if (!list_empty(&policy->list)) {
		AA_ERROR("%s: internal error, policy '%s' still on list\n",
			 __func__, policy->name);
		BUG();
	}

	/* don't free name as its a subset of hname */
	kzfree(policy->hname);
}
Ejemplo n.º 4
0
static void policy_destroy(struct aa_policy *policy)
{
	
	if (!list_empty(&policy->profiles)) {
		AA_ERROR("%s: internal error, "
			 "policy '%s' still contains profiles\n",
			 __func__, policy->name);
		BUG();
	}
	if (!list_empty(&policy->list)) {
		AA_ERROR("%s: internal error, policy '%s' still on list\n",
			 __func__, policy->name);
		BUG();
	}

	
	kzfree(policy->hname);
}
Ejemplo n.º 5
0
/**
 * split_token_from_name - separate a string of form  <token>^<name>
 * @op: operation being checked
 * @args: string to parse  (NOT NULL)
 * @token: stores returned parsed token value  (NOT NULL)
 *
 * Returns: start position of name after token else NULL on failure
 */
static char *split_token_from_name(int op, char *args, u64 * token)
{
	char *name;

	*token = simple_strtoull(args, &name, 16);
	if ((name == args) || *name != '^') {
		AA_ERROR("%s: Invalid input '%s'", op_table[op], args);
		return ERR_PTR(-EINVAL);
	}

	name++;			/* skip ^ */
	if (!*name)
		name = NULL;
	return name;
}
Ejemplo n.º 6
0
static int __init init_profile_hash(void)
{
	struct crypto_shash *tfm;

	if (!apparmor_initialized)
		return 0;

	tfm = crypto_alloc_shash("sha1", 0, 0);
	if (IS_ERR(tfm)) {
		int error = PTR_ERR(tfm);
		AA_ERROR("failed to setup profile sha1 hashing: %d\n", error);
		return error;
	}
	apparmor_tfm = tfm;
	apparmor_hash_size = crypto_shash_digestsize(apparmor_tfm);

	aa_info_message("AppArmor sha1 policy hashing enabled");

	return 0;
}
Ejemplo n.º 7
0
/**
 * aa_setprocattr_chagnehat - handle procattr interface to change_hat
 * @args: args received from writing to /proc/<pid>/attr/current (NOT NULL)
 * @size: size of the args
 * @test: true if this is a test of change_hat permissions
 *
 * Returns: %0 or error code if change_hat fails
 */
int aa_setprocattr_changehat(char *args, size_t size, int test)
{
	char *hat;
	u64 token;
	const char *hats[16];		/* current hard limit on # of names */
	int count = 0;

	hat = split_token_from_name(OP_CHANGE_HAT, args, &token);
	if (IS_ERR(hat))
		return PTR_ERR(hat);

	if (!hat && !token) {
		AA_ERROR("change_hat: Invalid input, NULL hat and NULL magic");
		return -EINVAL;
	}

	if (hat) {
		/* set up hat name vector, args guaranteed null terminated
		 * at args[size] by setprocattr.
		 *
		 * If there are multiple hat names in the buffer each is
		 * separated by a \0.  Ie. userspace writes them pre tokenized
		 */
		char *end = args + size;
		for (count = 0; (hat < end) && count < 16; ++count) {
			char *next = hat + strlen(hat) + 1;
			hats[count] = hat;
			hat = next;
		}
	}

	AA_DEBUG("%s: Magic 0x%llx Hat '%s'\n",
		 __func__, token, hat ? hat : NULL);

	return aa_change_hat(hats, count, token, test);
}
Ejemplo n.º 8
0
/**
 * aa_audit_base - core AppArmor function.
 * @type: type of audit message (see include/linux/apparmor.h)
 * @profile: active profile for event (MAY BE NULL)
 * @sa: audit structure containing data to audit
 * @audit_cxt: audit_cxt that event is under
 * @cb: audit cb for this event
 *
 * Record an audit message for data is @sa, and handle deal with kill and
 * complain messages switches.
 *
 * Returns: 0 or sa->error on success, else error
 */
static int aa_audit_base(int type, struct aa_profile *profile,
			 struct aa_audit *sa, struct audit_context *audit_cxt,
			 void (*cb) (struct audit_buffer *, struct aa_audit *))
{
	struct audit_buffer *ab = NULL;
	struct task_struct *task = sa->task ? sa->task : current;

	if (profile && DO_KILL(profile) && type == AUDIT_APPARMOR_DENIED)
		type = AUDIT_APPARMOR_KILL;

	/* ab freed below in audit_log_end */
	ab = audit_log_start(audit_cxt, sa->gfp_mask, type);

	if (!ab) {
		AA_ERROR("(%d) Unable to log event of type (%d)\n",
			 -ENOMEM, type);
		sa->error = -ENOMEM;
		goto out;
	}

	if (aa_g_audit_header) {
		audit_log_format(ab, " type=");
		audit_log_string(ab, aa_audit_type[type - AUDIT_APPARMOR_AUDIT]);
	}

	if (sa->operation) {
		audit_log_format(ab, " operation=");
		audit_log_string(ab, sa->operation);
	}

	if (sa->info) {
		audit_log_format(ab, " info=");
		audit_log_string(ab, sa->info);
		if (sa->error)
			audit_log_format(ab, " error=%d", sa->error);
	}

	audit_log_format(ab, " pid=%d", task->pid);

	if (profile && !unconfined(profile)) {
		pid_t pid;
		rcu_read_lock();
		pid = task->real_parent->pid;
		rcu_read_unlock();
		audit_log_format(ab, " parent=%d", pid);
		audit_log_format(ab, " profile=");
		audit_log_untrustedstring(ab, profile->base.hname);

		if (profile->ns != root_ns) {
			audit_log_format(ab, " namespace=");
			audit_log_untrustedstring(ab, profile->ns->base.hname);
		}
	}

	if (cb)
		cb(ab, sa);

	audit_log_end(ab);

out:
	if (type == AUDIT_APPARMOR_KILL)
		(void)send_sig_info(SIGKILL, NULL, task);

	return type == AUDIT_APPARMOR_ALLOWED ? 0 : sa->error;
}