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

Subversion リポジトリの参照

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

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

revision 1084 by kumaneko, Thu Apr 3 09:54:46 2008 UTC revision 2344 by kumaneko, Wed Apr 1 02:23:18 2009 UTC
# Line 3  Line 3 
3   *   *
4   * Implementation of the Domain-Based Mandatory Access Control.   * Implementation of the Domain-Based Mandatory Access Control.
5   *   *
6   * Copyright (C) 2005-2008  NTT DATA CORPORATION   * Copyright (C) 2005-2009  NTT DATA CORPORATION
7   *   *
8   * Version: 1.6.0   2008/04/01   * Version: 1.6.7   2009/04/01
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 14  Line 14 
14    
15  #include <linux/ccs_common.h>  #include <linux/ccs_common.h>
16  #include <linux/tomoyo.h>  #include <linux/tomoyo.h>
17    #include <linux/tomoyo_socket.h>
18  #include <linux/realpath.h>  #include <linux/realpath.h>
19  #include <linux/net.h>  #include <linux/net.h>
20  #include <linux/inet.h>  #include <linux/inet.h>
21  #include <linux/in.h>  #include <linux/in.h>
22  #include <linux/in6.h>  #include <linux/in6.h>
23    #include <net/ip.h>
24    #include <net/ipv6.h>
25    #include <net/udp.h>
26    
27    /* Index numbers for Network Controls. */
28    enum ccs_network_acl_index {
29            NETWORK_ACL_UDP_BIND,
30            NETWORK_ACL_UDP_CONNECT,
31            NETWORK_ACL_TCP_BIND,
32            NETWORK_ACL_TCP_LISTEN,
33            NETWORK_ACL_TCP_CONNECT,
34            NETWORK_ACL_TCP_ACCEPT,
35            NETWORK_ACL_RAW_BIND,
36            NETWORK_ACL_RAW_CONNECT
37    };
38    
39  /**  /**
40   * audit_network_log - Audit network log.   * ccs_audit_network_log - Audit network log.
41   *   *
42   * @is_ipv6:    True if @address is an IPv6 address.   * @r:          Pointer to "struct ccs_request_info".
43   * @operation:  The name of operation.   * @operation:  The name of operation.
44   * @address:    An IPv4 or IPv6 address.   * @address:    An IPv4 or IPv6 address.
45   * @port:       Port number.   * @port:       Port number.
46   * @is_granted: True if this is a granted log.   * @is_granted: True if this is a granted log.
  * @profile:    Profile number used.  
  * @mode:       Access control mode used.  
47   *   *
48   * Returns 0 on success, negative value otherwise.   * Returns 0 on success, negative value otherwise.
49   */   */
50  static int audit_network_log(const bool is_ipv6, const char *operation,  static int ccs_audit_network_log(struct ccs_request_info *r,
51                               const char *address, const u16 port,                                   const char *operation, const char *address,
52                               const bool is_granted,                                   const u16 port, const bool is_granted)
                              const u8 profile, const u8 mode)  
53  {  {
54          char *buf;          return ccs_write_audit_log(is_granted, r, KEYWORD_ALLOW_NETWORK
55          int len = 256;                                     "%s %s %u\n", operation, address, port);
         int len2;  
         if (ccs_can_save_audit_log(is_granted) < 0)  
                 return -ENOMEM;  
         buf = ccs_init_audit_log(&len, profile, mode, NULL);  
         if (!buf)  
                 return -ENOMEM;  
         len2 = strlen(buf);  
         snprintf(buf + len2, len - len2 - 1, KEYWORD_ALLOW_NETWORK "%s %s %u\n",  
                  operation, address, port);  
         return ccs_write_audit_log(buf, is_granted);  
56  }  }
57    
58  /**  /**
59   * save_ipv6_address - Keep the given IPv6 address on the RAM.   * ccs_save_ipv6_address - Keep the given IPv6 address on the RAM.
60   *   *
61   * @addr: Pointer to "struct in6_addr".   * @addr: Pointer to "struct in6_addr".
62   *   *
# Line 61  static int audit_network_log(const bool Line 64  static int audit_network_log(const bool
64   *   *
65   * The RAM is shared, so NEVER try to modify or kfree() the returned address.   * The RAM is shared, so NEVER try to modify or kfree() the returned address.
66   */   */
67  static const struct in6_addr *save_ipv6_address(const struct in6_addr *addr)  static const struct in6_addr *ccs_save_ipv6_address(const struct in6_addr *addr)
68  {  {
69          static const u8 block_size = 16;          static const u8 ccs_block_size = 16;
70          struct addr_list {          struct ccs_addr_list {
71                  struct in6_addr addr[block_size];                  /* Workaround for gcc 4.3's bug. */
72                    struct in6_addr addr[16]; /* = ccs_block_size */
73                  struct list1_head list;                  struct list1_head list;
74                  u32 in_use_count;                  u32 in_use_count;
75          };          };
76          static LIST1_HEAD(address_list);          static LIST1_HEAD(ccs_address_list);
77          struct addr_list *ptr;          struct ccs_addr_list *ptr;
78          static DEFINE_MUTEX(lock);          static DEFINE_MUTEX(lock);
79          u8 i = block_size;          u8 i = ccs_block_size;
80          if (!addr)          if (!addr)
81                  return NULL;                  return NULL;
82          mutex_lock(&lock);          mutex_lock(&lock);
83          list1_for_each_entry(ptr, &address_list, list) {          list1_for_each_entry(ptr, &ccs_address_list, list) {
84                  for (i = 0; i < ptr->in_use_count; i++) {                  for (i = 0; i < ptr->in_use_count; i++) {
85                          if (!memcmp(&ptr->addr[i], addr, sizeof(*addr)))                          if (!memcmp(&ptr->addr[i], addr, sizeof(*addr)))
86                                  goto ok;                                  goto ok;
87                  }                  }
88                  if (i < block_size)                  if (i < ccs_block_size)
89                          break;                          break;
90          }          }
91          if (i == block_size) {          if (i == ccs_block_size) {
92                  ptr = ccs_alloc_element(sizeof(*ptr));                  ptr = ccs_alloc_element(sizeof(*ptr));
93                  if (!ptr)                  if (!ptr)
94                          goto ok;                          goto ok;
95                  list1_add_tail_mb(&ptr->list, &address_list);                  list1_add_tail_mb(&ptr->list, &ccs_address_list);
96                  i = 0;                  i = 0;
97          }          }
98          ptr->addr[ptr->in_use_count++] = *addr;          ptr->addr[ptr->in_use_count++] = *addr;
# Line 97  static const struct in6_addr *save_ipv6_ Line 101  static const struct in6_addr *save_ipv6_
101          return ptr ? &ptr->addr[i] : NULL;          return ptr ? &ptr->addr[i] : NULL;
102  }  }
103    
104  /* The list for "struct address_group_entry". */  /* The list for "struct ccs_address_group_entry". */
105  static LIST1_HEAD(address_group_list);  static LIST1_HEAD(ccs_address_group_list);
106    
107  /**  /**
108   * update_address_group_entry - Update "struct address_group_entry" list.   * ccs_update_address_group_entry - Update "struct ccs_address_group_entry" list.
109   *   *
110   * @group_name:  The name of address group.   * @group_name:  The name of address group.
111   * @is_ipv6:     True if @min_address and @max_address are IPv6 addresses.   * @is_ipv6:     True if @min_address and @max_address are IPv6 addresses.
# Line 111  static LIST1_HEAD(address_group_list); Line 115  static LIST1_HEAD(address_group_list);
115   *   *
116   * Returns 0 on success, negative value otherwise.   * Returns 0 on success, negative value otherwise.
117   */   */
118  static int update_address_group_entry(const char *group_name,  static int ccs_update_address_group_entry(const char *group_name,
119                                        const bool is_ipv6,                                            const bool is_ipv6,
120                                        const u16 *min_address,                                            const u16 *min_address,
121                                        const u16 *max_address,                                            const u16 *max_address,
122                                        const bool is_delete)                                            const bool is_delete)
123  {  {
124          static DEFINE_MUTEX(lock);          static DEFINE_MUTEX(lock);
125          struct address_group_entry *new_group;          struct ccs_address_group_entry *new_group;
126          struct address_group_entry *group;          struct ccs_address_group_entry *group;
127          struct address_group_member *new_member;          struct ccs_address_group_member *new_member;
128          struct address_group_member *member;          struct ccs_address_group_member *member;
129          const struct path_info *saved_group_name;          const struct ccs_path_info *saved_group_name;
130          const struct in6_addr *saved_min_address = NULL;          const struct in6_addr *saved_min_address = NULL;
131          const struct in6_addr *saved_max_address = NULL;          const struct in6_addr *saved_max_address = NULL;
132          int error = -ENOMEM;          int error = -ENOMEM;
# Line 136  static int update_address_group_entry(co Line 140  static int update_address_group_entry(co
140          if (!is_ipv6)          if (!is_ipv6)
141                  goto not_ipv6;                  goto not_ipv6;
142          saved_min_address          saved_min_address
143                  = save_ipv6_address((struct in6_addr *) min_address);                  = ccs_save_ipv6_address((struct in6_addr *) min_address);
144          saved_max_address          saved_max_address
145                  = save_ipv6_address((struct in6_addr *) max_address);                  = ccs_save_ipv6_address((struct in6_addr *) max_address);
146          if (!saved_min_address || !saved_max_address)          if (!saved_min_address || !saved_max_address)
147                  return -ENOMEM;                  return -ENOMEM;
148   not_ipv6:   not_ipv6:
149          mutex_lock(&lock);          mutex_lock(&lock);
150          list1_for_each_entry(group, &address_group_list, list) {          list1_for_each_entry(group, &ccs_address_group_list, list) {
151                  if (saved_group_name != group->group_name)                  if (saved_group_name != group->group_name)
152                          continue;                          continue;
153                  list1_for_each_entry(member, &group->address_group_member_list,                  list1_for_each_entry(member, &group->address_group_member_list,
# Line 176  static int update_address_group_entry(co Line 180  static int update_address_group_entry(co
180                          goto out;                          goto out;
181                  INIT_LIST1_HEAD(&new_group->address_group_member_list);                  INIT_LIST1_HEAD(&new_group->address_group_member_list);
182                  new_group->group_name = saved_group_name;                  new_group->group_name = saved_group_name;
183                  list1_add_tail_mb(&new_group->list, &address_group_list);                  list1_add_tail_mb(&new_group->list, &ccs_address_group_list);
184                  group = new_group;                  group = new_group;
185          }          }
186          new_member = ccs_alloc_element(sizeof(*new_member));          new_member = ccs_alloc_element(sizeof(*new_member));
# Line 199  static int update_address_group_entry(co Line 203  static int update_address_group_entry(co
203  }  }
204    
205  /**  /**
206   * ccs_write_address_group_policy - Write "struct address_group_entry" list.   * ccs_parse_ip_address - Parse an IP address.
207     *
208     * @address: String to parse.
209     * @min:     Pointer to store min address.
210     * @max:     Pointer to store max address.
211     *
212     * Returns 2 if @address is an IPv6, 1 if @address is an IPv4, 0 otherwise.
213     */
214    static int ccs_parse_ip_address(char *address, u16 *min, u16 *max)
215    {
216            int count = sscanf(address, "%hx:%hx:%hx:%hx:%hx:%hx:%hx:%hx"
217                               "-%hx:%hx:%hx:%hx:%hx:%hx:%hx:%hx",
218                               &min[0], &min[1], &min[2], &min[3],
219                               &min[4], &min[5], &min[6], &min[7],
220                               &max[0], &max[1], &max[2], &max[3],
221                               &max[4], &max[5], &max[6], &max[7]);
222            if (count == 8 || count == 16) {
223                    u8 i;
224                    if (count == 8)
225                            memmove(max, min, sizeof(u16) * 8);
226                    for (i = 0; i < 8; i++) {
227                            min[i] = htons(min[i]);
228                            max[i] = htons(max[i]);
229                    }
230                    return 2;
231            }
232            count = sscanf(address, "%hu.%hu.%hu.%hu-%hu.%hu.%hu.%hu",
233                           &min[0], &min[1], &min[2], &min[3],
234                           &max[0], &max[1], &max[2], &max[3]);
235            if (count == 4 || count == 8) {
236                    u32 ip = htonl((((u8) min[0]) << 24) + (((u8) min[1]) << 16)
237                                   + (((u8) min[2]) << 8) + (u8) min[3]);
238                    memmove(min, &ip, sizeof(ip));
239                    if (count == 8)
240                            ip = htonl((((u8) max[0]) << 24) + (((u8) max[1]) << 16)
241                                       + (((u8) max[2]) << 8) + (u8) max[3]);
242                    memmove(max, &ip, sizeof(ip));
243                    return 1;
244            }
245            return 0;
246    }
247    
248    /**
249     * ccs_write_address_group_policy - Write "struct ccs_address_group_entry" list.
250   *   *
251   * @data:      String to parse.   * @data:      String to parse.
252   * @is_delete: True if it is a delete request.   * @is_delete: True if it is a delete request.
# Line 208  static int update_address_group_entry(co Line 255  static int update_address_group_entry(co
255   */   */
256  int ccs_write_address_group_policy(char *data, const bool is_delete)  int ccs_write_address_group_policy(char *data, const bool is_delete)
257  {  {
         u8 count;  
258          bool is_ipv6;          bool is_ipv6;
259          u16 min_address[8];          u16 min_address[8];
260          u16 max_address[8];          u16 max_address[8];
# Line 216  int ccs_write_address_group_policy(char Line 262  int ccs_write_address_group_policy(char
262          if (!cp)          if (!cp)
263                  return -EINVAL;                  return -EINVAL;
264          *cp++ = '\0';          *cp++ = '\0';
265          count = sscanf(cp, "%hx:%hx:%hx:%hx:%hx:%hx:%hx:%hx"          switch (ccs_parse_ip_address(cp, min_address, max_address)) {
266                         "-%hx:%hx:%hx:%hx:%hx:%hx:%hx:%hx",          case 2:
                        &min_address[0], &min_address[1],  
                        &min_address[2], &min_address[3],  
                        &min_address[4], &min_address[5],  
                        &min_address[6], &min_address[7],  
                        &max_address[0], &max_address[1],  
                        &max_address[2], &max_address[3],  
                        &max_address[4], &max_address[5],  
                        &max_address[6], &max_address[7]);  
         if (count == 8 || count == 16) {  
                 u8 i;  
                 for (i = 0; i < 8; i++) {  
                         min_address[i] = htons(min_address[i]);  
                         max_address[i] = htons(max_address[i]);  
                 }  
                 if (count == 8)  
                         memmove(max_address, min_address, sizeof(min_address));  
267                  is_ipv6 = true;                  is_ipv6 = true;
268                  goto ok;                  break;
269          }          case 1:
         count = sscanf(cp, "%hu.%hu.%hu.%hu-%hu.%hu.%hu.%hu",  
                        &min_address[0], &min_address[1],  
                        &min_address[2], &min_address[3],  
                        &max_address[0], &max_address[1],  
                        &max_address[2], &max_address[3]);  
         if (count == 4 || count == 8) {  
                 u32 ip = ((((u8) min_address[0]) << 24)  
                           + (((u8) min_address[1]) << 16)  
                           + (((u8) min_address[2]) << 8)  
                           + (u8) min_address[3]);  
                 *(u32 *) min_address = ip;  
                 if (count == 8)  
                         ip = ((((u8) max_address[0]) << 24)  
                               + (((u8) max_address[1]) << 16)  
                               + (((u8) max_address[2]) << 8)  
                               + (u8) max_address[3]);  
                 *(u32 *) max_address = ip;  
270                  is_ipv6 = false;                  is_ipv6 = false;
271                  goto ok;                  break;
272            default:
273                    return -EINVAL;
274          }          }
275          return -EINVAL;          return ccs_update_address_group_entry(data, is_ipv6, min_address,
276   ok:                                                max_address, is_delete);
         return update_address_group_entry(data, is_ipv6,  
                                           min_address, max_address, is_delete);  
277  }  }
278    
279  /**  /**
280   * find_or_assign_new_address_group - Create address group.   * ccs_find_or_assign_new_address_group - Create address group.
281   *   *
282   * @group_name: The name of address group.   * @group_name: The name of address group.
283   *   *
284   * Returns pointer to "struct address_group_entry" on success, NULL otherwise.   * Returns pointer to "struct ccs_address_group_entry" on success,
285     * NULL otherwise.
286   */   */
287  static struct address_group_entry *  static struct ccs_address_group_entry *
288  find_or_assign_new_address_group(const char *group_name)  ccs_find_or_assign_new_address_group(const char *group_name)
289  {  {
290          u8 i;          u8 i;
291          struct address_group_entry *group;          struct ccs_address_group_entry *group;
292          for (i = 0; i <= 1; i++) {          for (i = 0; i <= 1; i++) {
293                  list1_for_each_entry(group, &address_group_list, list) {                  list1_for_each_entry(group, &ccs_address_group_list, list) {
294                          if (!strcmp(group_name, group->group_name->name))                          if (!strcmp(group_name, group->group_name->name))
295                                  return group;                                  return group;
296                  }                  }
297                  if (!i) {                  if (!i) {
298                          const u16 dummy[2] = { 0, 0 };                          const u16 dummy[2] = { 0, 0 };
299                          update_address_group_entry(group_name, false,                          ccs_update_address_group_entry(group_name, false,
300                                                     dummy, dummy, false);                                                         dummy, dummy, false);
301                          update_address_group_entry(group_name, false,                          ccs_update_address_group_entry(group_name, false,
302                                                     dummy, dummy, true);                                                         dummy, dummy, true);
303                  }                  }
304          }          }
305          return NULL;          return NULL;
306  }  }
307    
308  /**  /**
309   * address_matches_to_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.
310   *   *
311   * @is_ipv6: True if @address is an IPv6 address.   * @is_ipv6: True if @address is an IPv6 address.
312   * @address: An IPv4 or IPv6 address.   * @address: An IPv4 or IPv6 address.
313   * @group:   Pointer to "struct address_group_entry".   * @group:   Pointer to "struct ccs_address_group_entry".
314   *   *
315   * Returns true if @address matches addresses in @group group, false otherwise.   * Returns true if @address matches addresses in @group group, false otherwise.
316   */   */
317  static bool address_matches_to_group(const bool is_ipv6, const u32 *address,  static bool ccs_address_matches_group(const bool is_ipv6, const u32 *address,
318                                       const struct address_group_entry *group)                                        const struct ccs_address_group_entry *
319                                          group)
320  {  {
321          struct address_group_member *member;          struct ccs_address_group_member *member;
322          const u32 ip = ntohl(*address);          const u32 ip = ntohl(*address);
323          list1_for_each_entry(member, &group->address_group_member_list, list) {          list1_for_each_entry(member, &group->address_group_member_list, list) {
324                  if (member->is_deleted)                  if (member->is_deleted)
# Line 323  static bool address_matches_to_group(con Line 338  static bool address_matches_to_group(con
338  }  }
339    
340  /**  /**
341   * ccs_read_address_group_policy - Read "struct address_group_entry" list.   * ccs_read_address_group_policy - Read "struct ccs_address_group_entry" list.
342   *   *
343   * @head: Pointer to "struct ccs_io_buffer".   * @head: Pointer to "struct ccs_io_buffer".
344   *   *
# Line 333  bool ccs_read_address_group_policy(struc Line 348  bool ccs_read_address_group_policy(struc
348  {  {
349          struct list1_head *gpos;          struct list1_head *gpos;
350          struct list1_head *mpos;          struct list1_head *mpos;
351          list1_for_each_cookie(gpos, head->read_var1, &address_group_list) {          list1_for_each_cookie(gpos, head->read_var1, &ccs_address_group_list) {
352                  struct address_group_entry *group;                  struct ccs_address_group_entry *group;
353                  group = list1_entry(gpos, struct address_group_entry, list);                  group = list1_entry(gpos, struct ccs_address_group_entry, list);
354                  list1_for_each_cookie(mpos, head->read_var2,                  list1_for_each_cookie(mpos, head->read_var2,
355                                        &group->address_group_member_list) {                                        &group->address_group_member_list) {
356                          char buf[128];                          char buf[128];
357                          struct address_group_member *member;                          struct ccs_address_group_member *member;
358                          member = list1_entry(mpos, struct address_group_member,                          member = list1_entry(mpos,
359                                                 struct ccs_address_group_member,
360                                               list);                                               list);
361                          if (member->is_deleted)                          if (member->is_deleted)
362                                  continue;                                  continue;
# Line 352  bool ccs_read_address_group_policy(struc Line 368  bool ccs_read_address_group_policy(struc
368                                  ccs_print_ipv6(buf, sizeof(buf), min_address);                                  ccs_print_ipv6(buf, sizeof(buf), min_address);
369                                  if (min_address != max_address) {                                  if (min_address != max_address) {
370                                          int len;                                          int len;
371                                          char *cp = strchr(buf, '\0');                                          char *cp = buf + strlen(buf);
372                                          *cp++ = '-';                                          *cp++ = '-';
373                                          len = strlen(buf);                                          len = strlen(buf);
374                                          ccs_print_ipv6(cp, sizeof(buf) - len,                                          ccs_print_ipv6(cp, sizeof(buf) - len,
# Line 447  const char *ccs_net2keyword(const u8 ope Line 463  const char *ccs_net2keyword(const u8 ope
463  }  }
464    
465  /**  /**
466   * update_network_entry - Update "struct ip_network_acl_record" list.   * ccs_update_network_entry - Update "struct ccs_ip_network_acl_record" list.
467   *   *
468   * @operation:   Type of operation.   * @operation:   Type of operation.
469   * @record_type: Type of address.   * @record_type: Type of address.
470   * @group:       Pointer to "struct address_group_entry". May be NULL.   * @group:       Pointer to "struct ccs_address_group_entry". May be NULL.
471   * @min_address: Start of IPv4 or IPv6 address range.   * @min_address: Start of IPv4 or IPv6 address range.
472   * @max_address: End of IPv4 or IPv6 address range.   * @max_address: End of IPv4 or IPv6 address range.
473   * @min_port:    Start of port number range.   * @min_port:    Start of port number range.
474   * @max_port:    End of port number range.   * @max_port:    End of port number range.
475   * @domain:      Pointer to "struct domain_info".   * @domain:      Pointer to "struct ccs_domain_info".
476   * @condition:   Pointer to "struct condition_list". May be NULL.   * @condition:   Pointer to "struct ccs_condition_list". May be NULL.
477   * @is_delete:   True if it is a delete request.   * @is_delete:   True if it is a delete request.
478   *   *
479   * Returns 0 on success, negative value otherwise.   * Returns 0 on success, negative value otherwise.
480   */   */
481  static int update_network_entry(const u8 operation, const u8 record_type,  static int ccs_update_network_entry(const u8 operation, const u8 record_type,
482                                  const struct address_group_entry *group,                                      const struct ccs_address_group_entry *group,
483                                  const u32 *min_address, const u32 *max_address,                                      const u32 *min_address,
484                                  const u16 min_port, const u16 max_port,                                      const u32 *max_address,
485                                  struct domain_info *domain,                                      const u16 min_port, const u16 max_port,
486                                  const struct condition_list *condition,                                      struct ccs_domain_info *domain,
487                                  const bool is_delete)                                      const struct ccs_condition_list *condition,
488                                        const bool is_delete)
489  {  {
490          struct acl_info *ptr;          static DEFINE_MUTEX(lock);
491          struct ip_network_acl_record *acl;          struct ccs_acl_info *ptr;
492            struct ccs_ip_network_acl_record *acl;
493          int error = -ENOMEM;          int error = -ENOMEM;
494          /* using host byte order to allow u32 comparison than memcmp().*/          /* using host byte order to allow u32 comparison than memcmp().*/
495          const u32 min_ip = ntohl(*min_address);          const u32 min_ip = ntohl(*min_address);
# Line 482  static int update_network_entry(const u8 Line 500  static int update_network_entry(const u8
500                  return -EINVAL;                  return -EINVAL;
501          if (record_type != IP_RECORD_TYPE_IPv6)          if (record_type != IP_RECORD_TYPE_IPv6)
502                  goto not_ipv6;                  goto not_ipv6;
503          saved_min_address = save_ipv6_address((struct in6_addr *) min_address);          saved_min_address = ccs_save_ipv6_address((struct in6_addr *)
504          saved_max_address = save_ipv6_address((struct in6_addr *) max_address);                                                    min_address);
505            saved_max_address = ccs_save_ipv6_address((struct in6_addr *)
506                                                      max_address);
507          if (!saved_min_address || !saved_max_address)          if (!saved_min_address || !saved_max_address)
508                  return -ENOMEM;                  return -ENOMEM;
509   not_ipv6:   not_ipv6:
510          mutex_lock(&domain_acl_lock);          mutex_lock(&lock);
511          if (is_delete)          if (is_delete)
512                  goto delete;                  goto delete;
513          list1_for_each_entry(ptr, &domain->acl_info_list, list) {          list1_for_each_entry(ptr, &domain->acl_info_list, list) {
# Line 495  static int update_network_entry(const u8 Line 515  static int update_network_entry(const u8
515                          continue;                          continue;
516                  if (ccs_get_condition_part(ptr) != condition)                  if (ccs_get_condition_part(ptr) != condition)
517                          continue;                          continue;
518                  acl = container_of(ptr, struct ip_network_acl_record, head);                  acl = container_of(ptr, struct ccs_ip_network_acl_record, head);
519                  if (acl->operation_type != operation ||                  if (acl->operation_type != operation ||
520                      acl->record_type != record_type ||                      acl->record_type != record_type ||
521                      acl->min_port != min_port || max_port != acl->max_port)                      acl->min_port != min_port || max_port != acl->max_port)
# Line 541  static int update_network_entry(const u8 Line 561  static int update_network_entry(const u8
561                          continue;                          continue;
562                  if (ccs_get_condition_part(ptr) != condition)                  if (ccs_get_condition_part(ptr) != condition)
563                          continue;                          continue;
564                  acl = container_of(ptr, struct ip_network_acl_record, head);                  acl = container_of(ptr, struct ccs_ip_network_acl_record, head);
565                  if (acl->operation_type != operation ||                  if (acl->operation_type != operation ||
566                      acl->record_type != record_type ||                      acl->record_type != record_type ||
567                      acl->min_port != min_port || max_port != acl->max_port)                      acl->min_port != min_port || max_port != acl->max_port)
# Line 562  static int update_network_entry(const u8 Line 582  static int update_network_entry(const u8
582                  break;                  break;
583          }          }
584   out:   out:
585          mutex_unlock(&domain_acl_lock);          mutex_unlock(&lock);
586          return error;          return error;
587  }  }
588    
589  /**  /**
590   * check_network_entry - Check permission for network operation.   * ccs_check_network_entry - Check permission for network operation.
591   *   *
592   * @is_ipv6:   True if @address is an IPv6 address.   * @is_ipv6:   True if @address is an IPv6 address.
593   * @operation: Type of operation.   * @operation: Type of operation.
# Line 576  static int update_network_entry(const u8 Line 596  static int update_network_entry(const u8
596   *   *
597   * Returns 0 on success, negative value otherwise.   * Returns 0 on success, negative value otherwise.
598   */   */
599  static int check_network_entry(const bool is_ipv6, const u8 operation,  static int ccs_check_network_entry(const bool is_ipv6, const u8 operation,
600                                 const u32 *address, const u16 port)                                     const u32 *address, const u16 port)
601  {  {
602          struct domain_info * const domain = current->domain_info;          struct ccs_request_info r;
603          struct acl_info *ptr;          struct ccs_acl_info *ptr;
604          const char *keyword = ccs_net2keyword(operation);          const char *keyword = ccs_net2keyword(operation);
605          const u8 profile = current->domain_info->profile;          bool is_enforce;
         const u8 mode = ccs_check_flags(CCS_TOMOYO_MAC_FOR_NETWORK);  
         const bool is_enforce = (mode == 3);  
606          /* using host byte order to allow u32 comparison than memcmp().*/          /* using host byte order to allow u32 comparison than memcmp().*/
607          const u32 ip = ntohl(*address);          const u32 ip = ntohl(*address);
608          bool found = false;          bool found = false;
609          char buf[64];          char buf[64];
610          if (!mode)          if (!ccs_can_sleep())
611                  return 0;                  return 0;
612          list1_for_each_entry(ptr, &domain->acl_info_list, list) {          ccs_init_request_info(&r, NULL, CCS_MAC_FOR_NETWORK);
613                  struct ip_network_acl_record *acl;          is_enforce = (r.mode == 3);
614            if (!r.mode)
615                    return 0;
616     retry:
617            list1_for_each_entry(ptr, &r.domain->acl_info_list, list) {
618                    struct ccs_ip_network_acl_record *acl;
619                  if (ccs_acl_type2(ptr) != TYPE_IP_NETWORK_ACL)                  if (ccs_acl_type2(ptr) != TYPE_IP_NETWORK_ACL)
620                          continue;                          continue;
621                  acl = container_of(ptr, struct ip_network_acl_record, head);                  acl = container_of(ptr, struct ccs_ip_network_acl_record, head);
622                  if (acl->operation_type != operation || port < acl->min_port ||                  if (acl->operation_type != operation || port < acl->min_port ||
623                      acl->max_port < port || !ccs_check_condition(ptr, NULL))                      acl->max_port < port || !ccs_check_condition(&r, ptr))
624                          continue;                          continue;
625                  if (acl->record_type == IP_RECORD_TYPE_ADDRESS_GROUP) {                  if (acl->record_type == IP_RECORD_TYPE_ADDRESS_GROUP) {
626                          if (!address_matches_to_group(is_ipv6, address,                          if (!ccs_address_matches_group(is_ipv6, address,
627                                                        acl->u.group))                                                         acl->u.group))
628                                  continue;                                  continue;
629                  } else if (acl->record_type == IP_RECORD_TYPE_IPv4) {                  } else if (acl->record_type == IP_RECORD_TYPE_IPv4) {
630                          if (is_ipv6 ||                          if (is_ipv6 ||
# Line 613  static int check_network_entry(const boo Line 636  static int check_network_entry(const boo
636                              memcmp(address, acl->u.ipv6.max, 16) > 0)                              memcmp(address, acl->u.ipv6.max, 16) > 0)
637                                  continue;                                  continue;
638                  }                  }
639                  ccs_update_condition(ptr);                  r.cond = ccs_get_condition_part(ptr);
640                  found = true;                  found = true;
641                  break;                  break;
642          }          }
# Line 623  static int check_network_entry(const boo Line 646  static int check_network_entry(const boo
646                                 (const struct in6_addr *) address);                                 (const struct in6_addr *) address);
647          else          else
648                  snprintf(buf, sizeof(buf) - 1, "%u.%u.%u.%u", HIPQUAD(ip));                  snprintf(buf, sizeof(buf) - 1, "%u.%u.%u.%u", HIPQUAD(ip));
649          audit_network_log(is_ipv6, keyword, buf, port, found, profile, mode);          ccs_audit_network_log(&r, keyword, buf, port, found);
650          if (found)          if (found)
651                  return 0;                  return 0;
652          if (ccs_verbose_mode())          if (ccs_verbose_mode(r.domain))
653                  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",
654                         ccs_get_msg(is_enforce), keyword, buf, port,                         ccs_get_msg(is_enforce), keyword, buf, port,
655                         ccs_get_last_name(domain));                         ccs_get_last_name(r.domain));
656          if (is_enforce)          if (is_enforce) {
657                  return ccs_check_supervisor("%s\n" KEYWORD_ALLOW_NETWORK "%s "                  int error = ccs_check_supervisor(&r, KEYWORD_ALLOW_NETWORK
658                                              "%s %u\n", domain->domainname->name,                                                   "%s %s %u\n", keyword, buf,
659                                              keyword, buf, port);                                                   port);
660          if (mode == 1 && ccs_check_domain_quota(domain))                  if (error == 1)
661                  update_network_entry(operation, is_ipv6 ?                          goto retry;
662                                       IP_RECORD_TYPE_IPv6 : IP_RECORD_TYPE_IPv4,                  return error;
663                                       NULL, address, address, port, port, domain,          }
664                                       NULL, 0);          if (r.mode == 1 && ccs_domain_quota_ok(r.domain))
665                    ccs_update_network_entry(operation, is_ipv6 ?
666                                             IP_RECORD_TYPE_IPv6 :
667                                             IP_RECORD_TYPE_IPv4,
668                                             NULL, address, address, port, port,
669                                             r.domain, ccs_handler_cond(), 0);
670          return 0;          return 0;
671  }  }
672    
673  /**  /**
674   * ccs_write_network_policy - Write "struct ip_network_acl_record" list.   * ccs_write_network_policy - Write "struct ccs_ip_network_acl_record" list.
675   *   *
676   * @data:      String to parse.   * @data:      String to parse.
677   * @domain:    Pointer to "struct domain_info".   * @domain:    Pointer to "struct ccs_domain_info".
678   * @condition: Pointer to "struct condition_list". May be NULL.   * @condition: Pointer to "struct ccs_condition_list". May be NULL.
679   * @is_delete: True if it is a delete request.   * @is_delete: True if it is a delete request.
680   *   *
681   * Returns 0 on success, negative value otherwise.   * Returns 0 on success, negative value otherwise.
682   */   */
683  int ccs_write_network_policy(char *data, struct domain_info *domain,  int ccs_write_network_policy(char *data, struct ccs_domain_info *domain,
684                               const struct condition_list *condition,                               const struct ccs_condition_list *condition,
685                               const bool is_delete)                               const bool is_delete)
686  {  {
687          u8 sock_type;          u8 sock_type;
# Line 661  int ccs_write_network_policy(char *data, Line 689  int ccs_write_network_policy(char *data,
689          u8 record_type;          u8 record_type;
690          u16 min_address[8];          u16 min_address[8];
691          u16 max_address[8];          u16 max_address[8];
692          struct address_group_entry *group = NULL;          struct ccs_address_group_entry *group = NULL;
693          u16 min_port;          u16 min_port;
694          u16 max_port;          u16 max_port;
695          u8 count;          u8 count;
# Line 714  int ccs_write_network_policy(char *data, Line 742  int ccs_write_network_policy(char *data,
742          if (!cp1)          if (!cp1)
743                  goto out;                  goto out;
744          *cp1++ = '\0';          *cp1++ = '\0';
745          count = sscanf(cp2, "%hx:%hx:%hx:%hx:%hx:%hx:%hx:%hx"          switch (ccs_parse_ip_address(cp2, min_address, max_address)) {
746                         "-%hx:%hx:%hx:%hx:%hx:%hx:%hx:%hx",          case 2:
                        &min_address[0], &min_address[1],  
                        &min_address[2], &min_address[3],  
                        &min_address[4], &min_address[5],  
                        &min_address[6], &min_address[7],  
                        &max_address[0], &max_address[1],  
                        &max_address[2], &max_address[3],  
                        &max_address[4], &max_address[5],  
                        &max_address[6], &max_address[7]);  
         if (count == 8 || count == 16) {  
                 u8 i;  
                 for (i = 0; i < 8; i++) {  
                         min_address[i] = htons(min_address[i]);  
                         max_address[i] = htons(max_address[i]);  
                 }  
                 if (count == 8)  
                         memmove(max_address, min_address, sizeof(min_address));  
747                  record_type = IP_RECORD_TYPE_IPv6;                  record_type = IP_RECORD_TYPE_IPv6;
748                  goto ok;                  break;
749          }          case 1:
         count = sscanf(cp2, "%hu.%hu.%hu.%hu-%hu.%hu.%hu.%hu",  
                        &min_address[0], &min_address[1],  
                        &min_address[2], &min_address[3],  
                        &max_address[0], &max_address[1],  
                        &max_address[2], &max_address[3]);  
         if (count == 4 || count == 8) {  
                 u32 ip = htonl((((u8) min_address[0]) << 24)  
                                + (((u8) min_address[1]) << 16)  
                                + (((u8) min_address[2]) << 8)  
                                + (u8) min_address[3]);  
                 *(u32 *) min_address = ip;  
                 if (count == 8)  
                         ip = htonl((((u8) max_address[0]) << 24)  
                                    + (((u8) max_address[1]) << 16)  
                                    + (((u8) max_address[2]) << 8)  
                                    + (u8) max_address[3]);  
                 *(u32 *) max_address = ip;  
750                  record_type = IP_RECORD_TYPE_IPv4;                  record_type = IP_RECORD_TYPE_IPv4;
751                  goto ok;                  break;
752          }          default:
753          if (*cp2 == '@') {                  if (*cp2 != '@')
754                  group = find_or_assign_new_address_group(cp2 + 1);                          goto out;
755                    group = ccs_find_or_assign_new_address_group(cp2 + 1);
756                  if (!group)                  if (!group)
757                          return -ENOMEM;                          return -ENOMEM;
758                  record_type = IP_RECORD_TYPE_ADDRESS_GROUP;                  record_type = IP_RECORD_TYPE_ADDRESS_GROUP;
759                  goto ok;                  break;
760          }          }
  out:  
         return -EINVAL;  
  ok:  
761          if (strchr(cp1, ' '))          if (strchr(cp1, ' '))
762                  goto out;                  goto out;
763          count = sscanf(cp1, "%hu-%hu", &min_port, &max_port);          count = sscanf(cp1, "%hu-%hu", &min_port, &max_port);
# Line 772  int ccs_write_network_policy(char *data, Line 765  int ccs_write_network_policy(char *data,
765                  goto out;                  goto out;
766          if (count == 1)          if (count == 1)
767                  max_port = min_port;                  max_port = min_port;
768          return update_network_entry(operation, record_type, group,          return ccs_update_network_entry(operation, record_type, group,
769                                      (u32 *) min_address, (u32 *) max_address,                                          (u32 *) min_address,
770                                      min_port, max_port, domain, condition,                                          (u32 *) max_address,
771                                      is_delete);                                          min_port, max_port, domain, condition,
772                                            is_delete);
773     out:
774            return -EINVAL;
775  }  }
776    
777  /**  /**
# Line 787  int ccs_write_network_policy(char *data, Line 783  int ccs_write_network_policy(char *data,
783   *   *
784   * Returns 0 on success, negative value otherwise.   * Returns 0 on success, negative value otherwise.
785   */   */
786  int ccs_check_network_listen_acl(const _Bool is_ipv6, const u8 *address,  static inline int ccs_check_network_listen_acl(const bool is_ipv6,
787                                   const u16 port)                                                 const u8 *address,
788                                                   const u16 port)
789  {  {
790          return check_network_entry(is_ipv6, NETWORK_ACL_TCP_LISTEN,          return ccs_check_network_entry(is_ipv6, NETWORK_ACL_TCP_LISTEN,
791                                     (const u32 *) address, ntohs(port));                                         (const u32 *) address, ntohs(port));
792  }  }
793    
794  /**  /**
# Line 804  int ccs_check_network_listen_acl(const _ Line 801  int ccs_check_network_listen_acl(const _
801   *   *
802   * Returns 0 on success, negative value otherwise.   * Returns 0 on success, negative value otherwise.
803   */   */
804  int ccs_check_network_connect_acl(const _Bool is_ipv6, const int sock_type,  static inline int ccs_check_network_connect_acl(const bool is_ipv6,
805                                    const u8 *address, const u16 port)                                                  const int sock_type,
806                                                    const u8 *address,
807                                                    const u16 port)
808  {  {
809          u8 operation;          u8 operation;
810          switch (sock_type) {          switch (sock_type) {
# Line 818  int ccs_check_network_connect_acl(const Line 817  int ccs_check_network_connect_acl(const
817          default:          default:
818                  operation = NETWORK_ACL_RAW_CONNECT;                  operation = NETWORK_ACL_RAW_CONNECT;
819          }          }
820          return check_network_entry(is_ipv6, operation, (const u32 *) address,          return ccs_check_network_entry(is_ipv6, operation,
821                                     ntohs(port));                                         (const u32 *) address, ntohs(port));
822  }  }
823    
824  /**  /**
# Line 832  int ccs_check_network_connect_acl(const Line 831  int ccs_check_network_connect_acl(const
831   *   *
832   * Returns 0 on success, negative value otherwise.   * Returns 0 on success, negative value otherwise.
833   */   */
834  int ccs_check_network_bind_acl(const _Bool is_ipv6, const int sock_type,  static int ccs_check_network_bind_acl(const bool is_ipv6, const int sock_type,
835                                 const u8 *address, const u16 port)                                        const u8 *address, const u16 port)
836  {  {
837          u8 operation;          u8 operation;
838          switch (sock_type) {          switch (sock_type) {
# Line 846  int ccs_check_network_bind_acl(const _Bo Line 845  int ccs_check_network_bind_acl(const _Bo
845          default:          default:
846                  operation = NETWORK_ACL_RAW_BIND;                  operation = NETWORK_ACL_RAW_BIND;
847          }          }
848          return check_network_entry(is_ipv6, operation, (const u32 *) address,          return ccs_check_network_entry(is_ipv6, operation,
849                                     ntohs(port));                                         (const u32 *) address, ntohs(port));
850  }  }
851    
852  /**  /**
# Line 859  int ccs_check_network_bind_acl(const _Bo Line 858  int ccs_check_network_bind_acl(const _Bo
858   *   *
859   * Returns 0 on success, negative value otherwise.   * Returns 0 on success, negative value otherwise.
860   */   */
861  int ccs_check_network_accept_acl(const _Bool is_ipv6, const u8 *address,  static inline int ccs_check_network_accept_acl(const bool is_ipv6,
862                                   const u16 port)                                                 const u8 *address,
863                                                   const u16 port)
864  {  {
865          int retval;          int retval;
866          current->tomoyo_flags |= CCS_DONT_SLEEP_ON_ENFORCE_ERROR;          current->ccs_flags |= CCS_DONT_SLEEP_ON_ENFORCE_ERROR;
867          retval = check_network_entry(is_ipv6, NETWORK_ACL_TCP_ACCEPT,          retval = ccs_check_network_entry(is_ipv6, NETWORK_ACL_TCP_ACCEPT,
868                                       (const u32 *) address, ntohs(port));                                           (const u32 *) address, ntohs(port));
869          current->tomoyo_flags &= ~CCS_DONT_SLEEP_ON_ENFORCE_ERROR;          current->ccs_flags &= ~CCS_DONT_SLEEP_ON_ENFORCE_ERROR;
870          return retval;          return retval;
871  }  }
872    
# Line 880  int ccs_check_network_accept_acl(const _ Line 880  int ccs_check_network_accept_acl(const _
880   *   *
881   * Returns 0 on success, negative value otherwise.   * Returns 0 on success, negative value otherwise.
882   */   */
883  int ccs_check_network_sendmsg_acl(const _Bool is_ipv6, const int sock_type,  static inline int ccs_check_network_sendmsg_acl(const bool is_ipv6,
884                                    const u8 *address, const u16 port)                                                  const int sock_type,
885                                                    const u8 *address,
886                                                    const u16 port)
887  {  {
888          u8 operation;          u8 operation;
889          if (sock_type == SOCK_DGRAM)          if (sock_type == SOCK_DGRAM)
890                  operation = NETWORK_ACL_UDP_CONNECT;                  operation = NETWORK_ACL_UDP_CONNECT;
891          else          else
892                  operation = NETWORK_ACL_RAW_CONNECT;                  operation = NETWORK_ACL_RAW_CONNECT;
893          return check_network_entry(is_ipv6, operation, (const u32 *) address,          return ccs_check_network_entry(is_ipv6, operation,
894                                     ntohs(port));                                         (const u32 *) address, ntohs(port));
895  }  }
896    
897  /**  /**
# Line 902  int ccs_check_network_sendmsg_acl(const Line 904  int ccs_check_network_sendmsg_acl(const
904   *   *
905   * Returns 0 on success, negative value otherwise.   * Returns 0 on success, negative value otherwise.
906   */   */
907  int ccs_check_network_recvmsg_acl(const _Bool is_ipv6, const int sock_type,  static inline int ccs_check_network_recvmsg_acl(const bool is_ipv6,
908                                    const u8 *address, const u16 port)                                                  const int sock_type,
909                                                    const u8 *address,
910                                                    const u16 port)
911  {  {
912          int retval;          int retval;
913          const u8 operation          const u8 operation
914                  = (sock_type == SOCK_DGRAM) ?                  = (sock_type == SOCK_DGRAM) ?
915                  NETWORK_ACL_UDP_CONNECT : NETWORK_ACL_RAW_CONNECT;                  NETWORK_ACL_UDP_CONNECT : NETWORK_ACL_RAW_CONNECT;
916          current->tomoyo_flags |= CCS_DONT_SLEEP_ON_ENFORCE_ERROR;          current->ccs_flags |= CCS_DONT_SLEEP_ON_ENFORCE_ERROR;
917          retval = check_network_entry(is_ipv6, operation, (const u32 *) address,          retval = ccs_check_network_entry(is_ipv6, operation,
918                                       ntohs(port));                                           (const u32 *) address, ntohs(port));
919          current->tomoyo_flags &= ~CCS_DONT_SLEEP_ON_ENFORCE_ERROR;          current->ccs_flags &= ~CCS_DONT_SLEEP_ON_ENFORCE_ERROR;
920          return retval;          return retval;
921  }  }
922    
923    #define MAX_SOCK_ADDR 128 /* net/socket.c */
924    
925    /* Check permission for creating a socket. */
926    int ccs_socket_create_permission(int family, int type, int protocol)
927    {
928            int error = 0;
929            /* Nothing to do if I am a kernel service. */
930            if (segment_eq(get_fs(), KERNEL_DS))
931                    return 0;
932            if (family == PF_PACKET && !ccs_capable(CCS_USE_PACKET_SOCKET))
933                    return -EPERM;
934            if (family == PF_ROUTE && !ccs_capable(CCS_USE_ROUTE_SOCKET))
935                    return -EPERM;
936            if (family != PF_INET && family != PF_INET6)
937                    return 0;
938            switch (type) {
939            case SOCK_STREAM:
940                    if (!ccs_capable(CCS_INET_STREAM_SOCKET_CREATE))
941                            error = -EPERM;
942                    break;
943            case SOCK_DGRAM:
944                    if (!ccs_capable(CCS_USE_INET_DGRAM_SOCKET))
945                            error = -EPERM;
946                    break;
947            case SOCK_RAW:
948                    if (!ccs_capable(CCS_USE_INET_RAW_SOCKET))
949                            error = -EPERM;
950                    break;
951            }
952            return error;
953    }
954    
955    /* Check permission for listening a TCP socket. */
956    int ccs_socket_listen_permission(struct socket *sock)
957    {
958            int error = 0;
959            char addr[MAX_SOCK_ADDR];
960            int addr_len;
961            /* Nothing to do if I am a kernel service. */
962            if (segment_eq(get_fs(), KERNEL_DS))
963                    return 0;
964            if (sock->type != SOCK_STREAM)
965                    return 0;
966            switch (sock->sk->sk_family) {
967            case PF_INET:
968            case PF_INET6:
969                    break;
970            default:
971                    return 0;
972            }
973            if (!ccs_capable(CCS_INET_STREAM_SOCKET_LISTEN))
974                    return -EPERM;
975            if (sock->ops->getname(sock, (struct sockaddr *) addr, &addr_len, 0))
976                    return -EPERM;
977            switch (((struct sockaddr *) addr)->sa_family) {
978                    struct sockaddr_in6 *addr6;
979                    struct sockaddr_in *addr4;
980            case AF_INET6:
981                    addr6 = (struct sockaddr_in6 *) addr;
982                    error = ccs_check_network_listen_acl(true,
983                                                         addr6->sin6_addr.s6_addr,
984                                                         addr6->sin6_port);
985                    break;
986            case AF_INET:
987                    addr4 = (struct sockaddr_in *) addr;
988                    error = ccs_check_network_listen_acl(false,
989                                                         (u8 *) &addr4->sin_addr,
990                                                         addr4->sin_port);
991                    break;
992            }
993            return error;
994    }
995    
996    /* Check permission for setting the remote IP address/port pair of a socket. */
997    int ccs_socket_connect_permission(struct socket *sock, struct sockaddr *addr,
998                                      int addr_len)
999    {
1000            int error = 0;
1001            const unsigned int type = sock->type;
1002            /* Nothing to do if I am a kernel service. */
1003            if (segment_eq(get_fs(), KERNEL_DS))
1004                    return 0;
1005            switch (type) {
1006            case SOCK_STREAM:
1007            case SOCK_DGRAM:
1008            case SOCK_RAW:
1009                    break;
1010            default:
1011                    return 0;
1012            }
1013            switch (addr->sa_family) {
1014                    struct sockaddr_in6 *addr6;
1015                    struct sockaddr_in *addr4;
1016                    u16 port;
1017            case AF_INET6:
1018                    if (addr_len < SIN6_LEN_RFC2133)
1019                            break;
1020                    addr6 = (struct sockaddr_in6 *) addr;
1021                    if (type != SOCK_RAW)
1022                            port = addr6->sin6_port;
1023                    else
1024                            port = htons(sock->sk->sk_protocol);
1025                    error = ccs_check_network_connect_acl(true, type,
1026                                                          addr6->sin6_addr.s6_addr,
1027                                                          port);
1028                    break;
1029            case AF_INET:
1030                    if (addr_len < sizeof(struct sockaddr_in))
1031                            break;
1032                    addr4 = (struct sockaddr_in *) addr;
1033                    if (type != SOCK_RAW)
1034                            port = addr4->sin_port;
1035                    else
1036                            port = htons(sock->sk->sk_protocol);
1037                    error = ccs_check_network_connect_acl(false, type,
1038                                                          (u8 *) &addr4->sin_addr,
1039                                                          port);
1040                    break;
1041            }
1042            if (type != SOCK_STREAM)
1043                    return error;
1044            switch (sock->sk->sk_family) {
1045            case PF_INET:
1046            case PF_INET6:
1047                    if (!ccs_capable(CCS_INET_STREAM_SOCKET_CONNECT))
1048                            error = -EPERM;
1049                    break;
1050            }
1051            return error;
1052    }
1053    
1054    /* Check permission for setting the local IP address/port pair of a socket. */
1055    int ccs_socket_bind_permission(struct socket *sock, struct sockaddr *addr,
1056                                   int addr_len)
1057    {
1058            int error = 0;
1059            const unsigned int type = sock->type;
1060            /* Nothing to do if I am a kernel service. */
1061            if (segment_eq(get_fs(), KERNEL_DS))
1062                    return 0;
1063            switch (type) {
1064            case SOCK_STREAM:
1065            case SOCK_DGRAM:
1066            case SOCK_RAW:
1067                    break;
1068            default:
1069                    return 0;
1070            }
1071            switch (addr->sa_family) {
1072                    struct sockaddr_in6 *addr6;
1073                    struct sockaddr_in *addr4;
1074                    u16 port;
1075            case AF_INET6:
1076                    if (addr_len < SIN6_LEN_RFC2133)
1077                            break;
1078                    addr6 = (struct sockaddr_in6 *) addr;
1079                    if (type != SOCK_RAW)
1080                            port = addr6->sin6_port;
1081                    else
1082                            port = htons(sock->sk->sk_protocol);
1083                    error = ccs_check_network_bind_acl(true, type,
1084                                                       addr6->sin6_addr.s6_addr,
1085                                                       port);
1086                    break;
1087            case AF_INET:
1088                    if (addr_len < sizeof(struct sockaddr_in))
1089                            break;
1090                    addr4 = (struct sockaddr_in *) addr;
1091                    if (type != SOCK_RAW)
1092                            port = addr4->sin_port;
1093                    else
1094                            port = htons(sock->sk->sk_protocol);
1095                    error = ccs_check_network_bind_acl(false, type,
1096                                                       (u8 *) &addr4->sin_addr,
1097                                                       port);
1098                    break;
1099            }
1100            return error;
1101    }
1102    
1103    /*
1104     * Check permission for accepting a TCP socket.
1105     *
1106     * Currently, the LSM hook for this purpose is not provided.
1107     */
1108    int ccs_socket_accept_permission(struct socket *sock, struct sockaddr *addr)
1109    {
1110            int error = 0;
1111            int addr_len;
1112            /* Nothing to do if I am a kernel service. */
1113            if (segment_eq(get_fs(), KERNEL_DS))
1114                    return 0;
1115            switch (sock->sk->sk_family) {
1116            case PF_INET:
1117            case PF_INET6:
1118                    break;
1119            default:
1120                    return 0;
1121            }
1122            error = sock->ops->getname(sock, addr, &addr_len, 2);
1123            if (error)
1124                    return error;
1125            switch (addr->sa_family) {
1126                    struct sockaddr_in6 *addr6;
1127                    struct sockaddr_in *addr4;
1128            case AF_INET6:
1129                    addr6 = (struct sockaddr_in6 *) addr;
1130                    error = ccs_check_network_accept_acl(true,
1131                                                         addr6->sin6_addr.s6_addr,
1132                                                         addr6->sin6_port);
1133                    break;
1134            case AF_INET:
1135                    addr4 = (struct sockaddr_in *) addr;
1136                    error = ccs_check_network_accept_acl(false,
1137                                                         (u8 *) &addr4->sin_addr,
1138                                                         addr4->sin_port);
1139                    break;
1140            }
1141            return error;
1142    }
1143    
1144    /* Check permission for sending a datagram via a UDP or RAW socket. */
1145    int ccs_socket_sendmsg_permission(struct socket *sock, struct sockaddr *addr,
1146                                      int addr_len)
1147    {
1148            int error = 0;
1149            const int type = sock->type;
1150            /* Nothing to do if I am a kernel service. */
1151            if (segment_eq(get_fs(), KERNEL_DS))
1152                    return 0;
1153            if (!addr || (type != SOCK_DGRAM && type != SOCK_RAW))
1154                    return 0;
1155            switch (addr->sa_family) {
1156                    struct sockaddr_in6 *addr6;
1157                    struct sockaddr_in *addr4;
1158                    u16 port;
1159            case AF_INET6:
1160                    if (addr_len < SIN6_LEN_RFC2133)
1161                            break;
1162                    addr6 = (struct sockaddr_in6 *) addr;
1163                    if (type == SOCK_DGRAM)
1164                            port = addr6->sin6_port;
1165                    else
1166                            port = htons(sock->sk->sk_protocol);
1167                    error = ccs_check_network_sendmsg_acl(true, type,
1168                                                          addr6->sin6_addr.s6_addr,
1169                                                          port);
1170                    break;
1171            case AF_INET:
1172                    if (addr_len < sizeof(struct sockaddr_in))
1173                            break;
1174                    addr4 = (struct sockaddr_in *) addr;
1175                    if (type == SOCK_DGRAM)
1176                            port = addr4->sin_port;
1177                    else
1178                            port = htons(sock->sk->sk_protocol);
1179                    error = ccs_check_network_sendmsg_acl(false, type,
1180                                                          (u8 *) &addr4->sin_addr,
1181                                                          port);
1182                    break;
1183            }
1184            return error;
1185    }
1186    
1187    #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 22)
1188    #if !defined(RHEL_MAJOR) || RHEL_MAJOR != 5
1189    
1190    static inline struct iphdr *ip_hdr(const struct sk_buff *skb)
1191    {
1192            return skb->nh.iph;
1193    }
1194    
1195    static inline struct udphdr *udp_hdr(const struct sk_buff *skb)
1196    {
1197            return skb->h.uh;
1198    }
1199    
1200    static inline struct ipv6hdr *ipv6_hdr(const struct sk_buff *skb)
1201    {
1202            return skb->nh.ipv6h;
1203    }
1204    
1205    #endif
1206    #endif
1207    
1208    /*
1209     * Check permission for receiving a datagram via a UDP or RAW socket.
1210     *
1211     * Currently, the LSM hook for this purpose is not provided.
1212     */
1213    int ccs_socket_recv_datagram_permission(struct sock *sk, struct sk_buff *skb,
1214                                            const unsigned int flags)
1215    {
1216            int error = 0;
1217            const unsigned int type = sk->sk_type;
1218            /* Nothing to do if I didn't receive a datagram. */
1219            if (!skb)
1220                    return 0;
1221            /* Nothing to do if I can't sleep. */
1222    #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 5, 0)
1223            if (in_interrupt())
1224                    return 0;
1225    #else
1226            if (in_atomic())
1227                    return 0;
1228    #endif
1229            /* Nothing to do if I am a kernel service. */
1230            if (segment_eq(get_fs(), KERNEL_DS))
1231                    return 0;
1232            if (type != SOCK_DGRAM && type != SOCK_RAW)
1233                    return 0;
1234    
1235            switch (sk->sk_family) {
1236                    struct in6_addr sin6;
1237                    struct in_addr sin4;
1238                    u16 port;
1239            case PF_INET6:
1240                    if (type == SOCK_DGRAM) { /* UDP IPv6 */
1241                            if (skb->protocol == htons(ETH_P_IP)) {
1242                                    ipv6_addr_set(&sin6, 0, 0, htonl(0xffff),
1243                                                  ip_hdr(skb)->saddr);
1244                            } else {
1245                                    ipv6_addr_copy(&sin6, &ipv6_hdr(skb)->saddr);
1246                            }
1247                            port = udp_hdr(skb)->source;
1248                    } else { /* RAW IPv6 */
1249                            ipv6_addr_copy(&sin6, &ipv6_hdr(skb)->saddr);
1250                            port = htons(sk->sk_protocol);
1251                    }
1252                    error = ccs_check_network_recvmsg_acl(true, type,
1253                                                          (u8 *) &sin6, port);
1254                    break;
1255            case PF_INET:
1256                    if (type == SOCK_DGRAM) { /* UDP IPv4 */
1257                            sin4.s_addr = ip_hdr(skb)->saddr;
1258                            port = udp_hdr(skb)->source;
1259                    } else { /* RAW IPv4 */
1260                            sin4.s_addr = ip_hdr(skb)->saddr;
1261                            port = htons(sk->sk_protocol);
1262                    }
1263                    error = ccs_check_network_recvmsg_acl(false, type,
1264                                                          (u8 *) &sin4, port);
1265                    break;
1266            }
1267            if (!error)
1268                    return 0;
1269    #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)
1270            lock_sock(sk);
1271    #endif
1272            /*
1273             * Remove from queue if MSG_PEEK is used so that
1274             * the head message from unwanted source in receive queue will not
1275             * prevent the caller from picking up next message from wanted source
1276             * when the caller is using MSG_PEEK flag for picking up.
1277             */
1278            if (flags & MSG_PEEK) {
1279                    unsigned long cpu_flags;
1280                    /***** CRITICAL SECTION START *****/
1281                    spin_lock_irqsave(&sk->sk_receive_queue.lock, cpu_flags);
1282                    if (skb == skb_peek(&sk->sk_receive_queue)) {
1283                            __skb_unlink(skb, &sk->sk_receive_queue);
1284                            atomic_dec(&skb->users);
1285                    }
1286                    spin_unlock_irqrestore(&sk->sk_receive_queue.lock, cpu_flags);
1287                    /***** CRITICAL SECTION END *****/
1288            }
1289            /* Drop reference count. */
1290            skb_free_datagram(sk, skb);
1291    #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)
1292            release_sock(sk);
1293    #endif
1294            /* Hope less harmful than -EPERM. */
1295            return -EAGAIN;
1296    }

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

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