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

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 1056 by kumaneko, Wed Mar 26 05:36:41 2008 UTC revision 1700 by kumaneko, Mon Oct 13 04:57: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-rc   2008/03/26   * 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(domain_list_lock);
42    
43  /* Structure for "initialize_domain" and "no_initialize_domain" keyword. */  /* Structure for "initialize_domain" and "no_initialize_domain" keyword. */
44  struct domain_initializer_entry {  struct domain_initializer_entry {
# Line 91  struct alias_entry { Line 88  struct alias_entry {
88  void ccs_set_domain_flag(struct domain_info *domain, const bool is_delete,  void ccs_set_domain_flag(struct domain_info *domain, const bool is_delete,
89                           const u8 flags)                           const u8 flags)
90  {  {
91          mutex_lock(&new_domain_assign_lock);          /* We need to serialize because this is bitfield operation. */
92            static DEFINE_SPINLOCK(lock);
93            /***** CRITICAL SECTION START *****/
94            spin_lock(&lock);
95          if (!is_delete)          if (!is_delete)
96                  domain->flags |= flags;                  domain->flags |= flags;
97          else          else
98                  domain->flags &= ~flags;                  domain->flags &= ~flags;
99          mutex_unlock(&new_domain_assign_lock);          spin_unlock(&lock);
100            /***** CRITICAL SECTION END *****/
101  }  }
102    
103  /**  /**
# Line 108  void ccs_set_domain_flag(struct domain_i Line 109  void ccs_set_domain_flag(struct domain_i
109   */   */
110  const char *ccs_get_last_name(const struct domain_info *domain)  const char *ccs_get_last_name(const struct domain_info *domain)
111  {  {
112          const char *cp0 = domain->domainname->name, *cp1 = strrchr(cp0, ' ');          const char *cp0 = domain->domainname->name;
113            const char *cp1 = strrchr(cp0, ' ');
114          if (cp1)          if (cp1)
115                  return cp1 + 1;                  return cp1 + 1;
116          return cp0;          return cp0;
# Line 117  const char *ccs_get_last_name(const stru Line 119  const char *ccs_get_last_name(const stru
119  /**  /**
120   * ccs_add_domain_acl - Add the given ACL to the given domain.   * ccs_add_domain_acl - Add the given ACL to the given domain.
121   *   *
122   * @domain: Pointer to "struct domain_info".   * @domain: Pointer to "struct domain_info". May be NULL.
123   * @acl:    Pointer to "struct acl_info".   * @acl:    Pointer to "struct acl_info".
124   *   *
125   * Returns 0.   * Returns 0.
126   */   */
127  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)
128  {  {
129          if (domain)          if (domain) {
130                    /*
131                     * We need to serialize because this function is called by
132                     * various update functions.
133                     */
134                    static DEFINE_SPINLOCK(lock);
135                    /***** CRITICAL SECTION START *****/
136                    spin_lock(&lock);
137                  list1_add_tail_mb(&acl->list, &domain->acl_info_list);                  list1_add_tail_mb(&acl->list, &domain->acl_info_list);
138          else                  spin_unlock(&lock);
139                    /***** CRITICAL SECTION END *****/
140            } else {
141                  acl->type &= ~ACL_DELETED;                  acl->type &= ~ACL_DELETED;
142            }
143          ccs_update_counter(CCS_UPDATES_COUNTER_DOMAIN_POLICY);          ccs_update_counter(CCS_UPDATES_COUNTER_DOMAIN_POLICY);
144          return 0;          return 0;
145  }  }
# Line 135  int ccs_add_domain_acl(struct domain_inf Line 147  int ccs_add_domain_acl(struct domain_inf
147  /**  /**
148   * ccs_del_domain_acl - Delete the given ACL from the domain.   * ccs_del_domain_acl - Delete the given ACL from the domain.
149   *   *
150   * @acl: Pointer to "struct acl_info".   * @acl: Pointer to "struct acl_info". May be NULL.
151   *   *
152   * Returns 0.   * Returns 0.
153   */   */
# Line 150  int ccs_del_domain_acl(struct acl_info * Line 162  int ccs_del_domain_acl(struct acl_info *
162  /**  /**
163   * audit_execute_handler_log - Audit execute_handler log.   * audit_execute_handler_log - Audit execute_handler log.
164   *   *
165   * @is_preferred: True if it is "preffered_execute_handler" log.   * @is_default: True if it is "execute_handler" log.
166   * @handler:      The realpath of the handler.   * @handler:    The realpath of the handler.
167   * @bprm:         Pointer to "struct linux_binprm".   * @bprm:       Pointer to "struct linux_binprm".
168   *   *
169   * Returns 0 on success, negative value otherwise.   * Returns 0 on success, negative value otherwise.
170   */   */
171  static int audit_execute_handler_log(const bool is_preferred,  static int audit_execute_handler_log(const bool is_default,
172                                       const char *handler,                                       const char *handler,
173                                       struct linux_binprm *bprm)                                       struct linux_binprm *bprm)
174  {  {
175          char *buf;          struct ccs_request_info r;
176          int len;          ccs_init_request_info(&r, NULL, CCS_TOMOYO_MAC_FOR_FILE);
177          int len2;          r.bprm = bprm;
178          u8 profile;          return ccs_write_audit_log(true, &r, "%s %s\n",
179          u8 mode;                                     is_default ? KEYWORD_EXECUTE_HANDLER :
180          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_preferred ?  
                  KEYWORD_PREFERRED_EXECUTE_HANDLER :  
                  KEYWORD_DEFAULT_EXECUTE_HANDLER,  
                  handler);  
         return ccs_write_audit_log(buf, true);  
181  }  }
182    
183  /**  /**
184   * audit_domain_creation_log - Audit domain creation log.   * audit_domain_creation_log - Audit domain creation log.
185   *   *
186   * @domainname: The name of newly created domain.   * @domain:  Pointer to "struct domain_info".
  * @mode:       Access control mode.  
  * @profile:    Profile number.  
187   *   *
188   * Returns 0 on success, negative value otherwise.   * Returns 0 on success, negative value otherwise.
189   */   */
190  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)  
191  {  {
192          char *buf;          struct ccs_request_info r;
193          char *cp;          ccs_init_request_info(&r, domain, CCS_TOMOYO_MAC_FOR_FILE);
194          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);  
195  }  }
196    
197  /* The list for "struct domain_initializer_entry". */  /* The list for "struct domain_initializer_entry". */
# Line 234  static int update_domain_initializer_ent Line 212  static int update_domain_initializer_ent
212                                             const bool is_not,                                             const bool is_not,
213                                             const bool is_delete)                                             const bool is_delete)
214  {  {
215          struct domain_initializer_entry *new_entry, *ptr;          struct domain_initializer_entry *new_entry;
216            struct domain_initializer_entry *ptr;
217          static DEFINE_MUTEX(lock);          static DEFINE_MUTEX(lock);
218          const struct path_info *saved_program, *saved_domainname = NULL;          const struct path_info *saved_program;
219            const struct path_info *saved_domainname = NULL;
220          int error = -ENOMEM;          int error = -ENOMEM;
221          bool is_last_name = false;          bool is_last_name = false;
222          if (!ccs_is_correct_path(program, 1, -1, -1, __func__))          if (!ccs_is_correct_path(program, 1, -1, -1, __func__))
# Line 279  static int update_domain_initializer_ent Line 259  static int update_domain_initializer_ent
259          error = 0;          error = 0;
260   out:   out:
261          mutex_unlock(&lock);          mutex_unlock(&lock);
262            ccs_update_counter(CCS_UPDATES_COUNTER_EXCEPTION_POLICY);
263          return error;          return error;
264  }  }
265    
# Line 293  bool ccs_read_domain_initializer_policy( Line 274  bool ccs_read_domain_initializer_policy(
274  {  {
275          struct list1_head *pos;          struct list1_head *pos;
276          list1_for_each_cookie(pos, head->read_var2, &domain_initializer_list) {          list1_for_each_cookie(pos, head->read_var2, &domain_initializer_list) {
277                    const char *no;
278                    const char *from = "";
279                    const char *domain = "";
280                  struct domain_initializer_entry *ptr;                  struct domain_initializer_entry *ptr;
281                  ptr = list1_entry(pos, struct domain_initializer_entry, list);                  ptr = list1_entry(pos, struct domain_initializer_entry, list);
282                  if (ptr->is_deleted)                  if (ptr->is_deleted)
283                          continue;                          continue;
284                    no = ptr->is_not ? "no_" : "";
285                  if (ptr->domainname) {                  if (ptr->domainname) {
286                          if (!ccs_io_printf(head, "%s" KEYWORD_INITIALIZE_DOMAIN                          from = " from ";
287                                             "%s from %s\n",                          domain = ptr->domainname->name;
                                            ptr->is_not ? "no_" : "",  
                                            ptr->program->name,  
                                            ptr->domainname->name))  
                                 goto out;  
                 } else {  
                         if (!ccs_io_printf(head, "%s"  
                                            KEYWORD_INITIALIZE_DOMAIN "%s\n",  
                                            ptr->is_not ? "no_" : "",  
                                            ptr->program->name))  
                                 goto out;  
288                  }                  }
289                    if (!ccs_io_printf(head,
290                                       "%s" KEYWORD_INITIALIZE_DOMAIN "%s%s%s\n",
291                                       no, ptr->program->name, from, domain))
292                                    goto out;
293          }          }
294          return true;          return true;
295   out:   out:
# Line 334  int ccs_write_domain_initializer_policy( Line 313  int ccs_write_domain_initializer_policy(
313                  *cp = '\0';                  *cp = '\0';
314                  return update_domain_initializer_entry(cp + 6, data, is_not,                  return update_domain_initializer_entry(cp + 6, data, is_not,
315                                                         is_delete);                                                         is_delete);
         } else {  
                 return update_domain_initializer_entry(NULL, data, is_not,  
                                                        is_delete);  
316          }          }
317            return update_domain_initializer_entry(NULL, data, is_not, is_delete);
318  }  }
319    
320  /**  /**
# Line 394  static int update_domain_keeper_entry(co Line 371  static int update_domain_keeper_entry(co
371                                        const char *program,                                        const char *program,
372                                        const bool is_not, const bool is_delete)                                        const bool is_not, const bool is_delete)
373  {  {
374          struct domain_keeper_entry *new_entry, *ptr;          struct domain_keeper_entry *new_entry;
375          const struct path_info *saved_domainname, *saved_program = NULL;          struct domain_keeper_entry *ptr;
376            const struct path_info *saved_domainname;
377            const struct path_info *saved_program = NULL;
378          static DEFINE_MUTEX(lock);          static DEFINE_MUTEX(lock);
379          int error = -ENOMEM;          int error = -ENOMEM;
380          bool is_last_name = false;          bool is_last_name = false;
# Line 439  static int update_domain_keeper_entry(co Line 418  static int update_domain_keeper_entry(co
418          error = 0;          error = 0;
419   out:   out:
420          mutex_unlock(&lock);          mutex_unlock(&lock);
421            ccs_update_counter(CCS_UPDATES_COUNTER_EXCEPTION_POLICY);
422          return error;          return error;
423  }  }
424    
# Line 458  int ccs_write_domain_keeper_policy(char Line 438  int ccs_write_domain_keeper_policy(char
438                  *cp = '\0';                  *cp = '\0';
439                  return update_domain_keeper_entry(cp + 6, data,                  return update_domain_keeper_entry(cp + 6, data,
440                                                    is_not, is_delete);                                                    is_not, is_delete);
         } else {  
                 return update_domain_keeper_entry(data, NULL,  
                                                   is_not, is_delete);  
441          }          }
442            return update_domain_keeper_entry(data, NULL, is_not, is_delete);
443  }  }
444    
445  /**  /**
# Line 476  bool ccs_read_domain_keeper_policy(struc Line 454  bool ccs_read_domain_keeper_policy(struc
454          struct list1_head *pos;          struct list1_head *pos;
455          list1_for_each_cookie(pos, head->read_var2, &domain_keeper_list) {          list1_for_each_cookie(pos, head->read_var2, &domain_keeper_list) {
456                  struct domain_keeper_entry *ptr;                  struct domain_keeper_entry *ptr;
457                  const char *is_not;                  const char *no;
458                    const char *from = "";
459                    const char *program = "";
460                  ptr = list1_entry(pos, struct domain_keeper_entry, list);                  ptr = list1_entry(pos, struct domain_keeper_entry, list);
461                  if (ptr->is_deleted)                  if (ptr->is_deleted)
462                          continue;                          continue;
463                  is_not = ptr->is_not ? "no_" : "";                  no = ptr->is_not ? "no_" : "";
464                  if (ptr->program) {                  if (ptr->program) {
465                          if (!ccs_io_printf(head,                          from = " from ";
466                                             "%s" KEYWORD_KEEP_DOMAIN "%s "                          program = ptr->program->name;
                                            "from %s\n",  
                                            is_not, ptr->program->name,  
                                            ptr->domainname->name))  
                                 goto out;  
                 } else {  
                         if (!ccs_io_printf(head,  
                                            "%s" KEYWORD_KEEP_DOMAIN "%s\n",  
                                            is_not, ptr->domainname->name))  
                                 goto out;  
467                  }                  }
468                    if (!ccs_io_printf(head,
469                                       "%s" KEYWORD_KEEP_DOMAIN "%s%s%s\n", no,
470                                       program, from, ptr->domainname->name))
471                                    goto out;
472          }          }
473          return true;          return true;
474   out:   out:
# Line 551  static int update_alias_entry(const char Line 526  static int update_alias_entry(const char
526                                const char *aliased_name,                                const char *aliased_name,
527                                const bool is_delete)                                const bool is_delete)
528  {  {
529          struct alias_entry *new_entry, *ptr;          struct alias_entry *new_entry;
530            struct alias_entry *ptr;
531          static DEFINE_MUTEX(lock);          static DEFINE_MUTEX(lock);
532          const struct path_info *saved_original_name, *saved_aliased_name;          const struct path_info *saved_original_name;
533            const struct path_info *saved_aliased_name;
534          int error = -ENOMEM;          int error = -ENOMEM;
535          if (!ccs_is_correct_path(original_name, 1, -1, -1, __func__) ||          if (!ccs_is_correct_path(original_name, 1, -1, -1, __func__) ||
536              !ccs_is_correct_path(aliased_name, 1, -1, -1, __func__))              !ccs_is_correct_path(aliased_name, 1, -1, -1, __func__))
# Line 584  static int update_alias_entry(const char Line 561  static int update_alias_entry(const char
561          error = 0;          error = 0;
562   out:   out:
563          mutex_unlock(&lock);          mutex_unlock(&lock);
564            ccs_update_counter(CCS_UPDATES_COUNTER_EXCEPTION_POLICY);
565          return error;          return error;
566  }  }
567    
# Line 645  static int update_aggregator_entry(const Line 623  static int update_aggregator_entry(const
623                                     const char *aggregated_name,                                     const char *aggregated_name,
624                                     const bool is_delete)                                     const bool is_delete)
625  {  {
626          struct aggregator_entry *new_entry, *ptr;          struct aggregator_entry *new_entry;
627            struct aggregator_entry *ptr;
628          static DEFINE_MUTEX(lock);          static DEFINE_MUTEX(lock);
629          const struct path_info *saved_original_name, *saved_aggregated_name;          const struct path_info *saved_original_name;
630            const struct path_info *saved_aggregated_name;
631          int error = -ENOMEM;          int error = -ENOMEM;
632          if (!ccs_is_correct_path(original_name, 1, 0, -1, __func__) ||          if (!ccs_is_correct_path(original_name, 1, 0, -1, __func__) ||
633              !ccs_is_correct_path(aggregated_name, 1, -1, -1, __func__))              !ccs_is_correct_path(aggregated_name, 1, -1, -1, __func__))
# Line 678  static int update_aggregator_entry(const Line 658  static int update_aggregator_entry(const
658          error = 0;          error = 0;
659   out:   out:
660          mutex_unlock(&lock);          mutex_unlock(&lock);
661            ccs_update_counter(CCS_UPDATES_COUNTER_EXCEPTION_POLICY);
662          return error;          return error;
663  }  }
664    
# Line 740  int ccs_delete_domain(char *domainname) Line 721  int ccs_delete_domain(char *domainname)
721          struct path_info name;          struct path_info name;
722          name.name = domainname;          name.name = domainname;
723          ccs_fill_path_info(&name);          ccs_fill_path_info(&name);
724          mutex_lock(&new_domain_assign_lock);          mutex_lock(&domain_list_lock);
725  #ifdef DEBUG_DOMAIN_UNDELETE  #ifdef DEBUG_DOMAIN_UNDELETE
726          printk(KERN_DEBUG "ccs_delete_domain %s\n", domainname);          printk(KERN_DEBUG "ccs_delete_domain %s\n", domainname);
727          list1_for_each_entry(domain, &domain_list, list) {          list1_for_each_entry(domain, &domain_list, list) {
# Line 778  int ccs_delete_domain(char *domainname) Line 759  int ccs_delete_domain(char *domainname)
759  #endif  #endif
760                  break;                  break;
761          }          }
762          mutex_unlock(&new_domain_assign_lock);          mutex_unlock(&domain_list_lock);
763          return 0;          return 0;
764  }  }
765    
# Line 791  int ccs_delete_domain(char *domainname) Line 772  int ccs_delete_domain(char *domainname)
772   */   */
773  struct domain_info *ccs_undelete_domain(const char *domainname)  struct domain_info *ccs_undelete_domain(const char *domainname)
774  {  {
775          struct domain_info *domain, *candidate_domain = NULL;          struct domain_info *domain;
776            struct domain_info *candidate_domain = NULL;
777          struct path_info name;          struct path_info name;
778          name.name = domainname;          name.name = domainname;
779          ccs_fill_path_info(&name);          ccs_fill_path_info(&name);
780          mutex_lock(&new_domain_assign_lock);          mutex_lock(&domain_list_lock);
781  #ifdef DEBUG_DOMAIN_UNDELETE  #ifdef DEBUG_DOMAIN_UNDELETE
782          printk(KERN_DEBUG "ccs_undelete_domain %s\n", domainname);          printk(KERN_DEBUG "ccs_undelete_domain %s\n", domainname);
783          list1_for_each_entry(domain, &domain_list, list) {          list1_for_each_entry(domain, &domain_list, list) {
# Line 826  struct domain_info *ccs_undelete_domain( Line 808  struct domain_info *ccs_undelete_domain(
808                  printk(KERN_DEBUG "%p was undeleted.\n", candidate_domain);                  printk(KERN_DEBUG "%p was undeleted.\n", candidate_domain);
809  #endif  #endif
810          }          }
811          mutex_unlock(&new_domain_assign_lock);          mutex_unlock(&domain_list_lock);
812          return candidate_domain;          return candidate_domain;
813  }  }
814    
# Line 843  struct domain_info *ccs_find_or_assign_n Line 825  struct domain_info *ccs_find_or_assign_n
825  {  {
826          struct domain_info *domain = NULL;          struct domain_info *domain = NULL;
827          const struct path_info *saved_domainname;          const struct path_info *saved_domainname;
828          mutex_lock(&new_domain_assign_lock);          mutex_lock(&domain_list_lock);
829          domain = ccs_find_domain(domainname);          domain = ccs_find_domain(domainname);
830          if (domain)          if (domain)
831                  goto out;                  goto out;
# Line 864  struct domain_info *ccs_find_or_assign_n Line 846  struct domain_info *ccs_find_or_assign_n
846                  /***** CRITICAL SECTION START *****/                  /***** CRITICAL SECTION START *****/
847                  read_lock(&tasklist_lock);                  read_lock(&tasklist_lock);
848                  for_each_process(p) {                  for_each_process(p) {
849                          if (p->domain_info == domain) {                          if (p->domain_info != domain)
850                                  flag = true;                                  continue;
851                                  break;                          flag = true;
852                          }                          break;
853                  }                  }
854                  read_unlock(&tasklist_lock);                  read_unlock(&tasklist_lock);
855                  /***** CRITICAL SECTION END *****/                  /***** CRITICAL SECTION END *****/
# Line 880  struct domain_info *ccs_find_or_assign_n Line 862  struct domain_info *ccs_find_or_assign_n
862                  list1_for_each_entry(ptr, &domain->acl_info_list, list) {                  list1_for_each_entry(ptr, &domain->acl_info_list, list) {
863                          ptr->type |= ACL_DELETED;                          ptr->type |= ACL_DELETED;
864                  }                  }
865                  /*                  ccs_set_domain_flag(domain, true, domain->flags);
                  * Don't use ccs_set_domain_flag() because  
                  * new_domain_assign_lock is held.  
                  */  
                 domain->flags = 0;  
866                  domain->profile = profile;                  domain->profile = profile;
867                  domain->quota_warned = false;                  domain->quota_warned = false;
868                  mb(); /* Avoid out-of-order execution. */                  mb(); /* Avoid out-of-order execution. */
# Line 900  struct domain_info *ccs_find_or_assign_n Line 878  struct domain_info *ccs_find_or_assign_n
878                  list1_add_tail_mb(&domain->list, &domain_list);                  list1_add_tail_mb(&domain->list, &domain_list);
879          }          }
880   out:   out:
881          mutex_unlock(&new_domain_assign_lock);          mutex_unlock(&domain_list_lock);
882          return domain;          return domain;
883  }  }
884    
# Line 983  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, s, l;  
991    
992          {          {
993                  /*                  /*
994                   * Built-in initializers. This is needed because policies are                   * Built-in initializers. This is needed because policies are
995                   * not loaded until starting /sbin/init .                   * not loaded until starting /sbin/init.
996                   */                   */
997                  static bool first = true;                  static bool first = true;
998                  if (first) {                  if (first) {
# Line 1026  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. */
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 1057  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 1086  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 1098  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 1140  static int find_next_domain(struct linux Line 1138  static int find_next_domain(struct linux
1138          if (domain)          if (domain)
1139                  goto done;                  goto done;
1140          if (is_enforce) {          if (is_enforce) {
1141                  if (ccs_check_supervisor("#Need to create domain\n%s\n",                  int error = ccs_check_supervisor(r,
1142                                           new_domain_name))                                                   "# 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          }          }
1152          domain = ccs_find_or_assign_new_domain(new_domain_name,          domain = ccs_find_or_assign_new_domain(new_domain_name, r->profile);
                                                old_domain->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 {
1162                            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;
1191          int i = pos / PAGE_SIZE, offset = pos % PAGE_SIZE;          int i = pos / PAGE_SIZE;
1192            int offset = pos % PAGE_SIZE;
1193          int argv_count = bprm->argc;          int argv_count = bprm->argc;
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 1235  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 1255  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 1270  static int check_environ(struct linux_bi Line 1279  static int check_environ(struct linux_bi
1279  static void unescape(unsigned char *dest)  static void unescape(unsigned char *dest)
1280  {  {
1281          unsigned char *src = dest;          unsigned char *src = dest;
1282          unsigned char c, d, e;          unsigned char c;
1283            unsigned char d;
1284            unsigned char e;
1285          while ((c = *src++) != '\0') {          while ((c = *src++) != '\0') {
1286                  if (c != '\\') {                  if (c != '\\') {
1287                          *dest++ = c;                          *dest++ = c;
# Line 1306  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 1322  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 1369  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.
1388           * The envp[] in original bprm is moved to argv[] so that           * The envp[] in original bprm is moved to argv[] so that
1389           * the alternatively executed program won't be affected by           * the alternatively executed program won't be affected by
1390           * some dangerous environment variables like LD_PRELOAD .           * some dangerous environment variables like LD_PRELOAD.
1391           *           *
1392           * modified bprm->argc           * modified bprm->argc
1393           *    = original bprm->argc + original bprm->envc + 7           *    = original bprm->argc + original bprm->envc + 7
# Line 1418  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 1555  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 1570  static int try_alt_exec(struct linux_bin Line 1572  static int try_alt_exec(struct linux_bin
1572   */   */
1573  static const struct path_info *find_execute_handler(const u8 type)  static const struct path_info *find_execute_handler(const u8 type)
1574  {  {
1575          const struct domain_info *domain = current->domain_info;          struct task_struct *task = current;
1576            const struct domain_info *domain = task->domain_info;
1577          struct acl_info *ptr;          struct acl_info *ptr;
1578            /*
1579             * Don't use execute handler if the current process is
1580             * marked as execute handler to avoid infinite execute handler loop.
1581             */
1582            if (task->tomoyo_flags & TOMOYO_TASK_IS_EXECUTE_HANDLER)
1583                    return NULL;
1584          list1_for_each_entry(ptr, &domain->acl_info_list, list) {          list1_for_each_entry(ptr, &domain->acl_info_list, list) {
1585                  struct execute_handler_record *acl;                  struct execute_handler_record *acl;
1586                  if ((ptr->type & ~ACL_DELETED) != type)                  if (ptr->type != type)
1587                          continue;                          continue;
1588                  acl = container_of(ptr, struct execute_handler_record, head);                  acl = container_of(ptr, struct execute_handler_record, head);
1589                  return acl->handler;                  return acl->handler;
# Line 1582  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 1594  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          handler = find_execute_handler(TYPE_PREFERRED_EXECUTE_HANDLER);          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);
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_DEFAULT_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;                  goto out;
1729          task->domain_info = next_domain;          r.mode = ccs_check_flags(r.domain, CCS_TOMOYO_MAC_FOR_ENV);
1730          retval = check_environ(bprm, buf);          retval = check_environ(&r);
1731          if (retval)          if (retval < 0)
1732                    goto out;
1733            retval = ccs_register_next_domain(r.domain);
1734            if (retval < 0)
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:  
1739          if (retval < 0)          if (retval < 0)
1740                  task->domain_info = prev_domain;                  goto out;
1741          ccs_free(work);          /* Proceed to next domain if execution suceeded. */
1742          ccs_free(buf);          task->domain_info = r.domain;
1743            mb(); /* Make domain transition visible to other CPUs. */
1744            /* Mark the current process as execute handler. */
1745            if (handler)
1746                    task->tomoyo_flags |= TOMOYO_TASK_IS_EXECUTE_HANDLER;
1747            /* Mark the current process as normal process. */
1748            else
1749                    task->tomoyo_flags &= ~TOMOYO_TASK_IS_EXECUTE_HANDLER;
1750     out:
1751            ccs_unregister_next_domain();
1752            ccs_free(eh_path);
1753            ccs_free(tmp);
1754          return retval;          return retval;
1755  }  }
1756    
# Line 1657  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.1056  
changed lines
  Added in v.1700

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