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

Subversion リポジトリの参照

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

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

trunk/1.6.x/ccs-patch/fs/tomoyo_domain.c revision 2219 by kumaneko, Tue Mar 3 06:30:38 2009 UTC branches/ccs-patch/fs/tomoyo_domain.c revision 2718 by kumaneko, Thu Jul 2 01:30:12 2009 UTC
# Line 5  Line 5 
5   *   *
6   * Copyright (C) 2005-2009  NTT DATA CORPORATION   * Copyright (C) 2005-2009  NTT DATA CORPORATION
7   *   *
8   * Version: 1.6.7-rc   2009/03/03   * Version: 1.7.0-pre   2009/05/28
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 20  Line 20 
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 29  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;
   
 /* The list for "struct domain_info". */  
 LIST1_HEAD(ccs_domain_list);  
   
 #ifdef CONFIG_TOMOYO  
36    
37  /* Domain creation lock. */  /* The list for "struct ccs_domain_info". */
38  static DEFINE_MUTEX(ccs_domain_list_lock);  LIST_HEAD(ccs_domain_list);
   
 /* Structure for "initialize_domain" and "no_initialize_domain" keyword. */  
 struct ccs_domain_initializer_entry {  
         struct list1_head list;  
         const struct ccs_path_info *domainname;    /* This may be NULL */  
         const struct ccs_path_info *program;  
         bool is_deleted;  
         bool is_not;       /* True if this entry is "no_initialize_domain".  */  
         bool is_last_name; /* True if the domainname is ccs_get_last_name(). */  
 };  
   
 /* Structure for "keep_domain" and "no_keep_domain" keyword. */  
 struct ccs_domain_keeper_entry {  
         struct list1_head list;  
         const struct ccs_path_info *domainname;  
         const struct ccs_path_info *program;       /* This may be NULL */  
         bool is_deleted;  
         bool is_not;       /* True if this entry is "no_keep_domain".        */  
         bool is_last_name; /* True if the domainname is ccs_get_last_name(). */  
 };  
   
 /* Structure for "aggregator" keyword. */  
 struct ccs_aggregator_entry {  
         struct list1_head list;  
         const struct ccs_path_info *original_name;  
         const struct ccs_path_info *aggregated_name;  
         bool is_deleted;  
 };  
   
 /* Structure for "alias" keyword. */  
 struct ccs_alias_entry {  
         struct list1_head list;  
         const struct ccs_path_info *original_name;  
         const struct ccs_path_info *aliased_name;  
         bool is_deleted;  
 };  
   
 /**  
  * ccs_set_domain_flag - Set or clear domain's attribute flags.  
  *  
  * @domain:    Pointer to "struct domain_info".  
  * @is_delete: True if it is a delete request.  
  * @flags:     Flags to set or clear.  
  *  
  * Returns nothing.  
  */  
 void ccs_set_domain_flag(struct domain_info *domain, const bool is_delete,  
                          const u8 flags)  
 {  
         /* We need to serialize because this is bitfield operation. */  
         static DEFINE_SPINLOCK(lock);  
         /***** CRITICAL SECTION START *****/  
         spin_lock(&lock);  
         if (!is_delete)  
                 domain->flags |= flags;  
         else  
                 domain->flags &= ~flags;  
         spin_unlock(&lock);  
         /***** CRITICAL SECTION END *****/  
 }  
39    
40  /**  /**
41   * ccs_get_last_name - Get last component of a domainname.   * ccs_get_last_name - Get last component of a domainname.
42   *   *
43   * @domain: Pointer to "struct domain_info".   * @domain: Pointer to "struct ccs_domain_info".
44   *   *
45   * Returns the last component of the domainname.   * Returns the last component of the domainname.
46   */   */
47  const char *ccs_get_last_name(const struct domain_info *domain)  const char *ccs_get_last_name(const struct ccs_domain_info *domain)
48  {  {
49          const char *cp0 = domain->domainname->name;          const char *cp0 = domain->domainname->name;
50          const char *cp1 = strrchr(cp0, ' ');          const char *cp1 = strrchr(cp0, ' ');
# Line 118  const char *ccs_get_last_name(const stru Line 56  const char *ccs_get_last_name(const stru
56  /**  /**
57   * ccs_add_domain_acl - Add the given ACL to the given domain.   * ccs_add_domain_acl - Add the given ACL to the given domain.
58   *   *
59   * @domain: Pointer to "struct domain_info". May be NULL.   * @domain: Pointer to "struct ccs_domain_info". May be NULL.
60   * @acl:    Pointer to "struct ccs_acl_info".   * @acl:    Pointer to "struct ccs_acl_info".
61   *   *
62   * Returns 0.   * Returns 0.
63   */   */
64  int ccs_add_domain_acl(struct domain_info *domain, struct ccs_acl_info *acl)  int ccs_add_domain_acl(struct ccs_domain_info *domain, struct ccs_acl_info *acl)
65  {  {
66          if (domain) {          if (domain) {
67                  /*                  if (acl->cond)
68                   * We need to serialize because this function is called by                          atomic_inc(&acl->cond->users);
69                   * various update functions.                  list_add_tail_rcu(&acl->list, &domain->acl_info_list);
                  */  
                 static DEFINE_SPINLOCK(lock);  
                 /***** CRITICAL SECTION START *****/  
                 spin_lock(&lock);  
                 list1_add_tail_mb(&acl->list, &domain->acl_info_list);  
                 spin_unlock(&lock);  
                 /***** CRITICAL SECTION END *****/  
70          } else {          } else {
71                  acl->type &= ~ACL_DELETED;                  acl->type &= ~ACL_DELETED;
72          }          }
         ccs_update_counter(CCS_UPDATES_COUNTER_DOMAIN_POLICY);  
73          return 0;          return 0;
74  }  }
75    
# Line 154  int ccs_del_domain_acl(struct ccs_acl_in Line 84  int ccs_del_domain_acl(struct ccs_acl_in
84  {  {
85          if (acl)          if (acl)
86                  acl->type |= ACL_DELETED;                  acl->type |= ACL_DELETED;
         ccs_update_counter(CCS_UPDATES_COUNTER_DOMAIN_POLICY);  
87          return 0;          return 0;
88  }  }
89    
# Line 171  static int ccs_audit_execute_handler_log Line 100  static int ccs_audit_execute_handler_log
100  {  {
101          struct ccs_request_info *r = &ee->r;          struct ccs_request_info *r = &ee->r;
102          const char *handler = ee->handler->name;          const char *handler = ee->handler->name;
103          r->mode = ccs_check_flags(r->domain, CCS_TOMOYO_MAC_FOR_FILE);          r->mode = ccs_check_flags(r->domain, CCS_MAC_FOR_FILE);
104          return ccs_write_audit_log(true, r, "%s %s\n",          return ccs_write_audit_log(true, r, "%s %s\n",
105                                     is_default ? KEYWORD_EXECUTE_HANDLER :                                     is_default ? KEYWORD_EXECUTE_HANDLER :
106                                     KEYWORD_DENIED_EXECUTE_HANDLER, handler);                                     KEYWORD_DENIED_EXECUTE_HANDLER, handler);
# Line 180  static int ccs_audit_execute_handler_log Line 109  static int ccs_audit_execute_handler_log
109  /**  /**
110   * ccs_audit_domain_creation_log - Audit domain creation log.   * ccs_audit_domain_creation_log - Audit domain creation log.
111   *   *
112   * @domain:  Pointer to "struct domain_info".   * @domain:  Pointer to "struct ccs_domain_info".
113   *   *
114   * Returns 0 on success, negative value otherwise.   * Returns 0 on success, negative value otherwise.
115   */   */
116  static int ccs_audit_domain_creation_log(struct domain_info *domain)  static int ccs_audit_domain_creation_log(struct ccs_domain_info *domain)
117  {  {
118            int error;
119          struct ccs_request_info r;          struct ccs_request_info r;
120          ccs_init_request_info(&r, domain, CCS_TOMOYO_MAC_FOR_FILE);          ccs_init_request_info(&r, domain, CCS_MAC_FOR_FILE);
121          return ccs_write_audit_log(false, &r, "use_profile %u\n", r.profile);          error = ccs_write_audit_log(false, &r, "use_profile %u\n", r.profile);
122            return error;
123  }  }
124    
125  /* The list for "struct ccs_domain_initializer_entry". */  /* The list for "struct ccs_domain_initializer_entry". */
126  static LIST1_HEAD(ccs_domain_initializer_list);  LIST_HEAD(ccs_domain_initializer_list);
127    
128  /**  /**
129   * ccs_update_domain_initializer_entry - Update "struct ccs_domain_initializer_entry" list.   * ccs_update_domain_initializer_entry - Update "struct ccs_domain_initializer_entry" list.
# Line 209  static int ccs_update_domain_initializer Line 140  static int ccs_update_domain_initializer
140                                                 const bool is_not,                                                 const bool is_not,
141                                                 const bool is_delete)                                                 const bool is_delete)
142  {  {
143          struct ccs_domain_initializer_entry *new_entry;          struct ccs_domain_initializer_entry *entry = NULL;
144          struct ccs_domain_initializer_entry *ptr;          struct ccs_domain_initializer_entry *ptr;
         static DEFINE_MUTEX(lock);  
145          const struct ccs_path_info *saved_program;          const struct ccs_path_info *saved_program;
146          const struct ccs_path_info *saved_domainname = NULL;          const struct ccs_path_info *saved_domainname = NULL;
147          int error = -ENOMEM;          int error = is_delete ? -ENOENT : -ENOMEM;
148          bool is_last_name = false;          bool is_last_name = false;
149          if (!ccs_is_correct_path(program, 1, -1, -1, __func__))          if (!ccs_is_correct_path(program, 1, -1, -1))
150                  return -EINVAL; /* No patterns allowed. */                  return -EINVAL; /* No patterns allowed. */
151          if (domainname) {          if (domainname) {
152                  if (!ccs_is_domain_def(domainname) &&                  if (!ccs_is_domain_def(domainname) &&
153                      ccs_is_correct_path(domainname, 1, -1, -1, __func__))                      ccs_is_correct_path(domainname, 1, -1, -1))
154                          is_last_name = true;                          is_last_name = true;
155                  else if (!ccs_is_correct_domain(domainname, __func__))                  else if (!ccs_is_correct_domain(domainname))
156                          return -EINVAL;                          return -EINVAL;
157                  saved_domainname = ccs_save_name(domainname);                  saved_domainname = ccs_get_name(domainname);
158                  if (!saved_domainname)                  if (!saved_domainname)
159                          return -ENOMEM;                          return -ENOMEM;
160          }          }
161          saved_program = ccs_save_name(program);          saved_program = ccs_get_name(program);
162          if (!saved_program)          if (!saved_program) {
163                    ccs_put_name(saved_domainname);
164                  return -ENOMEM;                  return -ENOMEM;
165          mutex_lock(&lock);          }
166          list1_for_each_entry(ptr, &ccs_domain_initializer_list, list) {          if (!is_delete)
167                    entry = kzalloc(sizeof(*entry), GFP_KERNEL);
168            mutex_lock(&ccs_policy_lock);
169            list_for_each_entry_rcu(ptr, &ccs_domain_initializer_list, list) {
170                  if (ptr->is_not != is_not ||                  if (ptr->is_not != is_not ||
171                      ptr->domainname != saved_domainname ||                      ptr->domainname != saved_domainname ||
172                      ptr->program != saved_program)                      ptr->program != saved_program)
173                          continue;                          continue;
174                  ptr->is_deleted = is_delete;                  ptr->is_deleted = is_delete;
175                  error = 0;                  error = 0;
176                  goto out;                  break;
177          }          }
178          if (is_delete) {          if (!is_delete && error && ccs_memory_ok(entry, sizeof(*entry))) {
179                  error = -ENOENT;                  entry->domainname = saved_domainname;
180                  goto out;                  saved_domainname = NULL;
181                    entry->program = saved_program;
182                    saved_program = NULL;
183                    entry->is_not = is_not;
184                    entry->is_last_name = is_last_name;
185                    list_add_tail_rcu(&entry->list, &ccs_domain_initializer_list);
186                    entry = NULL;
187                    error = 0;
188          }          }
189          new_entry = ccs_alloc_element(sizeof(*new_entry));          mutex_unlock(&ccs_policy_lock);
190          if (!new_entry)          ccs_put_name(saved_domainname);
191                  goto out;          ccs_put_name(saved_program);
192          new_entry->domainname = saved_domainname;          kfree(entry);
         new_entry->program = saved_program;  
         new_entry->is_not = is_not;  
         new_entry->is_last_name = is_last_name;  
         list1_add_tail_mb(&new_entry->list, &ccs_domain_initializer_list);  
         error = 0;  
  out:  
         mutex_unlock(&lock);  
         ccs_update_counter(CCS_UPDATES_COUNTER_EXCEPTION_POLICY);  
193          return error;          return error;
194  }  }
195    
# Line 266  static int ccs_update_domain_initializer Line 199  static int ccs_update_domain_initializer
199   * @head: Pointer to "struct ccs_io_buffer".   * @head: Pointer to "struct ccs_io_buffer".
200   *   *
201   * Returns true on success, false otherwise.   * Returns true on success, false otherwise.
202     *
203     * Caller holds srcu_read_lock(&ccs_ss).
204   */   */
205  bool ccs_read_domain_initializer_policy(struct ccs_io_buffer *head)  bool ccs_read_domain_initializer_policy(struct ccs_io_buffer *head)
206  {  {
207          struct list1_head *pos;          struct list_head *pos;
208          list1_for_each_cookie(pos, head->read_var2,          bool done = true;
209                                &ccs_domain_initializer_list) {          list_for_each_cookie(pos, head->read_var2,
210                                 &ccs_domain_initializer_list) {
211                  const char *no;                  const char *no;
212                  const char *from = "";                  const char *from = "";
213                  const char *domain = "";                  const char *domain = "";
214                  struct ccs_domain_initializer_entry *ptr;                  struct ccs_domain_initializer_entry *ptr;
215                  ptr = list1_entry(pos, struct ccs_domain_initializer_entry,                  ptr = list_entry(pos, struct ccs_domain_initializer_entry,
216                                    list);                                    list);
217                  if (ptr->is_deleted)                  if (ptr->is_deleted)
218                          continue;                          continue;
# Line 285  bool ccs_read_domain_initializer_policy( Line 221  bool ccs_read_domain_initializer_policy(
221                          from = " from ";                          from = " from ";
222                          domain = ptr->domainname->name;                          domain = ptr->domainname->name;
223                  }                  }
224                  if (!ccs_io_printf(head,                  done = ccs_io_printf(head,
225                                     "%s" KEYWORD_INITIALIZE_DOMAIN "%s%s%s\n",                                       "%s" KEYWORD_INITIALIZE_DOMAIN "%s%s%s\n",
226                                     no, ptr->program->name, from, domain))                                       no, ptr->program->name, from, domain);
227                          goto out;                  if (!done)
228                            break;
229          }          }
230          return true;          return done;
  out:  
         return false;  
231  }  }
232    
233  /**  /**
# Line 326  int ccs_write_domain_initializer_policy( Line 261  int ccs_write_domain_initializer_policy(
261   *   *
262   * Returns true if executing @program reinitializes domain transition,   * Returns true if executing @program reinitializes domain transition,
263   * false otherwise.   * false otherwise.
264     *
265     * Caller holds srcu_read_lock(&ccs_ss).
266   */   */
267  static bool ccs_is_domain_initializer(const struct ccs_path_info *domainname,  static bool ccs_is_domain_initializer(const struct ccs_path_info *domainname,
268                                        const struct ccs_path_info *program,                                        const struct ccs_path_info *program,
# Line 333  static bool ccs_is_domain_initializer(co Line 270  static bool ccs_is_domain_initializer(co
270  {  {
271          struct ccs_domain_initializer_entry *ptr;          struct ccs_domain_initializer_entry *ptr;
272          bool flag = false;          bool flag = false;
273          list1_for_each_entry(ptr, &ccs_domain_initializer_list, list) {          list_for_each_entry_rcu(ptr, &ccs_domain_initializer_list, list) {
274                  if (ptr->is_deleted)                  if (ptr->is_deleted)
275                          continue;                          continue;
276                  if (ptr->domainname) {                  if (ptr->domainname) {
# Line 347  static bool ccs_is_domain_initializer(co Line 284  static bool ccs_is_domain_initializer(co
284                  }                  }
285                  if (ccs_pathcmp(ptr->program, program))                  if (ccs_pathcmp(ptr->program, program))
286                          continue;                          continue;
287                  if (ptr->is_not)                  if (ptr->is_not) {
288                          return false;                          flag = false;
289                            break;
290                    }
291                  flag = true;                  flag = true;
292          }          }
293          return flag;          return flag;
294  }  }
295    
296  /* The list for "struct ccs_domain_keeper_entry". */  /* The list for "struct ccs_domain_keeper_entry". */
297  static LIST1_HEAD(ccs_domain_keeper_list);  LIST_HEAD(ccs_domain_keeper_list);
298    
299  /**  /**
300   * ccs_update_domain_keeper_entry - Update "struct ccs_domain_keeper_entry" list.   * ccs_update_domain_keeper_entry - Update "struct ccs_domain_keeper_entry" list.
# Line 372  static int ccs_update_domain_keeper_entr Line 311  static int ccs_update_domain_keeper_entr
311                                            const bool is_not,                                            const bool is_not,
312                                            const bool is_delete)                                            const bool is_delete)
313  {  {
314          struct ccs_domain_keeper_entry *new_entry;          struct ccs_domain_keeper_entry *entry = NULL;
315          struct ccs_domain_keeper_entry *ptr;          struct ccs_domain_keeper_entry *ptr;
316          const struct ccs_path_info *saved_domainname;          const struct ccs_path_info *saved_domainname;
317          const struct ccs_path_info *saved_program = NULL;          const struct ccs_path_info *saved_program = NULL;
318          static DEFINE_MUTEX(lock);          int error = is_delete ? -ENOENT : -ENOMEM;
         int error = -ENOMEM;  
319          bool is_last_name = false;          bool is_last_name = false;
320          if (!ccs_is_domain_def(domainname) &&          if (!ccs_is_domain_def(domainname) &&
321              ccs_is_correct_path(domainname, 1, -1, -1, __func__))              ccs_is_correct_path(domainname, 1, -1, -1))
322                  is_last_name = true;                  is_last_name = true;
323          else if (!ccs_is_correct_domain(domainname, __func__))          else if (!ccs_is_correct_domain(domainname))
324                  return -EINVAL;                  return -EINVAL;
325          if (program) {          if (program) {
326                  if (!ccs_is_correct_path(program, 1, -1, -1, __func__))                  if (!ccs_is_correct_path(program, 1, -1, -1))
327                          return -EINVAL;                          return -EINVAL;
328                  saved_program = ccs_save_name(program);                  saved_program = ccs_get_name(program);
329                  if (!saved_program)                  if (!saved_program)
330                          return -ENOMEM;                          return -ENOMEM;
331          }          }
332          saved_domainname = ccs_save_name(domainname);          saved_domainname = ccs_get_name(domainname);
333          if (!saved_domainname)          if (!saved_domainname) {
334                    ccs_put_name(saved_program);
335                  return -ENOMEM;                  return -ENOMEM;
336          mutex_lock(&lock);          }
337          list1_for_each_entry(ptr, &ccs_domain_keeper_list, list) {          if (!is_delete)
338                    entry = kzalloc(sizeof(*entry), GFP_KERNEL);
339            mutex_lock(&ccs_policy_lock);
340            list_for_each_entry_rcu(ptr, &ccs_domain_keeper_list, list) {
341                  if (ptr->is_not != is_not ||                  if (ptr->is_not != is_not ||
342                      ptr->domainname != saved_domainname ||                      ptr->domainname != saved_domainname ||
343                      ptr->program != saved_program)                      ptr->program != saved_program)
344                          continue;                          continue;
345                  ptr->is_deleted = is_delete;                  ptr->is_deleted = is_delete;
346                  error = 0;                  error = 0;
347                  goto out;                  break;
348          }          }
349          if (is_delete) {          if (!is_delete && error && ccs_memory_ok(entry, sizeof(*entry))) {
350                  error = -ENOENT;                  entry->domainname = saved_domainname;
351                  goto out;                  saved_domainname = NULL;
352                    entry->program = saved_program;
353                    saved_program = NULL;
354                    entry->is_not = is_not;
355                    entry->is_last_name = is_last_name;
356                    list_add_tail_rcu(&entry->list, &ccs_domain_keeper_list);
357                    entry = NULL;
358                    error = 0;
359          }          }
360          new_entry = ccs_alloc_element(sizeof(*new_entry));          mutex_unlock(&ccs_policy_lock);
361          if (!new_entry)          ccs_put_name(saved_domainname);
362                  goto out;          ccs_put_name(saved_program);
363          new_entry->domainname = saved_domainname;          kfree(entry);
         new_entry->program = saved_program;  
         new_entry->is_not = is_not;  
         new_entry->is_last_name = is_last_name;  
         list1_add_tail_mb(&new_entry->list, &ccs_domain_keeper_list);  
         error = 0;  
  out:  
         mutex_unlock(&lock);  
         ccs_update_counter(CCS_UPDATES_COUNTER_EXCEPTION_POLICY);  
364          return error;          return error;
365  }  }
366    
# Line 449  int ccs_write_domain_keeper_policy(char Line 390  int ccs_write_domain_keeper_policy(char
390   * @head: Pointer to "struct ccs_io_buffer".   * @head: Pointer to "struct ccs_io_buffer".
391   *   *
392   * Returns true on success, false otherwise.   * Returns true on success, false otherwise.
393     *
394     * Caller holds srcu_read_lock(&ccs_ss).
395   */   */
396  bool ccs_read_domain_keeper_policy(struct ccs_io_buffer *head)  bool ccs_read_domain_keeper_policy(struct ccs_io_buffer *head)
397  {  {
398          struct list1_head *pos;          struct list_head *pos;
399          list1_for_each_cookie(pos, head->read_var2, &ccs_domain_keeper_list) {          bool done = true;
400            list_for_each_cookie(pos, head->read_var2,
401                                 &ccs_domain_keeper_list) {
402                  struct ccs_domain_keeper_entry *ptr;                  struct ccs_domain_keeper_entry *ptr;
403                  const char *no;                  const char *no;
404                  const char *from = "";                  const char *from = "";
405                  const char *program = "";                  const char *program = "";
406                  ptr = list1_entry(pos, struct ccs_domain_keeper_entry, list);                  ptr = list_entry(pos, struct ccs_domain_keeper_entry, list);
407                  if (ptr->is_deleted)                  if (ptr->is_deleted)
408                          continue;                          continue;
409                  no = ptr->is_not ? "no_" : "";                  no = ptr->is_not ? "no_" : "";
# Line 466  bool ccs_read_domain_keeper_policy(struc Line 411  bool ccs_read_domain_keeper_policy(struc
411                          from = " from ";                          from = " from ";
412                          program = ptr->program->name;                          program = ptr->program->name;
413                  }                  }
414                  if (!ccs_io_printf(head,                  done = ccs_io_printf(head,
415                                     "%s" KEYWORD_KEEP_DOMAIN "%s%s%s\n", no,                                       "%s" KEYWORD_KEEP_DOMAIN "%s%s%s\n", no,
416                                     program, from, ptr->domainname->name))                                       program, from, ptr->domainname->name);
417                          goto out;                  if (!done)
418                            break;
419          }          }
420          return true;          return done;
  out:  
         return false;  
421  }  }
422    
423  /**  /**
# Line 485  bool ccs_read_domain_keeper_policy(struc Line 429  bool ccs_read_domain_keeper_policy(struc
429   *   *
430   * Returns true if executing @program supresses domain transition,   * Returns true if executing @program supresses domain transition,
431   * false otherwise.   * false otherwise.
432     *
433     * Caller holds srcu_read_lock(&ccs_ss).
434   */   */
435  static bool ccs_is_domain_keeper(const struct ccs_path_info *domainname,  static bool ccs_is_domain_keeper(const struct ccs_path_info *domainname,
436                                   const struct ccs_path_info *program,                                   const struct ccs_path_info *program,
# Line 492  static bool ccs_is_domain_keeper(const s Line 438  static bool ccs_is_domain_keeper(const s
438  {  {
439          struct ccs_domain_keeper_entry *ptr;          struct ccs_domain_keeper_entry *ptr;
440          bool flag = false;          bool flag = false;
441          list1_for_each_entry(ptr, &ccs_domain_keeper_list, list) {          list_for_each_entry_rcu(ptr, &ccs_domain_keeper_list, list) {
442                  if (ptr->is_deleted)                  if (ptr->is_deleted)
443                          continue;                          continue;
444                  if (!ptr->is_last_name) {                  if (!ptr->is_last_name) {
# Line 504  static bool ccs_is_domain_keeper(const s Line 450  static bool ccs_is_domain_keeper(const s
450                  }                  }
451                  if (ptr->program && ccs_pathcmp(ptr->program, program))                  if (ptr->program && ccs_pathcmp(ptr->program, program))
452                          continue;                          continue;
453                  if (ptr->is_not)                  if (ptr->is_not) {
454                          return false;                          flag = false;
455                            break;
456                    }
457                  flag = true;                  flag = true;
458          }          }
459          return flag;          return flag;
460  }  }
461    
462  /* The list for "struct ccs_alias_entry". */  /* The list for "struct ccs_alias_entry". */
463  static LIST1_HEAD(ccs_alias_list);  LIST_HEAD(ccs_alias_list);
464    
465  /**  /**
466   * ccs_update_alias_entry - Update "struct ccs_alias_entry" list.   * ccs_update_alias_entry - Update "struct ccs_alias_entry" list.
# Line 527  static int ccs_update_alias_entry(const Line 475  static int ccs_update_alias_entry(const
475                                    const char *aliased_name,                                    const char *aliased_name,
476                                    const bool is_delete)                                    const bool is_delete)
477  {  {
478          struct ccs_alias_entry *new_entry;          struct ccs_alias_entry *entry = NULL;
479          struct ccs_alias_entry *ptr;          struct ccs_alias_entry *ptr;
         static DEFINE_MUTEX(lock);  
480          const struct ccs_path_info *saved_original_name;          const struct ccs_path_info *saved_original_name;
481          const struct ccs_path_info *saved_aliased_name;          const struct ccs_path_info *saved_aliased_name;
482          int error = -ENOMEM;          int error = is_delete ? -ENOENT : -ENOMEM;
483          if (!ccs_is_correct_path(original_name, 1, -1, -1, __func__) ||          if (!ccs_is_correct_path(original_name, 1, -1, -1) ||
484              !ccs_is_correct_path(aliased_name, 1, -1, -1, __func__))              !ccs_is_correct_path(aliased_name, 1, -1, -1))
485                  return -EINVAL; /* No patterns allowed. */                  return -EINVAL; /* No patterns allowed. */
486          saved_original_name = ccs_save_name(original_name);          saved_original_name = ccs_get_name(original_name);
487          saved_aliased_name = ccs_save_name(aliased_name);          saved_aliased_name = ccs_get_name(aliased_name);
488          if (!saved_original_name || !saved_aliased_name)          if (!saved_original_name || !saved_aliased_name) {
489                    ccs_put_name(saved_original_name);
490                    ccs_put_name(saved_aliased_name);
491                  return -ENOMEM;                  return -ENOMEM;
492          mutex_lock(&lock);          }
493          list1_for_each_entry(ptr, &ccs_alias_list, list) {          if (!is_delete)
494                    entry = kzalloc(sizeof(*entry), GFP_KERNEL);
495            mutex_lock(&ccs_policy_lock);
496            list_for_each_entry_rcu(ptr, &ccs_alias_list, list) {
497                  if (ptr->original_name != saved_original_name ||                  if (ptr->original_name != saved_original_name ||
498                      ptr->aliased_name != saved_aliased_name)                      ptr->aliased_name != saved_aliased_name)
499                          continue;                          continue;
500                  ptr->is_deleted = is_delete;                  ptr->is_deleted = is_delete;
501                  error = 0;                  error = 0;
502                  goto out;                  break;
503          }          }
504          if (is_delete) {          if (!is_delete && error && ccs_memory_ok(entry, sizeof(*entry))) {
505                  error = -ENOENT;                  entry->original_name = saved_original_name;
506                  goto out;                  saved_original_name = NULL;
507                    entry->aliased_name = saved_aliased_name;
508                    saved_aliased_name = NULL;
509                    list_add_tail_rcu(&entry->list, &ccs_alias_list);
510                    entry = NULL;
511                    error = 0;
512          }          }
513          new_entry = ccs_alloc_element(sizeof(*new_entry));          mutex_unlock(&ccs_policy_lock);
514          if (!new_entry)          ccs_put_name(saved_original_name);
515                  goto out;          ccs_put_name(saved_aliased_name);
516          new_entry->original_name = saved_original_name;          kfree(entry);
         new_entry->aliased_name = saved_aliased_name;  
         list1_add_tail_mb(&new_entry->list, &ccs_alias_list);  
         error = 0;  
  out:  
         mutex_unlock(&lock);  
         ccs_update_counter(CCS_UPDATES_COUNTER_EXCEPTION_POLICY);  
517          return error;          return error;
518  }  }
519    
# Line 572  static int ccs_update_alias_entry(const Line 523  static int ccs_update_alias_entry(const
523   * @head: Pointer to "struct ccs_io_buffer".   * @head: Pointer to "struct ccs_io_buffer".
524   *   *
525   * Returns true on success, false otherwise.   * Returns true on success, false otherwise.
526     *
527     * Caller holds srcu_read_lock(&ccs_ss).
528   */   */
529  bool ccs_read_alias_policy(struct ccs_io_buffer *head)  bool ccs_read_alias_policy(struct ccs_io_buffer *head)
530  {  {
531          struct list1_head *pos;          struct list_head *pos;
532          list1_for_each_cookie(pos, head->read_var2, &ccs_alias_list) {          bool done = true;
533            list_for_each_cookie(pos, head->read_var2, &ccs_alias_list) {
534                  struct ccs_alias_entry *ptr;                  struct ccs_alias_entry *ptr;
535                  ptr = list1_entry(pos, struct ccs_alias_entry, list);                  ptr = list_entry(pos, struct ccs_alias_entry, list);
536                  if (ptr->is_deleted)                  if (ptr->is_deleted)
537                          continue;                          continue;
538                  if (!ccs_io_printf(head, KEYWORD_ALIAS "%s %s\n",                  done = ccs_io_printf(head, KEYWORD_ALIAS "%s %s\n",
539                                     ptr->original_name->name,                                       ptr->original_name->name,
540                                     ptr->aliased_name->name))                                       ptr->aliased_name->name);
541                          goto out;                  if (!done)
542                            break;
543          }          }
544          return true;          return done;
  out:  
         return false;  
545  }  }
546    
547  /**  /**
# Line 609  int ccs_write_alias_policy(char *data, c Line 562  int ccs_write_alias_policy(char *data, c
562  }  }
563    
564  /* The list for "struct ccs_aggregator_entry". */  /* The list for "struct ccs_aggregator_entry". */
565  static LIST1_HEAD(ccs_aggregator_list);  LIST_HEAD(ccs_aggregator_list);
566    
567  /**  /**
568   * ccs_update_aggregator_entry - Update "struct ccs_aggregator_entry" list.   * ccs_update_aggregator_entry - Update "struct ccs_aggregator_entry" list.
# Line 624  static int ccs_update_aggregator_entry(c Line 577  static int ccs_update_aggregator_entry(c
577                                         const char *aggregated_name,                                         const char *aggregated_name,
578                                         const bool is_delete)                                         const bool is_delete)
579  {  {
580          struct ccs_aggregator_entry *new_entry;          struct ccs_aggregator_entry *entry = NULL;
581          struct ccs_aggregator_entry *ptr;          struct ccs_aggregator_entry *ptr;
         static DEFINE_MUTEX(lock);  
582          const struct ccs_path_info *saved_original_name;          const struct ccs_path_info *saved_original_name;
583          const struct ccs_path_info *saved_aggregated_name;          const struct ccs_path_info *saved_aggregated_name;
584          int error = -ENOMEM;          int error = is_delete ? -ENOENT : -ENOMEM;
585          if (!ccs_is_correct_path(original_name, 1, 0, -1, __func__) ||          if (!ccs_is_correct_path(original_name, 1, 0, -1) ||
586              !ccs_is_correct_path(aggregated_name, 1, -1, -1, __func__))              !ccs_is_correct_path(aggregated_name, 1, -1, -1))
587                  return -EINVAL;                  return -EINVAL;
588          saved_original_name = ccs_save_name(original_name);          saved_original_name = ccs_get_name(original_name);
589          saved_aggregated_name = ccs_save_name(aggregated_name);          saved_aggregated_name = ccs_get_name(aggregated_name);
590          if (!saved_original_name || !saved_aggregated_name)          if (!saved_original_name || !saved_aggregated_name) {
591                    ccs_put_name(saved_original_name);
592                    ccs_put_name(saved_aggregated_name);
593                  return -ENOMEM;                  return -ENOMEM;
594          mutex_lock(&lock);          }
595          list1_for_each_entry(ptr, &ccs_aggregator_list, list) {          if (!is_delete)
596                    entry = kzalloc(sizeof(*entry), GFP_KERNEL);
597            mutex_lock(&ccs_policy_lock);
598            list_for_each_entry_rcu(ptr, &ccs_aggregator_list, list) {
599                  if (ptr->original_name != saved_original_name ||                  if (ptr->original_name != saved_original_name ||
600                      ptr->aggregated_name != saved_aggregated_name)                      ptr->aggregated_name != saved_aggregated_name)
601                          continue;                          continue;
602                  ptr->is_deleted = is_delete;                  ptr->is_deleted = is_delete;
603                  error = 0;                  error = 0;
604                  goto out;                  break;
605          }          }
606          if (is_delete) {          if (!is_delete && error && ccs_memory_ok(entry, sizeof(*entry))) {
607                  error = -ENOENT;                  entry->original_name = saved_original_name;
608                  goto out;                  saved_original_name = NULL;
609                    entry->aggregated_name = saved_aggregated_name;
610                    saved_aggregated_name = NULL;
611                    list_add_tail_rcu(&entry->list, &ccs_aggregator_list);
612                    entry = NULL;
613                    error = 0;
614          }          }
615          new_entry = ccs_alloc_element(sizeof(*new_entry));          mutex_unlock(&ccs_policy_lock);
616          if (!new_entry)          ccs_put_name(saved_original_name);
617                  goto out;          ccs_put_name(saved_aggregated_name);
618          new_entry->original_name = saved_original_name;          kfree(entry);
         new_entry->aggregated_name = saved_aggregated_name;  
         list1_add_tail_mb(&new_entry->list, &ccs_aggregator_list);  
         error = 0;  
  out:  
         mutex_unlock(&lock);  
         ccs_update_counter(CCS_UPDATES_COUNTER_EXCEPTION_POLICY);  
619          return error;          return error;
620  }  }
621    
# Line 669  static int ccs_update_aggregator_entry(c Line 625  static int ccs_update_aggregator_entry(c
625   * @head: Pointer to "struct ccs_io_buffer".   * @head: Pointer to "struct ccs_io_buffer".
626   *   *
627   * Returns true on success, false otherwise.   * Returns true on success, false otherwise.
628     *
629     * Caller holds srcu_read_lock(&ccs_ss).
630   */   */
631  bool ccs_read_aggregator_policy(struct ccs_io_buffer *head)  bool ccs_read_aggregator_policy(struct ccs_io_buffer *head)
632  {  {
633          struct list1_head *pos;          struct list_head *pos;
634          list1_for_each_cookie(pos, head->read_var2, &ccs_aggregator_list) {          bool done = true;
635            list_for_each_cookie(pos, head->read_var2, &ccs_aggregator_list) {
636                  struct ccs_aggregator_entry *ptr;                  struct ccs_aggregator_entry *ptr;
637                  ptr = list1_entry(pos, struct ccs_aggregator_entry, list);                  ptr = list_entry(pos, struct ccs_aggregator_entry, list);
638                  if (ptr->is_deleted)                  if (ptr->is_deleted)
639                          continue;                          continue;
640                  if (!ccs_io_printf(head, KEYWORD_AGGREGATOR "%s %s\n",                  done = ccs_io_printf(head, KEYWORD_AGGREGATOR "%s %s\n",
641                                     ptr->original_name->name,                                       ptr->original_name->name,
642                                     ptr->aggregated_name->name))                                       ptr->aggregated_name->name);
643                          goto out;                  if (!done)
644                            break;
645          }          }
646          return true;          return done;
  out:  
         return false;  
647  }  }
648    
649  /**  /**
# Line 705  int ccs_write_aggregator_policy(char *da Line 663  int ccs_write_aggregator_policy(char *da
663          return ccs_update_aggregator_entry(data, cp, is_delete);          return ccs_update_aggregator_entry(data, cp, is_delete);
664  }  }
665    
666  /* Domain create/delete/undelete handler. */  /* Domain create/delete handler. */
   
 /* #define DEBUG_DOMAIN_UNDELETE */  
667    
668  /**  /**
669   * ccs_delete_domain - Delete a domain.   * ccs_delete_domain - Delete a domain.
# Line 718  int ccs_write_aggregator_policy(char *da Line 674  int ccs_write_aggregator_policy(char *da
674   */   */
675  int ccs_delete_domain(char *domainname)  int ccs_delete_domain(char *domainname)
676  {  {
677          struct domain_info *domain;          struct ccs_domain_info *domain;
678          struct ccs_path_info name;          struct ccs_path_info name;
679          name.name = domainname;          name.name = domainname;
680          ccs_fill_path_info(&name);          ccs_fill_path_info(&name);
681          mutex_lock(&ccs_domain_list_lock);          mutex_lock(&ccs_policy_lock);
 #ifdef DEBUG_DOMAIN_UNDELETE  
         printk(KERN_DEBUG "ccs_delete_domain %s\n", domainname);  
         list1_for_each_entry(domain, &ccs_domain_list, list) {  
                 if (ccs_pathcmp(domain->domainname, &name))  
                         continue;  
                 printk(KERN_DEBUG "List: %p %u\n", domain, domain->is_deleted);  
         }  
 #endif  
682          /* Is there an active domain? */          /* Is there an active domain? */
683          list1_for_each_entry(domain, &ccs_domain_list, list) {          list_for_each_entry_rcu(domain, &ccs_domain_list, list) {
684                  struct domain_info *domain2;                  /* Never delete ccs_kernel_domain */
685                  /* Never delete KERNEL_DOMAIN */                  if (domain == &ccs_kernel_domain)
                 if (domain == &KERNEL_DOMAIN)  
686                          continue;                          continue;
687                  if (domain->is_deleted ||                  if (domain->is_deleted ||
688                      ccs_pathcmp(domain->domainname, &name))                      ccs_pathcmp(domain->domainname, &name))
689                          continue;                          continue;
690                  /* Mark already deleted domains as non undeletable. */                  domain->is_deleted = true;
                 list1_for_each_entry(domain2, &ccs_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  
691                  break;                  break;
692          }          }
693          mutex_unlock(&ccs_domain_list_lock);          mutex_unlock(&ccs_policy_lock);
694          return 0;          return 0;
695  }  }
696    
697  /**  /**
  * 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 ccs_path_info name;  
         name.name = domainname;  
         ccs_fill_path_info(&name);  
         mutex_lock(&ccs_domain_list_lock);  
 #ifdef DEBUG_DOMAIN_UNDELETE  
         printk(KERN_DEBUG "ccs_undelete_domain %s\n", domainname);  
         list1_for_each_entry(domain, &ccs_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, &ccs_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(&ccs_domain_list_lock);  
         return candidate_domain;  
 }  
   
 /**  
698   * ccs_find_or_assign_new_domain - Create a domain.   * ccs_find_or_assign_new_domain - Create a domain.
699   *   *
700   * @domainname: The name of domain.   * @domainname: The name of domain.
701   * @profile:    Profile number to assign if the domain was newly created.   * @profile:    Profile number to assign if the domain was newly created.
702   *   *
703   * Returns pointer to "struct domain_info" on success, NULL otherwise.   * Returns pointer to "struct ccs_domain_info" on success, NULL otherwise.
704   */   */
705  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,
706                                                    const u8 profile)                                                        const u8 profile)
707  {  {
708          struct domain_info *domain = NULL;          struct ccs_domain_info *entry;
709            struct ccs_domain_info *domain;
710          const struct ccs_path_info *saved_domainname;          const struct ccs_path_info *saved_domainname;
711          mutex_lock(&ccs_domain_list_lock);          bool found = false;
712          domain = ccs_find_domain(domainname);  
713          if (domain)          if (!ccs_is_correct_domain(domainname))
714                  goto out;                  return NULL;
715          if (!ccs_is_correct_domain(domainname, __func__))          saved_domainname = ccs_get_name(domainname);
                 goto out;  
         saved_domainname = ccs_save_name(domainname);  
716          if (!saved_domainname)          if (!saved_domainname)
717                  goto out;                  return NULL;
718          /* Can I reuse memory of deleted domain? */          entry = kzalloc(sizeof(*entry), GFP_KERNEL);
719          list1_for_each_entry(domain, &ccs_domain_list, list) {          mutex_lock(&ccs_policy_lock);
720                  struct task_struct *p;          list_for_each_entry_rcu(domain, &ccs_domain_list, list) {
721                  struct ccs_acl_info *ptr;                  if (domain->is_deleted ||
722                  bool flag;                      ccs_pathcmp(saved_domainname, domain->domainname))
723                  if (!domain->is_deleted ||                          continue;
724                      domain->domainname != saved_domainname)                  found = true;
725                          continue;                  break;
                 flag = false;  
                 /***** CRITICAL SECTION START *****/  
                 read_lock(&tasklist_lock);  
                 for_each_process(p) {  
                         if (p->domain_info != domain)  
                                 continue;  
                         flag = true;  
                         break;  
                 }  
                 read_unlock(&tasklist_lock);  
                 /***** CRITICAL SECTION END *****/  
                 if (flag)  
                         continue;  
 #ifdef DEBUG_DOMAIN_UNDELETE  
                 printk(KERN_DEBUG "Reusing %p %s\n", domain,  
                        domain->domainname->name);  
 #endif  
                 list1_for_each_entry(ptr, &domain->acl_info_list, list) {  
                         ptr->type |= ACL_DELETED;  
                 }  
                 ccs_set_domain_flag(domain, true, domain->flags);  
                 domain->profile = profile;  
                 domain->quota_warned = false;  
                 mb(); /* Avoid out-of-order execution. */  
                 domain->is_deleted = 0;  
                 goto out;  
         }  
         /* No memory reusable. Create using new memory. */  
         domain = ccs_alloc_element(sizeof(*domain));  
         if (domain) {  
                 INIT_LIST1_HEAD(&domain->acl_info_list);  
                 domain->domainname = saved_domainname;  
                 domain->profile = profile;  
                 list1_add_tail_mb(&domain->list, &ccs_domain_list);  
726          }          }
727   out:          if (!found && ccs_memory_ok(entry, sizeof(*entry))) {
728          mutex_unlock(&ccs_domain_list_lock);                  INIT_LIST_HEAD(&entry->acl_info_list);
729          return domain;                  entry->domainname = saved_domainname;
730                    saved_domainname = NULL;
731                    entry->profile = profile;
732                    list_add_tail_rcu(&entry->list, &ccs_domain_list);
733                    domain = entry;
734                    entry = NULL;
735                    found = true;
736            }
737            mutex_unlock(&ccs_policy_lock);
738            ccs_put_name(saved_domainname);
739            kfree(entry);
740            return found ? domain : NULL;
741  }  }
742    
743  /**  /**
# Line 944  static bool ccs_get_argv0(struct ccs_exe Line 801  static bool ccs_get_argv0(struct ccs_exe
801   * @ee: Pointer to "struct ccs_execve_entry".   * @ee: Pointer to "struct ccs_execve_entry".
802   *   *
803   * Returns 0 on success, negative value otherwise.   * Returns 0 on success, negative value otherwise.
804     *
805     * Caller holds srcu_read_lock(&ccs_ss).
806   */   */
807  static int ccs_find_next_domain(struct ccs_execve_entry *ee)  static int ccs_find_next_domain(struct ccs_execve_entry *ee)
808  {  {
809          struct ccs_request_info *r = &ee->r;          struct ccs_request_info *r = &ee->r;
810          const struct ccs_path_info *handler = ee->handler;          const struct ccs_path_info *handler = ee->handler;
811          struct domain_info *domain = NULL;          struct ccs_domain_info *domain = NULL;
812          const char *old_domain_name = r->domain->domainname->name;          const char *old_domain_name = r->domain->domainname->name;
813          struct linux_binprm *bprm = ee->bprm;          struct linux_binprm *bprm = ee->bprm;
814          const u8 mode = r->mode;          const u8 mode = r->mode;
815          const bool is_enforce = (mode == 3);          const bool is_enforce = (mode == 3);
816          const u32 tomoyo_flags = current->tomoyo_flags;          const u32 ccs_flags = current->ccs_flags;
817          char *new_domain_name = NULL;          char *new_domain_name = NULL;
818          struct ccs_path_info rn; /* real name */          struct ccs_path_info rn; /* real name */
819          struct ccs_path_info sn; /* symlink name */          struct ccs_path_info sn; /* symlink name */
820          struct ccs_path_info ln; /* last name */          struct ccs_path_info ln; /* last name */
821          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) {  
                         ccs_update_domain_initializer_entry(NULL,  
                                                             "/sbin/hotplug",  
                                                             false, false);  
                         ccs_update_domain_initializer_entry(NULL,  
                                                             "/sbin/modprobe",  
                                                             false, false);  
                         first = false;  
                 }  
         }  
   
822   retry:   retry:
823          current->tomoyo_flags = tomoyo_flags;          current->ccs_flags = ccs_flags;
824          r->cond = NULL;          r->cond = NULL;
825          /* Get realpath of program and symbolic link. */          /* Get realpath of program and symbolic link. */
826          retval = ccs_realpath_both(bprm->filename, ee);          retval = ccs_realpath_both(bprm->filename, ee);
# Line 1011  static int ccs_find_next_domain(struct c Line 852  static int ccs_find_next_domain(struct c
852          if (ccs_pathcmp(&rn, &sn)) {          if (ccs_pathcmp(&rn, &sn)) {
853                  struct ccs_alias_entry *ptr;                  struct ccs_alias_entry *ptr;
854                  /* Is this program allowed to be called via symbolic links? */                  /* Is this program allowed to be called via symbolic links? */
855                  list1_for_each_entry(ptr, &ccs_alias_list, list) {                  list_for_each_entry_rcu(ptr, &ccs_alias_list, list) {
856                          if (ptr->is_deleted ||                          if (ptr->is_deleted ||
857                              ccs_pathcmp(&rn, ptr->original_name) ||                              ccs_pathcmp(&rn, ptr->original_name) ||
858                              ccs_pathcmp(&sn, ptr->aliased_name))                              ccs_pathcmp(&sn, ptr->aliased_name))
# Line 1025  static int ccs_find_next_domain(struct c Line 866  static int ccs_find_next_domain(struct c
866          /* sn will be overwritten after here. */          /* sn will be overwritten after here. */
867    
868          /* Compare basename of program_path and argv[0] */          /* Compare basename of program_path and argv[0] */
869          r->mode = ccs_check_flags(r->domain, CCS_TOMOYO_MAC_FOR_ARGV0);          r->mode = ccs_check_flags(r->domain, CCS_MAC_FOR_ARGV0);
870          if (bprm->argc > 0 && r->mode) {          if (bprm->argc > 0 && r->mode) {
871                  char *base_argv0 = ee->tmp;                  char *base_argv0 = ee->tmp;
872                  const char *base_filename;                  const char *base_filename;
# Line 1050  static int ccs_find_next_domain(struct c Line 891  static int ccs_find_next_domain(struct c
891          {          {
892                  struct ccs_aggregator_entry *ptr;                  struct ccs_aggregator_entry *ptr;
893                  /* Is this program allowed to be aggregated? */                  /* Is this program allowed to be aggregated? */
894                  list1_for_each_entry(ptr, &ccs_aggregator_list, list) {                  list_for_each_entry_rcu(ptr, &ccs_aggregator_list, list) {
895                          if (ptr->is_deleted ||                          if (ptr->is_deleted ||
896                              !ccs_path_matches_pattern(&rn, ptr->original_name))                              !ccs_path_matches_pattern(&rn, ptr->original_name))
897                                  continue;                                  continue;
# Line 1072  static int ccs_find_next_domain(struct c Line 913  static int ccs_find_next_domain(struct c
913   calculate_domain:   calculate_domain:
914          new_domain_name = ee->tmp;          new_domain_name = ee->tmp;
915          if (ccs_is_domain_initializer(r->domain->domainname, &rn, &ln)) {          if (ccs_is_domain_initializer(r->domain->domainname, &rn, &ln)) {
916                  /* Transit to the child of KERNEL_DOMAIN domain. */                  /* Transit to the child of ccs_kernel_domain domain. */
917                  snprintf(new_domain_name, CCS_EXEC_TMPSIZE - 1,                  snprintf(new_domain_name, CCS_EXEC_TMPSIZE - 1,
918                           ROOT_NAME " " "%s", ee->program_path);                           ROOT_NAME " " "%s", ee->program_path);
919          } else if (r->domain == &KERNEL_DOMAIN && !ccs_policy_loaded) {          } else if (r->domain == &ccs_kernel_domain && !ccs_policy_loaded) {
920                  /*                  /*
921                   * Needn't to transit from kernel domain before starting                   * Needn't to transit from kernel domain before starting
922                   * /sbin/init. But transit from kernel domain if executing                   * /sbin/init. But transit from kernel domain if executing
# Line 1106  static int ccs_find_next_domain(struct c Line 947  static int ccs_find_next_domain(struct c
947          }          }
948          domain = ccs_find_or_assign_new_domain(new_domain_name, r->profile);          domain = ccs_find_or_assign_new_domain(new_domain_name, r->profile);
949          if (domain)          if (domain)
950                  ccs_audit_domain_creation_log(domain);                  ccs_audit_domain_creation_log(r->domain);
951   done:   done:
952          if (!domain) {          if (!domain) {
953                  printk(KERN_WARNING "TOMOYO-ERROR: Domain '%s' not defined.\n",                  printk(KERN_WARNING "TOMOYO-ERROR: Domain '%s' not defined.\n",
# Line 1115  static int ccs_find_next_domain(struct c Line 956  static int ccs_find_next_domain(struct c
956                          retval = -EPERM;                          retval = -EPERM;
957                  else {                  else {
958                          retval = 0;                          retval = 0;
959                          ccs_set_domain_flag(r->domain, false,                          r->domain->domain_transition_failed = true;
                                             DOMAIN_FLAGS_TRANSITION_FAILED);  
960                  }                  }
961          } else {          } else {
962                  retval = 0;                  retval = 0;
963          }          }
964   out:   out:
965          if (domain)          if (domain)
966                  r->domain = domain;                  r->domain = domain;
967          return retval;          return retval;
968  }  }
969    
# Line 1318  static DEFINE_SPINLOCK(ccs_execve_list_l Line 1158  static DEFINE_SPINLOCK(ccs_execve_list_l
1158   */   */
1159  static struct ccs_execve_entry *ccs_allocate_execve_entry(void)  static struct ccs_execve_entry *ccs_allocate_execve_entry(void)
1160  {  {
1161          struct ccs_execve_entry *ee = ccs_alloc(sizeof(*ee), false);          struct ccs_execve_entry *ee = kzalloc(sizeof(*ee), GFP_KERNEL);
1162          if (!ee)          if (!ee)
1163                  return NULL;                  return NULL;
1164          memset(ee, 0, sizeof(*ee));          memset(ee, 0, sizeof(*ee));
1165          ee->program_path = ccs_alloc(CCS_MAX_PATHNAME_LEN, false);          ee->program_path = kzalloc(CCS_MAX_PATHNAME_LEN, GFP_KERNEL);
1166          ee->tmp = ccs_alloc(CCS_MAX_PATHNAME_LEN, false);          ee->tmp = kzalloc(CCS_MAX_PATHNAME_LEN, GFP_KERNEL);
1167          if (!ee->program_path || !ee->tmp) {          if (!ee->program_path || !ee->tmp) {
1168                  ccs_free(ee->program_path);                  kfree(ee->program_path);
1169                  ccs_free(ee->tmp);                  kfree(ee->tmp);
1170                  ccs_free(ee);                  kfree(ee);
1171                  return NULL;                  return NULL;
1172          }          }
1173            ee->srcu_idx = srcu_read_lock(&ccs_ss);
1174          /* ee->dump->data is allocated by ccs_dump_page(). */          /* ee->dump->data is allocated by ccs_dump_page(). */
1175          ee->task = current;          ee->task = current;
1176          /***** CRITICAL SECTION START *****/          /***** CRITICAL SECTION START *****/
# Line 1377  static void ccs_free_execve_entry(struct Line 1218  static void ccs_free_execve_entry(struct
1218          list_del(&ee->list);          list_del(&ee->list);
1219          spin_unlock(&ccs_execve_list_lock);          spin_unlock(&ccs_execve_list_lock);
1220          /***** CRITICAL SECTION END *****/          /***** CRITICAL SECTION END *****/
1221          ccs_free(ee->program_path);          kfree(ee->program_path);
1222          ccs_free(ee->tmp);          kfree(ee->tmp);
1223          kfree(ee->dump.data);          kfree(ee->dump.data);
1224          ccs_free(ee);          srcu_read_unlock(&ccs_ss, ee->srcu_idx);
1225            kfree(ee);
1226  }  }
1227    
1228  /**  /**
# Line 1406  static int ccs_try_alt_exec(struct ccs_e Line 1248  static int ccs_try_alt_exec(struct ccs_e
1248           * modified bprm->argv[0]           * modified bprm->argv[0]
1249           *    = the program's name specified by execute_handler           *    = the program's name specified by execute_handler
1250           * modified bprm->argv[1]           * modified bprm->argv[1]
1251           *    = current->domain_info->domainname->name           *    = ccs_current_domain()->domainname->name
1252           * modified bprm->argv[2]           * modified bprm->argv[2]
1253           *    = the current process's name           *    = the current process's name
1254           * modified bprm->argv[3]           * modified bprm->argv[3]
# Line 1478  static int ccs_try_alt_exec(struct ccs_e Line 1320  static int ccs_try_alt_exec(struct ccs_e
1320          /* Set argv[3] */          /* Set argv[3] */
1321          {          {
1322                  char *cp = ee->tmp;                  char *cp = ee->tmp;
1323                  const u32 tomoyo_flags = task->tomoyo_flags;                  const u32 ccs_flags = task->ccs_flags;
1324                  snprintf(ee->tmp, CCS_EXEC_TMPSIZE - 1,                  snprintf(ee->tmp, CCS_EXEC_TMPSIZE - 1,
1325                           "pid=%d uid=%d gid=%d euid=%d egid=%d suid=%d "                           "pid=%d uid=%d gid=%d euid=%d egid=%d suid=%d "
1326                           "sgid=%d fsuid=%d fsgid=%d state[0]=%u "                           "sgid=%d fsuid=%d fsgid=%d state[0]=%u "
# Line 1486  static int ccs_try_alt_exec(struct ccs_e Line 1328  static int ccs_try_alt_exec(struct ccs_e
1328                           (pid_t) sys_getpid(), current_uid(), current_gid(),                           (pid_t) sys_getpid(), current_uid(), current_gid(),
1329                           current_euid(), current_egid(), current_suid(),                           current_euid(), current_egid(), current_suid(),
1330                           current_sgid(), current_fsuid(), current_fsgid(),                           current_sgid(), current_fsuid(), current_fsgid(),
1331                           (u8) (tomoyo_flags >> 24), (u8) (tomoyo_flags >> 16),                           (u8) (ccs_flags >> 24), (u8) (ccs_flags >> 16),
1332                           (u8) (tomoyo_flags >> 8));                           (u8) (ccs_flags >> 8));
1333                  retval = copy_strings_kernel(1, &cp, bprm);                  retval = copy_strings_kernel(1, &cp, bprm);
1334                  if (retval < 0)                  if (retval < 0)
1335                          goto out;                          goto out;
# Line 1499  static int ccs_try_alt_exec(struct ccs_e Line 1341  static int ccs_try_alt_exec(struct ccs_e
1341                  char *exe = (char *) ccs_get_exe();                  char *exe = (char *) ccs_get_exe();
1342                  if (exe) {                  if (exe) {
1343                          retval = copy_strings_kernel(1, &exe, bprm);                          retval = copy_strings_kernel(1, &exe, bprm);
1344                          ccs_free(exe);                          kfree(exe);
1345                  } else {                  } else {
1346                          exe = ee->tmp;                          exe = ee->tmp;
1347                          strncpy(ee->tmp, "<unknown>", CCS_EXEC_TMPSIZE - 1);                          strncpy(ee->tmp, "<unknown>", CCS_EXEC_TMPSIZE - 1);
# Line 1513  static int ccs_try_alt_exec(struct ccs_e Line 1355  static int ccs_try_alt_exec(struct ccs_e
1355          /* Set argv[1] */          /* Set argv[1] */
1356          {          {
1357                  char *cp = ee->tmp;                  char *cp = ee->tmp;
1358                  strncpy(ee->tmp, task->domain_info->domainname->name,                  strncpy(ee->tmp, ccs_current_domain()->domainname->name,
1359                          CCS_EXEC_TMPSIZE - 1);                          CCS_EXEC_TMPSIZE - 1);
1360                  retval = copy_strings_kernel(1, &cp, bprm);                  retval = copy_strings_kernel(1, &cp, bprm);
1361                  if (retval < 0)                  if (retval < 0)
# Line 1570  static int ccs_try_alt_exec(struct ccs_e Line 1412  static int ccs_try_alt_exec(struct ccs_e
1412                   * overwrite ee->program_path and ee->tmp.                   * overwrite ee->program_path and ee->tmp.
1413                   */                   */
1414                  const int len = strlen(ee->program_path) + 1;                  const int len = strlen(ee->program_path) + 1;
1415                  char *cp = kmalloc(len, GFP_KERNEL);                  char *cp = kzalloc(len, GFP_KERNEL);
1416                  if (!cp) {                  if (!cp) {
1417                          retval = -ENOMEM;                          retval = -ENOMEM;
1418                          goto out;                          goto out;
# Line 1580  static int ccs_try_alt_exec(struct ccs_e Line 1422  static int ccs_try_alt_exec(struct ccs_e
1422  #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 5, 0)  #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 5, 0)
1423                  bprm->interp = bprm->filename;                  bprm->interp = bprm->filename;
1424  #endif  #endif
1425                  task->tomoyo_flags |= CCS_DONT_SLEEP_ON_ENFORCE_ERROR;                  task->ccs_flags |= CCS_DONT_SLEEP_ON_ENFORCE_ERROR;
1426                  retval = ccs_find_next_domain(ee);                  retval = ccs_find_next_domain(ee);
1427                  task->tomoyo_flags &= ~CCS_DONT_SLEEP_ON_ENFORCE_ERROR;                  task->ccs_flags &= ~CCS_DONT_SLEEP_ON_ENFORCE_ERROR;
1428                  /* Restore ee->program_path for search_binary_handler(). */                  /* Restore ee->program_path for search_binary_handler(). */
1429                  memmove(ee->program_path, cp, len);                  memmove(ee->program_path, cp, len);
1430                  bprm->filename = ee->program_path;                  bprm->filename = ee->program_path;
# Line 1602  static int ccs_try_alt_exec(struct ccs_e Line 1444  static int ccs_try_alt_exec(struct ccs_e
1444   * @type: Type of execute handler.   * @type: Type of execute handler.
1445   *   *
1446   * Returns true if found, false otherwise.   * Returns true if found, false otherwise.
1447     *
1448     * Caller holds srcu_read_lock(&ccs_ss).
1449   */   */
1450  static bool ccs_find_execute_handler(struct ccs_execve_entry *ee,  static bool ccs_find_execute_handler(struct ccs_execve_entry *ee,
1451                                       const u8 type)                                       const u8 type)
1452  {  {
1453          struct task_struct *task = current;          struct task_struct *task = current;
1454          const struct domain_info *domain = task->domain_info;          const struct ccs_domain_info *domain = ccs_current_domain();
1455          struct ccs_acl_info *ptr;          struct ccs_acl_info *ptr;
1456            bool found = false;
1457          /*          /*
1458           * Don't use execute handler if the current process is           * Don't use execute handler if the current process is
1459           * marked as execute handler to avoid infinite execute handler loop.           * marked as execute handler to avoid infinite execute handler loop.
1460           */           */
1461          if (task->tomoyo_flags & TOMOYO_TASK_IS_EXECUTE_HANDLER)          if (task->ccs_flags & CCS_TASK_IS_EXECUTE_HANDLER)
1462                  return false;                  return false;
1463          list1_for_each_entry(ptr, &domain->acl_info_list, list) {          list_for_each_entry(ptr, &domain->acl_info_list, list) {
1464                  struct ccs_execute_handler_record *acl;                  struct ccs_execute_handler_record *acl;
1465                  if (ptr->type != type)                  if (ptr->type != type)
1466                          continue;                          continue;
1467                  acl = container_of(ptr, struct ccs_execute_handler_record,                  acl = container_of(ptr, struct ccs_execute_handler_record,
1468                                     head);                                     head);
1469                  ee->handler = acl->handler;                  ee->handler = acl->handler;
1470                  return true;                  found = true;
1471                    break;
1472          }          }
1473          return false;          return found;
1474  }  }
1475    
1476  /**  /**
# Line 1642  bool ccs_dump_page(struct linux_binprm * Line 1488  bool ccs_dump_page(struct linux_binprm *
1488          struct page *page;          struct page *page;
1489          /* dump->data is released by ccs_free_execve_entry(). */          /* dump->data is released by ccs_free_execve_entry(). */
1490          if (!dump->data) {          if (!dump->data) {
1491                  dump->data = kmalloc(PAGE_SIZE, GFP_KERNEL);                  dump->data = kzalloc(PAGE_SIZE, GFP_KERNEL);
1492                  if (!dump->data)                  if (!dump->data)
1493                          return false;                          return false;
1494          }          }
# Line 1650  bool ccs_dump_page(struct linux_binprm * Line 1496  bool ccs_dump_page(struct linux_binprm *
1496  #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 23) && defined(CONFIG_MMU)  #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 23) && defined(CONFIG_MMU)
1497          if (get_user_pages(current, bprm->mm, pos, 1, 0, 1, &page, NULL) <= 0)          if (get_user_pages(current, bprm->mm, pos, 1, 0, 1, &page, NULL) <= 0)
1498                  return false;                  return false;
1499    #elif defined(RHEL_MAJOR) && RHEL_MAJOR == 5 && defined(RHEL_MINOR) && RHEL_MINOR == 3 && defined(CONFIG_MMU)
1500            if (get_user_pages(current, bprm->mm, pos, 1, 0, 1, &page, NULL) <= 0)
1501                    return false;
1502  #else  #else
1503          page = bprm->page[pos / PAGE_SIZE];          page = bprm->page[pos / PAGE_SIZE];
1504  #endif  #endif
# Line 1668  bool ccs_dump_page(struct linux_binprm * Line 1517  bool ccs_dump_page(struct linux_binprm *
1517          /* Same with put_arg_page(page) in fs/exec.c */          /* Same with put_arg_page(page) in fs/exec.c */
1518  #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 23) && defined(CONFIG_MMU)  #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 23) && defined(CONFIG_MMU)
1519          put_page(page);          put_page(page);
1520    #elif defined(RHEL_MAJOR) && RHEL_MAJOR == 5 && defined(RHEL_MINOR) && RHEL_MINOR == 3 && defined(CONFIG_MMU)
1521            put_page(page);
1522  #endif  #endif
1523          return true;          return true;
1524  }  }
# Line 1675  bool ccs_dump_page(struct linux_binprm * Line 1526  bool ccs_dump_page(struct linux_binprm *
1526  /**  /**
1527   * ccs_fetch_next_domain - Fetch next_domain from the list.   * ccs_fetch_next_domain - Fetch next_domain from the list.
1528   *   *
1529   * 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()
1530   * succeeds. This function does not return NULL.   * succeeds. This function does not return NULL.
1531   */   */
1532  struct domain_info *ccs_fetch_next_domain(void)  struct ccs_domain_info *ccs_fetch_next_domain(void)
1533  {  {
1534          struct ccs_execve_entry *ee = ccs_find_execve_entry();          struct ccs_execve_entry *ee = ccs_find_execve_entry();
1535          struct domain_info *next_domain = NULL;          struct ccs_domain_info *next_domain = NULL;
1536          if (ee)          if (ee)
1537                  next_domain = ee->next_domain;                  next_domain = ee->r.domain;
1538          if (!next_domain)          if (!next_domain)
1539                  next_domain = current->domain_info;                  next_domain = ccs_current_domain();
1540          return next_domain;          return next_domain;
1541  }  }
1542    
# Line 1705  int ccs_start_execve(struct linux_binprm Line 1556  int ccs_start_execve(struct linux_binprm
1556                  ccs_load_policy(bprm->filename);                  ccs_load_policy(bprm->filename);
1557          if (!ee)          if (!ee)
1558                  return -ENOMEM;                  return -ENOMEM;
1559          ccs_init_request_info(&ee->r, NULL, CCS_TOMOYO_MAC_FOR_FILE);          ccs_init_request_info(&ee->r, NULL, CCS_MAC_FOR_FILE);
1560          ee->r.ee = ee;          ee->r.ee = ee;
1561          ee->bprm = bprm;          ee->bprm = bprm;
1562          ee->r.obj = &ee->obj;          ee->r.obj = &ee->obj;
1563          ee->obj.path1_dentry = bprm->file->f_dentry;          ee->obj.path1_dentry = bprm->file->f_dentry;
1564          ee->obj.path1_vfsmnt = bprm->file->f_vfsmnt;          ee->obj.path1_vfsmnt = bprm->file->f_vfsmnt;
1565          /* Clear manager flag. */          /* Clear manager flag. */
1566          task->tomoyo_flags &= ~CCS_TASK_IS_POLICY_MANAGER;          task->ccs_flags &= ~CCS_TASK_IS_POLICY_MANAGER;
1567          if (ccs_find_execute_handler(ee, TYPE_EXECUTE_HANDLER)) {          if (ccs_find_execute_handler(ee, TYPE_EXECUTE_HANDLER)) {
1568                  retval = ccs_try_alt_exec(ee);                  retval = ccs_try_alt_exec(ee);
1569                  if (!retval)                  if (!retval)
# Line 1730  int ccs_start_execve(struct linux_binprm Line 1581  int ccs_start_execve(struct linux_binprm
1581   ok:   ok:
1582          if (retval < 0)          if (retval < 0)
1583                  goto out;                  goto out;
1584          ee->r.mode = ccs_check_flags(ee->r.domain, CCS_TOMOYO_MAC_FOR_ENV);          ee->r.mode = ccs_check_flags(ee->r.domain, CCS_MAC_FOR_ENV);
1585          retval = ccs_check_environ(ee);          retval = ccs_check_environ(ee);
1586          if (retval < 0)          if (retval < 0)
1587                  goto out;                  goto out;
1588          ee->next_domain = ee->r.domain;          task->ccs_flags |= CCS_CHECK_READ_FOR_OPEN_EXEC;
         task->tomoyo_flags |= TOMOYO_CHECK_READ_FOR_OPEN_EXEC;  
1589          retval = 0;          retval = 0;
1590   out:   out:
1591          if (retval)          if (retval)
# Line 1747  int ccs_start_execve(struct linux_binprm Line 1597  int ccs_start_execve(struct linux_binprm
1597   * ccs_finish_execve - Clean up execve() operation.   * ccs_finish_execve - Clean up execve() operation.
1598   *   *
1599   * @retval: Return code of an execve() operation.   * @retval: Return code of an execve() operation.
1600     *
1601     * Caller holds srcu_read_lock(&ccs_ss).
1602   */   */
1603  void ccs_finish_execve(int retval)  void ccs_finish_execve(int retval)
1604  {  {
1605          struct task_struct *task = current;          struct task_struct *task = current;
1606          struct ccs_execve_entry *ee = ccs_find_execve_entry();          struct ccs_execve_entry *ee = ccs_find_execve_entry();
1607          task->tomoyo_flags &= ~TOMOYO_CHECK_READ_FOR_OPEN_EXEC;          task->ccs_flags &= ~CCS_CHECK_READ_FOR_OPEN_EXEC;
1608          if (!ee)          if (!ee)
1609                  return;                  return;
1610          if (retval < 0)          if (retval < 0)
1611                  goto out;                  goto out;
1612          /* Proceed to next domain if execution suceeded. */          /* Proceed to next domain if execution suceeded. */
1613          task->domain_info = ee->r.domain;          task->ccs_domain_info = ee->r.domain;
         mb(); /* Make domain transition visible to other CPUs. */  
1614          /* Mark the current process as execute handler. */          /* Mark the current process as execute handler. */
1615          if (ee->handler)          if (ee->handler)
1616                  task->tomoyo_flags |= TOMOYO_TASK_IS_EXECUTE_HANDLER;                  task->ccs_flags |= CCS_TASK_IS_EXECUTE_HANDLER;
1617          /* Mark the current process as normal process. */          /* Mark the current process as normal process. */
1618          else          else
1619                  task->tomoyo_flags &= ~TOMOYO_TASK_IS_EXECUTE_HANDLER;                  task->ccs_flags &= ~CCS_TASK_IS_EXECUTE_HANDLER;
1620   out:   out:
1621          ccs_free_execve_entry(ee);          ccs_free_execve_entry(ee);
1622  }  }
   
 #else  
   
 /**  
  * ccs_start_execve - Prepare for execve() operation.  
  *  
  * @bprm: Pointer to "struct linux_binprm".  
  *  
  * Returns 0.  
  */  
 int ccs_start_execve(struct linux_binprm *bprm)  
 {  
 #ifdef CONFIG_SAKURA  
         /* Clear manager flag. */  
         current->tomoyo_flags &= ~CCS_TASK_IS_POLICY_MANAGER;  
         if (!ccs_policy_loaded)  
                 ccs_load_policy(bprm->filename);  
 #endif  
         return 0;  
 }  
   
 /**  
  * ccs_finish_execve - Clean up execve() operation.  
  */  
 void ccs_finish_execve(int retval)  
 {  
 }  
   
 #endif  

Legend:
Removed from v.2219  
changed lines
  Added in v.2718

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