TOMOYO: Support longer pathname.
authorTetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>
Thu, 3 Jun 2010 11:36:43 +0000 (20:36 +0900)
committerJames Morris <jmorris@namei.org>
Mon, 2 Aug 2010 05:33:41 +0000 (15:33 +1000)
Allow pathnames longer than 4000 bytes.

Signed-off-by: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>
Signed-off-by: James Morris <jmorris@namei.org>
security/tomoyo/common.h
security/tomoyo/domain.c
security/tomoyo/file.c
security/tomoyo/memory.c
security/tomoyo/mount.c
security/tomoyo/realpath.c

index 6270a53..f4a8aa2 100644 (file)
@@ -33,14 +33,7 @@ struct linux_binprm;
 #define TOMOYO_HASH_BITS  8
 #define TOMOYO_MAX_HASH (1u<<TOMOYO_HASH_BITS)
 
-/*
- * This is the max length of a token.
- *
- * A token consists of only ASCII printable characters.
- * Non printable characters in a token is represented in \ooo style
- * octal string. Thus, \ itself is represented as \\.
- */
-#define TOMOYO_MAX_PATHNAME_LEN 4000
+#define TOMOYO_EXEC_TMPSIZE     4096
 
 /* Profile number is an integer between 0 and 255. */
 #define TOMOYO_MAX_PROFILES 256
@@ -167,17 +160,6 @@ enum tomoyo_securityfs_interface_index {
 
 /********** Structure definitions. **********/
 
-/*
- * tomoyo_page_buffer is a structure which is used for holding a pathname
- * obtained from "struct dentry" and "struct vfsmount" pair.
- * As of now, it is 4096 bytes. If users complain that 4096 bytes is too small
- * (because TOMOYO escapes non ASCII printable characters using \ooo format),
- * we will make the buffer larger.
- */
-struct tomoyo_page_buffer {
-       char buffer[4096];
-};
-
 /*
  * tomoyo_request_info is a structure which is used for holding
  *
@@ -231,28 +213,6 @@ struct tomoyo_name_entry {
        struct tomoyo_path_info entry;
 };
 
-/*
- * tomoyo_path_info_with_data is a structure which is used for holding a
- * pathname obtained from "struct dentry" and "struct vfsmount" pair.
- *
- * "struct tomoyo_path_info_with_data" consists of "struct tomoyo_path_info"
- * and buffer for the pathname, while "struct tomoyo_page_buffer" consists of
- * buffer for the pathname only.
- *
- * "struct tomoyo_path_info_with_data" is intended to allow TOMOYO to release
- * both "struct tomoyo_path_info" and buffer for the pathname by single kfree()
- * so that we don't need to return two pointers to the caller. If the caller
- * puts "struct tomoyo_path_info" on stack memory, we will be able to remove
- * "struct tomoyo_path_info_with_data".
- */
-struct tomoyo_path_info_with_data {
-       /* Keep "head" first, for this pointer is passed to kfree(). */
-       struct tomoyo_path_info head;
-       char barrier1[16]; /* Safeguard for overrun. */
-       char body[TOMOYO_MAX_PATHNAME_LEN];
-       char barrier2[16]; /* Safeguard for overrun. */
-};
-
 struct tomoyo_name_union {
        const struct tomoyo_path_info *filename;
        struct tomoyo_path_group *group;
@@ -827,11 +787,7 @@ void tomoyo_load_policy(const char *filename);
 void tomoyo_put_number_union(struct tomoyo_number_union *ptr);
 
 /* Convert binary string to ascii string. */
-int tomoyo_encode(char *buffer, int buflen, const char *str);
-
-/* Returns realpath(3) of the given pathname but ignores chroot'ed root. */
-int tomoyo_realpath_from_path2(struct path *path, char *newname,
-                              int newname_len);
+char *tomoyo_encode(const char *str);
 
 /*
  * Returns realpath(3) of the given pathname but ignores chroot'ed root.
index 08428bc..7b8693e 100644 (file)
@@ -676,47 +676,43 @@ struct tomoyo_domain_info *tomoyo_find_or_assign_new_domain(const char *
 int tomoyo_find_next_domain(struct linux_binprm *bprm)
 {
        struct tomoyo_request_info r;
-       /*
-        * This function assumes that the size of buffer returned by
-        * tomoyo_realpath() = TOMOYO_MAX_PATHNAME_LEN.
-        */
-       struct tomoyo_page_buffer *tmp = kzalloc(sizeof(*tmp), GFP_NOFS);
+       char *tmp = kzalloc(TOMOYO_EXEC_TMPSIZE, GFP_NOFS);
        struct tomoyo_domain_info *old_domain = tomoyo_domain();
        struct tomoyo_domain_info *domain = NULL;
        const char *old_domain_name = old_domain->domainname->name;
        const char *original_name = bprm->filename;
-       char *new_domain_name = NULL;
-       char *real_program_name = NULL;
-       char *symlink_program_name = NULL;
        const u8 mode = tomoyo_check_flags(old_domain, TOMOYO_MAC_FOR_FILE);
        const bool is_enforce = (mode == TOMOYO_CONFIG_ENFORCING);
        int retval = -ENOMEM;
-       struct tomoyo_path_info rn; /* real name */
-       struct tomoyo_path_info sn; /* symlink name */
+       bool need_kfree = false;
+       struct tomoyo_path_info rn = { }; /* real name */
+       struct tomoyo_path_info sn = { }; /* symlink name */
        struct tomoyo_path_info ln; /* last name */
 
+       ln.name = tomoyo_get_last_name(old_domain);
+       tomoyo_fill_path_info(&ln);
        tomoyo_init_request_info(&r, NULL);
        if (!tmp)
                goto out;
 
  retry:
+       if (need_kfree) {
+               kfree(rn.name);
+               need_kfree = false;
+       }
        /* Get tomoyo_realpath of program. */
        retval = -ENOENT;
-       /* I hope tomoyo_realpath() won't fail with -ENOMEM. */
-       real_program_name = tomoyo_realpath(original_name);
-       if (!real_program_name)
+       rn.name = tomoyo_realpath(original_name);
+       if (!rn.name)
                goto out;
+       tomoyo_fill_path_info(&rn);
+       need_kfree = true;
+
        /* Get tomoyo_realpath of symbolic link. */
-       symlink_program_name = tomoyo_realpath_nofollow(original_name);
-       if (!symlink_program_name)
+       sn.name = tomoyo_realpath_nofollow(original_name);
+       if (!sn.name)
                goto out;
-
-       rn.name = real_program_name;
-       tomoyo_fill_path_info(&rn);
-       sn.name = symlink_program_name;
        tomoyo_fill_path_info(&sn);
-       ln.name = tomoyo_get_last_name(old_domain);
-       tomoyo_fill_path_info(&ln);
 
        /* Check 'alias' directive. */
        if (tomoyo_pathcmp(&rn, &sn)) {
@@ -727,10 +723,10 @@ int tomoyo_find_next_domain(struct linux_binprm *bprm)
                            tomoyo_pathcmp(&rn, ptr->original_name) ||
                            tomoyo_pathcmp(&sn, ptr->aliased_name))
                                continue;
-                       memset(real_program_name, 0, TOMOYO_MAX_PATHNAME_LEN);
-                       strncpy(real_program_name, ptr->aliased_name->name,
-                               TOMOYO_MAX_PATHNAME_LEN - 1);
-                       tomoyo_fill_path_info(&rn);
+                       kfree(rn.name);
+                       need_kfree = false;
+                       /* This is OK because it is read only. */
+                       rn = *ptr->aliased_name;
                        break;
                }
        }
@@ -742,11 +738,10 @@ int tomoyo_find_next_domain(struct linux_binprm *bprm)
        if (retval < 0)
                goto out;
 
-       new_domain_name = tmp->buffer;
        if (tomoyo_is_domain_initializer(old_domain->domainname, &rn, &ln)) {
                /* Transit to the child of tomoyo_kernel_domain domain. */
-               snprintf(new_domain_name, TOMOYO_MAX_PATHNAME_LEN + 1,
-                        TOMOYO_ROOT_NAME " " "%s", real_program_name);
+               snprintf(tmp, TOMOYO_EXEC_TMPSIZE - 1,
+                        TOMOYO_ROOT_NAME " " "%s", rn.name);
        } else if (old_domain == &tomoyo_kernel_domain &&
                   !tomoyo_policy_loaded) {
                /*
@@ -760,29 +755,27 @@ int tomoyo_find_next_domain(struct linux_binprm *bprm)
                domain = old_domain;
        } else {
                /* Normal domain transition. */
-               snprintf(new_domain_name, TOMOYO_MAX_PATHNAME_LEN + 1,
-                        "%s %s", old_domain_name, real_program_name);
+               snprintf(tmp, TOMOYO_EXEC_TMPSIZE - 1,
+                        "%s %s", old_domain_name, rn.name);
        }
-       if (domain || strlen(new_domain_name) >= TOMOYO_MAX_PATHNAME_LEN)
+       if (domain || strlen(tmp) >= TOMOYO_EXEC_TMPSIZE - 10)
                goto done;
-       domain = tomoyo_find_domain(new_domain_name);
+       domain = tomoyo_find_domain(tmp);
        if (domain)
                goto done;
        if (is_enforce) {
                int error = tomoyo_supervisor(&r, "# wants to create domain\n"
-                                             "%s\n", new_domain_name);
+                                             "%s\n", tmp);
                if (error == TOMOYO_RETRY_REQUEST)
                        goto retry;
                if (error < 0)
                        goto done;
        }
-       domain = tomoyo_find_or_assign_new_domain(new_domain_name,
-                                                 old_domain->profile);
+       domain = tomoyo_find_or_assign_new_domain(tmp, old_domain->profile);
  done:
        if (domain)
                goto out;
-       printk(KERN_WARNING "TOMOYO-ERROR: Domain '%s' not defined.\n",
-              new_domain_name);
+       printk(KERN_WARNING "TOMOYO-ERROR: Domain '%s' not defined.\n", tmp);
        if (is_enforce)
                retval = -EPERM;
        else
@@ -793,8 +786,9 @@ int tomoyo_find_next_domain(struct linux_binprm *bprm)
        /* Update reference count on "struct tomoyo_domain_info". */
        atomic_inc(&domain->users);
        bprm->cred->security = domain;
-       kfree(real_program_name);
-       kfree(symlink_program_name);
+       if (need_kfree)
+               kfree(rn.name);
+       kfree(sn.name);
        kfree(tmp);
        return retval;
 }
Simple merge
Simple merge
Simple merge
Simple merge