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

Subversion リポジトリの参照

Diff of /trunk/1.8.x/ccs-patch/security/ccsecurity/domain.c

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

revision 1139 by kumaneko, Fri Apr 25 04:04:20 2008 UTC revision 1695 by kumaneko, Sat Oct 11 08:46:59 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.1-rc   2008/04/24   * Version: 1.6.5-pre   2008/10/11
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 37  LIST1_HEAD(domain_list); Line 37  LIST1_HEAD(domain_list);
37    
38  #ifdef CONFIG_TOMOYO  #ifdef CONFIG_TOMOYO
39    
 /* Lock for appending domain's ACL. */  
 DEFINE_MUTEX(domain_acl_lock);  
   
40  /* Domain creation lock. */  /* Domain creation lock. */
41  static DEFINE_MUTEX(new_domain_assign_lock);  static DEFINE_MUTEX(new_domain_assign_lock);
42    
# Line 108  void ccs_set_domain_flag(struct domain_i Line 105  void ccs_set_domain_flag(struct domain_i
105   */   */
106  const char *ccs_get_last_name(const struct domain_info *domain)  const char *ccs_get_last_name(const struct domain_info *domain)
107  {  {
108          const char *cp0 = domain->domainname->name, *cp1 = strrchr(cp0, ' ');          const char *cp0 = domain->domainname->name;
109            const char *cp1 = strrchr(cp0, ' ');
110          if (cp1)          if (cp1)
111                  return cp1 + 1;                  return cp1 + 1;
112          return cp0;          return cp0;
# Line 124  const char *ccs_get_last_name(const stru Line 122  const char *ccs_get_last_name(const stru
122   */   */
123  int ccs_add_domain_acl(struct domain_info *domain, struct acl_info *acl)  int ccs_add_domain_acl(struct domain_info *domain, struct acl_info *acl)
124  {  {
125          if (domain)          if (domain) {
126                    /*
127                     * We need to serialize because this function is called by
128                     * various update functions.
129                     */
130                    static DEFINE_SPINLOCK(lock);
131                    /***** CRITICAL SECTION START *****/
132                    spin_lock(&lock);
133                  list1_add_tail_mb(&acl->list, &domain->acl_info_list);                  list1_add_tail_mb(&acl->list, &domain->acl_info_list);
134          else                  spin_unlock(&lock);
135                    /***** CRITICAL SECTION END *****/
136            } else {
137                  acl->type &= ~ACL_DELETED;                  acl->type &= ~ACL_DELETED;
138            }
139          ccs_update_counter(CCS_UPDATES_COUNTER_DOMAIN_POLICY);          ccs_update_counter(CCS_UPDATES_COUNTER_DOMAIN_POLICY);
140          return 0;          return 0;
141  }  }
# Line 160  static int audit_execute_handler_log(con Line 168  static int audit_execute_handler_log(con
168                                       const char *handler,                                       const char *handler,
169                                       struct linux_binprm *bprm)                                       struct linux_binprm *bprm)
170  {  {
171          char *buf;          struct ccs_request_info r;
172          int len;          ccs_init_request_info(&r, NULL, CCS_TOMOYO_MAC_FOR_FILE);
173          int len2;          r.bprm = bprm;
174          u8 profile;          return ccs_write_audit_log(true, &r, "%s %s\n",
175          u8 mode;                                     is_default ? KEYWORD_EXECUTE_HANDLER :
176          if (ccs_can_save_audit_log(true) < 0)                                     KEYWORD_DENIED_EXECUTE_HANDLER, handler);
                 return -ENOMEM;  
         len = strlen(handler) + 32;  
         profile = current->domain_info->profile;  
         mode = ccs_check_flags(CCS_TOMOYO_MAC_FOR_FILE);  
         buf = ccs_init_audit_log(&len, profile, mode, bprm);  
         if (!buf)  
                 return -ENOMEM;  
         len2 = strlen(buf);  
         snprintf(buf + len2, len - len2 - 1, "%s %s\n",  
                  is_default ? KEYWORD_EXECUTE_HANDLER :  
                  KEYWORD_DENIED_EXECUTE_HANDLER, handler);  
         return ccs_write_audit_log(buf, true);  
177  }  }
178    
179  /**  /**
180   * audit_domain_creation_log - Audit domain creation log.   * audit_domain_creation_log - Audit domain creation log.
181   *   *
182   * @domainname: The name of newly created domain.   * @domain:  Pointer to "struct domain_info".
  * @mode:       Access control mode used.  
  * @profile:    Profile number used.  
183   *   *
184   * Returns 0 on success, negative value otherwise.   * Returns 0 on success, negative value otherwise.
185   */   */
186  static int audit_domain_creation_log(const char *domainname, const u8 mode,  static int audit_domain_creation_log(struct domain_info *domain)
                                      const u8 profile)  
187  {  {
188          char *buf;          struct ccs_request_info r;
189          char *cp;          ccs_init_request_info(&r, domain, CCS_TOMOYO_MAC_FOR_FILE);
190          int len;          return ccs_write_audit_log(false, &r, "use_profile %u\n", r.profile);
         int len2;  
         if (ccs_can_save_audit_log(false) < 0)  
                 return -ENOMEM;  
         len = strlen(domainname) + 32;  
         buf = ccs_init_audit_log(&len, profile, mode, NULL);  
         if (!buf)  
                 return -ENOMEM;  
         cp = strchr(buf, '\n');  
         if (!cp) {  
                 ccs_free(buf);  
                 return -ENOMEM;  
         }  
         *++cp = '\0';  
         len2 = strlen(buf);  
         snprintf(buf + len2, len - len2 - 1, "%s\nuse_profile %u\n",  
                  domainname, profile);  
         return ccs_write_audit_log(buf, false);  
191  }  }
192    
193  /* The list for "struct domain_initializer_entry". */  /* The list for "struct domain_initializer_entry". */
# Line 985  static bool get_argv0(struct linux_binpr Line 961  static bool get_argv0(struct linux_binpr
961  /**  /**
962   * find_next_domain - Find a domain.   * find_next_domain - Find a domain.
963   *   *
964   * @bprm:           Pointer to "struct linux_binprm".   * @r:       Pointer to "struct ccs_request_info".
965   * @next_domain:    Pointer to pointer to "struct domain_info".   * @handler: Pathname to verify. May be NULL.
  * @path_to_verify: Pathname to verify. May be NULL.  
  * @tmp:            Buffer for temporal use.  
966   *   *
967   * Returns 0 on success, negative value otherwise.   * Returns 0 on success, negative value otherwise.
968   */   */
969  static int find_next_domain(struct linux_binprm *bprm,  static int find_next_domain(struct ccs_request_info *r,
970                              struct domain_info **next_domain,                              const struct path_info *handler)
                             const struct path_info *path_to_verify,  
                             struct ccs_page_buffer *tmp)  
971  {  {
972          /*          /*
973           * This function assumes that the size of buffer returned by           * This function assumes that the size of buffer returned by
974           * ccs_realpath() = CCS_MAX_PATHNAME_LEN.           * ccs_realpath() = CCS_MAX_PATHNAME_LEN.
975           */           */
         struct domain_info *old_domain = current->domain_info;  
976          struct domain_info *domain = NULL;          struct domain_info *domain = NULL;
977          const char *old_domain_name = old_domain->domainname->name;          const char *old_domain_name = r->domain->domainname->name;
978            struct linux_binprm *bprm = r->bprm;
979            struct ccs_page_buffer *tmp = r->obj->tmp;
980          const char *original_name = bprm->filename;          const char *original_name = bprm->filename;
981            const u8 mode = r->mode;
982            const bool is_enforce = (mode == 3);
983            const u32 tomoyo_flags = r->tomoyo_flags;
984          char *new_domain_name = NULL;          char *new_domain_name = NULL;
985          char *real_program_name = NULL;          char *real_program_name = NULL;
986          char *symlink_program_name = NULL;          char *symlink_program_name = NULL;
987          const u8 mode = ccs_check_flags(CCS_TOMOYO_MAC_FOR_FILE);          struct path_info rn; /* real name */
988          const bool is_enforce = (mode == 3);          struct path_info sn; /* symlink name */
989            struct path_info ln; /* last name */
990          int retval;          int retval;
         struct path_info r; /* real name */  
         struct path_info s; /* symlink name */  
         struct path_info l; /* last name */  
991    
992          {          {
993                  /*                  /*
# Line 1030  static int find_next_domain(struct linux Line 1004  static int find_next_domain(struct linux
1004                  }                  }
1005          }          }
1006    
1007     retry:
1008            current->tomoyo_flags = tomoyo_flags;
1009            r->tomoyo_flags = tomoyo_flags;
1010          /* Get ccs_realpath of program. */          /* Get ccs_realpath of program. */
1011          retval = -ENOENT; /* I hope ccs_realpath() won't fail with -ENOMEM. */          retval = -ENOENT; /* I hope ccs_realpath() won't fail with -ENOMEM. */
1012            ccs_free(real_program_name);
1013          real_program_name = ccs_realpath(original_name);          real_program_name = ccs_realpath(original_name);
1014          if (!real_program_name)          if (!real_program_name)
1015                  goto out;                  goto out;
1016          /* Get ccs_realpath of symbolic link. */          /* Get ccs_realpath of symbolic link. */
1017            ccs_free(symlink_program_name);
1018          symlink_program_name = ccs_realpath_nofollow(original_name);          symlink_program_name = ccs_realpath_nofollow(original_name);
1019          if (!symlink_program_name)          if (!symlink_program_name)
1020                  goto out;                  goto out;
1021    
1022          r.name = real_program_name;          rn.name = real_program_name;
1023          ccs_fill_path_info(&r);          ccs_fill_path_info(&rn);
1024          s.name = symlink_program_name;          sn.name = symlink_program_name;
1025          ccs_fill_path_info(&s);          ccs_fill_path_info(&sn);
1026          l.name = ccs_get_last_name(old_domain);          ln.name = ccs_get_last_name(r->domain);
1027          ccs_fill_path_info(&l);          ccs_fill_path_info(&ln);
1028    
1029          if (path_to_verify) {          if (handler) {
1030                  if (ccs_pathcmp(&r, path_to_verify)) {                  if (ccs_pathcmp(&rn, handler)) {
1031                          /* Failed to verify execute handler. */                          /* Failed to verify execute handler. */
1032                          static u8 counter = 20;                          static u8 counter = 20;
1033                          if (counter) {                          if (counter) {
1034                                  counter--;                                  counter--;
1035                                  printk(KERN_WARNING "Failed to verify: %s\n",                                  printk(KERN_WARNING "Failed to verify: %s\n",
1036                                         path_to_verify->name);                                         handler->name);
1037                          }                          }
1038                          goto out;                          goto out;
1039                  }                  }
# Line 1062  static int find_next_domain(struct linux Line 1041  static int find_next_domain(struct linux
1041          }          }
1042    
1043          /* Check 'alias' directive. */          /* Check 'alias' directive. */
1044          if (ccs_pathcmp(&r, &s)) {          if (ccs_pathcmp(&rn, &sn)) {
1045                  struct alias_entry *ptr;                  struct alias_entry *ptr;
1046                  /* Is this program allowed to be called via symbolic links? */                  /* Is this program allowed to be called via symbolic links? */
1047                  list1_for_each_entry(ptr, &alias_list, list) {                  list1_for_each_entry(ptr, &alias_list, list) {
1048                          if (ptr->is_deleted ||                          if (ptr->is_deleted ||
1049                              ccs_pathcmp(&r, ptr->original_name) ||                              ccs_pathcmp(&rn, ptr->original_name) ||
1050                              ccs_pathcmp(&s, ptr->aliased_name))                              ccs_pathcmp(&sn, ptr->aliased_name))
1051                                  continue;                                  continue;
1052                          memset(real_program_name, 0, CCS_MAX_PATHNAME_LEN);                          memset(real_program_name, 0, CCS_MAX_PATHNAME_LEN);
1053                          strncpy(real_program_name, ptr->aliased_name->name,                          strncpy(real_program_name, ptr->aliased_name->name,
1054                                  CCS_MAX_PATHNAME_LEN - 1);                                  CCS_MAX_PATHNAME_LEN - 1);
1055                          ccs_fill_path_info(&r);                          ccs_fill_path_info(&rn);
1056                          break;                          break;
1057                  }                  }
1058          }          }
1059    
1060          /* Compare basename of real_program_name and argv[0] */          /* Compare basename of real_program_name and argv[0] */
1061          if (bprm->argc > 0 && ccs_check_flags(CCS_TOMOYO_MAC_FOR_ARGV0)) {          r->mode = ccs_check_flags(r->domain, CCS_TOMOYO_MAC_FOR_ARGV0);
1062            if (bprm->argc > 0 && r->mode) {
1063                  char *base_argv0 = tmp->buffer;                  char *base_argv0 = tmp->buffer;
1064                  const char *base_filename;                  const char *base_filename;
1065                  retval = -ENOMEM;                  retval = -ENOMEM;
# Line 1091  static int find_next_domain(struct linux Line 1071  static int find_next_domain(struct linux
1071                  else                  else
1072                          base_filename++;                          base_filename++;
1073                  if (strcmp(base_argv0, base_filename)) {                  if (strcmp(base_argv0, base_filename)) {
1074                          retval = ccs_check_argv0_perm(&r, base_argv0);                          retval = ccs_check_argv0_perm(r, &rn, base_argv0);
1075                          if (retval)                          if (retval == 1) {
1076                                    r->retry++;
1077                                    goto retry;
1078                            }
1079                            r->retry = 0;
1080                            r->tomoyo_flags = current->tomoyo_flags;
1081                            if (retval < 0)
1082                                  goto out;                                  goto out;
1083                  }                  }
1084          }          }
# Line 1103  static int find_next_domain(struct linux Line 1089  static int find_next_domain(struct linux
1089                  /* Is this program allowed to be aggregated? */                  /* Is this program allowed to be aggregated? */
1090                  list1_for_each_entry(ptr, &aggregator_list, list) {                  list1_for_each_entry(ptr, &aggregator_list, list) {
1091                          if (ptr->is_deleted ||                          if (ptr->is_deleted ||
1092                              !ccs_path_matches_pattern(&r, ptr->original_name))                              !ccs_path_matches_pattern(&rn, ptr->original_name))
1093                                  continue;                                  continue;
1094                          memset(real_program_name, 0, CCS_MAX_PATHNAME_LEN);                          memset(real_program_name, 0, CCS_MAX_PATHNAME_LEN);
1095                          strncpy(real_program_name, ptr->aggregated_name->name,                          strncpy(real_program_name, ptr->aggregated_name->name,
1096                                  CCS_MAX_PATHNAME_LEN - 1);                                  CCS_MAX_PATHNAME_LEN - 1);
1097                          ccs_fill_path_info(&r);                          ccs_fill_path_info(&rn);
1098                          break;                          break;
1099                  }                  }
1100          }          }
1101    
1102          /* Check execute permission. */          /* Check execute permission. */
1103          retval = ccs_check_exec_perm(&r, bprm, tmp);          r->mode = mode;
1104            retval = ccs_check_exec_perm(r, &rn);
1105            if (retval == 1) {
1106                    r->retry++;
1107                    goto retry;
1108            }
1109            r->retry = 0;
1110            r->tomoyo_flags = current->tomoyo_flags;
1111          if (retval < 0)          if (retval < 0)
1112                  goto out;                  goto out;
1113    
1114   calculate_domain:   calculate_domain:
1115          new_domain_name = tmp->buffer;          new_domain_name = tmp->buffer;
1116          if (is_domain_initializer(old_domain->domainname, &r, &l)) {          if (is_domain_initializer(r->domain->domainname, &rn, &ln)) {
1117                  /* Transit to the child of KERNEL_DOMAIN domain. */                  /* Transit to the child of KERNEL_DOMAIN domain. */
1118                  snprintf(new_domain_name, CCS_MAX_PATHNAME_LEN + 1,                  snprintf(new_domain_name, CCS_MAX_PATHNAME_LEN + 1,
1119                           ROOT_NAME " " "%s", real_program_name);                           ROOT_NAME " " "%s", real_program_name);
1120          } else if (old_domain == &KERNEL_DOMAIN && !sbin_init_started) {          } else if (r->domain == &KERNEL_DOMAIN && !sbin_init_started) {
1121                  /*                  /*
1122                   * Needn't to transit from kernel domain before starting                   * Needn't to transit from kernel domain before starting
1123                   * /sbin/init. But transit from kernel domain if executing                   * /sbin/init. But transit from kernel domain if executing
1124                   * initializers because they might start before /sbin/init.                   * initializers because they might start before /sbin/init.
1125                   */                   */
1126                  domain = old_domain;                  domain = r->domain;
1127          } else if (is_domain_keeper(old_domain->domainname, &r, &l)) {          } else if (is_domain_keeper(r->domain->domainname, &rn, &ln)) {
1128                  /* Keep current domain. */                  /* Keep current domain. */
1129                  domain = old_domain;                  domain = r->domain;
1130          } else {          } else {
1131                  /* Normal domain transition. */                  /* Normal domain transition. */
1132                  snprintf(new_domain_name, CCS_MAX_PATHNAME_LEN + 1,                  snprintf(new_domain_name, CCS_MAX_PATHNAME_LEN + 1,
# Line 1144  static int find_next_domain(struct linux Line 1137  static int find_next_domain(struct linux
1137          domain = ccs_find_domain(new_domain_name);          domain = ccs_find_domain(new_domain_name);
1138          if (domain)          if (domain)
1139                  goto done;                  goto done;
1140          if (is_enforce && ccs_check_supervisor("#Need to create domain\n%s\n",          if (is_enforce) {
1141                                                 new_domain_name))                  int error = ccs_check_supervisor(r,
1142                                                     "# wants to create domain\n"
1143                                                     "%s\n", new_domain_name);
1144                    if (error == 1) {
1145                            r->retry++;
1146                            goto retry;
1147                    }
1148                    r->retry = 0;
1149                    if (error < 0)
1150                          goto done;                          goto done;
1151          domain = ccs_find_or_assign_new_domain(new_domain_name,          }
1152                                                 old_domain->profile);          domain = ccs_find_or_assign_new_domain(new_domain_name, r->profile);
1153          if (domain)          if (domain)
1154                  audit_domain_creation_log(new_domain_name, mode,                  audit_domain_creation_log(domain);
                                           domain->profile);  
1155   done:   done:
1156          if (!domain) {          if (!domain) {
1157                  printk(KERN_WARNING "TOMOYO-ERROR: Domain '%s' not defined.\n",                  printk(KERN_WARNING "TOMOYO-ERROR: Domain '%s' not defined.\n",
1158                         new_domain_name);                         new_domain_name);
1159                  if (is_enforce)                  if (is_enforce)
1160                          retval = -EPERM;                          retval = -EPERM;
1161                  else                  else {
1162                          retval = -ENOMEM;                          retval = 0;
1163                            ccs_set_domain_flag(r->domain, false,
1164                                                DOMAIN_FLAGS_TRANSITION_FAILED);
1165                    }
1166          } else {          } else {
1167                  retval = 0;                  retval = 0;
1168          }          }
1169   out:   out:
1170          ccs_free(real_program_name);          ccs_free(real_program_name);
1171          ccs_free(symlink_program_name);          ccs_free(symlink_program_name);
1172          *next_domain = domain ? domain : old_domain;          if (domain)
1173                    r->domain = domain;
1174          return retval;          return retval;
1175  }  }
1176    
1177  /**  /**
1178   * check_environ - Check permission for environment variable names.   * check_environ - Check permission for environment variable names.
1179   *   *
1180   * @bprm: Pointer to "struct linux_binprm".   * @r: Pointer to "struct ccs_request_info".
  * @tmp:  Buffer for temporal use.  
1181   *   *
1182   * Returns 0 on success, negative value otherwise.   * Returns 0 on success, negative value otherwise.
1183   */   */
1184  static int check_environ(struct linux_binprm *bprm, struct ccs_page_buffer *tmp)  static int check_environ(struct ccs_request_info *r)
1185  {  {
1186          const u8 profile = current->domain_info->profile;          struct linux_binprm *bprm = r->bprm;
1187          const u8 mode = ccs_check_flags(CCS_TOMOYO_MAC_FOR_ENV);          struct ccs_page_buffer *tmp = r->obj->tmp;
1188          char *arg_ptr = tmp->buffer;          char *arg_ptr = tmp->buffer;
1189          int arg_len = 0;          int arg_len = 0;
1190          unsigned long pos = bprm->p;          unsigned long pos = bprm->p;
# Line 1191  static int check_environ(struct linux_bi Line 1194  static int check_environ(struct linux_bi
1194          int envp_count = bprm->envc;          int envp_count = bprm->envc;
1195          /* printk(KERN_DEBUG "start %d %d\n", argv_count, envp_count); */          /* printk(KERN_DEBUG "start %d %d\n", argv_count, envp_count); */
1196          int error = -ENOMEM;          int error = -ENOMEM;
1197          if (!mode || !envp_count)          if (!r->mode || !envp_count)
1198                  return 0;                  return 0;
1199          while (error == -ENOMEM) {          while (error == -ENOMEM) {
1200                  struct page *page;                  struct page *page;
# Line 1241  static int check_environ(struct linux_bi Line 1244  static int check_environ(struct linux_bi
1244                          }                          }
1245                          if (c)                          if (c)
1246                                  continue;                                  continue;
1247                          if (ccs_check_env_perm(arg_ptr, profile, mode)) {                          if (ccs_check_env_perm(r, arg_ptr)) {
1248                                  error = -EPERM;                                  error = -EPERM;
1249                                  break;                                  break;
1250                          }                          }
# Line 1261  static int check_environ(struct linux_bi Line 1264  static int check_environ(struct linux_bi
1264                  offset = 0;                  offset = 0;
1265          }          }
1266   out:   out:
1267          if (error && mode != 3)          if (r->mode != 3)
1268                  error = 0;                  error = 0;
1269          return error;          return error;
1270  }  }
# Line 1314  static inline int root_depth(struct dent Line 1317  static inline int root_depth(struct dent
1317  {  {
1318          int depth = 0;          int depth = 0;
1319          /***** CRITICAL SECTION START *****/          /***** CRITICAL SECTION START *****/
1320          spin_lock(&dcache_lock);          ccs_realpath_lock();
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 5, 0)  
         spin_lock(&vfsmount_lock);  
 #endif  
1321          for (;;) {          for (;;) {
1322                  if (dentry == vfsmnt->mnt_root || IS_ROOT(dentry)) {                  if (dentry == vfsmnt->mnt_root || IS_ROOT(dentry)) {
1323                          /* Global root? */                          /* Global root? */
# Line 1330  static inline int root_depth(struct dent Line 1330  static inline int root_depth(struct dent
1330                  dentry = dentry->d_parent;                  dentry = dentry->d_parent;
1331                  depth++;                  depth++;
1332          }          }
1333  #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 5, 0)          ccs_realpath_unlock();
         spin_unlock(&vfsmount_lock);  
 #endif  
         spin_unlock(&dcache_lock);  
1334          /***** CRITICAL SECTION END *****/          /***** CRITICAL SECTION END *****/
1335          return depth;          return depth;
1336  }  }
# Line 1377  static int get_root_depth(void) Line 1374  static int get_root_depth(void)
1374  /**  /**
1375   * try_alt_exec - Try to start execute handler.   * try_alt_exec - Try to start execute handler.
1376   *   *
1377   * @bprm:        Pointer to "struct linux_binprm".   * @r:           Pointer to "struct ccs_request_info".
1378   * @filename:    The name of requested program.   * @handler:     Pointer to the name of execute handler.
1379   * @work:        Pointer to pointer to the name of execute handler.   * @eh_path:     Pointer to pointer to the name of execute handler.
  * @next_domain: Pointer to pointer to "struct domain_info".  
  * @tmp:         Buffer for temporal use.  
1380   *   *
1381   * Returns 0 on success, negative value otherwise.   * Returns 0 on success, negative value otherwise.
1382   */   */
1383  static int try_alt_exec(struct linux_binprm *bprm,  static int try_alt_exec(struct ccs_request_info *r,
1384                          const struct path_info *filename, char **work,                          const struct path_info *handler, char **eh_path)
                         struct domain_info **next_domain,  
                         struct ccs_page_buffer *tmp)  
1385  {  {
1386          /*          /*
1387           * Contents of modified bprm.           * Contents of modified bprm.
# Line 1426  static int try_alt_exec(struct linux_bin Line 1419  static int try_alt_exec(struct linux_bin
1419           * modified bprm->argv[bprm->envc + bprm->argc + 6]           * modified bprm->argv[bprm->envc + bprm->argc + 6]
1420           *     = original bprm->envp[bprm->envc - 1]           *     = original bprm->envp[bprm->envc - 1]
1421           */           */
1422            struct linux_binprm *bprm = r->bprm;
1423          struct file *filp;          struct file *filp;
1424          int retval;          int retval;
1425          const int original_argc = bprm->argc;          const int original_argc = bprm->argc;
1426          const int original_envc = bprm->envc;          const int original_envc = bprm->envc;
1427          struct task_struct *task = current;          struct task_struct *task = current;
1428          char *buffer = tmp->buffer;          char *buffer = r->obj->tmp->buffer;
1429          /* Allocate memory for execute handler's pathname. */          /* Allocate memory for execute handler's pathname. */
1430          char *execute_handler = ccs_alloc(sizeof(struct ccs_page_buffer));          char *execute_handler = ccs_alloc(sizeof(struct ccs_page_buffer));
1431          *work = execute_handler;          *eh_path = execute_handler;
1432          if (!execute_handler)          if (!execute_handler)
1433                  return -ENOMEM;                  return -ENOMEM;
1434          strncpy(execute_handler, filename->name,          strncpy(execute_handler, handler->name,
1435                  sizeof(struct ccs_page_buffer) - 1);                  sizeof(struct ccs_page_buffer) - 1);
1436          unescape(execute_handler);          unescape(execute_handler);
1437    
# Line 1563  static int try_alt_exec(struct linux_bin Line 1557  static int try_alt_exec(struct linux_bin
1557          if (retval < 0)          if (retval < 0)
1558                  goto out;                  goto out;
1559          task->tomoyo_flags |= CCS_DONT_SLEEP_ON_ENFORCE_ERROR;          task->tomoyo_flags |= CCS_DONT_SLEEP_ON_ENFORCE_ERROR;
1560          retval = find_next_domain(bprm, next_domain, filename, tmp);          retval = find_next_domain(r, handler);
1561          task->tomoyo_flags &= ~CCS_DONT_SLEEP_ON_ENFORCE_ERROR;          task->tomoyo_flags &= ~CCS_DONT_SLEEP_ON_ENFORCE_ERROR;
1562   out:   out:
1563          return retval;          return retval;
# Line 1597  static const struct path_info *find_exec Line 1591  static const struct path_info *find_exec
1591          return NULL;          return NULL;
1592  }  }
1593    
1594    /* List of next_domain which is used for checking interpreter's permissions. */
1595    struct execve_entry {
1596            struct list_head list;
1597            struct task_struct *task;
1598            struct domain_info *next_domain;
1599    };
1600    
1601    static LIST_HEAD(execve_list);
1602    static DEFINE_SPINLOCK(execve_list_lock);
1603    
1604    /**
1605     * ccs_register_next_domain - Remember next_domain.
1606     *
1607     * @next_domain: Pointer to "struct domain_info".
1608     *
1609     * Returns 0 on success, -ENOMEM otherwise.
1610     */
1611    static int ccs_register_next_domain(struct domain_info *next_domain)
1612    {
1613            struct execve_entry *ee = kmalloc(sizeof(*ee), GFP_KERNEL);
1614            if (!ee)
1615                    return -ENOMEM;
1616            ee->task = current;
1617            ee->next_domain = next_domain;
1618            /***** CRITICAL SECTION START *****/
1619            spin_lock(&execve_list_lock);
1620            list_add(&ee->list, &execve_list);
1621            spin_unlock(&execve_list_lock);
1622            /***** CRITICAL SECTION END *****/
1623            return 0;
1624    }
1625    
1626    /**
1627     * ccs_fetch_next_domain - Fetch next_domain from the list.
1628     *
1629     * Returns pointer to "struct domain_info" which will be used if execve()
1630     * succeeds. This function does not return NULL.
1631     */
1632    struct domain_info *ccs_fetch_next_domain(void)
1633    {
1634            struct task_struct *task = current;
1635            struct domain_info *next_domain = task->domain_info;
1636            struct execve_entry *p;
1637            /***** CRITICAL SECTION START *****/
1638            spin_lock(&execve_list_lock);
1639            list_for_each_entry(p, &execve_list, list) {
1640                    if (p->task != task)
1641                            continue;
1642                    next_domain = p->next_domain;
1643                    break;
1644            }
1645            spin_unlock(&execve_list_lock);
1646            /***** CRITICAL SECTION END *****/
1647            return next_domain;
1648    }
1649    
1650    /**
1651     * ccs_unregister_next_domain - Forget next_domain.
1652     */
1653    static void ccs_unregister_next_domain(void)
1654    {
1655            struct task_struct *task = current;
1656            struct execve_entry *p;
1657            struct execve_entry *ee = NULL;
1658            /***** CRITICAL SECTION START *****/
1659            spin_lock(&execve_list_lock);
1660            list_for_each_entry(p, &execve_list, list) {
1661                    if (p->task != task)
1662                            continue;
1663                    list_del(&p->list);
1664                    ee = p;
1665                    break;
1666            }
1667            spin_unlock(&execve_list_lock);
1668            /***** CRITICAL SECTION END *****/
1669            kfree(ee);
1670    }
1671    
1672  /**  /**
1673   * search_binary_handler_with_transition - Perform domain transition.   * search_binary_handler_with_transition - Perform domain transition.
1674   *   *
# Line 1609  static const struct path_info *find_exec Line 1681  static const struct path_info *find_exec
1681  int search_binary_handler_with_transition(struct linux_binprm *bprm,  int search_binary_handler_with_transition(struct linux_binprm *bprm,
1682                                            struct pt_regs *regs)                                            struct pt_regs *regs)
1683  {  {
1684            int retval;
1685          struct task_struct *task = current;          struct task_struct *task = current;
         struct domain_info *next_domain = NULL;  
         struct domain_info *prev_domain = task->domain_info;  
1686          const struct path_info *handler;          const struct path_info *handler;
1687          int retval;          struct ccs_request_info r;
1688            struct obj_info obj;
1689          /*          /*
1690           * "work" holds path to program.           * "eh_path" holds path to execute handler program.
1691           * Thus, keep valid until search_binary_handler() finishes.           * Thus, keep valid until search_binary_handler() finishes.
1692           */           */
1693          char *work = NULL;          char *eh_path = NULL;
1694          struct ccs_page_buffer *buf = ccs_alloc(sizeof(struct ccs_page_buffer));          struct ccs_page_buffer *tmp = ccs_alloc(sizeof(struct ccs_page_buffer));
1695          ccs_load_policy(bprm->filename);          memset(&obj, 0, sizeof(obj));
1696          if (!buf)          if (!sbin_init_started)
1697                    ccs_load_policy(bprm->filename);
1698            if (!tmp)
1699                  return -ENOMEM;                  return -ENOMEM;
1700          /* printk(KERN_DEBUG "rootdepth=%d\n", get_root_depth()); */  
1701            ccs_init_request_info(&r, NULL, CCS_TOMOYO_MAC_FOR_FILE);
1702            r.bprm = bprm;
1703            r.obj = &obj;
1704            obj.path1_dentry = bprm->file->f_dentry;
1705            obj.path1_vfsmnt = bprm->file->f_vfsmnt;
1706            obj.tmp = tmp;
1707    
1708            /* Clear manager flag. */
1709            task->tomoyo_flags &= ~CCS_TASK_IS_POLICY_MANAGER;
1710          handler = find_execute_handler(TYPE_EXECUTE_HANDLER);          handler = find_execute_handler(TYPE_EXECUTE_HANDLER);
1711          if (handler) {          if (handler) {
1712                  retval = try_alt_exec(bprm, handler, &work, &next_domain, buf);                  retval = try_alt_exec(&r, handler, &eh_path);
1713                  if (!retval)                  if (!retval)
1714                          audit_execute_handler_log(true, work, bprm);                          audit_execute_handler_log(true, handler->name, bprm);
1715                  goto ok;                  goto ok;
1716          }          }
1717          retval = find_next_domain(bprm, &next_domain, NULL, buf);          retval = find_next_domain(&r, NULL);
1718          if (retval != -EPERM)          if (retval != -EPERM)
1719                  goto ok;                  goto ok;
1720          handler = find_execute_handler(TYPE_DENIED_EXECUTE_HANDLER);          handler = find_execute_handler(TYPE_DENIED_EXECUTE_HANDLER);
1721          if (handler) {          if (handler) {
1722                  retval = try_alt_exec(bprm, handler, &work, &next_domain, buf);                  retval = try_alt_exec(&r, handler, &eh_path);
1723                  if (!retval)                  if (!retval)
1724                          audit_execute_handler_log(false, work, bprm);                          audit_execute_handler_log(false, handler->name, bprm);
1725          }          }
1726   ok:   ok:
1727          if (retval)          if (retval < 0)
1728                    goto out;
1729            r.mode = ccs_check_flags(r.domain, CCS_TOMOYO_MAC_FOR_ENV);
1730            retval = check_environ(&r);
1731            if (retval < 0)
1732                  goto out;                  goto out;
1733          task->domain_info = next_domain;          retval = ccs_register_next_domain(r.domain);
1734          retval = check_environ(bprm, buf);          if (retval < 0)
         if (retval)  
1735                  goto out;                  goto out;
1736          task->tomoyo_flags |= TOMOYO_CHECK_READ_FOR_OPEN_EXEC;          task->tomoyo_flags |= TOMOYO_CHECK_READ_FOR_OPEN_EXEC;
1737          retval = search_binary_handler(bprm, regs);          retval = search_binary_handler(bprm, regs);
1738          task->tomoyo_flags &= ~TOMOYO_CHECK_READ_FOR_OPEN_EXEC;          task->tomoyo_flags &= ~TOMOYO_CHECK_READ_FOR_OPEN_EXEC;
  out:  
         /* Return to previous domain if execution failed. */  
1739          if (retval < 0)          if (retval < 0)
1740                  task->domain_info = prev_domain;                  goto out;
1741            /* Proceed to next domain if execution suceeded. */
1742            task->domain_info = r.domain;
1743            mb(); /* Make domain transition visible to other CPUs. */
1744          /* Mark the current process as execute handler. */          /* Mark the current process as execute handler. */
1745          else if (handler)          if (handler)
1746                  task->tomoyo_flags |= TOMOYO_TASK_IS_EXECUTE_HANDLER;                  task->tomoyo_flags |= TOMOYO_TASK_IS_EXECUTE_HANDLER;
1747          /* Mark the current process as normal process. */          /* Mark the current process as normal process. */
1748          else          else
1749                  task->tomoyo_flags &= ~TOMOYO_TASK_IS_EXECUTE_HANDLER;                  task->tomoyo_flags &= ~TOMOYO_TASK_IS_EXECUTE_HANDLER;
1750          ccs_free(work);   out:
1751          ccs_free(buf);          ccs_unregister_next_domain();
1752            ccs_free(eh_path);
1753            ccs_free(tmp);
1754          return retval;          return retval;
1755  }  }
1756    
# Line 1679  int search_binary_handler_with_transitio Line 1768  int search_binary_handler_with_transitio
1768                                            struct pt_regs *regs)                                            struct pt_regs *regs)
1769  {  {
1770  #ifdef CONFIG_SAKURA  #ifdef CONFIG_SAKURA
1771            /* Clear manager flag. */
1772            current->tomoyo_flags &= ~CCS_TASK_IS_POLICY_MANAGER;
1773          ccs_load_policy(bprm->filename);          ccs_load_policy(bprm->filename);
1774  #endif  #endif
1775          return search_binary_handler(bprm, regs);          return search_binary_handler(bprm, regs);

Legend:
Removed from v.1139  
changed lines
  Added in v.1695

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