Re: [AppArmor 37/41] AppArmor: Main Part

2007-04-13 Thread Nick Piggin

Andreas Gruenbacher wrote:

On Thursday 12 April 2007 12:37, Alan Cox wrote:


+   if (PTR_ERR(sa->name) == -ENOENT && (check & AA_CHECK_FD))
+   denied_mask = 0;


Now there is an interesting question. Is PTR_ERR() safe for kernel
pointers on all platforms or just for user ones ?



It's used for kernel pointers all over the place and mmap also mixes user 
addresses with -Exxx, so it's definitely supposed to work. I'm not sure how 
exactly the topmost page is kept from getting mapped.


Yeah, the comments indicate it was first used for dentries.

I wonder if it shouldn't be using the NULL page instead? (ie 0-4095)

--
SUSE Labs, Novell Inc.
-
To unsubscribe from this list: send the line "unsubscribe linux-fsdevel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [AppArmor 37/41] AppArmor: Main Part

2007-04-13 Thread Andreas Gruenbacher
On Thursday 12 April 2007 12:37, Alan Cox wrote:
> > +   if (PTR_ERR(sa->name) == -ENOENT && (check & AA_CHECK_FD))
> > +   denied_mask = 0;
>
> Now there is an interesting question. Is PTR_ERR() safe for kernel
> pointers on all platforms or just for user ones ?

It's used for kernel pointers all over the place and mmap also mixes user 
addresses with -Exxx, so it's definitely supposed to work. I'm not sure how 
exactly the topmost page is kept from getting mapped.

Andreas
-
To unsubscribe from this list: send the line "unsubscribe linux-fsdevel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [AppArmor 37/41] AppArmor: Main Part

2007-04-13 Thread Andreas Gruenbacher
On Thursday 12 April 2007 12:37, Alan Cox wrote:
> The proc file system may not be mounted at /proc. There are environments
> where this is done for good reason (eg not wanting the /proc info exposed
> to a low trust environment). Another is when FUSE is providing an
> arbitrated proc either by merging across clusters or by removing stuff.
> [...]
> Why can't this be done in the profile itself to avoid kernel special case
> uglies and inflexibility ?

Good points. I'm in fact not sure how this could have been missed, and indeed 
it makes more sense to put this in profiles.

Thanks,
Andreas
-
To unsubscribe from this list: send the line "unsubscribe linux-fsdevel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [AppArmor 37/41] AppArmor: Main Part

2007-04-12 Thread Alan Cox
> + * 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;

The proc file system may not be mounted at /proc. There are environments
where this is done for good reason (eg not wanting the /proc info exposed
to a low trust environment). Another is when FUSE is providing an
arbitrated proc either by merging across clusters or by removing stuff.

> +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;

Why can't this be done in the profile itself to avoid kernel special case
uglies and inflexibility ?

> + if (PTR_ERR(sa->name) == -ENOENT && (check & AA_CHECK_FD))
> + denied_mask = 0;

Now there is an interesting question. Is PTR_ERR() safe for kernel
pointers on all platforms or just for user ones ?


-
To unsubscribe from this list: send the line "unsubscribe linux-fsdevel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[AppArmor 37/41] AppArmor: Main Part

2007-04-12 Thread jjohansen
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