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

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 1695 by kumaneko, Sat Oct 11 08:46:59 2008 UTC revision 2411 by kumaneko, Fri Apr 10 01:54:30 2009 UTC
# Line 3  Line 3 
3   *   *
4   * Implementation of the Domain-Based Mandatory Access Control.   * Implementation of the Domain-Based Mandatory Access Control.
5   *   *
6   * Copyright (C) 2005-2008  NTT DATA CORPORATION   * Copyright (C) 2005-2009  NTT DATA CORPORATION
7   *   *
8   * Version: 1.6.5-pre   2008/10/11   * Version: 1.6.7+   2009/04/10
9   *   *
10   * This file is applicable to both 2.4.30 and 2.6.11 and later.   * This file is applicable to both 2.4.30 and 2.6.11 and later.
11   * See README.ccs for ChangeLog.   * See README.ccs for ChangeLog.
# Line 16  Line 16 
16  #include <linux/tomoyo.h>  #include <linux/tomoyo.h>
17  #include <linux/realpath.h>  #include <linux/realpath.h>
18  #include <linux/highmem.h>  #include <linux/highmem.h>
 #include <linux/binfmts.h>  
19  #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 5, 0)  #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 5, 0)
20  #include <linux/namei.h>  #include <linux/namei.h>
21  #include <linux/mount.h>  #include <linux/mount.h>
22  #endif  #endif
23    #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 30)
24    #include <linux/fs_struct.h>
25    #endif
26    
27  /* For compatibility with older kernels. */  /* For compatibility with older kernels. */
28  #ifndef for_each_process  #ifndef for_each_process
# Line 30  Line 32 
32  /* Variables definitions.*/  /* Variables definitions.*/
33    
34  /* The initial domain. */  /* The initial domain. */
35  struct domain_info KERNEL_DOMAIN;  struct ccs_domain_info ccs_kernel_domain;
36    
37  /* The list for "struct domain_info". */  /* The list for "struct ccs_domain_info". */
38  LIST1_HEAD(domain_list);  LIST1_HEAD(ccs_domain_list);
39    
40  #ifdef CONFIG_TOMOYO  #ifdef CONFIG_TOMOYO
41    
42  /* Domain creation lock. */  /* Domain creation lock. */
43  static DEFINE_MUTEX(new_domain_assign_lock);  static DEFINE_MUTEX(ccs_domain_list_lock);
44    
45  /* Structure for "initialize_domain" and "no_initialize_domain" keyword. */  /* Structure for "initialize_domain" and "no_initialize_domain" keyword. */
46  struct domain_initializer_entry {  struct ccs_domain_initializer_entry {
47          struct list1_head list;          struct list1_head list;
48          const struct path_info *domainname;    /* This may be NULL */          const struct ccs_path_info *domainname;    /* This may be NULL */
49          const struct path_info *program;          const struct ccs_path_info *program;
50          bool is_deleted;          bool is_deleted;
51          bool is_not;       /* True if this entry is "no_initialize_domain".  */          bool is_not;       /* True if this entry is "no_initialize_domain".  */
52          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(). */
53  };  };
54    
55  /* Structure for "keep_domain" and "no_keep_domain" keyword. */  /* Structure for "keep_domain" and "no_keep_domain" keyword. */
56  struct domain_keeper_entry {  struct ccs_domain_keeper_entry {
57          struct list1_head list;          struct list1_head list;
58          const struct path_info *domainname;          const struct ccs_path_info *domainname;
59          const struct path_info *program;       /* This may be NULL */          const struct ccs_path_info *program;       /* This may be NULL */
60          bool is_deleted;          bool is_deleted;
61          bool is_not;       /* True if this entry is "no_keep_domain".        */          bool is_not;       /* True if this entry is "no_keep_domain".        */
62          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(). */
63  };  };
64    
65  /* Structure for "aggregator" keyword. */  /* Structure for "aggregator" keyword. */
66  struct aggregator_entry {  struct ccs_aggregator_entry {
67          struct list1_head list;          struct list1_head list;
68          const struct path_info *original_name;          const struct ccs_path_info *original_name;
69          const struct path_info *aggregated_name;          const struct ccs_path_info *aggregated_name;
70          bool is_deleted;          bool is_deleted;
71  };  };
72    
73  /* Structure for "alias" keyword. */  /* Structure for "alias" keyword. */
74  struct alias_entry {  struct ccs_alias_entry {
75          struct list1_head list;          struct list1_head list;
76          const struct path_info *original_name;          const struct ccs_path_info *original_name;
77          const struct path_info *aliased_name;          const struct ccs_path_info *aliased_name;
78          bool is_deleted;          bool is_deleted;
79  };  };
80    
81  /**  /**
82   * ccs_set_domain_flag - Set or clear domain's attribute flags.   * ccs_set_domain_flag - Set or clear domain's attribute flags.
83   *   *
84   * @domain:    Pointer to "struct domain_info".   * @domain:    Pointer to "struct ccs_domain_info".
85   * @is_delete: True if it is a delete request.   * @is_delete: True if it is a delete request.
86   * @flags:     Flags to set or clear.   * @flags:     Flags to set or clear.
87   *   *
88   * Returns nothing.   * Returns nothing.
89   */   */
90  void ccs_set_domain_flag(struct domain_info *domain, const bool is_delete,  void ccs_set_domain_flag(struct ccs_domain_info *domain, const bool is_delete,
91                           const u8 flags)                           const u8 flags)
92  {  {
93          mutex_lock(&new_domain_assign_lock);          /* We need to serialize because this is bitfield operation. */
94            static DEFINE_SPINLOCK(lock);
95            /***** CRITICAL SECTION START *****/
96            spin_lock(&lock);
97          if (!is_delete)          if (!is_delete)
98                  domain->flags |= flags;                  domain->flags |= flags;
99          else          else
100                  domain->flags &= ~flags;                  domain->flags &= ~flags;
101          mutex_unlock(&new_domain_assign_lock);          spin_unlock(&lock);
102            /***** CRITICAL SECTION END *****/
103  }  }
104    
105  /**  /**
106   * ccs_get_last_name - Get last component of a domainname.   * ccs_get_last_name - Get last component of a domainname.
107   *   *
108   * @domain: Pointer to "struct domain_info".   * @domain: Pointer to "struct ccs_domain_info".
109   *   *
110   * Returns the last component of the domainname.   * Returns the last component of the domainname.
111   */   */
112  const char *ccs_get_last_name(const struct domain_info *domain)  const char *ccs_get_last_name(const struct ccs_domain_info *domain)
113  {  {
114          const char *cp0 = domain->domainname->name;          const char *cp0 = domain->domainname->name;
115          const char *cp1 = strrchr(cp0, ' ');          const char *cp1 = strrchr(cp0, ' ');
# Line 115  const char *ccs_get_last_name(const stru Line 121  const char *ccs_get_last_name(const stru
121  /**  /**
122   * ccs_add_domain_acl - Add the given ACL to the given domain.   * ccs_add_domain_acl - Add the given ACL to the given domain.
123   *   *
124   * @domain: Pointer to "struct domain_info". May be NULL.   * @domain: Pointer to "struct ccs_domain_info". May be NULL.
125   * @acl:    Pointer to "struct acl_info".   * @acl:    Pointer to "struct ccs_acl_info".
126   *   *
127   * Returns 0.   * Returns 0.
128   */   */
129  int ccs_add_domain_acl(struct domain_info *domain, struct acl_info *acl)  int ccs_add_domain_acl(struct ccs_domain_info *domain, struct ccs_acl_info *acl)
130  {  {
131          if (domain) {          if (domain) {
132                  /*                  /*
# Line 143  int ccs_add_domain_acl(struct domain_inf Line 149  int ccs_add_domain_acl(struct domain_inf
149  /**  /**
150   * ccs_del_domain_acl - Delete the given ACL from the domain.   * ccs_del_domain_acl - Delete the given ACL from the domain.
151   *   *
152   * @acl: Pointer to "struct acl_info". May be NULL.   * @acl: Pointer to "struct ccs_acl_info". May be NULL.
153   *   *
154   * Returns 0.   * Returns 0.
155   */   */
156  int ccs_del_domain_acl(struct acl_info *acl)  int ccs_del_domain_acl(struct ccs_acl_info *acl)
157  {  {
158          if (acl)          if (acl)
159                  acl->type |= ACL_DELETED;                  acl->type |= ACL_DELETED;
# Line 156  int ccs_del_domain_acl(struct acl_info * Line 162  int ccs_del_domain_acl(struct acl_info *
162  }  }
163    
164  /**  /**
165   * audit_execute_handler_log - Audit execute_handler log.   * ccs_audit_execute_handler_log - Audit execute_handler log.
166   *   *
167     * @ee:         Pointer to "struct ccs_execve_entry".
168   * @is_default: True if it is "execute_handler" log.   * @is_default: True if it is "execute_handler" log.
  * @handler:    The realpath of the handler.  
  * @bprm:       Pointer to "struct linux_binprm".  
169   *   *
170   * Returns 0 on success, negative value otherwise.   * Returns 0 on success, negative value otherwise.
171   */   */
172  static int audit_execute_handler_log(const bool is_default,  static int ccs_audit_execute_handler_log(struct ccs_execve_entry *ee,
173                                       const char *handler,                                           const bool is_default)
                                      struct linux_binprm *bprm)  
174  {  {
175          struct ccs_request_info r;          struct ccs_request_info *r = &ee->r;
176          ccs_init_request_info(&r, NULL, CCS_TOMOYO_MAC_FOR_FILE);          const char *handler = ee->handler->name;
177          r.bprm = bprm;          r->mode = ccs_check_flags(r->domain, CCS_MAC_FOR_FILE);
178          return ccs_write_audit_log(true, &r, "%s %s\n",          return ccs_write_audit_log(true, r, "%s %s\n",
179                                     is_default ? KEYWORD_EXECUTE_HANDLER :                                     is_default ? KEYWORD_EXECUTE_HANDLER :
180                                     KEYWORD_DENIED_EXECUTE_HANDLER, handler);                                     KEYWORD_DENIED_EXECUTE_HANDLER, handler);
181  }  }
182    
183  /**  /**
184   * audit_domain_creation_log - Audit domain creation log.   * ccs_audit_domain_creation_log - Audit domain creation log.
185   *   *
186   * @domain:  Pointer to "struct domain_info".   * @domain:  Pointer to "struct ccs_domain_info".
187   *   *
188   * Returns 0 on success, negative value otherwise.   * Returns 0 on success, negative value otherwise.
189   */   */
190  static int audit_domain_creation_log(struct domain_info *domain)  static int ccs_audit_domain_creation_log(struct ccs_domain_info *domain)
191  {  {
192          struct ccs_request_info r;          struct ccs_request_info r;
193          ccs_init_request_info(&r, domain, CCS_TOMOYO_MAC_FOR_FILE);          ccs_init_request_info(&r, domain, CCS_MAC_FOR_FILE);
194          return ccs_write_audit_log(false, &r, "use_profile %u\n", r.profile);          return ccs_write_audit_log(false, &r, "use_profile %u\n", r.profile);
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 203  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 231  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 251  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 260  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 269  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 285  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 293  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 307  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 323  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 350  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 363  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 390  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 410  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 419  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 432  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 448  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 464  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 472  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 481  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 506  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 518  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 536  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 553  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 562  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 571  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 587  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 600  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 615  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 633  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 650  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 659  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 668  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 684  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 697  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 handler. */
   
 /* #define DEBUG_DOMAIN_UNDELETE */  
712    
713  /**  /**
714   * ccs_delete_domain - Delete a domain.   * ccs_delete_domain - Delete a domain.
# Line 713  int ccs_write_aggregator_policy(char *da Line 719  int ccs_write_aggregator_policy(char *da
719   */   */
720  int ccs_delete_domain(char *domainname)  int ccs_delete_domain(char *domainname)
721  {  {
722          struct domain_info *domain;          struct ccs_domain_info *domain;
723          struct path_info name;          struct ccs_path_info name;
724          name.name = domainname;          name.name = domainname;
725          ccs_fill_path_info(&name);          ccs_fill_path_info(&name);
726          mutex_lock(&new_domain_assign_lock);          mutex_lock(&ccs_domain_list_lock);
 #ifdef DEBUG_DOMAIN_UNDELETE  
         printk(KERN_DEBUG "ccs_delete_domain %s\n", domainname);  
         list1_for_each_entry(domain, &domain_list, list) {  
                 if (ccs_pathcmp(domain->domainname, &name))  
                         continue;  
                 printk(KERN_DEBUG "List: %p %u\n", domain, domain->is_deleted);  
         }  
 #endif  
727          /* Is there an active domain? */          /* Is there an active domain? */
728          list1_for_each_entry(domain, &domain_list, list) {          list1_for_each_entry(domain, &ccs_domain_list, list) {
729                  struct domain_info *domain2;                  /* Never delete ccs_kernel_domain */
730                  /* Never delete KERNEL_DOMAIN */                  if (domain == &ccs_kernel_domain)
                 if (domain == &KERNEL_DOMAIN)  
731                          continue;                          continue;
732                  if (domain->is_deleted ||                  if (domain->is_deleted ||
733                      ccs_pathcmp(domain->domainname, &name))                      ccs_pathcmp(domain->domainname, &name))
734                          continue;                          continue;
735                  /* Mark already deleted domains as non undeletable. */                  domain->is_deleted = true;
                 list1_for_each_entry(domain2, &domain_list, list) {  
                         if (!domain2->is_deleted ||  
                             ccs_pathcmp(domain2->domainname, &name))  
                                 continue;  
 #ifdef DEBUG_DOMAIN_UNDELETE  
                         if (domain2->is_deleted != 255)  
                                 printk(KERN_DEBUG  
                                        "Marked %p as non undeletable\n",  
                                        domain2);  
 #endif  
                         domain2->is_deleted = 255;  
                 }  
                 /* Delete and mark active domain as undeletable. */  
                 domain->is_deleted = 1;  
 #ifdef DEBUG_DOMAIN_UNDELETE  
                 printk(KERN_DEBUG "Marked %p as undeletable\n", domain);  
 #endif  
736                  break;                  break;
737          }          }
738          mutex_unlock(&new_domain_assign_lock);          mutex_unlock(&ccs_domain_list_lock);
739          return 0;          return 0;
740  }  }
741    
742  /**  /**
  * ccs_undelete_domain - Undelete a domain.  
  *  
  * @domainname: The name of domain.  
  *  
  * Returns pointer to "struct domain_info" on success, NULL otherwise.  
  */  
 struct domain_info *ccs_undelete_domain(const char *domainname)  
 {  
         struct domain_info *domain;  
         struct domain_info *candidate_domain = NULL;  
         struct path_info name;  
         name.name = domainname;  
         ccs_fill_path_info(&name);  
         mutex_lock(&new_domain_assign_lock);  
 #ifdef DEBUG_DOMAIN_UNDELETE  
         printk(KERN_DEBUG "ccs_undelete_domain %s\n", domainname);  
         list1_for_each_entry(domain, &domain_list, list) {  
                 if (ccs_pathcmp(domain->domainname, &name))  
                         continue;  
                 printk(KERN_DEBUG "List: %p %u\n", domain, domain->is_deleted);  
         }  
 #endif  
         list1_for_each_entry(domain, &domain_list, list) {  
                 if (ccs_pathcmp(&name, domain->domainname))  
                         continue;  
                 if (!domain->is_deleted) {  
                         /* This domain is active. I can't undelete. */  
                         candidate_domain = NULL;  
 #ifdef DEBUG_DOMAIN_UNDELETE  
                         printk(KERN_DEBUG "%p is active. I can't undelete.\n",  
                                domain);  
 #endif  
                         break;  
                 }  
                 /* Is this domain undeletable? */  
                 if (domain->is_deleted == 1)  
                         candidate_domain = domain;  
         }  
         if (candidate_domain) {  
                 candidate_domain->is_deleted = 0;  
 #ifdef DEBUG_DOMAIN_UNDELETE  
                 printk(KERN_DEBUG "%p was undeleted.\n", candidate_domain);  
 #endif  
         }  
         mutex_unlock(&new_domain_assign_lock);  
         return candidate_domain;  
 }  
   
 /**  
743   * ccs_find_or_assign_new_domain - Create a domain.   * ccs_find_or_assign_new_domain - Create a domain.
744   *   *
745   * @domainname: The name of domain.   * @domainname: The name of domain.
746   * @profile:    Profile number to assign if the domain was newly created.   * @profile:    Profile number to assign if the domain was newly created.
747   *   *
748   * Returns pointer to "struct domain_info" on success, NULL otherwise.   * Returns pointer to "struct ccs_domain_info" on success, NULL otherwise.
749   */   */
750  struct domain_info *ccs_find_or_assign_new_domain(const char *domainname,  struct ccs_domain_info *ccs_find_or_assign_new_domain(const char *domainname,
751                                                    const u8 profile)                                                    const u8 profile)
752  {  {
753          struct domain_info *domain = NULL;          struct ccs_domain_info *domain = NULL;
754          const struct path_info *saved_domainname;          const struct ccs_path_info *saved_domainname;
755          mutex_lock(&new_domain_assign_lock);          mutex_lock(&ccs_domain_list_lock);
756          domain = ccs_find_domain(domainname);          domain = ccs_find_domain(domainname);
757          if (domain)          if (domain)
758                  goto out;                  goto out;
# Line 831  struct domain_info *ccs_find_or_assign_n Line 762  struct domain_info *ccs_find_or_assign_n
762          if (!saved_domainname)          if (!saved_domainname)
763                  goto out;                  goto out;
764          /* Can I reuse memory of deleted domain? */          /* Can I reuse memory of deleted domain? */
765          list1_for_each_entry(domain, &domain_list, list) {          list1_for_each_entry(domain, &ccs_domain_list, list) {
766                  struct task_struct *p;                  struct task_struct *p;
767                  struct acl_info *ptr;                  struct ccs_acl_info *ptr;
768                  bool flag;                  bool flag;
769                  if (!domain->is_deleted ||                  if (!domain->is_deleted ||
770                      domain->domainname != saved_domainname)                      domain->domainname != saved_domainname)
# Line 842  struct domain_info *ccs_find_or_assign_n Line 773  struct domain_info *ccs_find_or_assign_n
773                  /***** CRITICAL SECTION START *****/                  /***** CRITICAL SECTION START *****/
774                  read_lock(&tasklist_lock);                  read_lock(&tasklist_lock);
775                  for_each_process(p) {                  for_each_process(p) {
776                          if (p->domain_info != domain)                          if (ccs_task_domain(p) != domain)
777                                  continue;                                  continue;
778                          flag = true;                          flag = true;
779                          break;                          break;
# Line 851  struct domain_info *ccs_find_or_assign_n Line 782  struct domain_info *ccs_find_or_assign_n
782                  /***** CRITICAL SECTION END *****/                  /***** CRITICAL SECTION END *****/
783                  if (flag)                  if (flag)
784                          continue;                          continue;
 #ifdef DEBUG_DOMAIN_UNDELETE  
                 printk(KERN_DEBUG "Reusing %p %s\n", domain,  
                        domain->domainname->name);  
 #endif  
785                  list1_for_each_entry(ptr, &domain->acl_info_list, list) {                  list1_for_each_entry(ptr, &domain->acl_info_list, list) {
786                          ptr->type |= ACL_DELETED;                          ptr->type |= ACL_DELETED;
787                  }                  }
788                  /*                  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;  
789                  domain->profile = profile;                  domain->profile = profile;
790                  domain->quota_warned = false;                  domain->quota_warned = false;
791                  mb(); /* Avoid out-of-order execution. */                  mb(); /* Avoid out-of-order execution. */
792                  domain->is_deleted = 0;                  domain->is_deleted = false;
793                  goto out;                  goto out;
794          }          }
795          /* No memory reusable. Create using new memory. */          /* No memory reusable. Create using new memory. */
# Line 875  struct domain_info *ccs_find_or_assign_n Line 798  struct domain_info *ccs_find_or_assign_n
798                  INIT_LIST1_HEAD(&domain->acl_info_list);                  INIT_LIST1_HEAD(&domain->acl_info_list);
799                  domain->domainname = saved_domainname;                  domain->domainname = saved_domainname;
800                  domain->profile = profile;                  domain->profile = profile;
801                  list1_add_tail_mb(&domain->list, &domain_list);                  list1_add_tail_mb(&domain->list, &ccs_domain_list);
802          }          }
803   out:   out:
804          mutex_unlock(&new_domain_assign_lock);          mutex_unlock(&ccs_domain_list_lock);
805          return domain;          return domain;
806  }  }
807    
808  /**  /**
809   * get_argv0 - Get argv[0].   * ccs_get_argv0 - Get argv[0].
810   *   *
811   * @bprm: Pointer to "struct linux_binprm".   * @ee: Pointer to "struct ccs_execve_entry".
  * @tmp:  Buffer for temporal use.  
812   *   *
813   * Returns true on success, false otherwise.   * Returns true on success, false otherwise.
814   */   */
815  static bool get_argv0(struct linux_binprm *bprm, struct ccs_page_buffer *tmp)  static bool ccs_get_argv0(struct ccs_execve_entry *ee)
816  {  {
817          char *arg_ptr = tmp->buffer;          struct linux_binprm *bprm = ee->bprm;
818            char *arg_ptr = ee->tmp;
819          int arg_len = 0;          int arg_len = 0;
820          unsigned long pos = bprm->p;          unsigned long pos = bprm->p;
         int i = pos / PAGE_SIZE;  
821          int offset = pos % PAGE_SIZE;          int offset = pos % PAGE_SIZE;
822          bool done = false;          bool done = false;
823          if (!bprm->argc)          if (!bprm->argc)
824                  goto out;                  goto out;
825          while (1) {          while (1) {
826                  struct page *page;                  if (!ccs_dump_page(bprm, pos, &ee->dump))
                 const char *kaddr;  
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 23) && defined(CONFIG_MMU)  
                 if (get_user_pages(current, bprm->mm, pos, 1, 0, 1, &page,  
                                    NULL) <= 0)  
827                          goto out;                          goto out;
828                  pos += PAGE_SIZE - offset;                  pos += PAGE_SIZE - offset;
 #else  
                 page = bprm->page[i];  
 #endif  
                 /* Map. */  
                 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;  
                 }  
829                  /* Read. */                  /* Read. */
830                  while (offset < PAGE_SIZE) {                  while (offset < PAGE_SIZE) {
831                            const char *kaddr = ee->dump.data;
832                          const unsigned char c = kaddr[offset++];                          const unsigned char c = kaddr[offset++];
833                          if (c && arg_len < CCS_MAX_PATHNAME_LEN - 10) {                          if (c && arg_len < CCS_MAX_PATHNAME_LEN - 10) {
834                                  if (c == '\\') {                                  if (c == '\\') {
# Line 943  static bool get_argv0(struct linux_binpr Line 851  static bool get_argv0(struct linux_binpr
851                                  break;                                  break;
852                          }                          }
853                  }                  }
                 /* Unmap. */  
                 kunmap(page);  
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 23) && defined(CONFIG_MMU)  
                 put_page(page);  
 #endif  
                 i++;  
854                  offset = 0;                  offset = 0;
855                  if (done)                  if (done)
856                          break;                          break;
# Line 959  static bool get_argv0(struct linux_binpr Line 861  static bool get_argv0(struct linux_binpr
861  }  }
862    
863  /**  /**
864   * find_next_domain - Find a domain.   * ccs_find_next_domain - Find a domain.
865   *   *
866   * @r:       Pointer to "struct ccs_request_info".   * @ee: Pointer to "struct ccs_execve_entry".
  * @handler: Pathname to verify. May be NULL.  
867   *   *
868   * Returns 0 on success, negative value otherwise.   * Returns 0 on success, negative value otherwise.
869   */   */
870  static int find_next_domain(struct ccs_request_info *r,  static int ccs_find_next_domain(struct ccs_execve_entry *ee)
                             const struct path_info *handler)  
871  {  {
872          /*          struct ccs_request_info *r = &ee->r;
873           * This function assumes that the size of buffer returned by          const struct ccs_path_info *handler = ee->handler;
874           * ccs_realpath() = CCS_MAX_PATHNAME_LEN.          struct ccs_domain_info *domain = NULL;
          */  
         struct domain_info *domain = NULL;  
875          const char *old_domain_name = r->domain->domainname->name;          const char *old_domain_name = r->domain->domainname->name;
876          struct linux_binprm *bprm = r->bprm;          struct linux_binprm *bprm = ee->bprm;
         struct ccs_page_buffer *tmp = r->obj->tmp;  
         const char *original_name = bprm->filename;  
877          const u8 mode = r->mode;          const u8 mode = r->mode;
878          const bool is_enforce = (mode == 3);          const bool is_enforce = (mode == 3);
879          const u32 tomoyo_flags = r->tomoyo_flags;          const u32 ccs_flags = current->ccs_flags;
880          char *new_domain_name = NULL;          char *new_domain_name = NULL;
881          char *real_program_name = NULL;          struct ccs_path_info rn; /* real name */
882          char *symlink_program_name = NULL;          struct ccs_path_info sn; /* symlink name */
883          struct path_info rn; /* real name */          struct ccs_path_info ln; /* last name */
         struct path_info sn; /* symlink name */  
         struct path_info ln; /* last name */  
884          int retval;          int retval;
   
         {  
                 /*  
                  * Built-in initializers. This is needed because policies are  
                  * not loaded until starting /sbin/init.  
                  */  
                 static bool first = true;  
                 if (first) {  
                         update_domain_initializer_entry(NULL, "/sbin/hotplug",  
                                                         false, false);  
                         update_domain_initializer_entry(NULL, "/sbin/modprobe",  
                                                         false, false);  
                         first = false;  
                 }  
         }  
   
885   retry:   retry:
886          current->tomoyo_flags = tomoyo_flags;          current->ccs_flags = ccs_flags;
887          r->tomoyo_flags = tomoyo_flags;          r->cond = NULL;
888          /* Get ccs_realpath of program. */          /* Get realpath of program and symbolic link. */
889          retval = -ENOENT; /* I hope ccs_realpath() won't fail with -ENOMEM. */          retval = ccs_realpath_both(bprm->filename, ee);
890          ccs_free(real_program_name);          if (retval < 0)
         real_program_name = ccs_realpath(original_name);  
         if (!real_program_name)  
                 goto out;  
         /* Get ccs_realpath of symbolic link. */  
         ccs_free(symlink_program_name);  
         symlink_program_name = ccs_realpath_nofollow(original_name);  
         if (!symlink_program_name)  
891                  goto out;                  goto out;
892    
893          rn.name = real_program_name;          rn.name = ee->program_path;
894          ccs_fill_path_info(&rn);          ccs_fill_path_info(&rn);
895          sn.name = symlink_program_name;          sn.name = ee->tmp;
896          ccs_fill_path_info(&sn);          ccs_fill_path_info(&sn);
897          ln.name = ccs_get_last_name(r->domain);          ln.name = ccs_get_last_name(r->domain);
898          ccs_fill_path_info(&ln);          ccs_fill_path_info(&ln);
# Line 1042  static int find_next_domain(struct ccs_r Line 913  static int find_next_domain(struct ccs_r
913    
914          /* Check 'alias' directive. */          /* Check 'alias' directive. */
915          if (ccs_pathcmp(&rn, &sn)) {          if (ccs_pathcmp(&rn, &sn)) {
916                  struct alias_entry *ptr;                  struct ccs_alias_entry *ptr;
917                  /* Is this program allowed to be called via symbolic links? */                  /* Is this program allowed to be called via symbolic links? */
918                  list1_for_each_entry(ptr, &alias_list, list) {                  list1_for_each_entry(ptr, &ccs_alias_list, list) {
919                          if (ptr->is_deleted ||                          if (ptr->is_deleted ||
920                              ccs_pathcmp(&rn, ptr->original_name) ||                              ccs_pathcmp(&rn, ptr->original_name) ||
921                              ccs_pathcmp(&sn, ptr->aliased_name))                              ccs_pathcmp(&sn, ptr->aliased_name))
922                                  continue;                                  continue;
923                          memset(real_program_name, 0, CCS_MAX_PATHNAME_LEN);                          strncpy(ee->program_path, ptr->aliased_name->name,
                         strncpy(real_program_name, ptr->aliased_name->name,  
924                                  CCS_MAX_PATHNAME_LEN - 1);                                  CCS_MAX_PATHNAME_LEN - 1);
925                          ccs_fill_path_info(&rn);                          ccs_fill_path_info(&rn);
926                          break;                          break;
927                  }                  }
928          }          }
929            /* sn will be overwritten after here. */
930    
931          /* Compare basename of real_program_name and argv[0] */          /* Compare basename of program_path and argv[0] */
932          r->mode = ccs_check_flags(r->domain, CCS_TOMOYO_MAC_FOR_ARGV0);          r->mode = ccs_check_flags(r->domain, CCS_MAC_FOR_ARGV0);
933          if (bprm->argc > 0 && r->mode) {          if (bprm->argc > 0 && r->mode) {
934                  char *base_argv0 = tmp->buffer;                  char *base_argv0 = ee->tmp;
935                  const char *base_filename;                  const char *base_filename;
936                  retval = -ENOMEM;                  retval = -ENOMEM;
937                  if (!get_argv0(bprm, tmp))                  if (!ccs_get_argv0(ee))
938                          goto out;                          goto out;
939                  base_filename = strrchr(real_program_name, '/');                  base_filename = strrchr(ee->program_path, '/');
940                  if (!base_filename)                  if (!base_filename)
941                          base_filename = real_program_name;                          base_filename = ee->program_path;
942                  else                  else
943                          base_filename++;                          base_filename++;
944                  if (strcmp(base_argv0, base_filename)) {                  if (strcmp(base_argv0, base_filename)) {
945                          retval = ccs_check_argv0_perm(r, &rn, base_argv0);                          retval = ccs_check_argv0_perm(r, &rn, base_argv0);
946                          if (retval == 1) {                          if (retval == 1)
                                 r->retry++;  
947                                  goto retry;                                  goto retry;
                         }  
                         r->retry = 0;  
                         r->tomoyo_flags = current->tomoyo_flags;  
948                          if (retval < 0)                          if (retval < 0)
949                                  goto out;                                  goto out;
950                  }                  }
# Line 1085  static int find_next_domain(struct ccs_r Line 952  static int find_next_domain(struct ccs_r
952    
953          /* Check 'aggregator' directive. */          /* Check 'aggregator' directive. */
954          {          {
955                  struct aggregator_entry *ptr;                  struct ccs_aggregator_entry *ptr;
956                  /* Is this program allowed to be aggregated? */                  /* Is this program allowed to be aggregated? */
957                  list1_for_each_entry(ptr, &aggregator_list, list) {                  list1_for_each_entry(ptr, &ccs_aggregator_list, list) {
958                          if (ptr->is_deleted ||                          if (ptr->is_deleted ||
959                              !ccs_path_matches_pattern(&rn, ptr->original_name))                              !ccs_path_matches_pattern(&rn, ptr->original_name))
960                                  continue;                                  continue;
961                          memset(real_program_name, 0, CCS_MAX_PATHNAME_LEN);                          strncpy(ee->program_path, ptr->aggregated_name->name,
                         strncpy(real_program_name, ptr->aggregated_name->name,  
962                                  CCS_MAX_PATHNAME_LEN - 1);                                  CCS_MAX_PATHNAME_LEN - 1);
963                          ccs_fill_path_info(&rn);                          ccs_fill_path_info(&rn);
964                          break;                          break;
# Line 1102  static int find_next_domain(struct ccs_r Line 968  static int find_next_domain(struct ccs_r
968          /* Check execute permission. */          /* Check execute permission. */
969          r->mode = mode;          r->mode = mode;
970          retval = ccs_check_exec_perm(r, &rn);          retval = ccs_check_exec_perm(r, &rn);
971          if (retval == 1) {          if (retval == 1)
                 r->retry++;  
972                  goto retry;                  goto retry;
         }  
         r->retry = 0;  
         r->tomoyo_flags = current->tomoyo_flags;  
973          if (retval < 0)          if (retval < 0)
974                  goto out;                  goto out;
975    
976   calculate_domain:   calculate_domain:
977          new_domain_name = tmp->buffer;          new_domain_name = ee->tmp;
978          if (is_domain_initializer(r->domain->domainname, &rn, &ln)) {          if (ccs_is_domain_initializer(r->domain->domainname, &rn, &ln)) {
979                  /* Transit to the child of KERNEL_DOMAIN domain. */                  /* Transit to the child of ccs_kernel_domain domain. */
980                  snprintf(new_domain_name, CCS_MAX_PATHNAME_LEN + 1,                  snprintf(new_domain_name, CCS_EXEC_TMPSIZE - 1,
981                           ROOT_NAME " " "%s", real_program_name);                           ROOT_NAME " " "%s", ee->program_path);
982          } else if (r->domain == &KERNEL_DOMAIN && !sbin_init_started) {          } else if (r->domain == &ccs_kernel_domain && !ccs_policy_loaded) {
983                  /*                  /*
984                   * Needn't to transit from kernel domain before starting                   * Needn't to transit from kernel domain before starting
985                   * /sbin/init. But transit from kernel domain if executing                   * /sbin/init. But transit from kernel domain if executing
986                   * initializers because they might start before /sbin/init.                   * initializers because they might start before /sbin/init.
987                   */                   */
988                  domain = r->domain;                  domain = r->domain;
989          } else if (is_domain_keeper(r->domain->domainname, &rn, &ln)) {          } else if (ccs_is_domain_keeper(r->domain->domainname, &rn, &ln)) {
990                  /* Keep current domain. */                  /* Keep current domain. */
991                  domain = r->domain;                  domain = r->domain;
992          } else {          } else {
993                  /* Normal domain transition. */                  /* Normal domain transition. */
994                  snprintf(new_domain_name, CCS_MAX_PATHNAME_LEN + 1,                  snprintf(new_domain_name, CCS_EXEC_TMPSIZE - 1,
995                           "%s %s", old_domain_name, real_program_name);                           "%s %s", old_domain_name, ee->program_path);
996          }          }
997          if (domain || strlen(new_domain_name) >= CCS_MAX_PATHNAME_LEN)          if (domain || strlen(new_domain_name) >= CCS_MAX_PATHNAME_LEN)
998                  goto done;                  goto done;
# Line 1141  static int find_next_domain(struct ccs_r Line 1003  static int find_next_domain(struct ccs_r
1003                  int error = ccs_check_supervisor(r,                  int error = ccs_check_supervisor(r,
1004                                                   "# wants to create domain\n"                                                   "# wants to create domain\n"
1005                                                   "%s\n", new_domain_name);                                                   "%s\n", new_domain_name);
1006                  if (error == 1) {                  if (error == 1)
                         r->retry++;  
1007                          goto retry;                          goto retry;
                 }  
                 r->retry = 0;  
1008                  if (error < 0)                  if (error < 0)
1009                          goto done;                          goto done;
1010          }          }
1011          domain = ccs_find_or_assign_new_domain(new_domain_name, r->profile);          domain = ccs_find_or_assign_new_domain(new_domain_name, r->profile);
1012          if (domain)          if (domain)
1013                  audit_domain_creation_log(domain);                  ccs_audit_domain_creation_log(domain);
1014   done:   done:
1015          if (!domain) {          if (!domain) {
1016                  printk(KERN_WARNING "TOMOYO-ERROR: Domain '%s' not defined.\n",                  printk(KERN_WARNING "TOMOYO-ERROR: Domain '%s' not defined.\n",
# Line 1167  static int find_next_domain(struct ccs_r Line 1026  static int find_next_domain(struct ccs_r
1026                  retval = 0;                  retval = 0;
1027          }          }
1028   out:   out:
         ccs_free(real_program_name);  
         ccs_free(symlink_program_name);  
1029          if (domain)          if (domain)
1030                  r->domain = domain;                  r->domain = domain;
1031          return retval;          return retval;
1032  }  }
1033    
1034  /**  /**
1035   * check_environ - Check permission for environment variable names.   * ccs_check_environ - Check permission for environment variable names.
1036   *   *
1037   * @r: Pointer to "struct ccs_request_info".   * @ee: Pointer to "struct ccs_execve_entry".
1038   *   *
1039   * Returns 0 on success, negative value otherwise.   * Returns 0 on success, negative value otherwise.
1040   */   */
1041  static int check_environ(struct ccs_request_info *r)  static int ccs_check_environ(struct ccs_execve_entry *ee)
1042  {  {
1043          struct linux_binprm *bprm = r->bprm;          struct ccs_request_info *r = &ee->r;
1044          struct ccs_page_buffer *tmp = r->obj->tmp;          struct linux_binprm *bprm = ee->bprm;
1045          char *arg_ptr = tmp->buffer;          char *arg_ptr = ee->tmp;
1046          int arg_len = 0;          int arg_len = 0;
1047          unsigned long pos = bprm->p;          unsigned long pos = bprm->p;
         int i = pos / PAGE_SIZE;  
1048          int offset = pos % PAGE_SIZE;          int offset = pos % PAGE_SIZE;
1049          int argv_count = bprm->argc;          int argv_count = bprm->argc;
1050          int envp_count = bprm->envc;          int envp_count = bprm->envc;
# Line 1197  static int check_environ(struct ccs_requ Line 1053  static int check_environ(struct ccs_requ
1053          if (!r->mode || !envp_count)          if (!r->mode || !envp_count)
1054                  return 0;                  return 0;
1055          while (error == -ENOMEM) {          while (error == -ENOMEM) {
1056                  struct page *page;                  if (!ccs_dump_page(bprm, pos, &ee->dump))
                 const char *kaddr;  
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 23) && defined(CONFIG_MMU)  
                 if (get_user_pages(current, bprm->mm, pos, 1, 0, 1, &page,  
                                    NULL) <= 0)  
1057                          goto out;                          goto out;
1058                  pos += PAGE_SIZE - offset;                  pos += PAGE_SIZE - offset;
 #else  
                 page = bprm->page[i];  
 #endif  
                 /* Map. */  
                 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;  
                 }  
1059                  /* Read. */                  /* Read. */
1060                  while (argv_count && offset < PAGE_SIZE) {                  while (argv_count && offset < PAGE_SIZE) {
1061                            const char *kaddr = ee->dump.data;
1062                          if (!kaddr[offset++])                          if (!kaddr[offset++])
1063                                  argv_count--;                                  argv_count--;
1064                  }                  }
1065                  if (argv_count)                  if (argv_count) {
1066                          goto unmap_page;                          offset = 0;
1067                            continue;
1068                    }
1069                  while (offset < PAGE_SIZE) {                  while (offset < PAGE_SIZE) {
1070                            const char *kaddr = ee->dump.data;
1071                          const unsigned char c = kaddr[offset++];                          const unsigned char c = kaddr[offset++];
1072                          if (c && arg_len < CCS_MAX_PATHNAME_LEN - 10) {                          if (c && arg_len < CCS_MAX_PATHNAME_LEN - 10) {
1073                                  if (c == '=') {                                  if (c == '=') {
# Line 1254  static int check_environ(struct ccs_requ Line 1099  static int check_environ(struct ccs_requ
1099                          }                          }
1100                          arg_len = 0;                          arg_len = 0;
1101                  }                  }
  unmap_page:  
                 /* Unmap. */  
                 kunmap(page);  
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 23) && defined(CONFIG_MMU)  
                 put_page(page);  
 #endif  
                 i++;  
1102                  offset = 0;                  offset = 0;
1103          }          }
1104   out:   out:
# Line 1270  static int check_environ(struct ccs_requ Line 1108  static int check_environ(struct ccs_requ
1108  }  }
1109    
1110  /**  /**
1111   * unescape - Unescape escaped string.   * ccs_unescape - Unescape escaped string.
1112   *   *
1113   * @dest: String to unescape.   * @dest: String to unescape.
1114   *   *
1115   * Returns nothing.   * Returns nothing.
1116   */   */
1117  static void unescape(unsigned char *dest)  static void ccs_unescape(unsigned char *dest)
1118  {  {
1119          unsigned char *src = dest;          unsigned char *src = dest;
1120          unsigned char c;          unsigned char c;
1121          unsigned char d;          unsigned char d;
1122          unsigned char e;          unsigned char e;
1123          while ((c = *src++) != '\0') {          while (1) {
1124                    c = *src++;
1125                    if (!c)
1126                            break;
1127                  if (c != '\\') {                  if (c != '\\') {
1128                          *dest++ = c;                          *dest++ = c;
1129                          continue;                          continue;
# Line 1306  static void unescape(unsigned char *dest Line 1147  static void unescape(unsigned char *dest
1147  }  }
1148    
1149  /**  /**
1150   * root_depth - Get number of directories to strip.   * ccs_root_depth - Get number of directories to strip.
1151   *   *
1152   * @dentry: Pointer to "struct dentry".   * @dentry: Pointer to "struct dentry".
1153   * @vfsmnt: Pointer to "struct vfsmount".   * @vfsmnt: Pointer to "struct vfsmount".
1154   *   *
1155   * Returns number of directories to strip.   * Returns number of directories to strip.
1156   */   */
1157  static inline int root_depth(struct dentry *dentry, struct vfsmount *vfsmnt)  static inline int ccs_root_depth(struct dentry *dentry, struct vfsmount *vfsmnt)
1158  {  {
1159          int depth = 0;          int depth = 0;
1160          /***** CRITICAL SECTION START *****/          /***** CRITICAL SECTION START *****/
# Line 1336  static inline int root_depth(struct dent Line 1177  static inline int root_depth(struct dent
1177  }  }
1178    
1179  /**  /**
1180   * get_root_depth - return the depth of root directory.   * ccs_get_root_depth - return the depth of root directory.
1181   *   *
1182   * Returns number of directories to strip.   * Returns number of directories to strip.
1183   */   */
1184  static int get_root_depth(void)  static int ccs_get_root_depth(void)
1185  {  {
1186          int depth;          int depth;
1187          struct dentry *dentry;          struct dentry *dentry;
# Line 1361  static int get_root_depth(void) Line 1202  static int get_root_depth(void)
1202  #endif  #endif
1203          read_unlock(&current->fs->lock);          read_unlock(&current->fs->lock);
1204          /***** CRITICAL SECTION END *****/          /***** CRITICAL SECTION END *****/
1205          depth = root_depth(dentry, vfsmnt);          depth = ccs_root_depth(dentry, vfsmnt);
1206  #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)  #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)
1207          path_put(&root);          path_put(&root);
1208  #else  #else
# Line 1371  static int get_root_depth(void) Line 1212  static int get_root_depth(void)
1212          return depth;          return depth;
1213  }  }
1214    
1215    static LIST_HEAD(ccs_execve_list);
1216    static DEFINE_SPINLOCK(ccs_execve_list_lock);
1217    
1218    /**
1219     * ccs_allocate_execve_entry - Allocate memory for execve().
1220     *
1221     * Returns pointer to "struct ccs_execve_entry" on success, NULL otherwise.
1222     */
1223    static struct ccs_execve_entry *ccs_allocate_execve_entry(void)
1224    {
1225            struct ccs_execve_entry *ee = ccs_alloc(sizeof(*ee), false);
1226            if (!ee)
1227                    return NULL;
1228            memset(ee, 0, sizeof(*ee));
1229            ee->program_path = ccs_alloc(CCS_MAX_PATHNAME_LEN, false);
1230            ee->tmp = ccs_alloc(CCS_MAX_PATHNAME_LEN, false);
1231            if (!ee->program_path || !ee->tmp) {
1232                    ccs_free(ee->program_path);
1233                    ccs_free(ee->tmp);
1234                    ccs_free(ee);
1235                    return NULL;
1236            }
1237            /* ee->dump->data is allocated by ccs_dump_page(). */
1238            ee->task = current;
1239            /***** CRITICAL SECTION START *****/
1240            spin_lock(&ccs_execve_list_lock);
1241            list_add(&ee->list, &ccs_execve_list);
1242            spin_unlock(&ccs_execve_list_lock);
1243            /***** CRITICAL SECTION END *****/
1244            return ee;
1245    }
1246    
1247    /**
1248     * ccs_find_execve_entry - Find ccs_execve_entry of current process.
1249     *
1250     * Returns pointer to "struct ccs_execve_entry" on success, NULL otherwise.
1251     */
1252    static struct ccs_execve_entry *ccs_find_execve_entry(void)
1253    {
1254            struct task_struct *task = current;
1255            struct ccs_execve_entry *ee = NULL;
1256            struct ccs_execve_entry *p;
1257            /***** CRITICAL SECTION START *****/
1258            spin_lock(&ccs_execve_list_lock);
1259            list_for_each_entry(p, &ccs_execve_list, list) {
1260                    if (p->task != task)
1261                            continue;
1262                    ee = p;
1263                    break;
1264            }
1265            spin_unlock(&ccs_execve_list_lock);
1266            /***** CRITICAL SECTION END *****/
1267            return ee;
1268    }
1269    
1270    /**
1271     * ccs_free_execve_entry - Free memory for execve().
1272     *
1273     * @ee: Pointer to "struct ccs_execve_entry".
1274     */
1275    static void ccs_free_execve_entry(struct ccs_execve_entry *ee)
1276    {
1277            if (!ee)
1278                    return;
1279            /***** CRITICAL SECTION START *****/
1280            spin_lock(&ccs_execve_list_lock);
1281            list_del(&ee->list);
1282            spin_unlock(&ccs_execve_list_lock);
1283            /***** CRITICAL SECTION END *****/
1284            ccs_free(ee->program_path);
1285            ccs_free(ee->tmp);
1286            kfree(ee->dump.data);
1287            ccs_free(ee);
1288    }
1289    
1290  /**  /**
1291   * try_alt_exec - Try to start execute handler.   * ccs_try_alt_exec - Try to start execute handler.
1292   *   *
1293   * @r:           Pointer to "struct ccs_request_info".   * @ee: Pointer to "struct ccs_execve_entry".
  * @handler:     Pointer to the name of execute handler.  
  * @eh_path:     Pointer to pointer to the name of execute handler.  
1294   *   *
1295   * Returns 0 on success, negative value otherwise.   * Returns 0 on success, negative value otherwise.
1296   */   */
1297  static int try_alt_exec(struct ccs_request_info *r,  static int ccs_try_alt_exec(struct ccs_execve_entry *ee)
                         const struct path_info *handler, char **eh_path)  
1298  {  {
1299          /*          /*
1300           * Contents of modified bprm.           * Contents of modified bprm.
# Line 1397  static int try_alt_exec(struct ccs_reque Line 1310  static int try_alt_exec(struct ccs_reque
1310           * modified bprm->argv[0]           * modified bprm->argv[0]
1311           *    = the program's name specified by execute_handler           *    = the program's name specified by execute_handler
1312           * modified bprm->argv[1]           * modified bprm->argv[1]
1313           *    = current->domain_info->domainname->name           *    = ccs_current_domain()->domainname->name
1314           * modified bprm->argv[2]           * modified bprm->argv[2]
1315           *    = the current process's name           *    = the current process's name
1316           * modified bprm->argv[3]           * modified bprm->argv[3]
# Line 1419  static int try_alt_exec(struct ccs_reque Line 1332  static int try_alt_exec(struct ccs_reque
1332           * modified bprm->argv[bprm->envc + bprm->argc + 6]           * modified bprm->argv[bprm->envc + bprm->argc + 6]
1333           *     = original bprm->envp[bprm->envc - 1]           *     = original bprm->envp[bprm->envc - 1]
1334           */           */
1335          struct linux_binprm *bprm = r->bprm;          struct linux_binprm *bprm = ee->bprm;
1336          struct file *filp;          struct file *filp;
1337          int retval;          int retval;
1338          const int original_argc = bprm->argc;          const int original_argc = bprm->argc;
1339          const int original_envc = bprm->envc;          const int original_envc = bprm->envc;
1340          struct task_struct *task = current;          struct task_struct *task = current;
         char *buffer = r->obj->tmp->buffer;  
         /* Allocate memory for execute handler's pathname. */  
         char *execute_handler = ccs_alloc(sizeof(struct ccs_page_buffer));  
         *eh_path = execute_handler;  
         if (!execute_handler)  
                 return -ENOMEM;  
         strncpy(execute_handler, handler->name,  
                 sizeof(struct ccs_page_buffer) - 1);  
         unescape(execute_handler);  
1341    
1342          /* Close the requested program's dentry. */          /* Close the requested program's dentry. */
1343          allow_write_access(bprm->file);          allow_write_access(bprm->file);
1344          fput(bprm->file);          fput(bprm->file);
1345          bprm->file = NULL;          bprm->file = NULL;
1346    
1347          { /* Adjust root directory for open_exec(). */          /* Invalidate page dump cache. */
1348                  int depth = get_root_depth();          ee->dump.page = NULL;
                 char *cp = execute_handler;  
                 if (!*cp || *cp != '/')  
                         return -ENOENT;  
                 while (depth) {  
                         cp = strchr(cp + 1, '/');  
                         if (!cp)  
                                 return -ENOENT;  
                         depth--;  
                 }  
                 memmove(execute_handler, cp, strlen(cp) + 1);  
         }  
1349    
1350          /* Move envp[] to argv[] */          /* Move envp[] to argv[] */
1351          bprm->argc += bprm->envc;          bprm->argc += bprm->envc;
# Line 1460  static int try_alt_exec(struct ccs_reque Line 1353  static int try_alt_exec(struct ccs_reque
1353    
1354          /* Set argv[6] */          /* Set argv[6] */
1355          {          {
1356                  snprintf(buffer, sizeof(struct ccs_page_buffer) - 1, "%d",                  char *cp = ee->tmp;
1357                           original_envc);                  snprintf(ee->tmp, CCS_EXEC_TMPSIZE - 1, "%d", original_envc);
1358                  retval = copy_strings_kernel(1, &buffer, bprm);                  retval = copy_strings_kernel(1, &cp, bprm);
1359                  if (retval < 0)                  if (retval < 0)
1360                          goto out;                          goto out;
1361                  bprm->argc++;                  bprm->argc++;
# Line 1470  static int try_alt_exec(struct ccs_reque Line 1363  static int try_alt_exec(struct ccs_reque
1363    
1364          /* Set argv[5] */          /* Set argv[5] */
1365          {          {
1366                  snprintf(buffer, sizeof(struct ccs_page_buffer) - 1, "%d",                  char *cp = ee->tmp;
1367                           original_argc);                  snprintf(ee->tmp, CCS_EXEC_TMPSIZE - 1, "%d", original_argc);
1368                  retval = copy_strings_kernel(1, &buffer, bprm);                  retval = copy_strings_kernel(1, &cp, bprm);
1369                  if (retval < 0)                  if (retval < 0)
1370                          goto out;                          goto out;
1371                  bprm->argc++;                  bprm->argc++;
# Line 1488  static int try_alt_exec(struct ccs_reque Line 1381  static int try_alt_exec(struct ccs_reque
1381    
1382          /* Set argv[3] */          /* Set argv[3] */
1383          {          {
1384                  const u32 tomoyo_flags = task->tomoyo_flags;                  char *cp = ee->tmp;
1385                  snprintf(buffer, sizeof(struct ccs_page_buffer) - 1,                  const u32 ccs_flags = task->ccs_flags;
1386                    snprintf(ee->tmp, CCS_EXEC_TMPSIZE - 1,
1387                           "pid=%d uid=%d gid=%d euid=%d egid=%d suid=%d "                           "pid=%d uid=%d gid=%d euid=%d egid=%d suid=%d "
1388                           "sgid=%d fsuid=%d fsgid=%d state[0]=%u "                           "sgid=%d fsuid=%d fsgid=%d state[0]=%u "
1389                           "state[1]=%u state[2]=%u",                           "state[1]=%u state[2]=%u",
1390                           task->pid, task->uid, task->gid, task->euid,                           (pid_t) sys_getpid(), current_uid(), current_gid(),
1391                           task->egid, task->suid, task->sgid, task->fsuid,                           current_euid(), current_egid(), current_suid(),
1392                           task->fsgid, (u8) (tomoyo_flags >> 24),                           current_sgid(), current_fsuid(), current_fsgid(),
1393                           (u8) (tomoyo_flags >> 16), (u8) (tomoyo_flags >> 8));                           (u8) (ccs_flags >> 24), (u8) (ccs_flags >> 16),
1394                  retval = copy_strings_kernel(1, &buffer, bprm);                           (u8) (ccs_flags >> 8));
1395                    retval = copy_strings_kernel(1, &cp, bprm);
1396                  if (retval < 0)                  if (retval < 0)
1397                          goto out;                          goto out;
1398                  bprm->argc++;                  bprm->argc++;
# Line 1510  static int try_alt_exec(struct ccs_reque Line 1405  static int try_alt_exec(struct ccs_reque
1405                          retval = copy_strings_kernel(1, &exe, bprm);                          retval = copy_strings_kernel(1, &exe, bprm);
1406                          ccs_free(exe);                          ccs_free(exe);
1407                  } else {                  } else {
1408                          snprintf(buffer, sizeof(struct ccs_page_buffer) - 1,                          exe = ee->tmp;
1409                                   "<unknown>");                          strncpy(ee->tmp, "<unknown>", CCS_EXEC_TMPSIZE - 1);
1410                          retval = copy_strings_kernel(1, &buffer, bprm);                          retval = copy_strings_kernel(1, &exe, bprm);
1411                  }                  }
1412                  if (retval < 0)                  if (retval < 0)
1413                          goto out;                          goto out;
# Line 1521  static int try_alt_exec(struct ccs_reque Line 1416  static int try_alt_exec(struct ccs_reque
1416    
1417          /* Set argv[1] */          /* Set argv[1] */
1418          {          {
1419                  strncpy(buffer, task->domain_info->domainname->name,                  char *cp = ee->tmp;
1420                          sizeof(struct ccs_page_buffer) - 1);                  strncpy(ee->tmp, ccs_current_domain()->domainname->name,
1421                  retval = copy_strings_kernel(1, &buffer, bprm);                          CCS_EXEC_TMPSIZE - 1);
1422                    retval = copy_strings_kernel(1, &cp, bprm);
1423                  if (retval < 0)                  if (retval < 0)
1424                          goto out;                          goto out;
1425                  bprm->argc++;                  bprm->argc++;
# Line 1531  static int try_alt_exec(struct ccs_reque Line 1427  static int try_alt_exec(struct ccs_reque
1427    
1428          /* Set argv[0] */          /* Set argv[0] */
1429          {          {
1430                  retval = copy_strings_kernel(1, &execute_handler, bprm);                  int depth = ccs_get_root_depth();
1431                    char *cp = ee->program_path;
1432                    strncpy(cp, ee->handler->name, CCS_MAX_PATHNAME_LEN - 1);
1433                    ccs_unescape(cp);
1434                    retval = -ENOENT;
1435                    if (!*cp || *cp != '/')
1436                            goto out;
1437                    /* Adjust root directory for open_exec(). */
1438                    while (depth) {
1439                            cp = strchr(cp + 1, '/');
1440                            if (!cp)
1441                                    goto out;
1442                            depth--;
1443                    }
1444                    memmove(ee->program_path, cp, strlen(cp) + 1);
1445                    cp = ee->program_path;
1446                    retval = copy_strings_kernel(1, &cp, bprm);
1447                  if (retval < 0)                  if (retval < 0)
1448                          goto out;                          goto out;
1449                  bprm->argc++;                  bprm->argc++;
# Line 1543  static int try_alt_exec(struct ccs_reque Line 1455  static int try_alt_exec(struct ccs_reque
1455  #endif  #endif
1456    
1457          /* OK, now restart the process with execute handler program's dentry. */          /* OK, now restart the process with execute handler program's dentry. */
1458          filp = open_exec(execute_handler);          filp = open_exec(ee->program_path);
1459          if (IS_ERR(filp)) {          if (IS_ERR(filp)) {
1460                  retval = PTR_ERR(filp);                  retval = PTR_ERR(filp);
1461                  goto out;                  goto out;
1462          }          }
1463          bprm->file = filp;          bprm->file = filp;
1464          bprm->filename = execute_handler;          bprm->filename = ee->program_path;
1465  #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 5, 0)  #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 5, 0)
1466          bprm->interp = execute_handler;          bprm->interp = bprm->filename;
1467  #endif  #endif
1468          retval = prepare_binprm(bprm);          retval = prepare_binprm(bprm);
1469          if (retval < 0)          if (retval < 0)
1470                  goto out;                  goto out;
1471          task->tomoyo_flags |= CCS_DONT_SLEEP_ON_ENFORCE_ERROR;          {
1472          retval = find_next_domain(r, handler);                  /*
1473          task->tomoyo_flags &= ~CCS_DONT_SLEEP_ON_ENFORCE_ERROR;                   * Backup ee->program_path because ccs_find_next_domain() will
1474                     * overwrite ee->program_path and ee->tmp.
1475                     */
1476                    const int len = strlen(ee->program_path) + 1;
1477                    char *cp = kmalloc(len, GFP_KERNEL);
1478                    if (!cp) {
1479                            retval = -ENOMEM;
1480                            goto out;
1481                    }
1482                    memmove(cp, ee->program_path, len);
1483                    bprm->filename = cp;
1484    #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 5, 0)
1485                    bprm->interp = bprm->filename;
1486    #endif
1487                    task->ccs_flags |= CCS_DONT_SLEEP_ON_ENFORCE_ERROR;
1488                    retval = ccs_find_next_domain(ee);
1489                    task->ccs_flags &= ~CCS_DONT_SLEEP_ON_ENFORCE_ERROR;
1490                    /* Restore ee->program_path for search_binary_handler(). */
1491                    memmove(ee->program_path, cp, len);
1492                    bprm->filename = ee->program_path;
1493    #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 5, 0)
1494                    bprm->interp = bprm->filename;
1495    #endif
1496                    kfree(cp);
1497            }
1498   out:   out:
1499          return retval;          return retval;
1500  }  }
1501    
1502  /**  /**
1503   * find_execute_handler - Find an execute handler.   * ccs_find_execute_handler - Find an execute handler.
1504   *   *
1505     * @ee:   Pointer to "struct ccs_execve_entry".
1506   * @type: Type of execute handler.   * @type: Type of execute handler.
1507   *   *
1508   * Returns pointer to "struct path_info" if found, NULL otherwise.   * Returns true if found, false otherwise.
1509   */   */
1510  static const struct path_info *find_execute_handler(const u8 type)  static bool ccs_find_execute_handler(struct ccs_execve_entry *ee,
1511                                         const u8 type)
1512  {  {
1513          struct task_struct *task = current;          struct task_struct *task = current;
1514          const struct domain_info *domain = task->domain_info;          const struct ccs_domain_info *domain = ccs_current_domain();
1515          struct acl_info *ptr;          struct ccs_acl_info *ptr;
1516          /*          /*
1517           * Don't use execute handler if the current process is           * Don't use execute handler if the current process is
1518           * marked as execute handler to avoid infinite execute handler loop.           * marked as execute handler to avoid infinite execute handler loop.
1519           */           */
1520          if (task->tomoyo_flags & TOMOYO_TASK_IS_EXECUTE_HANDLER)          if (task->ccs_flags & CCS_TASK_IS_EXECUTE_HANDLER)
1521                  return NULL;                  return false;
1522          list1_for_each_entry(ptr, &domain->acl_info_list, list) {          list1_for_each_entry(ptr, &domain->acl_info_list, list) {
1523                  struct execute_handler_record *acl;                  struct ccs_execute_handler_record *acl;
1524                  if (ptr->type != type)                  if (ptr->type != type)
1525                          continue;                          continue;
1526                  acl = container_of(ptr, struct execute_handler_record, head);                  acl = container_of(ptr, struct ccs_execute_handler_record,
1527                  return acl->handler;                                     head);
1528                    ee->handler = acl->handler;
1529                    return true;
1530          }          }
1531          return NULL;          return false;
1532  }  }
1533    
 /* List of next_domain which is used for checking interpreter's permissions. */  
 struct execve_entry {  
         struct list_head list;  
         struct task_struct *task;  
         struct domain_info *next_domain;  
 };  
   
 static LIST_HEAD(execve_list);  
 static DEFINE_SPINLOCK(execve_list_lock);  
   
1534  /**  /**
1535   * ccs_register_next_domain - Remember next_domain.   * ccs_dump_page - Dump a page to buffer.
1536   *   *
1537   * @next_domain: Pointer to "struct domain_info".   * @bprm: Pointer to "struct linux_binprm".
1538     * @pos:  Location to dump.
1539     * @dump: Poiner to "struct ccs_page_dump".
1540   *   *
1541   * Returns 0 on success, -ENOMEM otherwise.   * Returns true on success, false otherwise.
1542   */   */
1543  static int ccs_register_next_domain(struct domain_info *next_domain)  bool ccs_dump_page(struct linux_binprm *bprm, unsigned long pos,
1544                       struct ccs_page_dump *dump)
1545  {  {
1546          struct execve_entry *ee = kmalloc(sizeof(*ee), GFP_KERNEL);          struct page *page;
1547          if (!ee)          /* dump->data is released by ccs_free_execve_entry(). */
1548                  return -ENOMEM;          if (!dump->data) {
1549          ee->task = current;                  dump->data = kmalloc(PAGE_SIZE, GFP_KERNEL);
1550          ee->next_domain = next_domain;                  if (!dump->data)
1551          /***** CRITICAL SECTION START *****/                          return false;
1552          spin_lock(&execve_list_lock);          }
1553          list_add(&ee->list, &execve_list);          /* Same with get_arg_page(bprm, pos, 0) in fs/exec.c */
1554          spin_unlock(&execve_list_lock);  #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 23) && defined(CONFIG_MMU)
1555          /***** CRITICAL SECTION END *****/          if (get_user_pages(current, bprm->mm, pos, 1, 0, 1, &page, NULL) <= 0)
1556          return 0;                  return false;
1557    #elif defined(RHEL_MAJOR) && RHEL_MAJOR == 5 && defined(RHEL_MINOR) && RHEL_MINOR == 3 && defined(CONFIG_MMU)
1558            if (get_user_pages(current, bprm->mm, pos, 1, 0, 1, &page, NULL) <= 0)
1559                    return false;
1560    #else
1561            page = bprm->page[pos / PAGE_SIZE];
1562    #endif
1563            if (page != dump->page) {
1564                    const unsigned int offset = pos % PAGE_SIZE;
1565                    /*
1566                     * Maybe kmap()/kunmap() should be used here.
1567                     * But remove_arg_zero() uses kmap_atomic()/kunmap_atomic().
1568                     * So do I.
1569                     */
1570                    char *kaddr = kmap_atomic(page, KM_USER0);
1571                    dump->page = page;
1572                    memcpy(dump->data + offset, kaddr + offset, PAGE_SIZE - offset);
1573                    kunmap_atomic(kaddr, KM_USER0);
1574            }
1575            /* Same with put_arg_page(page) in fs/exec.c */
1576    #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 23) && defined(CONFIG_MMU)
1577            put_page(page);
1578    #elif defined(RHEL_MAJOR) && RHEL_MAJOR == 5 && defined(RHEL_MINOR) && RHEL_MINOR == 3 && defined(CONFIG_MMU)
1579            put_page(page);
1580    #endif
1581            return true;
1582  }  }
1583    
1584  /**  /**
1585   * ccs_fetch_next_domain - Fetch next_domain from the list.   * ccs_fetch_next_domain - Fetch next_domain from the list.
1586   *   *
1587   * Returns pointer to "struct domain_info" which will be used if execve()   * Returns pointer to "struct ccs_domain_info" which will be used if execve()
1588   * succeeds. This function does not return NULL.   * succeeds. This function does not return NULL.
1589   */   */
1590  struct domain_info *ccs_fetch_next_domain(void)  struct ccs_domain_info *ccs_fetch_next_domain(void)
1591  {  {
1592          struct task_struct *task = current;          struct ccs_execve_entry *ee = ccs_find_execve_entry();
1593          struct domain_info *next_domain = task->domain_info;          struct ccs_domain_info *next_domain = NULL;
1594          struct execve_entry *p;          if (ee)
1595          /***** CRITICAL SECTION START *****/                  next_domain = ee->next_domain;
1596          spin_lock(&execve_list_lock);          if (!next_domain)
1597          list_for_each_entry(p, &execve_list, list) {                  next_domain = ccs_current_domain();
                 if (p->task != task)  
                         continue;  
                 next_domain = p->next_domain;  
                 break;  
         }  
         spin_unlock(&execve_list_lock);  
         /***** CRITICAL SECTION END *****/  
1598          return next_domain;          return next_domain;
1599  }  }
1600    
1601  /**  /**
1602   * ccs_unregister_next_domain - Forget next_domain.   * ccs_start_execve - Prepare for execve() operation.
  */  
 static void ccs_unregister_next_domain(void)  
 {  
         struct task_struct *task = current;  
         struct execve_entry *p;  
         struct execve_entry *ee = NULL;  
         /***** CRITICAL SECTION START *****/  
         spin_lock(&execve_list_lock);  
         list_for_each_entry(p, &execve_list, list) {  
                 if (p->task != task)  
                         continue;  
                 list_del(&p->list);  
                 ee = p;  
                 break;  
         }  
         spin_unlock(&execve_list_lock);  
         /***** CRITICAL SECTION END *****/  
         kfree(ee);  
 }  
   
 /**  
  * search_binary_handler_with_transition - Perform domain transition.  
1603   *   *
1604   * @bprm: Pointer to "struct linux_binprm".   * @bprm: Pointer to "struct linux_binprm".
  * @regs: Pointer to "struct pt_regs".  
1605   *   *
1606   * Returns result of search_binary_handler() on success,   * Returns 0 on success, negative value otherwise.
  * negative value otherwise.  
1607   */   */
1608  int search_binary_handler_with_transition(struct linux_binprm *bprm,  int ccs_start_execve(struct linux_binprm *bprm)
                                           struct pt_regs *regs)  
1609  {  {
1610          int retval;          int retval;
1611          struct task_struct *task = current;          struct task_struct *task = current;
1612          const struct path_info *handler;          struct ccs_execve_entry *ee = ccs_allocate_execve_entry();
1613          struct ccs_request_info r;          if (!ccs_policy_loaded)
         struct obj_info obj;  
         /*  
          * "eh_path" holds path to execute handler program.  
          * Thus, keep valid until search_binary_handler() finishes.  
          */  
         char *eh_path = NULL;  
         struct ccs_page_buffer *tmp = ccs_alloc(sizeof(struct ccs_page_buffer));  
         memset(&obj, 0, sizeof(obj));  
         if (!sbin_init_started)  
1614                  ccs_load_policy(bprm->filename);                  ccs_load_policy(bprm->filename);
1615          if (!tmp)          if (!ee)
1616                  return -ENOMEM;                  return -ENOMEM;
1617            ccs_init_request_info(&ee->r, NULL, CCS_MAC_FOR_FILE);
1618          ccs_init_request_info(&r, NULL, CCS_TOMOYO_MAC_FOR_FILE);          ee->r.ee = ee;
1619          r.bprm = bprm;          ee->bprm = bprm;
1620          r.obj = &obj;          ee->r.obj = &ee->obj;
1621          obj.path1_dentry = bprm->file->f_dentry;          ee->obj.path1_dentry = bprm->file->f_dentry;
1622          obj.path1_vfsmnt = bprm->file->f_vfsmnt;          ee->obj.path1_vfsmnt = bprm->file->f_vfsmnt;
         obj.tmp = tmp;  
   
1623          /* Clear manager flag. */          /* Clear manager flag. */
1624          task->tomoyo_flags &= ~CCS_TASK_IS_POLICY_MANAGER;          task->ccs_flags &= ~CCS_TASK_IS_POLICY_MANAGER;
1625          handler = find_execute_handler(TYPE_EXECUTE_HANDLER);          if (ccs_find_execute_handler(ee, TYPE_EXECUTE_HANDLER)) {
1626          if (handler) {                  retval = ccs_try_alt_exec(ee);
                 retval = try_alt_exec(&r, handler, &eh_path);  
1627                  if (!retval)                  if (!retval)
1628                          audit_execute_handler_log(true, handler->name, bprm);                          ccs_audit_execute_handler_log(ee, true);
1629                  goto ok;                  goto ok;
1630          }          }
1631          retval = find_next_domain(&r, NULL);          retval = ccs_find_next_domain(ee);
1632          if (retval != -EPERM)          if (retval != -EPERM)
1633                  goto ok;                  goto ok;
1634          handler = find_execute_handler(TYPE_DENIED_EXECUTE_HANDLER);          if (ccs_find_execute_handler(ee, TYPE_DENIED_EXECUTE_HANDLER)) {
1635          if (handler) {                  retval = ccs_try_alt_exec(ee);
                 retval = try_alt_exec(&r, handler, &eh_path);  
1636                  if (!retval)                  if (!retval)
1637                          audit_execute_handler_log(false, handler->name, bprm);                          ccs_audit_execute_handler_log(ee, false);
1638          }          }
1639   ok:   ok:
1640          if (retval < 0)          if (retval < 0)
1641                  goto out;                  goto out;
1642          r.mode = ccs_check_flags(r.domain, CCS_TOMOYO_MAC_FOR_ENV);          ee->r.mode = ccs_check_flags(ee->r.domain, CCS_MAC_FOR_ENV);
1643          retval = check_environ(&r);          retval = ccs_check_environ(ee);
         if (retval < 0)  
                 goto out;  
         retval = ccs_register_next_domain(r.domain);  
1644          if (retval < 0)          if (retval < 0)
1645                  goto out;                  goto out;
1646          task->tomoyo_flags |= TOMOYO_CHECK_READ_FOR_OPEN_EXEC;          ee->next_domain = ee->r.domain;
1647          retval = search_binary_handler(bprm, regs);          task->ccs_flags |= CCS_CHECK_READ_FOR_OPEN_EXEC;
1648          task->tomoyo_flags &= ~TOMOYO_CHECK_READ_FOR_OPEN_EXEC;          retval = 0;
1649     out:
1650            if (retval)
1651                    ccs_finish_execve(retval);
1652            return retval;
1653    }
1654    
1655    /**
1656     * ccs_finish_execve - Clean up execve() operation.
1657     *
1658     * @retval: Return code of an execve() operation.
1659     */
1660    void ccs_finish_execve(int retval)
1661    {
1662            struct task_struct *task = current;
1663            struct ccs_execve_entry *ee = ccs_find_execve_entry();
1664            task->ccs_flags &= ~CCS_CHECK_READ_FOR_OPEN_EXEC;
1665            if (!ee)
1666                    return;
1667          if (retval < 0)          if (retval < 0)
1668                  goto out;                  goto out;
1669          /* Proceed to next domain if execution suceeded. */          /* Proceed to next domain if execution suceeded. */
1670          task->domain_info = r.domain;          task->ccs_domain_info = ee->r.domain;
1671          mb(); /* Make domain transition visible to other CPUs. */          mb(); /* Make domain transition visible to other CPUs. */
1672          /* Mark the current process as execute handler. */          /* Mark the current process as execute handler. */
1673          if (handler)          if (ee->handler)
1674                  task->tomoyo_flags |= TOMOYO_TASK_IS_EXECUTE_HANDLER;                  task->ccs_flags |= CCS_TASK_IS_EXECUTE_HANDLER;
1675          /* Mark the current process as normal process. */          /* Mark the current process as normal process. */
1676          else          else
1677                  task->tomoyo_flags &= ~TOMOYO_TASK_IS_EXECUTE_HANDLER;                  task->ccs_flags &= ~CCS_TASK_IS_EXECUTE_HANDLER;
1678   out:   out:
1679          ccs_unregister_next_domain();          ccs_free_execve_entry(ee);
         ccs_free(eh_path);  
         ccs_free(tmp);  
         return retval;  
1680  }  }
1681    
1682  #else  #else
1683    
1684  /**  /**
1685   * search_binary_handler_with_transition - Wrapper for search_binary_handler().   * ccs_start_execve - Prepare for execve() operation.
1686   *   *
1687   * @bprm: Pointer to "struct linux_binprm".   * @bprm: Pointer to "struct linux_binprm".
  * @regs: Pointer to "struct pt_regs".  
1688   *   *
1689   * Returns the result of search_binary_handler().   * Returns 0.
1690   */   */
1691  int search_binary_handler_with_transition(struct linux_binprm *bprm,  int ccs_start_execve(struct linux_binprm *bprm)
                                           struct pt_regs *regs)  
1692  {  {
1693  #ifdef CONFIG_SAKURA  #ifdef CONFIG_SAKURA
1694          /* Clear manager flag. */          /* Clear manager flag. */
1695          current->tomoyo_flags &= ~CCS_TASK_IS_POLICY_MANAGER;          current->ccs_flags &= ~CCS_TASK_IS_POLICY_MANAGER;
1696          ccs_load_policy(bprm->filename);          if (!ccs_policy_loaded)
1697                    ccs_load_policy(bprm->filename);
1698  #endif  #endif
1699          return search_binary_handler(bprm, regs);          return 0;
1700    }
1701    
1702    /**
1703     * ccs_finish_execve - Clean up execve() operation.
1704     */
1705    void ccs_finish_execve(int retval)
1706    {
1707  }  }
1708    
1709  #endif  #endif

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

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