オープンソース・ソフトウェアの開発とダウンロード

Subversion リポジトリの参照

Diff of /trunk/1.6.x/ccs-patch/fs/tomoyo_domain.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 1016 by kumaneko, Tue Mar 4 05:51:18 2008 UTC revision 1029 by kumaneko, Mon Mar 10 08:00:50 2008 UTC
# Line 5  Line 5 
5   *   *
6   * Copyright (C) 2005-2008  NTT DATA CORPORATION   * Copyright (C) 2005-2008  NTT DATA CORPORATION
7   *   *
8   * Version: 1.6.0-pre   2008/03/04   * Version: 1.6.0-pre   2008/03/10
9   *   *
10   * This file is applicable to both 2.4.30 and 2.6.11 and later.   * This file is applicable to both 2.4.30 and 2.6.11 and later.
11   * See README.ccs for ChangeLog.   * See README.ccs for ChangeLog.
# Line 85  static DEFINE_MUTEX(new_domain_assign_lo Line 85  static DEFINE_MUTEX(new_domain_assign_lo
85    
86  /*************************  UTILITY FUNCTIONS  *************************/  /*************************  UTILITY FUNCTIONS  *************************/
87    
88    void SetDomainFlag(struct domain_info *domain, const bool is_delete, const u8 flags)
89    {
90            mutex_lock(&new_domain_assign_lock);
91            if (!is_delete) domain->flags |= flags;
92            else domain->flags &= ~flags;
93            mutex_unlock(&new_domain_assign_lock);
94    }
95    
96  const char *GetLastName(const struct domain_info *domain)  const char *GetLastName(const struct domain_info *domain)
97  {  {
98          const char *cp0 = domain->domainname->name, *cp1;          const char *cp0 = domain->domainname->name, *cp1;
# Line 602  static char *get_argv0(struct linux_binp Line 610  static char *get_argv0(struct linux_binp
610          return NULL;          return NULL;
611  }  }
612    
613  static int FindNextDomain(struct linux_binprm *bprm, struct domain_info **next_domain, const u8 do_perm_check)  static int FindNextDomain(struct linux_binprm *bprm, struct domain_info **next_domain, const struct path_info *path_to_verify)
614  {  {
615          /* This function assumes that the size of buffer returned by realpath() = CCS_MAX_PATHNAME_LEN. */          /* This function assumes that the size of buffer returned by realpath() = CCS_MAX_PATHNAME_LEN. */
616          struct domain_info *old_domain = current->domain_info, *domain = NULL;          struct domain_info *old_domain = current->domain_info, *domain = NULL;
# Line 640  static int FindNextDomain(struct linux_b Line 648  static int FindNextDomain(struct linux_b
648          else l.name = old_domain_name;          else l.name = old_domain_name;
649          fill_path_info(&l);          fill_path_info(&l);
650    
651          if (!do_perm_check) goto ok;          if (path_to_verify) {
652                    if (pathcmp(&r, path_to_verify)) {
653                            static u8 counter = 20;
654                            if (counter) {
655                                    counter--;
656                                    printk("Failed to verify: %s\n", path_to_verify->name);
657                            }
658                            goto out;
659                    }
660                    goto ok;
661            }
662    
663          /* Check 'alias' directive. */          /* Check 'alias' directive. */
664          if (pathcmp(&r, &s)) {          if (pathcmp(&r, &s)) {
# Line 839  static void UnEscape(unsigned char *dest Line 857  static void UnEscape(unsigned char *dest
857          *dest = '\0';          *dest = '\0';
858  }  }
859    
860  static int try_alt_exec(struct linux_binprm *bprm, char **work)  #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
861    #include <linux/namei.h>
862    #include <linux/mount.h>
863    #endif
864    
865    /*
866     * GetRootDepth - return the depth of root directory.
867     */
868    static int GetRootDepth(void)
869    {
870            int depth = 0;
871            struct dentry *dentry;
872            struct vfsmount *vfsmnt;
873    #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,25)
874            struct path root;
875    #endif
876            read_lock(&current->fs->lock);
877    #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,25)
878            root = current->fs->root;
879            path_get(&current->fs->root);
880            dentry = root.dentry;
881            vfsmnt = root.mnt;
882    #else
883            dentry = dget(current->fs->root);
884            vfsmnt = mntget(current->fs->rootmnt);
885    #endif
886            read_unlock(&current->fs->lock);
887            /***** CRITICAL SECTION START *****/
888            spin_lock(&dcache_lock);
889    #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
890            spin_lock(&vfsmount_lock);
891    #endif
892            for (;;) {
893                    if (dentry == vfsmnt->mnt_root || IS_ROOT(dentry)) {
894                            /* Global root? */
895                            if (vfsmnt->mnt_parent == vfsmnt) break;
896                            dentry = vfsmnt->mnt_mountpoint;
897                            vfsmnt = vfsmnt->mnt_parent;
898                            continue;
899                    }
900                    dentry = dentry->d_parent;
901                    depth++;
902            }
903    #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
904            spin_unlock(&vfsmount_lock);
905    #endif
906            spin_unlock(&dcache_lock);
907            /***** CRITICAL SECTION END *****/
908    #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,25)
909            path_put(&root);
910    #else
911            dput(dentry);
912            mntput(vfsmnt);
913    #endif
914            return depth;
915    }
916    
917    static int try_alt_exec(struct linux_binprm *bprm, const struct path_info *filename, char **work, struct domain_info **next_domain)
918  {  {
919          /*          /*
920           * Contents of modified bprm.           * Contents of modified bprm.
# Line 853  static int try_alt_exec(struct linux_bin Line 928  static int try_alt_exec(struct linux_bin
928           *    = 0           *    = 0
929           *           *
930           * modified bprm->argv[0]           * modified bprm->argv[0]
931           *    = the program's name specified by alt_exec           *    = the program's name specified by execute_handler
932           * modified bprm->argv[1]           * modified bprm->argv[1]
933           *    = current->domain_info->domainname->name           *    = current->domain_info->domainname->name
934           * modified bprm->argv[2]           * modified bprm->argv[2]
# Line 882  static int try_alt_exec(struct linux_bin Line 957  static int try_alt_exec(struct linux_bin
957          const int original_argc = bprm->argc;          const int original_argc = bprm->argc;
958          const int original_envc = bprm->envc;          const int original_envc = bprm->envc;
959          struct task_struct *task = current;          struct task_struct *task = current;
960          static const int buffer_len = PAGE_SIZE;          static const int buffer_len = CCS_MAX_PATHNAME_LEN;
961          char *buffer = NULL;          char *buffer = NULL;
962          char *alt_exec;          char *execute_handler;
         const char *alt_exec1 = GetAltExec();  
         if (!alt_exec1 || *alt_exec1 != '/') return -EINVAL;  
         retval = strlen(alt_exec1) + 1;  
         alt_exec = ccs_alloc(retval);  
         if (!alt_exec) return -ENOMEM;  
         *work = alt_exec;  
         memmove(alt_exec, alt_exec1, retval);  
         UnEscape(alt_exec);  
963    
964          /* Close the rejected program's dentry. */          /* Close the requested program's dentry. */
965          allow_write_access(bprm->file);          allow_write_access(bprm->file);
966          fput(bprm->file);          fput(bprm->file);
967          bprm->file = NULL;          bprm->file = NULL;
968    
969            /* Allocate memory for execute handler's pathname. */
970            execute_handler = ccs_alloc(buffer_len);
971            *work = execute_handler;
972            if (!execute_handler) return -ENOMEM;
973            strncpy(execute_handler, filename->name, buffer_len - 1);
974            UnEscape(execute_handler);
975            
976            if (1) { /* Adjust root directory for open_exec(). */
977                    int depth = GetRootDepth();
978                    char *cp = execute_handler;
979                    if (!*cp || *cp != '/') return -ENOENT;
980                    while (depth) {
981                            cp = strchr(cp + 1, '/');
982                            if (!cp) return -ENOENT;
983                            depth--;
984                    }
985                    memmove(execute_handler, cp, strlen(cp) + 1);
986            }
987    
988          /* Allocate buffer. */          /* Allocate buffer. */
989          buffer = ccs_alloc(buffer_len);          buffer = ccs_alloc(buffer_len);
990          if (!buffer) return -ENOMEM;          if (!buffer) return -ENOMEM;
# Line 963  static int try_alt_exec(struct linux_bin Line 1049  static int try_alt_exec(struct linux_bin
1049    
1050          /* Set argv[0] */          /* Set argv[0] */
1051          {          {
1052                  retval = copy_strings_kernel(1, &alt_exec, bprm);                  retval = copy_strings_kernel(1, &execute_handler, bprm);
1053                  if (retval < 0) goto out;                  if (retval < 0) goto out;
1054                  bprm->argc++;                  bprm->argc++;
1055          }          }
# Line 971  static int try_alt_exec(struct linux_bin Line 1057  static int try_alt_exec(struct linux_bin
1057          bprm->argv_len = bprm->exec - bprm->p;          bprm->argv_len = bprm->exec - bprm->p;
1058  #endif  #endif
1059    
1060          /* OK, now restart the process with the alternative program's dentry. */          /* OK, now restart the process with execute handler program's dentry. */
1061          filp = open_exec(alt_exec);          filp = open_exec(execute_handler);
1062          if (IS_ERR(filp)) {          if (IS_ERR(filp)) {
1063                  retval = PTR_ERR(filp);                  retval = PTR_ERR(filp);
1064                  goto out;                  goto out;
1065          }          }
1066          bprm->file= filp;          bprm->file= filp;
1067          bprm->filename = alt_exec;          bprm->filename = execute_handler;
1068  #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)  #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
1069          bprm->interp = alt_exec;          bprm->interp = execute_handler;
1070  #endif  #endif
1071          retval = 0;          retval = prepare_binprm(bprm);
1072            if (retval < 0) goto out;
1073            task->tomoyo_flags |= CCS_DONT_SLEEP_ON_ENFORCE_ERROR;
1074            retval = FindNextDomain(bprm, next_domain, filename);
1075            task->tomoyo_flags &= ~CCS_DONT_SLEEP_ON_ENFORCE_ERROR;
1076   out:   out:
1077          /* Free buffer. */          /* Free buffer. */
1078          ccs_free(buffer);          ccs_free(buffer);
1079          return retval;          return retval;
1080  }  }
1081    
1082    static const struct path_info *FindExecuteHandler(bool is_preferred_handler)
1083    {
1084            const struct domain_info *domain = current->domain_info;
1085            struct acl_info *ptr;
1086            const u8 type = is_preferred_handler ? TYPE_PREFERRED_EXECUTE_HANDLER : TYPE_DEFAULT_EXECUTE_HANDLER;
1087            list1_for_each_entry(ptr, &domain->acl_info_list, list) {
1088                    struct execute_handler_record *acl;
1089                    if (ptr->type != type) continue;
1090                    acl = container_of(ptr, struct execute_handler_record, head);
1091                    return acl->handler;
1092            }
1093            return NULL;
1094    }
1095    
1096  int search_binary_handler_with_transition(struct linux_binprm *bprm, struct pt_regs *regs)  int search_binary_handler_with_transition(struct linux_binprm *bprm, struct pt_regs *regs)
1097  {  {
1098          struct domain_info *next_domain = NULL, *prev_domain = current->domain_info;          struct task_struct *task = current;
1099            struct domain_info *next_domain = NULL, *prev_domain = task->domain_info;
1100            const struct path_info *handler;
1101          int retval;          int retval;
1102          char *work = NULL; /* Keep valid until search_binary_handler() finishes. */          char *work = NULL; /* Keep valid until search_binary_handler() finishes. */
1103          CCS_LoadPolicy(bprm->filename);          CCS_LoadPolicy(bprm->filename);
1104          if (prev_domain->flags & DOMAIN_FLAGS_FORCE_ALT_EXEC) retval = -EPERM;          //printk("rootdepth=%d\n", GetRootDepth());
1105          else retval = FindNextDomain(bprm, &next_domain, 1);          handler = FindExecuteHandler(true);
1106          if (retval == -EPERM && try_alt_exec(bprm, &work) == 0 && prepare_binprm(bprm) >= 0) {          if (handler) {
1107                  current->tomoyo_flags |= CCS_DONT_SLEEP_ON_ENFORCE_ERROR;                  retval = try_alt_exec(bprm, handler, &work, &next_domain);
1108                  retval = FindNextDomain(bprm, &next_domain, 0);          } else if ((retval = FindNextDomain(bprm, &next_domain, NULL)) == -EPERM) {
1109                  current->tomoyo_flags &= ~CCS_DONT_SLEEP_ON_ENFORCE_ERROR;                  handler = FindExecuteHandler(false);
1110          }                  if (handler) retval = try_alt_exec(bprm, handler, &work, &next_domain);
1111          if (retval == 0) {          }
1112                  current->domain_info = next_domain;          if (retval) goto out;
1113                  retval = CheckEnviron(bprm);          task->domain_info = next_domain;
1114                  current->tomoyo_flags |= TOMOYO_CHECK_READ_FOR_OPEN_EXEC;          retval = CheckEnviron(bprm);
1115                  if (!retval) retval = search_binary_handler(bprm, regs);          if (retval) goto out;
1116                  current->tomoyo_flags &= ~TOMOYO_CHECK_READ_FOR_OPEN_EXEC;          task->tomoyo_flags |= TOMOYO_CHECK_READ_FOR_OPEN_EXEC;
1117                  if (retval < 0) current->domain_info = prev_domain;          retval = search_binary_handler(bprm, regs);
1118          }          task->tomoyo_flags &= ~TOMOYO_CHECK_READ_FOR_OPEN_EXEC;
1119     out:
1120            if (retval < 0) task->domain_info = prev_domain;
1121          ccs_free(work);          ccs_free(work);
1122          return retval;          return retval;
1123  }  }

Legend:
Removed from v.1016  
changed lines
  Added in v.1029

Back to OSDN">Back to OSDN
ViewVC Help
Powered by ViewVC 1.1.26