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

Subversion リポジトリの参照

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

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

trunk/1.6.x/ccs-patch/fs/tomoyo_network.c revision 2344 by kumaneko, Wed Apr 1 02:23:18 2009 UTC branches/ccs-patch/fs/tomoyo_network.c revision 2570 by kumaneko, Wed May 20 07:12:32 2009 UTC
# Line 5  Line 5 
5   *   *
6   * Copyright (C) 2005-2009  NTT DATA CORPORATION   * Copyright (C) 2005-2009  NTT DATA CORPORATION
7   *   *
8   * Version: 1.6.7   2009/04/01   * Version: 1.6.8-pre   2009/05/08
9   *   *
10   * This file is applicable to both 2.4.30 and 2.6.11 and later.   * This file is applicable to both 2.4.30 and 2.6.11 and later.
11   * See README.ccs for ChangeLog.   * See README.ccs for ChangeLog.
# Line 55  static int ccs_audit_network_log(struct Line 55  static int ccs_audit_network_log(struct
55                                     "%s %s %u\n", operation, address, port);                                     "%s %s %u\n", operation, address, port);
56  }  }
57    
58    /* The list for "struct ccs_address_group_entry". */
59    LIST_HEAD(ccs_address_group_list);
60    
61  /**  /**
62   * ccs_save_ipv6_address - Keep the given IPv6 address on the RAM.   * ccs_get_address_group - Allocate memory for "struct ccs_address_group_entry".
  *  
  * @addr: Pointer to "struct in6_addr".  
63   *   *
64   * Returns pointer to "struct in6_addr" on success, NULL otherwise.   * @group_name: The name of address group.
65   *   *
66   * The RAM is shared, so NEVER try to modify or kfree() the returned address.   * Returns pointer to "struct ccs_address_group_entry" on success,
67     * NULL otherwise.
68   */   */
69  static const struct in6_addr *ccs_save_ipv6_address(const struct in6_addr *addr)  static struct ccs_address_group_entry *ccs_get_address_group(const char *
70  {                                                               group_name)
71          static const u8 ccs_block_size = 16;  {
72          struct ccs_addr_list {          struct ccs_address_group_entry *entry = NULL;
73                  /* Workaround for gcc 4.3's bug. */          struct ccs_address_group_entry *group;
74                  struct in6_addr addr[16]; /* = ccs_block_size */          const struct ccs_path_info *saved_group_name;
75                  struct list1_head list;          int error = -ENOMEM;
76                  u32 in_use_count;          if (!ccs_is_correct_path(group_name, 0, 0, 0, __func__) ||
77          };              !group_name[0])
         static LIST1_HEAD(ccs_address_list);  
         struct ccs_addr_list *ptr;  
         static DEFINE_MUTEX(lock);  
         u8 i = ccs_block_size;  
         if (!addr)  
78                  return NULL;                  return NULL;
79          mutex_lock(&lock);          saved_group_name = ccs_get_name(group_name);
80          list1_for_each_entry(ptr, &ccs_address_list, list) {          if (!saved_group_name)
81                  for (i = 0; i < ptr->in_use_count; i++) {                  return NULL;
82                          if (!memcmp(&ptr->addr[i], addr, sizeof(*addr)))          entry = kzalloc(sizeof(*entry), GFP_KERNEL);
83                                  goto ok;          /***** WRITER SECTION START *****/
84                  }          down_write(&ccs_policy_lock);
85                  if (i < ccs_block_size)          list_for_each_entry(group, &ccs_address_group_list, list) {
86                          break;                  if (saved_group_name != group->group_name)
87                            continue;
88                    atomic_inc(&group->users);
89                    error = 0;
90                    break;
91          }          }
92          if (i == ccs_block_size) {          if (error && ccs_memory_ok(entry)) {
93                  ptr = ccs_alloc_element(sizeof(*ptr));                  INIT_LIST_HEAD(&entry->address_group_member_list);
94                  if (!ptr)                  entry->group_name = saved_group_name;
95                          goto ok;                  saved_group_name = NULL;
96                  list1_add_tail_mb(&ptr->list, &ccs_address_list);                  atomic_set(&entry->users, 1);
97                  i = 0;                  list_add_tail(&entry->list, &ccs_address_group_list);
98          }                  group = entry;
99          ptr->addr[ptr->in_use_count++] = *addr;                  entry = NULL;
100   ok:                  error = 0;
101          mutex_unlock(&lock);          }
102          return ptr ? &ptr->addr[i] : NULL;          up_write(&ccs_policy_lock);
103            /***** WRITER SECTION END *****/
104            ccs_put_name(saved_group_name);
105            kfree(entry);
106            return !error ? group : NULL;
107  }  }
108    
 /* The list for "struct ccs_address_group_entry". */  
 static LIST1_HEAD(ccs_address_group_list);  
   
109  /**  /**
110   * ccs_update_address_group_entry - Update "struct ccs_address_group_entry" list.   * ccs_update_address_group_entry - Update "struct ccs_address_group_entry" list.
111   *   *
# Line 121  static int ccs_update_address_group_entr Line 123  static int ccs_update_address_group_entr
123                                            const u16 *max_address,                                            const u16 *max_address,
124                                            const bool is_delete)                                            const bool is_delete)
125  {  {
         static DEFINE_MUTEX(lock);  
         struct ccs_address_group_entry *new_group;  
126          struct ccs_address_group_entry *group;          struct ccs_address_group_entry *group;
127          struct ccs_address_group_member *new_member;          struct ccs_address_group_member *entry = NULL;
128          struct ccs_address_group_member *member;          struct ccs_address_group_member *member;
         const struct ccs_path_info *saved_group_name;  
129          const struct in6_addr *saved_min_address = NULL;          const struct in6_addr *saved_min_address = NULL;
130          const struct in6_addr *saved_max_address = NULL;          const struct in6_addr *saved_max_address = NULL;
131          int error = -ENOMEM;          int error = is_delete ? -ENOENT : -ENOMEM;
132          bool found = false;          const u32 min_ipv4_address = ntohl(*(u32 *) min_address);
133          if (!ccs_is_correct_path(group_name, 0, 0, 0, __func__) ||          const u32 max_ipv4_address = ntohl(*(u32 *) max_address);
134              !group_name[0])          group = ccs_get_address_group(group_name);
135                  return -EINVAL;          if (!group)
         saved_group_name = ccs_save_name(group_name);  
         if (!saved_group_name)  
                 return -ENOMEM;  
         if (!is_ipv6)  
                 goto not_ipv6;  
         saved_min_address  
                 = ccs_save_ipv6_address((struct in6_addr *) min_address);  
         saved_max_address  
                 = ccs_save_ipv6_address((struct in6_addr *) max_address);  
         if (!saved_min_address || !saved_max_address)  
136                  return -ENOMEM;                  return -ENOMEM;
137   not_ipv6:          if (is_ipv6) {
138          mutex_lock(&lock);                  saved_min_address
139          list1_for_each_entry(group, &ccs_address_group_list, list) {                          = ccs_get_ipv6_address((struct in6_addr *)
140                  if (saved_group_name != group->group_name)                                                 min_address);
141                    saved_max_address
142                            = ccs_get_ipv6_address((struct in6_addr *)
143                                                   max_address);
144                    if (!saved_min_address || !saved_max_address)
145                            goto out;
146            }
147            if (!is_delete)
148                    entry = kzalloc(sizeof(*entry), GFP_KERNEL);
149            /***** WRITER SECTION START *****/
150            down_write(&ccs_policy_lock);
151            list_for_each_entry(member, &group->address_group_member_list, list) {
152                    if (member->is_ipv6 != is_ipv6)
153                          continue;                          continue;
154                  list1_for_each_entry(member, &group->address_group_member_list,                  if (is_ipv6) {
155                                       list) {                          if (member->min.ipv6 != saved_min_address ||
156                          if (member->is_ipv6 != is_ipv6)                              member->max.ipv6 != saved_max_address)
157                                    continue;
158                    } else {
159                            if (member->min.ipv4 != min_ipv4_address ||
160                                member->max.ipv4 != max_ipv4_address)
161                                  continue;                                  continue;
                         if (is_ipv6) {  
                                 if (member->min.ipv6 != saved_min_address ||  
                                     member->max.ipv6 != saved_max_address)  
                                         continue;  
                         } else {  
                                 if (member->min.ipv4 != *(u32 *) min_address ||  
                                     member->max.ipv4 != *(u32 *) max_address)  
                                         continue;  
                         }  
                         member->is_deleted = is_delete;  
                         error = 0;  
                         goto out;  
162                  }                  }
163                  found = true;                  member->is_deleted = is_delete;
164                    error = 0;
165                  break;                  break;
166          }          }
167          if (is_delete) {          if (!is_delete && error && ccs_memory_ok(entry)) {
168                  error = -ENOENT;                  entry->is_ipv6 = is_ipv6;
169                  goto out;                  if (is_ipv6) {
170          }                          entry->min.ipv6 = saved_min_address;
171          if (!found) {                          saved_min_address = NULL;
172                  new_group = ccs_alloc_element(sizeof(*new_group));                          entry->max.ipv6 = saved_max_address;
173                  if (!new_group)                          saved_max_address = NULL;
174                          goto out;                  } else {
175                  INIT_LIST1_HEAD(&new_group->address_group_member_list);                          entry->min.ipv4 = min_ipv4_address;
176                  new_group->group_name = saved_group_name;                          entry->max.ipv4 = max_ipv4_address;
177                  list1_add_tail_mb(&new_group->list, &ccs_address_group_list);                  }
178                  group = new_group;                  list_add_tail(&entry->list, &group->address_group_member_list);
179          }                  entry = NULL;
180          new_member = ccs_alloc_element(sizeof(*new_member));                  atomic_inc(&group->users);
181          if (!new_member)                  error = 0;
                 goto out;  
         new_member->is_ipv6 = is_ipv6;  
         if (is_ipv6) {  
                 new_member->min.ipv6 = saved_min_address;  
                 new_member->max.ipv6 = saved_max_address;  
         } else {  
                 new_member->min.ipv4 = *(u32 *) min_address;  
                 new_member->max.ipv4 = *(u32 *) max_address;  
182          }          }
183          list1_add_tail_mb(&new_member->list, &group->address_group_member_list);          up_write(&ccs_policy_lock);
184          error = 0;          /***** WRITER SECTION END *****/
185   out:   out:
186          mutex_unlock(&lock);          ccs_put_ipv6_address(saved_min_address);
187            ccs_put_ipv6_address(saved_max_address);
188            ccs_put_address_group(group);
189          ccs_update_counter(CCS_UPDATES_COUNTER_EXCEPTION_POLICY);          ccs_update_counter(CCS_UPDATES_COUNTER_EXCEPTION_POLICY);
190          return error;          return error;
191  }  }
# Line 277  int ccs_write_address_group_policy(char Line 265  int ccs_write_address_group_policy(char
265  }  }
266    
267  /**  /**
  * ccs_find_or_assign_new_address_group - Create address group.  
  *  
  * @group_name: The name of address group.  
  *  
  * Returns pointer to "struct ccs_address_group_entry" on success,  
  * NULL otherwise.  
  */  
 static struct ccs_address_group_entry *  
 ccs_find_or_assign_new_address_group(const char *group_name)  
 {  
         u8 i;  
         struct ccs_address_group_entry *group;  
         for (i = 0; i <= 1; i++) {  
                 list1_for_each_entry(group, &ccs_address_group_list, list) {  
                         if (!strcmp(group_name, group->group_name->name))  
                                 return group;  
                 }  
                 if (!i) {  
                         const u16 dummy[2] = { 0, 0 };  
                         ccs_update_address_group_entry(group_name, false,  
                                                        dummy, dummy, false);  
                         ccs_update_address_group_entry(group_name, false,  
                                                        dummy, dummy, true);  
                 }  
         }  
         return NULL;  
 }  
   
 /**  
268   * ccs_address_matches_group - Check whether the given address matches members of the given address group.   * ccs_address_matches_group - Check whether the given address matches members of the given address group.
269   *   *
270   * @is_ipv6: True if @address is an IPv6 address.   * @is_ipv6: True if @address is an IPv6 address.
# Line 313  ccs_find_or_assign_new_address_group(con Line 272  ccs_find_or_assign_new_address_group(con
272   * @group:   Pointer to "struct ccs_address_group_entry".   * @group:   Pointer to "struct ccs_address_group_entry".
273   *   *
274   * Returns true if @address matches addresses in @group group, false otherwise.   * Returns true if @address matches addresses in @group group, false otherwise.
275     *
276     * Caller holds ccs_policy_lockfor reading.
277   */   */
278  static bool ccs_address_matches_group(const bool is_ipv6, const u32 *address,  static bool ccs_address_matches_group(const bool is_ipv6, const u32 *address,
279                                        const struct ccs_address_group_entry *                                        const struct ccs_address_group_entry *
# Line 320  static bool ccs_address_matches_group(co Line 281  static bool ccs_address_matches_group(co
281  {  {
282          struct ccs_address_group_member *member;          struct ccs_address_group_member *member;
283          const u32 ip = ntohl(*address);          const u32 ip = ntohl(*address);
284          list1_for_each_entry(member, &group->address_group_member_list, list) {          bool matched = false;
285            list_for_each_entry(member, &group->address_group_member_list, list) {
286                  if (member->is_deleted)                  if (member->is_deleted)
287                          continue;                          continue;
288                  if (member->is_ipv6) {                  if (member->is_ipv6) {
289                          if (is_ipv6 &&                          if (is_ipv6 &&
290                              memcmp(member->min.ipv6, address, 16) <= 0 &&                              memcmp(member->min.ipv6, address, 16) <= 0 &&
291                              memcmp(address, member->max.ipv6, 16) <= 0)                              memcmp(address, member->max.ipv6, 16) <= 0) {
292                                  return true;                                  matched = true;
293                                    break;
294                            }
295                  } else {                  } else {
296                          if (!is_ipv6 &&                          if (!is_ipv6 &&
297                              member->min.ipv4 <= ip && ip <= member->max.ipv4)                              member->min.ipv4 <= ip && ip <= member->max.ipv4) {
298                                  return true;                                  matched = true;
299                                    break;
300                            }
301                  }                  }
302          }          }
303          return false;          return matched;
304  }  }
305    
306  /**  /**
# Line 346  static bool ccs_address_matches_group(co Line 312  static bool ccs_address_matches_group(co
312   */   */
313  bool ccs_read_address_group_policy(struct ccs_io_buffer *head)  bool ccs_read_address_group_policy(struct ccs_io_buffer *head)
314  {  {
315          struct list1_head *gpos;          struct list_head *gpos;
316          struct list1_head *mpos;          struct list_head *mpos;
317          list1_for_each_cookie(gpos, head->read_var1, &ccs_address_group_list) {          bool done = true;
318            /***** READER SECTION START *****/
319            down_read(&ccs_policy_lock);
320            list_for_each_cookie(gpos, head->read_var1.u.list,
321                                  &ccs_address_group_list) {
322                  struct ccs_address_group_entry *group;                  struct ccs_address_group_entry *group;
323                  group = list1_entry(gpos, struct ccs_address_group_entry, list);                  group = list_entry(gpos, struct ccs_address_group_entry, list);
324                  list1_for_each_cookie(mpos, head->read_var2,                  list_for_each_cookie(mpos, head->read_var2.u.list,
325                                        &group->address_group_member_list) {                                        &group->address_group_member_list) {
326                          char buf[128];                          char buf[128];
327                          struct ccs_address_group_member *member;                          struct ccs_address_group_member *member;
328                          member = list1_entry(mpos,                          member = list_entry(mpos,
329                                               struct ccs_address_group_member,                                               struct ccs_address_group_member,
330                                               list);                                               list);
331                          if (member->is_deleted)                          if (member->is_deleted)
# Line 388  bool ccs_read_address_group_policy(struc Line 358  bool ccs_read_address_group_policy(struc
358                                                   HIPQUAD(max_address));                                                   HIPQUAD(max_address));
359                                  }                                  }
360                          }                          }
361                          if (!ccs_io_printf(head, KEYWORD_ADDRESS_GROUP                          done = ccs_io_printf(head, KEYWORD_ADDRESS_GROUP
362                                             "%s %s\n", group->group_name->name,                                               "%s %s\n", group->group_name->name,
363                                             buf))                                               buf);
364                                  goto out;                          if (!done)
365                                    break;
366                  }                  }
367                    if (!done)
368                            break;
369          }          }
370          return true;          up_read(&ccs_policy_lock);
371   out:          /***** READER SECTION END *****/
372          return false;          return done;
373  }  }
374    
375  #if !defined(NIP6)  #if !defined(NIP6)
# Line 467  const char *ccs_net2keyword(const u8 ope Line 440  const char *ccs_net2keyword(const u8 ope
440   *   *
441   * @operation:   Type of operation.   * @operation:   Type of operation.
442   * @record_type: Type of address.   * @record_type: Type of address.
443   * @group:       Pointer to "struct ccs_address_group_entry". May be NULL.   * @group:       Name of group. May be NULL.
444   * @min_address: Start of IPv4 or IPv6 address range.   * @min_address: Start of IPv4 or IPv6 address range.
445   * @max_address: End of IPv4 or IPv6 address range.   * @max_address: End of IPv4 or IPv6 address range.
446   * @min_port:    Start of port number range.   * @min_port:    Start of port number range.
# Line 479  const char *ccs_net2keyword(const u8 ope Line 452  const char *ccs_net2keyword(const u8 ope
452   * Returns 0 on success, negative value otherwise.   * Returns 0 on success, negative value otherwise.
453   */   */
454  static int ccs_update_network_entry(const u8 operation, const u8 record_type,  static int ccs_update_network_entry(const u8 operation, const u8 record_type,
455                                      const struct ccs_address_group_entry *group,                                      const char *group_name,
456                                      const u32 *min_address,                                      const u32 *min_address,
457                                      const u32 *max_address,                                      const u32 *max_address,
458                                      const u16 min_port, const u16 max_port,                                      const u16 min_port, const u16 max_port,
459                                      struct ccs_domain_info *domain,                                      struct ccs_domain_info *domain,
460                                      const struct ccs_condition_list *condition,                                      struct ccs_condition_list *condition,
461                                      const bool is_delete)                                      const bool is_delete)
462  {  {
463          static DEFINE_MUTEX(lock);          struct ccs_ip_network_acl_record *entry = NULL;
464          struct ccs_acl_info *ptr;          struct ccs_acl_info *ptr;
465          struct ccs_ip_network_acl_record *acl;          int error = is_delete ? -ENOENT : -ENOMEM;
         int error = -ENOMEM;  
466          /* using host byte order to allow u32 comparison than memcmp().*/          /* using host byte order to allow u32 comparison than memcmp().*/
467          const u32 min_ip = ntohl(*min_address);          const u32 min_ip = ntohl(*min_address);
468          const u32 max_ip = ntohl(*max_address);          const u32 max_ip = ntohl(*max_address);
469          const struct in6_addr *saved_min_address = NULL;          const struct in6_addr *saved_min_address = NULL;
470          const struct in6_addr *saved_max_address = NULL;          const struct in6_addr *saved_max_address = NULL;
471            struct ccs_address_group_entry *group = NULL;
472          if (!domain)          if (!domain)
473                  return -EINVAL;                  return -EINVAL;
474          if (record_type != IP_RECORD_TYPE_IPv6)          if (group_name) {
475                  goto not_ipv6;                  group = ccs_get_address_group(group_name);
476          saved_min_address = ccs_save_ipv6_address((struct in6_addr *)                  if (!group)
477                                                    min_address);                          return -ENOMEM;
478          saved_max_address = ccs_save_ipv6_address((struct in6_addr *)          } else if (record_type == IP_RECORD_TYPE_IPv6) {
479                                                    max_address);                  saved_min_address = ccs_get_ipv6_address((struct in6_addr *)
480          if (!saved_min_address || !saved_max_address)                                                           min_address);
481                  return -ENOMEM;                  saved_max_address = ccs_get_ipv6_address((struct in6_addr *)
482   not_ipv6:                                                           max_address);
483          mutex_lock(&lock);                  if (!saved_min_address || !saved_max_address)
484                            goto out;
485            }
486          if (is_delete)          if (is_delete)
487                  goto delete;                  goto delete;
488          list1_for_each_entry(ptr, &domain->acl_info_list, list) {          entry = kzalloc(sizeof(*entry), GFP_KERNEL);
489            /***** WRITER SECTION START *****/
490            down_write(&ccs_policy_lock);
491            list_for_each_entry(ptr, &domain->acl_info_list, list) {
492                    struct ccs_ip_network_acl_record *acl;
493                  if (ccs_acl_type1(ptr) != TYPE_IP_NETWORK_ACL)                  if (ccs_acl_type1(ptr) != TYPE_IP_NETWORK_ACL)
494                          continue;                          continue;
495                  if (ccs_get_condition_part(ptr) != condition)                  if (ptr->cond != condition)
496                          continue;                          continue;
497                  acl = container_of(ptr, struct ccs_ip_network_acl_record, head);                  acl = container_of(ptr, struct ccs_ip_network_acl_record, head);
498                  if (acl->operation_type != operation ||                  if (acl->operation_type != operation ||
# Line 533  static int ccs_update_network_entry(cons Line 512  static int ccs_update_network_entry(cons
512                                  continue;                                  continue;
513                  }                  }
514                  error = ccs_add_domain_acl(NULL, ptr);                  error = ccs_add_domain_acl(NULL, ptr);
515                  goto out;                  break;
516          }          }
517          /* Not found. Append it to the tail. */          if (error && ccs_memory_ok(entry)) {
518          acl = ccs_alloc_acl_element(TYPE_IP_NETWORK_ACL, condition);                  entry->head.type = TYPE_IP_NETWORK_ACL;
519          if (!acl)                  entry->head.cond = condition;
520                  goto out;                  entry->operation_type = operation;
521          acl->operation_type = operation;                  entry->record_type = record_type;
522          acl->record_type = record_type;                  if (record_type == IP_RECORD_TYPE_ADDRESS_GROUP) {
523          if (record_type == IP_RECORD_TYPE_ADDRESS_GROUP) {                          entry->u.group = group;
524                  acl->u.group = group;                          group = NULL;
525          } else if (record_type == IP_RECORD_TYPE_IPv4) {                  } else if (record_type == IP_RECORD_TYPE_IPv4) {
526                  acl->u.ipv4.min = min_ip;                          entry->u.ipv4.min = min_ip;
527                  acl->u.ipv4.max = max_ip;                          entry->u.ipv4.max = max_ip;
528          } else {                  } else {
529                  acl->u.ipv6.min = saved_min_address;                          entry->u.ipv6.min = saved_min_address;
530                  acl->u.ipv6.max = saved_max_address;                          saved_min_address = NULL;
531          }                          entry->u.ipv6.max = saved_max_address;
532          acl->min_port = min_port;                          saved_max_address = NULL;
533          acl->max_port = max_port;                  }
534          error = ccs_add_domain_acl(domain, &acl->head);                  entry->min_port = min_port;
535                    entry->max_port = max_port;
536                    error = ccs_add_domain_acl(domain, &entry->head);
537                    entry = NULL;
538            }
539            up_write(&ccs_policy_lock);
540            /***** WRITER SECTION END *****/
541          goto out;          goto out;
542   delete:   delete:
543          error = -ENOENT;          /***** WRITER SECTION START *****/
544          list1_for_each_entry(ptr, &domain->acl_info_list, list) {          down_write(&ccs_policy_lock);
545            list_for_each_entry(ptr, &domain->acl_info_list, list) {
546                    struct ccs_ip_network_acl_record *acl;
547                  if (ccs_acl_type2(ptr) != TYPE_IP_NETWORK_ACL)                  if (ccs_acl_type2(ptr) != TYPE_IP_NETWORK_ACL)
548                          continue;                          continue;
549                  if (ccs_get_condition_part(ptr) != condition)                  if (ptr->cond != condition)
550                          continue;                          continue;
551                  acl = container_of(ptr, struct ccs_ip_network_acl_record, head);                  acl = container_of(ptr, struct ccs_ip_network_acl_record, head);
552                  if (acl->operation_type != operation ||                  if (acl->operation_type != operation ||
# Line 581  static int ccs_update_network_entry(cons Line 568  static int ccs_update_network_entry(cons
568                  error = ccs_del_domain_acl(ptr);                  error = ccs_del_domain_acl(ptr);
569                  break;                  break;
570          }          }
571            up_write(&ccs_policy_lock);
572            /***** WRITER SECTION END *****/
573   out:   out:
574          mutex_unlock(&lock);          ccs_put_ipv6_address(saved_min_address);
575            ccs_put_ipv6_address(saved_max_address);
576            ccs_put_address_group(group);
577            kfree(entry);
578          return error;          return error;
579  }  }
580    
# Line 606  static int ccs_check_network_entry(const Line 598  static int ccs_check_network_entry(const
598          /* using host byte order to allow u32 comparison than memcmp().*/          /* using host byte order to allow u32 comparison than memcmp().*/
599          const u32 ip = ntohl(*address);          const u32 ip = ntohl(*address);
600          bool found = false;          bool found = false;
601            int error = -EPERM;
602          char buf[64];          char buf[64];
603          if (!ccs_can_sleep())          if (!ccs_can_sleep())
604                  return 0;                  return 0;
605          ccs_init_request_info(&r, NULL, CCS_MAC_FOR_NETWORK);          ccs_init_request_info(&r, NULL, CCS_MAC_FOR_NETWORK);
606          is_enforce = (r.mode == 3);          is_enforce = (r.mode == 3);
607          if (!r.mode)          if (!r.mode) {
608                  return 0;                  error = 0;
609                    goto done;
610            }
611   retry:   retry:
612          list1_for_each_entry(ptr, &r.domain->acl_info_list, list) {          /***** READER SECTION START *****/
613            down_read(&ccs_policy_lock);
614            list_for_each_entry(ptr, &r.cookie.u.domain->acl_info_list, list) {
615                  struct ccs_ip_network_acl_record *acl;                  struct ccs_ip_network_acl_record *acl;
616                  if (ccs_acl_type2(ptr) != TYPE_IP_NETWORK_ACL)                  if (ccs_acl_type2(ptr) != TYPE_IP_NETWORK_ACL)
617                          continue;                          continue;
# Line 636  static int ccs_check_network_entry(const Line 633  static int ccs_check_network_entry(const
633                              memcmp(address, acl->u.ipv6.max, 16) > 0)                              memcmp(address, acl->u.ipv6.max, 16) > 0)
634                                  continue;                                  continue;
635                  }                  }
636                  r.cond = ccs_get_condition_part(ptr);                  r.condition_cookie.u.cond = ptr->cond;
637                  found = true;                  found = true;
638                  break;                  break;
639          }          }
640            up_read(&ccs_policy_lock);
641            /***** READER SECTION END *****/
642          memset(buf, 0, sizeof(buf));          memset(buf, 0, sizeof(buf));
643          if (is_ipv6)          if (is_ipv6)
644                  ccs_print_ipv6(buf, sizeof(buf),                  ccs_print_ipv6(buf, sizeof(buf),
# Line 647  static int ccs_check_network_entry(const Line 646  static int ccs_check_network_entry(const
646          else          else
647                  snprintf(buf, sizeof(buf) - 1, "%u.%u.%u.%u", HIPQUAD(ip));                  snprintf(buf, sizeof(buf) - 1, "%u.%u.%u.%u", HIPQUAD(ip));
648          ccs_audit_network_log(&r, keyword, buf, port, found);          ccs_audit_network_log(&r, keyword, buf, port, found);
649          if (found)          if (found) {
650                  return 0;                  error = 0;
651          if (ccs_verbose_mode(r.domain))                  goto done;
652            }
653            if (ccs_verbose_mode(r.cookie.u.domain))
654                  printk(KERN_WARNING "TOMOYO-%s: %s to %s %u denied for %s\n",                  printk(KERN_WARNING "TOMOYO-%s: %s to %s %u denied for %s\n",
655                         ccs_get_msg(is_enforce), keyword, buf, port,                         ccs_get_msg(is_enforce), keyword, buf, port,
656                         ccs_get_last_name(r.domain));                         ccs_get_last_name(r.cookie.u.domain));
657          if (is_enforce) {          if (is_enforce) {
658                  int error = ccs_check_supervisor(&r, KEYWORD_ALLOW_NETWORK                  int err = ccs_check_supervisor(&r, KEYWORD_ALLOW_NETWORK
659                                                   "%s %s %u\n", keyword, buf,                                                 "%s %s %u\n", keyword, buf,
660                                                   port);                                                 port);
661                  if (error == 1)                  if (err == 1)
662                          goto retry;                          goto retry;
663                  return error;                  error = err;
664                    goto done;
665          }          }
666          if (r.mode == 1 && ccs_domain_quota_ok(r.domain))          if (r.mode == 1 && ccs_domain_quota_ok(r.cookie.u.domain))
667                  ccs_update_network_entry(operation, is_ipv6 ?                  ccs_update_network_entry(operation, is_ipv6 ?
668                                           IP_RECORD_TYPE_IPv6 :                                           IP_RECORD_TYPE_IPv6 :
669                                           IP_RECORD_TYPE_IPv4,                                           IP_RECORD_TYPE_IPv4,
670                                           NULL, address, address, port, port,                                           NULL, address, address, port, port,
671                                           r.domain, ccs_handler_cond(), 0);                                           r.cookie.u.domain, ccs_handler_cond(),
672          return 0;                                           false);
673            error = 0;
674     done:
675            ccs_exit_request_info(&r);
676            return error;
677  }  }
678    
679  /**  /**
# Line 681  static int ccs_check_network_entry(const Line 687  static int ccs_check_network_entry(const
687   * Returns 0 on success, negative value otherwise.   * Returns 0 on success, negative value otherwise.
688   */   */
689  int ccs_write_network_policy(char *data, struct ccs_domain_info *domain,  int ccs_write_network_policy(char *data, struct ccs_domain_info *domain,
690                               const struct ccs_condition_list *condition,                               struct ccs_condition_list *condition,
691                               const bool is_delete)                               const bool is_delete)
692  {  {
693          u8 sock_type;          u8 sock_type;
# Line 689  int ccs_write_network_policy(char *data, Line 695  int ccs_write_network_policy(char *data,
695          u8 record_type;          u8 record_type;
696          u16 min_address[8];          u16 min_address[8];
697          u16 max_address[8];          u16 max_address[8];
698          struct ccs_address_group_entry *group = NULL;          const char *group_name = NULL;
699          u16 min_port;          u16 min_port;
700          u16 max_port;          u16 max_port;
701          u8 count;          u8 count;
# Line 752  int ccs_write_network_policy(char *data, Line 758  int ccs_write_network_policy(char *data,
758          default:          default:
759                  if (*cp2 != '@')                  if (*cp2 != '@')
760                          goto out;                          goto out;
761                  group = ccs_find_or_assign_new_address_group(cp2 + 1);                  group_name = cp2 + 1;
                 if (!group)  
                         return -ENOMEM;  
762                  record_type = IP_RECORD_TYPE_ADDRESS_GROUP;                  record_type = IP_RECORD_TYPE_ADDRESS_GROUP;
763                  break;                  break;
764          }          }
# Line 765  int ccs_write_network_policy(char *data, Line 769  int ccs_write_network_policy(char *data,
769                  goto out;                  goto out;
770          if (count == 1)          if (count == 1)
771                  max_port = min_port;                  max_port = min_port;
772          return ccs_update_network_entry(operation, record_type, group,          return ccs_update_network_entry(operation, record_type, group_name,
773                                          (u32 *) min_address,                                          (u32 *) min_address,
774                                          (u32 *) max_address,                                          (u32 *) max_address,
775                                          min_port, max_port, domain, condition,                                          min_port, max_port, domain, condition,
# Line 1205  static inline struct ipv6hdr *ipv6_hdr(c Line 1209  static inline struct ipv6hdr *ipv6_hdr(c
1209  #endif  #endif
1210  #endif  #endif
1211    
1212    #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 12)
1213    static void skb_kill_datagram(struct sock *sk, struct sk_buff *skb,
1214                                  unsigned int flags)
1215    {
1216            /* Clear queue. */
1217            if (flags & MSG_PEEK) {
1218                    int clear = 0;
1219                    spin_lock_irq(&sk->sk_receive_queue.lock);
1220                    if (skb == skb_peek(&sk->sk_receive_queue)) {
1221                            __skb_unlink(skb, &sk->sk_receive_queue);
1222                            clear = 1;
1223                    }
1224                    spin_unlock_irq(&sk->sk_receive_queue.lock);
1225                    if (clear)
1226                            kfree_skb(skb);
1227            }
1228            skb_free_datagram(sk, skb);
1229    }
1230    #elif LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 16)
1231    static void skb_kill_datagram(struct sock *sk, struct sk_buff *skb,
1232                                  unsigned int flags)
1233    {
1234            /* Clear queue. */
1235            if (flags & MSG_PEEK) {
1236                    int clear = 0;
1237                    spin_lock_bh(&sk->sk_receive_queue.lock);
1238                    if (skb == skb_peek(&sk->sk_receive_queue)) {
1239                            __skb_unlink(skb, &sk->sk_receive_queue);
1240                            clear = 1;
1241                    }
1242                    spin_unlock_bh(&sk->sk_receive_queue.lock);
1243                    if (clear)
1244                            kfree_skb(skb);
1245            }
1246            skb_free_datagram(sk, skb);
1247    }
1248    #endif
1249    
1250  /*  /*
1251   * Check permission for receiving a datagram via a UDP or RAW socket.   * Check permission for receiving a datagram via a UDP or RAW socket.
1252   *   *
1253   * Currently, the LSM hook for this purpose is not provided.   * Currently, the LSM hook for this purpose is not provided.
1254   */   */
1255  int ccs_socket_recv_datagram_permission(struct sock *sk, struct sk_buff *skb,  int ccs_socket_recvmsg_permission(struct sock *sk, struct sk_buff *skb,
1256                                          const unsigned int flags)                                    const unsigned int flags)
1257  {  {
1258          int error = 0;          int error = 0;
1259          const unsigned int type = sk->sk_type;          const unsigned int type = sk->sk_type;
1260          /* Nothing to do if I didn't receive a datagram. */          if (type != SOCK_DGRAM && type != SOCK_RAW)
         if (!skb)  
                 return 0;  
         /* Nothing to do if I can't sleep. */  
 #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 5, 0)  
         if (in_interrupt())  
                 return 0;  
 #else  
         if (in_atomic())  
1261                  return 0;                  return 0;
 #endif  
1262          /* Nothing to do if I am a kernel service. */          /* Nothing to do if I am a kernel service. */
1263          if (segment_eq(get_fs(), KERNEL_DS))          if (segment_eq(get_fs(), KERNEL_DS))
1264                  return 0;                  return 0;
         if (type != SOCK_DGRAM && type != SOCK_RAW)  
                 return 0;  
1265    
1266          switch (sk->sk_family) {          switch (sk->sk_family) {
1267                  struct in6_addr sin6;                  struct in6_addr sin6;
# Line 1266  int ccs_socket_recv_datagram_permission( Line 1297  int ccs_socket_recv_datagram_permission(
1297          }          }
1298          if (!error)          if (!error)
1299                  return 0;                  return 0;
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)  
         lock_sock(sk);  
 #endif  
1300          /*          /*
1301           * Remove from queue if MSG_PEEK is used so that           * Remove from queue if MSG_PEEK is used so that
1302           * the head message from unwanted source in receive queue will not           * the head message from unwanted source in receive queue will not
1303           * prevent the caller from picking up next message from wanted source           * prevent the caller from picking up next message from wanted source
1304           * when the caller is using MSG_PEEK flag for picking up.           * when the caller is using MSG_PEEK flag for picking up.
1305           */           */
         if (flags & MSG_PEEK) {  
                 unsigned long cpu_flags;  
                 /***** CRITICAL SECTION START *****/  
                 spin_lock_irqsave(&sk->sk_receive_queue.lock, cpu_flags);  
                 if (skb == skb_peek(&sk->sk_receive_queue)) {  
                         __skb_unlink(skb, &sk->sk_receive_queue);  
                         atomic_dec(&skb->users);  
                 }  
                 spin_unlock_irqrestore(&sk->sk_receive_queue.lock, cpu_flags);  
                 /***** CRITICAL SECTION END *****/  
         }  
         /* Drop reference count. */  
         skb_free_datagram(sk, skb);  
1306  #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)  #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)
1307          release_sock(sk);          if (type == SOCK_DGRAM)
1308                    lock_sock(sk);
1309    #endif
1310            skb_kill_datagram(sk, skb, flags);
1311    #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)
1312            if (type == SOCK_DGRAM)
1313                    release_sock(sk);
1314  #endif  #endif
1315          /* Hope less harmful than -EPERM. */          /* Hope less harmful than -EPERM. */
1316          return -EAGAIN;          return -ENOMEM;
1317  }  }
1318    EXPORT_SYMBOL(ccs_socket_recvmsg_permission);

Legend:
Removed from v.2344  
changed lines
  Added in v.2570

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