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

Subversion リポジトリの参照

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

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

revision 2894 by kumaneko, Tue Aug 11 08:15:11 2009 UTC revision 2932 by kumaneko, Fri Aug 21 08:26:08 2009 UTC
# Line 12  Line 12 
12    
13  #include "internal.h"  #include "internal.h"
14    
15  static atomic_t ccs_non_string_memory_size;  void ccs_warn_oom(const char *function)
16  static unsigned int ccs_quota_for_non_string;  {
17            /* Reduce error messages. */
18            static pid_t ccs_last_pid;
19            const pid_t pid = current->pid;
20            if (ccs_last_pid != pid) {
21                    printk(KERN_WARNING "ERROR: Out of memory at %s.\n",
22                           function);
23                    ccs_last_pid = pid;
24            }
25            if (!ccs_policy_loaded)
26                    panic("MAC Initialization failed.\n");
27    }
28    
29    static atomic_t ccs_policy_memory_size;
30    static unsigned int ccs_quota_for_policy;
31    
32  /**  /**
33   * ccs_memory_ok - Check memory quota.   * ccs_memory_ok - Check memory quota.
# Line 25  static unsigned int ccs_quota_for_non_st Line 39  static unsigned int ccs_quota_for_non_st
39   */   */
40  bool ccs_memory_ok(const void *ptr, const unsigned int size)  bool ccs_memory_ok(const void *ptr, const unsigned int size)
41  {  {
42          atomic_add(size, &ccs_non_string_memory_size);          size_t s = ccs_round2(size);
43          if (ptr && (!ccs_quota_for_non_string ||          atomic_add(s, &ccs_policy_memory_size);
44                      atomic_read(&ccs_non_string_memory_size)          if (ptr && (!ccs_quota_for_policy ||
45                      <= ccs_quota_for_non_string))                      atomic_read(&ccs_policy_memory_size)
46                        <= ccs_quota_for_policy))
47                  return true;                  return true;
48          atomic_sub(size, &ccs_non_string_memory_size);          atomic_sub(s, &ccs_policy_memory_size);
49          printk(KERN_WARNING "ERROR: Out of memory. (%s)\n", __func__);          ccs_warn_oom(__func__);
         if (!ccs_policy_loaded)  
                 panic("MAC Initialization failed.\n");  
50          return false;          return false;
51  }  }
52    
53  /**  /**
54   * ccs_memory_free - Free memory for elements.   * ccs_commit_ok - Check memory quota.
55   *   *
56   * @ptr:  Pointer to allocated memory.   * @ptr:    Pointer to allocated memory.
57   * @size: Size in byte.   * @data:   Data to copy from.
58   */   * @size:   Size in byte.
 void ccs_memory_free(const void *ptr, size_t size)  
 {  
         atomic_sub(size, &ccs_non_string_memory_size);  
         kfree(ptr);  
 }  
   
 /**  
  * ccs_put_path_group - Delete memory for "struct ccs_path_group".  
59   *   *
60   * @group: Pointer to "struct ccs_path_group".   * Returns true if @ptr is not NULL and quota not exceeded, false otehrwise.
61   */   */
62  void ccs_put_path_group(struct ccs_path_group *group)  bool ccs_commit_ok(void *ptr, void *data, const unsigned int size)
63  {  {
64          struct ccs_path_group_member *member;          if (ccs_memory_ok(ptr, size)) {
65          struct ccs_path_group_member *next_member;                  memmove(ptr, data, size);
66          LIST_HEAD(q);                  memset(data, 0, size);
67          bool can_delete_group = false;                  return true;
         if (!group)  
                 return;  
         mutex_lock(&ccs_policy_lock);  
         if (atomic_dec_and_test(&group->users)) {  
                 list_for_each_entry_safe(member, next_member,  
                                          &group->path_group_member_list,  
                                          list) {  
                         if (!member->is_deleted)  
                                 break;  
                         list_del(&member->list);  
                         list_add(&member->list, &q);  
                 }  
                 if (list_empty(&group->path_group_member_list)) {  
                         list_del(&group->list);  
                         can_delete_group = true;  
                 }  
         }  
         mutex_unlock(&ccs_policy_lock);  
         list_for_each_entry_safe(member, next_member, &q, list) {  
                 list_del(&member->list);  
                 ccs_put_name(member->member_name);  
                 ccs_memory_free(member, sizeof(*member));  
         }  
         if (can_delete_group) {  
                 ccs_put_name(group->group_name);  
                 ccs_memory_free(group, sizeof(*group));  
68          }          }
69            return false;
70  }  }
71    
 /**  
  * ccs_put_address_group - Delete memory for "struct ccs_address_group_entry".  
  *  
  * @group: Pointer to "struct ccs_address_group_entry".  
  */  
 void ccs_put_address_group(struct ccs_address_group_entry *group)  
 {  
         struct ccs_address_group_member *member;  
         struct ccs_address_group_member *next_member;  
         LIST_HEAD(q);  
         bool can_delete_group = false;  
         if (!group)  
                 return;  
         mutex_lock(&ccs_policy_lock);  
         if (atomic_dec_and_test(&group->users)) {  
                 list_for_each_entry_safe(member, next_member,  
                                          &group->address_group_member_list,  
                                          list) {  
                         if (!member->is_deleted)  
                                 break;  
                         list_del(&member->list);  
                         list_add(&member->list, &q);  
                 }  
                 if (list_empty(&group->address_group_member_list)) {  
                         list_del(&group->list);  
                         can_delete_group = true;  
                 }  
         }  
         mutex_unlock(&ccs_policy_lock);  
         list_for_each_entry_safe(member, next_member, &q, list) {  
                 list_del(&member->list);  
                 if (member->is_ipv6) {  
                         ccs_put_ipv6_address(member->min.ipv6);  
                         ccs_put_ipv6_address(member->max.ipv6);  
                 }  
                 ccs_memory_free(member, sizeof(*member));  
         }  
         if (can_delete_group) {  
                 ccs_put_name(group->group_name);  
                 ccs_memory_free(group, sizeof(*group));  
         }  
 }  
72    
73  /**  /**
74   * ccs_put_number_group - Delete memory for "struct ccs_number_group".   * ccs_memory_free - Free memory for elements.
75   *   *
76   * @group: Pointer to "struct ccs_number_group".   * @ptr:  Pointer to allocated memory.
77     * @size: Size in byte.
78   */   */
79  void ccs_put_number_group(struct ccs_number_group *group)  void ccs_memory_free(const void *ptr, size_t size)
80  {  {
81          struct ccs_number_group_member *member;          atomic_sub(ccs_round2(size), &ccs_policy_memory_size);
82          struct ccs_number_group_member *next_member;          kfree(ptr);
         LIST_HEAD(q);  
         bool can_delete_group = false;  
         if (!group)  
                 return;  
         mutex_lock(&ccs_policy_lock);  
         if (atomic_dec_and_test(&group->users)) {  
                 list_for_each_entry_safe(member, next_member,  
                                          &group->number_group_member_list,  
                                          list) {  
                         if (!member->is_deleted)  
                                 break;  
                         list_del(&member->list);  
                         list_add(&member->list, &q);  
                 }  
                 if (list_empty(&group->number_group_member_list)) {  
                         list_del(&group->list);  
                         can_delete_group = true;  
                 }  
         }  
         mutex_unlock(&ccs_policy_lock);  
         list_for_each_entry_safe(member, next_member, &q, list) {  
                 list_del(&member->list);  
                 ccs_memory_free(member, sizeof(*member));  
         }  
         if (can_delete_group) {  
                 ccs_put_name(group->group_name);  
                 ccs_memory_free(group, sizeof(*group));  
         }  
83  }  }
84    
85  static LIST_HEAD(ccs_address_list);  static LIST_HEAD(ccs_address_list);
# Line 253  void ccs_put_condition(struct ccs_condit Line 164  void ccs_put_condition(struct ccs_condit
164          bool can_delete = false;          bool can_delete = false;
165          if (!cond)          if (!cond)
166                  return;                  return;
167            BUG_ON(atomic_read(&cond->users) <= 0);
168          mutex_lock(&ccs_policy_lock);          mutex_lock(&ccs_policy_lock);
169          if (atomic_dec_and_test(&cond->users)) {          if (atomic_dec_and_test(&cond->users)) {
170                  list_del(&cond->list);                  list_del(&cond->list);
# Line 271  void ccs_put_condition(struct ccs_condit Line 183  void ccs_put_condition(struct ccs_condit
183          names_p = (struct ccs_name_union *) (numbers_p + numbers_count);          names_p = (struct ccs_name_union *) (numbers_p + numbers_count);
184          argv = (const struct ccs_argv_entry *) (names_p + names_count);          argv = (const struct ccs_argv_entry *) (names_p + names_count);
185          envp = (const struct ccs_envp_entry *) (argv + argc);          envp = (const struct ccs_envp_entry *) (argv + argc);
186          for (i = 0; i < cond->numbers_count; i++)          for (i = 0; i < numbers_count; i++)
187                  ccs_put_number_union(numbers_p++);                  ccs_put_number_union(numbers_p++);
188          for (i = 0; i < cond->names_count; i++)          for (i = 0; i < names_count; i++)
189                  ccs_put_name_union(names_p++);                  ccs_put_name_union(names_p++);
190          for (i = 0; i < argc; argv++, i++)          for (i = 0; i < argc; argv++, i++)
191                  ccs_put_name(argv->value);                  ccs_put_name(argv->value);
# Line 284  void ccs_put_condition(struct ccs_condit Line 196  void ccs_put_condition(struct ccs_condit
196          ccs_memory_free(cond, cond->size);          ccs_memory_free(cond, cond->size);
197  }  }
198    
 static unsigned int ccs_string_memory_size;  
 static unsigned int ccs_quota_for_string;  
   
199  #define CCS_MAX_HASH 256  #define CCS_MAX_HASH 256
200    
201  /* Structure for string data. */  /* Structure for string data. */
# Line 318  const struct ccs_path_info *ccs_get_name Line 227  const struct ccs_path_info *ccs_get_name
227          if (!name)          if (!name)
228                  return NULL;                  return NULL;
229          len = strlen(name) + 1;          len = strlen(name) + 1;
         if (len > CCS_MAX_PATHNAME_LEN) {  
                 printk(KERN_WARNING "ERROR: Name too long. (%s)\n", __func__);  
                 return NULL;  
         }  
230          hash = full_name_hash((const unsigned char *) name, len - 1);          hash = full_name_hash((const unsigned char *) name, len - 1);
         /***** EXCLUSIVE SECTION START *****/  
231          mutex_lock(&ccs_name_list_lock);          mutex_lock(&ccs_name_list_lock);
232          list_for_each_entry(ptr, &ccs_name_list[hash % CCS_MAX_HASH], list) {          list_for_each_entry(ptr, &ccs_name_list[hash % CCS_MAX_HASH], list) {
233                  if (hash != ptr->entry.hash || strcmp(name, ptr->entry.name))                  if (hash != ptr->entry.hash || strcmp(name, ptr->entry.name))
# Line 331  const struct ccs_path_info *ccs_get_name Line 235  const struct ccs_path_info *ccs_get_name
235                  atomic_inc(&ptr->users);                  atomic_inc(&ptr->users);
236                  goto out;                  goto out;
237          }          }
238          ptr = kzalloc(sizeof(*ptr) + len, GFP_KERNEL);          allocated_len = ccs_round2(sizeof(*ptr) + len);
239          allocated_len = ptr ? sizeof(*ptr) + len : 0;          ptr = kzalloc(allocated_len, GFP_KERNEL);
240          ccs_string_memory_size += allocated_len;          if (!ptr || (ccs_quota_for_policy &&
241          if (!allocated_len ||                       atomic_read(&ccs_policy_memory_size) + allocated_len
242              (ccs_quota_for_string &&                       > ccs_quota_for_policy)) {
              ccs_string_memory_size > ccs_quota_for_string)) {  
                 ccs_string_memory_size -= allocated_len;  
243                  kfree(ptr);                  kfree(ptr);
244                  ptr = NULL;                  ptr = NULL;
245                  printk(KERN_WARNING "ERROR: Out of memory. (%s)\n", __func__);                  ccs_warn_oom(__func__);
                 if (!ccs_policy_loaded)  
                         panic("MAC Initialization failed.\n");  
246                  goto out;                  goto out;
247          }          }
248            atomic_add(allocated_len, &ccs_policy_memory_size);
249          ptr->entry.name = ((char *) ptr) + sizeof(*ptr);          ptr->entry.name = ((char *) ptr) + sizeof(*ptr);
250          memmove((char *) ptr->entry.name, name, len);          memmove((char *) ptr->entry.name, name, len);
251          atomic_set(&ptr->users, 1);          atomic_set(&ptr->users, 1);
# Line 353  const struct ccs_path_info *ccs_get_name Line 254  const struct ccs_path_info *ccs_get_name
254          list_add_tail(&ptr->list, &ccs_name_list[hash % CCS_MAX_HASH]);          list_add_tail(&ptr->list, &ccs_name_list[hash % CCS_MAX_HASH]);
255   out:   out:
256          mutex_unlock(&ccs_name_list_lock);          mutex_unlock(&ccs_name_list_lock);
         /***** EXCLUSIVE SECTION END *****/  
257          return ptr ? &ptr->entry : NULL;          return ptr ? &ptr->entry : NULL;
258  }  }
259    
# Line 369  void ccs_put_name(const struct ccs_path_ Line 269  void ccs_put_name(const struct ccs_path_
269          if (!name)          if (!name)
270                  return;                  return;
271          ptr = container_of(name, struct ccs_name_entry, entry);          ptr = container_of(name, struct ccs_name_entry, entry);
         /***** EXCLUSIVE SECTION START *****/  
272          mutex_lock(&ccs_name_list_lock);          mutex_lock(&ccs_name_list_lock);
273          if (atomic_dec_and_test(&ptr->users)) {          if (atomic_dec_and_test(&ptr->users)) {
274                  list_del(&ptr->list);                  list_del(&ptr->list);
                 ccs_string_memory_size -= ptr->size;  
275                  can_delete = true;                  can_delete = true;
276          }          }
277          mutex_unlock(&ccs_name_list_lock);          mutex_unlock(&ccs_name_list_lock);
278          /***** EXCLUSIVE SECTION END *****/          if (can_delete) {
279          if (can_delete)                  atomic_sub(ptr->size, &ccs_policy_memory_size);
280                  kfree(ptr);                  kfree(ptr);
281            }
282  }  }
283    
284  struct srcu_struct ccs_ss;  struct srcu_struct ccs_ss;
# Line 392  struct srcu_struct ccs_ss; Line 291  struct srcu_struct ccs_ss;
291  static int __init ccs_realpath_init(void)  static int __init ccs_realpath_init(void)
292  {  {
293          int i;          int i;
         /* Constraint for ccs_get_name(). */  
         if (CCS_MAX_PATHNAME_LEN > PAGE_SIZE)  
                 panic("Bad size.");  
         /* Constraint for "struct ccs_execve_entry"->tmp users. */  
         if (CCS_MAX_PATHNAME_LEN > CCS_EXEC_TMPSIZE)  
                 panic("Bad size.");  
294          if (init_srcu_struct(&ccs_ss))          if (init_srcu_struct(&ccs_ss))
295                  panic("Out of memory.");                  panic("Out of memory.");
296          for (i = 0; i < CCS_MAX_HASH; i++)          for (i = 0; i < CCS_MAX_HASH; i++)
# Line 448  unsigned int ccs_quota_for_query; Line 341  unsigned int ccs_quota_for_query;
341  int ccs_read_memory_counter(struct ccs_io_buffer *head)  int ccs_read_memory_counter(struct ccs_io_buffer *head)
342  {  {
343          if (!head->read_eof) {          if (!head->read_eof) {
344                  const unsigned int string = ccs_string_memory_size;                  const unsigned int usage[3] = {
345                  const unsigned int nonstring                          atomic_read(&ccs_policy_memory_size),
346                          = atomic_read(&ccs_non_string_memory_size);                          ccs_audit_log_memory_size,
347                  const unsigned int audit_log = ccs_audit_log_memory_size;                          ccs_query_memory_size
348                  const unsigned int query = ccs_query_memory_size;                  };
349                  char buffer[64];                  const unsigned int quota[3] = {
350                  memset(buffer, 0, sizeof(buffer));                          ccs_quota_for_policy,
351                  if (ccs_quota_for_string)                          ccs_quota_for_audit_log,
352                          snprintf(buffer, sizeof(buffer) - 1,                          ccs_quota_for_query
353                                   "   (Quota: %10u)", ccs_quota_for_string);                  };
354                  else                  static const char *header[4] = {
355                          buffer[0] = '\0';                          "Policy:     ",
356                  ccs_io_printf(head, "Policy (string):         %10u%s\n",                          "Audit logs: ",
357                                string, buffer);                          "Query lists:",
358                  if (ccs_quota_for_non_string)                          "Total:      "
359                          snprintf(buffer, sizeof(buffer) - 1,                  };
360                                   "   (Quota: %10u)", ccs_quota_for_non_string);                  unsigned int total = 0;
361                  else                  int i;
362                          buffer[0] = '\0';                  for (i = 0; i < 3; i++) {
363                  ccs_io_printf(head, "Policy (non-string):     %10u%s\n",                          total += usage[i];
364                                nonstring, buffer);                          ccs_io_printf(head, "%s %10u", header[i], usage[i]);
365                  if (ccs_quota_for_audit_log)                          if (quota[i])
366                          snprintf(buffer, sizeof(buffer) - 1,                                  ccs_io_printf(head, "   (Quota: %10u)",
367                                   "   (Quota: %10u)", ccs_quota_for_audit_log);                                                quota[i]);
368                  else                          ccs_io_printf(head, "\n");
369                          buffer[0] = '\0';                  }
370                  ccs_io_printf(head, "Audit logs:              %10u%s\n",                  ccs_io_printf(head, "%s %10u\n", header[3], total);
                               audit_log, buffer);  
                 if (ccs_quota_for_query)  
                         snprintf(buffer, sizeof(buffer) - 1,  
                                  "   (Quota: %10u)", ccs_quota_for_query);  
                 else  
                         buffer[0] = '\0';  
                 ccs_io_printf(head, "Interactive enforcement: %10u%s\n",  
                               query, buffer);  
                 ccs_io_printf(head, "Total:                   %10u\n",  
                               string + nonstring + audit_log + query);  
371                  head->read_eof = true;                  head->read_eof = true;
372          }          }
373          return 0;          return 0;
# Line 501  int ccs_write_memory_quota(struct ccs_io Line 384  int ccs_write_memory_quota(struct ccs_io
384  {  {
385          char *data = head->write_buf;          char *data = head->write_buf;
386          unsigned int size;          unsigned int size;
387          if (sscanf(data, "Policy (string): %u", &size) == 1)          if (sscanf(data, "Policy: %u", &size) == 1)
388                  ccs_quota_for_string = size;                  ccs_quota_for_policy = size;
         else if (sscanf(data, "Policy (non-string): %u", &size) == 1)  
                 ccs_quota_for_non_string = size;  
389          else if (sscanf(data, "Audit logs: %u", &size) == 1)          else if (sscanf(data, "Audit logs: %u", &size) == 1)
390                  ccs_quota_for_audit_log = size;                  ccs_quota_for_audit_log = size;
391          else if (sscanf(data, "Interactive enforcement: %u", &size) == 1)          else if (sscanf(data, "Query lists: %u", &size) == 1)
392                  ccs_quota_for_query = size;                  ccs_quota_for_query = size;
393          return 0;          return 0;
394  }  }

Legend:
Removed from v.2894  
changed lines
  Added in v.2932

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