lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite for Android: free password hash cracker in your pocket
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <1257292099-15802-4-git-send-email-john.johansen@canonical.com>
Date:	Tue,  3 Nov 2009 15:48:10 -0800
From:	John Johansen <john.johansen@...onical.com>
To:	linux-kernel@...r.kernel.org
Cc:	linux-security-module@...r.kernel.org,
	John Johansen <john.johansen@...onical.com>
Subject: [PATCH 03/12] AppArmor: contexts used in attaching policy to system objects

AppArmor contexts attach profiles and state to tasks, files, etc. when
a direct profile reference is not sufficient.

Signed-off-by: John Johansen <john.johansen@...onical.com>
---
 security/apparmor/context.c         |  224 +++++++++++++++++++++++++++++++++++
 security/apparmor/include/context.h |  146 +++++++++++++++++++++++
 2 files changed, 370 insertions(+), 0 deletions(-)
 create mode 100644 security/apparmor/context.c
 create mode 100644 security/apparmor/include/context.h

diff --git a/security/apparmor/context.c b/security/apparmor/context.c
new file mode 100644
index 0000000..81cc089
--- /dev/null
+++ b/security/apparmor/context.c
@@ -0,0 +1,224 @@
+/*
+ * AppArmor security module
+ *
+ * This file contains AppArmor functions used to manipulate object security
+ * contexts.
+ *
+ * Copyright (C) 1998-2008 Novell/SUSE
+ * Copyright 2009 Canonical Ltd.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation, version 2 of the
+ * License.
+ */
+
+#include "include/context.h"
+#include "include/policy.h"
+
+struct aa_task_context *aa_alloc_task_context(gfp_t flags)
+{
+	return kzalloc(sizeof(struct aa_task_context), flags);
+}
+
+void aa_free_task_context(struct aa_task_context *cxt)
+{
+	if (cxt) {
+		aa_put_profile(cxt->sys.profile);
+		aa_put_profile(cxt->sys.previous);
+		aa_put_profile(cxt->sys.onexec);
+
+		kzfree(cxt);
+	}
+}
+
+/*
+ * duplicate a task context, incrementing reference counts
+ */
+struct aa_task_context *aa_dup_task_context(struct aa_task_context *old_cxt,
+					    gfp_t gfp)
+{
+	struct aa_task_context *cxt;
+
+	cxt = kmemdup(old_cxt, sizeof(*cxt), gfp);
+	if (!cxt)
+		return NULL;
+
+	aa_get_profile(cxt->sys.profile);
+	aa_get_profile(cxt->sys.previous);
+	aa_get_profile(cxt->sys.onexec);
+
+	return cxt;
+}
+
+/**
+ * aa_cred_policy - obtain cred's profiles
+ * @cred: cred to obtain profiles from
+ * @sys: return system profile
+ * does NOT increment reference count
+ */
+void aa_cred_policy(const struct cred *cred, struct aa_profile **sys)
+{
+	struct aa_task_context *cxt = cred->security;
+	BUG_ON(!cxt);
+	*sys = aa_filtered_profile(aa_profile_newest(cxt->sys.profile));
+}
+
+/**
+ * aa_get_task_policy - get the cred with the task policy, and current profiles
+ * @task: task to get policy of
+ * @sys: return - pointer to system profile
+ *
+ * Only gets the cred ref count which has ref counts on the profiles returned
+ */
+struct cred *aa_get_task_policy(const struct task_struct *task,
+				struct aa_profile **sys)
+{
+	struct cred *cred = get_task_cred(task);
+	aa_cred_policy(cred, sys);
+	return cred;
+}
+
+void aa_put_task_policy(struct cred *cred)
+{
+	put_cred(cred);
+}
+
+static void replace_group(struct aa_task_cxt_group *cgrp,
+			  struct aa_profile *profile)
+{
+	if (cgrp->profile == profile)
+		return;
+
+	if (!profile || (profile->flags & PFLAG_UNCONFINED) ||
+	    (cgrp->profile && cgrp->profile->ns != profile->ns)) {
+		aa_put_profile(cgrp->previous);
+		aa_put_profile(cgrp->onexec);
+		cgrp->previous = NULL;
+		cgrp->onexec = NULL;
+		cgrp->token = 0;
+	}
+	aa_put_profile(cgrp->profile);
+	cgrp->profile = aa_get_profile(profile);
+}
+
+/**
+ * aa_replace_current_profiles - replace the current tasks profiles
+ * @sys: new system profile
+ *
+ * Returns: error on failure
+ */
+int aa_replace_current_profiles(struct aa_profile *sys)
+{
+	struct aa_task_context *cxt;
+	struct cred *new = prepare_creds();
+	if (!new)
+		return -ENOMEM;
+
+	cxt = new->security;
+	replace_group(&cxt->sys, sys);
+
+	commit_creds(new);
+	return 0;
+}
+
+/**
+ * aa_set_current_onexec - set the tasks change_profile to happen onexec
+ * @sys: system profile to set at exec
+ *
+ * Returns: error on failure
+ */
+int aa_set_current_onexec(struct aa_profile *sys)
+{
+	struct aa_task_context *cxt;
+	struct cred *new = prepare_creds();
+	if (!new)
+		return -ENOMEM;
+
+	cxt = new->security;
+	aa_put_profile(cxt->sys.onexec);
+	cxt->sys.onexec = aa_get_profile(sys);
+
+	commit_creds(new);
+	return 0;
+}
+
+/**
+ * aa_set_current_hat - set the current tasks hat
+ * @profile: profile to set as the current hat
+ * @token: token value that must be specified to change from the hat
+ *
+ * Do switch of tasks hat.  If the task is currently in a hat
+ * validate the token to match.
+ *
+ * Returns: error on failure
+ */
+int aa_set_current_hat(struct aa_profile *profile, u64 token)
+{
+	struct aa_task_context *cxt;
+	struct cred *new = prepare_creds();
+	if (!new)
+		return -ENOMEM;
+
+	cxt = new->security;
+	if (!cxt->sys.previous) {
+		cxt->sys.previous = cxt->sys.profile;
+		cxt->sys.token = token;
+	} else if (cxt->sys.token == token) {
+		aa_put_profile(cxt->sys.profile);
+	} else {
+		/* previous_profile && cxt->token != token */
+		abort_creds(new);
+		return -EACCES;
+	}
+	cxt->sys.profile = aa_get_profile(profile);
+	/* clear exec on switching context */
+	aa_put_profile(cxt->sys.onexec);
+	cxt->sys.onexec = NULL;
+
+	commit_creds(new);
+	return 0;
+}
+
+/**
+ * aa_restore_previous_profile - exit from hat context restoring the profile
+ * @token: the token that must be matched to exit hat context
+ *
+ * Attempt to return out of a hat to the previous profile.  The token
+ * must match the stored token value.
+ *
+ * Returns: error of failure
+ */
+int aa_restore_previous_profile(u64 token)
+{
+	struct aa_task_context *cxt;
+	struct cred *new = prepare_creds();
+	if (!new)
+		return -ENOMEM;
+
+	cxt = new->security;
+	if (cxt->sys.token != token) {
+		abort_creds(new);
+		return -EACCES;
+	}
+	/* ignore restores when there is no saved profile */
+	if (!cxt->sys.previous) {
+		abort_creds(new);
+		return 0;
+	}
+
+	aa_put_profile(cxt->sys.profile);
+	cxt->sys.profile = aa_profile_newest(cxt->sys.previous);
+	if (unlikely(cxt->sys.profile != cxt->sys.previous)) {
+		aa_get_profile(cxt->sys.profile);
+		aa_put_profile(cxt->sys.previous);
+	}
+	/* clear exec && prev information when restoring to previous context */
+	cxt->sys.previous = NULL;
+	cxt->sys.token = 0;
+	aa_put_profile(cxt->sys.onexec);
+	cxt->sys.onexec = NULL;
+
+	commit_creds(new);
+	return 0;
+}
diff --git a/security/apparmor/include/context.h b/security/apparmor/include/context.h
new file mode 100644
index 0000000..5f30f31
--- /dev/null
+++ b/security/apparmor/include/context.h
@@ -0,0 +1,146 @@
+/*
+ * AppArmor security module
+ *
+ * This file contains AppArmor contexts used to associate "labels" to objects.
+ *
+ * Copyright (C) 1998-2008 Novell/SUSE
+ * Copyright 2009 Canonical Ltd.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation, version 2 of the
+ * License.
+ */
+
+#ifndef __AA_CONTEXT_H
+#define __AA_CONTEXT_H
+
+#include <linux/cred.h>
+#include <linux/slab.h>
+#include <linux/sched.h>
+
+#include "policy.h"
+
+/* struct aa_file_cxt - the AppArmor context the file was opened in
+ * @profile: the profile the file was opened under
+ * @perms: the permission the file was opened with
+ */
+struct aa_file_cxt {
+	struct aa_profile *profile;
+	u16 allowed;
+};
+
+static inline struct aa_file_cxt *aa_alloc_file_context(gfp_t gfp)
+{
+	return kzalloc(sizeof(struct aa_file_cxt), gfp);
+}
+
+static inline void aa_free_file_context(struct aa_file_cxt *cxt)
+{
+	aa_put_profile(cxt->profile);
+	memset(cxt, 0, sizeof(struct aa_file_cxt));
+	kfree(cxt);
+}
+
+/* struct aa_task_cxt_group - a grouping label data for confined tasks
+ * @profile: the current profile
+ * @exec: profile to transition to on next exec
+ * @previous: profile the task may return to
+ * @token: magic value the task must know for returning to @previous_profile
+ *
+ * Contains the task's current profile (which could change due to
+ * change_hat).  Plus the hat_magic needed during change_hat.
+ */
+struct aa_task_cxt_group {
+	struct aa_profile *profile;
+	struct aa_profile *onexec;
+	struct aa_profile *previous;
+	u64 token;
+};
+
+/**
+ * struct aa_task_context - primary label for confined tasks
+ * @sys: the system labeling for the task
+ *
+ * A task is confined by the intersection of its system and user profiles
+ */
+struct aa_task_context {
+	struct aa_task_cxt_group sys;
+};
+
+struct aa_task_context *aa_alloc_task_context(gfp_t flags);
+void aa_free_task_context(struct aa_task_context *cxt);
+struct aa_task_context *aa_dup_task_context(struct aa_task_context *old_cxt,
+					    gfp_t gfp);
+void aa_cred_policy(const struct cred *cred, struct aa_profile **sys);
+struct cred *aa_get_task_policy(const struct task_struct *task,
+				struct aa_profile **sys);
+int aa_replace_current_profiles(struct aa_profile *sys);
+void aa_put_task_policy(struct cred *cred);
+int aa_set_current_onexec(struct aa_profile *sys);
+int aa_set_current_hat(struct aa_profile *profile, u64 token);
+int aa_restore_previous_profile(u64 cookie);
+
+static inline struct aa_task_context *__aa_task_cxt(struct task_struct *task)
+{
+	return __task_cred(task)->security;
+}
+
+/**
+ * __aa_task_is_confined - determine if @task has any confinement
+ * @task: task to check confinement of
+ *
+ * If @task != current needs to be in RCU safe critical section
+ */
+static inline int __aa_task_is_confined(struct task_struct *task)
+{
+	struct aa_task_context *cxt;
+	int rc = 1;
+
+	cxt = __aa_task_cxt(task);
+	if (!cxt || (cxt->sys.profile->flags & PFLAG_UNCONFINED))
+		rc = 0;
+
+	return rc;
+}
+
+static inline const struct cred *aa_current_policy(struct aa_profile **sys)
+{
+	const struct cred *cred = current_cred();
+	struct aa_task_context *cxt = cred->security;
+	BUG_ON(!cxt);
+	*sys = aa_filtered_profile(aa_profile_newest(cxt->sys.profile));
+
+	return cred;
+}
+
+static inline const struct cred *aa_current_policy_wupd(struct aa_profile **sys)
+{
+	const struct cred *cred = current_cred();
+	struct aa_task_context *cxt = cred->security;
+	BUG_ON(!cxt);
+
+	*sys = aa_profile_newest(cxt->sys.profile);
+	if (unlikely((cxt->sys.profile != *sys)))
+		aa_replace_current_profiles(*sys);
+	*sys = aa_filtered_profile(*sys);
+
+	return cred;
+}
+
+static inline struct aa_profile *aa_current_profile(void)
+{
+	const struct cred *cred = current_cred();
+	struct aa_task_context *cxt = cred->security;
+	BUG_ON(!cxt);
+	return aa_filtered_profile(aa_profile_newest(cxt->sys.profile));
+}
+
+static inline struct aa_profile *aa_current_profile_wupd(void)
+{
+	struct aa_profile *p;
+	aa_current_policy_wupd(&p);
+	return p;
+}
+
+#endif /* __AA_CONTEXT_H */
-- 
1.6.3.3

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ