The underlying functions by which the AppArmor LSM hooks are implemented.
Signed-off-by: John Johansen <[EMAIL PROTECTED]>
Signed-off-by: Andreas Gruenbacher <[EMAIL PROTECTED]>
---
security/apparmor/main.c | 1322 +++
1 file changed, 1322 insertions(+)
--- /dev/null
+++ b/security/apparmor/main.c
@@ -0,0 +1,1322 @@
+/*
+ * Copyright (C) 2002-2007 Novell/SUSE
+ *
+ * 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.
+ *
+ * AppArmor Core
+ */
+
+#include
+#include
+#include
+#include
+#include
+
+#include "apparmor.h"
+
+#include "inline.h"
+
+/*
+ * Table of capability names: we generate it from capabilities.h.
+ */
+static const char *capability_names[] = {
+#include "capability_names.h"
+};
+
+/* NULL complain profile
+ *
+ * Used when in complain mode, to emit Permitting messages for non-existant
+ * profiles and hats. This is necessary because of selective mode, in which
+ * case we need a complain null_profile and enforce null_profile
+ *
+ * The null_complain_profile cannot be statically allocated, because it
+ * can be associated to files which keep their reference even if apparmor is
+ * unloaded
+ */
+struct aa_profile *null_complain_profile;
+
+/**
+ * aa_taskattr_access
+ * @name: name of the file to check
+ *
+ * Check if name matches /proc/self/attr/current, with self resolved
+ * to the current pid. This file is the usermode iterface for
+ * changing one's hat.
+ */
+static inline int aa_taskattr_access(const char *name)
+{
+ unsigned long pid;
+ char *end;
+
+ if (strncmp(name, "/proc/", 6) != 0)
+ return 0;
+ pid = simple_strtoul(name + 6, &end, 10);
+ if (pid != current->pid)
+ return 0;
+ return strcmp(end, "/attr/current") == 0;
+}
+
+static inline void aa_permerror2result(int perm_result, struct aa_audit *sa)
+{
+ if (perm_result == 0) { /* success */
+ sa->result = 1;
+ sa->error_code = 0;
+ } else { /* -ve internal error code or +ve mask of denied perms */
+ sa->result = 0;
+ sa->error_code = perm_result;
+ }
+}
+
+/**
+ * aa_file_denied - check for @mask access on a file
+ * @profile: profile to check against
+ * @name: pathname of file
+ * @mask: permission mask requested for file
+ *
+ * Return %0 on success, or else the permissions in @mask that the
+ * profile denies.
+ */
+static int aa_file_denied(struct aa_profile *profile, const char *name,
+ int mask)
+{
+ int perms;
+
+ /* Always allow write access to /proc/self/attr/current. */
+ if (mask == MAY_WRITE && aa_taskattr_access(name))
+ return 0;
+
+ perms = aa_match(profile->file_rules, name);
+
+ return (mask & ~perms);
+}
+
+/**
+ * aa_link_denied - check for permission to link a file
+ * @profile: profile to check against
+ * @link: pathname of link being created
+ * @target: pathname of target to be linked to
+ *
+ * Return %0 on success, or else the permissions that the profile denies.
+ */
+static int aa_link_denied(struct aa_profile *profile, const char *link,
+ const char *target)
+{
+ int l_mode, t_mode;
+
+ l_mode = aa_match(profile->file_rules, link);
+ t_mode = aa_match(profile->file_rules, target);
+
+ /**
+* Link always requires 'l' on the link, a subset of the
+* target's 'r', 'w', 'x', and 'm' permissions on the link, and
+* if the link has 'x', an exact match of all the execute flags
+* ('i', 'u', 'U', 'p', 'P').
+*/
+#define RWXM (MAY_READ | MAY_WRITE | MAY_EXEC | AA_EXEC_MMAP)
+ if ((l_mode & AA_MAY_LINK) &&
+ (l_mode & RWXM) && !(l_mode & ~t_mode & RWXM) &&
+ (!(l_mode & MAY_EXEC) ||
+((l_mode & AA_EXEC_MODIFIERS) == (t_mode & AA_EXEC_MODIFIERS) &&
+ (l_mode & AA_EXEC_UNSAFE) == (t_mode & AA_EXEC_UNSAFE
+ return 0;
+#undef RWXM
+ /**
+* FIXME: There currenly is no way to report which permissions
+* we expect in t_mode, so linking could fail even after learning
+* the required l_mode.
+*/
+ return AA_MAY_LINK;
+}
+
+/**
+ * aa_get_name - compute the pathname of a file
+ * @dentry: dentry of the file
+ * @mnt: vfsmount of the file
+ * @buffer: buffer that aa_get_name() allocated
+ * @check: AA_CHECK_DIR is set if the file is a directory
+ *
+ * Returns a pointer to the beginning of the pathname (which usually differs
+ * from the beginning of the buffer), or an error code.
+ *
+ * We need @check to indicate whether the file is a directory or not because
+ * the file may not yet exist, and so we cannot check the inode's file type.
+ */
+static char *aa_get_name(struct dentry *dentr