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

Subversion リポジトリの参照

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

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

trunk/1.6.x/ccs-patch/fs/tomoyo_network.c revision 2039 by kumaneko, Wed Jan 7 04:42:05 2009 UTC branches/ccs-patch/security/ccsecurity/network.c revision 2897 by kumaneko, Wed Aug 12 06:16:57 2009 UTC
# Line 1  Line 1 
1  /*  /*
2   * fs/tomoyo_network.c   * security/ccsecurity/network.c
  *  
  * Implementation of the Domain-Based Mandatory Access Control.  
3   *   *
4   * Copyright (C) 2005-2009  NTT DATA CORPORATION   * Copyright (C) 2005-2009  NTT DATA CORPORATION
5   *   *
6   * Version: 1.6.6-pre   2009/01/05   * Version: 1.7.0-pre   2009/08/08
7   *   *
8   * This file is applicable to both 2.4.30 and 2.6.11 and later.   * This file is applicable to both 2.4.30 and 2.6.11 and later.
9   * See README.ccs for ChangeLog.   * See README.ccs for ChangeLog.
10   *   *
11   */   */
12    
 #include <linux/ccs_common.h>  
 #include <linux/tomoyo.h>  
 #include <linux/realpath.h>  
13  #include <linux/net.h>  #include <linux/net.h>
14  #include <linux/inet.h>  #include <linux/inet.h>
15  #include <linux/in.h>  #include <linux/in.h>
# Line 22  Line 17 
17  #include <net/ip.h>  #include <net/ip.h>
18  #include <net/ipv6.h>  #include <net/ipv6.h>
19  #include <net/udp.h>  #include <net/udp.h>
20    #include "internal.h"
21    
22  /* Index numbers for Network Controls. */  /* Index numbers for Network Controls. */
23  enum ccs_network_acl_index {  enum ccs_network_acl_index {
24          NETWORK_ACL_UDP_BIND,          CCS_NETWORK_ACL_UDP_BIND,
25          NETWORK_ACL_UDP_CONNECT,          CCS_NETWORK_ACL_UDP_CONNECT,
26          NETWORK_ACL_TCP_BIND,          CCS_NETWORK_ACL_TCP_BIND,
27          NETWORK_ACL_TCP_LISTEN,          CCS_NETWORK_ACL_TCP_LISTEN,
28          NETWORK_ACL_TCP_CONNECT,          CCS_NETWORK_ACL_TCP_CONNECT,
29          NETWORK_ACL_TCP_ACCEPT,          CCS_NETWORK_ACL_TCP_ACCEPT,
30          NETWORK_ACL_RAW_BIND,          CCS_NETWORK_ACL_RAW_BIND,
31          NETWORK_ACL_RAW_CONNECT          CCS_NETWORK_ACL_RAW_CONNECT
32  };  };
33    
34  /**  /**
# Line 50  static int ccs_audit_network_log(struct Line 46  static int ccs_audit_network_log(struct
46                                   const char *operation, const char *address,                                   const char *operation, const char *address,
47                                   const u16 port, const bool is_granted)                                   const u16 port, const bool is_granted)
48  {  {
49          return ccs_write_audit_log(is_granted, r, KEYWORD_ALLOW_NETWORK          if (!is_granted && ccs_verbose_mode(r->domain))
50                    printk(KERN_WARNING "TOMOYO-%s: %s to %s %u denied for %s\n",
51                           ccs_get_msg(r->mode == 3), operation, address, port,
52                           ccs_get_last_name(r->domain));
53            return ccs_write_audit_log(is_granted, r, CCS_KEYWORD_ALLOW_NETWORK
54                                     "%s %s %u\n", operation, address, port);                                     "%s %s %u\n", operation, address, port);
55  }  }
56    
 /**  
  * ccs_save_ipv6_address - Keep the given IPv6 address on the RAM.  
  *  
  * @addr: Pointer to "struct in6_addr".  
  *  
  * Returns pointer to "struct in6_addr" on success, NULL otherwise.  
  *  
  * The RAM is shared, so NEVER try to modify or kfree() the returned address.  
  */  
 static const struct in6_addr *ccs_save_ipv6_address(const struct in6_addr *addr)  
 {  
         static const u8 ccs_block_size = 16;  
         struct ccs_addr_list {  
                 /* Workaround for gcc 4.3's bug. */  
                 struct in6_addr addr[16]; /* = ccs_block_size */  
                 struct list1_head list;  
                 u32 in_use_count;  
         };  
         static LIST1_HEAD(ccs_address_list);  
         struct ccs_addr_list *ptr;  
         static DEFINE_MUTEX(lock);  
         u8 i = ccs_block_size;  
         if (!addr)  
                 return NULL;  
         mutex_lock(&lock);  
         list1_for_each_entry(ptr, &ccs_address_list, list) {  
                 for (i = 0; i < ptr->in_use_count; i++) {  
                         if (!memcmp(&ptr->addr[i], addr, sizeof(*addr)))  
                                 goto ok;  
                 }  
                 if (i < ccs_block_size)  
                         break;  
         }  
         if (i == ccs_block_size) {  
                 ptr = ccs_alloc_element(sizeof(*ptr));  
                 if (!ptr)  
                         goto ok;  
                 list1_add_tail_mb(&ptr->list, &ccs_address_list);  
                 i = 0;  
         }  
         ptr->addr[ptr->in_use_count++] = *addr;  
  ok:  
         mutex_unlock(&lock);  
         return ptr ? &ptr->addr[i] : NULL;  
 }  
   
57  /* The list for "struct ccs_address_group_entry". */  /* The list for "struct ccs_address_group_entry". */
58  static LIST1_HEAD(ccs_address_group_list);  LIST_HEAD(ccs_address_group_list);
59    
60  /**  /**
61   * ccs_update_address_group_entry - Update "struct ccs_address_group_entry" list.   * ccs_get_address_group - Allocate memory for "struct ccs_address_group_entry".
62   *   *
63   * @group_name:  The name of address group.   * @group_name: The name of address group.
  * @is_ipv6:     True if @min_address and @max_address are IPv6 addresses.  
  * @min_address: Start of IPv4 or IPv6 address range.  
  * @max_address: End of IPv4 or IPv6 address range.  
  * @is_delete:   True if it is a delete request.  
64   *   *
65   * Returns 0 on success, negative value otherwise.   * Returns pointer to "struct ccs_address_group_entry" on success,
66     * NULL otherwise.
67   */   */
68  static int ccs_update_address_group_entry(const char *group_name,  static struct ccs_address_group_entry *ccs_get_address_group(const char *
69                                            const bool is_ipv6,                                                               group_name)
                                           const u16 *min_address,  
                                           const u16 *max_address,  
                                           const bool is_delete)  
70  {  {
71          static DEFINE_MUTEX(lock);          struct ccs_address_group_entry *entry = NULL;
         struct ccs_address_group_entry *new_group;  
72          struct ccs_address_group_entry *group;          struct ccs_address_group_entry *group;
         struct ccs_address_group_member *new_member;  
         struct ccs_address_group_member *member;  
73          const struct ccs_path_info *saved_group_name;          const struct ccs_path_info *saved_group_name;
         const struct in6_addr *saved_min_address = NULL;  
         const struct in6_addr *saved_max_address = NULL;  
74          int error = -ENOMEM;          int error = -ENOMEM;
75          bool found = false;          if (!ccs_is_correct_path(group_name, 0, 0, 0) ||
         if (!ccs_is_correct_path(group_name, 0, 0, 0, __func__) ||  
76              !group_name[0])              !group_name[0])
77                  return -EINVAL;                  return NULL;
78          saved_group_name = ccs_save_name(group_name);          saved_group_name = ccs_get_name(group_name);
79          if (!saved_group_name)          if (!saved_group_name)
80                  return -ENOMEM;                  return NULL;
81          if (!is_ipv6)          entry = kzalloc(sizeof(*entry), GFP_KERNEL);
82                  goto not_ipv6;          mutex_lock(&ccs_policy_lock);
83          saved_min_address          list_for_each_entry_rcu(group, &ccs_address_group_list, list) {
                 = ccs_save_ipv6_address((struct in6_addr *) min_address);  
         saved_max_address  
                 = ccs_save_ipv6_address((struct in6_addr *) max_address);  
         if (!saved_min_address || !saved_max_address)  
                 return -ENOMEM;  
  not_ipv6:  
         mutex_lock(&lock);  
         list1_for_each_entry(group, &ccs_address_group_list, list) {  
84                  if (saved_group_name != group->group_name)                  if (saved_group_name != group->group_name)
85                          continue;                          continue;
86                  list1_for_each_entry(member,                  atomic_inc(&group->users);
87                                       &group->address_group_member_list,                  error = 0;
                                      list) {  
                         if (member->is_ipv6 != is_ipv6)  
                                 continue;  
                         if (is_ipv6) {  
                                 if (member->min.ipv6 != saved_min_address ||  
                                     member->max.ipv6 != saved_max_address)  
                                         continue;  
                         } else {  
                                 if (member->min.ipv4 != *(u32 *) min_address ||  
                                     member->max.ipv4 != *(u32 *) max_address)  
                                         continue;  
                         }  
                         member->is_deleted = is_delete;  
                         error = 0;  
                         goto out;  
                 }  
                 found = true;  
88                  break;                  break;
89          }          }
90          if (is_delete) {          if (error && ccs_memory_ok(entry, sizeof(*entry))) {
91                  error = -ENOENT;                  INIT_LIST_HEAD(&entry->address_group_member_list);
92                  goto out;                  entry->group_name = saved_group_name;
93          }                  saved_group_name = NULL;
94          if (!found) {                  atomic_set(&entry->users, 1);
95                  new_group = ccs_alloc_element(sizeof(*new_group));                  list_add_tail_rcu(&entry->list, &ccs_address_group_list);
96                  if (!new_group)                  group = entry;
97                          goto out;                  entry = NULL;
98                  INIT_LIST1_HEAD(&new_group->address_group_member_list);                  error = 0;
99                  new_group->group_name = saved_group_name;          }
100                  list1_add_tail_mb(&new_group->list, &ccs_address_group_list);          mutex_unlock(&ccs_policy_lock);
101                  group = new_group;          ccs_put_name(saved_group_name);
102          }          kfree(entry);
103          new_member = ccs_alloc_element(sizeof(*new_member));          return !error ? group : NULL;
         if (!new_member)  
                 goto out;  
         new_member->is_ipv6 = is_ipv6;  
         if (is_ipv6) {  
                 new_member->min.ipv6 = saved_min_address;  
                 new_member->max.ipv6 = saved_max_address;  
         } else {  
                 new_member->min.ipv4 = *(u32 *) min_address;  
                 new_member->max.ipv4 = *(u32 *) max_address;  
         }  
         list1_add_tail_mb(&new_member->list,  
                           &group->address_group_member_list);  
         error = 0;  
  out:  
         mutex_unlock(&lock);  
         ccs_update_counter(CCS_UPDATES_COUNTER_EXCEPTION_POLICY);  
         return error;  
104  }  }
105    
106  /**  /**
# Line 247  static int ccs_parse_ip_address(char *ad Line 147  static int ccs_parse_ip_address(char *ad
147  }  }
148    
149  /**  /**
150   * ccs_write_address_group_policy - Write "struct ccs_address_group_entry" list.   * ccs_update_address_group_entry - Update "struct ccs_address_group_entry" list.
151   *   *
152   * @data:      String to parse.   * @group_name:  The name of address group.
153   * @is_delete: True if it is a delete request.   * @address:     IP address.
154     * @is_delete:   True if it is a delete request.
155   *   *
156   * Returns 0 on success, negative value otherwise.   * Returns 0 on success, negative value otherwise.
157   */   */
158  int ccs_write_address_group_policy(char *data, const bool is_delete)  static int ccs_update_address_group_entry(const char *group_name,
159                                              char *address, const bool is_delete)
160  {  {
161          bool is_ipv6;          struct ccs_address_group_entry *group;
162            struct ccs_address_group_member *entry = NULL;
163            struct ccs_address_group_member *member;
164            const struct in6_addr *saved_min_address = NULL;
165            const struct in6_addr *saved_max_address = NULL;
166            int error = is_delete ? -ENOENT : -ENOMEM;
167            u32 min_ipv4_address = 0;
168            u32 max_ipv4_address = 0;
169          u16 min_address[8];          u16 min_address[8];
170          u16 max_address[8];          u16 max_address[8];
171          char *cp = strchr(data, ' ');          bool is_ipv6 = false;
172          if (!cp)          group = ccs_get_address_group(group_name);
173                  return -EINVAL;          if (!group)
174          *cp++ = '\0';                  return -ENOMEM;
175          switch (ccs_parse_ip_address(cp, min_address, max_address)) {          switch (ccs_parse_ip_address(address, min_address, max_address)) {
176          case 2:          case 2:
177                  is_ipv6 = true;                  is_ipv6 = true;
178                    saved_min_address
179                            = ccs_get_ipv6_address((struct in6_addr *)
180                                                   min_address);
181                    saved_max_address
182                            = ccs_get_ipv6_address((struct in6_addr *)
183                                                   max_address);
184                    if (!saved_min_address || !saved_max_address)
185                            goto out;
186                  break;                  break;
187          case 1:          case 1:
188                  is_ipv6 = false;                  min_ipv4_address = ntohl(*(u32 *) min_address);
189                    max_ipv4_address = ntohl(*(u32 *) max_address);
190                  break;                  break;
191          default:          default:
192                  return -EINVAL;                  goto out;
193          }          }
194          return ccs_update_address_group_entry(data, is_ipv6, min_address,          if (!is_delete)
195                                                max_address, is_delete);                  entry = kzalloc(sizeof(*entry), GFP_KERNEL);
196            mutex_lock(&ccs_policy_lock);
197            list_for_each_entry_rcu(member, &group->address_group_member_list,
198                                    list) {
199                    if (member->is_ipv6 != is_ipv6)
200                            continue;
201                    if (is_ipv6) {
202                            if (member->min.ipv6 != saved_min_address ||
203                                member->max.ipv6 != saved_max_address)
204                                    continue;
205                    } else {
206                            if (member->min.ipv4 != min_ipv4_address ||
207                                member->max.ipv4 != max_ipv4_address)
208                                    continue;
209                    }
210                    member->is_deleted = is_delete;
211                    error = 0;
212                    break;
213            }
214            if (!is_delete && error && ccs_memory_ok(entry, sizeof(*entry))) {
215                    entry->is_ipv6 = is_ipv6;
216                    if (is_ipv6) {
217                            entry->min.ipv6 = saved_min_address;
218                            saved_min_address = NULL;
219                            entry->max.ipv6 = saved_max_address;
220                            saved_max_address = NULL;
221                    } else {
222                            entry->min.ipv4 = min_ipv4_address;
223                            entry->max.ipv4 = max_ipv4_address;
224                    }
225                    list_add_tail_rcu(&entry->list,
226                                      &group->address_group_member_list);
227                    entry = NULL;
228                    error = 0;
229            }
230            mutex_unlock(&ccs_policy_lock);
231     out:
232            ccs_put_ipv6_address(saved_min_address);
233            ccs_put_ipv6_address(saved_max_address);
234            ccs_put_address_group(group);
235            return error;
236  }  }
237    
238  /**  /**
239   * ccs_find_or_assign_new_address_group - Create address group.   * ccs_write_address_group_policy - Write "struct ccs_address_group_entry" list.
240   *   *
241   * @group_name: The name of address group.   * @data:      String to parse.
242     * @is_delete: True if it is a delete request.
243   *   *
244   * Returns pointer to "struct ccs_address_group_entry" on success,   * Returns 0 on success, negative value otherwise.
  * NULL otherwise.  
245   */   */
246  static struct ccs_address_group_entry *  int ccs_write_address_group_policy(char *data, const bool is_delete)
 ccs_find_or_assign_new_address_group(const char *group_name)  
247  {  {
248          u8 i;          char *w[2];
249          struct ccs_address_group_entry *group;          if (!ccs_tokenize(data, w, sizeof(w)) || !w[1][0])
250          for (i = 0; i <= 1; i++) {                  return -EINVAL;
251                  list1_for_each_entry(group, &ccs_address_group_list, list) {          return ccs_update_address_group_entry(w[0], w[1], is_delete);
                         if (!strcmp(group_name, group->group_name->name))  
                                 return group;  
                 }  
                 if (!i) {  
                         const u16 dummy[2] = { 0, 0 };  
                         ccs_update_address_group_entry(group_name, false,  
                                                        dummy, dummy, false);  
                         ccs_update_address_group_entry(group_name, false,  
                                                        dummy, dummy, true);  
                 }  
         }  
         return NULL;  
252  }  }
253    
254  /**  /**
# Line 314  ccs_find_or_assign_new_address_group(con Line 259  ccs_find_or_assign_new_address_group(con
259   * @group:   Pointer to "struct ccs_address_group_entry".   * @group:   Pointer to "struct ccs_address_group_entry".
260   *   *
261   * Returns true if @address matches addresses in @group group, false otherwise.   * Returns true if @address matches addresses in @group group, false otherwise.
262     *
263     * Caller holds ccs_read_lock().
264   */   */
265  static bool ccs_address_matches_group(const bool is_ipv6, const u32 *address,  static bool ccs_address_matches_group(const bool is_ipv6, const u32 *address,
266                                        const struct ccs_address_group_entry *                                        const struct ccs_address_group_entry *
# Line 321  static bool ccs_address_matches_group(co Line 268  static bool ccs_address_matches_group(co
268  {  {
269          struct ccs_address_group_member *member;          struct ccs_address_group_member *member;
270          const u32 ip = ntohl(*address);          const u32 ip = ntohl(*address);
271          list1_for_each_entry(member, &group->address_group_member_list,          bool matched = false;
272                               list) {          ccs_check_read_lock();
273            list_for_each_entry_rcu(member, &group->address_group_member_list,
274                                    list) {
275                  if (member->is_deleted)                  if (member->is_deleted)
276                          continue;                          continue;
277                  if (member->is_ipv6) {                  if (member->is_ipv6) {
278                          if (is_ipv6 &&                          if (is_ipv6 &&
279                              memcmp(member->min.ipv6, address, 16) <= 0 &&                              memcmp(member->min.ipv6, address, 16) <= 0 &&
280                              memcmp(address, member->max.ipv6, 16) <= 0)                              memcmp(address, member->max.ipv6, 16) <= 0) {
281                                  return true;                                  matched = true;
282                                    break;
283                            }
284                  } else {                  } else {
285                          if (!is_ipv6 &&                          if (!is_ipv6 &&
286                              member->min.ipv4 <= ip && ip <= member->max.ipv4)                              member->min.ipv4 <= ip && ip <= member->max.ipv4) {
287                                  return true;                                  matched = true;
288                                    break;
289                            }
290                  }                  }
291          }          }
292          return false;          return matched;
293  }  }
294    
295  /**  /**
# Line 345  static bool ccs_address_matches_group(co Line 298  static bool ccs_address_matches_group(co
298   * @head: Pointer to "struct ccs_io_buffer".   * @head: Pointer to "struct ccs_io_buffer".
299   *   *
300   * Returns true on success, false otherwise.   * Returns true on success, false otherwise.
301     *
302     * Caller holds ccs_read_lock().
303   */   */
304  bool ccs_read_address_group_policy(struct ccs_io_buffer *head)  bool ccs_read_address_group_policy(struct ccs_io_buffer *head)
305  {  {
306          struct list1_head *gpos;          struct list_head *gpos;
307          struct list1_head *mpos;          struct list_head *mpos;
308          list1_for_each_cookie(gpos, head->read_var1, &ccs_address_group_list) {          bool done = true;
309            ccs_check_read_lock();
310            list_for_each_cookie(gpos, head->read_var1, &ccs_address_group_list) {
311                  struct ccs_address_group_entry *group;                  struct ccs_address_group_entry *group;
312                  group = list1_entry(gpos, struct ccs_address_group_entry, list);                  group = list_entry(gpos, struct ccs_address_group_entry, list);
313                  list1_for_each_cookie(mpos, head->read_var2,                  list_for_each_cookie(mpos, head->read_var2,
314                                        &group->address_group_member_list) {                                       &group->address_group_member_list) {
315                          char buf[128];                          char buf[128];
316                          struct ccs_address_group_member *member;                          struct ccs_address_group_member *member;
317                          member = list1_entry(mpos,                          member = list_entry(mpos,
318                                               struct ccs_address_group_member,                                               struct ccs_address_group_member,
319                                               list);                                               list);
320                          if (member->is_deleted)                          if (member->is_deleted)
# Line 390  bool ccs_read_address_group_policy(struc Line 347  bool ccs_read_address_group_policy(struc
347                                                   HIPQUAD(max_address));                                                   HIPQUAD(max_address));
348                                  }                                  }
349                          }                          }
350                          if (!ccs_io_printf(head, KEYWORD_ADDRESS_GROUP                          done = ccs_io_printf(head, CCS_KEYWORD_ADDRESS_GROUP
351                                             "%s %s\n", group->group_name->name,                                               "%s %s\n", group->group_name->name,
352                                             buf))                                               buf);
353                                  goto out;                          if (!done)
354                                    break;
355                  }                  }
356                    if (!done)
357                            break;
358          }          }
359          return true;          return done;
  out:  
         return false;  
360  }  }
361    
362  #if !defined(NIP6)  #if !defined(NIP6)
# Line 436  const char *ccs_net2keyword(const u8 ope Line 394  const char *ccs_net2keyword(const u8 ope
394  {  {
395          const char *keyword = "unknown";          const char *keyword = "unknown";
396          switch (operation) {          switch (operation) {
397          case NETWORK_ACL_UDP_BIND:          case CCS_NETWORK_ACL_UDP_BIND:
398                  keyword = "UDP bind";                  keyword = "UDP bind";
399                  break;                  break;
400          case NETWORK_ACL_UDP_CONNECT:          case CCS_NETWORK_ACL_UDP_CONNECT:
401                  keyword = "UDP connect";                  keyword = "UDP connect";
402                  break;                  break;
403          case NETWORK_ACL_TCP_BIND:          case CCS_NETWORK_ACL_TCP_BIND:
404                  keyword = "TCP bind";                  keyword = "TCP bind";
405                  break;                  break;
406          case NETWORK_ACL_TCP_LISTEN:          case CCS_NETWORK_ACL_TCP_LISTEN:
407                  keyword = "TCP listen";                  keyword = "TCP listen";
408                  break;                  break;
409          case NETWORK_ACL_TCP_CONNECT:          case CCS_NETWORK_ACL_TCP_CONNECT:
410                  keyword = "TCP connect";                  keyword = "TCP connect";
411                  break;                  break;
412          case NETWORK_ACL_TCP_ACCEPT:          case CCS_NETWORK_ACL_TCP_ACCEPT:
413                  keyword = "TCP accept";                  keyword = "TCP accept";
414                  break;                  break;
415          case NETWORK_ACL_RAW_BIND:          case CCS_NETWORK_ACL_RAW_BIND:
416                  keyword = "RAW bind";                  keyword = "RAW bind";
417                  break;                  break;
418          case NETWORK_ACL_RAW_CONNECT:          case CCS_NETWORK_ACL_RAW_CONNECT:
419                  keyword = "RAW connect";                  keyword = "RAW connect";
420                  break;                  break;
421          }          }
# Line 467  const char *ccs_net2keyword(const u8 ope Line 425  const char *ccs_net2keyword(const u8 ope
425  /**  /**
426   * ccs_update_network_entry - Update "struct ccs_ip_network_acl_record" list.   * ccs_update_network_entry - Update "struct ccs_ip_network_acl_record" list.
427   *   *
428     * @protocol:    Protocol name.
429   * @operation:   Type of operation.   * @operation:   Type of operation.
430   * @record_type: Type of address.   * @address:     Address.
431   * @group:       Pointer to "struct ccs_address_group_entry". May be NULL.   * @port:        Port number.
432   * @min_address: Start of IPv4 or IPv6 address range.   * @domain:      Pointer to "struct ccs_domain_info".
433   * @max_address: End of IPv4 or IPv6 address range.   * @condition:   Pointer to "struct ccs_condition". May be NULL.
  * @min_port:    Start of port number range.  
  * @max_port:    End of port number range.  
  * @domain:      Pointer to "struct domain_info".  
  * @condition:   Pointer to "struct ccs_condition_list". May be NULL.  
434   * @is_delete:   True if it is a delete request.   * @is_delete:   True if it is a delete request.
435   *   *
436   * Returns 0 on success, negative value otherwise.   * Returns 0 on success, negative value otherwise.
437   */   */
438  static int ccs_update_network_entry(const u8 operation, const u8 record_type,  static int ccs_update_network_entry(const char *protocol,
439                                      const struct ccs_address_group_entry *group,                                      const char *operation, char *address,
440                                      const u32 *min_address,                                      char *port, struct ccs_domain_info *domain,
441                                      const u32 *max_address,                                      struct ccs_condition *condition,
                                     const u16 min_port, const u16 max_port,  
                                     struct domain_info *domain,  
                                     const struct ccs_condition_list *condition,  
442                                      const bool is_delete)                                      const bool is_delete)
443  {  {
444          static DEFINE_MUTEX(lock);          static const u8 offset = offsetof(struct ccs_ip_network_acl_record,
445                                              head.cond);
446          struct ccs_acl_info *ptr;          struct ccs_acl_info *ptr;
447          struct ccs_ip_network_acl_record *acl;          struct ccs_ip_network_acl_record e;
448          int error = -ENOMEM;          struct ccs_ip_network_acl_record *entry = NULL;
449          /* using host byte order to allow u32 comparison than memcmp().*/          u16 min_address[8];
450          const u32 min_ip = ntohl(*min_address);          u16 max_address[8];
451          const u32 max_ip = ntohl(*max_address);          int error = is_delete ? -ENOENT : -ENOMEM;
452          const struct in6_addr *saved_min_address = NULL;          u8 sock_type;
453          const struct in6_addr *saved_max_address = NULL;          memset(&e, 0, sizeof(e));
454            e.head.type = CCS_TYPE_IP_NETWORK_ACL;
455            e.head.cond = condition;
456          if (!domain)          if (!domain)
457                  return -EINVAL;                  return -EINVAL;
458          if (record_type != IP_RECORD_TYPE_IPv6)          if (!strcmp(protocol, "TCP"))
459                  goto not_ipv6;                  sock_type = SOCK_STREAM;
460          saved_min_address = ccs_save_ipv6_address((struct in6_addr *)          else if (!strcmp(protocol, "UDP"))
461                                                    min_address);                  sock_type = SOCK_DGRAM;
462          saved_max_address = ccs_save_ipv6_address((struct in6_addr *)          else if (!strcmp(protocol, "RAW"))
463                                                    max_address);                  sock_type = SOCK_RAW;
464          if (!saved_min_address || !saved_max_address)          else
465                  return -ENOMEM;                  return -EINVAL;
466   not_ipv6:          if (!strcmp(operation, "bind"))
467          mutex_lock(&lock);                  switch (sock_type) {
468                    case SOCK_STREAM:
469                            e.operation_type = CCS_NETWORK_ACL_TCP_BIND;
470                            break;
471                    case SOCK_DGRAM:
472                            e.operation_type = CCS_NETWORK_ACL_UDP_BIND;
473                            break;
474                    default:
475                            e.operation_type = CCS_NETWORK_ACL_RAW_BIND;
476                            break;
477                    }
478            else if (!strcmp(operation, "connect"))
479                    switch (sock_type) {
480                    case SOCK_STREAM:
481                            e.operation_type = CCS_NETWORK_ACL_TCP_CONNECT;
482                            break;
483                    case SOCK_DGRAM:
484                            e.operation_type = CCS_NETWORK_ACL_UDP_CONNECT;
485                            break;
486                    default:
487                            e.operation_type = CCS_NETWORK_ACL_RAW_CONNECT;
488                            break;
489                    }
490            else if (sock_type == SOCK_STREAM && !strcmp(operation, "listen"))
491                    e.operation_type = CCS_NETWORK_ACL_TCP_LISTEN;
492            else if (sock_type == SOCK_STREAM && !strcmp(operation, "accept"))
493                    e.operation_type = CCS_NETWORK_ACL_TCP_ACCEPT;
494            else
495                    return -EINVAL;
496            switch (ccs_parse_ip_address(address, min_address, max_address)) {
497            case 2:
498                    e.record_type = CCS_IP_RECORD_TYPE_IPv6;
499                    e.address.ipv6.min = ccs_get_ipv6_address((struct in6_addr *)
500                                                              min_address);
501                    e.address.ipv6.max = ccs_get_ipv6_address((struct in6_addr *)
502                                                              max_address);
503                    if (!e.address.ipv6.min || !e.address.ipv6.max)
504                            goto out;
505                    break;
506            case 1:
507                    e.record_type = CCS_IP_RECORD_TYPE_IPv4;
508                    /* use host byte order to allow u32 comparison.*/
509                    e.address.ipv4.min = ntohl(* (u32 *) min_address);
510                    e.address.ipv4.max = ntohl(* (u32 *) max_address);
511                    break;
512            default:
513                    if (address[0] != '@')
514                            return -EINVAL;
515                    e.record_type = CCS_IP_RECORD_TYPE_ADDRESS_GROUP;
516                    e.address.group = ccs_get_address_group(address + 1);
517                    if (!e.address.group)
518                            return -ENOMEM;
519                    break;
520            }
521            if (!ccs_parse_number_union(port, &e.port))
522                    goto out;
523          if (is_delete)          if (is_delete)
524                  goto delete;                  goto delete;
525          list1_for_each_entry(ptr, &domain->acl_info_list, list) {          entry = kzalloc(sizeof(*entry), GFP_KERNEL);
526                  if (ccs_acl_type1(ptr) != TYPE_IP_NETWORK_ACL)          mutex_lock(&ccs_policy_lock);
527                          continue;          list_for_each_entry_rcu(ptr, &domain->acl_info_list, list) {
528                  if (ccs_get_condition_part(ptr) != condition)                  struct ccs_ip_network_acl_record *acl;
529                    if (ccs_acl_type1(ptr) != CCS_TYPE_IP_NETWORK_ACL)
530                          continue;                          continue;
531                    //if (ptr->cond != condition)
532                    //continue;
533                  acl = container_of(ptr, struct ccs_ip_network_acl_record, head);                  acl = container_of(ptr, struct ccs_ip_network_acl_record, head);
534                  if (acl->operation_type != operation ||                  if (memcmp(((char *) acl) + offset, ((char *) &e) + offset,
535                      acl->record_type != record_type ||                             sizeof(e) - offset))
                     acl->min_port != min_port || max_port != acl->max_port)  
536                          continue;                          continue;
                 if (record_type == IP_RECORD_TYPE_ADDRESS_GROUP) {  
                         if (acl->u.group != group)  
                                 continue;  
                 } else if (record_type == IP_RECORD_TYPE_IPv4) {  
                         if (acl->u.ipv4.min != min_ip ||  
                             max_ip != acl->u.ipv4.max)  
                                 continue;  
                 } else if (record_type == IP_RECORD_TYPE_IPv6) {  
                         if (acl->u.ipv6.min != saved_min_address ||  
                             saved_max_address != acl->u.ipv6.max)  
                                 continue;  
                 }  
537                  error = ccs_add_domain_acl(NULL, ptr);                  error = ccs_add_domain_acl(NULL, ptr);
538                  goto out;                  break;
539          }          }
540          /* Not found. Append it to the tail. */          if (error && ccs_memory_ok(entry, sizeof(*entry))) {
541          acl = ccs_alloc_acl_element(TYPE_IP_NETWORK_ACL, condition);                  memmove(entry, &e, sizeof(e));
542          if (!acl)                  memset(&e, 0, sizeof(e));
543                  goto out;                  error = ccs_add_domain_acl(domain, &entry->head);
544          acl->operation_type = operation;                  entry = NULL;
545          acl->record_type = record_type;          }
546          if (record_type == IP_RECORD_TYPE_ADDRESS_GROUP) {          mutex_unlock(&ccs_policy_lock);
                 acl->u.group = group;  
         } else if (record_type == IP_RECORD_TYPE_IPv4) {  
                 acl->u.ipv4.min = min_ip;  
                 acl->u.ipv4.max = max_ip;  
         } else {  
                 acl->u.ipv6.min = saved_min_address;  
                 acl->u.ipv6.max = saved_max_address;  
         }  
         acl->min_port = min_port;  
         acl->max_port = max_port;  
         error = ccs_add_domain_acl(domain, &acl->head);  
547          goto out;          goto out;
548   delete:   delete:
549          error = -ENOENT;          mutex_lock(&ccs_policy_lock);
550          list1_for_each_entry(ptr, &domain->acl_info_list, list) {          list_for_each_entry_rcu(ptr, &domain->acl_info_list, list) {
551                  if (ccs_acl_type2(ptr) != TYPE_IP_NETWORK_ACL)                  struct ccs_ip_network_acl_record *acl;
552                          continue;                  if (ccs_acl_type2(ptr) != CCS_TYPE_IP_NETWORK_ACL)
                 if (ccs_get_condition_part(ptr) != condition)  
553                          continue;                          continue;
554                    //if (ptr->cond != condition)
555                    //continue;
556                  acl = container_of(ptr, struct ccs_ip_network_acl_record, head);                  acl = container_of(ptr, struct ccs_ip_network_acl_record, head);
557                  if (acl->operation_type != operation ||                  if (memcmp(((char *) acl) + offset, ((char *) &e) + offset,
558                      acl->record_type != record_type ||                             sizeof(e) - offset))
                     acl->min_port != min_port || max_port != acl->max_port)  
559                          continue;                          continue;
                 if (record_type == IP_RECORD_TYPE_ADDRESS_GROUP) {  
                         if (acl->u.group != group)  
                                 continue;  
                 } else if (record_type == IP_RECORD_TYPE_IPv4) {  
                         if (acl->u.ipv4.min != min_ip ||  
                             max_ip != acl->u.ipv4.max)  
                                 continue;  
                 } else if (record_type == IP_RECORD_TYPE_IPv6) {  
                         if (acl->u.ipv6.min != saved_min_address ||  
                             saved_max_address != acl->u.ipv6.max)  
                                 continue;  
                 }  
560                  error = ccs_del_domain_acl(ptr);                  error = ccs_del_domain_acl(ptr);
561                  break;                  break;
562          }          }
563            mutex_unlock(&ccs_policy_lock);
564   out:   out:
565          mutex_unlock(&lock);          if (address[0] == '@')
566                    ccs_put_address_group(e.address.group);
567            else if (e.record_type == CCS_IP_RECORD_TYPE_IPv6) {
568                    ccs_put_ipv6_address(e.address.ipv6.min);
569                    ccs_put_ipv6_address(e.address.ipv6.max);
570            }
571            ccs_put_number_union(&e.port);
572            kfree(entry);
573          return error;          return error;
574  }  }
575    
576  /**  /**
577   * ccs_check_network_entry - Check permission for network operation.   * ccs_check_network_entry2 - Check permission for network operation.
578   *   *
579   * @is_ipv6:   True if @address is an IPv6 address.   * @is_ipv6:   True if @address is an IPv6 address.
580   * @operation: Type of operation.   * @operation: Type of operation.
# Line 597  static int ccs_update_network_entry(cons Line 582  static int ccs_update_network_entry(cons
582   * @port:      Port number.   * @port:      Port number.
583   *   *
584   * Returns 0 on success, negative value otherwise.   * Returns 0 on success, negative value otherwise.
585     *
586     * Caller holds ccs_read_lock().
587   */   */
588  static int ccs_check_network_entry(const bool is_ipv6, const u8 operation,  static int ccs_check_network_entry2(const bool is_ipv6, const u8 operation,
589                                     const u32 *address, const u16 port)                                      const u32 *address, const u16 port)
590  {  {
591          struct ccs_request_info r;          struct ccs_request_info r;
592          struct ccs_acl_info *ptr;          struct ccs_acl_info *ptr;
# Line 607  static int ccs_check_network_entry(const Line 594  static int ccs_check_network_entry(const
594          bool is_enforce;          bool is_enforce;
595          /* using host byte order to allow u32 comparison than memcmp().*/          /* using host byte order to allow u32 comparison than memcmp().*/
596          const u32 ip = ntohl(*address);          const u32 ip = ntohl(*address);
597          bool found = false;          int error;
598          char buf[64];          char buf[64];
599            ccs_check_read_lock();
600          if (!ccs_can_sleep())          if (!ccs_can_sleep())
601                  return 0;                  return 0;
602          ccs_init_request_info(&r, NULL, CCS_TOMOYO_MAC_FOR_NETWORK);          ccs_init_request_info(&r, NULL, CCS_MAC_FOR_NETWORK);
603          is_enforce = (r.mode == 3);          is_enforce = (r.mode == 3);
604          if (!r.mode)          if (!r.mode)
605                  return 0;                  return 0;
606   retry:   retry:
607          list1_for_each_entry(ptr, &r.domain->acl_info_list, list) {          error = -EPERM;
608            list_for_each_entry_rcu(ptr, &r.domain->acl_info_list, list) {
609                  struct ccs_ip_network_acl_record *acl;                  struct ccs_ip_network_acl_record *acl;
610                  if (ccs_acl_type2(ptr) != TYPE_IP_NETWORK_ACL)                  if (ccs_acl_type2(ptr) != CCS_TYPE_IP_NETWORK_ACL)
611                          continue;                          continue;
612                  acl = container_of(ptr, struct ccs_ip_network_acl_record, head);                  acl = container_of(ptr, struct ccs_ip_network_acl_record, head);
613                  if (acl->operation_type != operation || port < acl->min_port ||                  if (acl->operation_type != operation)
                     acl->max_port < port || !ccs_check_condition(&r, ptr))  
614                          continue;                          continue;
615                  if (acl->record_type == IP_RECORD_TYPE_ADDRESS_GROUP) {                  if (!ccs_compare_number_union(port, &acl->port) ||
616                        !ccs_check_condition(&r, ptr))
617                            continue;
618                    if (acl->record_type == CCS_IP_RECORD_TYPE_ADDRESS_GROUP) {
619                          if (!ccs_address_matches_group(is_ipv6, address,                          if (!ccs_address_matches_group(is_ipv6, address,
620                                                         acl->u.group))                                                         acl->address.group))
621                                  continue;                                  continue;
622                  } else if (acl->record_type == IP_RECORD_TYPE_IPv4) {                  } else if (acl->record_type == CCS_IP_RECORD_TYPE_IPv4) {
623                          if (is_ipv6 ||                          if (is_ipv6 ||
624                              ip < acl->u.ipv4.min || acl->u.ipv4.max < ip)                              ip < acl->address.ipv4.min ||
625                                acl->address.ipv4.max < ip)
626                                  continue;                                  continue;
627                  } else {                  } else {
628                          if (!is_ipv6 ||                          if (!is_ipv6 ||
629                              memcmp(acl->u.ipv6.min, address, 16) > 0 ||                              memcmp(acl->address.ipv6.min, address, 16) > 0 ||
630                              memcmp(address, acl->u.ipv6.max, 16) > 0)                              memcmp(address, acl->address.ipv6.max, 16) > 0)
631                                  continue;                                  continue;
632                  }                  }
633                  r.cond = ccs_get_condition_part(ptr);                  r.cond = ptr->cond;
634                  found = true;                  error = 0;
635                  break;                  break;
636          }          }
637          memset(buf, 0, sizeof(buf));          memset(buf, 0, sizeof(buf));
# Line 648  static int ccs_check_network_entry(const Line 640  static int ccs_check_network_entry(const
640                                 (const struct in6_addr *) address);                                 (const struct in6_addr *) address);
641          else          else
642                  snprintf(buf, sizeof(buf) - 1, "%u.%u.%u.%u", HIPQUAD(ip));                  snprintf(buf, sizeof(buf) - 1, "%u.%u.%u.%u", HIPQUAD(ip));
643          ccs_audit_network_log(&r, keyword, buf, port, found);          ccs_audit_network_log(&r, keyword, buf, port, !error);
644          if (found)          if (error)
645                  return 0;                  error = ccs_check_supervisor(&r, CCS_KEYWORD_ALLOW_NETWORK
646          if (ccs_verbose_mode(r.domain))                                               "%s %s %u\n", keyword, buf, port);
647                  printk(KERN_WARNING "TOMOYO-%s: %s to %s %u denied for %s\n",          if (error == 1)
648                         ccs_get_msg(is_enforce), keyword, buf, port,                  goto retry;
649                         ccs_get_last_name(r.domain));          if (!is_enforce)
650          if (is_enforce) {                  error = 0;
651                  int error = ccs_check_supervisor(&r, KEYWORD_ALLOW_NETWORK          return error;
652                                                   "%s %s %u\n", keyword, buf,  }
653                                                   port);  
654                  if (error == 1)  /**
655                          goto retry;   * ccs_check_network_entry - Check permission for network operation.
656                  return error;   *
657          }   * @is_ipv6:   True if @address is an IPv6 address.
658          if (r.mode == 1 && ccs_check_domain_quota(r.domain))   * @operation: Type of operation.
659                  ccs_update_network_entry(operation, is_ipv6 ?   * @address:   An IPv4 or IPv6 address.
660                                           IP_RECORD_TYPE_IPv6 :   * @port:      Port number.
661                                           IP_RECORD_TYPE_IPv4,   *
662                                           NULL, address, address, port, port,   * Returns 0 on success, negative value otherwise.
663                                           r.domain, ccs_handler_cond(), 0);   */
664          return 0;  static int ccs_check_network_entry(const bool is_ipv6, const u8 operation,
665                                       const u32 *address, const u16 port)
666    {
667            const int idx = ccs_read_lock();
668            const int error = ccs_check_network_entry2(is_ipv6, operation,
669                                                       address, port);
670            ccs_read_unlock(idx);
671            return error;
672  }  }
673    
674  /**  /**
675   * ccs_write_network_policy - Write "struct ccs_ip_network_acl_record" list.   * ccs_write_network_policy - Write "struct ccs_ip_network_acl_record" list.
676   *   *
677   * @data:      String to parse.   * @data:      String to parse.
678   * @domain:    Pointer to "struct domain_info".   * @domain:    Pointer to "struct ccs_domain_info".
679   * @condition: Pointer to "struct ccs_condition_list". May be NULL.   * @condition: Pointer to "struct ccs_condition". May be NULL.
680   * @is_delete: True if it is a delete request.   * @is_delete: True if it is a delete request.
681   *   *
682   * Returns 0 on success, negative value otherwise.   * Returns 0 on success, negative value otherwise.
683   */   */
684  int ccs_write_network_policy(char *data, struct domain_info *domain,  int ccs_write_network_policy(char *data, struct ccs_domain_info *domain,
685                               const struct ccs_condition_list *condition,                               struct ccs_condition *condition,
686                               const bool is_delete)                               const bool is_delete)
687  {  {
688          u8 sock_type;          char *w[4];
689          u8 operation;          if (!ccs_tokenize(data, w, sizeof(w)) || !w[3][0])
690          u8 record_type;                  return -EINVAL;
691          u16 min_address[8];          return ccs_update_network_entry(w[0], w[1], w[2], w[3], domain,
692          u16 max_address[8];                                          condition, is_delete);
         struct ccs_address_group_entry *group = NULL;  
         u16 min_port;  
         u16 max_port;  
         u8 count;  
         char *cp1 = strchr(data, ' ');  
         char *cp2;  
         if (!cp1)  
                 goto out;  
         cp1++;  
         if (!strncmp(data, "TCP ", 4))  
                 sock_type = SOCK_STREAM;  
         else if (!strncmp(data, "UDP ", 4))  
                 sock_type = SOCK_DGRAM;  
         else if (!strncmp(data, "RAW ", 4))  
                 sock_type = SOCK_RAW;  
         else  
                 goto out;  
         cp2 = strchr(cp1, ' ');  
         if (!cp2)  
                 goto out;  
         cp2++;  
         if (!strncmp(cp1, "bind ", 5))  
                 switch (sock_type) {  
                 case SOCK_STREAM:  
                         operation = NETWORK_ACL_TCP_BIND;  
                         break;  
                 case SOCK_DGRAM:  
                         operation = NETWORK_ACL_UDP_BIND;  
                         break;  
                 default:  
                         operation = NETWORK_ACL_RAW_BIND;  
                 }  
         else if (!strncmp(cp1, "connect ", 8))  
                 switch (sock_type) {  
                 case SOCK_STREAM:  
                         operation = NETWORK_ACL_TCP_CONNECT;  
                         break;  
                 case SOCK_DGRAM:  
                         operation = NETWORK_ACL_UDP_CONNECT;  
                         break;  
                 default:  
                         operation = NETWORK_ACL_RAW_CONNECT;  
                 }  
         else if (sock_type == SOCK_STREAM && !strncmp(cp1, "listen ", 7))  
                 operation = NETWORK_ACL_TCP_LISTEN;  
         else if (sock_type == SOCK_STREAM && !strncmp(cp1, "accept ", 7))  
                 operation = NETWORK_ACL_TCP_ACCEPT;  
         else  
                 goto out;  
         cp1 = strchr(cp2, ' ');  
         if (!cp1)  
                 goto out;  
         *cp1++ = '\0';  
         switch (ccs_parse_ip_address(cp2, min_address, max_address)) {  
         case 2:  
                 record_type = IP_RECORD_TYPE_IPv6;  
                 break;  
         case 1:  
                 record_type = IP_RECORD_TYPE_IPv4;  
                 break;  
         default:  
                 if (*cp2 != '@')  
                         goto out;  
                 group = ccs_find_or_assign_new_address_group(cp2 + 1);  
                 if (!group)  
                         return -ENOMEM;  
                 record_type = IP_RECORD_TYPE_ADDRESS_GROUP;  
                 break;  
         }  
         if (strchr(cp1, ' '))  
                 goto out;  
         count = sscanf(cp1, "%hu-%hu", &min_port, &max_port);  
         if (count != 1 && count != 2)  
                 goto out;  
         if (count == 1)  
                 max_port = min_port;  
         return ccs_update_network_entry(operation, record_type, group,  
                                         (u32 *) min_address,  
                                         (u32 *) max_address,  
                                         min_port, max_port, domain, condition,  
                                         is_delete);  
  out:  
         return -EINVAL;  
693  }  }
694    
695  /**  /**
# Line 789  static inline int ccs_check_network_list Line 705  static inline int ccs_check_network_list
705                                                 const u8 *address,                                                 const u8 *address,
706                                                 const u16 port)                                                 const u16 port)
707  {  {
708          return ccs_check_network_entry(is_ipv6, NETWORK_ACL_TCP_LISTEN,          return ccs_check_network_entry(is_ipv6, CCS_NETWORK_ACL_TCP_LISTEN,
709                                         (const u32 *) address, ntohs(port));                                         (const u32 *) address, ntohs(port));
710  }  }
711    
# Line 811  static inline int ccs_check_network_conn Line 727  static inline int ccs_check_network_conn
727          u8 operation;          u8 operation;
728          switch (sock_type) {          switch (sock_type) {
729          case SOCK_STREAM:          case SOCK_STREAM:
730                  operation = NETWORK_ACL_TCP_CONNECT;                  operation = CCS_NETWORK_ACL_TCP_CONNECT;
731                  break;                  break;
732          case SOCK_DGRAM:          case SOCK_DGRAM:
733                  operation = NETWORK_ACL_UDP_CONNECT;                  operation = CCS_NETWORK_ACL_UDP_CONNECT;
734                  break;                  break;
735          default:          default:
736                  operation = NETWORK_ACL_RAW_CONNECT;                  operation = CCS_NETWORK_ACL_RAW_CONNECT;
737          }          }
738          return ccs_check_network_entry(is_ipv6, operation,          return ccs_check_network_entry(is_ipv6, operation,
739                                         (const u32 *) address, ntohs(port));                                         (const u32 *) address, ntohs(port));
# Line 839  static int ccs_check_network_bind_acl(co Line 755  static int ccs_check_network_bind_acl(co
755          u8 operation;          u8 operation;
756          switch (sock_type) {          switch (sock_type) {
757          case SOCK_STREAM:          case SOCK_STREAM:
758                  operation = NETWORK_ACL_TCP_BIND;                  operation = CCS_NETWORK_ACL_TCP_BIND;
759                  break;                  break;
760          case SOCK_DGRAM:          case SOCK_DGRAM:
761                  operation = NETWORK_ACL_UDP_BIND;                  operation = CCS_NETWORK_ACL_UDP_BIND;
762                  break;                  break;
763          default:          default:
764                  operation = NETWORK_ACL_RAW_BIND;                  operation = CCS_NETWORK_ACL_RAW_BIND;
765          }          }
766          return ccs_check_network_entry(is_ipv6, operation,          return ccs_check_network_entry(is_ipv6, operation,
767                                         (const u32 *) address, ntohs(port));                                         (const u32 *) address, ntohs(port));
# Line 865  static inline int ccs_check_network_acce Line 781  static inline int ccs_check_network_acce
781                                                 const u16 port)                                                 const u16 port)
782  {  {
783          int retval;          int retval;
784          current->tomoyo_flags |= CCS_DONT_SLEEP_ON_ENFORCE_ERROR;          current->ccs_flags |= CCS_DONT_SLEEP_ON_ENFORCE_ERROR;
785          retval = ccs_check_network_entry(is_ipv6, NETWORK_ACL_TCP_ACCEPT,          retval = ccs_check_network_entry(is_ipv6, CCS_NETWORK_ACL_TCP_ACCEPT,
786                                           (const u32 *) address, ntohs(port));                                           (const u32 *) address, ntohs(port));
787          current->tomoyo_flags &= ~CCS_DONT_SLEEP_ON_ENFORCE_ERROR;          current->ccs_flags &= ~CCS_DONT_SLEEP_ON_ENFORCE_ERROR;
788          return retval;          return retval;
789  }  }
790    
# Line 889  static inline int ccs_check_network_send Line 805  static inline int ccs_check_network_send
805  {  {
806          u8 operation;          u8 operation;
807          if (sock_type == SOCK_DGRAM)          if (sock_type == SOCK_DGRAM)
808                  operation = NETWORK_ACL_UDP_CONNECT;                  operation = CCS_NETWORK_ACL_UDP_CONNECT;
809          else          else
810                  operation = NETWORK_ACL_RAW_CONNECT;                  operation = CCS_NETWORK_ACL_RAW_CONNECT;
811          return ccs_check_network_entry(is_ipv6, operation,          return ccs_check_network_entry(is_ipv6, operation,
812                                         (const u32 *) address, ntohs(port));                                         (const u32 *) address, ntohs(port));
813  }  }
# Line 914  static inline int ccs_check_network_recv Line 830  static inline int ccs_check_network_recv
830          int retval;          int retval;
831          const u8 operation          const u8 operation
832                  = (sock_type == SOCK_DGRAM) ?                  = (sock_type == SOCK_DGRAM) ?
833                  NETWORK_ACL_UDP_CONNECT : NETWORK_ACL_RAW_CONNECT;                  CCS_NETWORK_ACL_UDP_CONNECT : CCS_NETWORK_ACL_RAW_CONNECT;
834          current->tomoyo_flags |= CCS_DONT_SLEEP_ON_ENFORCE_ERROR;          current->ccs_flags |= CCS_DONT_SLEEP_ON_ENFORCE_ERROR;
835          retval = ccs_check_network_entry(is_ipv6, operation,          retval = ccs_check_network_entry(is_ipv6, operation,
836                                           (const u32 *) address, ntohs(port));                                           (const u32 *) address, ntohs(port));
837          current->tomoyo_flags &= ~CCS_DONT_SLEEP_ON_ENFORCE_ERROR;          current->ccs_flags &= ~CCS_DONT_SLEEP_ON_ENFORCE_ERROR;
838          return retval;          return retval;
839  }  }
840    
# Line 931  int ccs_socket_create_permission(int fam Line 847  int ccs_socket_create_permission(int fam
847          /* Nothing to do if I am a kernel service. */          /* Nothing to do if I am a kernel service. */
848          if (segment_eq(get_fs(), KERNEL_DS))          if (segment_eq(get_fs(), KERNEL_DS))
849                  return 0;                  return 0;
850          if (family == PF_PACKET && !ccs_capable(TOMOYO_USE_PACKET_SOCKET))          if (family == PF_PACKET && !ccs_capable(CCS_USE_PACKET_SOCKET))
851                  return -EPERM;                  return -EPERM;
852          if (family == PF_ROUTE && !ccs_capable(TOMOYO_USE_ROUTE_SOCKET))          if (family == PF_ROUTE && !ccs_capable(CCS_USE_ROUTE_SOCKET))
853                  return -EPERM;                  return -EPERM;
854          if (family != PF_INET && family != PF_INET6)          if (family != PF_INET && family != PF_INET6)
855                  return 0;                  return 0;
856          switch (type) {          switch (type) {
857          case SOCK_STREAM:          case SOCK_STREAM:
858                  if (!ccs_capable(TOMOYO_INET_STREAM_SOCKET_CREATE))                  if (!ccs_capable(CCS_INET_STREAM_SOCKET_CREATE))
859                          error = -EPERM;                          error = -EPERM;
860                  break;                  break;
861          case SOCK_DGRAM:          case SOCK_DGRAM:
862                  if (!ccs_capable(TOMOYO_USE_INET_DGRAM_SOCKET))                  if (!ccs_capable(CCS_USE_INET_DGRAM_SOCKET))
863                          error = -EPERM;                          error = -EPERM;
864                  break;                  break;
865          case SOCK_RAW:          case SOCK_RAW:
866                  if (!ccs_capable(TOMOYO_USE_INET_RAW_SOCKET))                  if (!ccs_capable(CCS_USE_INET_RAW_SOCKET))
867                          error = -EPERM;                          error = -EPERM;
868                  break;                  break;
869          }          }
# Line 972  int ccs_socket_listen_permission(struct Line 888  int ccs_socket_listen_permission(struct
888          default:          default:
889                  return 0;                  return 0;
890          }          }
891          if (!ccs_capable(TOMOYO_INET_STREAM_SOCKET_LISTEN))          if (!ccs_capable(CCS_INET_STREAM_SOCKET_LISTEN))
892                  return -EPERM;                  return -EPERM;
893          if (sock->ops->getname(sock, (struct sockaddr *) addr, &addr_len, 0))          if (sock->ops->getname(sock, (struct sockaddr *) addr, &addr_len, 0))
894                  return -EPERM;                  return -EPERM;
# Line 1046  int ccs_socket_connect_permission(struct Line 962  int ccs_socket_connect_permission(struct
962          switch (sock->sk->sk_family) {          switch (sock->sk->sk_family) {
963          case PF_INET:          case PF_INET:
964          case PF_INET6:          case PF_INET6:
965                  if (!ccs_capable(TOMOYO_INET_STREAM_SOCKET_CONNECT))                  if (!ccs_capable(CCS_INET_STREAM_SOCKET_CONNECT))
966                          error = -EPERM;                          error = -EPERM;
967                  break;                  break;
968          }          }
# Line 1207  static inline struct ipv6hdr *ipv6_hdr(c Line 1123  static inline struct ipv6hdr *ipv6_hdr(c
1123  #endif  #endif
1124  #endif  #endif
1125    
1126    #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 12)
1127    static void skb_kill_datagram(struct sock *sk, struct sk_buff *skb,
1128                                  unsigned int flags)
1129    {
1130            /* Clear queue. */
1131            if (flags & MSG_PEEK) {
1132                    int clear = 0;
1133                    spin_lock_irq(&sk->sk_receive_queue.lock);
1134                    if (skb == skb_peek(&sk->sk_receive_queue)) {
1135                            __skb_unlink(skb, &sk->sk_receive_queue);
1136                            clear = 1;
1137                    }
1138                    spin_unlock_irq(&sk->sk_receive_queue.lock);
1139                    if (clear)
1140                            kfree_skb(skb);
1141            }
1142            skb_free_datagram(sk, skb);
1143    }
1144    #elif LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 16)
1145    static void skb_kill_datagram(struct sock *sk, struct sk_buff *skb,
1146                                  unsigned int flags)
1147    {
1148            /* Clear queue. */
1149            if (flags & MSG_PEEK) {
1150                    int clear = 0;
1151                    spin_lock_bh(&sk->sk_receive_queue.lock);
1152                    if (skb == skb_peek(&sk->sk_receive_queue)) {
1153                            __skb_unlink(skb, &sk->sk_receive_queue);
1154                            clear = 1;
1155                    }
1156                    spin_unlock_bh(&sk->sk_receive_queue.lock);
1157                    if (clear)
1158                            kfree_skb(skb);
1159            }
1160            skb_free_datagram(sk, skb);
1161    }
1162    #endif
1163    
1164  /*  /*
1165   * Check permission for receiving a datagram via a UDP or RAW socket.   * Check permission for receiving a datagram via a UDP or RAW socket.
1166   *   *
1167   * Currently, the LSM hook for this purpose is not provided.   * Currently, the LSM hook for this purpose is not provided.
1168   */   */
1169  int ccs_socket_recv_datagram_permission(struct sock *sk, struct sk_buff *skb,  int ccs_socket_recvmsg_permission(struct sock *sk, struct sk_buff *skb,
1170                                          const unsigned int flags)                                    const unsigned int flags)
1171  {  {
1172          int error = 0;          int error = 0;
1173          const unsigned int type = sk->sk_type;          const unsigned int type = sk->sk_type;
1174          /* Nothing to do if I didn't receive a datagram. */          if (type != SOCK_DGRAM && type != SOCK_RAW)
         if (!skb)  
                 return 0;  
         /* Nothing to do if I can't sleep. */  
 #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 5, 0)  
         if (in_interrupt())  
                 return 0;  
 #else  
         if (in_atomic())  
1175                  return 0;                  return 0;
 #endif  
1176          /* Nothing to do if I am a kernel service. */          /* Nothing to do if I am a kernel service. */
1177          if (segment_eq(get_fs(), KERNEL_DS))          if (segment_eq(get_fs(), KERNEL_DS))
1178                  return 0;                  return 0;
         if (type != SOCK_DGRAM && type != SOCK_RAW)  
                 return 0;  
1179    
1180          switch (sk->sk_family) {          switch (sk->sk_family) {
1181                  struct in6_addr sin6;                  struct in6_addr sin6;
# Line 1268  int ccs_socket_recv_datagram_permission( Line 1211  int ccs_socket_recv_datagram_permission(
1211          }          }
1212          if (!error)          if (!error)
1213                  return 0;                  return 0;
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)  
         lock_sock(sk);  
 #endif  
1214          /*          /*
1215           * Remove from queue if MSG_PEEK is used so that           * Remove from queue if MSG_PEEK is used so that
1216           * the head message from unwanted source in receive queue will not           * the head message from unwanted source in receive queue will not
1217           * prevent the caller from picking up next message from wanted source           * prevent the caller from picking up next message from wanted source
1218           * when the caller is using MSG_PEEK flag for picking up.           * when the caller is using MSG_PEEK flag for picking up.
1219           */           */
         if (flags & MSG_PEEK) {  
                 unsigned long cpu_flags;  
                 /***** CRITICAL SECTION START *****/  
                 spin_lock_irqsave(&sk->sk_receive_queue.lock, cpu_flags);  
                 if (skb == skb_peek(&sk->sk_receive_queue)) {  
                         __skb_unlink(skb, &sk->sk_receive_queue);  
                         atomic_dec(&skb->users);  
                 }  
                 spin_unlock_irqrestore(&sk->sk_receive_queue.lock, cpu_flags);  
                 /***** CRITICAL SECTION END *****/  
         }  
         /* Drop reference count. */  
         skb_free_datagram(sk, skb);  
1220  #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)  #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)
1221          release_sock(sk);          if (type == SOCK_DGRAM)
1222                    lock_sock(sk);
1223    #endif
1224            skb_kill_datagram(sk, skb, flags);
1225    #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)
1226            if (type == SOCK_DGRAM)
1227                    release_sock(sk);
1228  #endif  #endif
1229          /* Hope less harmful than -EPERM. */          /* Hope less harmful than -EPERM. */
1230          return -EAGAIN;          return -ENOMEM;
1231  }  }
1232    EXPORT_SYMBOL(ccs_socket_recvmsg_permission);

Legend:
Removed from v.2039  
changed lines
  Added in v.2897

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