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

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 2519 by kumaneko, Fri May 8 05:45:21 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.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 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;
133          bool found = false;          bool found = false;
134            const u32 min_ipv4_address = ntohl(*(u32 *) min_address);
135            const u32 max_ipv4_address = ntohl(*(u32 *) max_address);
136          if (!ccs_is_correct_path(group_name, 0, 0, 0, __func__) ||          if (!ccs_is_correct_path(group_name, 0, 0, 0, __func__) ||
137              !group_name[0])              !group_name[0])
138                  return -EINVAL;                  return -EINVAL;
# Line 136  static int update_address_group_entry(co Line 142  static int update_address_group_entry(co
142          if (!is_ipv6)          if (!is_ipv6)
143                  goto not_ipv6;                  goto not_ipv6;
144          saved_min_address          saved_min_address
145                  = save_ipv6_address((struct in6_addr *) min_address);                  = ccs_save_ipv6_address((struct in6_addr *) min_address);
146          saved_max_address          saved_max_address
147                  = save_ipv6_address((struct in6_addr *) max_address);                  = ccs_save_ipv6_address((struct in6_addr *) max_address);
148          if (!saved_min_address || !saved_max_address)          if (!saved_min_address || !saved_max_address)
149                  return -ENOMEM;                  return -ENOMEM;
150   not_ipv6:   not_ipv6:
151          mutex_lock(&lock);          mutex_lock(&lock);
152          list1_for_each_entry(group, &address_group_list, list) {          list1_for_each_entry(group, &ccs_address_group_list, list) {
153                  if (saved_group_name != group->group_name)                  if (saved_group_name != group->group_name)
154                          continue;                          continue;
155                  list1_for_each_entry(member, &group->address_group_member_list,                  list1_for_each_entry(member, &group->address_group_member_list,
# Line 155  static int update_address_group_entry(co Line 161  static int update_address_group_entry(co
161                                      member->max.ipv6 != saved_max_address)                                      member->max.ipv6 != saved_max_address)
162                                          continue;                                          continue;
163                          } else {                          } else {
164                                  if (member->min.ipv4 != *(u32 *) min_address ||                                  if (member->min.ipv4 != min_ipv4_address ||
165                                      member->max.ipv4 != *(u32 *) max_address)                                      member->max.ipv4 != max_ipv4_address)
166                                          continue;                                          continue;
167                          }                          }
168                          member->is_deleted = is_delete;                          member->is_deleted = is_delete;
# Line 176  static int update_address_group_entry(co Line 182  static int update_address_group_entry(co
182                          goto out;                          goto out;
183                  INIT_LIST1_HEAD(&new_group->address_group_member_list);                  INIT_LIST1_HEAD(&new_group->address_group_member_list);
184                  new_group->group_name = saved_group_name;                  new_group->group_name = saved_group_name;
185                  list1_add_tail_mb(&new_group->list, &address_group_list);                  list1_add_tail_mb(&new_group->list, &ccs_address_group_list);
186                  group = new_group;                  group = new_group;
187          }          }
188          new_member = ccs_alloc_element(sizeof(*new_member));          new_member = ccs_alloc_element(sizeof(*new_member));
# Line 187  static int update_address_group_entry(co Line 193  static int update_address_group_entry(co
193                  new_member->min.ipv6 = saved_min_address;                  new_member->min.ipv6 = saved_min_address;
194                  new_member->max.ipv6 = saved_max_address;                  new_member->max.ipv6 = saved_max_address;
195          } else {          } else {
196                  new_member->min.ipv4 = *(u32 *) min_address;                  new_member->min.ipv4 = min_ipv4_address;
197                  new_member->max.ipv4 = *(u32 *) max_address;                  new_member->max.ipv4 = max_ipv4_address;
198          }          }
199          list1_add_tail_mb(&new_member->list, &group->address_group_member_list);          list1_add_tail_mb(&new_member->list, &group->address_group_member_list);
200          error = 0;          error = 0;
# Line 199  static int update_address_group_entry(co Line 205  static int update_address_group_entry(co
205  }  }
206    
207  /**  /**
208   * ccs_write_address_group_policy - Write "struct address_group_entry" list.   * ccs_parse_ip_address - Parse an IP address.
209     *
210     * @address: String to parse.
211     * @min:     Pointer to store min address.
212     * @max:     Pointer to store max address.
213     *
214     * Returns 2 if @address is an IPv6, 1 if @address is an IPv4, 0 otherwise.
215     */
216    static int ccs_parse_ip_address(char *address, u16 *min, u16 *max)
217    {
218            int count = sscanf(address, "%hx:%hx:%hx:%hx:%hx:%hx:%hx:%hx"
219                               "-%hx:%hx:%hx:%hx:%hx:%hx:%hx:%hx",
220                               &min[0], &min[1], &min[2], &min[3],
221                               &min[4], &min[5], &min[6], &min[7],
222                               &max[0], &max[1], &max[2], &max[3],
223                               &max[4], &max[5], &max[6], &max[7]);
224            if (count == 8 || count == 16) {
225                    u8 i;
226                    if (count == 8)
227                            memmove(max, min, sizeof(u16) * 8);
228                    for (i = 0; i < 8; i++) {
229                            min[i] = htons(min[i]);
230                            max[i] = htons(max[i]);
231                    }
232                    return 2;
233            }
234            count = sscanf(address, "%hu.%hu.%hu.%hu-%hu.%hu.%hu.%hu",
235                           &min[0], &min[1], &min[2], &min[3],
236                           &max[0], &max[1], &max[2], &max[3]);
237            if (count == 4 || count == 8) {
238                    u32 ip = htonl((((u8) min[0]) << 24) + (((u8) min[1]) << 16)
239                                   + (((u8) min[2]) << 8) + (u8) min[3]);
240                    memmove(min, &ip, sizeof(ip));
241                    if (count == 8)
242                            ip = htonl((((u8) max[0]) << 24) + (((u8) max[1]) << 16)
243                                       + (((u8) max[2]) << 8) + (u8) max[3]);
244                    memmove(max, &ip, sizeof(ip));
245                    return 1;
246            }
247            return 0;
248    }
249    
250    /**
251     * ccs_write_address_group_policy - Write "struct ccs_address_group_entry" list.
252   *   *
253   * @data:      String to parse.   * @data:      String to parse.
254   * @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 257  static int update_address_group_entry(co
257   */   */
258  int ccs_write_address_group_policy(char *data, const bool is_delete)  int ccs_write_address_group_policy(char *data, const bool is_delete)
259  {  {
         u8 count;  
260          bool is_ipv6;          bool is_ipv6;
261          u16 min_address[8];          u16 min_address[8];
262          u16 max_address[8];          u16 max_address[8];
# Line 216  int ccs_write_address_group_policy(char Line 264  int ccs_write_address_group_policy(char
264          if (!cp)          if (!cp)
265                  return -EINVAL;                  return -EINVAL;
266          *cp++ = '\0';          *cp++ = '\0';
267          count = sscanf(cp, "%hx:%hx:%hx:%hx:%hx:%hx:%hx:%hx"          switch (ccs_parse_ip_address(cp, min_address, max_address)) {
268                         "-%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));  
269                  is_ipv6 = true;                  is_ipv6 = true;
270                  goto ok;                  break;
271          }          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;  
272                  is_ipv6 = false;                  is_ipv6 = false;
273                  goto ok;                  break;
274            default:
275                    return -EINVAL;
276          }          }
277          return -EINVAL;          return ccs_update_address_group_entry(data, is_ipv6, min_address,
278   ok:                                                max_address, is_delete);
         return update_address_group_entry(data, is_ipv6,  
                                           min_address, max_address, is_delete);  
279  }  }
280    
281  /**  /**
282   * find_or_assign_new_address_group - Create address group.   * ccs_find_or_assign_new_address_group - Create address group.
283   *   *
284   * @group_name: The name of address group.   * @group_name: The name of address group.
285   *   *
286   * Returns pointer to "struct address_group_entry" on success, NULL otherwise.   * Returns pointer to "struct ccs_address_group_entry" on success,
287     * NULL otherwise.
288   */   */
289  static struct address_group_entry *  static struct ccs_address_group_entry *
290  find_or_assign_new_address_group(const char *group_name)  ccs_find_or_assign_new_address_group(const char *group_name)
291  {  {
292          u8 i;          u8 i;
293          struct address_group_entry *group;          struct ccs_address_group_entry *group;
294          for (i = 0; i <= 1; i++) {          for (i = 0; i <= 1; i++) {
295                  list1_for_each_entry(group, &address_group_list, list) {                  list1_for_each_entry(group, &ccs_address_group_list, list) {
296                          if (!strcmp(group_name, group->group_name->name))                          if (!strcmp(group_name, group->group_name->name))
297                                  return group;                                  return group;
298                  }                  }
299                  if (!i) {                  if (!i) {
300                          const u16 dummy[2] = { 0, 0 };                          const u16 dummy[2] = { 0, 0 };
301                          update_address_group_entry(group_name, false,                          ccs_update_address_group_entry(group_name, false,
302                                                     dummy, dummy, false);                                                         dummy, dummy, false);
303                          update_address_group_entry(group_name, false,                          ccs_update_address_group_entry(group_name, false,
304                                                     dummy, dummy, true);                                                         dummy, dummy, true);
305                  }                  }
306          }          }
307          return NULL;          return NULL;
308  }  }
309    
310  /**  /**
311   * 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.
312   *   *
313   * @is_ipv6: True if @address is an IPv6 address.   * @is_ipv6: True if @address is an IPv6 address.
314   * @address: An IPv4 or IPv6 address.   * @address: An IPv4 or IPv6 address.
315   * @group:   Pointer to "struct address_group_entry".   * @group:   Pointer to "struct ccs_address_group_entry".
316   *   *
317   * Returns true if @address matches addresses in @group group, false otherwise.   * Returns true if @address matches addresses in @group group, false otherwise.
318   */   */
319  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,
320                                       const struct address_group_entry *group)                                        const struct ccs_address_group_entry *
321                                          group)
322  {  {
323          struct address_group_member *member;          struct ccs_address_group_member *member;
324          const u32 ip = ntohl(*address);          const u32 ip = ntohl(*address);
325          list1_for_each_entry(member, &group->address_group_member_list, list) {          list1_for_each_entry(member, &group->address_group_member_list, list) {
326                  if (member->is_deleted)                  if (member->is_deleted)
# Line 323  static bool address_matches_to_group(con Line 340  static bool address_matches_to_group(con
340  }  }
341    
342  /**  /**
343   * ccs_read_address_group_policy - Read "struct address_group_entry" list.   * ccs_read_address_group_policy - Read "struct ccs_address_group_entry" list.
344   *   *
345   * @head: Pointer to "struct ccs_io_buffer".   * @head: Pointer to "struct ccs_io_buffer".
346   *   *
# Line 333  bool ccs_read_address_group_policy(struc Line 350  bool ccs_read_address_group_policy(struc
350  {  {
351          struct list1_head *gpos;          struct list1_head *gpos;
352          struct list1_head *mpos;          struct list1_head *mpos;
353          list1_for_each_cookie(gpos, head->read_var1, &address_group_list) {          list1_for_each_cookie(gpos, head->read_var1, &ccs_address_group_list) {
354                  struct address_group_entry *group;                  struct ccs_address_group_entry *group;
355                  group = list1_entry(gpos, struct address_group_entry, list);                  group = list1_entry(gpos, struct ccs_address_group_entry, list);
356                  list1_for_each_cookie(mpos, head->read_var2,                  list1_for_each_cookie(mpos, head->read_var2,
357                                        &group->address_group_member_list) {                                        &group->address_group_member_list) {
358                          char buf[128];                          char buf[128];
359                          struct address_group_member *member;                          struct ccs_address_group_member *member;
360                          member = list1_entry(mpos, struct address_group_member,                          member = list1_entry(mpos,
361                                                 struct ccs_address_group_member,
362                                               list);                                               list);
363                          if (member->is_deleted)                          if (member->is_deleted)
364                                  continue;                                  continue;
# Line 352  bool ccs_read_address_group_policy(struc Line 370  bool ccs_read_address_group_policy(struc
370                                  ccs_print_ipv6(buf, sizeof(buf), min_address);                                  ccs_print_ipv6(buf, sizeof(buf), min_address);
371                                  if (min_address != max_address) {                                  if (min_address != max_address) {
372                                          int len;                                          int len;
373                                          char *cp = strchr(buf, '\0');                                          char *cp = buf + strlen(buf);
374                                          *cp++ = '-';                                          *cp++ = '-';
375                                          len = strlen(buf);                                          len = strlen(buf);
376                                          ccs_print_ipv6(cp, sizeof(buf) - len,                                          ccs_print_ipv6(cp, sizeof(buf) - len,
# Line 447  const char *ccs_net2keyword(const u8 ope Line 465  const char *ccs_net2keyword(const u8 ope
465  }  }
466    
467  /**  /**
468   * update_network_entry - Update "struct ip_network_acl_record" list.   * ccs_update_network_entry - Update "struct ccs_ip_network_acl_record" list.
469   *   *
470   * @operation:   Type of operation.   * @operation:   Type of operation.
471   * @record_type: Type of address.   * @record_type: Type of address.
472   * @group:       Pointer to "struct address_group_entry". May be NULL.   * @group:       Pointer to "struct ccs_address_group_entry". May be NULL.
473   * @min_address: Start of IPv4 or IPv6 address range.   * @min_address: Start of IPv4 or IPv6 address range.
474   * @max_address: End of IPv4 or IPv6 address range.   * @max_address: End of IPv4 or IPv6 address range.
475   * @min_port:    Start of port number range.   * @min_port:    Start of port number range.
476   * @max_port:    End of port number range.   * @max_port:    End of port number range.
477   * @domain:      Pointer to "struct domain_info".   * @domain:      Pointer to "struct ccs_domain_info".
478   * @condition:   Pointer to "struct condition_list". May be NULL.   * @condition:   Pointer to "struct ccs_condition_list". May be NULL.
479   * @is_delete:   True if it is a delete request.   * @is_delete:   True if it is a delete request.
480   *   *
481   * Returns 0 on success, negative value otherwise.   * Returns 0 on success, negative value otherwise.
482   */   */
483  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,
484                                  const struct address_group_entry *group,                                      const struct ccs_address_group_entry *group,
485                                  const u32 *min_address, const u32 *max_address,                                      const u32 *min_address,
486                                  const u16 min_port, const u16 max_port,                                      const u32 *max_address,
487                                  struct domain_info *domain,                                      const u16 min_port, const u16 max_port,
488                                  const struct condition_list *condition,                                      struct ccs_domain_info *domain,
489                                  const bool is_delete)                                      const struct ccs_condition_list *condition,
490                                        const bool is_delete)
491  {  {
492          struct acl_info *ptr;          static DEFINE_MUTEX(lock);
493          struct ip_network_acl_record *acl;          struct ccs_acl_info *ptr;
494            struct ccs_ip_network_acl_record *acl;
495          int error = -ENOMEM;          int error = -ENOMEM;
496          /* using host byte order to allow u32 comparison than memcmp().*/          /* using host byte order to allow u32 comparison than memcmp().*/
497          const u32 min_ip = ntohl(*min_address);          const u32 min_ip = ntohl(*min_address);
# Line 482  static int update_network_entry(const u8 Line 502  static int update_network_entry(const u8
502                  return -EINVAL;                  return -EINVAL;
503          if (record_type != IP_RECORD_TYPE_IPv6)          if (record_type != IP_RECORD_TYPE_IPv6)
504                  goto not_ipv6;                  goto not_ipv6;
505          saved_min_address = save_ipv6_address((struct in6_addr *) min_address);          saved_min_address = ccs_save_ipv6_address((struct in6_addr *)
506          saved_max_address = save_ipv6_address((struct in6_addr *) max_address);                                                    min_address);
507            saved_max_address = ccs_save_ipv6_address((struct in6_addr *)
508                                                      max_address);
509          if (!saved_min_address || !saved_max_address)          if (!saved_min_address || !saved_max_address)
510                  return -ENOMEM;                  return -ENOMEM;
511   not_ipv6:   not_ipv6:
512          mutex_lock(&domain_acl_lock);          mutex_lock(&lock);
513          if (is_delete)          if (is_delete)
514                  goto delete;                  goto delete;
515          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 517  static int update_network_entry(const u8
517                          continue;                          continue;
518                  if (ccs_get_condition_part(ptr) != condition)                  if (ccs_get_condition_part(ptr) != condition)
519                          continue;                          continue;
520                  acl = container_of(ptr, struct ip_network_acl_record, head);                  acl = container_of(ptr, struct ccs_ip_network_acl_record, head);
521                  if (acl->operation_type != operation ||                  if (acl->operation_type != operation ||
522                      acl->record_type != record_type ||                      acl->record_type != record_type ||
523                      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 563  static int update_network_entry(const u8
563                          continue;                          continue;
564                  if (ccs_get_condition_part(ptr) != condition)                  if (ccs_get_condition_part(ptr) != condition)
565                          continue;                          continue;
566                  acl = container_of(ptr, struct ip_network_acl_record, head);                  acl = container_of(ptr, struct ccs_ip_network_acl_record, head);
567                  if (acl->operation_type != operation ||                  if (acl->operation_type != operation ||
568                      acl->record_type != record_type ||                      acl->record_type != record_type ||
569                      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 584  static int update_network_entry(const u8
584                  break;                  break;
585          }          }
586   out:   out:
587          mutex_unlock(&domain_acl_lock);          mutex_unlock(&lock);
588          return error;          return error;
589  }  }
590    
591  /**  /**
592   * check_network_entry - Check permission for network operation.   * ccs_check_network_entry - Check permission for network operation.
593   *   *
594   * @is_ipv6:   True if @address is an IPv6 address.   * @is_ipv6:   True if @address is an IPv6 address.
595   * @operation: Type of operation.   * @operation: Type of operation.
# Line 576  static int update_network_entry(const u8 Line 598  static int update_network_entry(const u8
598   *   *
599   * Returns 0 on success, negative value otherwise.   * Returns 0 on success, negative value otherwise.
600   */   */
601  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,
602                                 const u32 *address, const u16 port)                                     const u32 *address, const u16 port)
603  {  {
604          struct domain_info * const domain = current->domain_info;          struct ccs_request_info r;
605          struct acl_info *ptr;          struct ccs_acl_info *ptr;
606          const char *keyword = ccs_net2keyword(operation);          const char *keyword = ccs_net2keyword(operation);
607          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);  
608          /* using host byte order to allow u32 comparison than memcmp().*/          /* using host byte order to allow u32 comparison than memcmp().*/
609          const u32 ip = ntohl(*address);          const u32 ip = ntohl(*address);
610          bool found = false;          bool found = false;
611          char buf[64];          char buf[64];
612          if (!mode)          if (!ccs_can_sleep())
613                  return 0;                  return 0;
614          list1_for_each_entry(ptr, &domain->acl_info_list, list) {          ccs_init_request_info(&r, NULL, CCS_MAC_FOR_NETWORK);
615                  struct ip_network_acl_record *acl;          is_enforce = (r.mode == 3);
616            if (!r.mode)
617                    return 0;
618     retry:
619            list1_for_each_entry(ptr, &r.domain->acl_info_list, list) {
620                    struct ccs_ip_network_acl_record *acl;
621                  if (ccs_acl_type2(ptr) != TYPE_IP_NETWORK_ACL)                  if (ccs_acl_type2(ptr) != TYPE_IP_NETWORK_ACL)
622                          continue;                          continue;
623                  acl = container_of(ptr, struct ip_network_acl_record, head);                  acl = container_of(ptr, struct ccs_ip_network_acl_record, head);
624                  if (acl->operation_type != operation || port < acl->min_port ||                  if (acl->operation_type != operation || port < acl->min_port ||
625                      acl->max_port < port || !ccs_check_condition(ptr, NULL))                      acl->max_port < port || !ccs_check_condition(&r, ptr))
626                          continue;                          continue;
627                  if (acl->record_type == IP_RECORD_TYPE_ADDRESS_GROUP) {                  if (acl->record_type == IP_RECORD_TYPE_ADDRESS_GROUP) {
628                          if (!address_matches_to_group(is_ipv6, address,                          if (!ccs_address_matches_group(is_ipv6, address,
629                                                        acl->u.group))                                                         acl->u.group))
630                                  continue;                                  continue;
631                  } else if (acl->record_type == IP_RECORD_TYPE_IPv4) {                  } else if (acl->record_type == IP_RECORD_TYPE_IPv4) {
632                          if (is_ipv6 ||                          if (is_ipv6 ||
# Line 613  static int check_network_entry(const boo Line 638  static int check_network_entry(const boo
638                              memcmp(address, acl->u.ipv6.max, 16) > 0)                              memcmp(address, acl->u.ipv6.max, 16) > 0)
639                                  continue;                                  continue;
640                  }                  }
641                  ccs_update_condition(ptr);                  r.cond = ccs_get_condition_part(ptr);
642                  found = true;                  found = true;
643                  break;                  break;
644          }          }
# Line 623  static int check_network_entry(const boo Line 648  static int check_network_entry(const boo
648                                 (const struct in6_addr *) address);                                 (const struct in6_addr *) address);
649          else          else
650                  snprintf(buf, sizeof(buf) - 1, "%u.%u.%u.%u", HIPQUAD(ip));                  snprintf(buf, sizeof(buf) - 1, "%u.%u.%u.%u", HIPQUAD(ip));
651          audit_network_log(is_ipv6, keyword, buf, port, found, profile, mode);          ccs_audit_network_log(&r, keyword, buf, port, found);
652          if (found)          if (found)
653                  return 0;                  return 0;
654          if (ccs_verbose_mode())          if (ccs_verbose_mode(r.domain))
655                  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",
656                         ccs_get_msg(is_enforce), keyword, buf, port,                         ccs_get_msg(is_enforce), keyword, buf, port,
657                         ccs_get_last_name(domain));                         ccs_get_last_name(r.domain));
658          if (is_enforce)          if (is_enforce) {
659                  return ccs_check_supervisor("%s\n" KEYWORD_ALLOW_NETWORK "%s "                  int error = ccs_check_supervisor(&r, KEYWORD_ALLOW_NETWORK
660                                              "%s %u\n", domain->domainname->name,                                                   "%s %s %u\n", keyword, buf,
661                                              keyword, buf, port);                                                   port);
662          if (mode == 1 && ccs_check_domain_quota(domain))                  if (error == 1)
663                  update_network_entry(operation, is_ipv6 ?                          goto retry;
664                                       IP_RECORD_TYPE_IPv6 : IP_RECORD_TYPE_IPv4,                  return error;
665                                       NULL, address, address, port, port, domain,          }
666                                       NULL, 0);          if (r.mode == 1 && ccs_domain_quota_ok(r.domain))
667                    ccs_update_network_entry(operation, is_ipv6 ?
668                                             IP_RECORD_TYPE_IPv6 :
669                                             IP_RECORD_TYPE_IPv4,
670                                             NULL, address, address, port, port,
671                                             r.domain, ccs_handler_cond(), 0);
672          return 0;          return 0;
673  }  }
674    
675  /**  /**
676   * ccs_write_network_policy - Write "struct ip_network_acl_record" list.   * ccs_write_network_policy - Write "struct ccs_ip_network_acl_record" list.
677   *   *
678   * @data:      String to parse.   * @data:      String to parse.
679   * @domain:    Pointer to "struct domain_info".   * @domain:    Pointer to "struct ccs_domain_info".
680   * @condition: Pointer to "struct condition_list". May be NULL.   * @condition: Pointer to "struct ccs_condition_list". May be NULL.
681   * @is_delete: True if it is a delete request.   * @is_delete: True if it is a delete request.
682   *   *
683   * Returns 0 on success, negative value otherwise.   * Returns 0 on success, negative value otherwise.
684   */   */
685  int ccs_write_network_policy(char *data, struct domain_info *domain,  int ccs_write_network_policy(char *data, struct ccs_domain_info *domain,
686                               const struct condition_list *condition,                               const struct ccs_condition_list *condition,
687                               const bool is_delete)                               const bool is_delete)
688  {  {
689          u8 sock_type;          u8 sock_type;
# Line 661  int ccs_write_network_policy(char *data, Line 691  int ccs_write_network_policy(char *data,
691          u8 record_type;          u8 record_type;
692          u16 min_address[8];          u16 min_address[8];
693          u16 max_address[8];          u16 max_address[8];
694          struct address_group_entry *group = NULL;          struct ccs_address_group_entry *group = NULL;
695          u16 min_port;          u16 min_port;
696          u16 max_port;          u16 max_port;
697          u8 count;          u8 count;
# Line 714  int ccs_write_network_policy(char *data, Line 744  int ccs_write_network_policy(char *data,
744          if (!cp1)          if (!cp1)
745                  goto out;                  goto out;
746          *cp1++ = '\0';          *cp1++ = '\0';
747          count = sscanf(cp2, "%hx:%hx:%hx:%hx:%hx:%hx:%hx:%hx"          switch (ccs_parse_ip_address(cp2, min_address, max_address)) {
748                         "-%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));  
749                  record_type = IP_RECORD_TYPE_IPv6;                  record_type = IP_RECORD_TYPE_IPv6;
750                  goto ok;                  break;
751          }          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;  
752                  record_type = IP_RECORD_TYPE_IPv4;                  record_type = IP_RECORD_TYPE_IPv4;
753                  goto ok;                  break;
754          }          default:
755          if (*cp2 == '@') {                  if (*cp2 != '@')
756                  group = find_or_assign_new_address_group(cp2 + 1);                          goto out;
757                    group = ccs_find_or_assign_new_address_group(cp2 + 1);
758                  if (!group)                  if (!group)
759                          return -ENOMEM;                          return -ENOMEM;
760                  record_type = IP_RECORD_TYPE_ADDRESS_GROUP;                  record_type = IP_RECORD_TYPE_ADDRESS_GROUP;
761                  goto ok;                  break;
762          }          }
  out:  
         return -EINVAL;  
  ok:  
763          if (strchr(cp1, ' '))          if (strchr(cp1, ' '))
764                  goto out;                  goto out;
765          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 767  int ccs_write_network_policy(char *data,
767                  goto out;                  goto out;
768          if (count == 1)          if (count == 1)
769                  max_port = min_port;                  max_port = min_port;
770          return update_network_entry(operation, record_type, group,          return ccs_update_network_entry(operation, record_type, group,
771                                      (u32 *) min_address, (u32 *) max_address,                                          (u32 *) min_address,
772                                      min_port, max_port, domain, condition,                                          (u32 *) max_address,
773                                      is_delete);                                          min_port, max_port, domain, condition,
774                                            is_delete);
775     out:
776            return -EINVAL;
777  }  }
778    
779  /**  /**
# Line 787  int ccs_write_network_policy(char *data, Line 785  int ccs_write_network_policy(char *data,
785   *   *
786   * Returns 0 on success, negative value otherwise.   * Returns 0 on success, negative value otherwise.
787   */   */
788  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,
789                                   const u16 port)                                                 const u8 *address,
790                                                   const u16 port)
791  {  {
792          return check_network_entry(is_ipv6, NETWORK_ACL_TCP_LISTEN,          return ccs_check_network_entry(is_ipv6, NETWORK_ACL_TCP_LISTEN,
793                                     (const u32 *) address, ntohs(port));                                         (const u32 *) address, ntohs(port));
794  }  }
795    
796  /**  /**
# Line 804  int ccs_check_network_listen_acl(const _ Line 803  int ccs_check_network_listen_acl(const _
803   *   *
804   * Returns 0 on success, negative value otherwise.   * Returns 0 on success, negative value otherwise.
805   */   */
806  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,
807                                    const u8 *address, const u16 port)                                                  const int sock_type,
808                                                    const u8 *address,
809                                                    const u16 port)
810  {  {
811          u8 operation;          u8 operation;
812          switch (sock_type) {          switch (sock_type) {
# Line 818  int ccs_check_network_connect_acl(const Line 819  int ccs_check_network_connect_acl(const
819          default:          default:
820                  operation = NETWORK_ACL_RAW_CONNECT;                  operation = NETWORK_ACL_RAW_CONNECT;
821          }          }
822          return check_network_entry(is_ipv6, operation, (const u32 *) address,          return ccs_check_network_entry(is_ipv6, operation,
823                                     ntohs(port));                                         (const u32 *) address, ntohs(port));
824  }  }
825    
826  /**  /**
# Line 832  int ccs_check_network_connect_acl(const Line 833  int ccs_check_network_connect_acl(const
833   *   *
834   * Returns 0 on success, negative value otherwise.   * Returns 0 on success, negative value otherwise.
835   */   */
836  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,
837                                 const u8 *address, const u16 port)                                        const u8 *address, const u16 port)
838  {  {
839          u8 operation;          u8 operation;
840          switch (sock_type) {          switch (sock_type) {
# Line 846  int ccs_check_network_bind_acl(const _Bo Line 847  int ccs_check_network_bind_acl(const _Bo
847          default:          default:
848                  operation = NETWORK_ACL_RAW_BIND;                  operation = NETWORK_ACL_RAW_BIND;
849          }          }
850          return check_network_entry(is_ipv6, operation, (const u32 *) address,          return ccs_check_network_entry(is_ipv6, operation,
851                                     ntohs(port));                                         (const u32 *) address, ntohs(port));
852  }  }
853    
854  /**  /**
# Line 859  int ccs_check_network_bind_acl(const _Bo Line 860  int ccs_check_network_bind_acl(const _Bo
860   *   *
861   * Returns 0 on success, negative value otherwise.   * Returns 0 on success, negative value otherwise.
862   */   */
863  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,
864                                   const u16 port)                                                 const u8 *address,
865                                                   const u16 port)
866  {  {
867          int retval;          int retval;
868          current->tomoyo_flags |= CCS_DONT_SLEEP_ON_ENFORCE_ERROR;          current->ccs_flags |= CCS_DONT_SLEEP_ON_ENFORCE_ERROR;
869          retval = check_network_entry(is_ipv6, NETWORK_ACL_TCP_ACCEPT,          retval = ccs_check_network_entry(is_ipv6, NETWORK_ACL_TCP_ACCEPT,
870                                       (const u32 *) address, ntohs(port));                                           (const u32 *) address, ntohs(port));
871          current->tomoyo_flags &= ~CCS_DONT_SLEEP_ON_ENFORCE_ERROR;          current->ccs_flags &= ~CCS_DONT_SLEEP_ON_ENFORCE_ERROR;
872          return retval;          return retval;
873  }  }
874    
# Line 880  int ccs_check_network_accept_acl(const _ Line 882  int ccs_check_network_accept_acl(const _
882   *   *
883   * Returns 0 on success, negative value otherwise.   * Returns 0 on success, negative value otherwise.
884   */   */
885  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,
886                                    const u8 *address, const u16 port)                                                  const int sock_type,
887                                                    const u8 *address,
888                                                    const u16 port)
889  {  {
890          u8 operation;          u8 operation;
891          if (sock_type == SOCK_DGRAM)          if (sock_type == SOCK_DGRAM)
892                  operation = NETWORK_ACL_UDP_CONNECT;                  operation = NETWORK_ACL_UDP_CONNECT;
893          else          else
894                  operation = NETWORK_ACL_RAW_CONNECT;                  operation = NETWORK_ACL_RAW_CONNECT;
895          return check_network_entry(is_ipv6, operation, (const u32 *) address,          return ccs_check_network_entry(is_ipv6, operation,
896                                     ntohs(port));                                         (const u32 *) address, ntohs(port));
897  }  }
898    
899  /**  /**
# Line 902  int ccs_check_network_sendmsg_acl(const Line 906  int ccs_check_network_sendmsg_acl(const
906   *   *
907   * Returns 0 on success, negative value otherwise.   * Returns 0 on success, negative value otherwise.
908   */   */
909  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,
910                                    const u8 *address, const u16 port)                                                  const int sock_type,
911                                                    const u8 *address,
912                                                    const u16 port)
913  {  {
914          int retval;          int retval;
915          const u8 operation          const u8 operation
916                  = (sock_type == SOCK_DGRAM) ?                  = (sock_type == SOCK_DGRAM) ?
917                  NETWORK_ACL_UDP_CONNECT : NETWORK_ACL_RAW_CONNECT;                  NETWORK_ACL_UDP_CONNECT : NETWORK_ACL_RAW_CONNECT;
918          current->tomoyo_flags |= CCS_DONT_SLEEP_ON_ENFORCE_ERROR;          current->ccs_flags |= CCS_DONT_SLEEP_ON_ENFORCE_ERROR;
919          retval = check_network_entry(is_ipv6, operation, (const u32 *) address,          retval = ccs_check_network_entry(is_ipv6, operation,
920                                       ntohs(port));                                           (const u32 *) address, ntohs(port));
921          current->tomoyo_flags &= ~CCS_DONT_SLEEP_ON_ENFORCE_ERROR;          current->ccs_flags &= ~CCS_DONT_SLEEP_ON_ENFORCE_ERROR;
922          return retval;          return retval;
923  }  }
924    
925    #define MAX_SOCK_ADDR 128 /* net/socket.c */
926    
927    /* Check permission for creating a socket. */
928    int ccs_socket_create_permission(int family, int type, int protocol)
929    {
930            int error = 0;
931            /* Nothing to do if I am a kernel service. */
932            if (segment_eq(get_fs(), KERNEL_DS))
933                    return 0;
934            if (family == PF_PACKET && !ccs_capable(CCS_USE_PACKET_SOCKET))
935                    return -EPERM;
936            if (family == PF_ROUTE && !ccs_capable(CCS_USE_ROUTE_SOCKET))
937                    return -EPERM;
938            if (family != PF_INET && family != PF_INET6)
939                    return 0;
940            switch (type) {
941            case SOCK_STREAM:
942                    if (!ccs_capable(CCS_INET_STREAM_SOCKET_CREATE))
943                            error = -EPERM;
944                    break;
945            case SOCK_DGRAM:
946                    if (!ccs_capable(CCS_USE_INET_DGRAM_SOCKET))
947                            error = -EPERM;
948                    break;
949            case SOCK_RAW:
950                    if (!ccs_capable(CCS_USE_INET_RAW_SOCKET))
951                            error = -EPERM;
952                    break;
953            }
954            return error;
955    }
956    
957    /* Check permission for listening a TCP socket. */
958    int ccs_socket_listen_permission(struct socket *sock)
959    {
960            int error = 0;
961            char addr[MAX_SOCK_ADDR];
962            int addr_len;
963            /* Nothing to do if I am a kernel service. */
964            if (segment_eq(get_fs(), KERNEL_DS))
965                    return 0;
966            if (sock->type != SOCK_STREAM)
967                    return 0;
968            switch (sock->sk->sk_family) {
969            case PF_INET:
970            case PF_INET6:
971                    break;
972            default:
973                    return 0;
974            }
975            if (!ccs_capable(CCS_INET_STREAM_SOCKET_LISTEN))
976                    return -EPERM;
977            if (sock->ops->getname(sock, (struct sockaddr *) addr, &addr_len, 0))
978                    return -EPERM;
979            switch (((struct sockaddr *) addr)->sa_family) {
980                    struct sockaddr_in6 *addr6;
981                    struct sockaddr_in *addr4;
982            case AF_INET6:
983                    addr6 = (struct sockaddr_in6 *) addr;
984                    error = ccs_check_network_listen_acl(true,
985                                                         addr6->sin6_addr.s6_addr,
986                                                         addr6->sin6_port);
987                    break;
988            case AF_INET:
989                    addr4 = (struct sockaddr_in *) addr;
990                    error = ccs_check_network_listen_acl(false,
991                                                         (u8 *) &addr4->sin_addr,
992                                                         addr4->sin_port);
993                    break;
994            }
995            return error;
996    }
997    
998    /* Check permission for setting the remote IP address/port pair of a socket. */
999    int ccs_socket_connect_permission(struct socket *sock, struct sockaddr *addr,
1000                                      int addr_len)
1001    {
1002            int error = 0;
1003            const unsigned int type = sock->type;
1004            /* Nothing to do if I am a kernel service. */
1005            if (segment_eq(get_fs(), KERNEL_DS))
1006                    return 0;
1007            switch (type) {
1008            case SOCK_STREAM:
1009            case SOCK_DGRAM:
1010            case SOCK_RAW:
1011                    break;
1012            default:
1013                    return 0;
1014            }
1015            switch (addr->sa_family) {
1016                    struct sockaddr_in6 *addr6;
1017                    struct sockaddr_in *addr4;
1018                    u16 port;
1019            case AF_INET6:
1020                    if (addr_len < SIN6_LEN_RFC2133)
1021                            break;
1022                    addr6 = (struct sockaddr_in6 *) addr;
1023                    if (type != SOCK_RAW)
1024                            port = addr6->sin6_port;
1025                    else
1026                            port = htons(sock->sk->sk_protocol);
1027                    error = ccs_check_network_connect_acl(true, type,
1028                                                          addr6->sin6_addr.s6_addr,
1029                                                          port);
1030                    break;
1031            case AF_INET:
1032                    if (addr_len < sizeof(struct sockaddr_in))
1033                            break;
1034                    addr4 = (struct sockaddr_in *) addr;
1035                    if (type != SOCK_RAW)
1036                            port = addr4->sin_port;
1037                    else
1038                            port = htons(sock->sk->sk_protocol);
1039                    error = ccs_check_network_connect_acl(false, type,
1040                                                          (u8 *) &addr4->sin_addr,
1041                                                          port);
1042                    break;
1043            }
1044            if (type != SOCK_STREAM)
1045                    return error;
1046            switch (sock->sk->sk_family) {
1047            case PF_INET:
1048            case PF_INET6:
1049                    if (!ccs_capable(CCS_INET_STREAM_SOCKET_CONNECT))
1050                            error = -EPERM;
1051                    break;
1052            }
1053            return error;
1054    }
1055    
1056    /* Check permission for setting the local IP address/port pair of a socket. */
1057    int ccs_socket_bind_permission(struct socket *sock, struct sockaddr *addr,
1058                                   int addr_len)
1059    {
1060            int error = 0;
1061            const unsigned int type = sock->type;
1062            /* Nothing to do if I am a kernel service. */
1063            if (segment_eq(get_fs(), KERNEL_DS))
1064                    return 0;
1065            switch (type) {
1066            case SOCK_STREAM:
1067            case SOCK_DGRAM:
1068            case SOCK_RAW:
1069                    break;
1070            default:
1071                    return 0;
1072            }
1073            switch (addr->sa_family) {
1074                    struct sockaddr_in6 *addr6;
1075                    struct sockaddr_in *addr4;
1076                    u16 port;
1077            case AF_INET6:
1078                    if (addr_len < SIN6_LEN_RFC2133)
1079                            break;
1080                    addr6 = (struct sockaddr_in6 *) addr;
1081                    if (type != SOCK_RAW)
1082                            port = addr6->sin6_port;
1083                    else
1084                            port = htons(sock->sk->sk_protocol);
1085                    error = ccs_check_network_bind_acl(true, type,
1086                                                       addr6->sin6_addr.s6_addr,
1087                                                       port);
1088                    break;
1089            case AF_INET:
1090                    if (addr_len < sizeof(struct sockaddr_in))
1091                            break;
1092                    addr4 = (struct sockaddr_in *) addr;
1093                    if (type != SOCK_RAW)
1094                            port = addr4->sin_port;
1095                    else
1096                            port = htons(sock->sk->sk_protocol);
1097                    error = ccs_check_network_bind_acl(false, type,
1098                                                       (u8 *) &addr4->sin_addr,
1099                                                       port);
1100                    break;
1101            }
1102            return error;
1103    }
1104    
1105    /*
1106     * Check permission for accepting a TCP socket.
1107     *
1108     * Currently, the LSM hook for this purpose is not provided.
1109     */
1110    int ccs_socket_accept_permission(struct socket *sock, struct sockaddr *addr)
1111    {
1112            int error = 0;
1113            int addr_len;
1114            /* Nothing to do if I am a kernel service. */
1115            if (segment_eq(get_fs(), KERNEL_DS))
1116                    return 0;
1117            switch (sock->sk->sk_family) {
1118            case PF_INET:
1119            case PF_INET6:
1120                    break;
1121            default:
1122                    return 0;
1123            }
1124            error = sock->ops->getname(sock, addr, &addr_len, 2);
1125            if (error)
1126                    return error;
1127            switch (addr->sa_family) {
1128                    struct sockaddr_in6 *addr6;
1129                    struct sockaddr_in *addr4;
1130            case AF_INET6:
1131                    addr6 = (struct sockaddr_in6 *) addr;
1132                    error = ccs_check_network_accept_acl(true,
1133                                                         addr6->sin6_addr.s6_addr,
1134                                                         addr6->sin6_port);
1135                    break;
1136            case AF_INET:
1137                    addr4 = (struct sockaddr_in *) addr;
1138                    error = ccs_check_network_accept_acl(false,
1139                                                         (u8 *) &addr4->sin_addr,
1140                                                         addr4->sin_port);
1141                    break;
1142            }
1143            return error;
1144    }
1145    
1146    /* Check permission for sending a datagram via a UDP or RAW socket. */
1147    int ccs_socket_sendmsg_permission(struct socket *sock, struct sockaddr *addr,
1148                                      int addr_len)
1149    {
1150            int error = 0;
1151            const int type = sock->type;
1152            /* Nothing to do if I am a kernel service. */
1153            if (segment_eq(get_fs(), KERNEL_DS))
1154                    return 0;
1155            if (!addr || (type != SOCK_DGRAM && type != SOCK_RAW))
1156                    return 0;
1157            switch (addr->sa_family) {
1158                    struct sockaddr_in6 *addr6;
1159                    struct sockaddr_in *addr4;
1160                    u16 port;
1161            case AF_INET6:
1162                    if (addr_len < SIN6_LEN_RFC2133)
1163                            break;
1164                    addr6 = (struct sockaddr_in6 *) addr;
1165                    if (type == SOCK_DGRAM)
1166                            port = addr6->sin6_port;
1167                    else
1168                            port = htons(sock->sk->sk_protocol);
1169                    error = ccs_check_network_sendmsg_acl(true, type,
1170                                                          addr6->sin6_addr.s6_addr,
1171                                                          port);
1172                    break;
1173            case AF_INET:
1174                    if (addr_len < sizeof(struct sockaddr_in))
1175                            break;
1176                    addr4 = (struct sockaddr_in *) addr;
1177                    if (type == SOCK_DGRAM)
1178                            port = addr4->sin_port;
1179                    else
1180                            port = htons(sock->sk->sk_protocol);
1181                    error = ccs_check_network_sendmsg_acl(false, type,
1182                                                          (u8 *) &addr4->sin_addr,
1183                                                          port);
1184                    break;
1185            }
1186            return error;
1187    }
1188    
1189    #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 22)
1190    #if !defined(RHEL_MAJOR) || RHEL_MAJOR != 5
1191    
1192    static inline struct iphdr *ip_hdr(const struct sk_buff *skb)
1193    {
1194            return skb->nh.iph;
1195    }
1196    
1197    static inline struct udphdr *udp_hdr(const struct sk_buff *skb)
1198    {
1199            return skb->h.uh;
1200    }
1201    
1202    static inline struct ipv6hdr *ipv6_hdr(const struct sk_buff *skb)
1203    {
1204            return skb->nh.ipv6h;
1205    }
1206    
1207    #endif
1208    #endif
1209    
1210    #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 12)
1211    static void skb_kill_datagram(struct sock *sk, struct sk_buff *skb,
1212                                  unsigned int flags)
1213    {
1214            /* Clear queue. */
1215            if (flags & MSG_PEEK) {
1216                    int clear = 0;
1217                    spin_lock_irq(&sk->sk_receive_queue.lock);
1218                    if (skb == skb_peek(&sk->sk_receive_queue)) {
1219                            __skb_unlink(skb, &sk->sk_receive_queue);
1220                            clear = 1;
1221                    }
1222                    spin_unlock_irq(&sk->sk_receive_queue.lock);
1223                    if (clear)
1224                            kfree_skb(skb);
1225            }
1226    }
1227    #elif LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 16)
1228    static void skb_kill_datagram(struct sock *sk, struct sk_buff *skb,
1229                                  unsigned int flags)
1230    {
1231            /* Clear queue. */
1232            if (flags & MSG_PEEK) {
1233                    int clear = 0;
1234                    spin_lock_bh(&sk->sk_receive_queue.lock);
1235                    if (skb == skb_peek(&sk->sk_receive_queue)) {
1236                            __skb_unlink(skb, &sk->sk_receive_queue);
1237                            clear = 1;
1238                    }
1239                    spin_unlock_bh(&sk->sk_receive_queue.lock);
1240                    if (clear)
1241                            kfree_skb(skb);
1242            }
1243    }
1244    #endif
1245    
1246    /*
1247     * Check permission for receiving a datagram via a UDP or RAW socket.
1248     *
1249     * Currently, the LSM hook for this purpose is not provided.
1250     */
1251    int ccs_socket_recvmsg_permission(struct sock *sk, struct sk_buff *skb,
1252                                      const unsigned int flags)
1253    {
1254            int error = 0;
1255            const unsigned int type = sk->sk_type;
1256            if (type != SOCK_DGRAM && type != SOCK_RAW)
1257                    return 0;
1258            /* Nothing to do if I am a kernel service. */
1259            if (segment_eq(get_fs(), KERNEL_DS))
1260                    return 0;
1261    
1262            switch (sk->sk_family) {
1263                    struct in6_addr sin6;
1264                    struct in_addr sin4;
1265                    u16 port;
1266            case PF_INET6:
1267                    if (type == SOCK_DGRAM) { /* UDP IPv6 */
1268                            if (skb->protocol == htons(ETH_P_IP)) {
1269                                    ipv6_addr_set(&sin6, 0, 0, htonl(0xffff),
1270                                                  ip_hdr(skb)->saddr);
1271                            } else {
1272                                    ipv6_addr_copy(&sin6, &ipv6_hdr(skb)->saddr);
1273                            }
1274                            port = udp_hdr(skb)->source;
1275                    } else { /* RAW IPv6 */
1276                            ipv6_addr_copy(&sin6, &ipv6_hdr(skb)->saddr);
1277                            port = htons(sk->sk_protocol);
1278                    }
1279                    error = ccs_check_network_recvmsg_acl(true, type,
1280                                                          (u8 *) &sin6, port);
1281                    break;
1282            case PF_INET:
1283                    if (type == SOCK_DGRAM) { /* UDP IPv4 */
1284                            sin4.s_addr = ip_hdr(skb)->saddr;
1285                            port = udp_hdr(skb)->source;
1286                    } else { /* RAW IPv4 */
1287                            sin4.s_addr = ip_hdr(skb)->saddr;
1288                            port = htons(sk->sk_protocol);
1289                    }
1290                    error = ccs_check_network_recvmsg_acl(false, type,
1291                                                          (u8 *) &sin4, port);
1292                    break;
1293            }
1294            if (!error)
1295                    return 0;
1296            /*
1297             * Remove from queue if MSG_PEEK is used so that
1298             * the head message from unwanted source in receive queue will not
1299             * prevent the caller from picking up next message from wanted source
1300             * when the caller is using MSG_PEEK flag for picking up.
1301             */
1302    #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)
1303            if (type == SOCK_DGRAM)
1304                    lock_sock(sk);
1305    #endif
1306            skb_kill_datagram(sk, skb, flags);
1307    #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)
1308            if (type == SOCK_DGRAM)
1309                    release_sock(sk);
1310    #endif
1311            /* Hope less harmful than -EPERM. */
1312            return -ENOMEM;
1313    }
1314    EXPORT_SYMBOL(ccs_socket_recvmsg_permission);

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

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