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

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.7.x/ccs-patch/security/ccsecurity/domain.c revision 3626 by kumaneko, Wed May 5 02:06:14 2010 UTC branches/ccs-patch/security/ccsecurity/domain.c revision 3808 by kumaneko, Fri Jul 9 04:40:54 2010 UTC
# Line 3  Line 3 
3   *   *
4   * Copyright (C) 2005-2010  NTT DATA CORPORATION   * Copyright (C) 2005-2010  NTT DATA CORPORATION
5   *   *
6   * Version: 1.7.2+   2010/05/05   * Version: 1.7.2+   2010/06/04
7   *   *
8   * 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.
9   * See README.ccs for ChangeLog.   * See README.ccs for ChangeLog.
# Line 24  Line 24 
24    
25  /* Variables definitions.*/  /* Variables definitions.*/
26    
27    /* The global domain. */
28    struct ccs_domain_info ccs_global_domain;
29    
30  /* The initial domain. */  /* The initial domain. */
31  struct ccs_domain_info ccs_kernel_domain;  struct ccs_domain_info ccs_kernel_domain;
32    
33  /* The list for "struct ccs_domain_info". */  /* The list for "struct ccs_domain_info". */
34  LIST_HEAD(ccs_domain_list);  LIST_HEAD(ccs_domain_list);
35    
36    struct list_head ccs_policy_list[CCS_MAX_POLICY];
37    struct list_head ccs_group_list[CCS_MAX_GROUP];
38    struct list_head ccs_shared_list[CCS_MAX_LIST];
39    
40  /**  /**
41   * ccs_audit_execute_handler_log - Audit execute_handler log.   * ccs_audit_execute_handler_log - Audit execute_handler log.
42   *   *
43   * @ee:         Pointer to "struct ccs_execve_entry".   * @ee:         Pointer to "struct ccs_execve".
  * @is_default: True if it is "execute_handler" log.  
44   *   *
45   * Returns 0 on success, negative value otherwise.   * Returns 0 on success, negative value otherwise.
46   */   */
47  static int ccs_audit_execute_handler_log(struct ccs_execve_entry *ee,  static int ccs_audit_execute_handler_log(struct ccs_execve *ee)
                                          const bool is_default)  
48  {  {
         int error;  
49          struct ccs_request_info *r = &ee->r;          struct ccs_request_info *r = &ee->r;
         struct ccs_domain_info *domain = r->domain;  
50          const char *handler = ee->handler->name;          const char *handler = ee->handler->name;
51          r->type = CCS_MAC_FILE_EXECUTE;          r->type = CCS_MAC_FILE_EXECUTE;
52          r->mode = ccs_get_mode(r->profile, CCS_MAC_FILE_EXECUTE);          r->mode = ccs_get_mode(r->profile, CCS_MAC_FILE_EXECUTE);
53          r->domain = ee->previous_domain;          r->granted = true;
54          error = ccs_write_audit_log(true, r, "%s %s\n",          return ccs_write_log(r, "%s %s\n", ee->handler_type ==
55                                      is_default ? CCS_KEYWORD_EXECUTE_HANDLER :                               CCS_TYPE_DENIED_EXECUTE_HANDLER ?
56                                      CCS_KEYWORD_DENIED_EXECUTE_HANDLER,                               CCS_KEYWORD_DENIED_EXECUTE_HANDLER :
57                                      handler);                               CCS_KEYWORD_EXECUTE_HANDLER, handler);
         r->domain = domain;  
         return error;  
58  }  }
59    
60  /**  /**
61   * ccs_audit_domain_creation_log - Audit domain creation log.   * ccs_audit_domain_creation_log - Audit domain creation log.
62   *   *
  * @domain:  Pointer to "struct ccs_domain_info".  
  *  
63   * Returns 0 on success, negative value otherwise.   * Returns 0 on success, negative value otherwise.
64   */   */
65  static int ccs_audit_domain_creation_log(struct ccs_domain_info *domain)  static int ccs_audit_domain_creation_log(void)
66  {  {
67          struct ccs_request_info r;          struct ccs_request_info r;
68          ccs_init_request_info(&r, domain, CCS_MAC_FILE_EXECUTE);          ccs_init_request_info(&r, CCS_MAC_FILE_EXECUTE);
69          return ccs_write_audit_log(false, &r, "use_profile %u\n", r.profile);          r.granted = false;
70            return ccs_write_log(&r, "use_profile %u\n", r.profile);
71  }  }
72    
 /* The list for "struct ccs_domain_initializer_entry". */  
 LIST_HEAD(ccs_domain_initializer_list);  
   
73  /**  /**
74   * ccs_update_domain_initializer_entry - Update "struct ccs_domain_initializer_entry" list.   * ccs_update_policy - Update an entry for exception policy.
75   *   *
76   * @domainname: The name of domain. May be NULL.   * @new_entry:       Pointer to "struct ccs_acl_info".
77   * @program:    The name of program.   * @size:            Size of @new_entry in bytes.
78   * @is_not:     True if it is "no_initialize_domain" entry.   * @is_delete:       True if it is a delete request.
79   * @is_delete:  True if it is a delete request.   * @list:            Pointer to "struct list_head".
80     * @check_duplicate: Callback function to find duplicated entry.
81   *   *
82   * Returns 0 on success, negative value otherwise.   * Returns 0 on success, negative value otherwise.
83     *
84     * Caller holds ccs_read_lock().
85   */   */
86  static int ccs_update_domain_initializer_entry(const char *domainname,  int ccs_update_policy(struct ccs_acl_head *new_entry, const int size,
87                                                 const char *program,                        bool is_delete, struct list_head *list,
88                                                 const bool is_not,                        bool (*check_duplicate) (const struct ccs_acl_head *,
89                                                 const bool is_delete)                                                 const struct ccs_acl_head *))
90  {  {
         struct ccs_domain_initializer_entry *ptr;  
         struct ccs_domain_initializer_entry e = { .is_not = is_not };  
91          int error = is_delete ? -ENOENT : -ENOMEM;          int error = is_delete ? -ENOENT : -ENOMEM;
92          if (!ccs_is_correct_path(program, 1, -1, -1))          struct ccs_acl_head *entry;
                 return -EINVAL; /* No patterns allowed. */  
         if (domainname) {  
                 if (!ccs_is_domain_def(domainname) &&  
                     ccs_is_correct_path(domainname, 1, -1, -1))  
                         e.is_last_name = true;  
                 else if (!ccs_is_correct_domain(domainname))  
                         return -EINVAL;  
                 e.domainname = ccs_get_name(domainname);  
                 if (!e.domainname)  
                         goto out;  
         }  
         e.program = ccs_get_name(program);  
         if (!e.program)  
                 goto out;  
93          if (mutex_lock_interruptible(&ccs_policy_lock))          if (mutex_lock_interruptible(&ccs_policy_lock))
94                  goto out;                  return -ENOMEM;
95          list_for_each_entry_rcu(ptr, &ccs_domain_initializer_list, list) {          list_for_each_entry_rcu(entry, list, list) {
96                  if (!ccs_is_same_domain_initializer_entry(ptr, &e))                  if (!check_duplicate(entry, new_entry))
97                          continue;                          continue;
98                  ptr->is_deleted = is_delete;                  entry->is_deleted = is_delete;
99                  error = 0;                  error = 0;
100                  break;                  break;
101          }          }
102          if (!is_delete && error) {          if (error && !is_delete) {
103                  struct ccs_domain_initializer_entry *entry =                  entry = ccs_commit_ok(new_entry, size);
                         ccs_commit_ok(&e, sizeof(e));  
104                  if (entry) {                  if (entry) {
105                          list_add_tail_rcu(&entry->list,                          list_add_tail_rcu(&entry->list, list);
                                           &ccs_domain_initializer_list);  
106                          error = 0;                          error = 0;
107                  }                  }
108          }          }
109          mutex_unlock(&ccs_policy_lock);          mutex_unlock(&ccs_policy_lock);
  out:  
         ccs_put_name(e.domainname);  
         ccs_put_name(e.program);  
110          return error;          return error;
111  }  }
112    
113  /**  static void ccs_delete_type(struct ccs_domain_info *domain, u8 type)
  * ccs_read_domain_initializer_policy - Read "struct ccs_domain_initializer_entry" list.  
  *  
  * @head: Pointer to "struct ccs_io_buffer".  
  *  
  * Returns true on success, false otherwise.  
  *  
  * Caller holds ccs_read_lock().  
  */  
 bool ccs_read_domain_initializer_policy(struct ccs_io_buffer *head)  
114  {  {
115          struct list_head *pos;          struct ccs_acl_info *ptr;
116          bool done = true;          list_for_each_entry_rcu(ptr, &domain->acl_info_list, list) {
117          list_for_each_cookie(pos, head->read_var2,                  if (ptr->type == type)
118                               &ccs_domain_initializer_list) {                          ptr->is_deleted = true;
                 const char *no;  
                 const char *from = "";  
                 const char *domain = "";  
                 struct ccs_domain_initializer_entry *ptr;  
                 ptr = list_entry(pos, struct ccs_domain_initializer_entry,  
                                  list);  
                 if (ptr->is_deleted)  
                         continue;  
                 no = ptr->is_not ? "no_" : "";  
                 if (ptr->domainname) {  
                         from = " from ";  
                         domain = ptr->domainname->name;  
                 }  
                 done = ccs_io_printf(head, "%s" CCS_KEYWORD_INITIALIZE_DOMAIN  
                                      "%s%s%s\n", no, ptr->program->name, from,  
                                      domain);  
                 if (!done)  
                         break;  
119          }          }
         return done;  
120  }  }
121    
122  /**  /**
123   * ccs_write_domain_initializer_policy - Write "struct ccs_domain_initializer_entry" list.   * ccs_update_domain - Update an entry for domain policy.
124   *   *
125   * @data:      String to parse.   * @new_entry:       Pointer to "struct ccs_acl_info".
126   * @is_not:    True if it is "no_initialize_domain" entry.   * @size:            Size of @new_entry in bytes.
127   * @is_delete: True if it is a delete request.   * @is_delete:       True if it is a delete request.
128     * @domain:          Pointer to "struct ccs_domain_info".
129     * @check_duplicate: Callback function to find duplicated entry.
130     * @merge_duplicate: Callback function to merge duplicated entry.
131   *   *
132   * Returns 0 on success, negative value otherwise.   * Returns 0 on success, negative value otherwise.
  */  
 int ccs_write_domain_initializer_policy(char *data, const bool is_not,  
                                         const bool is_delete)  
 {  
         char *cp = strstr(data, " from ");  
         if (cp) {  
                 *cp = '\0';  
                 return ccs_update_domain_initializer_entry(cp + 6, data,  
                                                            is_not, is_delete);  
         }  
         return ccs_update_domain_initializer_entry(NULL, data, is_not,  
                                                    is_delete);  
 }  
   
 /**  
  * ccs_is_domain_initializer - Check whether the given program causes domainname reinitialization.  
  *  
  * @domainname: The name of domain.  
  * @program:    The name of program.  
  * @last_name:  The last component of @domainname.  
  *  
  * Returns true if executing @program reinitializes domain transition,  
  * false otherwise.  
133   *   *
134   * Caller holds ccs_read_lock().   * Caller holds ccs_read_lock().
135   */   */
136  static bool ccs_is_domain_initializer(const struct ccs_path_info *domainname,  int ccs_update_domain(struct ccs_acl_info *new_entry, const int size,
137                                        const struct ccs_path_info *program,                        bool is_delete, struct ccs_domain_info *domain,
138                                        const struct ccs_path_info *last_name)                        bool (*check_duplicate) (const struct ccs_acl_info *,
139  {                                                 const struct ccs_acl_info *),
140          struct ccs_domain_initializer_entry *ptr;                        bool (*merge_duplicate) (struct ccs_acl_info *,
141          bool flag = false;                                                 struct ccs_acl_info *,
142          list_for_each_entry_rcu(ptr, &ccs_domain_initializer_list, list) {                                                 const bool))
143                  if (ptr->is_deleted)  {
144            int error = is_delete ? -ENOENT : -ENOMEM;
145            struct ccs_acl_info *entry;
146            /*
147             * Only one "execute_handler" and "denied_execute_handler" can exist
148             * in a domain.
149             */
150            const u8 type = new_entry->type;
151            const bool exclusive = !is_delete &&
152                    (type == CCS_TYPE_EXECUTE_HANDLER ||
153                     type == CCS_TYPE_DENIED_EXECUTE_HANDLER);
154            if (mutex_lock_interruptible(&ccs_policy_lock))
155                    return error;
156            list_for_each_entry_rcu(entry, &domain->acl_info_list, list) {
157                    if (!check_duplicate(entry, new_entry))
158                          continue;                          continue;
159                  if (ptr->domainname) {                  if (exclusive)
160                          if (!ptr->is_last_name) {                          ccs_delete_type(domain, type);
161                                  if (ptr->domainname != domainname)                  if (merge_duplicate)
162                                          continue;                          entry->is_deleted = merge_duplicate(entry, new_entry,
163                          } else {                                                              is_delete);
164                                  if (ccs_pathcmp(ptr->domainname, last_name))                  else
165                                          continue;                          entry->is_deleted = is_delete;
166                          }                  error = 0;
167                    break;
168            }
169            if (error && !is_delete) {
170                    entry = ccs_commit_ok(new_entry, size);
171                    if (entry) {
172                            if (exclusive)
173                                    ccs_delete_type(domain, type);
174                            if (entry->cond)
175                                    atomic_inc(&entry->cond->head.users);
176                            list_add_tail_rcu(&entry->list,
177                                              &domain->acl_info_list);
178                            error = 0;
179                  }                  }
180                  if (ccs_pathcmp(ptr->program, program))          }
181            mutex_unlock(&ccs_policy_lock);
182            return error;
183    }
184    
185    void ccs_check_acl(struct ccs_request_info *r,
186                       bool (*check_entry) (const struct ccs_request_info *,
187                                            const struct ccs_acl_info *))
188    {
189            const struct ccs_domain_info *domain = ccs_current_domain();
190            struct ccs_acl_info *ptr;
191     retry:
192            list_for_each_entry_rcu(ptr, &domain->acl_info_list, list) {
193                    if (ptr->is_deleted || ptr->type != r->param_type)
194                          continue;                          continue;
195                  if (ptr->is_not) {                  if (check_entry(r, ptr) && ccs_condition(r, ptr->cond)) {
196                          flag = false;                          r->cond = ptr->cond;
197                          break;                          r->granted = true;
198                            return;
199                  }                  }
                 flag = true;  
200          }          }
201          return flag;          if (domain != &ccs_global_domain &&
202                !domain->flags[CCS_DIF_IGNORE_GLOBAL]) {
203                    domain = &ccs_global_domain;
204                    goto retry;
205            }
206            r->granted = false;
207  }  }
208    
209  /* The list for "struct ccs_domain_keeper_entry". */  static bool ccs_same_transition_control(const struct ccs_acl_head *a,
210  LIST_HEAD(ccs_domain_keeper_list);                                          const struct ccs_acl_head *b)
211    {
212            const struct ccs_transition_control *p1 = container_of(a, typeof(*p1),
213                                                                   head);
214            const struct ccs_transition_control *p2 = container_of(b, typeof(*p2),
215                                                                   head);
216            return p1->type == p2->type && p1->is_last_name == p2->is_last_name
217                    && p1->domainname == p2->domainname
218                    && p1->program == p2->program;
219    }
220    
221  /**  /**
222   * ccs_update_domain_keeper_entry - Update "struct ccs_domain_keeper_entry" list.   * ccs_update_transition_control_entry - Update "struct ccs_transition_control" list.
223   *   *
224   * @domainname: The name of domain.   * @domainname: The name of domain. Maybe NULL.
225   * @program:    The name of program. May be NULL.   * @program:    The name of program. Maybe NULL.
226   * @is_not:     True if it is "no_keep_domain" entry.   * @type:       Type of transition.
227   * @is_delete:  True if it is a delete request.   * @is_delete:  True if it is a delete request.
228   *   *
229   * Returns 0 on success, negative value otherwise.   * Returns 0 on success, negative value otherwise.
230   */   */
231  static int ccs_update_domain_keeper_entry(const char *domainname,  static int ccs_update_transition_control_entry(const char *domainname,
232                                            const char *program,                                                 const char *program,
233                                            const bool is_not,                                                 const u8 type,
234                                            const bool is_delete)                                                 const bool is_delete)
235  {  {
236          struct ccs_domain_keeper_entry *ptr;          struct ccs_transition_control e = { .type = type };
         struct ccs_domain_keeper_entry e = { .is_not = is_not };  
237          int error = is_delete ? -ENOENT : -ENOMEM;          int error = is_delete ? -ENOENT : -ENOMEM;
238          if (!ccs_is_domain_def(domainname) &&          if (program && strcmp(program, "any")) {
239              ccs_is_correct_path(domainname, 1, -1, -1))                  if (!ccs_correct_path(program))
                 e.is_last_name = true;  
         else if (!ccs_is_correct_domain(domainname))  
                 return -EINVAL;  
         if (program) {  
                 if (!ccs_is_correct_path(program, 1, -1, -1))  
240                          return -EINVAL;                          return -EINVAL;
241                  e.program = ccs_get_name(program);                  e.program = ccs_get_name(program);
242                  if (!e.program)                  if (!e.program)
243                          goto out;                          goto out;
244          }          }
245          e.domainname = ccs_get_name(domainname);          if (domainname && strcmp(domainname, "any")) {
246          if (!e.domainname)                  if (!ccs_correct_domain(domainname)) {
247                  goto out;                          if (!ccs_correct_path(domainname))
248          if (mutex_lock_interruptible(&ccs_policy_lock))                                  goto out;
249                  goto out;                          e.is_last_name = true;
         list_for_each_entry_rcu(ptr, &ccs_domain_keeper_list, list) {  
                 if (!ccs_is_same_domain_keeper_entry(ptr, &e))  
                         continue;  
                 ptr->is_deleted = is_delete;  
                 error = 0;  
                 break;  
         }  
         if (!is_delete && error) {  
                 struct ccs_domain_keeper_entry *entry =  
                         ccs_commit_ok(&e, sizeof(e));  
                 if (entry) {  
                         list_add_tail_rcu(&entry->list,  
                                           &ccs_domain_keeper_list);  
                         error = 0;  
250                  }                  }
251                    e.domainname = ccs_get_name(domainname);
252                    if (!e.domainname)
253                            goto out;
254          }          }
255          mutex_unlock(&ccs_policy_lock);          error = ccs_update_policy(&e.head, sizeof(e), is_delete,
256                                      &ccs_policy_list[CCS_ID_TRANSITION_CONTROL],
257                                      ccs_same_transition_control);
258   out:   out:
259          ccs_put_name(e.domainname);          ccs_put_name(e.domainname);
260          ccs_put_name(e.program);          ccs_put_name(e.program);
# Line 293  static int ccs_update_domain_keeper_entr Line 262  static int ccs_update_domain_keeper_entr
262  }  }
263    
264  /**  /**
265   * ccs_write_domain_keeper_policy - Write "struct ccs_domain_keeper_entry" list.   * ccs_write_transition_control - Write "struct ccs_transition_control" list.
266   *   *
267   * @data:      String to parse.   * @data:      String to parse.
  * @is_not:    True if it is "no_keep_domain" entry.  
268   * @is_delete: True if it is a delete request.   * @is_delete: True if it is a delete request.
269     * @type:      Type of this entry.
270   *   *
271     * Returns 0 on success, negative value otherwise.
272   */   */
273  int ccs_write_domain_keeper_policy(char *data, const bool is_not,  int ccs_write_transition_control(char *data, const bool is_delete,
274                                     const bool is_delete)                                   const u8 type)
 {  
         char *cp = strstr(data, " from ");  
         if (cp) {  
                 *cp = '\0';  
                 return ccs_update_domain_keeper_entry(cp + 6, data,  
                                                       is_not, is_delete);  
         }  
         return ccs_update_domain_keeper_entry(data, NULL, is_not, is_delete);  
 }  
   
 /**  
  * ccs_read_domain_keeper_policy - Read "struct ccs_domain_keeper_entry" list.  
  *  
  * @head: Pointer to "struct ccs_io_buffer".  
  *  
  * Returns true on success, false otherwise.  
  *  
  * Caller holds ccs_read_lock().  
  */  
 bool ccs_read_domain_keeper_policy(struct ccs_io_buffer *head)  
275  {  {
276          struct list_head *pos;          char *domainname = strstr(data, " from ");
277          bool done = true;          if (domainname) {
278          list_for_each_cookie(pos, head->read_var2,                  *domainname = '\0';
279                               &ccs_domain_keeper_list) {                  domainname += 6;
280                  struct ccs_domain_keeper_entry *ptr;          } else if (type == CCS_TRANSITION_CONTROL_NO_KEEP ||
281                  const char *no;                     type == CCS_TRANSITION_CONTROL_KEEP) {
282                  const char *from = "";                  domainname = data;
283                  const char *program = "";                  data = NULL;
                 ptr = list_entry(pos, struct ccs_domain_keeper_entry, list);  
                 if (ptr->is_deleted)  
                         continue;  
                 no = ptr->is_not ? "no_" : "";  
                 if (ptr->program) {  
                         from = " from ";  
                         program = ptr->program->name;  
                 }  
                 done = ccs_io_printf(head, "%s" CCS_KEYWORD_KEEP_DOMAIN  
                                      "%s%s%s\n", no, program, from,  
                                      ptr->domainname->name);  
                 if (!done)  
                         break;  
284          }          }
285          return done;          return ccs_update_transition_control_entry(domainname, data, type,
286                                                       is_delete);
287  }  }
288    
289  /**  /**
290   * ccs_is_domain_keeper - Check whether the given program causes domain transition suppression.   * ccs_transition_type - Get domain transition type.
291   *   *
292   * @domainname: The name of domain.   * @domainname: The name of domain.
293   * @program:    The name of program.   * @program:    The name of program.
  * @last_name:  The last component of @domainname.  
294   *   *
295   * Returns true if executing @program supresses domain transition,   * Returns CCS_TRANSITION_CONTROL_INITIALIZE if executing @program
296   * false otherwise.   * reinitializes domain transition, CCS_TRANSITION_CONTROL_KEEP if executing
297     * @program suppresses domain transition, others otherwise.
298   *   *
299   * Caller holds ccs_read_lock().   * Caller holds ccs_read_lock().
300   */   */
301  static bool ccs_is_domain_keeper(const struct ccs_path_info *domainname,  static u8 ccs_transition_type(const struct ccs_path_info *domainname,
302                                   const struct ccs_path_info *program,                                const struct ccs_path_info *program)
303                                   const struct ccs_path_info *last_name)  {
304  {          const struct ccs_transition_control *ptr;
305          struct ccs_domain_keeper_entry *ptr;          const char *last_name = ccs_last_word(domainname->name);
306          bool flag = false;          u8 type;
307          list_for_each_entry_rcu(ptr, &ccs_domain_keeper_list, list) {          for (type = 0; type < CCS_MAX_TRANSITION_TYPE; type++) {
308                  if (ptr->is_deleted)   next:
309                          continue;                  list_for_each_entry_rcu(ptr, &ccs_policy_list
310                  if (!ptr->is_last_name) {                                          [CCS_ID_TRANSITION_CONTROL],
311                          if (ptr->domainname != domainname)                                          head.list) {
312                            if (ptr->head.is_deleted || ptr->type != type)
313                                  continue;                                  continue;
314                  } else {                          if (ptr->domainname) {
315                          if (ccs_pathcmp(ptr->domainname, last_name))                                  if (!ptr->is_last_name) {
316                                            if (ptr->domainname != domainname)
317                                                    continue;
318                                    } else {
319                                            /*
320                                             * Use direct strcmp() since this is
321                                             * unlikely used.
322                                             */
323                                            if (strcmp(ptr->domainname->name,
324                                                       last_name))
325                                                    continue;
326                                    }
327                            }
328                            if (ptr->program && ccs_pathcmp(ptr->program, program))
329                                  continue;                                  continue;
330                            if (type == CCS_TRANSITION_CONTROL_NO_INITIALIZE) {
331                                    /*
332                                     * Do not check for initialize_domain if
333                                     * no_initialize_domain matched.
334                                     */
335                                    type = CCS_TRANSITION_CONTROL_NO_KEEP;
336                                    goto next;
337                            }
338                            goto done;
339                  }                  }
                 if (ptr->program && ccs_pathcmp(ptr->program, program))  
                         continue;  
                 if (ptr->is_not) {  
                         flag = false;  
                         break;  
                 }  
                 flag = true;  
340          }          }
341          return flag;   done:
342            return type;
343  }  }
344    
345  /* The list for "struct ccs_aggregator_entry". */  static bool ccs_same_aggregator(const struct ccs_acl_head *a,
346  LIST_HEAD(ccs_aggregator_list);                                  const struct ccs_acl_head *b)
347    {
348            const struct ccs_aggregator *p1 = container_of(a, typeof(*p1), head);
349            const struct ccs_aggregator *p2 = container_of(b, typeof(*p2), head);
350            return p1->original_name == p2->original_name &&
351                    p1->aggregated_name == p2->aggregated_name;
352    }
353    
354  /**  /**
355   * ccs_update_aggregator_entry - Update "struct ccs_aggregator_entry" list.   * ccs_update_aggregator_entry - Update "struct ccs_aggregator" list.
356   *   *
357   * @original_name:   The original program's name.   * @original_name:   The original program's name.
358   * @aggregated_name: The aggregated program's name.   * @aggregated_name: The aggregated program's name.
# Line 403  static int ccs_update_aggregator_entry(c Line 364  static int ccs_update_aggregator_entry(c
364                                         const char *aggregated_name,                                         const char *aggregated_name,
365                                         const bool is_delete)                                         const bool is_delete)
366  {  {
367          struct ccs_aggregator_entry *ptr;          struct ccs_aggregator e = { };
         struct ccs_aggregator_entry e = { };  
368          int error = is_delete ? -ENOENT : -ENOMEM;          int error = is_delete ? -ENOENT : -ENOMEM;
369          if (!ccs_is_correct_path(original_name, 1, 0, -1) ||          if (!ccs_correct_path(original_name) ||
370              !ccs_is_correct_path(aggregated_name, 1, -1, -1))              !ccs_correct_path(aggregated_name))
371                  return -EINVAL;                  return -EINVAL;
372          e.original_name = ccs_get_name(original_name);          e.original_name = ccs_get_name(original_name);
373          e.aggregated_name = ccs_get_name(aggregated_name);          e.aggregated_name = ccs_get_name(aggregated_name);
374          if (!e.original_name || !e.aggregated_name)          if (!e.original_name || !e.aggregated_name ||
375                e.aggregated_name->is_patterned) /* No patterns allowed. */
376                  goto out;                  goto out;
377          if (mutex_lock_interruptible(&ccs_policy_lock))          error = ccs_update_policy(&e.head, sizeof(e), is_delete,
378                  goto out;                                    &ccs_policy_list[CCS_ID_AGGREGATOR],
379          list_for_each_entry_rcu(ptr, &ccs_aggregator_list, list) {                                    ccs_same_aggregator);
                 if (!ccs_is_same_aggregator_entry(ptr, &e))  
                         continue;  
                 ptr->is_deleted = is_delete;  
                 error = 0;  
                 break;  
         }  
         if (!is_delete && error) {  
                 struct ccs_aggregator_entry *entry =  
                         ccs_commit_ok(&e, sizeof(e));  
                 if (entry) {  
                         list_add_tail_rcu(&entry->list, &ccs_aggregator_list);  
                         error = 0;  
                 }  
         }  
         mutex_unlock(&ccs_policy_lock);  
380   out:   out:
381          ccs_put_name(e.original_name);          ccs_put_name(e.original_name);
382          ccs_put_name(e.aggregated_name);          ccs_put_name(e.aggregated_name);
# Line 438  static int ccs_update_aggregator_entry(c Line 384  static int ccs_update_aggregator_entry(c
384  }  }
385    
386  /**  /**
387   * ccs_read_aggregator_policy - Read "struct ccs_aggregator_entry" list.   * ccs_write_aggregator - Write "struct ccs_aggregator" list.
  *  
  * @head: Pointer to "struct ccs_io_buffer".  
  *  
  * Returns true on success, false otherwise.  
  *  
  * Caller holds ccs_read_lock().  
  */  
 bool ccs_read_aggregator_policy(struct ccs_io_buffer *head)  
 {  
         struct list_head *pos;  
         bool done = true;  
         list_for_each_cookie(pos, head->read_var2, &ccs_aggregator_list) {  
                 struct ccs_aggregator_entry *ptr;  
                 ptr = list_entry(pos, struct ccs_aggregator_entry, list);  
                 if (ptr->is_deleted)  
                         continue;  
                 done = ccs_io_printf(head, CCS_KEYWORD_AGGREGATOR "%s %s\n",  
                                      ptr->original_name->name,  
                                      ptr->aggregated_name->name);  
                 if (!done)  
                         break;  
         }  
         return done;  
 }  
   
 /**  
  * ccs_write_aggregator_policy - Write "struct ccs_aggregator_entry" list.  
388   *   *
389   * @data:      String to parse.   * @data:      String to parse.
390   * @is_delete: True if it is a delete request.   * @is_delete: True if it is a delete request.
391   *   *
392   * Returns 0 on success, negative value otherwise.   * Returns 0 on success, negative value otherwise.
393   */   */
394  int ccs_write_aggregator_policy(char *data, const bool is_delete)  int ccs_write_aggregator(char *data, const bool is_delete)
395  {  {
396          char *w[2];          char *w[2];
397          if (!ccs_tokenize(data, w, sizeof(w)) || !w[1][0])          if (!ccs_tokenize(data, w, sizeof(w)) || !w[1][0])
# Line 513  int ccs_delete_domain(char *domainname) Line 432  int ccs_delete_domain(char *domainname)
432  }  }
433    
434  /**  /**
435   * ccs_find_or_assign_new_domain - Create a domain.   * ccs_assign_domain - Create a domain.
436   *   *
437   * @domainname: The name of domain.   * @domainname: The name of domain.
438   * @profile:    Profile number to assign if the domain was newly created.   * @profile:    Profile number to assign if the domain was newly created.
439   *   *
440   * Returns pointer to "struct ccs_domain_info" on success, NULL otherwise.   * Returns pointer to "struct ccs_domain_info" on success, NULL otherwise.
441   */   */
442  struct ccs_domain_info *ccs_find_or_assign_new_domain(const char *domainname,  struct ccs_domain_info *ccs_assign_domain(const char *domainname,
443                                                        const u8 profile)                                            const u8 profile)
444  {  {
445          struct ccs_domain_info *entry;          struct ccs_domain_info e = { };
446          struct ccs_domain_info *domain = NULL;          struct ccs_domain_info *entry = NULL;
         const struct ccs_path_info *saved_domainname;  
447          bool found = false;          bool found = false;
448    
449          if (!ccs_is_correct_domain(domainname))          if (!ccs_correct_domain(domainname))
450                  return NULL;                  return NULL;
451          saved_domainname = ccs_get_name(domainname);          e.profile = profile;
452          if (!saved_domainname)          e.domainname = ccs_get_name(domainname);
453            if (!e.domainname)
454                  return NULL;                  return NULL;
         entry = kzalloc(sizeof(*entry), CCS_GFP_FLAGS);  
455          if (mutex_lock_interruptible(&ccs_policy_lock))          if (mutex_lock_interruptible(&ccs_policy_lock))
456                  goto out;                  goto out;
457          list_for_each_entry_rcu(domain, &ccs_domain_list, list) {          list_for_each_entry_rcu(entry, &ccs_domain_list, list) {
458                  if (domain->is_deleted ||                  if (entry->is_deleted ||
459                      ccs_pathcmp(saved_domainname, domain->domainname))                      ccs_pathcmp(e.domainname, entry->domainname))
460                          continue;                          continue;
461                  found = true;                  found = true;
462                  break;                  break;
463          }          }
464          if (!found && ccs_memory_ok(entry, sizeof(*entry))) {          if (!found) {
465                  INIT_LIST_HEAD(&entry->acl_info_list);                  entry = ccs_commit_ok(&e, sizeof(e));
466                  entry->domainname = saved_domainname;                  if (entry) {
467                  saved_domainname = NULL;                          INIT_LIST_HEAD(&entry->acl_info_list);
468                  entry->profile = profile;                          list_add_tail_rcu(&entry->list, &ccs_domain_list);
469                  list_add_tail_rcu(&entry->list, &ccs_domain_list);                          found = true;
470                  domain = entry;                  }
                 entry = NULL;  
                 found = true;  
471          }          }
472          mutex_unlock(&ccs_policy_lock);          mutex_unlock(&ccs_policy_lock);
473   out:   out:
474          ccs_put_name(saved_domainname);          ccs_put_name(e.domainname);
475          kfree(entry);          return found ? entry : NULL;
         return found ? domain : NULL;  
476  }  }
477    
478  /**  /**
479   * ccs_find_next_domain - Find a domain.   * ccs_find_next_domain - Find a domain.
480   *   *
481   * @ee: Pointer to "struct ccs_execve_entry".   * @ee: Pointer to "struct ccs_execve".
482   *   *
483   * Returns 0 on success, negative value otherwise.   * Returns 0 on success, negative value otherwise.
484   *   *
485   * Caller holds ccs_read_lock().   * Caller holds ccs_read_lock().
486   */   */
487  static int ccs_find_next_domain(struct ccs_execve_entry *ee)  static int ccs_find_next_domain(struct ccs_execve *ee)
488  {  {
489          struct ccs_request_info *r = &ee->r;          struct ccs_request_info *r = &ee->r;
490          const struct ccs_path_info *handler = ee->handler;          const struct ccs_path_info *handler = ee->handler;
491          struct ccs_domain_info *domain = NULL;          struct ccs_domain_info *domain = NULL;
492          const char *old_domain_name = r->domain->domainname->name;          struct ccs_domain_info * const old_domain = ccs_current_domain();
493          struct linux_binprm *bprm = ee->bprm;          struct linux_binprm *bprm = ee->bprm;
494          const u32 ccs_flags = current->ccs_flags;          struct task_struct *task = current;
495            const u32 ccs_flags = task->ccs_flags;
496          struct ccs_path_info rn = { }; /* real name */          struct ccs_path_info rn = { }; /* real name */
         struct ccs_path_info ln; /* last name */  
497          int retval;          int retval;
498          bool need_kfree = false;          bool need_kfree = false;
499          ln.name = ccs_last_word(old_domain_name);          bool domain_created = false;
         ccs_fill_path_info(&ln);  
500   retry:   retry:
501          current->ccs_flags = ccs_flags;          current->ccs_flags = ccs_flags;
502          r->cond = NULL;          r->cond = NULL;
# Line 609  static int ccs_find_next_domain(struct c Line 523  static int ccs_find_next_domain(struct c
523                          goto out;                          goto out;
524                  }                  }
525          } else {          } else {
526                  struct ccs_aggregator_entry *ptr;                  struct ccs_aggregator *ptr;
527                  /* Check 'aggregator' directive. */                  /* Check 'aggregator' directive. */
528                  list_for_each_entry_rcu(ptr, &ccs_aggregator_list, list) {                  list_for_each_entry_rcu(ptr,
529                          if (ptr->is_deleted ||                                          &ccs_policy_list[CCS_ID_AGGREGATOR],
530                                            head.list) {
531                            if (ptr->head.is_deleted ||
532                              !ccs_path_matches_pattern(&rn, ptr->original_name))                              !ccs_path_matches_pattern(&rn, ptr->original_name))
533                                  continue;                                  continue;
534                          kfree(rn.name);                          kfree(rn.name);
# Line 623  static int ccs_find_next_domain(struct c Line 539  static int ccs_find_next_domain(struct c
539                  }                  }
540    
541                  /* Check execute permission. */                  /* Check execute permission. */
542                  retval = ccs_exec_perm(r, &rn);                  retval = ccs_path_permission(r, CCS_TYPE_EXECUTE, &rn);
543                  if (retval == CCS_RETRY_REQUEST)                  if (retval == CCS_RETRY_REQUEST)
544                          goto retry;                          goto retry;
545                  if (retval < 0)                  if (retval < 0)
# Line 631  static int ccs_find_next_domain(struct c Line 547  static int ccs_find_next_domain(struct c
547          }          }
548    
549          /* Calculate domain to transit to. */          /* Calculate domain to transit to. */
550          if (ccs_is_domain_initializer(r->domain->domainname, &rn, &ln)) {          switch (ccs_transition_type(old_domain->domainname, &rn)) {
551            case CCS_TRANSITION_CONTROL_INITIALIZE:
552                  /* Transit to the child of ccs_kernel_domain domain. */                  /* Transit to the child of ccs_kernel_domain domain. */
553                  snprintf(ee->tmp, CCS_EXEC_TMPSIZE - 1, ROOT_NAME " " "%s",                  snprintf(ee->tmp, CCS_EXEC_TMPSIZE - 1, CCS_ROOT_NAME " " "%s",
554                           rn.name);                           rn.name);
555          } else if (r->domain == &ccs_kernel_domain && !ccs_policy_loaded) {                  break;
556                  /*          case CCS_TRANSITION_CONTROL_KEEP:
                  * Needn't to transit from kernel domain before starting  
                  * /sbin/init. But transit from kernel domain if executing  
                  * initializers because they might start before /sbin/init.  
                  */  
                 domain = r->domain;  
         } else if (ccs_is_domain_keeper(r->domain->domainname, &rn, &ln)) {  
557                  /* Keep current domain. */                  /* Keep current domain. */
558                  domain = r->domain;                  domain = old_domain;
559          } else {                  break;
560                  /* Normal domain transition. */          default:
561                  snprintf(ee->tmp, CCS_EXEC_TMPSIZE - 1, "%s %s",                  if (old_domain == &ccs_kernel_domain && !ccs_policy_loaded) {
562                           old_domain_name, rn.name);                          /*
563                             * Needn't to transit from kernel domain before
564                             * starting /sbin/init. But transit from kernel domain
565                             * if executing initializers because they might start
566                             * before /sbin/init.
567                             */
568                            domain = old_domain;
569                    } else {
570                            /* Normal domain transition. */
571                            snprintf(ee->tmp, CCS_EXEC_TMPSIZE - 1, "%s %s",
572                                     old_domain->domainname->name, rn.name);
573                    }
574                    break;
575          }          }
576          if (domain || strlen(ee->tmp) >= CCS_EXEC_TMPSIZE - 10)          if (domain || strlen(ee->tmp) >= CCS_EXEC_TMPSIZE - 10)
577                  goto done;                  goto done;
# Line 663  static int ccs_find_next_domain(struct c Line 586  static int ccs_find_next_domain(struct c
586                  if (error < 0)                  if (error < 0)
587                          goto done;                          goto done;
588          }          }
589          domain = ccs_find_or_assign_new_domain(ee->tmp, r->profile);          domain = ccs_assign_domain(ee->tmp, r->profile);
590          if (domain)          if (domain)
591                  ccs_audit_domain_creation_log(domain);                  domain_created = true;
592   done:   done:
593          if (!domain) {          if (!domain) {
594                  retval = (r->mode == CCS_CONFIG_ENFORCING) ? -EPERM : 0;                  retval = (r->mode == CCS_CONFIG_ENFORCING) ? -EPERM : 0;
595                  if (!r->domain->domain_transition_failed) {                  if (!old_domain->flags[CCS_DIF_TRANSITION_FAILED]) {
596                          r->domain->domain_transition_failed = true;                          old_domain->flags[CCS_DIF_TRANSITION_FAILED] = true;
597                          ccs_write_audit_log(false, r,                          r->granted = false;
598                                              CCS_KEYWORD_TRANSITION_FAILED                          ccs_write_log(r, CCS_KEYWORD_TRANSITION_FAILED "\n");
599                                              "\n");                          printk(KERN_WARNING
600                          printk(KERN_WARNING "ERROR: Domain '%s' not defined.\n",                                 "ERROR: Domain '%s' not defined.\n", ee->tmp);
                                ee->tmp);  
601                  }                  }
602          } else {          } else {
603                  retval = 0;                  retval = 0;
604          }          }
605   out:          if (!retval && handler)
606                    ccs_audit_execute_handler_log(ee);
607            /*
608             * Tell GC that I started execve().
609             * Also, tell open_exec() to check read permission.
610             */
611            task->ccs_flags |= CCS_TASK_IS_IN_EXECVE;
612            /*
613             * Make task->ccs_flags visible to GC before changing
614             * task->ccs_domain_info .
615             */
616            smp_mb();
617            /*
618             * Proceed to the next domain in order to allow reaching via PID.
619             * It will be reverted if execve() failed. Reverting is not good.
620             * But it is better than being unable to reach via PID in interactive
621             * enforcing mode.
622             */
623          if (domain)          if (domain)
624                  r->domain = domain;                  task->ccs_domain_info = domain;
625            if (domain_created)
626                    ccs_audit_domain_creation_log();
627     out:
628          if (need_kfree)          if (need_kfree)
629                  kfree(rn.name);                  kfree(rn.name);
630          return retval;          return retval;
# Line 691  static int ccs_find_next_domain(struct c Line 633  static int ccs_find_next_domain(struct c
633  /**  /**
634   * ccs_environ - Check permission for environment variable names.   * ccs_environ - Check permission for environment variable names.
635   *   *
636   * @ee: Pointer to "struct ccs_execve_entry".   * @ee: Pointer to "struct ccs_execve".
637   *   *
638   * Returns 0 on success, negative value otherwise.   * Returns 0 on success, negative value otherwise.
639   */   */
640  static int ccs_environ(struct ccs_execve_entry *ee)  static int ccs_environ(struct ccs_execve *ee)
641  {  {
642          struct ccs_request_info *r = &ee->r;          struct ccs_request_info *r = &ee->r;
643          struct linux_binprm *bprm = ee->bprm;          struct linux_binprm *bprm = ee->bprm;
# Line 709  static int ccs_environ(struct ccs_execve Line 651  static int ccs_environ(struct ccs_execve
651          int envp_count = bprm->envc;          int envp_count = bprm->envc;
652          /* printk(KERN_DEBUG "start %d %d\n", argv_count, envp_count); */          /* printk(KERN_DEBUG "start %d %d\n", argv_count, envp_count); */
653          int error = -ENOMEM;          int error = -ENOMEM;
654            ee->r.type = CCS_MAC_ENVIRON;
655            ee->r.mode = ccs_get_mode(ccs_current_domain()->profile,
656                                      CCS_MAC_ENVIRON);
657          if (!r->mode || !envp_count)          if (!r->mode || !envp_count)
658                  return 0;                  return 0;
659          arg_ptr = kzalloc(CCS_EXEC_TMPSIZE, CCS_GFP_FLAGS);          arg_ptr = kzalloc(CCS_EXEC_TMPSIZE, CCS_GFP_FLAGS);
# Line 873  static int ccs_get_root_depth(void) Line 818  static int ccs_get_root_depth(void)
818  /**  /**
819   * ccs_try_alt_exec - Try to start execute handler.   * ccs_try_alt_exec - Try to start execute handler.
820   *   *
821   * @ee: Pointer to "struct ccs_execve_entry".   * @ee: Pointer to "struct ccs_execve".
822   *   *
823   * Returns 0 on success, negative value otherwise.   * Returns 0 on success, negative value otherwise.
824   */   */
825  static int ccs_try_alt_exec(struct ccs_execve_entry *ee)  static int ccs_try_alt_exec(struct ccs_execve *ee)
826  {  {
827          /*          /*
828           * Contents of modified bprm.           * Contents of modified bprm.
# Line 1075  static int ccs_try_alt_exec(struct ccs_e Line 1020  static int ccs_try_alt_exec(struct ccs_e
1020  /**  /**
1021   * ccs_find_execute_handler - Find an execute handler.   * ccs_find_execute_handler - Find an execute handler.
1022   *   *
1023   * @ee:   Pointer to "struct ccs_execve_entry".   * @ee:   Pointer to "struct ccs_execve".
1024   * @type: Type of execute handler.   * @type: Type of execute handler.
1025   *   *
1026   * Returns true if found, false otherwise.   * Returns true if found, false otherwise.
1027   *   *
1028   * Caller holds ccs_read_lock().   * Caller holds ccs_read_lock().
1029   */   */
1030  static bool ccs_find_execute_handler(struct ccs_execve_entry *ee,  static bool ccs_find_execute_handler(struct ccs_execve *ee, const u8 type)
                                      const u8 type)  
1031  {  {
1032          struct task_struct *task = current;          struct ccs_request_info *r = &ee->r;
1033          const struct ccs_domain_info *domain = ccs_current_domain();          const struct ccs_domain_info *domain = ccs_current_domain();
1034          struct ccs_acl_info *ptr;          struct ccs_acl_info *ptr;
         bool found = false;  
1035          /*          /*
1036           * Don't use execute handler if the current process is           * To avoid infinite execute handler loop, don't use execute handler
1037           * marked as execute handler to avoid infinite execute handler loop.           * if the current process is marked as execute handler .
1038           */           */
1039          if (task->ccs_flags & CCS_TASK_IS_EXECUTE_HANDLER)          if (current->ccs_flags & CCS_TASK_IS_EXECUTE_HANDLER)
1040                  return false;                  return false;
1041          list_for_each_entry(ptr, &domain->acl_info_list, list) {   retry:
1042                  struct ccs_execute_handler_record *acl;          list_for_each_entry_rcu(ptr, &domain->acl_info_list, list) {
1043                  if (ptr->type != type)                  struct ccs_execute_handler *acl;
1044                    if (ptr->type != type || !ccs_condition(r, ptr->cond))
1045                          continue;                          continue;
1046                  acl = container_of(ptr, struct ccs_execute_handler_record,                  acl = container_of(ptr, struct ccs_execute_handler, head);
                                    head);  
1047                  ee->handler = acl->handler;                  ee->handler = acl->handler;
1048                  found = true;                  ee->handler_type = type;
1049                  break;                  r->cond = ptr->cond;
1050                    return true;
1051          }          }
1052          return found;          if (domain != &ccs_global_domain &&
1053                !domain->flags[CCS_DIF_IGNORE_GLOBAL]) {
1054                    domain = &ccs_global_domain;
1055                    goto retry;
1056            }
1057            return false;
1058  }  }
1059    
1060    #ifdef CONFIG_MMU
1061    #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 23)
1062    #define CCS_BPRM_MMU
1063    #elif defined(RHEL_MAJOR) && RHEL_MAJOR == 5 && defined(RHEL_MINOR) && RHEL_MINOR >= 3
1064    #define CCS_BPRM_MMU
1065    #elif defined(AX_MAJOR) && AX_MAJOR == 3 && defined(AX_MINOR) && AX_MINOR >= 2
1066    #define CCS_BPRM_MMU
1067    #endif
1068    #endif
1069    
1070  /**  /**
1071   * ccs_dump_page - Dump a page to buffer.   * ccs_dump_page - Dump a page to buffer.
1072   *   *
# Line 1128  bool ccs_dump_page(struct linux_binprm * Line 1087  bool ccs_dump_page(struct linux_binprm *
1087                          return false;                          return false;
1088          }          }
1089          /* Same with get_arg_page(bprm, pos, 0) in fs/exec.c */          /* Same with get_arg_page(bprm, pos, 0) in fs/exec.c */
1090  #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 23) && defined(CONFIG_MMU)  #ifdef CCS_BPRM_MMU
         if (get_user_pages(current, bprm->mm, pos, 1, 0, 1, &page, NULL) <= 0)  
                 return false;  
 #elif defined(RHEL_MAJOR) && RHEL_MAJOR == 5 && defined(RHEL_MINOR) && RHEL_MINOR >= 3 && defined(CONFIG_MMU)  
         if (get_user_pages(current, bprm->mm, pos, 1, 0, 1, &page, NULL) <= 0)  
                 return false;  
 #elif defined(AX_MAJOR) && AX_MAJOR == 3 && defined(AX_MINOR) && AX_MINOR >= 2 && defined(CONFIG_MMU)  
1091          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)
1092                  return false;                  return false;
1093  #else  #else
# Line 1154  bool ccs_dump_page(struct linux_binprm * Line 1107  bool ccs_dump_page(struct linux_binprm *
1107                  kunmap_atomic(kaddr, KM_USER0);                  kunmap_atomic(kaddr, KM_USER0);
1108          }          }
1109          /* Same with put_arg_page(page) in fs/exec.c */          /* Same with put_arg_page(page) in fs/exec.c */
1110  #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 23) && defined(CONFIG_MMU)  #ifdef CCS_BPRM_MMU
         put_page(page);  
 #elif defined(RHEL_MAJOR) && RHEL_MAJOR == 5 && defined(RHEL_MINOR) && RHEL_MINOR >= 3 && defined(CONFIG_MMU)  
         put_page(page);  
 #elif defined(AX_MAJOR) && AX_MAJOR == 3 && defined(AX_MINOR) && AX_MINOR >= 2 && defined(CONFIG_MMU)  
1111          put_page(page);          put_page(page);
1112  #endif  #endif
1113          return true;          return true;
# Line 1168  bool ccs_dump_page(struct linux_binprm * Line 1117  bool ccs_dump_page(struct linux_binprm *
1117   * ccs_start_execve - Prepare for execve() operation.   * ccs_start_execve - Prepare for execve() operation.
1118   *   *
1119   * @bprm: Pointer to "struct linux_binprm".   * @bprm: Pointer to "struct linux_binprm".
1120   * @eep:  Pointer to "struct ccs_execve_entry *".   * @eep:  Pointer to "struct ccs_execve *".
1121   *   *
1122   * Returns 0 on success, negative value otherwise.   * Returns 0 on success, negative value otherwise.
1123   */   */
1124  static int ccs_start_execve(struct linux_binprm *bprm,  static int ccs_start_execve(struct linux_binprm *bprm,
1125                              struct ccs_execve_entry **eep)                              struct ccs_execve **eep)
1126  {  {
1127          int retval;          int retval;
1128          struct task_struct *task = current;          struct task_struct *task = current;
1129          struct ccs_execve_entry *ee;          struct ccs_execve *ee;
1130          *eep = NULL;          *eep = NULL;
1131          ee = kzalloc(sizeof(*ee), CCS_GFP_FLAGS);          ee = kzalloc(sizeof(*ee), CCS_GFP_FLAGS);
1132          if (!ee)          if (!ee)
# Line 1191  static int ccs_start_execve(struct linux Line 1140  static int ccs_start_execve(struct linux
1140          /* ee->dump->data is allocated by ccs_dump_page(). */          /* ee->dump->data is allocated by ccs_dump_page(). */
1141          ee->previous_domain = task->ccs_domain_info;          ee->previous_domain = task->ccs_domain_info;
1142          /* Clear manager flag. */          /* Clear manager flag. */
1143          task->ccs_flags &= ~CCS_TASK_IS_POLICY_MANAGER;          task->ccs_flags &= ~CCS_TASK_IS_MANAGER;
1144          *eep = ee;          *eep = ee;
1145          ccs_init_request_info(&ee->r, NULL, CCS_MAC_FILE_EXECUTE);          ccs_init_request_info(&ee->r, CCS_MAC_FILE_EXECUTE);
1146          ee->r.ee = ee;          ee->r.ee = ee;
1147          ee->bprm = bprm;          ee->bprm = bprm;
1148          ee->r.obj = &ee->obj;          ee->r.obj = &ee->obj;
1149          ee->obj.path1.dentry = bprm->file->f_dentry;          ee->obj.path1.dentry = bprm->file->f_dentry;
1150          ee->obj.path1.mnt = bprm->file->f_vfsmnt;          ee->obj.path1.mnt = bprm->file->f_vfsmnt;
         if (ccs_find_execute_handler(ee, CCS_TYPE_EXECUTE_HANDLER)) {  
                 retval = ccs_try_alt_exec(ee);  
                 if (!retval)  
                         ccs_audit_execute_handler_log(ee, true);  
                 goto ok;  
         }  
         retval = ccs_find_next_domain(ee);  
         if (retval != -EPERM)  
                 goto ok;  
         if (ccs_find_execute_handler(ee, CCS_TYPE_DENIED_EXECUTE_HANDLER)) {  
                 retval = ccs_try_alt_exec(ee);  
                 if (!retval)  
                         ccs_audit_execute_handler_log(ee, false);  
         }  
  ok:  
         if (retval < 0)  
                 goto out;  
1151          /*          /*
1152           * Tell GC that I started execve().           * No need to call ccs_environ() for execute handler because envp[] is
1153           * Also, tell open_exec() to check read permission.           * moved to argv[].
1154           */           */
1155          task->ccs_flags |= CCS_TASK_IS_IN_EXECVE;          if (ccs_find_execute_handler(ee, CCS_TYPE_EXECUTE_HANDLER))
1156          /*                  return ccs_try_alt_exec(ee);
1157           * Make task->ccs_flags visible to GC before changing          retval = ccs_find_next_domain(ee);
1158           * task->ccs_domain_info .          if (retval == -EPERM) {
1159           */                  if (ccs_find_execute_handler(ee,
1160          smp_mb();                                               CCS_TYPE_DENIED_EXECUTE_HANDLER))
1161          /*                          return ccs_try_alt_exec(ee);
1162           * Proceed to the next domain in order to allow reaching via PID.          }
1163           * It will be reverted if execve() failed. Reverting is not good.          if (!retval)
1164           * But it is better than being unable to reach via PID in interactive                  retval = ccs_environ(ee);
          * enforcing mode.  
          */  
         task->ccs_domain_info = ee->r.domain;  
         ee->r.type = CCS_MAC_ENVIRON;  
         ee->r.mode = ccs_get_mode(ee->r.domain->profile, CCS_MAC_ENVIRON);  
         retval = ccs_environ(ee);  
         if (retval < 0)  
                 goto out;  
         retval = 0;  
  out:  
1165          return retval;          return retval;
1166  }  }
1167    
# Line 1247  static int ccs_start_execve(struct linux Line 1169  static int ccs_start_execve(struct linux
1169   * ccs_finish_execve - Clean up execve() operation.   * ccs_finish_execve - Clean up execve() operation.
1170   *   *
1171   * @retval: Return code of an execve() operation.   * @retval: Return code of an execve() operation.
1172   * @ee:     Pointer to "struct ccs_execve_entry".   * @ee:     Pointer to "struct ccs_execve".
1173   *   *
1174   * Caller holds ccs_read_lock().   * Caller holds ccs_read_lock().
1175   */   */
1176  static void ccs_finish_execve(int retval, struct ccs_execve_entry *ee)  static void ccs_finish_execve(int retval, struct ccs_execve *ee)
1177  {  {
1178          struct task_struct *task = current;          struct task_struct *task = current;
1179          if (!ee)          if (!ee)
# Line 1296  int ccs_may_transit(const char *domainna Line 1218  int ccs_may_transit(const char *domainna
1218          struct ccs_request_info r;          struct ccs_request_info r;
1219          struct ccs_domain_info *domain;          struct ccs_domain_info *domain;
1220          int error;          int error;
1221            bool domain_created = false;
1222          name.name = pathname;          name.name = pathname;
1223          ccs_fill_path_info(&name);          ccs_fill_path_info(&name);
1224          /* Check allow_transit permission. */          /* Check "file transit" permission. */
1225          ccs_init_request_info(&r, NULL, CCS_MAC_FILE_TRANSIT);          ccs_init_request_info(&r, CCS_MAC_FILE_TRANSIT);
1226          error = ccs_path_permission(&r, CCS_TYPE_TRANSIT, &name);          error = ccs_path_permission(&r, CCS_TYPE_TRANSIT, &name);
1227          if (error)          if (error)
1228                  return error;                  return error;
# Line 1307  int ccs_may_transit(const char *domainna Line 1230  int ccs_may_transit(const char *domainna
1230          domain = ccs_find_domain(domainname);          domain = ccs_find_domain(domainname);
1231          if (!domain && r.mode != CCS_CONFIG_ENFORCING &&          if (!domain && r.mode != CCS_CONFIG_ENFORCING &&
1232              strlen(domainname) < CCS_EXEC_TMPSIZE - 10) {              strlen(domainname) < CCS_EXEC_TMPSIZE - 10) {
1233                  domain = ccs_find_or_assign_new_domain(domainname, r.profile);                  domain = ccs_assign_domain(domainname, r.profile);
1234                  if (domain)                  if (domain)
1235                          ccs_audit_domain_creation_log(domain);                          domain_created = true;
1236          }          }
1237          if (domain) {          if (domain) {
1238                  error = 0;                  error = 0;
1239                  current->ccs_domain_info = domain;                  current->ccs_domain_info = domain;
1240                    if (domain_created)
1241                            ccs_audit_domain_creation_log();
1242          } else {          } else {
1243                  error = -ENOENT;                  error = -ENOENT;
1244          }          }
# Line 1323  int ccs_may_transit(const char *domainna Line 1248  int ccs_may_transit(const char *domainna
1248  static int __ccs_search_binary_handler(struct linux_binprm *bprm,  static int __ccs_search_binary_handler(struct linux_binprm *bprm,
1249                                         struct pt_regs *regs)                                         struct pt_regs *regs)
1250  {  {
1251          struct ccs_execve_entry *ee;          struct ccs_execve *ee;
1252          int retval;          int retval;
1253          if (!ccs_policy_loaded)          if (!ccs_policy_loaded)
1254                  ccsecurity_exports.load_policy(bprm->filename);                  ccsecurity_exports.load_policy(bprm->filename);

Legend:
Removed from v.3626  
changed lines
  Added in v.3808

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