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

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 2080 by kumaneko, Thu Jan 29 00:28:51 2009 UTC branches/ccs-patch/fs/tomoyo_domain.c revision 2691 by kumaneko, Wed Jun 24 05:16:15 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-pre   2009/02/02   * Version: 1.6.8   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;
36    
37  /* The list for "struct domain_info". */  /* The list for "struct ccs_domain_info". */
38  LIST1_HEAD(ccs_domain_list);  LIST_HEAD(ccs_domain_list);
39    
40  #ifdef CONFIG_TOMOYO  #ifdef CONFIG_TOMOYO
41    
 /* Domain creation lock. */  
 static DEFINE_MUTEX(ccs_domain_list_lock);  
   
 /* 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 *****/  
 }  
   
42  /**  /**
43   * ccs_get_last_name - Get last component of a domainname.   * ccs_get_last_name - Get last component of a domainname.
44   *   *
45   * @domain: Pointer to "struct domain_info".   * @domain: Pointer to "struct ccs_domain_info".
46   *   *
47   * Returns the last component of the domainname.   * Returns the last component of the domainname.
48   */   */
49  const char *ccs_get_last_name(const struct domain_info *domain)  const char *ccs_get_last_name(const struct ccs_domain_info *domain)
50  {  {
51          const char *cp0 = domain->domainname->name;          const char *cp0 = domain->domainname->name;
52          const char *cp1 = strrchr(cp0, ' ');          const char *cp1 = strrchr(cp0, ' ');
# Line 118  const char *ccs_get_last_name(const stru Line 58  const char *ccs_get_last_name(const stru
58  /**  /**
59   * ccs_add_domain_acl - Add the given ACL to the given domain.   * ccs_add_domain_acl - Add the given ACL to the given domain.
60   *   *
61   * @domain: Pointer to "struct domain_info". May be NULL.   * @domain: Pointer to "struct ccs_domain_info". May be NULL.
62   * @acl:    Pointer to "struct ccs_acl_info".   * @acl:    Pointer to "struct ccs_acl_info".
63   *   *
64   * Returns 0.   * Returns 0.
65   */   */
66  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)
67  {  {
68          if (domain) {          if (domain) {
69                  /*                  if (acl->cond)
70                   * We need to serialize because this function is called by                          atomic_inc(&acl->cond->users);
71                   * 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 *****/  
72          } else {          } else {
73                  acl->type &= ~ACL_DELETED;                  acl->type &= ~ACL_DELETED;
74          }          }
# Line 171  static int ccs_audit_execute_handler_log Line 104  static int ccs_audit_execute_handler_log
104  {  {
105          struct ccs_request_info *r = &ee->r;          struct ccs_request_info *r = &ee->r;
106          const char *handler = ee->handler->name;          const char *handler = ee->handler->name;
107          r->mode = ccs_check_flags(r->domain, CCS_TOMOYO_MAC_FOR_FILE);          r->mode = ccs_check_flags(r->domain, CCS_MAC_FOR_FILE);
108          return ccs_write_audit_log(true, r, "%s %s\n",          return ccs_write_audit_log(true, r, "%s %s\n",
109                                     is_default ? KEYWORD_EXECUTE_HANDLER :                                     is_default ? KEYWORD_EXECUTE_HANDLER :
110                                     KEYWORD_DENIED_EXECUTE_HANDLER, handler);                                     KEYWORD_DENIED_EXECUTE_HANDLER, handler);
# Line 180  static int ccs_audit_execute_handler_log Line 113  static int ccs_audit_execute_handler_log
113  /**  /**
114   * ccs_audit_domain_creation_log - Audit domain creation log.   * ccs_audit_domain_creation_log - Audit domain creation log.
115   *   *
116   * @domain:  Pointer to "struct domain_info".   * @domain:  Pointer to "struct ccs_domain_info".
117   *   *
118   * Returns 0 on success, negative value otherwise.   * Returns 0 on success, negative value otherwise.
119   */   */
120  static int ccs_audit_domain_creation_log(struct domain_info *domain)  static int ccs_audit_domain_creation_log(struct ccs_domain_info *domain)
121  {  {
122            int error;
123          struct ccs_request_info r;          struct ccs_request_info r;
124          ccs_init_request_info(&r, domain, CCS_TOMOYO_MAC_FOR_FILE);          ccs_init_request_info(&r, domain, CCS_MAC_FOR_FILE);
125          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);
126            ccs_exit_request_info(&r);
127            return error;
128  }  }
129    
130  /* The list for "struct ccs_domain_initializer_entry". */  /* The list for "struct ccs_domain_initializer_entry". */
131  static LIST1_HEAD(ccs_domain_initializer_list);  LIST_HEAD(ccs_domain_initializer_list);
132    
133  /**  /**
134   * 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 145  static int ccs_update_domain_initializer
145                                                 const bool is_not,                                                 const bool is_not,
146                                                 const bool is_delete)                                                 const bool is_delete)
147  {  {
148          struct ccs_domain_initializer_entry *new_entry;          struct ccs_domain_initializer_entry *entry = NULL;
149          struct ccs_domain_initializer_entry *ptr;          struct ccs_domain_initializer_entry *ptr;
         static DEFINE_MUTEX(lock);  
150          const struct ccs_path_info *saved_program;          const struct ccs_path_info *saved_program;
151          const struct ccs_path_info *saved_domainname = NULL;          const struct ccs_path_info *saved_domainname = NULL;
152          int error = -ENOMEM;          int error = is_delete ? -ENOENT : -ENOMEM;
153          bool is_last_name = false;          bool is_last_name = false;
154          if (!ccs_is_correct_path(program, 1, -1, -1, __func__))          if (!ccs_is_correct_path(program, 1, -1, -1))
155                  return -EINVAL; /* No patterns allowed. */                  return -EINVAL; /* No patterns allowed. */
156          if (domainname) {          if (domainname) {
157                  if (!ccs_is_domain_def(domainname) &&                  if (!ccs_is_domain_def(domainname) &&
158                      ccs_is_correct_path(domainname, 1, -1, -1, __func__))                      ccs_is_correct_path(domainname, 1, -1, -1))
159                          is_last_name = true;                          is_last_name = true;
160                  else if (!ccs_is_correct_domain(domainname, __func__))                  else if (!ccs_is_correct_domain(domainname))
161                          return -EINVAL;                          return -EINVAL;
162                  saved_domainname = ccs_save_name(domainname);                  saved_domainname = ccs_get_name(domainname);
163                  if (!saved_domainname)                  if (!saved_domainname)
164                          return -ENOMEM;                          return -ENOMEM;
165          }          }
166          saved_program = ccs_save_name(program);          saved_program = ccs_get_name(program);
167          if (!saved_program)          if (!saved_program) {
168                    ccs_put_name(saved_domainname);
169                  return -ENOMEM;                  return -ENOMEM;
170          mutex_lock(&lock);          }
171          list1_for_each_entry(ptr, &ccs_domain_initializer_list, list) {          if (!is_delete)
172                    entry = kzalloc(sizeof(*entry), GFP_KERNEL);
173            mutex_lock(&ccs_policy_lock);
174            list_for_each_entry_rcu(ptr, &ccs_domain_initializer_list, list) {
175                  if (ptr->is_not != is_not ||                  if (ptr->is_not != is_not ||
176                      ptr->domainname != saved_domainname ||                      ptr->domainname != saved_domainname ||
177                      ptr->program != saved_program)                      ptr->program != saved_program)
178                          continue;                          continue;
179                  ptr->is_deleted = is_delete;                  ptr->is_deleted = is_delete;
180                  error = 0;                  error = 0;
181                  goto out;                  break;
182          }          }
183          if (is_delete) {          if (!is_delete && error && ccs_memory_ok(entry)) {
184                  error = -ENOENT;                  entry->domainname = saved_domainname;
185                  goto out;                  saved_domainname = NULL;
186                    entry->program = saved_program;
187                    saved_program = NULL;
188                    entry->is_not = is_not;
189                    entry->is_last_name = is_last_name;
190                    list_add_tail_rcu(&entry->list, &ccs_domain_initializer_list);
191                    entry = NULL;
192                    error = 0;
193          }          }
194          new_entry = ccs_alloc_element(sizeof(*new_entry));          mutex_unlock(&ccs_policy_lock);
195          if (!new_entry)          ccs_put_name(saved_domainname);
196                  goto out;          ccs_put_name(saved_program);
197          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);  
198          ccs_update_counter(CCS_UPDATES_COUNTER_EXCEPTION_POLICY);          ccs_update_counter(CCS_UPDATES_COUNTER_EXCEPTION_POLICY);
199          return error;          return error;
200  }  }
# Line 266  static int ccs_update_domain_initializer Line 205  static int ccs_update_domain_initializer
205   * @head: Pointer to "struct ccs_io_buffer".   * @head: Pointer to "struct ccs_io_buffer".
206   *   *
207   * Returns true on success, false otherwise.   * Returns true on success, false otherwise.
208     *
209     * Caller holds srcu_read_lock(&ccs_ss).
210   */   */
211  bool ccs_read_domain_initializer_policy(struct ccs_io_buffer *head)  bool ccs_read_domain_initializer_policy(struct ccs_io_buffer *head)
212  {  {
213          struct list1_head *pos;          struct list_head *pos;
214          list1_for_each_cookie(pos, head->read_var2,          bool done = true;
215                                &ccs_domain_initializer_list) {          list_for_each_cookie(pos, head->read_var2,
216                                 &ccs_domain_initializer_list) {
217                  const char *no;                  const char *no;
218                  const char *from = "";                  const char *from = "";
219                  const char *domain = "";                  const char *domain = "";
220                  struct ccs_domain_initializer_entry *ptr;                  struct ccs_domain_initializer_entry *ptr;
221                  ptr = list1_entry(pos, struct ccs_domain_initializer_entry,                  ptr = list_entry(pos, struct ccs_domain_initializer_entry,
222                                    list);                                    list);
223                  if (ptr->is_deleted)                  if (ptr->is_deleted)
224                          continue;                          continue;
# Line 285  bool ccs_read_domain_initializer_policy( Line 227  bool ccs_read_domain_initializer_policy(
227                          from = " from ";                          from = " from ";
228                          domain = ptr->domainname->name;                          domain = ptr->domainname->name;
229                  }                  }
230                  if (!ccs_io_printf(head,                  done = ccs_io_printf(head,
231                                     "%s" KEYWORD_INITIALIZE_DOMAIN "%s%s%s\n",                                       "%s" KEYWORD_INITIALIZE_DOMAIN "%s%s%s\n",
232                                     no, ptr->program->name, from, domain))                                       no, ptr->program->name, from, domain);
233                          goto out;                  if (!done)
234                            break;
235          }          }
236          return true;          return done;
  out:  
         return false;  
237  }  }
238    
239  /**  /**
# Line 326  int ccs_write_domain_initializer_policy( Line 267  int ccs_write_domain_initializer_policy(
267   *   *
268   * Returns true if executing @program reinitializes domain transition,   * Returns true if executing @program reinitializes domain transition,
269   * false otherwise.   * false otherwise.
270     *
271     * Caller holds srcu_read_lock(&ccs_ss).
272   */   */
273  static bool ccs_is_domain_initializer(const struct ccs_path_info *domainname,  static bool ccs_is_domain_initializer(const struct ccs_path_info *domainname,
274                                        const struct ccs_path_info *program,                                        const struct ccs_path_info *program,
# Line 333  static bool ccs_is_domain_initializer(co Line 276  static bool ccs_is_domain_initializer(co
276  {  {
277          struct ccs_domain_initializer_entry *ptr;          struct ccs_domain_initializer_entry *ptr;
278          bool flag = false;          bool flag = false;
279          list1_for_each_entry(ptr, &ccs_domain_initializer_list, list) {          list_for_each_entry_rcu(ptr, &ccs_domain_initializer_list, list) {
280                  if (ptr->is_deleted)                  if (ptr->is_deleted)
281                          continue;                          continue;
282                  if (ptr->domainname) {                  if (ptr->domainname) {
# Line 347  static bool ccs_is_domain_initializer(co Line 290  static bool ccs_is_domain_initializer(co
290                  }                  }
291                  if (ccs_pathcmp(ptr->program, program))                  if (ccs_pathcmp(ptr->program, program))
292                          continue;                          continue;
293                  if (ptr->is_not)                  if (ptr->is_not) {
294                          return false;                          flag = false;
295                            break;
296                    }
297                  flag = true;                  flag = true;
298          }          }
299          return flag;          return flag;
300  }  }
301    
302  /* The list for "struct ccs_domain_keeper_entry". */  /* The list for "struct ccs_domain_keeper_entry". */
303  static LIST1_HEAD(ccs_domain_keeper_list);  LIST_HEAD(ccs_domain_keeper_list);
304    
305  /**  /**
306   * 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 317  static int ccs_update_domain_keeper_entr
317                                            const bool is_not,                                            const bool is_not,
318                                            const bool is_delete)                                            const bool is_delete)
319  {  {
320          struct ccs_domain_keeper_entry *new_entry;          struct ccs_domain_keeper_entry *entry = NULL;
321          struct ccs_domain_keeper_entry *ptr;          struct ccs_domain_keeper_entry *ptr;
322          const struct ccs_path_info *saved_domainname;          const struct ccs_path_info *saved_domainname;
323          const struct ccs_path_info *saved_program = NULL;          const struct ccs_path_info *saved_program = NULL;
324          static DEFINE_MUTEX(lock);          int error = is_delete ? -ENOENT : -ENOMEM;
         int error = -ENOMEM;  
325          bool is_last_name = false;          bool is_last_name = false;
326          if (!ccs_is_domain_def(domainname) &&          if (!ccs_is_domain_def(domainname) &&
327              ccs_is_correct_path(domainname, 1, -1, -1, __func__))              ccs_is_correct_path(domainname, 1, -1, -1))
328                  is_last_name = true;                  is_last_name = true;
329          else if (!ccs_is_correct_domain(domainname, __func__))          else if (!ccs_is_correct_domain(domainname))
330                  return -EINVAL;                  return -EINVAL;
331          if (program) {          if (program) {
332                  if (!ccs_is_correct_path(program, 1, -1, -1, __func__))                  if (!ccs_is_correct_path(program, 1, -1, -1))
333                          return -EINVAL;                          return -EINVAL;
334                  saved_program = ccs_save_name(program);                  saved_program = ccs_get_name(program);
335                  if (!saved_program)                  if (!saved_program)
336                          return -ENOMEM;                          return -ENOMEM;
337          }          }
338          saved_domainname = ccs_save_name(domainname);          saved_domainname = ccs_get_name(domainname);
339          if (!saved_domainname)          if (!saved_domainname) {
340                    ccs_put_name(saved_program);
341                  return -ENOMEM;                  return -ENOMEM;
342          mutex_lock(&lock);          }
343          list1_for_each_entry(ptr, &ccs_domain_keeper_list, list) {          if (!is_delete)
344                    entry = kzalloc(sizeof(*entry), GFP_KERNEL);
345            mutex_lock(&ccs_policy_lock);
346            list_for_each_entry_rcu(ptr, &ccs_domain_keeper_list, list) {
347                  if (ptr->is_not != is_not ||                  if (ptr->is_not != is_not ||
348                      ptr->domainname != saved_domainname ||                      ptr->domainname != saved_domainname ||
349                      ptr->program != saved_program)                      ptr->program != saved_program)
350                          continue;                          continue;
351                  ptr->is_deleted = is_delete;                  ptr->is_deleted = is_delete;
352                  error = 0;                  error = 0;
353                  goto out;                  break;
354          }          }
355          if (is_delete) {          if (!is_delete && error && ccs_memory_ok(entry)) {
356                  error = -ENOENT;                  entry->domainname = saved_domainname;
357                  goto out;                  saved_domainname = NULL;
358                    entry->program = saved_program;
359                    saved_program = NULL;
360                    entry->is_not = is_not;
361                    entry->is_last_name = is_last_name;
362                    list_add_tail_rcu(&entry->list, &ccs_domain_keeper_list);
363                    entry = NULL;
364                    error = 0;
365          }          }
366          new_entry = ccs_alloc_element(sizeof(*new_entry));          mutex_unlock(&ccs_policy_lock);
367          if (!new_entry)          ccs_put_name(saved_domainname);
368                  goto out;          ccs_put_name(saved_program);
369          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);  
370          ccs_update_counter(CCS_UPDATES_COUNTER_EXCEPTION_POLICY);          ccs_update_counter(CCS_UPDATES_COUNTER_EXCEPTION_POLICY);
371          return error;          return error;
372  }  }
# Line 449  int ccs_write_domain_keeper_policy(char Line 397  int ccs_write_domain_keeper_policy(char
397   * @head: Pointer to "struct ccs_io_buffer".   * @head: Pointer to "struct ccs_io_buffer".
398   *   *
399   * Returns true on success, false otherwise.   * Returns true on success, false otherwise.
400     *
401     * Caller holds srcu_read_lock(&ccs_ss).
402   */   */
403  bool ccs_read_domain_keeper_policy(struct ccs_io_buffer *head)  bool ccs_read_domain_keeper_policy(struct ccs_io_buffer *head)
404  {  {
405          struct list1_head *pos;          struct list_head *pos;
406          list1_for_each_cookie(pos, head->read_var2, &ccs_domain_keeper_list) {          bool done = true;
407            list_for_each_cookie(pos, head->read_var2,
408                                 &ccs_domain_keeper_list) {
409                  struct ccs_domain_keeper_entry *ptr;                  struct ccs_domain_keeper_entry *ptr;
410                  const char *no;                  const char *no;
411                  const char *from = "";                  const char *from = "";
412                  const char *program = "";                  const char *program = "";
413                  ptr = list1_entry(pos, struct ccs_domain_keeper_entry, list);                  ptr = list_entry(pos, struct ccs_domain_keeper_entry, list);
414                  if (ptr->is_deleted)                  if (ptr->is_deleted)
415                          continue;                          continue;
416                  no = ptr->is_not ? "no_" : "";                  no = ptr->is_not ? "no_" : "";
# Line 466  bool ccs_read_domain_keeper_policy(struc Line 418  bool ccs_read_domain_keeper_policy(struc
418                          from = " from ";                          from = " from ";
419                          program = ptr->program->name;                          program = ptr->program->name;
420                  }                  }
421                  if (!ccs_io_printf(head,                  done = ccs_io_printf(head,
422                                     "%s" KEYWORD_KEEP_DOMAIN "%s%s%s\n", no,                                       "%s" KEYWORD_KEEP_DOMAIN "%s%s%s\n", no,
423                                     program, from, ptr->domainname->name))                                       program, from, ptr->domainname->name);
424                          goto out;                  if (!done)
425                            break;
426          }          }
427          return true;          return done;
  out:  
         return false;  
428  }  }
429    
430  /**  /**
# Line 485  bool ccs_read_domain_keeper_policy(struc Line 436  bool ccs_read_domain_keeper_policy(struc
436   *   *
437   * Returns true if executing @program supresses domain transition,   * Returns true if executing @program supresses domain transition,
438   * false otherwise.   * false otherwise.
439     *
440     * Caller holds srcu_read_lock(&ccs_ss).
441   */   */
442  static bool ccs_is_domain_keeper(const struct ccs_path_info *domainname,  static bool ccs_is_domain_keeper(const struct ccs_path_info *domainname,
443                                   const struct ccs_path_info *program,                                   const struct ccs_path_info *program,
# Line 492  static bool ccs_is_domain_keeper(const s Line 445  static bool ccs_is_domain_keeper(const s
445  {  {
446          struct ccs_domain_keeper_entry *ptr;          struct ccs_domain_keeper_entry *ptr;
447          bool flag = false;          bool flag = false;
448          list1_for_each_entry(ptr, &ccs_domain_keeper_list, list) {          list_for_each_entry_rcu(ptr, &ccs_domain_keeper_list, list) {
449                  if (ptr->is_deleted)                  if (ptr->is_deleted)
450                          continue;                          continue;
451                  if (!ptr->is_last_name) {                  if (!ptr->is_last_name) {
# Line 504  static bool ccs_is_domain_keeper(const s Line 457  static bool ccs_is_domain_keeper(const s
457                  }                  }
458                  if (ptr->program && ccs_pathcmp(ptr->program, program))                  if (ptr->program && ccs_pathcmp(ptr->program, program))
459                          continue;                          continue;
460                  if (ptr->is_not)                  if (ptr->is_not) {
461                          return false;                          flag = false;
462                            break;
463                    }
464                  flag = true;                  flag = true;
465          }          }
466          return flag;          return flag;
467  }  }
468    
469  /* The list for "struct ccs_alias_entry". */  /* The list for "struct ccs_alias_entry". */
470  static LIST1_HEAD(ccs_alias_list);  LIST_HEAD(ccs_alias_list);
471    
472  /**  /**
473   * 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 482  static int ccs_update_alias_entry(const
482                                    const char *aliased_name,                                    const char *aliased_name,
483                                    const bool is_delete)                                    const bool is_delete)
484  {  {
485          struct ccs_alias_entry *new_entry;          struct ccs_alias_entry *entry = NULL;
486          struct ccs_alias_entry *ptr;          struct ccs_alias_entry *ptr;
         static DEFINE_MUTEX(lock);  
487          const struct ccs_path_info *saved_original_name;          const struct ccs_path_info *saved_original_name;
488          const struct ccs_path_info *saved_aliased_name;          const struct ccs_path_info *saved_aliased_name;
489          int error = -ENOMEM;          int error = is_delete ? -ENOENT : -ENOMEM;
490          if (!ccs_is_correct_path(original_name, 1, -1, -1, __func__) ||          if (!ccs_is_correct_path(original_name, 1, -1, -1) ||
491              !ccs_is_correct_path(aliased_name, 1, -1, -1, __func__))              !ccs_is_correct_path(aliased_name, 1, -1, -1))
492                  return -EINVAL; /* No patterns allowed. */                  return -EINVAL; /* No patterns allowed. */
493          saved_original_name = ccs_save_name(original_name);          saved_original_name = ccs_get_name(original_name);
494          saved_aliased_name = ccs_save_name(aliased_name);          saved_aliased_name = ccs_get_name(aliased_name);
495          if (!saved_original_name || !saved_aliased_name)          if (!saved_original_name || !saved_aliased_name) {
496                    ccs_put_name(saved_original_name);
497                    ccs_put_name(saved_aliased_name);
498                  return -ENOMEM;                  return -ENOMEM;
499          mutex_lock(&lock);          }
500          list1_for_each_entry(ptr, &ccs_alias_list, list) {          if (!is_delete)
501                    entry = kzalloc(sizeof(*entry), GFP_KERNEL);
502            mutex_lock(&ccs_policy_lock);
503            list_for_each_entry_rcu(ptr, &ccs_alias_list, list) {
504                  if (ptr->original_name != saved_original_name ||                  if (ptr->original_name != saved_original_name ||
505                      ptr->aliased_name != saved_aliased_name)                      ptr->aliased_name != saved_aliased_name)
506                          continue;                          continue;
507                  ptr->is_deleted = is_delete;                  ptr->is_deleted = is_delete;
508                  error = 0;                  error = 0;
509                  goto out;                  break;
510          }          }
511          if (is_delete) {          if (!is_delete && error && ccs_memory_ok(entry)) {
512                  error = -ENOENT;                  entry->original_name = saved_original_name;
513                  goto out;                  saved_original_name = NULL;
514                    entry->aliased_name = saved_aliased_name;
515                    saved_aliased_name = NULL;
516                    list_add_tail_rcu(&entry->list, &ccs_alias_list);
517                    entry = NULL;
518                    error = 0;
519          }          }
520          new_entry = ccs_alloc_element(sizeof(*new_entry));          mutex_unlock(&ccs_policy_lock);
521          if (!new_entry)          ccs_put_name(saved_original_name);
522                  goto out;          ccs_put_name(saved_aliased_name);
523          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);  
524          ccs_update_counter(CCS_UPDATES_COUNTER_EXCEPTION_POLICY);          ccs_update_counter(CCS_UPDATES_COUNTER_EXCEPTION_POLICY);
525          return error;          return error;
526  }  }
# Line 572  static int ccs_update_alias_entry(const Line 531  static int ccs_update_alias_entry(const
531   * @head: Pointer to "struct ccs_io_buffer".   * @head: Pointer to "struct ccs_io_buffer".
532   *   *
533   * Returns true on success, false otherwise.   * Returns true on success, false otherwise.
534     *
535     * Caller holds srcu_read_lock(&ccs_ss).
536   */   */
537  bool ccs_read_alias_policy(struct ccs_io_buffer *head)  bool ccs_read_alias_policy(struct ccs_io_buffer *head)
538  {  {
539          struct list1_head *pos;          struct list_head *pos;
540          list1_for_each_cookie(pos, head->read_var2, &ccs_alias_list) {          bool done = true;
541            list_for_each_cookie(pos, head->read_var2, &ccs_alias_list) {
542                  struct ccs_alias_entry *ptr;                  struct ccs_alias_entry *ptr;
543                  ptr = list1_entry(pos, struct ccs_alias_entry, list);                  ptr = list_entry(pos, struct ccs_alias_entry, list);
544                  if (ptr->is_deleted)                  if (ptr->is_deleted)
545                          continue;                          continue;
546                  if (!ccs_io_printf(head, KEYWORD_ALIAS "%s %s\n",                  done = ccs_io_printf(head, KEYWORD_ALIAS "%s %s\n",
547                                     ptr->original_name->name,                                       ptr->original_name->name,
548                                     ptr->aliased_name->name))                                       ptr->aliased_name->name);
549                          goto out;                  if (!done)
550                            break;
551          }          }
552          return true;          return done;
  out:  
         return false;  
553  }  }
554    
555  /**  /**
# Line 609  int ccs_write_alias_policy(char *data, c Line 570  int ccs_write_alias_policy(char *data, c
570  }  }
571    
572  /* The list for "struct ccs_aggregator_entry". */  /* The list for "struct ccs_aggregator_entry". */
573  static LIST1_HEAD(ccs_aggregator_list);  LIST_HEAD(ccs_aggregator_list);
574    
575  /**  /**
576   * 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 585  static int ccs_update_aggregator_entry(c
585                                         const char *aggregated_name,                                         const char *aggregated_name,
586                                         const bool is_delete)                                         const bool is_delete)
587  {  {
588          struct ccs_aggregator_entry *new_entry;          struct ccs_aggregator_entry *entry = NULL;
589          struct ccs_aggregator_entry *ptr;          struct ccs_aggregator_entry *ptr;
         static DEFINE_MUTEX(lock);  
590          const struct ccs_path_info *saved_original_name;          const struct ccs_path_info *saved_original_name;
591          const struct ccs_path_info *saved_aggregated_name;          const struct ccs_path_info *saved_aggregated_name;
592          int error = -ENOMEM;          int error = is_delete ? -ENOENT : -ENOMEM;
593          if (!ccs_is_correct_path(original_name, 1, 0, -1, __func__) ||          if (!ccs_is_correct_path(original_name, 1, 0, -1) ||
594              !ccs_is_correct_path(aggregated_name, 1, -1, -1, __func__))              !ccs_is_correct_path(aggregated_name, 1, -1, -1))
595                  return -EINVAL;                  return -EINVAL;
596          saved_original_name = ccs_save_name(original_name);          saved_original_name = ccs_get_name(original_name);
597          saved_aggregated_name = ccs_save_name(aggregated_name);          saved_aggregated_name = ccs_get_name(aggregated_name);
598          if (!saved_original_name || !saved_aggregated_name)          if (!saved_original_name || !saved_aggregated_name) {
599                    ccs_put_name(saved_original_name);
600                    ccs_put_name(saved_aggregated_name);
601                  return -ENOMEM;                  return -ENOMEM;
602          mutex_lock(&lock);          }
603          list1_for_each_entry(ptr, &ccs_aggregator_list, list) {          if (!is_delete)
604                    entry = kzalloc(sizeof(*entry), GFP_KERNEL);
605            mutex_lock(&ccs_policy_lock);
606            list_for_each_entry_rcu(ptr, &ccs_aggregator_list, list) {
607                  if (ptr->original_name != saved_original_name ||                  if (ptr->original_name != saved_original_name ||
608                      ptr->aggregated_name != saved_aggregated_name)                      ptr->aggregated_name != saved_aggregated_name)
609                          continue;                          continue;
610                  ptr->is_deleted = is_delete;                  ptr->is_deleted = is_delete;
611                  error = 0;                  error = 0;
612                  goto out;                  break;
613          }          }
614          if (is_delete) {          if (!is_delete && error && ccs_memory_ok(entry)) {
615                  error = -ENOENT;                  entry->original_name = saved_original_name;
616                  goto out;                  saved_original_name = NULL;
617                    entry->aggregated_name = saved_aggregated_name;
618                    saved_aggregated_name = NULL;
619                    list_add_tail_rcu(&entry->list, &ccs_aggregator_list);
620                    entry = NULL;
621                    error = 0;
622          }          }
623          new_entry = ccs_alloc_element(sizeof(*new_entry));          mutex_unlock(&ccs_policy_lock);
624          if (!new_entry)          ccs_put_name(saved_original_name);
625                  goto out;          ccs_put_name(saved_aggregated_name);
626          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);  
627          ccs_update_counter(CCS_UPDATES_COUNTER_EXCEPTION_POLICY);          ccs_update_counter(CCS_UPDATES_COUNTER_EXCEPTION_POLICY);
628          return error;          return error;
629  }  }
# Line 669  static int ccs_update_aggregator_entry(c Line 634  static int ccs_update_aggregator_entry(c
634   * @head: Pointer to "struct ccs_io_buffer".   * @head: Pointer to "struct ccs_io_buffer".
635   *   *
636   * Returns true on success, false otherwise.   * Returns true on success, false otherwise.
637     *
638     * Caller holds srcu_read_lock(&ccs_ss).
639   */   */
640  bool ccs_read_aggregator_policy(struct ccs_io_buffer *head)  bool ccs_read_aggregator_policy(struct ccs_io_buffer *head)
641  {  {
642          struct list1_head *pos;          struct list_head *pos;
643          list1_for_each_cookie(pos, head->read_var2, &ccs_aggregator_list) {          bool done = true;
644            list_for_each_cookie(pos, head->read_var2, &ccs_aggregator_list) {
645                  struct ccs_aggregator_entry *ptr;                  struct ccs_aggregator_entry *ptr;
646                  ptr = list1_entry(pos, struct ccs_aggregator_entry, list);                  ptr = list_entry(pos, struct ccs_aggregator_entry, list);
647                  if (ptr->is_deleted)                  if (ptr->is_deleted)
648                          continue;                          continue;
649                  if (!ccs_io_printf(head, KEYWORD_AGGREGATOR "%s %s\n",                  done = ccs_io_printf(head, KEYWORD_AGGREGATOR "%s %s\n",
650                                     ptr->original_name->name,                                       ptr->original_name->name,
651                                     ptr->aggregated_name->name))                                       ptr->aggregated_name->name);
652                          goto out;                  if (!done)
653                            break;
654          }          }
655          return true;          return done;
  out:  
         return false;  
656  }  }
657    
658  /**  /**
# Line 705  int ccs_write_aggregator_policy(char *da Line 672  int ccs_write_aggregator_policy(char *da
672          return ccs_update_aggregator_entry(data, cp, is_delete);          return ccs_update_aggregator_entry(data, cp, is_delete);
673  }  }
674    
675  /* Domain create/delete/undelete handler. */  /* Domain create/delete handler. */
   
 /* #define DEBUG_DOMAIN_UNDELETE */  
676    
677  /**  /**
678   * ccs_delete_domain - Delete a domain.   * ccs_delete_domain - Delete a domain.
# Line 718  int ccs_write_aggregator_policy(char *da Line 683  int ccs_write_aggregator_policy(char *da
683   */   */
684  int ccs_delete_domain(char *domainname)  int ccs_delete_domain(char *domainname)
685  {  {
686          struct domain_info *domain;          struct ccs_domain_info *domain;
687          struct ccs_path_info name;          struct ccs_path_info name;
688          name.name = domainname;          name.name = domainname;
689          ccs_fill_path_info(&name);          ccs_fill_path_info(&name);
690          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  
691          /* Is there an active domain? */          /* Is there an active domain? */
692          list1_for_each_entry(domain, &ccs_domain_list, list) {          list_for_each_entry_rcu(domain, &ccs_domain_list, list) {
693                  struct domain_info *domain2;                  /* Never delete ccs_kernel_domain */
694                  /* Never delete KERNEL_DOMAIN */                  if (domain == &ccs_kernel_domain)
                 if (domain == &KERNEL_DOMAIN)  
695                          continue;                          continue;
696                  if (domain->is_deleted ||                  if (domain->is_deleted ||
697                      ccs_pathcmp(domain->domainname, &name))                      ccs_pathcmp(domain->domainname, &name))
698                          continue;                          continue;
699                  /* 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  
700                  break;                  break;
701          }          }
702          mutex_unlock(&ccs_domain_list_lock);          mutex_unlock(&ccs_policy_lock);
703          return 0;          return 0;
704  }  }
705    
706  /**  /**
  * 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;  
 }  
   
 /**  
707   * ccs_find_or_assign_new_domain - Create a domain.   * ccs_find_or_assign_new_domain - Create a domain.
708   *   *
709   * @domainname: The name of domain.   * @domainname: The name of domain.
710   * @profile:    Profile number to assign if the domain was newly created.   * @profile:    Profile number to assign if the domain was newly created.
711   *   *
712   * Returns pointer to "struct domain_info" on success, NULL otherwise.   * Returns pointer to "struct ccs_domain_info" on success, NULL otherwise.
713   */   */
714  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,
715                                                    const u8 profile)                                                        const u8 profile)
716  {  {
717          struct domain_info *domain = NULL;          struct ccs_domain_info *entry;
718            struct ccs_domain_info *domain;
719          const struct ccs_path_info *saved_domainname;          const struct ccs_path_info *saved_domainname;
720          mutex_lock(&ccs_domain_list_lock);          bool found = false;
721          domain = ccs_find_domain(domainname);  
722          if (domain)          if (!ccs_is_correct_domain(domainname))
723                  goto out;                  return NULL;
724          if (!ccs_is_correct_domain(domainname, __func__))          saved_domainname = ccs_get_name(domainname);
                 goto out;  
         saved_domainname = ccs_save_name(domainname);  
725          if (!saved_domainname)          if (!saved_domainname)
726                  goto out;                  return NULL;
727          /* Can I reuse memory of deleted domain? */          entry = kzalloc(sizeof(*entry), GFP_KERNEL);
728          list1_for_each_entry(domain, &ccs_domain_list, list) {          mutex_lock(&ccs_policy_lock);
729                  struct task_struct *p;          list_for_each_entry_rcu(domain, &ccs_domain_list, list) {
730                  struct ccs_acl_info *ptr;                  if (domain->is_deleted ||
731                  bool flag;                      ccs_pathcmp(saved_domainname, domain->domainname))
732                  if (!domain->is_deleted ||                          continue;
733                      domain->domainname != saved_domainname)                  found = true;
734                          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);  
735          }          }
736   out:          if (!found && ccs_memory_ok(entry)) {
737          mutex_unlock(&ccs_domain_list_lock);                  INIT_LIST_HEAD(&entry->acl_info_list);
738          return domain;                  entry->domainname = saved_domainname;
739                    saved_domainname = NULL;
740                    entry->profile = profile;
741                    list_add_tail_rcu(&entry->list, &ccs_domain_list);
742                    domain = entry;
743                    entry = NULL;
744                    found = true;
745            }
746            mutex_unlock(&ccs_policy_lock);
747            ccs_put_name(saved_domainname);
748            kfree(entry);
749            return found ? domain : NULL;
750  }  }
751    
752  /**  /**
# Line 944  static bool ccs_get_argv0(struct ccs_exe Line 810  static bool ccs_get_argv0(struct ccs_exe
810   * @ee: Pointer to "struct ccs_execve_entry".   * @ee: Pointer to "struct ccs_execve_entry".
811   *   *
812   * Returns 0 on success, negative value otherwise.   * Returns 0 on success, negative value otherwise.
813     *
814     * Caller holds srcu_read_lock(&ccs_ss).
815   */   */
816  static int ccs_find_next_domain(struct ccs_execve_entry *ee)  static int ccs_find_next_domain(struct ccs_execve_entry *ee)
817  {  {
818          struct ccs_request_info *r = &ee->r;          struct ccs_request_info *r = &ee->r;
819          const struct ccs_path_info *handler = ee->handler;          const struct ccs_path_info *handler = ee->handler;
820          struct domain_info *domain = NULL;          struct ccs_domain_info *domain = NULL;
821          const char *old_domain_name = r->domain->domainname->name;          const char *old_domain_name = r->domain->domainname->name;
822          struct linux_binprm *bprm = ee->bprm;          struct linux_binprm *bprm = ee->bprm;
823          const u8 mode = r->mode;          const u8 mode = r->mode;
824          const bool is_enforce = (mode == 3);          const bool is_enforce = (mode == 3);
825          const u32 tomoyo_flags = current->tomoyo_flags;          const u32 ccs_flags = current->ccs_flags;
826          char *new_domain_name = NULL;          char *new_domain_name = NULL;
827          struct ccs_path_info rn; /* real name */          struct ccs_path_info rn; /* real name */
828          struct ccs_path_info sn; /* symlink name */          struct ccs_path_info sn; /* symlink name */
829          struct ccs_path_info ln; /* last name */          struct ccs_path_info ln; /* last name */
830          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;  
                 }  
         }  
   
831   retry:   retry:
832          current->tomoyo_flags = tomoyo_flags;          current->ccs_flags = ccs_flags;
833          r->cond = NULL;          r->cond = NULL;
834          /* Get realpath of program and symbolic link. */          /* Get realpath of program and symbolic link. */
835          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 861  static int ccs_find_next_domain(struct c
861          if (ccs_pathcmp(&rn, &sn)) {          if (ccs_pathcmp(&rn, &sn)) {
862                  struct ccs_alias_entry *ptr;                  struct ccs_alias_entry *ptr;
863                  /* Is this program allowed to be called via symbolic links? */                  /* Is this program allowed to be called via symbolic links? */
864                  list1_for_each_entry(ptr, &ccs_alias_list, list) {                  list_for_each_entry_rcu(ptr, &ccs_alias_list, list) {
865                          if (ptr->is_deleted ||                          if (ptr->is_deleted ||
866                              ccs_pathcmp(&rn, ptr->original_name) ||                              ccs_pathcmp(&rn, ptr->original_name) ||
867                              ccs_pathcmp(&sn, ptr->aliased_name))                              ccs_pathcmp(&sn, ptr->aliased_name))
# Line 1025  static int ccs_find_next_domain(struct c Line 875  static int ccs_find_next_domain(struct c
875          /* sn will be overwritten after here. */          /* sn will be overwritten after here. */
876    
877          /* Compare basename of program_path and argv[0] */          /* Compare basename of program_path and argv[0] */
878          r->mode = ccs_check_flags(r->domain, CCS_TOMOYO_MAC_FOR_ARGV0);          r->mode = ccs_check_flags(r->domain, CCS_MAC_FOR_ARGV0);
879          if (bprm->argc > 0 && r->mode) {          if (bprm->argc > 0 && r->mode) {
880                  char *base_argv0 = ee->tmp;                  char *base_argv0 = ee->tmp;
881                  const char *base_filename;                  const char *base_filename;
# Line 1050  static int ccs_find_next_domain(struct c Line 900  static int ccs_find_next_domain(struct c
900          {          {
901                  struct ccs_aggregator_entry *ptr;                  struct ccs_aggregator_entry *ptr;
902                  /* Is this program allowed to be aggregated? */                  /* Is this program allowed to be aggregated? */
903                  list1_for_each_entry(ptr, &ccs_aggregator_list, list) {                  list_for_each_entry_rcu(ptr, &ccs_aggregator_list, list) {
904                          if (ptr->is_deleted ||                          if (ptr->is_deleted ||
905                              !ccs_path_matches_pattern(&rn, ptr->original_name))                              !ccs_path_matches_pattern(&rn, ptr->original_name))
906                                  continue;                                  continue;
# Line 1072  static int ccs_find_next_domain(struct c Line 922  static int ccs_find_next_domain(struct c
922   calculate_domain:   calculate_domain:
923          new_domain_name = ee->tmp;          new_domain_name = ee->tmp;
924          if (ccs_is_domain_initializer(r->domain->domainname, &rn, &ln)) {          if (ccs_is_domain_initializer(r->domain->domainname, &rn, &ln)) {
925                  /* Transit to the child of KERNEL_DOMAIN domain. */                  /* Transit to the child of ccs_kernel_domain domain. */
926                  snprintf(new_domain_name, CCS_EXEC_TMPSIZE - 1,                  snprintf(new_domain_name, CCS_EXEC_TMPSIZE - 1,
927                           ROOT_NAME " " "%s", ee->program_path);                           ROOT_NAME " " "%s", ee->program_path);
928          } else if (r->domain == &KERNEL_DOMAIN && !ccs_policy_loaded) {          } else if (r->domain == &ccs_kernel_domain && !ccs_policy_loaded) {
929                  /*                  /*
930                   * Needn't to transit from kernel domain before starting                   * Needn't to transit from kernel domain before starting
931                   * /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 956  static int ccs_find_next_domain(struct c
956          }          }
957          domain = ccs_find_or_assign_new_domain(new_domain_name, r->profile);          domain = ccs_find_or_assign_new_domain(new_domain_name, r->profile);
958          if (domain)          if (domain)
959                  ccs_audit_domain_creation_log(domain);                  ccs_audit_domain_creation_log(r->domain);
960   done:   done:
961          if (!domain) {          if (!domain) {
962                  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 965  static int ccs_find_next_domain(struct c
965                          retval = -EPERM;                          retval = -EPERM;
966                  else {                  else {
967                          retval = 0;                          retval = 0;
968                          ccs_set_domain_flag(r->domain, false,                          r->domain->domain_transition_failed = true;
                                             DOMAIN_FLAGS_TRANSITION_FAILED);  
969                  }                  }
970          } else {          } else {
971                  retval = 0;                  retval = 0;
972          }          }
973   out:   out:
974          if (domain)          if (domain)
975                  r->domain = domain;                  r->domain = domain;
976          return retval;          return retval;
977  }  }
978    
# Line 1406  static int ccs_try_alt_exec(struct ccs_e Line 1255  static int ccs_try_alt_exec(struct ccs_e
1255           * modified bprm->argv[0]           * modified bprm->argv[0]
1256           *    = the program's name specified by execute_handler           *    = the program's name specified by execute_handler
1257           * modified bprm->argv[1]           * modified bprm->argv[1]
1258           *    = current->domain_info->domainname->name           *    = ccs_current_domain()->domainname->name
1259           * modified bprm->argv[2]           * modified bprm->argv[2]
1260           *    = the current process's name           *    = the current process's name
1261           * modified bprm->argv[3]           * modified bprm->argv[3]
# Line 1478  static int ccs_try_alt_exec(struct ccs_e Line 1327  static int ccs_try_alt_exec(struct ccs_e
1327          /* Set argv[3] */          /* Set argv[3] */
1328          {          {
1329                  char *cp = ee->tmp;                  char *cp = ee->tmp;
1330                  const u32 tomoyo_flags = task->tomoyo_flags;                  const u32 ccs_flags = task->ccs_flags;
1331                  snprintf(ee->tmp, CCS_EXEC_TMPSIZE - 1,                  snprintf(ee->tmp, CCS_EXEC_TMPSIZE - 1,
1332                           "pid=%d uid=%d gid=%d euid=%d egid=%d suid=%d "                           "pid=%d uid=%d gid=%d euid=%d egid=%d suid=%d "
1333                           "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 1335  static int ccs_try_alt_exec(struct ccs_e
1335                           (pid_t) sys_getpid(), current_uid(), current_gid(),                           (pid_t) sys_getpid(), current_uid(), current_gid(),
1336                           current_euid(), current_egid(), current_suid(),                           current_euid(), current_egid(), current_suid(),
1337                           current_sgid(), current_fsuid(), current_fsgid(),                           current_sgid(), current_fsuid(), current_fsgid(),
1338                           (u8) (tomoyo_flags >> 24), (u8) (tomoyo_flags >> 16),                           (u8) (ccs_flags >> 24), (u8) (ccs_flags >> 16),
1339                           (u8) (tomoyo_flags >> 8));                           (u8) (ccs_flags >> 8));
1340                  retval = copy_strings_kernel(1, &cp, bprm);                  retval = copy_strings_kernel(1, &cp, bprm);
1341                  if (retval < 0)                  if (retval < 0)
1342                          goto out;                          goto out;
# Line 1513  static int ccs_try_alt_exec(struct ccs_e Line 1362  static int ccs_try_alt_exec(struct ccs_e
1362          /* Set argv[1] */          /* Set argv[1] */
1363          {          {
1364                  char *cp = ee->tmp;                  char *cp = ee->tmp;
1365                  strncpy(ee->tmp, task->domain_info->domainname->name,                  strncpy(ee->tmp, ccs_current_domain()->domainname->name,
1366                          CCS_EXEC_TMPSIZE - 1);                          CCS_EXEC_TMPSIZE - 1);
1367                  retval = copy_strings_kernel(1, &cp, bprm);                  retval = copy_strings_kernel(1, &cp, bprm);
1368                  if (retval < 0)                  if (retval < 0)
# Line 1580  static int ccs_try_alt_exec(struct ccs_e Line 1429  static int ccs_try_alt_exec(struct ccs_e
1429  #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 5, 0)  #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 5, 0)
1430                  bprm->interp = bprm->filename;                  bprm->interp = bprm->filename;
1431  #endif  #endif
1432                  task->tomoyo_flags |= CCS_DONT_SLEEP_ON_ENFORCE_ERROR;                  task->ccs_flags |= CCS_DONT_SLEEP_ON_ENFORCE_ERROR;
1433                  retval = ccs_find_next_domain(ee);                  retval = ccs_find_next_domain(ee);
1434                  task->tomoyo_flags &= ~CCS_DONT_SLEEP_ON_ENFORCE_ERROR;                  task->ccs_flags &= ~CCS_DONT_SLEEP_ON_ENFORCE_ERROR;
1435                  /* Restore ee->program_path for search_binary_handler(). */                  /* Restore ee->program_path for search_binary_handler(). */
1436                  memmove(ee->program_path, cp, len);                  memmove(ee->program_path, cp, len);
1437                  bprm->filename = ee->program_path;                  bprm->filename = ee->program_path;
# Line 1602  static int ccs_try_alt_exec(struct ccs_e Line 1451  static int ccs_try_alt_exec(struct ccs_e
1451   * @type: Type of execute handler.   * @type: Type of execute handler.
1452   *   *
1453   * Returns true if found, false otherwise.   * Returns true if found, false otherwise.
1454     *
1455     * Caller holds srcu_read_lock(&ccs_ss).
1456   */   */
1457  static bool ccs_find_execute_handler(struct ccs_execve_entry *ee,  static bool ccs_find_execute_handler(struct ccs_execve_entry *ee,
1458                                       const u8 type)                                       const u8 type)
1459  {  {
1460          struct task_struct *task = current;          struct task_struct *task = current;
1461          const struct domain_info *domain = task->domain_info;          const struct ccs_domain_info *domain = ccs_current_domain();
1462          struct ccs_acl_info *ptr;          struct ccs_acl_info *ptr;
1463            bool found = false;
1464          /*          /*
1465           * Don't use execute handler if the current process is           * Don't use execute handler if the current process is
1466           * marked as execute handler to avoid infinite execute handler loop.           * marked as execute handler to avoid infinite execute handler loop.
1467           */           */
1468          if (task->tomoyo_flags & TOMOYO_TASK_IS_EXECUTE_HANDLER)          if (task->ccs_flags & CCS_TASK_IS_EXECUTE_HANDLER)
1469                  return false;                  return false;
1470          list1_for_each_entry(ptr, &domain->acl_info_list, list) {          list_for_each_entry(ptr, &domain->acl_info_list, list) {
1471                  struct ccs_execute_handler_record *acl;                  struct ccs_execute_handler_record *acl;
1472                  if (ptr->type != type)                  if (ptr->type != type)
1473                          continue;                          continue;
1474                  acl = container_of(ptr, struct ccs_execute_handler_record,                  acl = container_of(ptr, struct ccs_execute_handler_record,
1475                                     head);                                     head);
1476                  ee->handler = acl->handler;                  ee->handler = acl->handler;
1477                  return true;                  found = true;
1478                    break;
1479          }          }
1480          return false;          return found;
1481  }  }
1482    
1483  /**  /**
# Line 1650  bool ccs_dump_page(struct linux_binprm * Line 1503  bool ccs_dump_page(struct linux_binprm *
1503  #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 23) && defined(CONFIG_MMU)  #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 23) && defined(CONFIG_MMU)
1504          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)
1505                  return false;                  return false;
1506    #elif defined(RHEL_MAJOR) && RHEL_MAJOR == 5 && defined(RHEL_MINOR) && RHEL_MINOR == 3 && defined(CONFIG_MMU)
1507            if (get_user_pages(current, bprm->mm, pos, 1, 0, 1, &page, NULL) <= 0)
1508                    return false;
1509  #else  #else
1510          page = bprm->page[pos / PAGE_SIZE];          page = bprm->page[pos / PAGE_SIZE];
1511  #endif  #endif
# Line 1668  bool ccs_dump_page(struct linux_binprm * Line 1524  bool ccs_dump_page(struct linux_binprm *
1524          /* Same with put_arg_page(page) in fs/exec.c */          /* Same with put_arg_page(page) in fs/exec.c */
1525  #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 23) && defined(CONFIG_MMU)  #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 23) && defined(CONFIG_MMU)
1526          put_page(page);          put_page(page);
1527    #elif defined(RHEL_MAJOR) && RHEL_MAJOR == 5 && defined(RHEL_MINOR) && RHEL_MINOR == 3 && defined(CONFIG_MMU)
1528            put_page(page);
1529  #endif  #endif
1530          return true;          return true;
1531  }  }
# Line 1675  bool ccs_dump_page(struct linux_binprm * Line 1533  bool ccs_dump_page(struct linux_binprm *
1533  /**  /**
1534   * ccs_fetch_next_domain - Fetch next_domain from the list.   * ccs_fetch_next_domain - Fetch next_domain from the list.
1535   *   *
1536   * 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()
1537   * succeeds. This function does not return NULL.   * succeeds. This function does not return NULL.
1538   */   */
1539  struct domain_info *ccs_fetch_next_domain(void)  struct ccs_domain_info *ccs_fetch_next_domain(void)
1540  {  {
1541          struct ccs_execve_entry *ee = ccs_find_execve_entry();          struct ccs_execve_entry *ee = ccs_find_execve_entry();
1542          struct domain_info *next_domain = NULL;          struct ccs_domain_info *next_domain = NULL;
1543          if (ee)          if (ee)
1544                  next_domain = ee->next_domain;                  next_domain = ee->r.domain;
1545          if (!next_domain)          if (!next_domain)
1546                  next_domain = current->domain_info;                  next_domain = ccs_current_domain();
1547          return next_domain;          return next_domain;
1548  }  }
1549    
# Line 1705  int ccs_start_execve(struct linux_binprm Line 1563  int ccs_start_execve(struct linux_binprm
1563                  ccs_load_policy(bprm->filename);                  ccs_load_policy(bprm->filename);
1564          if (!ee)          if (!ee)
1565                  return -ENOMEM;                  return -ENOMEM;
1566          ccs_init_request_info(&ee->r, NULL, CCS_TOMOYO_MAC_FOR_FILE);          ccs_init_request_info(&ee->r, NULL, CCS_MAC_FOR_FILE);
1567          ee->r.ee = ee;          ee->r.ee = ee;
1568          ee->bprm = bprm;          ee->bprm = bprm;
1569          ee->r.obj = &ee->obj;          ee->r.obj = &ee->obj;
1570          ee->obj.path1_dentry = bprm->file->f_dentry;          ee->obj.path1_dentry = bprm->file->f_dentry;
1571          ee->obj.path1_vfsmnt = bprm->file->f_vfsmnt;          ee->obj.path1_vfsmnt = bprm->file->f_vfsmnt;
1572          /* Clear manager flag. */          /* Clear manager flag. */
1573          task->tomoyo_flags &= ~CCS_TASK_IS_POLICY_MANAGER;          task->ccs_flags &= ~CCS_TASK_IS_POLICY_MANAGER;
1574          if (ccs_find_execute_handler(ee, TYPE_EXECUTE_HANDLER)) {          if (ccs_find_execute_handler(ee, TYPE_EXECUTE_HANDLER)) {
1575                  retval = ccs_try_alt_exec(ee);                  retval = ccs_try_alt_exec(ee);
1576                  if (!retval)                  if (!retval)
# Line 1730  int ccs_start_execve(struct linux_binprm Line 1588  int ccs_start_execve(struct linux_binprm
1588   ok:   ok:
1589          if (retval < 0)          if (retval < 0)
1590                  goto out;                  goto out;
1591          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);
1592          retval = ccs_check_environ(ee);          retval = ccs_check_environ(ee);
1593          if (retval < 0)          if (retval < 0)
1594                  goto out;                  goto out;
1595          ee->next_domain = ee->r.domain;          task->ccs_flags |= CCS_CHECK_READ_FOR_OPEN_EXEC;
         task->tomoyo_flags |= TOMOYO_CHECK_READ_FOR_OPEN_EXEC;  
1596          retval = 0;          retval = 0;
1597   out:   out:
1598          if (retval)          if (retval)
# Line 1747  int ccs_start_execve(struct linux_binprm Line 1604  int ccs_start_execve(struct linux_binprm
1604   * ccs_finish_execve - Clean up execve() operation.   * ccs_finish_execve - Clean up execve() operation.
1605   *   *
1606   * @retval: Return code of an execve() operation.   * @retval: Return code of an execve() operation.
1607     *
1608     * Caller holds srcu_read_lock(&ccs_ss).
1609   */   */
1610  void ccs_finish_execve(int retval)  void ccs_finish_execve(int retval)
1611  {  {
1612          struct task_struct *task = current;          struct task_struct *task = current;
1613          struct ccs_execve_entry *ee = ccs_find_execve_entry();          struct ccs_execve_entry *ee = ccs_find_execve_entry();
1614          task->tomoyo_flags &= ~TOMOYO_CHECK_READ_FOR_OPEN_EXEC;          task->ccs_flags &= ~CCS_CHECK_READ_FOR_OPEN_EXEC;
1615          if (!ee)          if (!ee)
1616                  return;                  return;
1617          if (retval < 0)          if (retval < 0)
1618                  goto out;                  goto out;
1619          /* Proceed to next domain if execution suceeded. */          /* Proceed to next domain if execution suceeded. */
1620          task->domain_info = ee->r.domain;          task->ccs_domain_info = ee->r.domain;
         mb(); /* Make domain transition visible to other CPUs. */  
1621          /* Mark the current process as execute handler. */          /* Mark the current process as execute handler. */
1622          if (ee->handler)          if (ee->handler)
1623                  task->tomoyo_flags |= TOMOYO_TASK_IS_EXECUTE_HANDLER;                  task->ccs_flags |= CCS_TASK_IS_EXECUTE_HANDLER;
1624          /* Mark the current process as normal process. */          /* Mark the current process as normal process. */
1625          else          else
1626                  task->tomoyo_flags &= ~TOMOYO_TASK_IS_EXECUTE_HANDLER;                  task->ccs_flags &= ~CCS_TASK_IS_EXECUTE_HANDLER;
1627   out:   out:
1628            ccs_exit_request_info(&ee->r);
1629          ccs_free_execve_entry(ee);          ccs_free_execve_entry(ee);
1630  }  }
1631    
# Line 1783  int ccs_start_execve(struct linux_binprm Line 1642  int ccs_start_execve(struct linux_binprm
1642  {  {
1643  #ifdef CONFIG_SAKURA  #ifdef CONFIG_SAKURA
1644          /* Clear manager flag. */          /* Clear manager flag. */
1645          current->tomoyo_flags &= ~CCS_TASK_IS_POLICY_MANAGER;          current->ccs_flags &= ~CCS_TASK_IS_POLICY_MANAGER;
1646          if (!ccs_policy_loaded)          if (!ccs_policy_loaded)
1647                  ccs_load_policy(bprm->filename);                  ccs_load_policy(bprm->filename);
1648  #endif  #endif

Legend:
Removed from v.2080  
changed lines
  Added in v.2691

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