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

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 1561 by kumaneko, Tue Sep 9 04:29:07 2008 UTC revision 2019 by kumaneko, Fri Dec 26 02:07:44 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.5-pre   2008/09/09   * Version: 1.6.6-pre   2008/12/24
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 33  Line 33 
33  struct domain_info KERNEL_DOMAIN;  struct domain_info KERNEL_DOMAIN;
34    
35  /* The list for "struct domain_info". */  /* The list for "struct domain_info". */
36  LIST1_HEAD(domain_list);  LIST1_HEAD(ccs_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(ccs_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 ccs_domain_initializer_entry {
45          struct list1_head list;          struct list1_head list;
46          const struct path_info *domainname;    /* This may be NULL */          const struct ccs_path_info *domainname;    /* This may be NULL */
47          const struct path_info *program;          const struct ccs_path_info *program;
48          bool is_deleted;          bool is_deleted;
49          bool is_not;       /* True if this entry is "no_initialize_domain".  */          bool is_not;       /* True if this entry is "no_initialize_domain".  */
50          bool is_last_name; /* True if the domainname is ccs_get_last_name(). */          bool is_last_name; /* True if the domainname is ccs_get_last_name(). */
51  };  };
52    
53  /* Structure for "keep_domain" and "no_keep_domain" keyword. */  /* Structure for "keep_domain" and "no_keep_domain" keyword. */
54  struct domain_keeper_entry {  struct ccs_domain_keeper_entry {
55          struct list1_head list;          struct list1_head list;
56          const struct path_info *domainname;          const struct ccs_path_info *domainname;
57          const struct path_info *program;       /* This may be NULL */          const struct ccs_path_info *program;       /* This may be NULL */
58          bool is_deleted;          bool is_deleted;
59          bool is_not;       /* True if this entry is "no_keep_domain".        */          bool is_not;       /* True if this entry is "no_keep_domain".        */
60          bool is_last_name; /* True if the domainname is ccs_get_last_name(). */          bool is_last_name; /* True if the domainname is ccs_get_last_name(). */
61  };  };
62    
63  /* Structure for "aggregator" keyword. */  /* Structure for "aggregator" keyword. */
64  struct aggregator_entry {  struct ccs_aggregator_entry {
65          struct list1_head list;          struct list1_head list;
66          const struct path_info *original_name;          const struct ccs_path_info *original_name;
67          const struct path_info *aggregated_name;          const struct ccs_path_info *aggregated_name;
68          bool is_deleted;          bool is_deleted;
69  };  };
70    
71  /* Structure for "alias" keyword. */  /* Structure for "alias" keyword. */
72  struct alias_entry {  struct ccs_alias_entry {
73          struct list1_head list;          struct list1_head list;
74          const struct path_info *original_name;          const struct ccs_path_info *original_name;
75          const struct path_info *aliased_name;          const struct ccs_path_info *aliased_name;
76          bool is_deleted;          bool is_deleted;
77  };  };
78    
# 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 118  const char *ccs_get_last_name(const stru Line 120  const char *ccs_get_last_name(const stru
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". May be NULL.   * @domain: Pointer to "struct domain_info". May be NULL.
123   * @acl:    Pointer to "struct acl_info".   * @acl:    Pointer to "struct ccs_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 ccs_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". May be NULL.   * @acl: Pointer to "struct ccs_acl_info". May be NULL.
151   *   *
152   * Returns 0.   * Returns 0.
153   */   */
154  int ccs_del_domain_acl(struct acl_info *acl)  int ccs_del_domain_acl(struct ccs_acl_info *acl)
155  {  {
156          if (acl)          if (acl)
157                  acl->type |= ACL_DELETED;                  acl->type |= ACL_DELETED;
# Line 148  int ccs_del_domain_acl(struct acl_info * Line 160  int ccs_del_domain_acl(struct acl_info *
160  }  }
161    
162  /**  /**
163   * audit_execute_handler_log - Audit execute_handler log.   * ccs_audit_execute_handler_log - Audit execute_handler log.
164   *   *
165   * @is_default: True if it is "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.
# Line 156  int ccs_del_domain_acl(struct acl_info * Line 168  int ccs_del_domain_acl(struct acl_info *
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_default,  static int ccs_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_default ? KEYWORD_EXECUTE_HANDLER :  
                  KEYWORD_DENIED_EXECUTE_HANDLER, handler);  
         return ccs_write_audit_log(buf, true);  
181  }  }
182    
183  /**  /**
184   * audit_domain_creation_log - Audit domain creation log.   * ccs_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 used.  
  * @profile:    Profile number used.  
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 ccs_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 ccs_domain_initializer_entry". */
198  static LIST1_HEAD(domain_initializer_list);  static LIST1_HEAD(ccs_domain_initializer_list);
199    
200  /**  /**
201   * update_domain_initializer_entry - Update "struct domain_initializer_entry" list.   * ccs_update_domain_initializer_entry - Update "struct ccs_domain_initializer_entry" list.
202   *   *
203   * @domainname: The name of domain. May be NULL.   * @domainname: The name of domain. May be NULL.
204   * @program:    The name of program.   * @program:    The name of program.
# Line 227  static LIST1_HEAD(domain_initializer_lis Line 207  static LIST1_HEAD(domain_initializer_lis
207   *   *
208   * Returns 0 on success, negative value otherwise.   * Returns 0 on success, negative value otherwise.
209   */   */
210  static int update_domain_initializer_entry(const char *domainname,  static int ccs_update_domain_initializer_entry(const char *domainname,
211                                             const char *program,                                                 const char *program,
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;          struct ccs_domain_initializer_entry *new_entry;
216          struct domain_initializer_entry *ptr;          struct ccs_domain_initializer_entry *ptr;
217          static DEFINE_MUTEX(lock);          static DEFINE_MUTEX(lock);
218          const struct path_info *saved_program;          const struct ccs_path_info *saved_program;
219          const struct path_info *saved_domainname = NULL;          const struct ccs_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 255  static int update_domain_initializer_ent Line 235  static int update_domain_initializer_ent
235          if (!saved_program)          if (!saved_program)
236                  return -ENOMEM;                  return -ENOMEM;
237          mutex_lock(&lock);          mutex_lock(&lock);
238          list1_for_each_entry(ptr, &domain_initializer_list, list) {          list1_for_each_entry(ptr, &ccs_domain_initializer_list, list) {
239                  if (ptr->is_not != is_not ||                  if (ptr->is_not != is_not ||
240                      ptr->domainname != saved_domainname ||                      ptr->domainname != saved_domainname ||
241                      ptr->program != saved_program)                      ptr->program != saved_program)
# Line 275  static int update_domain_initializer_ent Line 255  static int update_domain_initializer_ent
255          new_entry->program = saved_program;          new_entry->program = saved_program;
256          new_entry->is_not = is_not;          new_entry->is_not = is_not;
257          new_entry->is_last_name = is_last_name;          new_entry->is_last_name = is_last_name;
258          list1_add_tail_mb(&new_entry->list, &domain_initializer_list);          list1_add_tail_mb(&new_entry->list, &ccs_domain_initializer_list);
259          error = 0;          error = 0;
260   out:   out:
261          mutex_unlock(&lock);          mutex_unlock(&lock);
# Line 284  static int update_domain_initializer_ent Line 264  static int update_domain_initializer_ent
264  }  }
265    
266  /**  /**
267   * ccs_read_domain_initializer_policy - Read "struct domain_initializer_entry" list.   * ccs_read_domain_initializer_policy - Read "struct ccs_domain_initializer_entry" list.
268   *   *
269   * @head: Pointer to "struct ccs_io_buffer".   * @head: Pointer to "struct ccs_io_buffer".
270   *   *
# Line 293  static int update_domain_initializer_ent Line 273  static int update_domain_initializer_ent
273  bool ccs_read_domain_initializer_policy(struct ccs_io_buffer *head)  bool ccs_read_domain_initializer_policy(struct ccs_io_buffer *head)
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,
277                                  &ccs_domain_initializer_list) {
278                  const char *no;                  const char *no;
279                  const char *from = "";                  const char *from = "";
280                  const char *domain = "";                  const char *domain = "";
281                  struct domain_initializer_entry *ptr;                  struct ccs_domain_initializer_entry *ptr;
282                  ptr = list1_entry(pos, struct domain_initializer_entry, list);                  ptr = list1_entry(pos, struct ccs_domain_initializer_entry,
283                                      list);
284                  if (ptr->is_deleted)                  if (ptr->is_deleted)
285                          continue;                          continue;
286                  no = ptr->is_not ? "no_" : "";                  no = ptr->is_not ? "no_" : "";
# Line 309  bool ccs_read_domain_initializer_policy( Line 291  bool ccs_read_domain_initializer_policy(
291                  if (!ccs_io_printf(head,                  if (!ccs_io_printf(head,
292                                     "%s" KEYWORD_INITIALIZE_DOMAIN "%s%s%s\n",                                     "%s" KEYWORD_INITIALIZE_DOMAIN "%s%s%s\n",
293                                     no, ptr->program->name, from, domain))                                     no, ptr->program->name, from, domain))
294                                  goto out;                          goto out;
295          }          }
296          return true;          return true;
297   out:   out:
# Line 317  bool ccs_read_domain_initializer_policy( Line 299  bool ccs_read_domain_initializer_policy(
299  }  }
300    
301  /**  /**
302   * ccs_write_domain_initializer_policy - Write "struct domain_initializer_entry" list.   * ccs_write_domain_initializer_policy - Write "struct ccs_domain_initializer_entry" list.
303   *   *
304   * @data:      String to parse.   * @data:      String to parse.
305   * @is_not:    True if it is "no_initialize_domain" entry.   * @is_not:    True if it is "no_initialize_domain" entry.
# Line 331  int ccs_write_domain_initializer_policy( Line 313  int ccs_write_domain_initializer_policy(
313          char *cp = strstr(data, " from ");          char *cp = strstr(data, " from ");
314          if (cp) {          if (cp) {
315                  *cp = '\0';                  *cp = '\0';
316                  return update_domain_initializer_entry(cp + 6, data, is_not,                  return ccs_update_domain_initializer_entry(cp + 6, data,
317                                                         is_delete);                                                             is_not, is_delete);
318          }          }
319          return update_domain_initializer_entry(NULL, data, is_not, is_delete);          return ccs_update_domain_initializer_entry(NULL, data, is_not,
320                                                       is_delete);
321  }  }
322    
323  /**  /**
324   * is_domain_initializer - Check whether the given program causes domainname reinitialization.   * ccs_is_domain_initializer - Check whether the given program causes domainname reinitialization.
325   *   *
326   * @domainname: The name of domain.   * @domainname: The name of domain.
327   * @program:    The name of program.   * @program:    The name of program.
# Line 347  int ccs_write_domain_initializer_policy( Line 330  int ccs_write_domain_initializer_policy(
330   * Returns true if executing @program reinitializes domain transition,   * Returns true if executing @program reinitializes domain transition,
331   * false otherwise.   * false otherwise.
332   */   */
333  static bool is_domain_initializer(const struct path_info *domainname,  static bool ccs_is_domain_initializer(const struct ccs_path_info *domainname,
334                                    const struct path_info *program,                                        const struct ccs_path_info *program,
335                                    const struct path_info *last_name)                                        const struct ccs_path_info *last_name)
336  {  {
337          struct domain_initializer_entry *ptr;          struct ccs_domain_initializer_entry *ptr;
338          bool flag = false;          bool flag = false;
339          list1_for_each_entry(ptr,  &domain_initializer_list, list) {          list1_for_each_entry(ptr, &ccs_domain_initializer_list, list) {
340                  if (ptr->is_deleted)                  if (ptr->is_deleted)
341                          continue;                          continue;
342                  if (ptr->domainname) {                  if (ptr->domainname) {
# Line 374  static bool is_domain_initializer(const Line 357  static bool is_domain_initializer(const
357          return flag;          return flag;
358  }  }
359    
360  /* The list for "struct domain_keeper_entry". */  /* The list for "struct ccs_domain_keeper_entry". */
361  static LIST1_HEAD(domain_keeper_list);  static LIST1_HEAD(ccs_domain_keeper_list);
362    
363  /**  /**
364   * update_domain_keeper_entry - Update "struct domain_keeper_entry" list.   * ccs_update_domain_keeper_entry - Update "struct ccs_domain_keeper_entry" list.
365   *   *
366   * @domainname: The name of domain.   * @domainname: The name of domain.
367   * @program:    The name of program. May be NULL.   * @program:    The name of program. May be NULL.
# Line 387  static LIST1_HEAD(domain_keeper_list); Line 370  static LIST1_HEAD(domain_keeper_list);
370   *   *
371   * Returns 0 on success, negative value otherwise.   * Returns 0 on success, negative value otherwise.
372   */   */
373  static int update_domain_keeper_entry(const char *domainname,  static int ccs_update_domain_keeper_entry(const char *domainname,
374                                        const char *program,                                            const char *program,
375                                        const bool is_not, const bool is_delete)                                            const bool is_not,
376  {                                            const bool is_delete)
377          struct domain_keeper_entry *new_entry;  {
378          struct domain_keeper_entry *ptr;          struct ccs_domain_keeper_entry *new_entry;
379          const struct path_info *saved_domainname;          struct ccs_domain_keeper_entry *ptr;
380          const struct path_info *saved_program = NULL;          const struct ccs_path_info *saved_domainname;
381            const struct ccs_path_info *saved_program = NULL;
382          static DEFINE_MUTEX(lock);          static DEFINE_MUTEX(lock);
383          int error = -ENOMEM;          int error = -ENOMEM;
384          bool is_last_name = false;          bool is_last_name = false;
# Line 414  static int update_domain_keeper_entry(co Line 398  static int update_domain_keeper_entry(co
398          if (!saved_domainname)          if (!saved_domainname)
399                  return -ENOMEM;                  return -ENOMEM;
400          mutex_lock(&lock);          mutex_lock(&lock);
401          list1_for_each_entry(ptr, &domain_keeper_list, list) {          list1_for_each_entry(ptr, &ccs_domain_keeper_list, list) {
402                  if (ptr->is_not != is_not ||                  if (ptr->is_not != is_not ||
403                      ptr->domainname != saved_domainname ||                      ptr->domainname != saved_domainname ||
404                      ptr->program != saved_program)                      ptr->program != saved_program)
# Line 434  static int update_domain_keeper_entry(co Line 418  static int update_domain_keeper_entry(co
418          new_entry->program = saved_program;          new_entry->program = saved_program;
419          new_entry->is_not = is_not;          new_entry->is_not = is_not;
420          new_entry->is_last_name = is_last_name;          new_entry->is_last_name = is_last_name;
421          list1_add_tail_mb(&new_entry->list, &domain_keeper_list);          list1_add_tail_mb(&new_entry->list, &ccs_domain_keeper_list);
422          error = 0;          error = 0;
423   out:   out:
424          mutex_unlock(&lock);          mutex_unlock(&lock);
# Line 443  static int update_domain_keeper_entry(co Line 427  static int update_domain_keeper_entry(co
427  }  }
428    
429  /**  /**
430   * ccs_write_domain_keeper_policy - Write "struct domain_keeper_entry" list.   * ccs_write_domain_keeper_policy - Write "struct ccs_domain_keeper_entry" list.
431   *   *
432   * @data:      String to parse.   * @data:      String to parse.
433   * @is_not:    True if it is "no_keep_domain" entry.   * @is_not:    True if it is "no_keep_domain" entry.
# Line 456  int ccs_write_domain_keeper_policy(char Line 440  int ccs_write_domain_keeper_policy(char
440          char *cp = strstr(data, " from ");          char *cp = strstr(data, " from ");
441          if (cp) {          if (cp) {
442                  *cp = '\0';                  *cp = '\0';
443                  return update_domain_keeper_entry(cp + 6, data,                  return ccs_update_domain_keeper_entry(cp + 6, data,
444                                                    is_not, is_delete);                                                        is_not, is_delete);
445          }          }
446          return update_domain_keeper_entry(data, NULL, is_not, is_delete);          return ccs_update_domain_keeper_entry(data, NULL, is_not, is_delete);
447  }  }
448    
449  /**  /**
450   * ccs_read_domain_keeper_policy - Read "struct domain_keeper_entry" list.   * ccs_read_domain_keeper_policy - Read "struct ccs_domain_keeper_entry" list.
451   *   *
452   * @head: Pointer to "struct ccs_io_buffer".   * @head: Pointer to "struct ccs_io_buffer".
453   *   *
# Line 472  int ccs_write_domain_keeper_policy(char Line 456  int ccs_write_domain_keeper_policy(char
456  bool ccs_read_domain_keeper_policy(struct ccs_io_buffer *head)  bool ccs_read_domain_keeper_policy(struct ccs_io_buffer *head)
457  {  {
458          struct list1_head *pos;          struct list1_head *pos;
459          list1_for_each_cookie(pos, head->read_var2, &domain_keeper_list) {          list1_for_each_cookie(pos, head->read_var2, &ccs_domain_keeper_list) {
460                  struct domain_keeper_entry *ptr;                  struct ccs_domain_keeper_entry *ptr;
461                  const char *no;                  const char *no;
462                  const char *from = "";                  const char *from = "";
463                  const char *program = "";                  const char *program = "";
464                  ptr = list1_entry(pos, struct domain_keeper_entry, list);                  ptr = list1_entry(pos, struct ccs_domain_keeper_entry, list);
465                  if (ptr->is_deleted)                  if (ptr->is_deleted)
466                          continue;                          continue;
467                  no = ptr->is_not ? "no_" : "";                  no = ptr->is_not ? "no_" : "";
# Line 488  bool ccs_read_domain_keeper_policy(struc Line 472  bool ccs_read_domain_keeper_policy(struc
472                  if (!ccs_io_printf(head,                  if (!ccs_io_printf(head,
473                                     "%s" KEYWORD_KEEP_DOMAIN "%s%s%s\n", no,                                     "%s" KEYWORD_KEEP_DOMAIN "%s%s%s\n", no,
474                                     program, from, ptr->domainname->name))                                     program, from, ptr->domainname->name))
475                                  goto out;                          goto out;
476          }          }
477          return true;          return true;
478   out:   out:
# Line 496  bool ccs_read_domain_keeper_policy(struc Line 480  bool ccs_read_domain_keeper_policy(struc
480  }  }
481    
482  /**  /**
483   * is_domain_keeper - Check whether the given program causes domain transition suppression.   * ccs_is_domain_keeper - Check whether the given program causes domain transition suppression.
484   *   *
485   * @domainname: The name of domain.   * @domainname: The name of domain.
486   * @program:    The name of program.   * @program:    The name of program.
# Line 505  bool ccs_read_domain_keeper_policy(struc Line 489  bool ccs_read_domain_keeper_policy(struc
489   * Returns true if executing @program supresses domain transition,   * Returns true if executing @program supresses domain transition,
490   * false otherwise.   * false otherwise.
491   */   */
492  static bool is_domain_keeper(const struct path_info *domainname,  static bool ccs_is_domain_keeper(const struct ccs_path_info *domainname,
493                               const struct path_info *program,                                   const struct ccs_path_info *program,
494                               const struct path_info *last_name)                                   const struct ccs_path_info *last_name)
495  {  {
496          struct domain_keeper_entry *ptr;          struct ccs_domain_keeper_entry *ptr;
497          bool flag = false;          bool flag = false;
498          list1_for_each_entry(ptr, &domain_keeper_list, list) {          list1_for_each_entry(ptr, &ccs_domain_keeper_list, list) {
499                  if (ptr->is_deleted)                  if (ptr->is_deleted)
500                          continue;                          continue;
501                  if (!ptr->is_last_name) {                  if (!ptr->is_last_name) {
# Line 530  static bool is_domain_keeper(const struc Line 514  static bool is_domain_keeper(const struc
514          return flag;          return flag;
515  }  }
516    
517  /* The list for "struct alias_entry". */  /* The list for "struct ccs_alias_entry". */
518  static LIST1_HEAD(alias_list);  static LIST1_HEAD(ccs_alias_list);
519    
520  /**  /**
521   * update_alias_entry - Update "struct alias_entry" list.   * ccs_update_alias_entry - Update "struct ccs_alias_entry" list.
522   *   *
523   * @original_name: The original program's real name.   * @original_name: The original program's real name.
524   * @aliased_name:  The symbolic program's symbolic link's name.   * @aliased_name:  The symbolic program's symbolic link's name.
# Line 542  static LIST1_HEAD(alias_list); Line 526  static LIST1_HEAD(alias_list);
526   *   *
527   * Returns 0 on success, negative value otherwise.   * Returns 0 on success, negative value otherwise.
528   */   */
529  static int update_alias_entry(const char *original_name,  static int ccs_update_alias_entry(const char *original_name,
530                                const char *aliased_name,                                    const char *aliased_name,
531                                const bool is_delete)                                    const bool is_delete)
532  {  {
533          struct alias_entry *new_entry;          struct ccs_alias_entry *new_entry;
534          struct alias_entry *ptr;          struct ccs_alias_entry *ptr;
535          static DEFINE_MUTEX(lock);          static DEFINE_MUTEX(lock);
536          const struct path_info *saved_original_name;          const struct ccs_path_info *saved_original_name;
537          const struct path_info *saved_aliased_name;          const struct ccs_path_info *saved_aliased_name;
538          int error = -ENOMEM;          int error = -ENOMEM;
539          if (!ccs_is_correct_path(original_name, 1, -1, -1, __func__) ||          if (!ccs_is_correct_path(original_name, 1, -1, -1, __func__) ||
540              !ccs_is_correct_path(aliased_name, 1, -1, -1, __func__))              !ccs_is_correct_path(aliased_name, 1, -1, -1, __func__))
# Line 560  static int update_alias_entry(const char Line 544  static int update_alias_entry(const char
544          if (!saved_original_name || !saved_aliased_name)          if (!saved_original_name || !saved_aliased_name)
545                  return -ENOMEM;                  return -ENOMEM;
546          mutex_lock(&lock);          mutex_lock(&lock);
547          list1_for_each_entry(ptr, &alias_list, list) {          list1_for_each_entry(ptr, &ccs_alias_list, list) {
548                  if (ptr->original_name != saved_original_name ||                  if (ptr->original_name != saved_original_name ||
549                      ptr->aliased_name != saved_aliased_name)                      ptr->aliased_name != saved_aliased_name)
550                          continue;                          continue;
# Line 577  static int update_alias_entry(const char Line 561  static int update_alias_entry(const char
561                  goto out;                  goto out;
562          new_entry->original_name = saved_original_name;          new_entry->original_name = saved_original_name;
563          new_entry->aliased_name = saved_aliased_name;          new_entry->aliased_name = saved_aliased_name;
564          list1_add_tail_mb(&new_entry->list, &alias_list);          list1_add_tail_mb(&new_entry->list, &ccs_alias_list);
565          error = 0;          error = 0;
566   out:   out:
567          mutex_unlock(&lock);          mutex_unlock(&lock);
# Line 586  static int update_alias_entry(const char Line 570  static int update_alias_entry(const char
570  }  }
571    
572  /**  /**
573   * ccs_read_alias_policy - Read "struct alias_entry" list.   * ccs_read_alias_policy - Read "struct ccs_alias_entry" list.
574   *   *
575   * @head: Pointer to "struct ccs_io_buffer".   * @head: Pointer to "struct ccs_io_buffer".
576   *   *
# Line 595  static int update_alias_entry(const char Line 579  static int update_alias_entry(const char
579  bool ccs_read_alias_policy(struct ccs_io_buffer *head)  bool ccs_read_alias_policy(struct ccs_io_buffer *head)
580  {  {
581          struct list1_head *pos;          struct list1_head *pos;
582          list1_for_each_cookie(pos, head->read_var2, &alias_list) {          list1_for_each_cookie(pos, head->read_var2, &ccs_alias_list) {
583                  struct alias_entry *ptr;                  struct ccs_alias_entry *ptr;
584                  ptr = list1_entry(pos, struct alias_entry, list);                  ptr = list1_entry(pos, struct ccs_alias_entry, list);
585                  if (ptr->is_deleted)                  if (ptr->is_deleted)
586                          continue;                          continue;
587                  if (!ccs_io_printf(head, KEYWORD_ALIAS "%s %s\n",                  if (!ccs_io_printf(head, KEYWORD_ALIAS "%s %s\n",
# Line 611  bool ccs_read_alias_policy(struct ccs_io Line 595  bool ccs_read_alias_policy(struct ccs_io
595  }  }
596    
597  /**  /**
598   * ccs_write_alias_policy - Write "struct alias_entry" list.   * ccs_write_alias_policy - Write "struct ccs_alias_entry" list.
599   *   *
600   * @data:      String to parse.   * @data:      String to parse.
601   * @is_delete: True if it is a delete request.   * @is_delete: True if it is a delete request.
# Line 624  int ccs_write_alias_policy(char *data, c Line 608  int ccs_write_alias_policy(char *data, c
608          if (!cp)          if (!cp)
609                  return -EINVAL;                  return -EINVAL;
610          *cp++ = '\0';          *cp++ = '\0';
611          return update_alias_entry(data, cp, is_delete);          return ccs_update_alias_entry(data, cp, is_delete);
612  }  }
613    
614  /* The list for "struct aggregator_entry". */  /* The list for "struct ccs_aggregator_entry". */
615  static LIST1_HEAD(aggregator_list);  static LIST1_HEAD(ccs_aggregator_list);
616    
617  /**  /**
618   * update_aggregator_entry - Update "struct aggregator_entry" list.   * ccs_update_aggregator_entry - Update "struct ccs_aggregator_entry" list.
619   *   *
620   * @original_name:   The original program's name.   * @original_name:   The original program's name.
621   * @aggregated_name: The aggregated program's name.   * @aggregated_name: The aggregated program's name.
# Line 639  static LIST1_HEAD(aggregator_list); Line 623  static LIST1_HEAD(aggregator_list);
623   *   *
624   * Returns 0 on success, negative value otherwise.   * Returns 0 on success, negative value otherwise.
625   */   */
626  static int update_aggregator_entry(const char *original_name,  static int ccs_update_aggregator_entry(const char *original_name,
627                                     const char *aggregated_name,                                         const char *aggregated_name,
628                                     const bool is_delete)                                         const bool is_delete)
629  {  {
630          struct aggregator_entry *new_entry;          struct ccs_aggregator_entry *new_entry;
631          struct aggregator_entry *ptr;          struct ccs_aggregator_entry *ptr;
632          static DEFINE_MUTEX(lock);          static DEFINE_MUTEX(lock);
633          const struct path_info *saved_original_name;          const struct ccs_path_info *saved_original_name;
634          const struct path_info *saved_aggregated_name;          const struct ccs_path_info *saved_aggregated_name;
635          int error = -ENOMEM;          int error = -ENOMEM;
636          if (!ccs_is_correct_path(original_name, 1, 0, -1, __func__) ||          if (!ccs_is_correct_path(original_name, 1, 0, -1, __func__) ||
637              !ccs_is_correct_path(aggregated_name, 1, -1, -1, __func__))              !ccs_is_correct_path(aggregated_name, 1, -1, -1, __func__))
# Line 657  static int update_aggregator_entry(const Line 641  static int update_aggregator_entry(const
641          if (!saved_original_name || !saved_aggregated_name)          if (!saved_original_name || !saved_aggregated_name)
642                  return -ENOMEM;                  return -ENOMEM;
643          mutex_lock(&lock);          mutex_lock(&lock);
644          list1_for_each_entry(ptr, &aggregator_list, list) {          list1_for_each_entry(ptr, &ccs_aggregator_list, list) {
645                  if (ptr->original_name != saved_original_name ||                  if (ptr->original_name != saved_original_name ||
646                      ptr->aggregated_name != saved_aggregated_name)                      ptr->aggregated_name != saved_aggregated_name)
647                          continue;                          continue;
# Line 674  static int update_aggregator_entry(const Line 658  static int update_aggregator_entry(const
658                  goto out;                  goto out;
659          new_entry->original_name = saved_original_name;          new_entry->original_name = saved_original_name;
660          new_entry->aggregated_name = saved_aggregated_name;          new_entry->aggregated_name = saved_aggregated_name;
661          list1_add_tail_mb(&new_entry->list, &aggregator_list);          list1_add_tail_mb(&new_entry->list, &ccs_aggregator_list);
662          error = 0;          error = 0;
663   out:   out:
664          mutex_unlock(&lock);          mutex_unlock(&lock);
# Line 683  static int update_aggregator_entry(const Line 667  static int update_aggregator_entry(const
667  }  }
668    
669  /**  /**
670   * ccs_read_aggregator_policy - Read "struct aggregator_entry" list.   * ccs_read_aggregator_policy - Read "struct ccs_aggregator_entry" list.
671   *   *
672   * @head: Pointer to "struct ccs_io_buffer".   * @head: Pointer to "struct ccs_io_buffer".
673   *   *
# Line 692  static int update_aggregator_entry(const Line 676  static int update_aggregator_entry(const
676  bool ccs_read_aggregator_policy(struct ccs_io_buffer *head)  bool ccs_read_aggregator_policy(struct ccs_io_buffer *head)
677  {  {
678          struct list1_head *pos;          struct list1_head *pos;
679          list1_for_each_cookie(pos, head->read_var2, &aggregator_list) {          list1_for_each_cookie(pos, head->read_var2, &ccs_aggregator_list) {
680                  struct aggregator_entry *ptr;                  struct ccs_aggregator_entry *ptr;
681                  ptr = list1_entry(pos, struct aggregator_entry, list);                  ptr = list1_entry(pos, struct ccs_aggregator_entry, list);
682                  if (ptr->is_deleted)                  if (ptr->is_deleted)
683                          continue;                          continue;
684                  if (!ccs_io_printf(head, KEYWORD_AGGREGATOR "%s %s\n",                  if (!ccs_io_printf(head, KEYWORD_AGGREGATOR "%s %s\n",
# Line 708  bool ccs_read_aggregator_policy(struct c Line 692  bool ccs_read_aggregator_policy(struct c
692  }  }
693    
694  /**  /**
695   * ccs_write_aggregator_policy - Write "struct aggregator_entry" list.   * ccs_write_aggregator_policy - Write "struct ccs_aggregator_entry" list.
696   *   *
697   * @data:      String to parse.   * @data:      String to parse.
698   * @is_delete: True if it is a delete request.   * @is_delete: True if it is a delete request.
# Line 721  int ccs_write_aggregator_policy(char *da Line 705  int ccs_write_aggregator_policy(char *da
705          if (!cp)          if (!cp)
706                  return -EINVAL;                  return -EINVAL;
707          *cp++ = '\0';          *cp++ = '\0';
708          return update_aggregator_entry(data, cp, is_delete);          return ccs_update_aggregator_entry(data, cp, is_delete);
709  }  }
710    
711  /* Domain create/delete/undelete handler. */  /* Domain create/delete/undelete handler. */
# Line 738  int ccs_write_aggregator_policy(char *da Line 722  int ccs_write_aggregator_policy(char *da
722  int ccs_delete_domain(char *domainname)  int ccs_delete_domain(char *domainname)
723  {  {
724          struct domain_info *domain;          struct domain_info *domain;
725          struct path_info name;          struct ccs_path_info name;
726          name.name = domainname;          name.name = domainname;
727          ccs_fill_path_info(&name);          ccs_fill_path_info(&name);
728          mutex_lock(&new_domain_assign_lock);          mutex_lock(&ccs_domain_list_lock);
729  #ifdef DEBUG_DOMAIN_UNDELETE  #ifdef DEBUG_DOMAIN_UNDELETE
730          printk(KERN_DEBUG "ccs_delete_domain %s\n", domainname);          printk(KERN_DEBUG "ccs_delete_domain %s\n", domainname);
731          list1_for_each_entry(domain, &domain_list, list) {          list1_for_each_entry(domain, &ccs_domain_list, list) {
732                  if (ccs_pathcmp(domain->domainname, &name))                  if (ccs_pathcmp(domain->domainname, &name))
733                          continue;                          continue;
734                  printk(KERN_DEBUG "List: %p %u\n", domain, domain->is_deleted);                  printk(KERN_DEBUG "List: %p %u\n", domain, domain->is_deleted);
735          }          }
736  #endif  #endif
737          /* Is there an active domain? */          /* Is there an active domain? */
738          list1_for_each_entry(domain, &domain_list, list) {          list1_for_each_entry(domain, &ccs_domain_list, list) {
739                  struct domain_info *domain2;                  struct domain_info *domain2;
740                  /* Never delete KERNEL_DOMAIN */                  /* Never delete KERNEL_DOMAIN */
741                  if (domain == &KERNEL_DOMAIN)                  if (domain == &KERNEL_DOMAIN)
# Line 760  int ccs_delete_domain(char *domainname) Line 744  int ccs_delete_domain(char *domainname)
744                      ccs_pathcmp(domain->domainname, &name))                      ccs_pathcmp(domain->domainname, &name))
745                          continue;                          continue;
746                  /* Mark already deleted domains as non undeletable. */                  /* Mark already deleted domains as non undeletable. */
747                  list1_for_each_entry(domain2, &domain_list, list) {                  list1_for_each_entry(domain2, &ccs_domain_list, list) {
748                          if (!domain2->is_deleted ||                          if (!domain2->is_deleted ||
749                              ccs_pathcmp(domain2->domainname, &name))                              ccs_pathcmp(domain2->domainname, &name))
750                                  continue;                                  continue;
# Line 779  int ccs_delete_domain(char *domainname) Line 763  int ccs_delete_domain(char *domainname)
763  #endif  #endif
764                  break;                  break;
765          }          }
766          mutex_unlock(&new_domain_assign_lock);          mutex_unlock(&ccs_domain_list_lock);
767          return 0;          return 0;
768  }  }
769    
# Line 794  struct domain_info *ccs_undelete_domain( Line 778  struct domain_info *ccs_undelete_domain(
778  {  {
779          struct domain_info *domain;          struct domain_info *domain;
780          struct domain_info *candidate_domain = NULL;          struct domain_info *candidate_domain = NULL;
781          struct path_info name;          struct ccs_path_info name;
782          name.name = domainname;          name.name = domainname;
783          ccs_fill_path_info(&name);          ccs_fill_path_info(&name);
784          mutex_lock(&new_domain_assign_lock);          mutex_lock(&ccs_domain_list_lock);
785  #ifdef DEBUG_DOMAIN_UNDELETE  #ifdef DEBUG_DOMAIN_UNDELETE
786          printk(KERN_DEBUG "ccs_undelete_domain %s\n", domainname);          printk(KERN_DEBUG "ccs_undelete_domain %s\n", domainname);
787          list1_for_each_entry(domain, &domain_list, list) {          list1_for_each_entry(domain, &ccs_domain_list, list) {
788                  if (ccs_pathcmp(domain->domainname, &name))                  if (ccs_pathcmp(domain->domainname, &name))
789                          continue;                          continue;
790                  printk(KERN_DEBUG "List: %p %u\n", domain, domain->is_deleted);                  printk(KERN_DEBUG "List: %p %u\n", domain, domain->is_deleted);
791          }          }
792  #endif  #endif
793          list1_for_each_entry(domain, &domain_list, list) {          list1_for_each_entry(domain, &ccs_domain_list, list) {
794                  if (ccs_pathcmp(&name, domain->domainname))                  if (ccs_pathcmp(&name, domain->domainname))
795                          continue;                          continue;
796                  if (!domain->is_deleted) {                  if (!domain->is_deleted) {
# Line 828  struct domain_info *ccs_undelete_domain( Line 812  struct domain_info *ccs_undelete_domain(
812                  printk(KERN_DEBUG "%p was undeleted.\n", candidate_domain);                  printk(KERN_DEBUG "%p was undeleted.\n", candidate_domain);
813  #endif  #endif
814          }          }
815          mutex_unlock(&new_domain_assign_lock);          mutex_unlock(&ccs_domain_list_lock);
816          return candidate_domain;          return candidate_domain;
817  }  }
818    
# Line 844  struct domain_info *ccs_find_or_assign_n Line 828  struct domain_info *ccs_find_or_assign_n
828                                                    const u8 profile)                                                    const u8 profile)
829  {  {
830          struct domain_info *domain = NULL;          struct domain_info *domain = NULL;
831          const struct path_info *saved_domainname;          const struct ccs_path_info *saved_domainname;
832          mutex_lock(&new_domain_assign_lock);          mutex_lock(&ccs_domain_list_lock);
833          domain = ccs_find_domain(domainname);          domain = ccs_find_domain(domainname);
834          if (domain)          if (domain)
835                  goto out;                  goto out;
# Line 855  struct domain_info *ccs_find_or_assign_n Line 839  struct domain_info *ccs_find_or_assign_n
839          if (!saved_domainname)          if (!saved_domainname)
840                  goto out;                  goto out;
841          /* Can I reuse memory of deleted domain? */          /* Can I reuse memory of deleted domain? */
842          list1_for_each_entry(domain, &domain_list, list) {          list1_for_each_entry(domain, &ccs_domain_list, list) {
843                  struct task_struct *p;                  struct task_struct *p;
844                  struct acl_info *ptr;                  struct ccs_acl_info *ptr;
845                  bool flag;                  bool flag;
846                  if (!domain->is_deleted ||                  if (!domain->is_deleted ||
847                      domain->domainname != saved_domainname)                      domain->domainname != saved_domainname)
# Line 882  struct domain_info *ccs_find_or_assign_n Line 866  struct domain_info *ccs_find_or_assign_n
866                  list1_for_each_entry(ptr, &domain->acl_info_list, list) {                  list1_for_each_entry(ptr, &domain->acl_info_list, list) {
867                          ptr->type |= ACL_DELETED;                          ptr->type |= ACL_DELETED;
868                  }                  }
869                  /*                  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;  
870                  domain->profile = profile;                  domain->profile = profile;
871                  domain->quota_warned = false;                  domain->quota_warned = false;
872                  mb(); /* Avoid out-of-order execution. */                  mb(); /* Avoid out-of-order execution. */
# Line 899  struct domain_info *ccs_find_or_assign_n Line 879  struct domain_info *ccs_find_or_assign_n
879                  INIT_LIST1_HEAD(&domain->acl_info_list);                  INIT_LIST1_HEAD(&domain->acl_info_list);
880                  domain->domainname = saved_domainname;                  domain->domainname = saved_domainname;
881                  domain->profile = profile;                  domain->profile = profile;
882                  list1_add_tail_mb(&domain->list, &domain_list);                  list1_add_tail_mb(&domain->list, &ccs_domain_list);
883          }          }
884   out:   out:
885          mutex_unlock(&new_domain_assign_lock);          mutex_unlock(&ccs_domain_list_lock);
886          return domain;          return domain;
887  }  }
888    
889  /**  /**
890   * get_argv0 - Get argv[0].   * ccs_get_argv0 - Get argv[0].
891   *   *
892   * @bprm: Pointer to "struct linux_binprm".   * @bprm: Pointer to "struct linux_binprm".
893   * @tmp:  Buffer for temporal use.   * @tmp:  Buffer for temporary use.
894   *   *
895   * Returns true on success, false otherwise.   * Returns true on success, false otherwise.
896   */   */
897  static bool get_argv0(struct linux_binprm *bprm, struct ccs_page_buffer *tmp)  static bool ccs_get_argv0(struct linux_binprm *bprm,
898                              struct ccs_page_buffer *tmp)
899  {  {
900          char *arg_ptr = tmp->buffer;          char *arg_ptr = tmp->buffer;
901          int arg_len = 0;          int arg_len = 0;
# Line 937  static bool get_argv0(struct linux_binpr Line 918  static bool get_argv0(struct linux_binpr
918  #endif  #endif
919                  /* Map. */                  /* Map. */
920                  kaddr = kmap(page);                  kaddr = kmap(page);
                 if (!kaddr) { /* Mapping failed. */  
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 23) && defined(CONFIG_MMU)  
                         put_page(page);  
 #endif  
                         goto out;  
                 }  
921                  /* Read. */                  /* Read. */
922                  while (offset < PAGE_SIZE) {                  while (offset < PAGE_SIZE) {
923                          const unsigned char c = kaddr[offset++];                          const unsigned char c = kaddr[offset++];
# Line 983  static bool get_argv0(struct linux_binpr Line 958  static bool get_argv0(struct linux_binpr
958  }  }
959    
960  /**  /**
961   * find_next_domain - Find a domain.   * ccs_find_next_domain - Find a domain.
962   *   *
963   * @bprm:           Pointer to "struct linux_binprm".   * @r:       Pointer to "struct ccs_request_info".
964   * @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.  
965   *   *
966   * Returns 0 on success, negative value otherwise.   * Returns 0 on success, negative value otherwise.
967   */   */
968  static int find_next_domain(struct linux_binprm *bprm,  static int ccs_find_next_domain(struct ccs_request_info *r,
969                              struct domain_info **next_domain,                                  const struct ccs_path_info *handler)
                             const struct path_info *path_to_verify,  
                             struct ccs_page_buffer *tmp)  
970  {  {
971          /*          /*
972           * This function assumes that the size of buffer returned by           * This function assumes that the size of buffer returned by
973           * ccs_realpath() = CCS_MAX_PATHNAME_LEN.           * ccs_realpath() = CCS_MAX_PATHNAME_LEN.
974           */           */
         struct domain_info *old_domain = current->domain_info;  
975          struct domain_info *domain = NULL;          struct domain_info *domain = NULL;
976          const char *old_domain_name = old_domain->domainname->name;          const char *old_domain_name = r->domain->domainname->name;
977            struct linux_binprm *bprm = r->bprm;
978            struct ccs_page_buffer *tmp = r->obj->tmp;
979          const char *original_name = bprm->filename;          const char *original_name = bprm->filename;
980            const u8 mode = r->mode;
981            const bool is_enforce = (mode == 3);
982            const u32 tomoyo_flags = current->tomoyo_flags;
983          char *new_domain_name = NULL;          char *new_domain_name = NULL;
984          char *real_program_name = NULL;          char *real_program_name = NULL;
985          char *symlink_program_name = NULL;          char *symlink_program_name = NULL;
986          const u8 mode = ccs_check_flags(CCS_TOMOYO_MAC_FOR_FILE);          struct ccs_path_info rn; /* real name */
987          const bool is_enforce = (mode == 3);          struct ccs_path_info sn; /* symlink name */
988            struct ccs_path_info ln; /* last name */
989          int retval;          int retval;
         struct path_info r; /* real name */  
         struct path_info s; /* symlink name */  
         struct path_info l; /* last name */  
         const u32 tomoyo_flags = current->tomoyo_flags;  
990    
991          {          {
992                  /*                  /*
# Line 1023  static int find_next_domain(struct linux Line 995  static int find_next_domain(struct linux
995                   */                   */
996                  static bool first = true;                  static bool first = true;
997                  if (first) {                  if (first) {
998                          update_domain_initializer_entry(NULL, "/sbin/hotplug",                          ccs_update_domain_initializer_entry(NULL,
999                                                          false, false);                                                              "/sbin/hotplug",
1000                          update_domain_initializer_entry(NULL, "/sbin/modprobe",                                                              false, false);
1001                                                          false, false);                          ccs_update_domain_initializer_entry(NULL,
1002                                                                "/sbin/modprobe",
1003                                                                false, false);
1004                          first = false;                          first = false;
1005                  }                  }
1006          }          }
1007    
1008   retry:   retry:
1009          current->tomoyo_flags = tomoyo_flags;          current->tomoyo_flags = tomoyo_flags;
1010            r->cond = NULL;
1011          /* Get ccs_realpath of program. */          /* Get ccs_realpath of program. */
1012          retval = -ENOENT; /* I hope ccs_realpath() won't fail with -ENOMEM. */          retval = -ENOENT; /* I hope ccs_realpath() won't fail with -ENOMEM. */
1013          ccs_free(real_program_name);          ccs_free(real_program_name);
# Line 1045  static int find_next_domain(struct linux Line 1020  static int find_next_domain(struct linux
1020          if (!symlink_program_name)          if (!symlink_program_name)
1021                  goto out;                  goto out;
1022    
1023          r.name = real_program_name;          rn.name = real_program_name;
1024          ccs_fill_path_info(&r);          ccs_fill_path_info(&rn);
1025          s.name = symlink_program_name;          sn.name = symlink_program_name;
1026          ccs_fill_path_info(&s);          ccs_fill_path_info(&sn);
1027          l.name = ccs_get_last_name(old_domain);          ln.name = ccs_get_last_name(r->domain);
1028          ccs_fill_path_info(&l);          ccs_fill_path_info(&ln);
1029    
1030          if (path_to_verify) {          if (handler) {
1031                  if (ccs_pathcmp(&r, path_to_verify)) {                  if (ccs_pathcmp(&rn, handler)) {
1032                          /* Failed to verify execute handler. */                          /* Failed to verify execute handler. */
1033                          static u8 counter = 20;                          static u8 counter = 20;
1034                          if (counter) {                          if (counter) {
1035                                  counter--;                                  counter--;
1036                                  printk(KERN_WARNING "Failed to verify: %s\n",                                  printk(KERN_WARNING "Failed to verify: %s\n",
1037                                         path_to_verify->name);                                         handler->name);
1038                          }                          }
1039                          goto out;                          goto out;
1040                  }                  }
# Line 1067  static int find_next_domain(struct linux Line 1042  static int find_next_domain(struct linux
1042          }          }
1043    
1044          /* Check 'alias' directive. */          /* Check 'alias' directive. */
1045          if (ccs_pathcmp(&r, &s)) {          if (ccs_pathcmp(&rn, &sn)) {
1046                  struct alias_entry *ptr;                  struct ccs_alias_entry *ptr;
1047                  /* Is this program allowed to be called via symbolic links? */                  /* Is this program allowed to be called via symbolic links? */
1048                  list1_for_each_entry(ptr, &alias_list, list) {                  list1_for_each_entry(ptr, &ccs_alias_list, list) {
1049                          if (ptr->is_deleted ||                          if (ptr->is_deleted ||
1050                              ccs_pathcmp(&r, ptr->original_name) ||                              ccs_pathcmp(&rn, ptr->original_name) ||
1051                              ccs_pathcmp(&s, ptr->aliased_name))                              ccs_pathcmp(&sn, ptr->aliased_name))
1052                                  continue;                                  continue;
1053                          memset(real_program_name, 0, CCS_MAX_PATHNAME_LEN);                          memset(real_program_name, 0, CCS_MAX_PATHNAME_LEN);
1054                          strncpy(real_program_name, ptr->aliased_name->name,                          strncpy(real_program_name, ptr->aliased_name->name,
1055                                  CCS_MAX_PATHNAME_LEN - 1);                                  CCS_MAX_PATHNAME_LEN - 1);
1056                          ccs_fill_path_info(&r);                          ccs_fill_path_info(&rn);
1057                          break;                          break;
1058                  }                  }
1059          }          }
1060    
1061          /* Compare basename of real_program_name and argv[0] */          /* Compare basename of real_program_name and argv[0] */
1062          if (bprm->argc > 0 && ccs_check_flags(CCS_TOMOYO_MAC_FOR_ARGV0)) {          r->mode = ccs_check_flags(r->domain, CCS_TOMOYO_MAC_FOR_ARGV0);
1063            if (bprm->argc > 0 && r->mode) {
1064                  char *base_argv0 = tmp->buffer;                  char *base_argv0 = tmp->buffer;
1065                  const char *base_filename;                  const char *base_filename;
1066                  retval = -ENOMEM;                  retval = -ENOMEM;
1067                  if (!get_argv0(bprm, tmp))                  if (!ccs_get_argv0(bprm, tmp))
1068                          goto out;                          goto out;
1069                  base_filename = strrchr(real_program_name, '/');                  base_filename = strrchr(real_program_name, '/');
1070                  if (!base_filename)                  if (!base_filename)
# Line 1096  static int find_next_domain(struct linux Line 1072  static int find_next_domain(struct linux
1072                  else                  else
1073                          base_filename++;                          base_filename++;
1074                  if (strcmp(base_argv0, base_filename)) {                  if (strcmp(base_argv0, base_filename)) {
1075                          retval = ccs_check_argv0_perm(&r, base_argv0);                          retval = ccs_check_argv0_perm(r, &rn, base_argv0);
1076                          if (retval == 1)                          if (retval == 1)
1077                                  goto retry;                                  goto retry;
1078                          if (retval < 0)                          if (retval < 0)
# Line 1106  static int find_next_domain(struct linux Line 1082  static int find_next_domain(struct linux
1082    
1083          /* Check 'aggregator' directive. */          /* Check 'aggregator' directive. */
1084          {          {
1085                  struct aggregator_entry *ptr;                  struct ccs_aggregator_entry *ptr;
1086                  /* Is this program allowed to be aggregated? */                  /* Is this program allowed to be aggregated? */
1087                  list1_for_each_entry(ptr, &aggregator_list, list) {                  list1_for_each_entry(ptr, &ccs_aggregator_list, list) {
1088                          if (ptr->is_deleted ||                          if (ptr->is_deleted ||
1089                              !ccs_path_matches_pattern(&r, ptr->original_name))                              !ccs_path_matches_pattern(&rn, ptr->original_name))
1090                                  continue;                                  continue;
1091                          memset(real_program_name, 0, CCS_MAX_PATHNAME_LEN);                          memset(real_program_name, 0, CCS_MAX_PATHNAME_LEN);
1092                          strncpy(real_program_name, ptr->aggregated_name->name,                          strncpy(real_program_name, ptr->aggregated_name->name,
1093                                  CCS_MAX_PATHNAME_LEN - 1);                                  CCS_MAX_PATHNAME_LEN - 1);
1094                          ccs_fill_path_info(&r);                          ccs_fill_path_info(&rn);
1095                          break;                          break;
1096                  }                  }
1097          }          }
1098    
1099          /* Check execute permission. */          /* Check execute permission. */
1100          retval = ccs_check_exec_perm(&r, bprm, tmp);          r->mode = mode;
1101            retval = ccs_check_exec_perm(r, &rn);
1102          if (retval == 1)          if (retval == 1)
1103                  goto retry;                  goto retry;
1104          if (retval < 0)          if (retval < 0)
# Line 1129  static int find_next_domain(struct linux Line 1106  static int find_next_domain(struct linux
1106    
1107   calculate_domain:   calculate_domain:
1108          new_domain_name = tmp->buffer;          new_domain_name = tmp->buffer;
1109          if (is_domain_initializer(old_domain->domainname, &r, &l)) {          if (ccs_is_domain_initializer(r->domain->domainname, &rn, &ln)) {
1110                  /* Transit to the child of KERNEL_DOMAIN domain. */                  /* Transit to the child of KERNEL_DOMAIN domain. */
1111                  snprintf(new_domain_name, CCS_MAX_PATHNAME_LEN + 1,                  snprintf(new_domain_name, CCS_MAX_PATHNAME_LEN + 1,
1112                           ROOT_NAME " " "%s", real_program_name);                           ROOT_NAME " " "%s", real_program_name);
1113          } else if (old_domain == &KERNEL_DOMAIN && !sbin_init_started) {          } else if (r->domain == &KERNEL_DOMAIN && !ccs_sbin_init_started) {
1114                  /*                  /*
1115                   * Needn't to transit from kernel domain before starting                   * Needn't to transit from kernel domain before starting
1116                   * /sbin/init. But transit from kernel domain if executing                   * /sbin/init. But transit from kernel domain if executing
1117                   * initializers because they might start before /sbin/init.                   * initializers because they might start before /sbin/init.
1118                   */                   */
1119                  domain = old_domain;                  domain = r->domain;
1120          } else if (is_domain_keeper(old_domain->domainname, &r, &l)) {          } else if (ccs_is_domain_keeper(r->domain->domainname, &rn, &ln)) {
1121                  /* Keep current domain. */                  /* Keep current domain. */
1122                  domain = old_domain;                  domain = r->domain;
1123          } else {          } else {
1124                  /* Normal domain transition. */                  /* Normal domain transition. */
1125                  snprintf(new_domain_name, CCS_MAX_PATHNAME_LEN + 1,                  snprintf(new_domain_name, CCS_MAX_PATHNAME_LEN + 1,
# Line 1154  static int find_next_domain(struct linux Line 1131  static int find_next_domain(struct linux
1131          if (domain)          if (domain)
1132                  goto done;                  goto done;
1133          if (is_enforce) {          if (is_enforce) {
1134                  int error = ccs_check_supervisor(NULL,                  int error = ccs_check_supervisor(r,
1135                                                   "# wants to create domain\n"                                                   "# wants to create domain\n"
1136                                                   "%s\n", new_domain_name);                                                   "%s\n", new_domain_name);
1137                  if (error == 1)                  if (error == 1)
# Line 1162  static int find_next_domain(struct linux Line 1139  static int find_next_domain(struct linux
1139                  if (error < 0)                  if (error < 0)
1140                          goto done;                          goto done;
1141          }          }
1142          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);  
1143          if (domain)          if (domain)
1144                  audit_domain_creation_log(new_domain_name, mode,                  ccs_audit_domain_creation_log(domain);
                                           domain->profile);  
1145   done:   done:
1146          if (!domain) {          if (!domain) {
1147                  printk(KERN_WARNING "TOMOYO-ERROR: Domain '%s' not defined.\n",                  printk(KERN_WARNING "TOMOYO-ERROR: Domain '%s' not defined.\n",
# Line 1175  static int find_next_domain(struct linux Line 1150  static int find_next_domain(struct linux
1150                          retval = -EPERM;                          retval = -EPERM;
1151                  else {                  else {
1152                          retval = 0;                          retval = 0;
1153                          ccs_set_domain_flag(old_domain, false,                          ccs_set_domain_flag(r->domain, false,
1154                                              DOMAIN_FLAGS_TRANSITION_FAILED);                                              DOMAIN_FLAGS_TRANSITION_FAILED);
1155                  }                  }
1156          } else {          } else {
# Line 1184  static int find_next_domain(struct linux Line 1159  static int find_next_domain(struct linux
1159   out:   out:
1160          ccs_free(real_program_name);          ccs_free(real_program_name);
1161          ccs_free(symlink_program_name);          ccs_free(symlink_program_name);
1162          *next_domain = domain ? domain : old_domain;          if (domain)
1163                    r->domain = domain;
1164          return retval;          return retval;
1165  }  }
1166    
1167  /**  /**
1168   * check_environ - Check permission for environment variable names.   * ccs_check_environ - Check permission for environment variable names.
1169   *   *
1170   * @bprm: Pointer to "struct linux_binprm".   * @r: Pointer to "struct ccs_request_info".
  * @tmp:  Buffer for temporal use.  
1171   *   *
1172   * Returns 0 on success, negative value otherwise.   * Returns 0 on success, negative value otherwise.
1173   */   */
1174  static int check_environ(struct linux_binprm *bprm, struct ccs_page_buffer *tmp)  static int ccs_check_environ(struct ccs_request_info *r)
1175  {  {
1176          const u8 profile = current->domain_info->profile;          struct linux_binprm *bprm = r->bprm;
1177          const u8 mode = ccs_check_flags(CCS_TOMOYO_MAC_FOR_ENV);          struct ccs_page_buffer *tmp = r->obj->tmp;
1178          char *arg_ptr = tmp->buffer;          char *arg_ptr = tmp->buffer;
1179          int arg_len = 0;          int arg_len = 0;
1180          unsigned long pos = bprm->p;          unsigned long pos = bprm->p;
# Line 1209  static int check_environ(struct linux_bi Line 1184  static int check_environ(struct linux_bi
1184          int envp_count = bprm->envc;          int envp_count = bprm->envc;
1185          /* printk(KERN_DEBUG "start %d %d\n", argv_count, envp_count); */          /* printk(KERN_DEBUG "start %d %d\n", argv_count, envp_count); */
1186          int error = -ENOMEM;          int error = -ENOMEM;
1187          if (!mode || !envp_count)          if (!r->mode || !envp_count)
1188                  return 0;                  return 0;
1189          while (error == -ENOMEM) {          while (error == -ENOMEM) {
1190                  struct page *page;                  struct page *page;
# Line 1224  static int check_environ(struct linux_bi Line 1199  static int check_environ(struct linux_bi
1199  #endif  #endif
1200                  /* Map. */                  /* Map. */
1201                  kaddr = kmap(page);                  kaddr = kmap(page);
                 if (!kaddr) { /* Mapping failed. */  
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 23) && defined(CONFIG_MMU)  
                         put_page(page);  
 #endif  
                         goto out;  
                 }  
1202                  /* Read. */                  /* Read. */
1203                  while (argv_count && offset < PAGE_SIZE) {                  while (argv_count && offset < PAGE_SIZE) {
1204                          if (!kaddr[offset++])                          if (!kaddr[offset++])
# Line 1259  static int check_environ(struct linux_bi Line 1228  static int check_environ(struct linux_bi
1228                          }                          }
1229                          if (c)                          if (c)
1230                                  continue;                                  continue;
1231                          if (ccs_check_env_perm(arg_ptr, profile, mode)) {                          if (ccs_check_env_perm(r, arg_ptr)) {
1232                                  error = -EPERM;                                  error = -EPERM;
1233                                  break;                                  break;
1234                          }                          }
# Line 1269  static int check_environ(struct linux_bi Line 1238  static int check_environ(struct linux_bi
1238                          }                          }
1239                          arg_len = 0;                          arg_len = 0;
1240                  }                  }
1241   unmap_page:  unmap_page:
1242                  /* Unmap. */                  /* Unmap. */
1243                  kunmap(page);                  kunmap(page);
1244  #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 23) && defined(CONFIG_MMU)  #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 23) && defined(CONFIG_MMU)
# Line 1279  static int check_environ(struct linux_bi Line 1248  static int check_environ(struct linux_bi
1248                  offset = 0;                  offset = 0;
1249          }          }
1250   out:   out:
1251          if (error && mode != 3)          if (r->mode != 3)
1252                  error = 0;                  error = 0;
1253          return error;          return error;
1254  }  }
1255    
1256  /**  /**
1257   * unescape - Unescape escaped string.   * ccs_unescape - Unescape escaped string.
1258   *   *
1259   * @dest: String to unescape.   * @dest: String to ccs_unescape.
1260   *   *
1261   * Returns nothing.   * Returns nothing.
1262   */   */
1263  static void unescape(unsigned char *dest)  static void ccs_unescape(unsigned char *dest)
1264  {  {
1265          unsigned char *src = dest;          unsigned char *src = dest;
1266          unsigned char c;          unsigned char c;
1267          unsigned char d;          unsigned char d;
1268          unsigned char e;          unsigned char e;
1269          while ((c = *src++) != '\0') {          while (1) {
1270                    c = *src++;
1271                    if (!c)
1272                            break;
1273                  if (c != '\\') {                  if (c != '\\') {
1274                          *dest++ = c;                          *dest++ = c;
1275                          continue;                          continue;
# Line 1321  static void unescape(unsigned char *dest Line 1293  static void unescape(unsigned char *dest
1293  }  }
1294    
1295  /**  /**
1296   * root_depth - Get number of directories to strip.   * ccs_root_depth - Get number of directories to strip.
1297   *   *
1298   * @dentry: Pointer to "struct dentry".   * @dentry: Pointer to "struct dentry".
1299   * @vfsmnt: Pointer to "struct vfsmount".   * @vfsmnt: Pointer to "struct vfsmount".
1300   *   *
1301   * Returns number of directories to strip.   * Returns number of directories to strip.
1302   */   */
1303  static inline int root_depth(struct dentry *dentry, struct vfsmount *vfsmnt)  static inline int ccs_root_depth(struct dentry *dentry, struct vfsmount *vfsmnt)
1304  {  {
1305          int depth = 0;          int depth = 0;
1306          /***** CRITICAL SECTION START *****/          /***** CRITICAL SECTION START *****/
# Line 1351  static inline int root_depth(struct dent Line 1323  static inline int root_depth(struct dent
1323  }  }
1324    
1325  /**  /**
1326   * get_root_depth - return the depth of root directory.   * ccs_get_root_depth - return the depth of root directory.
1327   *   *
1328   * Returns number of directories to strip.   * Returns number of directories to strip.
1329   */   */
1330  static int get_root_depth(void)  static int ccs_get_root_depth(void)
1331  {  {
1332          int depth;          int depth;
1333          struct dentry *dentry;          struct dentry *dentry;
# Line 1376  static int get_root_depth(void) Line 1348  static int get_root_depth(void)
1348  #endif  #endif
1349          read_unlock(&current->fs->lock);          read_unlock(&current->fs->lock);
1350          /***** CRITICAL SECTION END *****/          /***** CRITICAL SECTION END *****/
1351          depth = root_depth(dentry, vfsmnt);          depth = ccs_root_depth(dentry, vfsmnt);
1352  #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)  #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)
1353          path_put(&root);          path_put(&root);
1354  #else  #else
# Line 1387  static int get_root_depth(void) Line 1359  static int get_root_depth(void)
1359  }  }
1360    
1361  /**  /**
1362   * try_alt_exec - Try to start execute handler.   * ccs_try_alt_exec - Try to start execute handler.
1363   *   *
1364   * @bprm:        Pointer to "struct linux_binprm".   * @r:           Pointer to "struct ccs_request_info".
1365   * @handler:     Pointer to the name of execute handler.   * @handler:     Pointer to the name of execute handler.
1366   * @eh_path:     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.  
1367   *   *
1368   * Returns 0 on success, negative value otherwise.   * Returns 0 on success, negative value otherwise.
1369   */   */
1370  static int try_alt_exec(struct linux_binprm *bprm,  static int ccs_try_alt_exec(struct ccs_request_info *r,
1371                          const struct path_info *handler, char **eh_path,                              const struct ccs_path_info *handler, char **eh_path)
                         struct domain_info **next_domain,  
                         struct ccs_page_buffer *tmp)  
1372  {  {
1373          /*          /*
1374           * Contents of modified bprm.           * Contents of modified bprm.
# Line 1438  static int try_alt_exec(struct linux_bin Line 1406  static int try_alt_exec(struct linux_bin
1406           * modified bprm->argv[bprm->envc + bprm->argc + 6]           * modified bprm->argv[bprm->envc + bprm->argc + 6]
1407           *     = original bprm->envp[bprm->envc - 1]           *     = original bprm->envp[bprm->envc - 1]
1408           */           */
1409            struct linux_binprm *bprm = r->bprm;
1410          struct file *filp;          struct file *filp;
1411          int retval;          int retval;
1412          const int original_argc = bprm->argc;          const int original_argc = bprm->argc;
1413          const int original_envc = bprm->envc;          const int original_envc = bprm->envc;
1414          struct task_struct *task = current;          struct task_struct *task = current;
1415          char *buffer = tmp->buffer;          char *buffer = r->obj->tmp->buffer;
1416          /* Allocate memory for execute handler's pathname. */          /* Allocate memory for execute handler's pathname. */
1417          char *execute_handler = ccs_alloc(sizeof(struct ccs_page_buffer));          char *execute_handler = ccs_alloc(sizeof(struct ccs_page_buffer),
1418                                              false);
1419          *eh_path = execute_handler;          *eh_path = execute_handler;
1420          if (!execute_handler)          if (!execute_handler)
1421                  return -ENOMEM;                  return -ENOMEM;
1422          strncpy(execute_handler, handler->name,          strncpy(execute_handler, handler->name,
1423                  sizeof(struct ccs_page_buffer) - 1);                  sizeof(struct ccs_page_buffer) - 1);
1424          unescape(execute_handler);          ccs_unescape(execute_handler);
1425    
1426          /* Close the requested program's dentry. */          /* Close the requested program's dentry. */
1427          allow_write_access(bprm->file);          allow_write_access(bprm->file);
# Line 1459  static int try_alt_exec(struct linux_bin Line 1429  static int try_alt_exec(struct linux_bin
1429          bprm->file = NULL;          bprm->file = NULL;
1430    
1431          { /* Adjust root directory for open_exec(). */          { /* Adjust root directory for open_exec(). */
1432                  int depth = get_root_depth();                  int depth = ccs_get_root_depth();
1433                  char *cp = execute_handler;                  char *cp = execute_handler;
1434                  if (!*cp || *cp != '/')                  if (!*cp || *cp != '/')
1435                          return -ENOENT;                          return -ENOENT;
# Line 1511  static int try_alt_exec(struct linux_bin Line 1481  static int try_alt_exec(struct linux_bin
1481                           "pid=%d uid=%d gid=%d euid=%d egid=%d suid=%d "                           "pid=%d uid=%d gid=%d euid=%d egid=%d suid=%d "
1482                           "sgid=%d fsuid=%d fsgid=%d state[0]=%u "                           "sgid=%d fsuid=%d fsgid=%d state[0]=%u "
1483                           "state[1]=%u state[2]=%u",                           "state[1]=%u state[2]=%u",
1484                           task->pid, task->uid, task->gid, task->euid,                           (pid_t) sys_getpid(), current_uid(), current_gid(),
1485                           task->egid, task->suid, task->sgid, task->fsuid,                           current_euid(), current_egid(), current_suid(),
1486                           task->fsgid, (u8) (tomoyo_flags >> 24),                           current_sgid(), current_fsuid(), current_fsgid(),
1487                           (u8) (tomoyo_flags >> 16), (u8) (tomoyo_flags >> 8));                           (u8) (tomoyo_flags >> 24), (u8) (tomoyo_flags >> 16),
1488                             (u8) (tomoyo_flags >> 8));
1489                  retval = copy_strings_kernel(1, &buffer, bprm);                  retval = copy_strings_kernel(1, &buffer, bprm);
1490                  if (retval < 0)                  if (retval < 0)
1491                          goto out;                          goto out;
# Line 1575  static int try_alt_exec(struct linux_bin Line 1546  static int try_alt_exec(struct linux_bin
1546          if (retval < 0)          if (retval < 0)
1547                  goto out;                  goto out;
1548          task->tomoyo_flags |= CCS_DONT_SLEEP_ON_ENFORCE_ERROR;          task->tomoyo_flags |= CCS_DONT_SLEEP_ON_ENFORCE_ERROR;
1549          retval = find_next_domain(bprm, next_domain, handler, tmp);          retval = ccs_find_next_domain(r, handler);
1550          task->tomoyo_flags &= ~CCS_DONT_SLEEP_ON_ENFORCE_ERROR;          task->tomoyo_flags &= ~CCS_DONT_SLEEP_ON_ENFORCE_ERROR;
1551   out:   out:
1552          return retval;          return retval;
1553  }  }
1554    
1555  /**  /**
1556   * find_execute_handler - Find an execute handler.   * ccs_find_execute_handler - Find an execute handler.
1557   *   *
1558   * @type: Type of execute handler.   * @type: Type of execute handler.
1559   *   *
1560   * Returns pointer to "struct path_info" if found, NULL otherwise.   * Returns pointer to "struct ccs_path_info" if found, NULL otherwise.
1561   */   */
1562  static const struct path_info *find_execute_handler(const u8 type)  static const struct ccs_path_info *ccs_find_execute_handler(const u8 type)
1563  {  {
1564          struct task_struct *task = current;          struct task_struct *task = current;
1565          const struct domain_info *domain = task->domain_info;          const struct domain_info *domain = task->domain_info;
1566          struct acl_info *ptr;          struct ccs_acl_info *ptr;
1567          /*          /*
1568           * Don't use execute handler if the current process is           * Don't use execute handler if the current process is
1569           * marked as execute handler to avoid infinite execute handler loop.           * marked as execute handler to avoid infinite execute handler loop.
# Line 1600  static const struct path_info *find_exec Line 1571  static const struct path_info *find_exec
1571          if (task->tomoyo_flags & TOMOYO_TASK_IS_EXECUTE_HANDLER)          if (task->tomoyo_flags & TOMOYO_TASK_IS_EXECUTE_HANDLER)
1572                  return NULL;                  return NULL;
1573          list1_for_each_entry(ptr, &domain->acl_info_list, list) {          list1_for_each_entry(ptr, &domain->acl_info_list, list) {
1574                  struct execute_handler_record *acl;                  struct ccs_execute_handler_record *acl;
1575                  if (ptr->type != type)                  if (ptr->type != type)
1576                          continue;                          continue;
1577                  acl = container_of(ptr, struct execute_handler_record, head);                  acl = container_of(ptr, struct ccs_execute_handler_record,
1578                                       head);
1579                  return acl->handler;                  return acl->handler;
1580          }          }
1581          return NULL;          return NULL;
1582  }  }
1583    
1584    /* List of next_domain which is used for checking interpreter's permissions. */
1585    struct ccs_execve_entry {
1586            struct list_head list;
1587            struct task_struct *task;
1588            struct domain_info *next_domain;
1589    };
1590    
1591    static LIST_HEAD(ccs_execve_list);
1592    static DEFINE_SPINLOCK(ccs_execve_list_lock);
1593    
1594    /**
1595     * ccs_register_next_domain - Remember next_domain.
1596     *
1597     * @next_domain: Pointer to "struct domain_info".
1598     *
1599     * Returns 0 on success, -ENOMEM otherwise.
1600     */
1601    static int ccs_register_next_domain(struct domain_info *next_domain)
1602    {
1603            struct ccs_execve_entry *ee = kmalloc(sizeof(*ee), GFP_KERNEL);
1604            if (!ee)
1605                    return -ENOMEM;
1606            ee->task = current;
1607            ee->next_domain = next_domain;
1608            /***** CRITICAL SECTION START *****/
1609            spin_lock(&ccs_execve_list_lock);
1610            list_add(&ee->list, &ccs_execve_list);
1611            spin_unlock(&ccs_execve_list_lock);
1612            /***** CRITICAL SECTION END *****/
1613            return 0;
1614    }
1615    
1616    /**
1617     * ccs_fetch_next_domain - Fetch next_domain from the list.
1618     *
1619     * Returns pointer to "struct domain_info" which will be used if execve()
1620     * succeeds. This function does not return NULL.
1621     */
1622    struct domain_info *ccs_fetch_next_domain(void)
1623    {
1624            struct task_struct *task = current;
1625            struct domain_info *next_domain = task->domain_info;
1626            struct ccs_execve_entry *p;
1627            /***** CRITICAL SECTION START *****/
1628            spin_lock(&ccs_execve_list_lock);
1629            list_for_each_entry(p, &ccs_execve_list, list) {
1630                    if (p->task != task)
1631                            continue;
1632                    next_domain = p->next_domain;
1633                    break;
1634            }
1635            spin_unlock(&ccs_execve_list_lock);
1636            /***** CRITICAL SECTION END *****/
1637            return next_domain;
1638    }
1639    
1640    /**
1641     * ccs_unregister_next_domain - Forget next_domain.
1642     */
1643    static void ccs_unregister_next_domain(void)
1644    {
1645            struct task_struct *task = current;
1646            struct ccs_execve_entry *p;
1647            struct ccs_execve_entry *ee = NULL;
1648            /***** CRITICAL SECTION START *****/
1649            spin_lock(&ccs_execve_list_lock);
1650            list_for_each_entry(p, &ccs_execve_list, list) {
1651                    if (p->task != task)
1652                            continue;
1653                    list_del(&p->list);
1654                    ee = p;
1655                    break;
1656            }
1657            spin_unlock(&ccs_execve_list_lock);
1658            /***** CRITICAL SECTION END *****/
1659            kfree(ee);
1660    }
1661    
1662  /**  /**
1663   * search_binary_handler_with_transition - Perform domain transition.   * search_binary_handler_with_transition - Perform domain transition.
1664   *   *
# Line 1621  static const struct path_info *find_exec Line 1671  static const struct path_info *find_exec
1671  int search_binary_handler_with_transition(struct linux_binprm *bprm,  int search_binary_handler_with_transition(struct linux_binprm *bprm,
1672                                            struct pt_regs *regs)                                            struct pt_regs *regs)
1673  {  {
         struct task_struct *task = current;  
         struct domain_info *next_domain = NULL;  
         struct domain_info *prev_domain = task->domain_info;  
         const struct path_info *handler;  
1674          int retval;          int retval;
1675            struct task_struct *task = current;
1676            const struct ccs_path_info *handler;
1677            struct ccs_request_info r;
1678            struct ccs_obj_info obj;
1679          /*          /*
1680           * "eh_path" holds path to execute handler program.           * "eh_path" holds path to execute handler program.
1681           * Thus, keep valid until search_binary_handler() finishes.           * Thus, keep valid until search_binary_handler() finishes.
1682           */           */
1683          char *eh_path = NULL;          char *eh_path = NULL;
1684          struct ccs_page_buffer *tmp = ccs_alloc(sizeof(struct ccs_page_buffer));          struct ccs_page_buffer *tmp = ccs_alloc(sizeof(struct ccs_page_buffer),
1685          ccs_load_policy(bprm->filename);                                                  false);
1686            memset(&obj, 0, sizeof(obj));
1687            if (!ccs_sbin_init_started)
1688                    ccs_load_policy(bprm->filename);
1689          if (!tmp)          if (!tmp)
1690                  return -ENOMEM;                  return -ENOMEM;
1691          /* printk(KERN_DEBUG "rootdepth=%d\n", get_root_depth()); */  
1692          handler = find_execute_handler(TYPE_EXECUTE_HANDLER);          ccs_init_request_info(&r, NULL, CCS_TOMOYO_MAC_FOR_FILE);
1693            r.bprm = bprm;
1694            r.obj = &obj;
1695            obj.path1_dentry = bprm->file->f_dentry;
1696            obj.path1_vfsmnt = bprm->file->f_vfsmnt;
1697            obj.tmp = tmp;
1698    
1699            /* Clear manager flag. */
1700            task->tomoyo_flags &= ~CCS_TASK_IS_POLICY_MANAGER;
1701            handler = ccs_find_execute_handler(TYPE_EXECUTE_HANDLER);
1702          if (handler) {          if (handler) {
1703                  retval = try_alt_exec(bprm, handler, &eh_path, &next_domain,                  retval = ccs_try_alt_exec(&r, handler, &eh_path);
                                       tmp);  
1704                  if (!retval)                  if (!retval)
1705                          audit_execute_handler_log(true, handler->name, bprm);                          ccs_audit_execute_handler_log(true, handler->name,
1706                                                          bprm);
1707                  goto ok;                  goto ok;
1708          }          }
1709          retval = find_next_domain(bprm, &next_domain, NULL, tmp);          retval = ccs_find_next_domain(&r, NULL);
1710          if (retval != -EPERM)          if (retval != -EPERM)
1711                  goto ok;                  goto ok;
1712          handler = find_execute_handler(TYPE_DENIED_EXECUTE_HANDLER);          handler = ccs_find_execute_handler(TYPE_DENIED_EXECUTE_HANDLER);
1713          if (handler) {          if (handler) {
1714                  retval = try_alt_exec(bprm, handler, &eh_path, &next_domain,                  retval = ccs_try_alt_exec(&r, handler, &eh_path);
                                       tmp);  
1715                  if (!retval)                  if (!retval)
1716                          audit_execute_handler_log(false, handler->name, bprm);                          ccs_audit_execute_handler_log(false, handler->name,
1717                                                          bprm);
1718          }          }
1719   ok:   ok:
1720          if (retval < 0)          if (retval < 0)
1721                  goto out;                  goto out;
1722          task->domain_info = next_domain;          r.mode = ccs_check_flags(r.domain, CCS_TOMOYO_MAC_FOR_ENV);
1723          retval = check_environ(bprm, tmp);          retval = ccs_check_environ(&r);
1724            if (retval < 0)
1725                    goto out;
1726            retval = ccs_register_next_domain(r.domain);
1727          if (retval < 0)          if (retval < 0)
1728                  goto out;                  goto out;
1729          task->tomoyo_flags |= TOMOYO_CHECK_READ_FOR_OPEN_EXEC;          task->tomoyo_flags |= TOMOYO_CHECK_READ_FOR_OPEN_EXEC;
1730          retval = search_binary_handler(bprm, regs);          retval = search_binary_handler(bprm, regs);
1731          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. */  
1732          if (retval < 0)          if (retval < 0)
1733                  task->domain_info = prev_domain;                  goto out;
1734            /* Proceed to next domain if execution suceeded. */
1735            task->domain_info = r.domain;
1736            mb(); /* Make domain transition visible to other CPUs. */
1737          /* Mark the current process as execute handler. */          /* Mark the current process as execute handler. */
1738          else if (handler)          if (handler)
1739                  task->tomoyo_flags |= TOMOYO_TASK_IS_EXECUTE_HANDLER;                  task->tomoyo_flags |= TOMOYO_TASK_IS_EXECUTE_HANDLER;
1740          /* Mark the current process as normal process. */          /* Mark the current process as normal process. */
1741          else          else
1742                  task->tomoyo_flags &= ~TOMOYO_TASK_IS_EXECUTE_HANDLER;                  task->tomoyo_flags &= ~TOMOYO_TASK_IS_EXECUTE_HANDLER;
1743     out:
1744            ccs_unregister_next_domain();
1745          ccs_free(eh_path);          ccs_free(eh_path);
1746          ccs_free(tmp);          ccs_free(tmp);
1747          return retval;          return retval;
# Line 1693  int search_binary_handler_with_transitio Line 1761  int search_binary_handler_with_transitio
1761                                            struct pt_regs *regs)                                            struct pt_regs *regs)
1762  {  {
1763  #ifdef CONFIG_SAKURA  #ifdef CONFIG_SAKURA
1764            /* Clear manager flag. */
1765            current->tomoyo_flags &= ~CCS_TASK_IS_POLICY_MANAGER;
1766          ccs_load_policy(bprm->filename);          ccs_load_policy(bprm->filename);
1767  #endif  #endif
1768          return search_binary_handler(bprm, regs);          return search_binary_handler(bprm, regs);

Legend:
Removed from v.1561  
changed lines
  Added in v.2019

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