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

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 3064 by kumaneko, Fri Sep 25 08:55:35 2009 UTC branches/ccs-patch/security/ccsecurity/domain.c revision 3691 by kumaneko, Sun May 23 03:22:24 2010 UTC
# Line 1  Line 1 
1  /*  /*
2   * security/ccsecurity/domain.c   * security/ccsecurity/domain.c
3   *   *
4   * Copyright (C) 2005-2009  NTT DATA CORPORATION   * Copyright (C) 2005-2010  NTT DATA CORPORATION
5   *   *
6   * Version: 1.7.0   2009/09/06   * Version: 1.7.2+   2010/05/05
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 30  struct ccs_domain_info ccs_kernel_domain Line 30  struct ccs_domain_info ccs_kernel_domain
30  /* The list for "struct ccs_domain_info". */  /* The list for "struct ccs_domain_info". */
31  LIST_HEAD(ccs_domain_list);  LIST_HEAD(ccs_domain_list);
32    
33    struct list_head ccs_policy_list[CCS_MAX_POLICY];
34    struct list_head ccs_group_list[CCS_MAX_GROUP];
35    struct list_head ccs_shared_list[CCS_MAX_LIST];
36    
37  /**  /**
38   * ccs_audit_execute_handler_log - Audit execute_handler log.   * ccs_audit_execute_handler_log - Audit execute_handler log.
39   *   *
40   * @ee:         Pointer to "struct ccs_execve_entry".   * @ee:         Pointer to "struct ccs_execve_entry".
  * @is_default: True if it is "execute_handler" log.  
41   *   *
42   * Returns 0 on success, negative value otherwise.   * Returns 0 on success, negative value otherwise.
43   */   */
44  static int ccs_audit_execute_handler_log(struct ccs_execve_entry *ee,  static int ccs_audit_execute_handler_log(struct ccs_execve_entry *ee)
                                          const bool is_default)  
45  {  {
46          struct ccs_request_info *r = &ee->r;          struct ccs_request_info *r = &ee->r;
47          const char *handler = ee->handler->name;          const char *handler = ee->handler->name;
48            r->type = CCS_MAC_FILE_EXECUTE;
49          r->mode = ccs_get_mode(r->profile, CCS_MAC_FILE_EXECUTE);          r->mode = ccs_get_mode(r->profile, CCS_MAC_FILE_EXECUTE);
50          return ccs_write_audit_log(true, r, "%s %s\n",          return ccs_write_audit_log(true, r, "%s" CCS_KEYWORD_EXECUTE_HANDLER
51                                     is_default ? CCS_KEYWORD_EXECUTE_HANDLER :                                     " %s\n", ee->handler_type ==
52                                     CCS_KEYWORD_DENIED_EXECUTE_HANDLER, handler);                                     CCS_TYPE_DENIED_EXECUTE_HANDLER ?
53                                       "denied_" : "", handler);
54  }  }
55    
56  /**  /**
57   * ccs_audit_domain_creation_log - Audit domain creation log.   * ccs_audit_domain_creation_log - Audit domain creation log.
58   *   *
  * @domain:  Pointer to "struct ccs_domain_info".  
  *  
59   * Returns 0 on success, negative value otherwise.   * Returns 0 on success, negative value otherwise.
60   */   */
61  static int ccs_audit_domain_creation_log(struct ccs_domain_info *domain)  static int ccs_audit_domain_creation_log(void)
62  {  {
         int error;  
63          struct ccs_request_info r;          struct ccs_request_info r;
64          ccs_init_request_info(&r, domain, CCS_MAC_FILE_EXECUTE);          ccs_init_request_info(&r, CCS_MAC_FILE_EXECUTE);
65          error = ccs_write_audit_log(false, &r, "use_profile %u\n", r.profile);          return ccs_write_audit_log(false, &r, "use_profile %u\n", r.profile);
66    }
67    
68    int ccs_update_policy(struct ccs_acl_head *new_entry, const int size,
69                          bool is_delete, const int idx, bool (*check_duplicate)
70                          (const struct ccs_acl_head *,
71                           const struct ccs_acl_head *))
72    {
73            int error = is_delete ? -ENOENT : -ENOMEM;
74            struct ccs_acl_head *entry;
75            if (mutex_lock_interruptible(&ccs_policy_lock))
76                    return -ENOMEM;
77            list_for_each_entry_rcu(entry, &ccs_policy_list[idx], list) {
78                    if (!check_duplicate(entry, new_entry))
79                            continue;
80                    entry->is_deleted = is_delete;
81                    error = 0;
82                    break;
83            }
84            if (error && !is_delete) {
85                    entry = ccs_commit_ok(new_entry, size);
86                    if (entry) {
87                            list_add_tail_rcu(&entry->list, &ccs_policy_list[idx]);
88                            error = 0;
89                    }
90            }
91            mutex_unlock(&ccs_policy_lock);
92            return error;
93    }
94    
95    int ccs_update_group(struct ccs_acl_head *new_entry, const int size,
96                         bool is_delete, struct ccs_group *group,
97                         bool (*check_duplicate) (const struct ccs_acl_head *,
98                                                  const struct ccs_acl_head *))
99    {
100            int error = is_delete ? -ENOENT : -ENOMEM;
101            struct ccs_acl_head *entry;
102            if (mutex_lock_interruptible(&ccs_policy_lock))
103                    return -ENOMEM;
104            list_for_each_entry_rcu(entry, &group->member_list, list) {
105                    if (!check_duplicate(entry, new_entry))
106                            continue;
107                    entry->is_deleted = is_delete;
108                    error = 0;
109                    break;
110            }
111            if (!is_delete && error) {
112                    entry = ccs_commit_ok(new_entry, size);
113                    if (entry) {
114                            list_add_tail_rcu(&entry->list, &group->member_list);
115                            error = 0;
116                    }
117            }
118            mutex_unlock(&ccs_policy_lock);
119          return error;          return error;
120  }  }
121    
122  /* The list for "struct ccs_domain_initializer_entry". */  int ccs_update_domain_policy(struct ccs_acl_info *new_entry, const int size,
123  LIST_HEAD(ccs_domain_initializer_list);                               bool is_delete, struct ccs_domain_info *domain,
124                                 bool (*check_duplicate)
125                                 (const struct ccs_acl_info *,
126                                  const struct ccs_acl_info *),
127                                 bool (*merge_duplicate) (struct ccs_acl_info *,
128                                                          struct ccs_acl_info *,
129                                                          const bool))
130    {
131            int error = is_delete ? -ENOENT : -ENOMEM;
132            struct ccs_acl_info *entry;
133            if (mutex_lock_interruptible(&ccs_policy_lock))
134                    return error;
135            list_for_each_entry_rcu(entry, &domain->acl_info_list, list) {
136                    if (!check_duplicate(entry, new_entry))
137                            continue;
138                    if (merge_duplicate)
139                            entry->is_deleted = merge_duplicate(entry, new_entry,
140                                                                is_delete);
141                    else
142                            entry->is_deleted = is_delete;
143                    error = 0;
144                    break;
145            }
146            if (error && !is_delete) {
147                    entry = ccs_commit_ok(new_entry, size);
148                    if (entry) {
149                            ccs_add_domain_acl(domain, entry);
150                            error = 0;
151                    }
152            }
153            mutex_unlock(&ccs_policy_lock);
154            return error;
155    }
156    
157    static bool ccs_is_same_domain_initializer_entry(const struct ccs_acl_head *a,
158                                                     const struct ccs_acl_head *b)
159    {
160            const struct ccs_domain_initializer_entry *p1 =
161                    container_of(a, typeof(*p1), head);
162            const struct ccs_domain_initializer_entry *p2 =
163                    container_of(b, typeof(*p2), head);
164            return p1->is_not == p2->is_not && p1->is_last_name == p2->is_last_name
165                    && p1->domainname == p2->domainname
166                    && p1->program == p2->program;
167    }
168    
169  /**  /**
170   * ccs_update_domain_initializer_entry - Update "struct ccs_domain_initializer_entry" list.   * ccs_update_domain_initializer_entry - Update "struct ccs_domain_initializer_entry" list.
# Line 83  static int ccs_update_domain_initializer Line 181  static int ccs_update_domain_initializer
181                                                 const bool is_not,                                                 const bool is_not,
182                                                 const bool is_delete)                                                 const bool is_delete)
183  {  {
         struct ccs_domain_initializer_entry *entry = NULL;  
         struct ccs_domain_initializer_entry *ptr;  
184          struct ccs_domain_initializer_entry e = { .is_not = is_not };          struct ccs_domain_initializer_entry e = { .is_not = is_not };
185          int error = is_delete ? -ENOENT : -ENOMEM;          int error = is_delete ? -ENOENT : -ENOMEM;
186          if (!ccs_is_correct_path(program, 1, -1, -1))          if (!ccs_is_correct_path(program, 1, -1, -1))
# Line 102  static int ccs_update_domain_initializer Line 198  static int ccs_update_domain_initializer
198          e.program = ccs_get_name(program);          e.program = ccs_get_name(program);
199          if (!e.program)          if (!e.program)
200                  goto out;                  goto out;
201          if (!is_delete)          error = ccs_update_policy(&e.head, sizeof(e), is_delete,
202                  entry = kmalloc(sizeof(e), GFP_KERNEL);                                    CCS_ID_DOMAIN_INITIALIZER,
203          mutex_lock(&ccs_policy_lock);                                    ccs_is_same_domain_initializer_entry);
         list_for_each_entry_rcu(ptr, &ccs_domain_initializer_list, list) {  
                 if (ccs_memcmp(ptr, &e, offsetof(typeof(e), is_not),  
                                sizeof(e)))  
                         continue;  
                 ptr->is_deleted = is_delete;  
                 error = 0;  
                 break;  
         }  
         if (!is_delete && error && ccs_commit_ok(entry, &e, sizeof(e))) {  
                 list_add_tail_rcu(&entry->list, &ccs_domain_initializer_list);  
                 entry = NULL;  
                 error = 0;  
         }  
         mutex_unlock(&ccs_policy_lock);  
204   out:   out:
205          ccs_put_name(e.domainname);          ccs_put_name(e.domainname);
206          ccs_put_name(e.program);          ccs_put_name(e.program);
         kfree(entry);  
207          return error;          return error;
208  }  }
209    
210  /**  /**
  * 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)  
 {  
         struct list_head *pos;  
         bool done = true;  
         list_for_each_cookie(pos, head->read_var2,  
                              &ccs_domain_initializer_list) {  
                 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;  
         }  
         return done;  
 }  
   
 /**  
211   * ccs_write_domain_initializer_policy - Write "struct ccs_domain_initializer_entry" list.   * ccs_write_domain_initializer_policy - Write "struct ccs_domain_initializer_entry" list.
212   *   *
213   * @data:      String to parse.   * @data:      String to parse.
  * @is_not:    True if it is "no_initialize_domain" entry.  
214   * @is_delete: True if it is a delete request.   * @is_delete: True if it is a delete request.
215   *   *
216   * Returns 0 on success, negative value otherwise.   * Returns 0 on success, negative value otherwise.
217   */   */
218  int ccs_write_domain_initializer_policy(char *data, const bool is_not,  int ccs_write_domain_initializer_policy(char *data, const bool is_delete, const u8 flags)
                                         const bool is_delete)  
219  {  {
220          char *cp = strstr(data, " from ");          char *domainname = strstr(data, " from ");
221          if (cp) {          if (domainname) {
222                  *cp = '\0';                  *domainname = '\0';
223                  return ccs_update_domain_initializer_entry(cp + 6, data,                  domainname += 6;
                                                            is_not, is_delete);  
224          }          }
225          return ccs_update_domain_initializer_entry(NULL, data, is_not,          return ccs_update_domain_initializer_entry(domainname, data, flags,
226                                                     is_delete);                                                     is_delete);
227  }  }
228    
# Line 203  static bool ccs_is_domain_initializer(co Line 244  static bool ccs_is_domain_initializer(co
244  {  {
245          struct ccs_domain_initializer_entry *ptr;          struct ccs_domain_initializer_entry *ptr;
246          bool flag = false;          bool flag = false;
247          list_for_each_entry_rcu(ptr, &ccs_domain_initializer_list, list) {          list_for_each_entry_rcu(ptr, &ccs_policy_list
248                  if (ptr->is_deleted)                                  [CCS_ID_DOMAIN_INITIALIZER], head.list) {
249                    if (ptr->head.is_deleted)
250                          continue;                          continue;
251                  if (ptr->domainname) {                  if (ptr->domainname) {
252                          if (!ptr->is_last_name) {                          if (!ptr->is_last_name) {
# Line 226  static bool ccs_is_domain_initializer(co Line 268  static bool ccs_is_domain_initializer(co
268          return flag;          return flag;
269  }  }
270    
271  /* The list for "struct ccs_domain_keeper_entry". */  static bool ccs_is_same_domain_keeper_entry(const struct ccs_acl_head *a,
272  LIST_HEAD(ccs_domain_keeper_list);                                              const struct ccs_acl_head *b)
273    {
274            const struct ccs_domain_keeper_entry *p1 =
275                    container_of(a, typeof(*p1), head);
276            const struct ccs_domain_keeper_entry *p2 =
277                    container_of(b, typeof(*p2), head);
278            return p1->is_not == p2->is_not && p1->is_last_name == p2->is_last_name
279                    && p1->domainname == p2->domainname
280                    && p1->program == p2->program;
281    }
282    
283  /**  /**
284   * ccs_update_domain_keeper_entry - Update "struct ccs_domain_keeper_entry" list.   * ccs_update_domain_keeper_entry - Update "struct ccs_domain_keeper_entry" list.
# Line 244  static int ccs_update_domain_keeper_entr Line 295  static int ccs_update_domain_keeper_entr
295                                            const bool is_not,                                            const bool is_not,
296                                            const bool is_delete)                                            const bool is_delete)
297  {  {
         struct ccs_domain_keeper_entry *entry = NULL;  
         struct ccs_domain_keeper_entry *ptr;  
298          struct ccs_domain_keeper_entry e = { .is_not = is_not };          struct ccs_domain_keeper_entry e = { .is_not = is_not };
299          int error = is_delete ? -ENOENT : -ENOMEM;          int error = is_delete ? -ENOENT : -ENOMEM;
300          if (!ccs_is_domain_def(domainname) &&          if (!ccs_is_domain_def(domainname) &&
# Line 263  static int ccs_update_domain_keeper_entr Line 312  static int ccs_update_domain_keeper_entr
312          e.domainname = ccs_get_name(domainname);          e.domainname = ccs_get_name(domainname);
313          if (!e.domainname)          if (!e.domainname)
314                  goto out;                  goto out;
315          if (!is_delete)          error = ccs_update_policy(&e.head, sizeof(e), is_delete,
316                  entry = kmalloc(sizeof(e), GFP_KERNEL);                                    CCS_ID_DOMAIN_KEEPER,
317          mutex_lock(&ccs_policy_lock);                                    ccs_is_same_domain_keeper_entry);
         list_for_each_entry_rcu(ptr, &ccs_domain_keeper_list, list) {  
                 if (ccs_memcmp(ptr, &e, offsetof(typeof(e), is_not),  
                                sizeof(e)))  
                         continue;  
                 ptr->is_deleted = is_delete;  
                 error = 0;  
                 break;  
         }  
         if (!is_delete && error && ccs_commit_ok(entry, &e, sizeof(e))) {  
                 list_add_tail_rcu(&entry->list, &ccs_domain_keeper_list);  
                 entry = NULL;  
                 error = 0;  
         }  
         mutex_unlock(&ccs_policy_lock);  
318   out:   out:
319          ccs_put_name(e.domainname);          ccs_put_name(e.domainname);
320          ccs_put_name(e.program);          ccs_put_name(e.program);
         kfree(entry);  
321          return error;          return error;
322  }  }
323    
# Line 291  static int ccs_update_domain_keeper_entr Line 325  static int ccs_update_domain_keeper_entr
325   * ccs_write_domain_keeper_policy - Write "struct ccs_domain_keeper_entry" list.   * ccs_write_domain_keeper_policy - Write "struct ccs_domain_keeper_entry" list.
326   *   *
327   * @data:      String to parse.   * @data:      String to parse.
  * @is_not:    True if it is "no_keep_domain" entry.  
328   * @is_delete: True if it is a delete request.   * @is_delete: True if it is a delete request.
329   *   *
330     * Returns 0 on success, negative value otherwise.
331   */   */
332  int ccs_write_domain_keeper_policy(char *data, const bool is_not,  int ccs_write_domain_keeper_policy(char *data, const bool is_delete,
333                                     const bool is_delete)                                     const u8 flags)
 {  
         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)  
334  {  {
335          struct list_head *pos;          char *domainname = strstr(data, " from ");
336          bool done = true;          if (domainname) {
337          list_for_each_cookie(pos, head->read_var2,                  *domainname = '\0';
338                               &ccs_domain_keeper_list) {                  domainname += 6;
339                  struct ccs_domain_keeper_entry *ptr;          } else {
340                  const char *no;                  domainname = data;
341                  const char *from = "";                  data = NULL;
                 const char *program = "";  
                 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;  
342          }          }
343          return done;          return ccs_update_domain_keeper_entry(domainname, data, flags,
344                                                  is_delete);
345  }  }
346    
347  /**  /**
# Line 361  static bool ccs_is_domain_keeper(const s Line 362  static bool ccs_is_domain_keeper(const s
362  {  {
363          struct ccs_domain_keeper_entry *ptr;          struct ccs_domain_keeper_entry *ptr;
364          bool flag = false;          bool flag = false;
365          list_for_each_entry_rcu(ptr, &ccs_domain_keeper_list, list) {          list_for_each_entry_rcu(ptr, &ccs_policy_list[CCS_ID_DOMAIN_KEEPER],
366                  if (ptr->is_deleted)                                  head.list) {
367                    if (ptr->head.is_deleted)
368                          continue;                          continue;
369                  if (!ptr->is_last_name) {                  if (!ptr->is_last_name) {
370                          if (ptr->domainname != domainname)                          if (ptr->domainname != domainname)
# Line 382  static bool ccs_is_domain_keeper(const s Line 384  static bool ccs_is_domain_keeper(const s
384          return flag;          return flag;
385  }  }
386    
387  /* The list for "struct ccs_aggregator_entry". */  static bool ccs_is_same_aggregator_entry(const struct ccs_acl_head *a,
388  LIST_HEAD(ccs_aggregator_list);                                           const struct ccs_acl_head *b)
389    {
390            const struct ccs_aggregator_entry *p1 =
391                    container_of(a, typeof(*p1), head);
392            const struct ccs_aggregator_entry *p2 =
393                    container_of(b, typeof(*p2), head);
394            return p1->original_name == p2->original_name &&
395                    p1->aggregated_name == p2->aggregated_name;
396    }
397    
398  /**  /**
399   * ccs_update_aggregator_entry - Update "struct ccs_aggregator_entry" list.   * ccs_update_aggregator_entry - Update "struct ccs_aggregator_entry" list.
# Line 398  static int ccs_update_aggregator_entry(c Line 408  static int ccs_update_aggregator_entry(c
408                                         const char *aggregated_name,                                         const char *aggregated_name,
409                                         const bool is_delete)                                         const bool is_delete)
410  {  {
         struct ccs_aggregator_entry *entry = NULL;  
         struct ccs_aggregator_entry *ptr;  
411          struct ccs_aggregator_entry e = { };          struct ccs_aggregator_entry e = { };
412          int error = is_delete ? -ENOENT : -ENOMEM;          int error = is_delete ? -ENOENT : -ENOMEM;
413          if (!ccs_is_correct_path(original_name, 1, 0, -1) ||          if (!ccs_is_correct_path(original_name, 1, 0, -1) ||
# Line 409  static int ccs_update_aggregator_entry(c Line 417  static int ccs_update_aggregator_entry(c
417          e.aggregated_name = ccs_get_name(aggregated_name);          e.aggregated_name = ccs_get_name(aggregated_name);
418          if (!e.original_name || !e.aggregated_name)          if (!e.original_name || !e.aggregated_name)
419                  goto out;                  goto out;
420          if (!is_delete)          error = ccs_update_policy(&e.head, sizeof(e), is_delete,
421                  entry = kmalloc(sizeof(e), GFP_KERNEL);                                    CCS_ID_AGGREGATOR,
422          mutex_lock(&ccs_policy_lock);                                    ccs_is_same_aggregator_entry);
         list_for_each_entry_rcu(ptr, &ccs_aggregator_list, list) {  
                 if (ccs_memcmp(ptr, &e, offsetof(typeof(e), original_name),  
                                sizeof(e)))  
                         continue;  
                 ptr->is_deleted = is_delete;  
                 error = 0;  
                 break;  
         }  
         if (!is_delete && error && ccs_commit_ok(entry, &e, sizeof(e))) {  
                 list_add_tail_rcu(&entry->list, &ccs_aggregator_list);  
                 entry = NULL;  
                 error = 0;  
         }  
         mutex_unlock(&ccs_policy_lock);  
423   out:   out:
424          ccs_put_name(e.original_name);          ccs_put_name(e.original_name);
425          ccs_put_name(e.aggregated_name);          ccs_put_name(e.aggregated_name);
         kfree(entry);  
426          return error;          return error;
427  }  }
428    
429  /**  /**
  * ccs_read_aggregator_policy - Read "struct ccs_aggregator_entry" 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;  
 }  
   
 /**  
430   * ccs_write_aggregator_policy - Write "struct ccs_aggregator_entry" list.   * ccs_write_aggregator_policy - Write "struct ccs_aggregator_entry" list.
431   *   *
432   * @data:      String to parse.   * @data:      String to parse.
# Line 468  bool ccs_read_aggregator_policy(struct c Line 434  bool ccs_read_aggregator_policy(struct c
434   *   *
435   * Returns 0 on success, negative value otherwise.   * Returns 0 on success, negative value otherwise.
436   */   */
437  int ccs_write_aggregator_policy(char *data, const bool is_delete)  int ccs_write_aggregator_policy(char *data, const bool is_delete, const u8 flags)
438  {  {
439          char *w[2];          char *w[2];
440          if (!ccs_tokenize(data, w, sizeof(w)) || !w[1][0])          if (!ccs_tokenize(data, w, sizeof(w)) || !w[1][0])
# Line 491  int ccs_delete_domain(char *domainname) Line 457  int ccs_delete_domain(char *domainname)
457          struct ccs_path_info name;          struct ccs_path_info name;
458          name.name = domainname;          name.name = domainname;
459          ccs_fill_path_info(&name);          ccs_fill_path_info(&name);
460          mutex_lock(&ccs_policy_lock);          if (mutex_lock_interruptible(&ccs_policy_lock))
461                    return 0;
462          /* Is there an active domain? */          /* Is there an active domain? */
463          list_for_each_entry_rcu(domain, &ccs_domain_list, list) {          list_for_each_entry_rcu(domain, &ccs_domain_list, list) {
464                  /* Never delete ccs_kernel_domain */                  /* Never delete ccs_kernel_domain */
# Line 519  struct ccs_domain_info *ccs_find_or_assi Line 486  struct ccs_domain_info *ccs_find_or_assi
486                                                        const u8 profile)                                                        const u8 profile)
487  {  {
488          struct ccs_domain_info *entry;          struct ccs_domain_info *entry;
489          struct ccs_domain_info *domain;          struct ccs_domain_info *domain = NULL;
490          const struct ccs_path_info *saved_domainname;          const struct ccs_path_info *saved_domainname;
491          bool found = false;          bool found = false;
492    
# Line 528  struct ccs_domain_info *ccs_find_or_assi Line 495  struct ccs_domain_info *ccs_find_or_assi
495          saved_domainname = ccs_get_name(domainname);          saved_domainname = ccs_get_name(domainname);
496          if (!saved_domainname)          if (!saved_domainname)
497                  return NULL;                  return NULL;
498          entry = kzalloc(sizeof(*entry), GFP_KERNEL);          entry = kzalloc(sizeof(*entry), CCS_GFP_FLAGS);
499          mutex_lock(&ccs_policy_lock);          if (mutex_lock_interruptible(&ccs_policy_lock))
500                    goto out;
501          list_for_each_entry_rcu(domain, &ccs_domain_list, list) {          list_for_each_entry_rcu(domain, &ccs_domain_list, list) {
502                  if (domain->is_deleted ||                  if (domain->is_deleted ||
503                      ccs_pathcmp(saved_domainname, domain->domainname))                      ccs_pathcmp(saved_domainname, domain->domainname))
# Line 548  struct ccs_domain_info *ccs_find_or_assi Line 516  struct ccs_domain_info *ccs_find_or_assi
516                  found = true;                  found = true;
517          }          }
518          mutex_unlock(&ccs_policy_lock);          mutex_unlock(&ccs_policy_lock);
519     out:
520          ccs_put_name(saved_domainname);          ccs_put_name(saved_domainname);
521          kfree(entry);          kfree(entry);
522          return found ? domain : NULL;          return found ? domain : NULL;
# Line 567  static int ccs_find_next_domain(struct c Line 536  static int ccs_find_next_domain(struct c
536          struct ccs_request_info *r = &ee->r;          struct ccs_request_info *r = &ee->r;
537          const struct ccs_path_info *handler = ee->handler;          const struct ccs_path_info *handler = ee->handler;
538          struct ccs_domain_info *domain = NULL;          struct ccs_domain_info *domain = NULL;
539          const char *old_domain_name = r->domain->domainname->name;          struct ccs_domain_info * const old_domain = ccs_current_domain();
540            const char *old_domain_name = old_domain->domainname->name;
541          struct linux_binprm *bprm = ee->bprm;          struct linux_binprm *bprm = ee->bprm;
542          const u32 ccs_flags = current->ccs_flags;          struct task_struct *task = current;
543            const u32 ccs_flags = task->ccs_flags;
544          struct ccs_path_info rn = { }; /* real name */          struct ccs_path_info rn = { }; /* real name */
545          struct ccs_path_info ln; /* last name */          struct ccs_path_info ln; /* last name */
546          int retval;          int retval;
547          bool need_kfree = false;          bool need_kfree = false;
548            bool domain_created = false;
549          ln.name = ccs_last_word(old_domain_name);          ln.name = ccs_last_word(old_domain_name);
550          ccs_fill_path_info(&ln);          ccs_fill_path_info(&ln);
551   retry:   retry:
# Line 604  static int ccs_find_next_domain(struct c Line 576  static int ccs_find_next_domain(struct c
576          } else {          } else {
577                  struct ccs_aggregator_entry *ptr;                  struct ccs_aggregator_entry *ptr;
578                  /* Check 'aggregator' directive. */                  /* Check 'aggregator' directive. */
579                  list_for_each_entry_rcu(ptr, &ccs_aggregator_list, list) {                  list_for_each_entry_rcu(ptr,
580                          if (ptr->is_deleted ||                                          &ccs_policy_list[CCS_ID_AGGREGATOR],
581                                            head.list) {
582                            if (ptr->head.is_deleted ||
583                              !ccs_path_matches_pattern(&rn, ptr->original_name))                              !ccs_path_matches_pattern(&rn, ptr->original_name))
584                                  continue;                                  continue;
585                          kfree(rn.name);                          kfree(rn.name);
# Line 617  static int ccs_find_next_domain(struct c Line 591  static int ccs_find_next_domain(struct c
591    
592                  /* Check execute permission. */                  /* Check execute permission. */
593                  retval = ccs_exec_perm(r, &rn);                  retval = ccs_exec_perm(r, &rn);
594                  if (retval == 1)                  if (retval == CCS_RETRY_REQUEST)
595                          goto retry;                          goto retry;
596                  if (retval < 0)                  if (retval < 0)
597                          goto out;                          goto out;
598          }          }
599    
600          /* Calculate domain to transit to. */          /* Calculate domain to transit to. */
601          if (ccs_is_domain_initializer(r->domain->domainname, &rn, &ln)) {          if (ccs_is_domain_initializer(old_domain->domainname, &rn, &ln)) {
602                  /* Transit to the child of ccs_kernel_domain domain. */                  /* Transit to the child of ccs_kernel_domain domain. */
603                  snprintf(ee->tmp, CCS_EXEC_TMPSIZE - 1, ROOT_NAME " " "%s",                  snprintf(ee->tmp, CCS_EXEC_TMPSIZE - 1, ROOT_NAME " " "%s",
604                           rn.name);                           rn.name);
605          } else if (r->domain == &ccs_kernel_domain && !ccs_policy_loaded) {          } else if (old_domain == &ccs_kernel_domain && !ccs_policy_loaded) {
606                  /*                  /*
607                   * Needn't to transit from kernel domain before starting                   * Needn't to transit from kernel domain before starting
608                   * /sbin/init. But transit from kernel domain if executing                   * /sbin/init. But transit from kernel domain if executing
609                   * initializers because they might start before /sbin/init.                   * initializers because they might start before /sbin/init.
610                   */                   */
611                  domain = r->domain;                  domain = old_domain;
612          } else if (ccs_is_domain_keeper(r->domain->domainname, &rn, &ln)) {          } else if (ccs_is_domain_keeper(old_domain->domainname, &rn, &ln)) {
613                  /* Keep current domain. */                  /* Keep current domain. */
614                  domain = r->domain;                  domain = old_domain;
615          } else {          } else {
616                  /* Normal domain transition. */                  /* Normal domain transition. */
617                  snprintf(ee->tmp, CCS_EXEC_TMPSIZE - 1, "%s %s",                  snprintf(ee->tmp, CCS_EXEC_TMPSIZE - 1, "%s %s",
# Line 651  static int ccs_find_next_domain(struct c Line 625  static int ccs_find_next_domain(struct c
625          if (r->mode == CCS_CONFIG_ENFORCING) {          if (r->mode == CCS_CONFIG_ENFORCING) {
626                  int error = ccs_supervisor(r, "# wants to create domain\n"                  int error = ccs_supervisor(r, "# wants to create domain\n"
627                                             "%s\n", ee->tmp);                                             "%s\n", ee->tmp);
628                  if (error == 1)                  if (error == CCS_RETRY_REQUEST)
629                          goto retry;                          goto retry;
630                  if (error < 0)                  if (error < 0)
631                          goto done;                          goto done;
632          }          }
633          domain = ccs_find_or_assign_new_domain(ee->tmp, r->profile);          domain = ccs_find_or_assign_new_domain(ee->tmp, r->profile);
634          if (domain)          if (domain)
635                  ccs_audit_domain_creation_log(r->domain);                  domain_created = true;
636   done:   done:
637          if (!domain) {          if (!domain) {
638                  printk(KERN_WARNING "ERROR: Domain '%s' not defined.\n",                  retval = (r->mode == CCS_CONFIG_ENFORCING) ? -EPERM : 0;
639                         ee->tmp);                  if (!old_domain->domain_transition_failed) {
640                  if (r->mode == CCS_CONFIG_ENFORCING)                          old_domain->domain_transition_failed = true;
641                          retval = -EPERM;                          ccs_write_audit_log(false, r,
642                  else {                                              CCS_KEYWORD_TRANSITION_FAILED
643                          retval = 0;                                              "\n");
644                          r->domain->domain_transition_failed = true;                          printk(KERN_WARNING "ERROR: Domain '%s' not defined.\n",
645                                   ee->tmp);
646                  }                  }
647          } else {          } else {
648                  retval = 0;                  retval = 0;
649          }          }
650   out:          if (!retval && handler)
651                    ccs_audit_execute_handler_log(ee);
652            /*
653             * Tell GC that I started execve().
654             * Also, tell open_exec() to check read permission.
655             */
656            task->ccs_flags |= CCS_TASK_IS_IN_EXECVE;
657            /*
658             * Make task->ccs_flags visible to GC before changing
659             * task->ccs_domain_info .
660             */
661            smp_mb();
662            /*
663             * Proceed to the next domain in order to allow reaching via PID.
664             * It will be reverted if execve() failed. Reverting is not good.
665             * But it is better than being unable to reach via PID in interactive
666             * enforcing mode.
667             */
668          if (domain)          if (domain)
669                  r->domain = domain;                  task->ccs_domain_info = domain;
670            if (domain_created)
671                    ccs_audit_domain_creation_log();
672     out:
673          if (need_kfree)          if (need_kfree)
674                  kfree(rn.name);                  kfree(rn.name);
675          return retval;          return retval;
# Line 691  static int ccs_environ(struct ccs_execve Line 686  static int ccs_environ(struct ccs_execve
686  {  {
687          struct ccs_request_info *r = &ee->r;          struct ccs_request_info *r = &ee->r;
688          struct linux_binprm *bprm = ee->bprm;          struct linux_binprm *bprm = ee->bprm;
689          char *arg_ptr = ee->tmp;          /* env_page->data is allocated by ccs_dump_page(). */
690            struct ccs_page_dump env_page = { };
691            char *arg_ptr; /* Size is CCS_EXEC_TMPSIZE bytes */
692          int arg_len = 0;          int arg_len = 0;
693          unsigned long pos = bprm->p;          unsigned long pos = bprm->p;
694          int offset = pos % PAGE_SIZE;          int offset = pos % PAGE_SIZE;
# Line 699  static int ccs_environ(struct ccs_execve Line 696  static int ccs_environ(struct ccs_execve
696          int envp_count = bprm->envc;          int envp_count = bprm->envc;
697          /* printk(KERN_DEBUG "start %d %d\n", argv_count, envp_count); */          /* printk(KERN_DEBUG "start %d %d\n", argv_count, envp_count); */
698          int error = -ENOMEM;          int error = -ENOMEM;
699            ee->r.type = CCS_MAC_ENVIRON;
700            ee->r.mode = ccs_get_mode(ccs_current_domain()->profile,
701                                      CCS_MAC_ENVIRON);
702          if (!r->mode || !envp_count)          if (!r->mode || !envp_count)
703                  return 0;                  return 0;
704            arg_ptr = kzalloc(CCS_EXEC_TMPSIZE, CCS_GFP_FLAGS);
705            if (!arg_ptr)
706                    goto out;
707          while (error == -ENOMEM) {          while (error == -ENOMEM) {
708                  if (!ccs_dump_page(bprm, pos, &ee->dump))                  if (!ccs_dump_page(bprm, pos, &env_page))
709                          goto out;                          goto out;
710                  pos += PAGE_SIZE - offset;                  pos += PAGE_SIZE - offset;
711                  /* Read. */                  /* Read. */
712                  while (argv_count && offset < PAGE_SIZE) {                  while (argv_count && offset < PAGE_SIZE) {
713                          const char *kaddr = ee->dump.data;                          if (!env_page.data[offset++])
                         if (!kaddr[offset++])  
714                                  argv_count--;                                  argv_count--;
715                  }                  }
716                  if (argv_count) {                  if (argv_count) {
# Line 716  static int ccs_environ(struct ccs_execve Line 718  static int ccs_environ(struct ccs_execve
718                          continue;                          continue;
719                  }                  }
720                  while (offset < PAGE_SIZE) {                  while (offset < PAGE_SIZE) {
721                          const char *kaddr = ee->dump.data;                          const unsigned char c = env_page.data[offset++];
                         const unsigned char c = kaddr[offset++];  
722                          if (c && arg_len < CCS_EXEC_TMPSIZE - 10) {                          if (c && arg_len < CCS_EXEC_TMPSIZE - 10) {
723                                  if (c == '=') {                                  if (c == '=') {
724                                          arg_ptr[arg_len++] = '\0';                                          arg_ptr[arg_len++] = '\0';
# Line 753  static int ccs_environ(struct ccs_execve Line 754  static int ccs_environ(struct ccs_execve
754   out:   out:
755          if (r->mode != 3)          if (r->mode != 3)
756                  error = 0;                  error = 0;
757            kfree(env_page.data);
758            kfree(arg_ptr);
759          return error;          return error;
760  }  }
761    
# Line 803  static void ccs_unescape(unsigned char * Line 806  static void ccs_unescape(unsigned char *
806   *   *
807   * Returns number of directories to strip.   * Returns number of directories to strip.
808   */   */
809  static inline int ccs_root_depth(struct dentry *dentry, struct vfsmount *vfsmnt)  static int ccs_root_depth(struct dentry *dentry, struct vfsmount *vfsmnt)
810  {  {
811          int depth = 0;          int depth = 0;
812          ccs_realpath_lock();          ccs_realpath_lock();
# Line 960  static int ccs_try_alt_exec(struct ccs_e Line 963  static int ccs_try_alt_exec(struct ccs_e
963                           "pid=%d uid=%d gid=%d euid=%d egid=%d suid=%d "                           "pid=%d uid=%d gid=%d euid=%d egid=%d suid=%d "
964                           "sgid=%d fsuid=%d fsgid=%d state[0]=%u "                           "sgid=%d fsuid=%d fsgid=%d state[0]=%u "
965                           "state[1]=%u state[2]=%u",                           "state[1]=%u state[2]=%u",
966                           (pid_t) sys_getpid(), current_uid(), current_gid(),                           (pid_t) ccsecurity_exports.sys_getpid(),
967                           current_euid(), current_egid(), current_suid(),                           current_uid(), current_gid(), current_euid(),
968                           current_sgid(), current_fsuid(), current_fsgid(),                           current_egid(), current_suid(), current_sgid(),
969                             current_fsuid(), current_fsgid(),
970                           (u8) (ccs_flags >> 24), (u8) (ccs_flags >> 16),                           (u8) (ccs_flags >> 24), (u8) (ccs_flags >> 16),
971                           (u8) (ccs_flags >> 8));                           (u8) (ccs_flags >> 8));
972                  retval = copy_strings_kernel(1, &cp, bprm);                  retval = copy_strings_kernel(1, &cp, bprm);
# Line 1002  static int ccs_try_alt_exec(struct ccs_e Line 1006  static int ccs_try_alt_exec(struct ccs_e
1006          {          {
1007                  int depth = ccs_get_root_depth();                  int depth = ccs_get_root_depth();
1008                  int len = ee->handler->total_len + 1;                  int len = ee->handler->total_len + 1;
1009                  char *cp = kmalloc(len, GFP_KERNEL);                  char *cp = kmalloc(len, CCS_GFP_FLAGS);
1010                  if (!cp) {                  if (!cp) {
1011                          retval = -ENOMEM;                          retval = -ENOMEM;
1012                          goto out;                          goto out;
# Line 1033  static int ccs_try_alt_exec(struct ccs_e Line 1037  static int ccs_try_alt_exec(struct ccs_e
1037  #endif  #endif
1038  #endif  #endif
1039    
1040          /* OK, now restart the process with execute handler program's dentry. */          /*
1041             * OK, now restart the process with execute handler program's dentry.
1042             */
1043          filp = open_exec(ee->handler_path);          filp = open_exec(ee->handler_path);
1044          if (IS_ERR(filp)) {          if (IS_ERR(filp)) {
1045                  retval = PTR_ERR(filp);                  retval = PTR_ERR(filp);
# Line 1070  static bool ccs_find_execute_handler(str Line 1076  static bool ccs_find_execute_handler(str
1076                                       const u8 type)                                       const u8 type)
1077  {  {
1078          struct task_struct *task = current;          struct task_struct *task = current;
1079          const struct ccs_domain_info *domain = ccs_current_domain();          const struct ccs_domain_info * const domain = ccs_current_domain();
1080          struct ccs_acl_info *ptr;          struct ccs_acl_info *ptr;
1081          bool found = false;          bool found = false;
1082          /*          /*
# Line 1086  static bool ccs_find_execute_handler(str Line 1092  static bool ccs_find_execute_handler(str
1092                  acl = container_of(ptr, struct ccs_execute_handler_record,                  acl = container_of(ptr, struct ccs_execute_handler_record,
1093                                     head);                                     head);
1094                  ee->handler = acl->handler;                  ee->handler = acl->handler;
1095                    ee->handler_type = type;
1096                  found = true;                  found = true;
1097                  break;                  break;
1098          }          }
# Line 1107  bool ccs_dump_page(struct linux_binprm * Line 1114  bool ccs_dump_page(struct linux_binprm *
1114          struct page *page;          struct page *page;
1115          /* dump->data is released by ccs_finish_execve(). */          /* dump->data is released by ccs_finish_execve(). */
1116          if (!dump->data) {          if (!dump->data) {
1117                  dump->data = kzalloc(PAGE_SIZE, GFP_KERNEL);                  dump->data = kzalloc(PAGE_SIZE, CCS_GFP_FLAGS);
1118                  if (!dump->data)                  if (!dump->data)
1119                          return false;                          return false;
1120          }          }
# Line 1133  bool ccs_dump_page(struct linux_binprm * Line 1140  bool ccs_dump_page(struct linux_binprm *
1140                   */                   */
1141                  char *kaddr = kmap_atomic(page, KM_USER0);                  char *kaddr = kmap_atomic(page, KM_USER0);
1142                  dump->page = page;                  dump->page = page;
1143                  memcpy(dump->data + offset, kaddr + offset, PAGE_SIZE - offset);                  memcpy(dump->data + offset, kaddr + offset,
1144                           PAGE_SIZE - offset);
1145                  kunmap_atomic(kaddr, KM_USER0);                  kunmap_atomic(kaddr, KM_USER0);
1146          }          }
1147          /* Same with put_arg_page(page) in fs/exec.c */          /* Same with put_arg_page(page) in fs/exec.c */
# Line 1155  bool ccs_dump_page(struct linux_binprm * Line 1163  bool ccs_dump_page(struct linux_binprm *
1163   *   *
1164   * Returns 0 on success, negative value otherwise.   * Returns 0 on success, negative value otherwise.
1165   */   */
1166  int ccs_start_execve(struct linux_binprm *bprm, struct ccs_execve_entry **eep)  static int ccs_start_execve(struct linux_binprm *bprm,
1167                                struct ccs_execve_entry **eep)
1168  {  {
1169          int retval;          int retval;
1170          struct task_struct *task = current;          struct task_struct *task = current;
1171          struct ccs_execve_entry *ee;          struct ccs_execve_entry *ee;
1172          *eep = NULL;          *eep = NULL;
1173          if (!ccs_policy_loaded)          ee = kzalloc(sizeof(*ee), CCS_GFP_FLAGS);
                 ccs_load_policy(bprm->filename);  
         ee = kzalloc(sizeof(*ee), GFP_KERNEL);  
1174          if (!ee)          if (!ee)
1175                  return -ENOMEM;                  return -ENOMEM;
1176          ee->tmp = kzalloc(CCS_EXEC_TMPSIZE, GFP_KERNEL);          ee->tmp = kzalloc(CCS_EXEC_TMPSIZE, CCS_GFP_FLAGS);
1177          if (!ee->tmp) {          if (!ee->tmp) {
1178                  kfree(ee);                  kfree(ee);
1179                  return -ENOMEM;                  return -ENOMEM;
# Line 1176  int ccs_start_execve(struct linux_binprm Line 1183  int ccs_start_execve(struct linux_binprm
1183          ee->previous_domain = task->ccs_domain_info;          ee->previous_domain = task->ccs_domain_info;
1184          /* Clear manager flag. */          /* Clear manager flag. */
1185          task->ccs_flags &= ~CCS_TASK_IS_POLICY_MANAGER;          task->ccs_flags &= ~CCS_TASK_IS_POLICY_MANAGER;
         /* Tell GC that I started execve(). */  
         task->ccs_flags |= CCS_TASK_IS_IN_EXECVE;  
         /*  
          * Make task->ccs_flags visible to GC before changing  
          * task->ccs_domain_info .  
          */  
         smp_mb();  
1186          *eep = ee;          *eep = ee;
1187          ccs_init_request_info(&ee->r, NULL, CCS_MAC_FILE_EXECUTE);          ccs_init_request_info(&ee->r, CCS_MAC_FILE_EXECUTE);
1188          ee->r.ee = ee;          ee->r.ee = ee;
1189          ee->bprm = bprm;          ee->bprm = bprm;
1190          ee->r.obj = &ee->obj;          ee->r.obj = &ee->obj;
1191          ee->obj.path1.dentry = bprm->file->f_dentry;          ee->obj.path1.dentry = bprm->file->f_dentry;
1192          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;  
1193          /*          /*
1194           * Proceed to the next domain in order to allow reaching via PID.           * No need to call ccs_environ() for execute handler because envp[] is
1195           * It will be reverted if execve() failed. Reverting is not good.           * moved to argv[].
          * But it is better than being unable to reach via PID in interactive  
          * enforcing mode.  
1196           */           */
1197          task->ccs_domain_info = ee->r.domain;          if (ccs_find_execute_handler(ee, CCS_TYPE_EXECUTE_HANDLER))
1198          ee->r.mode = ccs_get_mode(ee->r.domain->profile, CCS_MAC_ENVIRON);                  return ccs_try_alt_exec(ee);
1199          retval = ccs_environ(ee);          retval = ccs_find_next_domain(ee);
1200          if (retval < 0)          if (retval == -EPERM) {
1201                  goto out;                  if (ccs_find_execute_handler(ee,
1202          retval = 0;                                               CCS_TYPE_DENIED_EXECUTE_HANDLER))
1203   out:                          return ccs_try_alt_exec(ee);
1204            }
1205            if (!retval)
1206                    retval = ccs_environ(ee);
1207          return retval;          return retval;
1208  }  }
1209    
# Line 1231  int ccs_start_execve(struct linux_binprm Line 1215  int ccs_start_execve(struct linux_binprm
1215   *   *
1216   * Caller holds ccs_read_lock().   * Caller holds ccs_read_lock().
1217   */   */
1218  void ccs_finish_execve(int retval, struct ccs_execve_entry *ee)  static void ccs_finish_execve(int retval, struct ccs_execve_entry *ee)
1219  {  {
1220          struct task_struct *task = current;          struct task_struct *task = current;
1221          if (!ee)          if (!ee)
# Line 1259  void ccs_finish_execve(int retval, struc Line 1243  void ccs_finish_execve(int retval, struc
1243          kfree(ee->dump.data);          kfree(ee->dump.data);
1244          kfree(ee);          kfree(ee);
1245  }  }
1246    
1247    /**
1248     * ccs_may_transit - Check permission and do domain transition without execve().
1249     *
1250     * @domainname: Domainname to transit to.
1251     * @pathname: Pathname to check.
1252     *
1253     * Returns 0 on success, negative value otherwise.
1254     *
1255     * Caller holds ccs_read_lock().
1256     */
1257    int ccs_may_transit(const char *domainname, const char *pathname)
1258    {
1259            struct ccs_path_info name;
1260            struct ccs_request_info r;
1261            struct ccs_domain_info *domain;
1262            int error;
1263            bool domain_created = false;
1264            name.name = pathname;
1265            ccs_fill_path_info(&name);
1266            /* Check allow_transit permission. */
1267            ccs_init_request_info(&r, CCS_MAC_FILE_TRANSIT);
1268            error = ccs_path_permission(&r, CCS_TYPE_TRANSIT, &name);
1269            if (error)
1270                    return error;
1271            /* Check destination domain. */
1272            domain = ccs_find_domain(domainname);
1273            if (!domain && r.mode != CCS_CONFIG_ENFORCING &&
1274                strlen(domainname) < CCS_EXEC_TMPSIZE - 10) {
1275                    domain = ccs_find_or_assign_new_domain(domainname, r.profile);
1276                    if (domain)
1277                            domain_created = true;
1278            }
1279            if (domain) {
1280                    error = 0;
1281                    current->ccs_domain_info = domain;
1282                    if (domain_created)
1283                            ccs_audit_domain_creation_log();
1284            } else {
1285                    error = -ENOENT;
1286            }
1287            return error;
1288    }
1289    
1290    static int __ccs_search_binary_handler(struct linux_binprm *bprm,
1291                                           struct pt_regs *regs)
1292    {
1293            struct ccs_execve_entry *ee;
1294            int retval;
1295            if (!ccs_policy_loaded)
1296                    ccsecurity_exports.load_policy(bprm->filename);
1297            retval = ccs_start_execve(bprm, &ee);
1298            if (!retval)
1299                    retval = search_binary_handler(bprm, regs);
1300            ccs_finish_execve(retval, ee);
1301            return retval;
1302    }
1303    
1304    void __init ccs_domain_init(void)
1305    {
1306            ccsecurity_ops.search_binary_handler = __ccs_search_binary_handler;
1307    }

Legend:
Removed from v.3064  
changed lines
  Added in v.3691

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