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

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.5.x/ccs-patch/fs/tomoyo_domain.c revision 502 by kumaneko, Tue Sep 25 13:33:45 2007 UTC trunk/1.6.x/ccs-patch/fs/tomoyo_domain.c revision 1005 by kumaneko, Mon Feb 25 04:57:38 2008 UTC
# Line 3  Line 3 
3   *   *
4   * Implementation of the Domain-Based Mandatory Access Control.   * Implementation of the Domain-Based Mandatory Access Control.
5   *   *
6   * Copyright (C) 2005-2007  NTT DATA CORPORATION   * Copyright (C) 2005-2008  NTT DATA CORPORATION
7   *   *
8   * Version: 1.5.0   2007/09/20   * Version: 1.6.0-pre   2008/02/25
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 26  Line 26 
26  /*************************  VARIABLES  *************************/  /*************************  VARIABLES  *************************/
27    
28  /* The initial domain. */  /* The initial domain. */
29  struct domain_info KERNEL_DOMAIN = { NULL, NULL, NULL, 0, 0, 0 };  struct domain_info KERNEL_DOMAIN;
30    
31    /* List of domains. */
32    LIST1_HEAD(domain_list);
33    
34  /* /sbin/init started? */  /* /sbin/init started? */
35  extern int sbin_init_started;  extern bool sbin_init_started;
36    
37  #ifdef CONFIG_TOMOYO  #ifdef CONFIG_TOMOYO
38    
39  /* Lock for appending domain's ACL. */  /* Lock for appending domain's ACL. */
40  DECLARE_MUTEX(domain_acl_lock);  DEFINE_MUTEX(domain_acl_lock);
41    
42  /*************************  UTILITY FUNCTIONS  *************************/  /*************************  UTILITY FUNCTIONS  *************************/
43    
44  /***** The structure for program files to force domain reconstruction. *****/  /***** The structure for program files to force domain reconstruction. *****/
45    
46  struct domain_initializer_entry {  struct domain_initializer_entry {
47          struct domain_initializer_entry *next;          struct list1_head list;
48          const struct path_info *domainname;    /* This may be NULL */          const struct path_info *domainname;    /* This may be NULL */
49          const struct path_info *program;          const struct path_info *program;
50          u8 is_deleted;          bool is_deleted;
51          u8 is_not;          bool is_not;
52          u8 is_last_name;          bool is_last_name;
53  };  };
54    
55  /***** The structure for domains to not to transit domains. *****/  /***** The structure for domains to not to transit domains. *****/
56    
57  struct domain_keeper_entry {  struct domain_keeper_entry {
58          struct domain_keeper_entry *next;          struct list1_head list;
59          const struct path_info *domainname;          const struct path_info *domainname;
60          const struct path_info *program;       /* This may be NULL */          const struct path_info *program;       /* This may be NULL */
61          u8 is_deleted;          bool is_deleted;
62          u8 is_not;          bool is_not;
63          u8 is_last_name;          bool is_last_name;
64  };  };
65    
66  /***** The structure for program files that should be aggregated. *****/  /***** The structure for program files that should be aggregated. *****/
67    
68  struct aggregator_entry {  struct aggregator_entry {
69          struct aggregator_entry *next;          struct list1_head list;
70          const struct path_info *original_name;          const struct path_info *original_name;
71          const struct path_info *aggregated_name;          const struct path_info *aggregated_name;
72          int is_deleted;          bool is_deleted;
73  };  };
74    
75  /***** The structure for program files that should be aliased. *****/  /***** The structure for program files that should be aliased. *****/
76    
77  struct alias_entry {  struct alias_entry {
78          struct alias_entry *next;          struct list1_head list;
79          const struct path_info *original_name;          const struct path_info *original_name;
80          const struct path_info *aliased_name;          const struct path_info *aliased_name;
81          int is_deleted;          bool is_deleted;
82  };  };
83    
84  /*************************  VARIABLES  *************************/  /*************************  VARIABLES  *************************/
85    
86  /* Domain creation lock. */  /* Domain creation lock. */
87  static DECLARE_MUTEX(new_domain_assign_lock);  static DEFINE_MUTEX(new_domain_assign_lock);
88    
89  /*************************  UTILITY FUNCTIONS  *************************/  /*************************  UTILITY FUNCTIONS  *************************/
90    
# Line 92  const char *GetLastName(const struct dom Line 95  const char *GetLastName(const struct dom
95          return cp0;          return cp0;
96  }  }
97    
98  int AddDomainACL(struct acl_info *ptr, struct domain_info *domain, struct acl_info *new_ptr)  int AddDomainACL(struct domain_info *domain, struct acl_info *acl)
99  {  {
100          mb(); /* Instead of using spinlock. */          if (domain) list1_add_tail_mb(&acl->list, &domain->acl_info_list);
101          if (!ptr) domain->first_acl_ptr = (struct acl_info *) new_ptr;          else acl->type &= ~ACL_DELETED;
         else ptr->next = (struct acl_info *) new_ptr;  
102          UpdateCounter(CCS_UPDATES_COUNTER_DOMAIN_POLICY);          UpdateCounter(CCS_UPDATES_COUNTER_DOMAIN_POLICY);
103          return 0;          return 0;
104  }  }
105    
106  int DelDomainACL(struct acl_info *ptr)  int DelDomainACL(struct acl_info *acl)
107  {  {
108          ptr->is_deleted = 1;          if (acl) acl->type |= ACL_DELETED;
109          UpdateCounter(CCS_UPDATES_COUNTER_DOMAIN_POLICY);          UpdateCounter(CCS_UPDATES_COUNTER_DOMAIN_POLICY);
110          return 0;          return 0;
111  }  }
112    
 int TooManyDomainACL(struct domain_info * const domain) {  
         unsigned int count = 0;  
         struct acl_info *ptr;  
         for (ptr = domain->first_acl_ptr; ptr; ptr = ptr->next) {  
                 if (!ptr->is_deleted) count++;  
         }  
         /* If there are so many entries, don't append if learning mode. */  
         if (count < CheckCCSFlags(CCS_TOMOYO_MAX_ACCEPT_ENTRY)) return 0;  
         if (!domain->quota_warned) {  
                 printk("TOMOYO-WARNING: Domain '%s' has so many ACLs to hold. Stopped learning mode.\n", domain->domainname->name);  
                 domain->quota_warned = 1;  
         }  
         return 1;  
 }  
   
   
113  /*************************  DOMAIN INITIALIZER HANDLER  *************************/  /*************************  DOMAIN INITIALIZER HANDLER  *************************/
114    
115  static struct domain_initializer_entry *domain_initializer_list = NULL;  static LIST1_HEAD(domain_initializer_list);
116    
117  static int AddDomainInitializerEntry(const char *domainname, const char *program, const int is_not, const int is_delete)  static int AddDomainInitializerEntry(const char *domainname, const char *program, const bool is_not, const bool is_delete)
118  {  {
119          struct domain_initializer_entry *new_entry, *ptr;          struct domain_initializer_entry *new_entry, *ptr;
120          static DECLARE_MUTEX(lock);          static DEFINE_MUTEX(lock);
121          const struct path_info *saved_program, *saved_domainname = NULL;          const struct path_info *saved_program, *saved_domainname = NULL;
122          int error = -ENOMEM;          int error = -ENOMEM;
123          int is_last_name = 0;          bool is_last_name = 0;
124          if (!IsCorrectPath(program, 1, -1, -1, __FUNCTION__)) return -EINVAL; /* No patterns allowed. */          if (!IsCorrectPath(program, 1, -1, -1, __FUNCTION__)) return -EINVAL; /* No patterns allowed. */
125          if (domainname) {          if (domainname) {
126                  if (!IsDomainDef(domainname) && IsCorrectPath(domainname, 1, -1, -1, __FUNCTION__)) {                  if (!IsDomainDef(domainname) && IsCorrectPath(domainname, 1, -1, -1, __FUNCTION__)) {
# Line 145  static int AddDomainInitializerEntry(con Line 131  static int AddDomainInitializerEntry(con
131                  if ((saved_domainname = SaveName(domainname)) == NULL) return -ENOMEM;                  if ((saved_domainname = SaveName(domainname)) == NULL) return -ENOMEM;
132          }          }
133          if ((saved_program = SaveName(program)) == NULL) return -ENOMEM;          if ((saved_program = SaveName(program)) == NULL) return -ENOMEM;
134          down(&lock);          mutex_lock(&lock);
135          for (ptr = domain_initializer_list; ptr; ptr = ptr->next) {          list1_for_each_entry(ptr, &domain_initializer_list, list) {
136                  if (ptr->is_not == is_not && ptr->domainname == saved_domainname && ptr->program == saved_program) {                  if (ptr->is_not == is_not && ptr->domainname == saved_domainname && ptr->program == saved_program) {
137                          ptr->is_deleted = is_delete;                          ptr->is_deleted = is_delete;
138                          error = 0;                          error = 0;
# Line 162  static int AddDomainInitializerEntry(con Line 148  static int AddDomainInitializerEntry(con
148          new_entry->program = saved_program;          new_entry->program = saved_program;
149          new_entry->is_not = is_not;          new_entry->is_not = is_not;
150          new_entry->is_last_name = is_last_name;          new_entry->is_last_name = is_last_name;
151          mb(); /* Instead of using spinlock. */          list1_add_tail_mb(&new_entry->list, &domain_initializer_list);
         if ((ptr = domain_initializer_list) != NULL) {  
                 while (ptr->next) ptr = ptr->next; ptr->next = new_entry;  
         } else {  
                 domain_initializer_list = new_entry;  
         }  
152          error = 0;          error = 0;
153   out:   out:
154          up(&lock);          mutex_unlock(&lock);
155          return error;          return error;
156  }  }
157    
158  int ReadDomainInitializerPolicy(struct io_buffer *head)  int ReadDomainInitializerPolicy(struct io_buffer *head)
159  {  {
160          struct domain_initializer_entry *ptr = head->read_var2;          struct list1_head *pos;
161          if (!ptr) ptr = domain_initializer_list;          list1_for_each_cookie(pos, head->read_var2, &domain_initializer_list) {
162          while (ptr) {                  struct domain_initializer_entry *ptr;
163                  head->read_var2 = ptr;                  ptr = list1_entry(pos, struct domain_initializer_entry, list);
164                  if (!ptr->is_deleted) {                  if (ptr->is_deleted) continue;
165                          if (ptr->domainname) {                  if (ptr->domainname) {
166                                  if (io_printf(head, "%s" KEYWORD_INITIALIZE_DOMAIN "%s from %s\n", ptr->is_not ? "no_" : "", ptr->program->name, ptr->domainname->name)) break;                          if (io_printf(head, "%s" KEYWORD_INITIALIZE_DOMAIN "%s from %s\n", ptr->is_not ? "no_" : "", ptr->program->name, ptr->domainname->name)) return -ENOMEM;
167                          } else {                  } else {
168                                  if (io_printf(head, "%s" KEYWORD_INITIALIZE_DOMAIN "%s\n", ptr->is_not ? "no_" : "", ptr->program->name)) break;                          if (io_printf(head, "%s" KEYWORD_INITIALIZE_DOMAIN "%s\n", ptr->is_not ? "no_" : "", ptr->program->name)) return -ENOMEM;
                         }  
169                  }                  }
                 ptr = ptr->next;  
170          }          }
171          return ptr ? -ENOMEM : 0;          return 0;
172  }  }
173    
174  int AddDomainInitializerPolicy(char *data, const int is_not, const int is_delete)  int AddDomainInitializerPolicy(char *data, const bool is_not, const bool is_delete)
175  {  {
176          char *cp = strstr(data, " from ");          char *cp = strstr(data, " from ");
177          if (cp) {          if (cp) {
# Line 203  int AddDomainInitializerPolicy(char *dat Line 182  int AddDomainInitializerPolicy(char *dat
182          }          }
183  }  }
184    
185  static int IsDomainInitializer(const struct path_info *domainname, const struct path_info *program, const struct path_info *last_name)  static bool IsDomainInitializer(const struct path_info *domainname, const struct path_info *program, const struct path_info *last_name)
186  {  {
187          struct domain_initializer_entry *ptr;          struct domain_initializer_entry *ptr;
188          int flag = 0;          bool flag = 0;
189          for (ptr = domain_initializer_list; ptr; ptr = ptr->next) {          list1_for_each_entry(ptr,  &domain_initializer_list, list) {
190                  if (ptr->is_deleted ) continue;                  if (ptr->is_deleted) continue;
191                  if (ptr->domainname) {                  if (ptr->domainname) {
192                          if (!ptr->is_last_name) {                          if (!ptr->is_last_name) {
193                                  if (ptr->domainname != domainname) continue;                                  if (ptr->domainname != domainname) continue;
# Line 225  static int IsDomainInitializer(const str Line 204  static int IsDomainInitializer(const str
204    
205  /*************************  DOMAIN KEEPER HANDLER  *************************/  /*************************  DOMAIN KEEPER HANDLER  *************************/
206    
207  static struct domain_keeper_entry *domain_keeper_list = NULL;  static LIST1_HEAD(domain_keeper_list);
208    
209  static int AddDomainKeeperEntry(const char *domainname, const char *program, const int is_not, const int is_delete)  static int AddDomainKeeperEntry(const char *domainname, const char *program, const bool is_not, const bool is_delete)
210  {  {
211          struct domain_keeper_entry *new_entry, *ptr;          struct domain_keeper_entry *new_entry, *ptr;
212          const struct path_info *saved_domainname, *saved_program = NULL;          const struct path_info *saved_domainname, *saved_program = NULL;
213          static DECLARE_MUTEX(lock);          static DEFINE_MUTEX(lock);
214          int error = -ENOMEM;          int error = -ENOMEM;
215          int is_last_name = 0;          bool is_last_name = 0;
216          if (!IsDomainDef(domainname) && IsCorrectPath(domainname, 1, -1, -1, __FUNCTION__)) {          if (!IsDomainDef(domainname) && IsCorrectPath(domainname, 1, -1, -1, __FUNCTION__)) {
217                  is_last_name = 1;                  is_last_name = 1;
218          } else if (!IsCorrectDomain(domainname, __FUNCTION__)) {          } else if (!IsCorrectDomain(domainname, __FUNCTION__)) {
# Line 244  static int AddDomainKeeperEntry(const ch Line 223  static int AddDomainKeeperEntry(const ch
223                  if ((saved_program = SaveName(program)) == NULL) return -ENOMEM;                  if ((saved_program = SaveName(program)) == NULL) return -ENOMEM;
224          }          }
225          if ((saved_domainname = SaveName(domainname)) == NULL) return -ENOMEM;          if ((saved_domainname = SaveName(domainname)) == NULL) return -ENOMEM;
226          down(&lock);          mutex_lock(&lock);
227          for (ptr = domain_keeper_list; ptr; ptr = ptr->next) {          list1_for_each_entry(ptr, &domain_keeper_list, list) {
228                  if (ptr->is_not == is_not && ptr->domainname == saved_domainname && ptr->program == saved_program) {                  if (ptr->is_not == is_not && ptr->domainname == saved_domainname && ptr->program == saved_program) {
229                          ptr->is_deleted = is_delete;                          ptr->is_deleted = is_delete;
230                          error = 0;                          error = 0;
# Line 261  static int AddDomainKeeperEntry(const ch Line 240  static int AddDomainKeeperEntry(const ch
240          new_entry->program = saved_program;          new_entry->program = saved_program;
241          new_entry->is_not = is_not;          new_entry->is_not = is_not;
242          new_entry->is_last_name = is_last_name;          new_entry->is_last_name = is_last_name;
243          mb(); /* Instead of using spinlock. */          list1_add_tail_mb(&new_entry->list, &domain_keeper_list);
         if ((ptr = domain_keeper_list) != NULL) {  
                 while (ptr->next) ptr = ptr->next; ptr->next = new_entry;  
         } else {  
                 domain_keeper_list = new_entry;  
         }  
244          error = 0;          error = 0;
245   out:   out:
246          up(&lock);          mutex_unlock(&lock);
247          return error;          return error;
248  }  }
249    
250  int AddDomainKeeperPolicy(char *data, const int is_not, const int is_delete)  int AddDomainKeeperPolicy(char *data, const bool is_not, const bool is_delete)
251  {  {
252          char *cp = strstr(data, " from ");          char *cp = strstr(data, " from ");
253          if (cp) {          if (cp) {
# Line 286  int AddDomainKeeperPolicy(char *data, co Line 260  int AddDomainKeeperPolicy(char *data, co
260    
261  int ReadDomainKeeperPolicy(struct io_buffer *head)  int ReadDomainKeeperPolicy(struct io_buffer *head)
262  {  {
263          struct domain_keeper_entry *ptr = head->read_var2;          struct list1_head *pos;
264          if (!ptr) ptr = domain_keeper_list;          list1_for_each_cookie(pos, head->read_var2, &domain_keeper_list) {
265          while (ptr) {                  struct domain_keeper_entry *ptr;
266                  head->read_var2 = ptr;                  ptr = list1_entry(pos, struct domain_keeper_entry, list);
267                  if (!ptr->is_deleted) {                  if (ptr->is_deleted) continue;
268                          if (ptr->program) {                  if (ptr->program) {
269                                  if (io_printf(head, "%s" KEYWORD_KEEP_DOMAIN "%s from %s\n", ptr->is_not ? "no_" : "", ptr->program->name, ptr->domainname->name)) break;                          if (io_printf(head, "%s" KEYWORD_KEEP_DOMAIN "%s from %s\n", ptr->is_not ? "no_" : "", ptr->program->name, ptr->domainname->name)) return -ENOMEM;
270                          } else {                  } else {
271                                  if (io_printf(head, "%s" KEYWORD_KEEP_DOMAIN "%s\n", ptr->is_not ? "no_" : "", ptr->domainname->name)) break;                          if (io_printf(head, "%s" KEYWORD_KEEP_DOMAIN "%s\n", ptr->is_not ? "no_" : "", ptr->domainname->name)) return -ENOMEM;
                         }  
272                  }                  }
                 ptr = ptr->next;  
273          }          }
274          return ptr ? -ENOMEM : 0;          return 0;
275  }  }
276    
277  static int IsDomainKeeper(const struct path_info *domainname, const struct path_info *program, const struct path_info *last_name)  static bool IsDomainKeeper(const struct path_info *domainname, const struct path_info *program, const struct path_info *last_name)
278  {  {
279          struct domain_keeper_entry *ptr;          struct domain_keeper_entry *ptr;
280          int flag = 0;          bool flag = 0;
281          for (ptr = domain_keeper_list; ptr; ptr = ptr->next) {          list1_for_each_entry(ptr, &domain_keeper_list, list) {
282                  if (ptr->is_deleted) continue;                  if (ptr->is_deleted) continue;
283                  if (!ptr->is_last_name) {                  if (!ptr->is_last_name) {
284                          if (ptr->domainname != domainname) continue;                          if (ptr->domainname != domainname) continue;
285                  } else {                  } else {
286                          if (pathcmp(ptr->domainname, last_name)) continue;                          if (pathcmp(ptr->domainname, last_name)) continue;
287                  }                  }
288                  if (ptr->program && pathcmp(ptr->program, program)) continue;                  if (ptr->program && pathcmp(ptr->program, program)) continue;
289                  if (ptr->is_not) return 0;                  if (ptr->is_not) return 0;
# Line 322  static int IsDomainKeeper(const struct p Line 294  static int IsDomainKeeper(const struct p
294    
295  /*************************  SYMBOLIC LINKED PROGRAM HANDLER  *************************/  /*************************  SYMBOLIC LINKED PROGRAM HANDLER  *************************/
296    
297  static struct alias_entry *alias_list = NULL;  static LIST1_HEAD(alias_list);
298    
299  static int AddAliasEntry(const char *original_name, const char *aliased_name, const int is_delete)  static int AddAliasEntry(const char *original_name, const char *aliased_name, const bool is_delete)
300  {  {
301          struct alias_entry *new_entry, *ptr;          struct alias_entry *new_entry, *ptr;
302          static DECLARE_MUTEX(lock);          static DEFINE_MUTEX(lock);
303          const struct path_info *saved_original_name, *saved_aliased_name;          const struct path_info *saved_original_name, *saved_aliased_name;
304          int error = -ENOMEM;          int error = -ENOMEM;
305          if (!IsCorrectPath(original_name, 1, -1, -1, __FUNCTION__) || !IsCorrectPath(aliased_name, 1, -1, -1, __FUNCTION__)) return -EINVAL; /* No patterns allowed. */          if (!IsCorrectPath(original_name, 1, -1, -1, __FUNCTION__) || !IsCorrectPath(aliased_name, 1, -1, -1, __FUNCTION__)) return -EINVAL; /* No patterns allowed. */
306          if ((saved_original_name = SaveName(original_name)) == NULL || (saved_aliased_name = SaveName(aliased_name)) == NULL) return -ENOMEM;          if ((saved_original_name = SaveName(original_name)) == NULL || (saved_aliased_name = SaveName(aliased_name)) == NULL) return -ENOMEM;
307          down(&lock);          mutex_lock(&lock);
308          for (ptr = alias_list; ptr; ptr = ptr->next) {          list1_for_each_entry(ptr, &alias_list, list) {
309                  if (ptr->original_name == saved_original_name && ptr->aliased_name == saved_aliased_name) {                  if (ptr->original_name == saved_original_name && ptr->aliased_name == saved_aliased_name) {
310                          ptr->is_deleted = is_delete;                          ptr->is_deleted = is_delete;
311                          error = 0;                          error = 0;
# Line 347  static int AddAliasEntry(const char *ori Line 319  static int AddAliasEntry(const char *ori
319          if ((new_entry = alloc_element(sizeof(*new_entry))) == NULL) goto out;          if ((new_entry = alloc_element(sizeof(*new_entry))) == NULL) goto out;
320          new_entry->original_name = saved_original_name;          new_entry->original_name = saved_original_name;
321          new_entry->aliased_name = saved_aliased_name;          new_entry->aliased_name = saved_aliased_name;
322          mb(); /* Instead of using spinlock. */          list1_add_tail_mb(&new_entry->list, &alias_list);
         if ((ptr = alias_list) != NULL) {  
                 while (ptr->next) ptr = ptr->next; ptr->next = new_entry;  
         } else {  
                 alias_list = new_entry;  
         }  
323          error = 0;          error = 0;
324   out:   out:
325          up(&lock);          mutex_unlock(&lock);
326          return error;          return error;
327  }  }
328    
329  int ReadAliasPolicy(struct io_buffer *head)  int ReadAliasPolicy(struct io_buffer *head)
330  {  {
331          struct alias_entry *ptr = head->read_var2;          struct list1_head *pos;
332          if (!ptr) ptr = alias_list;          list1_for_each_cookie(pos, head->read_var2, &alias_list) {
333          while (ptr) {                  struct alias_entry *ptr;
334                  head->read_var2 = ptr;                  ptr = list1_entry(pos, struct alias_entry, list);
335                  if (!ptr->is_deleted && io_printf(head, KEYWORD_ALIAS "%s %s\n", ptr->original_name->name, ptr->aliased_name->name)) break;                  if (ptr->is_deleted) continue;
336                  ptr = ptr->next;                  if (io_printf(head, KEYWORD_ALIAS "%s %s\n", ptr->original_name->name, ptr->aliased_name->name)) return -ENOMEM;
337          }          }
338          return ptr ? -ENOMEM : 0;          return 0;
339  }  }
340    
341  int AddAliasPolicy(char *data, const int is_delete)  int AddAliasPolicy(char *data, const bool is_delete)
342  {  {
343          char *cp = strchr(data, ' ');          char *cp = strchr(data, ' ');
344          if (!cp) return -EINVAL;          if (!cp) return -EINVAL;
# Line 381  int AddAliasPolicy(char *data, const int Line 348  int AddAliasPolicy(char *data, const int
348    
349  /*************************  DOMAIN AGGREGATOR HANDLER  *************************/  /*************************  DOMAIN AGGREGATOR HANDLER  *************************/
350    
351  static struct aggregator_entry *aggregator_list = NULL;  static LIST1_HEAD(aggregator_list);
352    
353  static int AddAggregatorEntry(const char *original_name, const char *aggregated_name, const int is_delete)  static int AddAggregatorEntry(const char *original_name, const char *aggregated_name, const bool is_delete)
354  {  {
355          struct aggregator_entry *new_entry, *ptr;          struct aggregator_entry *new_entry, *ptr;
356          static DECLARE_MUTEX(lock);          static DEFINE_MUTEX(lock);
357          const struct path_info *saved_original_name, *saved_aggregated_name;          const struct path_info *saved_original_name, *saved_aggregated_name;
358          int error = -ENOMEM;          int error = -ENOMEM;
359          if (!IsCorrectPath(original_name, 1, 0, -1, __FUNCTION__) || !IsCorrectPath(aggregated_name, 1, -1, -1, __FUNCTION__)) return -EINVAL;          if (!IsCorrectPath(original_name, 1, 0, -1, __FUNCTION__) || !IsCorrectPath(aggregated_name, 1, -1, -1, __FUNCTION__)) return -EINVAL;
360          if ((saved_original_name = SaveName(original_name)) == NULL || (saved_aggregated_name = SaveName(aggregated_name)) == NULL) return -ENOMEM;          if ((saved_original_name = SaveName(original_name)) == NULL || (saved_aggregated_name = SaveName(aggregated_name)) == NULL) return -ENOMEM;
361          down(&lock);          mutex_lock(&lock);
362          for (ptr = aggregator_list; ptr; ptr = ptr->next) {          list1_for_each_entry(ptr, &aggregator_list, list) {
363                  if (ptr->original_name == saved_original_name && ptr->aggregated_name == saved_aggregated_name) {                  if (ptr->original_name == saved_original_name && ptr->aggregated_name == saved_aggregated_name) {
364                          ptr->is_deleted = is_delete;                          ptr->is_deleted = is_delete;
365                          error = 0;                          error = 0;
# Line 406  static int AddAggregatorEntry(const char Line 373  static int AddAggregatorEntry(const char
373          if ((new_entry = alloc_element(sizeof(*new_entry))) == NULL) goto out;          if ((new_entry = alloc_element(sizeof(*new_entry))) == NULL) goto out;
374          new_entry->original_name = saved_original_name;          new_entry->original_name = saved_original_name;
375          new_entry->aggregated_name = saved_aggregated_name;          new_entry->aggregated_name = saved_aggregated_name;
376          mb(); /* Instead of using spinlock. */          list1_add_tail_mb(&new_entry->list, &aggregator_list);
         if ((ptr = aggregator_list) != NULL) {  
                 while (ptr->next) ptr = ptr->next; ptr->next = new_entry;  
         } else {  
                 aggregator_list = new_entry;  
         }  
377          error = 0;          error = 0;
378   out:   out:
379          up(&lock);          mutex_unlock(&lock);
380          return error;          return error;
381  }  }
382    
383  int ReadAggregatorPolicy(struct io_buffer *head)  int ReadAggregatorPolicy(struct io_buffer *head)
384  {  {
385          struct aggregator_entry *ptr = head->read_var2;          struct list1_head *pos;
386          if (!ptr) ptr = aggregator_list;          list1_for_each_cookie(pos, head->read_var2, &aggregator_list) {
387          while (ptr) {                  struct aggregator_entry *ptr;
388                  head->read_var2 = ptr;                  ptr = list1_entry(pos, struct aggregator_entry, list);
389                  if (!ptr->is_deleted && io_printf(head, KEYWORD_AGGREGATOR "%s %s\n", ptr->original_name->name, ptr->aggregated_name->name)) break;                  if (ptr->is_deleted) continue;
390                  ptr = ptr->next;                  if (io_printf(head, KEYWORD_AGGREGATOR "%s %s\n", ptr->original_name->name, ptr->aggregated_name->name)) return -ENOMEM;
391          }          }
392          return ptr ? -ENOMEM : 0;          return 0;
393  }  }
394    
395  int AddAggregatorPolicy(char *data, const int is_delete)  int AddAggregatorPolicy(char *data, const bool is_delete)
396  {  {
397          char *cp = strchr(data, ' ');          char *cp = strchr(data, ' ');
398          if (!cp) return -EINVAL;          if (!cp) return -EINVAL;
# Line 448  int DeleteDomain(char *domainname0) Line 410  int DeleteDomain(char *domainname0)
410          struct path_info domainname;          struct path_info domainname;
411          domainname.name = domainname0;          domainname.name = domainname0;
412          fill_path_info(&domainname);          fill_path_info(&domainname);
413          down(&new_domain_assign_lock);          mutex_lock(&new_domain_assign_lock);
414  #ifdef DEBUG_DOMAIN_UNDELETE  #ifdef DEBUG_DOMAIN_UNDELETE
415          printk("DeleteDomain %s\n", domainname0);          printk("DeleteDomain %s\n", domainname0);
416          for (domain = KERNEL_DOMAIN.next; domain; domain = domain->next) {          list1_for_each_entry(domain, &domain_list, list) {
417                  if (pathcmp(domain->domainname, &domainname)) continue;                  if (pathcmp(domain->domainname, &domainname)) continue;
418                  printk("List: %p %u\n", domain, domain->is_deleted);                  printk("List: %p %u\n", domain, domain->is_deleted);
419          }          }
420  #endif  #endif
421          /* Is there an active domain? */          /* Is there an active domain? */
422          for (domain = KERNEL_DOMAIN.next; domain; domain = domain->next) { /* Never delete KERNEL_DOMAIN */          list1_for_each_entry(domain, &domain_list, list) {
                 if (domain->is_deleted || pathcmp(domain->domainname, &domainname)) continue;  
                 break;  
         }  
         if (domain) {  
423                  struct domain_info *domain2;                  struct domain_info *domain2;
424                    /* Never delete KERNEL_DOMAIN */
425                    if (domain == &KERNEL_DOMAIN || domain->is_deleted || pathcmp(domain->domainname, &domainname)) continue;
426                  /* Mark already deleted domains as non undeletable. */                  /* Mark already deleted domains as non undeletable. */
427                  for (domain2 = KERNEL_DOMAIN.next; domain2; domain2 = domain2->next) {                  list1_for_each_entry(domain2, &domain_list, list) {
428                          if (!domain2->is_deleted || pathcmp(domain2->domainname, &domainname)) continue;                          if (!domain2->is_deleted || pathcmp(domain2->domainname, &domainname)) continue;
429  #ifdef DEBUG_DOMAIN_UNDELETE  #ifdef DEBUG_DOMAIN_UNDELETE
430                          if (domain2->is_deleted != 255) printk("Marked %p as non undeletable\n", domain2);                          if (domain2->is_deleted != 255) printk("Marked %p as non undeletable\n", domain2);
# Line 476  int DeleteDomain(char *domainname0) Line 436  int DeleteDomain(char *domainname0)
436  #ifdef DEBUG_DOMAIN_UNDELETE  #ifdef DEBUG_DOMAIN_UNDELETE
437                  printk("Marked %p as undeletable\n", domain);                  printk("Marked %p as undeletable\n", domain);
438  #endif  #endif
439                    break;
440          }          }
441          up(&new_domain_assign_lock);          mutex_unlock(&new_domain_assign_lock);
442          return 0;          return 0;
443  }  }
444    
# Line 487  struct domain_info *UndeleteDomain(const Line 448  struct domain_info *UndeleteDomain(const
448          struct path_info domainname;          struct path_info domainname;
449          domainname.name = domainname0;          domainname.name = domainname0;
450          fill_path_info(&domainname);          fill_path_info(&domainname);
451          down(&new_domain_assign_lock);          mutex_lock(&new_domain_assign_lock);
452  #ifdef DEBUG_DOMAIN_UNDELETE  #ifdef DEBUG_DOMAIN_UNDELETE
453          printk("UndeleteDomain %s\n", domainname0);          printk("UndeleteDomain %s\n", domainname0);
454          for (domain = KERNEL_DOMAIN.next; domain; domain = domain->next) {          list1_for_each_entry(domain, &domain_list, list) {
455                  if (pathcmp(domain->domainname, &domainname)) continue;                  if (pathcmp(domain->domainname, &domainname)) continue;
456                  printk("List: %p %u\n", domain, domain->is_deleted);                  printk("List: %p %u\n", domain, domain->is_deleted);
457          }          }
458  #endif  #endif
459          for (domain = KERNEL_DOMAIN.next; domain; domain = domain->next) {          list1_for_each_entry(domain, &domain_list, list) {
460                  if (pathcmp(&domainname, domain->domainname)) continue;                  if (pathcmp(&domainname, domain->domainname)) continue;
461                  if (!domain->is_deleted) {                  if (!domain->is_deleted) {
462                          /* This domain is active. I can't undelete. */                          /* This domain is active. I can't undelete. */
# Line 514  struct domain_info *UndeleteDomain(const Line 475  struct domain_info *UndeleteDomain(const
475                  printk("%p was undeleted.\n", candidate_domain);                  printk("%p was undeleted.\n", candidate_domain);
476  #endif  #endif
477          }          }
478          up(&new_domain_assign_lock);          mutex_unlock(&new_domain_assign_lock);
479          return candidate_domain;          return candidate_domain;
480  }  }
481    
# Line 524  struct domain_info *FindOrAssignNewDomai Line 485  struct domain_info *FindOrAssignNewDomai
485  {  {
486          struct domain_info *domain = NULL;          struct domain_info *domain = NULL;
487          const struct path_info *saved_domainname;          const struct path_info *saved_domainname;
488          down(&new_domain_assign_lock);          mutex_lock(&new_domain_assign_lock);
489          if ((domain = FindDomain(domainname)) != NULL) goto out;          if ((domain = FindDomain(domainname)) != NULL) goto out;
490          if (!IsCorrectDomain(domainname, __FUNCTION__)) goto out;          if (!IsCorrectDomain(domainname, __FUNCTION__)) goto out;
491          if ((saved_domainname = SaveName(domainname)) == NULL) goto out;          if ((saved_domainname = SaveName(domainname)) == NULL) goto out;
492          /* Can I reuse memory of deleted domain? */          /* Can I reuse memory of deleted domain? */
493          for (domain = KERNEL_DOMAIN.next; domain; domain = domain->next) {          list1_for_each_entry(domain, &domain_list, list) {
494                  struct task_struct *p;                  struct task_struct *p;
495                  struct acl_info *ptr;                  struct acl_info *ptr;
496                  int flag;                  bool flag;
497                  if (!domain->is_deleted || domain->domainname != saved_domainname) continue;                  if (!domain->is_deleted || domain->domainname != saved_domainname) continue;
498                  flag = 0;                  flag = 0;
499                  /***** CRITICAL SECTION START *****/                  /***** CRITICAL SECTION START *****/
# Line 546  struct domain_info *FindOrAssignNewDomai Line 507  struct domain_info *FindOrAssignNewDomai
507  #ifdef DEBUG_DOMAIN_UNDELETE  #ifdef DEBUG_DOMAIN_UNDELETE
508                  printk("Reusing %p %s\n", domain, domain->domainname->name);                  printk("Reusing %p %s\n", domain, domain->domainname->name);
509  #endif  #endif
510                  for (ptr = domain->first_acl_ptr; ptr; ptr = ptr->next) ptr->is_deleted = 1;                  list1_for_each_entry(ptr, &domain->acl_info_list, list) {
511                            ptr->type |= ACL_DELETED;
512                    }
513                  domain->profile = profile;                  domain->profile = profile;
514                  domain->quota_warned = 0;                  domain->quota_warned = 0;
515                  mb(); /* Instead of using spinlock. */                  mb(); /* Avoid out-of-order execution. */
516                  domain->is_deleted = 0;                  domain->is_deleted = 0;
517                  goto out;                  goto out;
518          }          }
519          /* No memory reusable. Create using new memory. */          /* No memory reusable. Create using new memory. */
520          if ((domain = alloc_element(sizeof(*domain))) != NULL) {          if ((domain = alloc_element(sizeof(*domain))) != NULL) {
521                  struct domain_info *ptr = &KERNEL_DOMAIN;                  INIT_LIST1_HEAD(&domain->acl_info_list);
522                  domain->domainname = saved_domainname;                  domain->domainname = saved_domainname;
523                  domain->profile = profile;                  domain->profile = profile;
524                  mb(); /* Instead of using spinlock. */                  list1_add_tail_mb(&domain->list, &domain_list);
                 while (ptr->next) ptr = ptr->next; ptr->next = domain;  
525          }          }
526   out: ;   out: ;
527          up(&new_domain_assign_lock);          mutex_unlock(&new_domain_assign_lock);
528          return domain;          return domain;
529  }  }
530    
# Line 642  static char *get_argv0(struct linux_binp Line 604  static char *get_argv0(struct linux_binp
604          return NULL;          return NULL;
605  }  }
606    
607  static int FindNextDomain(struct linux_binprm *bprm, struct domain_info **next_domain)  static int FindNextDomain(struct linux_binprm *bprm, struct domain_info **next_domain, const u8 do_perm_check)
608  {  {
609          /* This function assumes that the size of buffer returned by realpath() = CCS_MAX_PATHNAME_LEN. */          /* This function assumes that the size of buffer returned by realpath() = CCS_MAX_PATHNAME_LEN. */
610          struct domain_info *old_domain = current->domain_info, *domain = NULL;          struct domain_info *old_domain = current->domain_info, *domain = NULL;
611          const char *old_domain_name = old_domain->domainname->name;          const char *old_domain_name = old_domain->domainname->name;
612          const char *original_name = bprm->filename;          const char *original_name = bprm->filename;
         struct file *filp = bprm->file;  
613          char *new_domain_name = NULL;          char *new_domain_name = NULL;
614          char *real_program_name = NULL, *symlink_program_name = NULL;          char *real_program_name = NULL, *symlink_program_name = NULL;
615          const int is_enforce = CheckCCSEnforce(CCS_TOMOYO_MAC_FOR_FILE);          const bool is_enforce = (CheckCCSFlags(CCS_TOMOYO_MAC_FOR_FILE) == 3);
616          int retval;          int retval;
617          struct path_info r, s, l;          struct path_info r, s, l;
618    
# Line 659  static int FindNextDomain(struct linux_b Line 620  static int FindNextDomain(struct linux_b
620                  /*                  /*
621                   * Built-in initializers. This is needed because policies are not loaded until starting /sbin/init .                   * Built-in initializers. This is needed because policies are not loaded until starting /sbin/init .
622                   */                   */
623                  static int first = 1;                  static bool first = 1;
624                  if (first) {                  if (first) {
625                          AddDomainInitializerEntry(NULL, "/sbin/hotplug", 0, 0);                          AddDomainInitializerEntry(NULL, "/sbin/hotplug", 0, 0);
626                          AddDomainInitializerEntry(NULL, "/sbin/modprobe", 0, 0);                          AddDomainInitializerEntry(NULL, "/sbin/modprobe", 0, 0);
# Line 681  static int FindNextDomain(struct linux_b Line 642  static int FindNextDomain(struct linux_b
642          else l.name = old_domain_name;          else l.name = old_domain_name;
643          fill_path_info(&l);          fill_path_info(&l);
644    
645            if (!do_perm_check) goto ok;
646    
647          /* Check 'alias' directive. */          /* Check 'alias' directive. */
648          if (pathcmp(&r, &s)) {          if (pathcmp(&r, &s)) {
649                  struct alias_entry *ptr;                  struct alias_entry *ptr;
650                  /* Is this program allowed to be called via symbolic links? */                  /* Is this program allowed to be called via symbolic links? */
651                  for (ptr = alias_list; ptr; ptr = ptr->next) {                  list1_for_each_entry(ptr, &alias_list, list) {
652                          if (ptr->is_deleted || pathcmp(&r, ptr->original_name) || pathcmp(&s, ptr->aliased_name)) continue;                          if (ptr->is_deleted || pathcmp(&r, ptr->original_name) || pathcmp(&s, ptr->aliased_name)) continue;
653                          memset(real_program_name, 0, CCS_MAX_PATHNAME_LEN);                          memset(real_program_name, 0, CCS_MAX_PATHNAME_LEN);
654                          strncpy(real_program_name, ptr->aliased_name->name, CCS_MAX_PATHNAME_LEN - 1);                          strncpy(real_program_name, ptr->aliased_name->name, CCS_MAX_PATHNAME_LEN - 1);
# Line 718  static int FindNextDomain(struct linux_b Line 681  static int FindNextDomain(struct linux_b
681          {          {
682                  struct aggregator_entry *ptr;                  struct aggregator_entry *ptr;
683                  /* Is this program allowed to be aggregated? */                  /* Is this program allowed to be aggregated? */
684                  for (ptr = aggregator_list; ptr; ptr = ptr->next) {                  list1_for_each_entry(ptr, &aggregator_list, list) {
685                          if (ptr->is_deleted || !PathMatchesToPattern(&r, ptr->original_name)) continue;                          if (ptr->is_deleted || !PathMatchesToPattern(&r, ptr->original_name)) continue;
686                          memset(real_program_name, 0, CCS_MAX_PATHNAME_LEN);                          memset(real_program_name, 0, CCS_MAX_PATHNAME_LEN);
687                          strncpy(real_program_name, ptr->aggregated_name->name, CCS_MAX_PATHNAME_LEN - 1);                          strncpy(real_program_name, ptr->aggregated_name->name, CCS_MAX_PATHNAME_LEN - 1);
# Line 728  static int FindNextDomain(struct linux_b Line 691  static int FindNextDomain(struct linux_b
691          }          }
692    
693          /* Check execute permission. */          /* Check execute permission. */
694          if ((retval = CheckExecPerm(&r, filp)) < 0) goto out;          if ((retval = CheckExecPerm(&r, bprm)) < 0) goto out;
695    
696     ok: ;
697          /* Allocate memory for calcurating domain name. */          /* Allocate memory for calcurating domain name. */
698          retval = -ENOMEM;          retval = -ENOMEM;
699          if ((new_domain_name = ccs_alloc(CCS_MAX_PATHNAME_LEN + 16)) == NULL) goto out;          if ((new_domain_name = ccs_alloc(CCS_MAX_PATHNAME_LEN + 16)) == NULL) goto out;
# Line 772  static int FindNextDomain(struct linux_b Line 736  static int FindNextDomain(struct linux_b
736          return retval;          return retval;
737  }  }
738    
739    static int CheckEnviron(struct linux_binprm *bprm)
740    {
741            const u8 profile = current->domain_info->profile;
742            const u8 mode = CheckCCSFlags(CCS_TOMOYO_MAC_FOR_ENV);
743            char *arg_ptr;
744            int arg_len = 0;
745            unsigned long pos = bprm->p;
746            int i = pos / PAGE_SIZE, offset = pos % PAGE_SIZE;
747            int argv_count = bprm->argc;
748            int envp_count = bprm->envc;
749            //printk("start %d %d\n", argv_count, envp_count);
750            int error = -ENOMEM;
751            if (!mode || !envp_count) return 0;
752            arg_ptr = ccs_alloc(CCS_MAX_PATHNAME_LEN);
753            if (!arg_ptr) goto out;
754            while (error == -ENOMEM) {
755                    struct page *page;
756                    const char *kaddr;
757    #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,23) && defined(CONFIG_MMU)
758                    if (get_user_pages(current, bprm->mm, pos, 1, 0, 1, &page, NULL) <= 0) goto out;
759                    pos += PAGE_SIZE - offset;
760    #else
761                    page = bprm->page[i];
762    #endif
763                    /* Map */
764                    kaddr = kmap(page);
765                    if (!kaddr) { /* Mapping failed. */
766    #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,23) && defined(CONFIG_MMU)
767                            put_page(page);
768    #endif
769                            goto out;
770                    }
771                    /* Read. */
772                    while (argv_count && offset < PAGE_SIZE) {
773                            if (!kaddr[offset++]) argv_count--;
774                    }
775                    if (argv_count) goto unmap_page;
776                    while (offset < PAGE_SIZE) {
777                            const unsigned char c = kaddr[offset++];
778                            if (c && arg_len < CCS_MAX_PATHNAME_LEN - 10) {
779                                    if (c == '=') {
780                                            arg_ptr[arg_len++] = '\0';
781                                    } else if (c == '\\') {
782                                            arg_ptr[arg_len++] = '\\';
783                                            arg_ptr[arg_len++] = '\\';
784                                    } else if (c > ' ' && c < 127) {
785                                            arg_ptr[arg_len++] = c;
786                                    } else {
787                                            arg_ptr[arg_len++] = '\\';
788                                            arg_ptr[arg_len++] = (c >> 6) + '0';
789                                            arg_ptr[arg_len++] = ((c >> 3) & 7) + '0';
790                                            arg_ptr[arg_len++] = (c & 7) + '0';
791                                    }
792                            } else {
793                                    arg_ptr[arg_len] = '\0';
794                            }
795                            if (c) continue;
796                            if (CheckEnvPerm(arg_ptr, profile, mode)) {
797                                    error = -EPERM;
798                                    break;
799                            }
800                            if (!--envp_count) {
801                                    error = 0;
802                                    break;
803                            }
804                            arg_len = 0;
805                    }
806            unmap_page:
807                    /* Unmap. */
808                    kunmap(page);
809    #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,23) && defined(CONFIG_MMU)
810                    put_page(page);
811    #endif
812                    i++;
813                    offset = 0;
814            }
815     out:
816            ccs_free(arg_ptr);
817            if (error && mode != 3) error = 0;
818            return error;
819    }
820    
821    static void UnEscape(unsigned char *dest)
822    {
823            unsigned char *src = dest;
824            unsigned char c, d, e;
825            while ((c = *src++) != '\0') {
826                    if (c != '\\') {
827                            *dest++ = c;
828                            continue;
829                    }
830                    c = *src++;
831                    if (c == '\\') {
832                            *dest++ = c;
833                    } else if (c >= '0' && c <= '3' &&
834                               (d = *src++) >= '0' && d <= '7' &&
835                               (e = *src++) >= '0' && e <= '7') {
836                            *dest++ = ((c - '0') << 6) | ((d - '0') << 3) | (e - '0');
837                    } else {
838                            break;
839                    }
840            }
841            *dest = '\0';
842    }
843    
844    static int try_alt_exec(struct linux_binprm *bprm, char **work)
845    {
846            /*
847             * Contents of modified bprm.
848             * The envp[] in original bprm is moved to argv[] so that
849             * the alternatively executed program won't be affected by
850             * some dangerous environment variables like LD_PRELOAD .
851             *
852             * modified bprm->argc
853             *    = original bprm->argc + original bprm->envc + 7
854             * modified bprm->envc
855             *    = 0
856             *
857             * modified bprm->argv[0]
858             *    = the program's name specified by alt_exec
859             * modified bprm->argv[1]
860             *    = current->domain_info->domainname->name
861             * modified bprm->argv[2]
862             *    = the current process's name
863             * modified bprm->argv[3]
864             *    = the current process's information (e.g. uid/gid).
865             * modified bprm->argv[4]
866             *    = original bprm->filename
867             * modified bprm->argv[5]
868             *    = original bprm->argc in string expression
869             * modified bprm->argv[6]
870             *    = original bprm->envc in string expression
871             * modified bprm->argv[7]
872             *    = original bprm->argv[0]
873             *  ...
874             * modified bprm->argv[bprm->argc + 6]
875             *     = original bprm->argv[bprm->argc - 1]
876             * modified bprm->argv[bprm->argc + 7]
877             *     = original bprm->envp[0]
878             *  ...
879             * modified bprm->argv[bprm->envc + bprm->argc + 6]
880             *     = original bprm->envp[bprm->envc - 1]
881             */
882            struct file *filp;
883            int retval;
884            const int original_argc = bprm->argc;
885            const int original_envc = bprm->envc;
886            struct task_struct *task = current;
887            static const int buffer_len = PAGE_SIZE;
888            char *buffer = NULL;
889            char *alt_exec;
890            const char *alt_exec1 = GetAltExec();
891            if (!alt_exec1 || *alt_exec1 != '/') return -EINVAL;
892            retval = strlen(alt_exec1) + 1;
893            alt_exec = ccs_alloc(retval);
894            if (!alt_exec) return -ENOMEM;
895            *work = alt_exec;
896            memmove(alt_exec, alt_exec1, retval);
897            UnEscape(alt_exec);
898    
899            /* Close the rejected program's dentry. */
900            allow_write_access(bprm->file);
901            fput(bprm->file);
902            bprm->file = NULL;
903    
904            /* Allocate buffer. */
905            buffer = ccs_alloc(buffer_len);
906            if (!buffer) return -ENOMEM;
907    
908            /* Move envp[] to argv[] */
909            bprm->argc += bprm->envc;
910            bprm->envc = 0;
911    
912            /* Set argv[6] */
913            {
914                    snprintf(buffer, buffer_len - 1, "%d", original_envc);
915                    retval = copy_strings_kernel(1, &buffer, bprm);
916                    if (retval < 0) goto out;
917                    bprm->argc++;
918            }
919    
920            /* Set argv[5] */
921            {
922                    snprintf(buffer, buffer_len - 1, "%d", original_argc);
923                    retval = copy_strings_kernel(1, &buffer, bprm);
924                    if (retval < 0) goto out;
925                    bprm->argc++;
926            }
927    
928            /* Set argv[4] */
929            {
930                    retval = copy_strings_kernel(1, &bprm->filename, bprm);
931                    if (retval < 0) goto out;
932                    bprm->argc++;
933            }
934    
935            /* Set argv[3] */
936            {
937                    const u32 tomoyo_flags = task->tomoyo_flags;
938                    snprintf(buffer, buffer_len - 1, "pid=%d uid=%d gid=%d euid=%d egid=%d suid=%d sgid=%d fsuid=%d fsgid=%d state[0]=%u state[1]=%u state[2]=%u", task->pid, task->uid, task->gid, task->euid, task->egid, task->suid, task->sgid, task->fsuid, task->fsgid, (u8) (tomoyo_flags >> 24), (u8) (tomoyo_flags >> 16), (u8) (tomoyo_flags >> 8));
939                    retval = copy_strings_kernel(1, &buffer, bprm);
940                    if (retval < 0) goto out;
941                    bprm->argc++;
942            }
943    
944            /* Set argv[2] */
945            {
946                    char *exe = (char *) GetEXE();
947                    if (exe) {
948                            retval = copy_strings_kernel(1, &exe, bprm);
949                            ccs_free(exe);
950                    } else {
951                            snprintf(buffer, buffer_len - 1, "<unknown>");
952                            retval = copy_strings_kernel(1, &buffer, bprm);
953                    }
954                    if (retval < 0) goto out;
955                    bprm->argc++;
956            }
957    
958            /* Set argv[1] */
959            {
960                    strncpy(buffer, task->domain_info->domainname->name, buffer_len - 1);
961                    retval = copy_strings_kernel(1, &buffer, bprm);
962                    if (retval < 0) goto out;
963                    bprm->argc++;
964            }
965    
966            /* Set argv[0] */
967            {
968                    retval = copy_strings_kernel(1, &alt_exec, bprm);
969                    if (retval < 0) goto out;
970                    bprm->argc++;
971            }
972    
973            /* OK, now restart the process with the alternative program's dentry. */
974            filp = open_exec(alt_exec);
975            if (IS_ERR(filp)) {
976                    retval = PTR_ERR(filp);
977                    goto out;
978            }
979            bprm->file= filp;
980            bprm->filename = alt_exec;
981    #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
982            bprm->interp = alt_exec;
983    #endif
984            retval = 0;
985     out:
986            /* Free buffer. */
987            ccs_free(buffer);
988            return retval;
989    }
990    
991  #endif  #endif
992    
993  int search_binary_handler_with_transition(struct linux_binprm *bprm, struct pt_regs *regs)  int search_binary_handler_with_transition(struct linux_binprm *bprm, struct pt_regs *regs)
994  {  {
995          struct domain_info *next_domain = NULL, *prev_domain = current->domain_info;          struct domain_info *next_domain = NULL, *prev_domain = current->domain_info;
996          int retval;          int retval;
997            char *work = NULL; /* Keep valid until search_binary_handler() finishes. */
998  #if defined(CONFIG_SAKURA) || defined(CONFIG_TOMOYO)  #if defined(CONFIG_SAKURA) || defined(CONFIG_TOMOYO)
999          extern void CCS_LoadPolicy(const char *filename);          extern void CCS_LoadPolicy(const char *filename);
1000          CCS_LoadPolicy(bprm->filename);          CCS_LoadPolicy(bprm->filename);
1001  #endif  #endif
1002  #if defined(CONFIG_TOMOYO)  #if defined(CONFIG_TOMOYO)
1003          retval = FindNextDomain(bprm, &next_domain);          retval = FindNextDomain(bprm, &next_domain, 1);
1004  #else          if (retval == -EPERM && try_alt_exec(bprm, &work) == 0 && prepare_binprm(bprm) >= 0) {
1005          retval = 0; next_domain = prev_domain;                  current->tomoyo_flags |= CCS_DONT_SLEEP_ON_ENFORCE_ERROR;
1006  #endif                  retval = FindNextDomain(bprm, &next_domain, 0);
1007                    current->tomoyo_flags &= ~CCS_DONT_SLEEP_ON_ENFORCE_ERROR;
1008            }
1009          if (retval == 0) {          if (retval == 0) {
                 current->tomoyo_flags |= TOMOYO_CHECK_READ_FOR_OPEN_EXEC;  
1010                  current->domain_info = next_domain;                  current->domain_info = next_domain;
1011                  retval = search_binary_handler(bprm, regs);                  retval = CheckEnviron(bprm);
1012                  if (retval < 0) current->domain_info = prev_domain;                  current->tomoyo_flags |= TOMOYO_CHECK_READ_FOR_OPEN_EXEC;
1013                    if (!retval) retval = search_binary_handler(bprm, regs);
1014                  current->tomoyo_flags &= ~TOMOYO_CHECK_READ_FOR_OPEN_EXEC;                  current->tomoyo_flags &= ~TOMOYO_CHECK_READ_FOR_OPEN_EXEC;
1015                    if (retval < 0) current->domain_info = prev_domain;
1016          }          }
1017            ccs_free(work);
1018          return retval;          return retval;
1019    #else
1020            return search_binary_handler(bprm, regs);
1021    #endif
1022  }  }
1023    
1024  /***** TOMOYO Linux end. *****/  /***** TOMOYO Linux end. *****/

Legend:
Removed from v.502  
changed lines
  Added in v.1005

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