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

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.5.x/ccs-patch/fs/tomoyo_network.c revision 853 by kumaneko, Wed Jan 2 07:32:11 2008 UTC branches/ccs-patch/fs/tomoyo_network.c revision 2727 by kumaneko, Fri Jul 3 14:06:48 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.5.3-pre   2008/01/02   * Version: 1.7.0-pre   2009/07/03
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.
12   *   *
13   */   */
 /***** TOMOYO Linux start. *****/  
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>
20    #include <linux/inet.h>
21    #include <linux/in.h>
22    #include <linux/in6.h>
23  #include <net/ip.h>  #include <net/ip.h>
24    #include <net/ipv6.h>
25    #include <net/udp.h>
26    
27  /*************************  VARIABLES  *************************/  /* 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  extern struct mutex domain_acl_lock;  /**
40     * ccs_audit_network_log - Audit network log.
41     *
42     * @r:          Pointer to "struct ccs_request_info".
43     * @operation:  The name of operation.
44     * @address:    An IPv4 or IPv6 address.
45     * @port:       Port number.
46     * @is_granted: True if this is a granted log.
47     *
48     * Returns 0 on success, negative value otherwise.
49     */
50    static int ccs_audit_network_log(struct ccs_request_info *r,
51                                     const char *operation, const char *address,
52                                     const u16 port, const bool is_granted)
53    {
54            return ccs_write_audit_log(is_granted, r, KEYWORD_ALLOW_NETWORK
55                                       "%s %s %u\n", operation, address, port);
56    }
57    
58  /*************************  AUDIT FUNCTIONS  *************************/  /* The list for "struct ccs_address_group_entry". */
59    LIST_HEAD(ccs_address_group_list);
60    
61  static int AuditNetworkLog(const bool is_ipv6, const char *operation, const u32 *address, const u16 port, const bool is_granted, const u8 profile, const u8 mode)  /**
62     * ccs_get_address_group - Allocate memory for "struct ccs_address_group_entry".
63     *
64     * @group_name: The name of address group.
65     *
66     * Returns pointer to "struct ccs_address_group_entry" on success,
67     * NULL otherwise.
68     */
69    static struct ccs_address_group_entry *ccs_get_address_group(const char *
70                                                                 group_name)
71  {  {
72          char *buf;          struct ccs_address_group_entry *entry = NULL;
73          int len = 256;          struct ccs_address_group_entry *group;
74          if (CanSaveAuditLog(is_granted) < 0) return -ENOMEM;          const struct ccs_path_info *saved_group_name;
         if ((buf = InitAuditLog(&len, profile, mode)) == NULL) return -ENOMEM;  
         snprintf(buf + strlen(buf), len - strlen(buf) - 1, KEYWORD_ALLOW_NETWORK "%s ", operation);  
         if (is_ipv6) {  
                 print_ipv6(buf + strlen(buf), len - strlen(buf), (const struct in6_addr *) address);  
         } else {  
                 u32 ip = *address;  
                 snprintf(buf + strlen(buf), len - strlen(buf) - 1, "%u.%u.%u.%u", NIPQUAD(ip));  
         }  
         snprintf(buf + strlen(buf), len - strlen(buf) - 1, " %u\n", port);  
         return WriteAuditLog(buf, is_granted);  
 }  
   
 /*************************  UTILITY FUNCTIONS  *************************/  
   
 /* Keep the given IPv6 address on the RAM. The RAM is shared, so NEVER try to modify or kfree() the returned address. */  
 static const struct in6_addr *SaveIPv6Address(const struct in6_addr *addr)  
 {  
         static const u8 block_size = 16;  
         struct addr_list {  
                 struct in6_addr addr[block_size];  
                 struct list1_head list;  
                 u32 in_use_count;  
         };  
         static LIST1_HEAD(address_list);  
         struct addr_list *ptr;  
         static DEFINE_MUTEX(lock);  
         u8 i = block_size;  
         if (!addr) return NULL;  
         mutex_lock(&lock);  
         list1_for_each_entry(ptr, &address_list, list) {  
                 for (i = 0; i < ptr->in_use_count; i++) {  
                         if (memcmp(&ptr->addr[i], addr, sizeof(*addr)) == 0) goto ok;  
                 }  
                 if (i < block_size) break;  
         }  
         if (i == block_size) {  
                 ptr = alloc_element(sizeof(*ptr));  
                 if (!ptr) goto ok;  
                 list1_add_tail_mb(&ptr->list, &address_list);  
                 i = 0;  
         }  
         ptr->addr[ptr->in_use_count++] = *addr;  
 ok:  
         mutex_unlock(&lock);  
         return ptr ? &ptr->addr[i] : NULL;  
 }  
   
 /*************************  ADDRESS GROUP HANDLER  *************************/  
   
 static LIST1_HEAD(address_group_list);  
   
 static int AddAddressGroupEntry(const char *group_name, const bool is_ipv6, const u16 *min_address, const u16 *max_address, const bool is_delete)  
 {  
         static DEFINE_MUTEX(lock);  
         struct address_group_entry *new_group, *group;  
         struct address_group_member *new_member, *member;  
         const struct path_info *saved_group_name;  
         const struct in6_addr *saved_min_address = NULL, *saved_max_address = NULL;  
75          int error = -ENOMEM;          int error = -ENOMEM;
76          bool found = 0;          if (!ccs_is_correct_path(group_name, 0, 0, 0) ||
77          if (!IsCorrectPath(group_name, 0, 0, 0, __FUNCTION__) || !group_name[0]) return -EINVAL;              !group_name[0])
78          if ((saved_group_name = SaveName(group_name)) == NULL) return -ENOMEM;                  return NULL;
79          if (is_ipv6) {          saved_group_name = ccs_get_name(group_name);
80                  if ((saved_min_address = SaveIPv6Address((struct in6_addr *) min_address)) == NULL          if (!saved_group_name)
81                      || (saved_max_address = SaveIPv6Address((struct in6_addr *) max_address)) == NULL) return -ENOMEM;                  return NULL;
82            entry = kzalloc(sizeof(*entry), GFP_KERNEL);
83            mutex_lock(&ccs_policy_lock);
84            list_for_each_entry_rcu(group, &ccs_address_group_list, list) {
85                    if (saved_group_name != group->group_name)
86                            continue;
87                    atomic_inc(&group->users);
88                    error = 0;
89                    break;
90          }          }
91          mutex_lock(&lock);          if (error && ccs_memory_ok(entry, sizeof(*entry))) {
92          list1_for_each_entry(group, &address_group_list, list) {                  INIT_LIST_HEAD(&entry->address_group_member_list);
93                  if (saved_group_name != group->group_name) continue;                  entry->group_name = saved_group_name;
94                  list1_for_each_entry(member, &group->address_group_member_list, list) {                  saved_group_name = NULL;
95                          if (member->is_ipv6 != is_ipv6) continue;                  atomic_set(&entry->users, 1);
96                          if (is_ipv6) {                  list_add_tail_rcu(&entry->list, &ccs_address_group_list);
97                                  if (member->min.ipv6 != saved_min_address || member->max.ipv6 != saved_max_address) continue;                  group = entry;
98                          } else {                  entry = NULL;
99                                  if (member->min.ipv4 != * (u32 *) min_address || member->max.ipv4 != * (u32 *) max_address) continue;                  error = 0;
100                          }          }
101                          member->is_deleted = is_delete;          mutex_unlock(&ccs_policy_lock);
102                          error = 0;          ccs_put_name(saved_group_name);
103            kfree(entry);
104            return !error ? group : NULL;
105    }
106    
107    /**
108     * ccs_update_address_group_entry - Update "struct ccs_address_group_entry" list.
109     *
110     * @group_name:  The name of address group.
111     * @is_ipv6:     True if @min_address and @max_address are IPv6 addresses.
112     * @min_address: Start of IPv4 or IPv6 address range.
113     * @max_address: End of IPv4 or IPv6 address range.
114     * @is_delete:   True if it is a delete request.
115     *
116     * Returns 0 on success, negative value otherwise.
117     */
118    static int ccs_update_address_group_entry(const char *group_name,
119                                              const bool is_ipv6,
120                                              const u16 *min_address,
121                                              const u16 *max_address,
122                                              const bool is_delete)
123    {
124            struct ccs_address_group_entry *group;
125            struct ccs_address_group_member *entry = NULL;
126            struct ccs_address_group_member *member;
127            const struct in6_addr *saved_min_address = NULL;
128            const struct in6_addr *saved_max_address = NULL;
129            int error = is_delete ? -ENOENT : -ENOMEM;
130            const u32 min_ipv4_address = ntohl(*(u32 *) min_address);
131            const u32 max_ipv4_address = ntohl(*(u32 *) max_address);
132            group = ccs_get_address_group(group_name);
133            if (!group)
134                    return -ENOMEM;
135            if (is_ipv6) {
136                    saved_min_address
137                            = ccs_get_ipv6_address((struct in6_addr *)
138                                                   min_address);
139                    saved_max_address
140                            = ccs_get_ipv6_address((struct in6_addr *)
141                                                   max_address);
142                    if (!saved_min_address || !saved_max_address)
143                          goto out;                          goto out;
144            }
145            if (!is_delete)
146                    entry = kzalloc(sizeof(*entry), GFP_KERNEL);
147            mutex_lock(&ccs_policy_lock);
148            list_for_each_entry_rcu(member, &group->address_group_member_list,
149                                    list) {
150                    if (member->is_ipv6 != is_ipv6)
151                            continue;
152                    if (is_ipv6) {
153                            if (member->min.ipv6 != saved_min_address ||
154                                member->max.ipv6 != saved_max_address)
155                                    continue;
156                    } else {
157                            if (member->min.ipv4 != min_ipv4_address ||
158                                member->max.ipv4 != max_ipv4_address)
159                                    continue;
160                  }                  }
161                  found = 1;                  member->is_deleted = is_delete;
162                    error = 0;
163                  break;                  break;
164          }          }
165          if (is_delete) {          if (!is_delete && error && ccs_memory_ok(entry, sizeof(*entry))) {
166                  error = -ENOENT;                  entry->is_ipv6 = is_ipv6;
167                  goto out;                  if (is_ipv6) {
168          }                          entry->min.ipv6 = saved_min_address;
169          if (!found) {                          saved_min_address = NULL;
170                  if ((new_group = alloc_element(sizeof(*new_group))) == NULL) goto out;                          entry->max.ipv6 = saved_max_address;
171                  INIT_LIST1_HEAD(&new_group->address_group_member_list);                          saved_max_address = NULL;
172                  new_group->group_name = saved_group_name;                  } else {
173                  list1_add_tail_mb(&new_group->list, &address_group_list);                          entry->min.ipv4 = min_ipv4_address;
174                  group = new_group;                          entry->max.ipv4 = max_ipv4_address;
175          }                  }
176          if ((new_member = alloc_element(sizeof(*new_member))) == NULL) goto out;                  list_add_tail_rcu(&entry->list,
177          new_member->is_ipv6 = is_ipv6;                                    &group->address_group_member_list);
178          if (is_ipv6) {                  entry = NULL;
179                  new_member->min.ipv6 = saved_min_address;                  error = 0;
                 new_member->max.ipv6 = saved_max_address;  
         } else {  
                 new_member->min.ipv4 = * (u32 *) min_address;  
                 new_member->max.ipv4 = * (u32 *) max_address;  
180          }          }
181          list1_add_tail_mb(&new_member->list, &group->address_group_member_list);          mutex_unlock(&ccs_policy_lock);
         error = 0;  
182   out:   out:
183          mutex_unlock(&lock);          ccs_put_ipv6_address(saved_min_address);
184            ccs_put_ipv6_address(saved_max_address);
185            ccs_put_address_group(group);
186          return error;          return error;
187  }  }
188    
189  int AddAddressGroupPolicy(char *data, const bool is_delete)  /**
190     * ccs_parse_ip_address - Parse an IP address.
191     *
192     * @address: String to parse.
193     * @min:     Pointer to store min address.
194     * @max:     Pointer to store max address.
195     *
196     * Returns 2 if @address is an IPv6, 1 if @address is an IPv4, 0 otherwise.
197     */
198    static int ccs_parse_ip_address(char *address, u16 *min, u16 *max)
199  {  {
200          u8 count;          int count = sscanf(address, "%hx:%hx:%hx:%hx:%hx:%hx:%hx:%hx"
201          bool is_ipv6;                             "-%hx:%hx:%hx:%hx:%hx:%hx:%hx:%hx",
202          u16 min_address[8], max_address[8];                             &min[0], &min[1], &min[2], &min[3],
203          char *cp = strchr(data, ' ');                             &min[4], &min[5], &min[6], &min[7],
204          if (!cp) return -EINVAL;                             &max[0], &max[1], &max[2], &max[3],
205          *cp++ = '\0';                             &max[4], &max[5], &max[6], &max[7]);
206          if ((count = sscanf(cp, "%hx:%hx:%hx:%hx:%hx:%hx:%hx:%hx-%hx:%hx:%hx:%hx:%hx:%hx:%hx:%hx",          if (count == 8 || count == 16) {
                             &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])) == 8 || count == 16) {  
207                  u8 i;                  u8 i;
208                    if (count == 8)
209                            memmove(max, min, sizeof(u16) * 8);
210                  for (i = 0; i < 8; i++) {                  for (i = 0; i < 8; i++) {
211                          min_address[i] = htons(min_address[i]);                          min[i] = htons(min[i]);
212                          max_address[i] = htons(max_address[i]);                          max[i] = htons(max[i]);
213                  }                  }
214                  if (count == 8) memmove(max_address, min_address, sizeof(min_address));                  return 2;
215                  is_ipv6 = 1;          }
216          } else if ((count = sscanf(cp, "%hu.%hu.%hu.%hu-%hu.%hu.%hu.%hu",          count = sscanf(address, "%hu.%hu.%hu.%hu-%hu.%hu.%hu.%hu",
217                                     &min_address[0], &min_address[1], &min_address[2], &min_address[3],                         &min[0], &min[1], &min[2], &min[3],
218                                     &max_address[0], &max_address[1], &max_address[2], &max_address[3])) == 4 || count == 8) {                         &max[0], &max[1], &max[2], &max[3]);
219                  u32 ip = ((((u8) min_address[0]) << 24) + (((u8) min_address[1]) << 16) + (((u8) min_address[2]) << 8) + (u8) min_address[3]);          if (count == 4 || count == 8) {
220                  * (u32 *) min_address = ip;                  u32 ip = htonl((((u8) min[0]) << 24) + (((u8) min[1]) << 16)
221                  if (count == 8) ip = ((((u8) max_address[0]) << 24) + (((u8) max_address[1]) << 16) + (((u8) max_address[2]) << 8) + (u8) max_address[3]);                                 + (((u8) min[2]) << 8) + (u8) min[3]);
222                  * (u32 *) max_address = ip;                  memmove(min, &ip, sizeof(ip));
223                  is_ipv6 = 0;                  if (count == 8)
224          } else {                          ip = htonl((((u8) max[0]) << 24) + (((u8) max[1]) << 16)
225                  return -EINVAL;                                     + (((u8) max[2]) << 8) + (u8) max[3]);
226                    memmove(max, &ip, sizeof(ip));
227                    return 1;
228          }          }
229          return AddAddressGroupEntry(data, is_ipv6, min_address, max_address, is_delete);          return 0;
230  }  }
231    
232  static struct address_group_entry *FindOrAssignNewAddressGroup(const char *group_name)  /**
233     * ccs_write_address_group_policy - Write "struct ccs_address_group_entry" list.
234     *
235     * @data:      String to parse.
236     * @is_delete: True if it is a delete request.
237     *
238     * Returns 0 on success, negative value otherwise.
239     */
240    int ccs_write_address_group_policy(char *data, const bool is_delete)
241  {  {
242          u8 i;          bool is_ipv6;
243          struct address_group_entry *group;          u16 min_address[8];
244          for (i = 0; i <= 1; i++) {          u16 max_address[8];
245                  list1_for_each_entry(group, &address_group_list, list) {          char *cp = strchr(data, ' ');
246                          if (strcmp(group_name, group->group_name->name) == 0) return group;          if (!cp)
247                  }                  return -EINVAL;
248                  if (i == 0) {          *cp++ = '\0';
249                          const u16 dummy[2] = { 0, 0 };          switch (ccs_parse_ip_address(cp, min_address, max_address)) {
250                          AddAddressGroupEntry(group_name, 0, dummy, dummy, 0);          case 2:
251                          AddAddressGroupEntry(group_name, 0, dummy, dummy, 1);                  is_ipv6 = true;
252                  }                  break;
253            case 1:
254                    is_ipv6 = false;
255                    break;
256            default:
257                    return -EINVAL;
258          }          }
259          return NULL;          return ccs_update_address_group_entry(data, is_ipv6, min_address,
260                                                  max_address, is_delete);
261  }  }
262    
263  static bool AddressMatchesToGroup(const bool is_ipv6, const u32 *address, const struct address_group_entry *group)  /**
264     * ccs_address_matches_group - Check whether the given address matches members of the given address group.
265     *
266     * @is_ipv6: True if @address is an IPv6 address.
267     * @address: An IPv4 or IPv6 address.
268     * @group:   Pointer to "struct ccs_address_group_entry".
269     *
270     * Returns true if @address matches addresses in @group group, false otherwise.
271     *
272     * Caller holds srcu_read_lock(&ccs_ss).
273     */
274    static bool ccs_address_matches_group(const bool is_ipv6, const u32 *address,
275                                          const struct ccs_address_group_entry *
276                                          group)
277  {  {
278          struct address_group_member *member;          struct ccs_address_group_member *member;
279          const u32 ip = ntohl(*address);          const u32 ip = ntohl(*address);
280          list1_for_each_entry(member, &group->address_group_member_list, list) {          bool matched = false;
281                  if (member->is_deleted) continue;          list_for_each_entry_rcu(member, &group->address_group_member_list,
282                                    list) {
283                    if (member->is_deleted)
284                            continue;
285                  if (member->is_ipv6) {                  if (member->is_ipv6) {
286                          if (is_ipv6 && memcmp(member->min.ipv6, address, 16) <= 0 && memcmp(address, member->max.ipv6, 16) <= 0) return 1;                          if (is_ipv6 &&
287                                memcmp(member->min.ipv6, address, 16) <= 0 &&
288                                memcmp(address, member->max.ipv6, 16) <= 0) {
289                                    matched = true;
290                                    break;
291                            }
292                  } else {                  } else {
293                          if (!is_ipv6 && member->min.ipv4 <= ip && ip <= member->max.ipv4) return 1;                          if (!is_ipv6 &&
294                                member->min.ipv4 <= ip && ip <= member->max.ipv4) {
295                                    matched = true;
296                                    break;
297                            }
298                  }                  }
299          }          }
300          return 0;          return matched;
301  }  }
302    
303  int ReadAddressGroupPolicy(struct io_buffer *head)  /**
304     * ccs_read_address_group_policy - Read "struct ccs_address_group_entry" list.
305     *
306     * @head: Pointer to "struct ccs_io_buffer".
307     *
308     * Returns true on success, false otherwise.
309     *
310     * Caller holds srcu_read_lock(&ccs_ss).
311     */
312    bool ccs_read_address_group_policy(struct ccs_io_buffer *head)
313  {  {
314          struct list1_head *gpos;          struct list_head *gpos;
315          struct list1_head *mpos;          struct list_head *mpos;
316          list1_for_each_cookie(gpos, head->read_var1, &address_group_list) {          bool done = true;
317                  struct address_group_entry *group;          list_for_each_cookie(gpos, head->read_var1, &ccs_address_group_list) {
318                  group = list1_entry(gpos, struct address_group_entry, list);                  struct ccs_address_group_entry *group;
319                  list1_for_each_cookie(mpos, head->read_var2, &group->address_group_member_list) {                  group = list_entry(gpos, struct ccs_address_group_entry, list);
320                    list_for_each_cookie(mpos, head->read_var2,
321                                         &group->address_group_member_list) {
322                          char buf[128];                          char buf[128];
323                          struct address_group_member *member;                          struct ccs_address_group_member *member;
324                          member = list1_entry(mpos, struct address_group_member, list);                          member = list_entry(mpos,
325                          if (member->is_deleted) continue;                                               struct ccs_address_group_member,
326                                                 list);
327                            if (member->is_deleted)
328                                    continue;
329                          if (member->is_ipv6) {                          if (member->is_ipv6) {
330                                  const struct in6_addr *min_address = member->min.ipv6, *max_address = member->max.ipv6;                                  const struct in6_addr *min_address
331                                  print_ipv6(buf, sizeof(buf), min_address);                                          = member->min.ipv6;
332                                    const struct in6_addr *max_address
333                                            = member->max.ipv6;
334                                    ccs_print_ipv6(buf, sizeof(buf), min_address);
335                                  if (min_address != max_address) {                                  if (min_address != max_address) {
336                                          char *cp = strchr(buf, '\0');                                          int len;
337                                            char *cp = buf + strlen(buf);
338                                          *cp++ = '-';                                          *cp++ = '-';
339                                          print_ipv6(cp, sizeof(buf) - strlen(buf), max_address);                                          len = strlen(buf);
340                                            ccs_print_ipv6(cp, sizeof(buf) - len,
341                                                           max_address);
342                                  }                                  }
343                          } else {                          } else {
344                                  const u32 min_address = member->min.ipv4, max_address = member->max.ipv4;                                  const u32 min_address = member->min.ipv4;
345                                    const u32 max_address = member->max.ipv4;
346                                  memset(buf, 0, sizeof(buf));                                  memset(buf, 0, sizeof(buf));
347                                  snprintf(buf, sizeof(buf) - 1, "%u.%u.%u.%u", HIPQUAD(min_address));                                  snprintf(buf, sizeof(buf) - 1, "%u.%u.%u.%u",
348                                             HIPQUAD(min_address));
349                                  if (min_address != max_address) {                                  if (min_address != max_address) {
350                                          const int len = strlen(buf);                                          const int len = strlen(buf);
351                                          snprintf(buf + len, sizeof(buf) - 1 - len, "-%u.%u.%u.%u", HIPQUAD(max_address));                                          snprintf(buf + len,
352                                                     sizeof(buf) - 1 - len,
353                                                     "-%u.%u.%u.%u",
354                                                     HIPQUAD(max_address));
355                                  }                                  }
356                          }                          }
357                          if (io_printf(head, KEYWORD_ADDRESS_GROUP "%s %s\n", group->group_name->name, buf)) return -ENOMEM;                          done = ccs_io_printf(head, KEYWORD_ADDRESS_GROUP
358                                                 "%s %s\n", group->group_name->name,
359                                                 buf);
360                            if (!done)
361                                    break;
362                  }                  }
363                    if (!done)
364                            break;
365          }          }
366          return 0;          return done;
367  }  }
368    
 /*************************  NETWORK NETWORK ACL HANDLER  *************************/  
   
369  #if !defined(NIP6)  #if !defined(NIP6)
370  #define NIP6(addr) \  #define NIP6(addr)      \
371          ntohs((addr).s6_addr16[0]), \          ntohs((addr).s6_addr16[0]), ntohs((addr).s6_addr16[1]), \
372          ntohs((addr).s6_addr16[1]), \          ntohs((addr).s6_addr16[2]), ntohs((addr).s6_addr16[3]), \
373          ntohs((addr).s6_addr16[2]), \          ntohs((addr).s6_addr16[4]), ntohs((addr).s6_addr16[5]), \
374          ntohs((addr).s6_addr16[3]), \          ntohs((addr).s6_addr16[6]), ntohs((addr).s6_addr16[7])
         ntohs((addr).s6_addr16[4]), \  
         ntohs((addr).s6_addr16[5]), \  
         ntohs((addr).s6_addr16[6]), \  
         ntohs((addr).s6_addr16[7])  
375  #endif  #endif
376    
377  char *print_ipv6(char *buffer, const int buffer_len, const struct in6_addr *ip)  /**
378     * ccs_print_ipv6 - Print an IPv6 address.
379     *
380     * @buffer:     Buffer to write to.
381     * @buffer_len: Size of @buffer.
382     * @ip:         Pointer to "struct in6_addr".
383     *
384     * Returns nothing.
385     */
386    void ccs_print_ipv6(char *buffer, const int buffer_len,
387                        const struct in6_addr *ip)
388  {  {
389          memset(buffer, 0, buffer_len);          memset(buffer, 0, buffer_len);
390          snprintf(buffer, buffer_len - 1, "%x:%x:%x:%x:%x:%x:%x:%x", NIP6(*ip));          snprintf(buffer, buffer_len - 1, "%x:%x:%x:%x:%x:%x:%x:%x", NIP6(*ip));
         return buffer;  
391  }  }
392    
393  const char *net_operation2keyword(const u8 operation)  /**
394     * ccs_net2keyword - Convert network operation index to network operation name.
395     *
396     * @operation: Type of operation.
397     *
398     * Returns the name of operation.
399     */
400    const char *ccs_net2keyword(const u8 operation)
401  {  {
402          const char *keyword = "unknown";          const char *keyword = "unknown";
403          switch (operation) {          switch (operation) {
# Line 293  const char *net_operation2keyword(const Line 429  const char *net_operation2keyword(const
429          return keyword;          return keyword;
430  }  }
431    
432  static int AddNetworkEntry(const u8 operation, const u8 record_type, const struct address_group_entry *group, const u32 *min_address, const u32 *max_address, const u16 min_port, const u16 max_port, struct domain_info *domain, const struct condition_list *condition, const bool is_delete)  /**
433     * ccs_update_network_entry - Update "struct ccs_ip_network_acl_record" list.
434     *
435     * @operation:   Type of operation.
436     * @record_type: Type of address.
437     * @group:       Name of group. May be NULL.
438     * @min_address: Start of IPv4 or IPv6 address range.
439     * @max_address: End of IPv4 or IPv6 address range.
440     * @min_port:    Start of port number range.
441     * @max_port:    End of port number range.
442     * @domain:      Pointer to "struct ccs_domain_info".
443     * @condition:   Pointer to "struct ccs_condition". May be NULL.
444     * @is_delete:   True if it is a delete request.
445     *
446     * Returns 0 on success, negative value otherwise.
447     */
448    static int ccs_update_network_entry(const u8 operation, const u8 record_type,
449                                        const char *group_name,
450                                        const u32 *min_address,
451                                        const u32 *max_address,
452                                        const u16 min_port, const u16 max_port,
453                                        struct ccs_domain_info *domain,
454                                        struct ccs_condition *condition,
455                                        const bool is_delete)
456  {  {
457          struct acl_info *ptr;          struct ccs_ip_network_acl_record *entry = NULL;
458          struct ip_network_acl_record *acl;          struct ccs_acl_info *ptr;
459          int error = -ENOMEM;          int error = is_delete ? -ENOENT : -ENOMEM;
460          const u32 min_ip = ntohl(*min_address), max_ip = ntohl(*max_address); /* using host byte order to allow u32 comparison than memcmp().*/          /* using host byte order to allow u32 comparison than memcmp().*/
461          const struct in6_addr *saved_min_address = NULL, *saved_max_address = NULL;          const u32 min_ip = ntohl(*min_address);
462          if (!domain) return -EINVAL;          const u32 max_ip = ntohl(*max_address);
463          if (record_type == IP_RECORD_TYPE_IPv6) {          const struct in6_addr *saved_min_address = NULL;
464                  if ((saved_min_address = SaveIPv6Address((struct in6_addr *) min_address)) == NULL          const struct in6_addr *saved_max_address = NULL;
465                      || (saved_max_address = SaveIPv6Address((struct in6_addr *) max_address)) == NULL) return -ENOMEM;          struct ccs_address_group_entry *group = NULL;
466          }          if (!domain)
467          mutex_lock(&domain_acl_lock);                  return -EINVAL;
468          if (!is_delete) {          if (group_name) {
469                  list1_for_each_entry(ptr, &domain->acl_info_list, list) {                  group = ccs_get_address_group(group_name);
470                          acl = container_of(ptr, struct ip_network_acl_record, head);                  if (!group)
471                          if (ptr->type == TYPE_IP_NETWORK_ACL && acl->operation_type == operation && acl->record_type == record_type && ptr->cond == condition && acl->min_port == min_port && max_port == acl->max_port) {                          return -ENOMEM;
472                                  if (record_type == IP_RECORD_TYPE_ADDRESS_GROUP) {          } else if (record_type == IP_RECORD_TYPE_IPv6) {
473                                          if (acl->u.group == group) {                  saved_min_address = ccs_get_ipv6_address((struct in6_addr *)
474                                                  ptr->is_deleted = 0;                                                           min_address);
475                                                  /* Found. Nothing to do. */                  saved_max_address = ccs_get_ipv6_address((struct in6_addr *)
476                                                  error = 0;                                                           max_address);
477                                                  goto out;                  if (!saved_min_address || !saved_max_address)
478                                          }                          goto out;
479                                  } else if (record_type == IP_RECORD_TYPE_IPv4) {          }
480                                          if (acl->u.ipv4.min == min_ip && max_ip == acl->u.ipv4.max) {          if (is_delete)
481                                                  ptr->is_deleted = 0;                  goto delete;
482                                                  /* Found. Nothing to do. */          entry = kzalloc(sizeof(*entry), GFP_KERNEL);
483                                                  error = 0;          mutex_lock(&ccs_policy_lock);
484                                                  goto out;          list_for_each_entry_rcu(ptr, &domain->acl_info_list, list) {
485                                          }                  struct ccs_ip_network_acl_record *acl;
486                                  } else if (record_type == IP_RECORD_TYPE_IPv6) {                  if (ccs_acl_type1(ptr) != TYPE_IP_NETWORK_ACL)
487                                          if (acl->u.ipv6.min == saved_min_address && saved_max_address == acl->u.ipv6.max) {                          continue;
488                                                  ptr->is_deleted = 0;                  if (ptr->cond != condition)
489                                                  /* Found. Nothing to do. */                          continue;
490                                                  error = 0;                  acl = container_of(ptr, struct ccs_ip_network_acl_record, head);
491                                                  goto out;                  if (acl->operation_type != operation ||
492                                          }                      acl->record_type != record_type ||
493                                  }                      acl->min_port != min_port || max_port != acl->max_port)
494                          }                          continue;
495                    if (record_type == IP_RECORD_TYPE_ADDRESS_GROUP) {
496                            if (acl->u.group != group)
497                                    continue;
498                    } else if (record_type == IP_RECORD_TYPE_IPv4) {
499                            if (acl->u.ipv4.min != min_ip ||
500                                max_ip != acl->u.ipv4.max)
501                                    continue;
502                    } else if (record_type == IP_RECORD_TYPE_IPv6) {
503                            if (acl->u.ipv6.min != saved_min_address ||
504                                saved_max_address != acl->u.ipv6.max)
505                                    continue;
506                  }                  }
507                  /* Not found. Append it to the tail. */                  error = ccs_add_domain_acl(NULL, ptr);
508                  if ((acl = alloc_element(sizeof(*acl))) == NULL) goto out;                  break;
509                  acl->head.type = TYPE_IP_NETWORK_ACL;          }
510                  acl->operation_type = operation;          if (error && ccs_memory_ok(entry, sizeof(*entry))) {
511                  acl->record_type = record_type;                  entry->head.type = TYPE_IP_NETWORK_ACL;
512                  acl->head.cond = condition;                  entry->head.cond = condition;
513                    entry->operation_type = operation;
514                    entry->record_type = record_type;
515                  if (record_type == IP_RECORD_TYPE_ADDRESS_GROUP) {                  if (record_type == IP_RECORD_TYPE_ADDRESS_GROUP) {
516                          acl->u.group = group;                          entry->u.group = group;
517                            group = NULL;
518                  } else if (record_type == IP_RECORD_TYPE_IPv4) {                  } else if (record_type == IP_RECORD_TYPE_IPv4) {
519                          acl->u.ipv4.min = min_ip;                          entry->u.ipv4.min = min_ip;
520                          acl->u.ipv4.max = max_ip;                          entry->u.ipv4.max = max_ip;
521                  } else {                  } else {
522                          acl->u.ipv6.min = saved_min_address;                          entry->u.ipv6.min = saved_min_address;
523                          acl->u.ipv6.max = saved_max_address;                          saved_min_address = NULL;
524                            entry->u.ipv6.max = saved_max_address;
525                            saved_max_address = NULL;
526                  }                  }
527                  acl->min_port = min_port;                  entry->min_port = min_port;
528                  acl->max_port = max_port;                  entry->max_port = max_port;
529                  error = AddDomainACL(domain, &acl->head);                  error = ccs_add_domain_acl(domain, &entry->head);
530          } else {                  entry = NULL;
531                  error = -ENOENT;          }
532                  list1_for_each_entry(ptr, &domain->acl_info_list, list) {          mutex_unlock(&ccs_policy_lock);
533                          acl = container_of(ptr, struct ip_network_acl_record, head);          goto out;
534                          if (ptr->type != TYPE_IP_NETWORK_ACL || ptr->is_deleted || acl->operation_type != operation || acl->record_type != record_type || ptr->cond != condition || acl->min_port != min_port || acl->max_port != max_port) continue;   delete:
535                          if (record_type == IP_RECORD_TYPE_ADDRESS_GROUP) {          mutex_lock(&ccs_policy_lock);
536                                  if (acl->u.group != group) continue;          list_for_each_entry_rcu(ptr, &domain->acl_info_list, list) {
537                          } else if (record_type == IP_RECORD_TYPE_IPv4) {                  struct ccs_ip_network_acl_record *acl;
538                                  if (acl->u.ipv4.min != min_ip || max_ip != acl->u.ipv4.max) continue;                  if (ccs_acl_type2(ptr) != TYPE_IP_NETWORK_ACL)
539                          } else if (record_type == IP_RECORD_TYPE_IPv6) {                          continue;
540                                  if (acl->u.ipv6.min != saved_min_address || saved_max_address != acl->u.ipv6.max) continue;                  if (ptr->cond != condition)
541                          }                          continue;
542                          error = DelDomainACL(ptr);                  acl = container_of(ptr, struct ccs_ip_network_acl_record, head);
543                          break;                  if (acl->operation_type != operation ||
544                        acl->record_type != record_type ||
545                        acl->min_port != min_port || max_port != acl->max_port)
546                            continue;
547                    if (record_type == IP_RECORD_TYPE_ADDRESS_GROUP) {
548                            if (acl->u.group != group)
549                                    continue;
550                    } else if (record_type == IP_RECORD_TYPE_IPv4) {
551                            if (acl->u.ipv4.min != min_ip ||
552                                max_ip != acl->u.ipv4.max)
553                                    continue;
554                    } else if (record_type == IP_RECORD_TYPE_IPv6) {
555                            if (acl->u.ipv6.min != saved_min_address ||
556                                saved_max_address != acl->u.ipv6.max)
557                                    continue;
558                  }                  }
559                    error = ccs_del_domain_acl(ptr);
560                    break;
561          }          }
562   out: ;          mutex_unlock(&ccs_policy_lock);
563          mutex_unlock(&domain_acl_lock);   out:
564            ccs_put_ipv6_address(saved_min_address);
565            ccs_put_ipv6_address(saved_max_address);
566            ccs_put_address_group(group);
567            kfree(entry);
568          return error;          return error;
569  }  }
570    
571  static int CheckNetworkEntry(const bool is_ipv6, const u8 operation, const u32 *address, const u16 port)  /**
572     * ccs_check_network_entry2 - Check permission for network operation.
573     *
574     * @is_ipv6:   True if @address is an IPv6 address.
575     * @operation: Type of operation.
576     * @address:   An IPv4 or IPv6 address.
577     * @port:      Port number.
578     *
579     * Returns 0 on success, negative value otherwise.
580     *
581     * Caller holds srcu_read_lock(&ccs_ss).
582     */
583    static int ccs_check_network_entry2(const bool is_ipv6, const u8 operation,
584                                        const u32 *address, const u16 port)
585  {  {
586          struct domain_info * const domain = current->domain_info;          struct ccs_request_info r;
587          struct acl_info *ptr;          struct ccs_acl_info *ptr;
588          const char *keyword = net_operation2keyword(operation);          const char *keyword = ccs_net2keyword(operation);
589          const u8 profile = current->domain_info->profile;          bool is_enforce;
590          const u8 mode = CheckCCSFlags(CCS_TOMOYO_MAC_FOR_NETWORK);          /* using host byte order to allow u32 comparison than memcmp().*/
591          const bool is_enforce = (mode == 3);          const u32 ip = ntohl(*address);
592          const u32 ip = ntohl(*address); /* using host byte order to allow u32 comparison than memcmp().*/          bool found = false;
593          bool found = 0;          char buf[64];
594          if (!mode) return 0;          if (!ccs_can_sleep())
595          list1_for_each_entry(ptr, &domain->acl_info_list, list) {                  return 0;
596                  struct ip_network_acl_record *acl;          ccs_init_request_info(&r, NULL, CCS_MAC_FOR_NETWORK);
597                  acl = container_of(ptr, struct ip_network_acl_record, head);          is_enforce = (r.mode == 3);
598                  if (ptr->type != TYPE_IP_NETWORK_ACL || ptr->is_deleted || acl->operation_type != operation || port < acl->min_port || acl->max_port < port || CheckCondition(ptr->cond, NULL)) continue;          if (!r.mode)
599                    return 0;
600     retry:
601            list_for_each_entry_rcu(ptr, &r.domain->acl_info_list, list) {
602                    struct ccs_ip_network_acl_record *acl;
603                    if (ccs_acl_type2(ptr) != TYPE_IP_NETWORK_ACL)
604                            continue;
605                    acl = container_of(ptr, struct ccs_ip_network_acl_record, head);
606                    if (acl->operation_type != operation || port < acl->min_port ||
607                        acl->max_port < port || !ccs_check_condition(&r, ptr))
608                            continue;
609                  if (acl->record_type == IP_RECORD_TYPE_ADDRESS_GROUP) {                  if (acl->record_type == IP_RECORD_TYPE_ADDRESS_GROUP) {
610                          if (!AddressMatchesToGroup(is_ipv6, address, acl->u.group)) continue;                          if (!ccs_address_matches_group(is_ipv6, address,
611                                                           acl->u.group))
612                                    continue;
613                  } else if (acl->record_type == IP_RECORD_TYPE_IPv4) {                  } else if (acl->record_type == IP_RECORD_TYPE_IPv4) {
614                          if (is_ipv6 || ip < acl->u.ipv4.min || acl->u.ipv4.max < ip) continue;                          if (is_ipv6 ||
615                                ip < acl->u.ipv4.min || acl->u.ipv4.max < ip)
616                                    continue;
617                  } else {                  } else {
618                          if (!is_ipv6 || memcmp(acl->u.ipv6.min, address, 16) > 0 || memcmp(address, acl->u.ipv6.max, 16) > 0) continue;                          if (!is_ipv6 ||
619                                memcmp(acl->u.ipv6.min, address, 16) > 0 ||
620                                memcmp(address, acl->u.ipv6.max, 16) > 0)
621                                    continue;
622                  }                  }
623                  found = 1;                  r.cond = ptr->cond;
624                    found = true;
625                  break;                  break;
626          }          }
627          AuditNetworkLog(is_ipv6, keyword, address, port, found, profile, mode);          memset(buf, 0, sizeof(buf));
628          if (found) return 0;          if (is_ipv6)
629          if (TomoyoVerboseMode()) {                  ccs_print_ipv6(buf, sizeof(buf),
630                  if (is_ipv6) {                                 (const struct in6_addr *) address);
631                          char buf[64];          else
632                          print_ipv6(buf, sizeof(buf), (const struct in6_addr *) address);                  snprintf(buf, sizeof(buf) - 1, "%u.%u.%u.%u", HIPQUAD(ip));
633                          printk("TOMOYO-%s: %s to %s %u denied for %s\n", GetMSG(is_enforce), keyword, buf, port, GetLastName(domain));          ccs_audit_network_log(&r, keyword, buf, port, found);
634                  } else {          if (found)
635                          printk("TOMOYO-%s: %s to %u.%u.%u.%u %u denied for %s\n", GetMSG(is_enforce), keyword, HIPQUAD(ip), port, GetLastName(domain));                  return 0;
636                  }          if (ccs_verbose_mode(r.domain))
637          }                  printk(KERN_WARNING "TOMOYO-%s: %s to %s %u denied for %s\n",
638                           ccs_get_msg(is_enforce), keyword, buf, port,
639                           ccs_get_last_name(r.domain));
640          if (is_enforce) {          if (is_enforce) {
641                  if (is_ipv6) {                  int err = ccs_check_supervisor(&r, KEYWORD_ALLOW_NETWORK
642                          char buf[64];                                                 "%s %s %u\n", keyword, buf,
643                          print_ipv6(buf, sizeof(buf), (const struct in6_addr *) address);                                                 port);
644                          return CheckSupervisor("%s\n" KEYWORD_ALLOW_NETWORK "%s %s %u\n", domain->domainname->name, keyword, buf, port);                  if (err == 1)
645                  }                          goto retry;
646                  return CheckSupervisor("%s\n" KEYWORD_ALLOW_NETWORK "%s %u.%u.%u.%u %u\n", domain->domainname->name, keyword, HIPQUAD(ip), port);                  return err;
647            }
648            if (r.mode == 1 && ccs_domain_quota_ok(r.domain)) {
649                    struct ccs_condition *cond = ccs_handler_cond();
650                    ccs_update_network_entry(operation, is_ipv6 ?
651                                             IP_RECORD_TYPE_IPv6 :
652                                             IP_RECORD_TYPE_IPv4,
653                                             NULL, address, address, port, port,
654                                             r.domain, cond, false);
655                    ccs_put_condition(cond);
656          }          }
         if (mode == 1 && CheckDomainQuota(domain)) AddNetworkEntry(operation, is_ipv6 ? IP_RECORD_TYPE_IPv6 : IP_RECORD_TYPE_IPv4, NULL, address, address, port, port, domain, NULL, 0);  
657          return 0;          return 0;
658  }  }
659    
660  int AddNetworkPolicy(char *data, struct domain_info *domain, const struct condition_list *condition, const bool is_delete)  /**
661     * ccs_check_network_entry - Check permission for network operation.
662     *
663     * @is_ipv6:   True if @address is an IPv6 address.
664     * @operation: Type of operation.
665     * @address:   An IPv4 or IPv6 address.
666     * @port:      Port number.
667     *
668     * Returns 0 on success, negative value otherwise.
669     */
670    static int ccs_check_network_entry(const bool is_ipv6, const u8 operation,
671                                       const u32 *address, const u16 port)
672    {
673            const int idx = srcu_read_lock(&ccs_ss);
674            const int error = ccs_check_network_entry2(is_ipv6, operation,
675                                                       address, port);
676            srcu_read_unlock(&ccs_ss, idx);
677            return error;
678    }
679    
680    /**
681     * ccs_write_network_policy - Write "struct ccs_ip_network_acl_record" list.
682     *
683     * @data:      String to parse.
684     * @domain:    Pointer to "struct ccs_domain_info".
685     * @condition: Pointer to "struct ccs_condition". May be NULL.
686     * @is_delete: True if it is a delete request.
687     *
688     * Returns 0 on success, negative value otherwise.
689     */
690    int ccs_write_network_policy(char *data, struct ccs_domain_info *domain,
691                                 struct ccs_condition *condition,
692                                 const bool is_delete)
693  {  {
694          u8 sock_type, operation, record_type;          u8 sock_type;
695          u16 min_address[8], max_address[8];          u8 operation;
696          struct address_group_entry *group = NULL;          u8 record_type;
697          u16 min_port, max_port;          u16 min_address[8];
698            u16 max_address[8];
699            const char *group_name = NULL;
700            u16 min_port;
701            u16 max_port;
702          u8 count;          u8 count;
703          char *cp1 = NULL, *cp2 = NULL;          char *cp1 = strchr(data, ' ');
704          if ((cp1 = strchr(data, ' ')) == NULL) goto out; cp1++;          char *cp2;
705          if (strncmp(data, "TCP ", 4) == 0) sock_type = SOCK_STREAM;          if (!cp1)
706          else if (strncmp(data, "UDP ", 4) == 0) sock_type = SOCK_DGRAM;                  goto out;
707          else if (strncmp(data, "RAW ", 4) == 0) sock_type = SOCK_RAW;          cp1++;
708          else goto out;          if (!strncmp(data, "TCP ", 4))
709          if ((cp2 = strchr(cp1, ' ')) == NULL) goto out; cp2++;                  sock_type = SOCK_STREAM;
710          if (strncmp(cp1, "bind ", 5) == 0) {          else if (!strncmp(data, "UDP ", 4))
711                  operation = (sock_type == SOCK_STREAM) ? NETWORK_ACL_TCP_BIND : (sock_type == SOCK_DGRAM) ? NETWORK_ACL_UDP_BIND : NETWORK_ACL_RAW_BIND;                  sock_type = SOCK_DGRAM;
712          } else if (strncmp(cp1, "connect ", 8) == 0) {          else if (!strncmp(data, "RAW ", 4))
713                  operation = (sock_type == SOCK_STREAM) ? NETWORK_ACL_TCP_CONNECT : (sock_type == SOCK_DGRAM) ? NETWORK_ACL_UDP_CONNECT : NETWORK_ACL_RAW_CONNECT;                  sock_type = SOCK_RAW;
714          } else if (sock_type == SOCK_STREAM && strncmp(cp1, "listen ", 7) == 0) {          else
715                    goto out;
716            cp2 = strchr(cp1, ' ');
717            if (!cp2)
718                    goto out;
719            cp2++;
720            if (!strncmp(cp1, "bind ", 5))
721                    switch (sock_type) {
722                    case SOCK_STREAM:
723                            operation = NETWORK_ACL_TCP_BIND;
724                            break;
725                    case SOCK_DGRAM:
726                            operation = NETWORK_ACL_UDP_BIND;
727                            break;
728                    default:
729                            operation = NETWORK_ACL_RAW_BIND;
730                    }
731            else if (!strncmp(cp1, "connect ", 8))
732                    switch (sock_type) {
733                    case SOCK_STREAM:
734                            operation = NETWORK_ACL_TCP_CONNECT;
735                            break;
736                    case SOCK_DGRAM:
737                            operation = NETWORK_ACL_UDP_CONNECT;
738                            break;
739                    default:
740                            operation = NETWORK_ACL_RAW_CONNECT;
741                    }
742            else if (sock_type == SOCK_STREAM && !strncmp(cp1, "listen ", 7))
743                  operation = NETWORK_ACL_TCP_LISTEN;                  operation = NETWORK_ACL_TCP_LISTEN;
744          } else if (sock_type == SOCK_STREAM && strncmp(cp1, "accept ", 7) == 0) {          else if (sock_type == SOCK_STREAM && !strncmp(cp1, "accept ", 7))
745                  operation = NETWORK_ACL_TCP_ACCEPT;                  operation = NETWORK_ACL_TCP_ACCEPT;
746          } else {          else
747                  goto out;                  goto out;
748          }          cp1 = strchr(cp2, ' ');
749          if ((cp1 = strchr(cp2, ' ')) == NULL) goto out; *cp1++ = '\0';          if (!cp1)
750          if ((count = sscanf(cp2, "%hx:%hx:%hx:%hx:%hx:%hx:%hx:%hx-%hx:%hx:%hx:%hx:%hx:%hx:%hx:%hx",                  goto out;
751                              &min_address[0], &min_address[1], &min_address[2], &min_address[3],          *cp1++ = '\0';
752                              &min_address[4], &min_address[5], &min_address[6], &min_address[7],          switch (ccs_parse_ip_address(cp2, min_address, max_address)) {
753                              &max_address[0], &max_address[1], &max_address[2], &max_address[3],          case 2:
                             &max_address[4], &max_address[5], &max_address[6], &max_address[7])) == 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));  
754                  record_type = IP_RECORD_TYPE_IPv6;                  record_type = IP_RECORD_TYPE_IPv6;
755          } else if ((count = sscanf(cp2, "%hu.%hu.%hu.%hu-%hu.%hu.%hu.%hu",                  break;
756                                     &min_address[0], &min_address[1], &min_address[2], &min_address[3],          case 1:
                                    &max_address[0], &max_address[1], &max_address[2], &max_address[3])) == 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;  
757                  record_type = IP_RECORD_TYPE_IPv4;                  record_type = IP_RECORD_TYPE_IPv4;
758          } else if (*cp2 == '@') {                  break;
759                  if ((group = FindOrAssignNewAddressGroup(cp2 + 1)) == NULL) return -ENOMEM;          default:
760                    if (*cp2 != '@')
761                            goto out;
762                    group_name = cp2 + 1;
763                  record_type = IP_RECORD_TYPE_ADDRESS_GROUP;                  record_type = IP_RECORD_TYPE_ADDRESS_GROUP;
764          } else {                  break;
                 goto out;  
         }  
         if (strchr(cp1, ' ')) goto out;  
         if ((count = sscanf(cp1, "%hu-%hu", &min_port, &max_port)) == 1 || count == 2) {  
                 if (count == 1) max_port = min_port;  
                 return AddNetworkEntry(operation, record_type, group, (u32 *) min_address, (u32 *) max_address, min_port, max_port, domain, condition, is_delete);  
765          }          }
766   out: ;          if (strchr(cp1, ' '))
767                    goto out;
768            count = sscanf(cp1, "%hu-%hu", &min_port, &max_port);
769            if (count != 1 && count != 2)
770                    goto out;
771            if (count == 1)
772                    max_port = min_port;
773            return ccs_update_network_entry(operation, record_type, group_name,
774                                            (u32 *) min_address,
775                                            (u32 *) max_address,
776                                            min_port, max_port, domain, condition,
777                                            is_delete);
778     out:
779          return -EINVAL;          return -EINVAL;
780  }  }
781    
782  int CheckNetworkListenACL(const _Bool is_ipv6, const u8 *address, const u16 port)  /**
783     * ccs_check_network_listen_acl - Check permission for listen() operation.
784     *
785     * @is_ipv6: True if @address is an IPv6 address.
786     * @address: An IPv4 or IPv6 address.
787     * @port:    Port number.
788     *
789     * Returns 0 on success, negative value otherwise.
790     */
791    static inline int ccs_check_network_listen_acl(const bool is_ipv6,
792                                                   const u8 *address,
793                                                   const u16 port)
794  {  {
795          return CheckNetworkEntry(is_ipv6, NETWORK_ACL_TCP_LISTEN, (const u32 *) address, ntohs(port));          return ccs_check_network_entry(is_ipv6, NETWORK_ACL_TCP_LISTEN,
796                                           (const u32 *) address, ntohs(port));
797  }  }
798    
799  int CheckNetworkConnectACL(const _Bool is_ipv6, const int sock_type, const u8 *address, const u16 port)  /**
800     * ccs_check_network_connect_acl - Check permission for connect() operation.
801     *
802     * @is_ipv6:   True if @address is an IPv6 address.
803     * @sock_type: Type of socket. (TCP or UDP or RAW)
804     * @address:   An IPv4 or IPv6 address.
805     * @port:      Port number.
806     *
807     * Returns 0 on success, negative value otherwise.
808     */
809    static inline int ccs_check_network_connect_acl(const bool is_ipv6,
810                                                    const int sock_type,
811                                                    const u8 *address,
812                                                    const u16 port)
813  {  {
814          return CheckNetworkEntry(is_ipv6, sock_type == SOCK_STREAM ? NETWORK_ACL_TCP_CONNECT : (sock_type == SOCK_DGRAM ? NETWORK_ACL_UDP_CONNECT : NETWORK_ACL_RAW_CONNECT), (const u32 *) address, ntohs(port));          u8 operation;
815            switch (sock_type) {
816            case SOCK_STREAM:
817                    operation = NETWORK_ACL_TCP_CONNECT;
818                    break;
819            case SOCK_DGRAM:
820                    operation = NETWORK_ACL_UDP_CONNECT;
821                    break;
822            default:
823                    operation = NETWORK_ACL_RAW_CONNECT;
824            }
825            return ccs_check_network_entry(is_ipv6, operation,
826                                           (const u32 *) address, ntohs(port));
827  }  }
828    
829  int CheckNetworkBindACL(const _Bool is_ipv6, const int sock_type, const u8 *address, const u16 port)  /**
830     * ccs_check_network_bind_acl - Check permission for bind() operation.
831     *
832     * @is_ipv6:   True if @address is an IPv6 address.
833     * @sock_type: Type of socket. (TCP or UDP or RAW)
834     * @address:   An IPv4 or IPv6 address.
835     * @port:      Port number.
836     *
837     * Returns 0 on success, negative value otherwise.
838     */
839    static int ccs_check_network_bind_acl(const bool is_ipv6, const int sock_type,
840                                          const u8 *address, const u16 port)
841  {  {
842          return CheckNetworkEntry(is_ipv6, sock_type == SOCK_STREAM ? NETWORK_ACL_TCP_BIND : (sock_type == SOCK_DGRAM ? NETWORK_ACL_UDP_BIND : NETWORK_ACL_RAW_BIND), (const u32 *) address, ntohs(port));          u8 operation;
843            switch (sock_type) {
844            case SOCK_STREAM:
845                    operation = NETWORK_ACL_TCP_BIND;
846                    break;
847            case SOCK_DGRAM:
848                    operation = NETWORK_ACL_UDP_BIND;
849                    break;
850            default:
851                    operation = NETWORK_ACL_RAW_BIND;
852            }
853            return ccs_check_network_entry(is_ipv6, operation,
854                                           (const u32 *) address, ntohs(port));
855  }  }
856    
857  int CheckNetworkAcceptACL(const _Bool is_ipv6, const u8 *address, const u16 port)  /**
858     * ccs_check_network_accept_acl - Check permission for accept() operation.
859     *
860     * @is_ipv6: True if @address is an IPv6 address.
861     * @address: An IPv4 or IPv6 address.
862     * @port:    Port number.
863     *
864     * Returns 0 on success, negative value otherwise.
865     */
866    static inline int ccs_check_network_accept_acl(const bool is_ipv6,
867                                                   const u8 *address,
868                                                   const u16 port)
869  {  {
870          int retval;          int retval;
871          current->tomoyo_flags |= CCS_DONT_SLEEP_ON_ENFORCE_ERROR;          current->ccs_flags |= CCS_DONT_SLEEP_ON_ENFORCE_ERROR;
872          retval = CheckNetworkEntry(is_ipv6, NETWORK_ACL_TCP_ACCEPT, (const u32 *) address, ntohs(port));          retval = ccs_check_network_entry(is_ipv6, NETWORK_ACL_TCP_ACCEPT,
873          current->tomoyo_flags &= ~CCS_DONT_SLEEP_ON_ENFORCE_ERROR;                                           (const u32 *) address, ntohs(port));
874            current->ccs_flags &= ~CCS_DONT_SLEEP_ON_ENFORCE_ERROR;
875          return retval;          return retval;
876  }  }
877    
878  int CheckNetworkSendMsgACL(const _Bool is_ipv6, const int sock_type, const u8 *address, const u16 port)  /**
879     * ccs_check_network_sendmsg_acl - Check permission for sendmsg() operation.
880     *
881     * @is_ipv6:   True if @address is an IPv6 address.
882     * @sock_type: Type of socket. (UDP or RAW)
883     * @address:   An IPv4 or IPv6 address.
884     * @port:      Port number.
885     *
886     * Returns 0 on success, negative value otherwise.
887     */
888    static inline int ccs_check_network_sendmsg_acl(const bool is_ipv6,
889                                                    const int sock_type,
890                                                    const u8 *address,
891                                                    const u16 port)
892  {  {
893          return CheckNetworkEntry(is_ipv6, sock_type == SOCK_DGRAM ? NETWORK_ACL_UDP_CONNECT : NETWORK_ACL_RAW_CONNECT, (const u32 *) address, ntohs(port));          u8 operation;
894            if (sock_type == SOCK_DGRAM)
895                    operation = NETWORK_ACL_UDP_CONNECT;
896            else
897                    operation = NETWORK_ACL_RAW_CONNECT;
898            return ccs_check_network_entry(is_ipv6, operation,
899                                           (const u32 *) address, ntohs(port));
900  }  }
901    
902  int CheckNetworkRecvMsgACL(const _Bool is_ipv6, const int sock_type, const u8 *address, const u16 port)  /**
903     * ccs_check_network_recvmsg_acl - Check permission for recvmsg() operation.
904     *
905     * @is_ipv6:   True if @address is an IPv6 address.
906     * @sock_type: Type of socket. (UDP or RAW)
907     * @address:   An IPv4 or IPv6 address.
908     * @port:      Port number.
909     *
910     * Returns 0 on success, negative value otherwise.
911     */
912    static inline int ccs_check_network_recvmsg_acl(const bool is_ipv6,
913                                                    const int sock_type,
914                                                    const u8 *address,
915                                                    const u16 port)
916  {  {
917          int retval;          int retval;
918          current->tomoyo_flags |= CCS_DONT_SLEEP_ON_ENFORCE_ERROR;          const u8 operation
919          retval = CheckNetworkEntry(is_ipv6, sock_type == SOCK_DGRAM ? NETWORK_ACL_UDP_CONNECT : NETWORK_ACL_RAW_CONNECT, (const u32 *) address, ntohs(port));                  = (sock_type == SOCK_DGRAM) ?
920          current->tomoyo_flags &= ~CCS_DONT_SLEEP_ON_ENFORCE_ERROR;                  NETWORK_ACL_UDP_CONNECT : NETWORK_ACL_RAW_CONNECT;
921            current->ccs_flags |= CCS_DONT_SLEEP_ON_ENFORCE_ERROR;
922            retval = ccs_check_network_entry(is_ipv6, operation,
923                                             (const u32 *) address, ntohs(port));
924            current->ccs_flags &= ~CCS_DONT_SLEEP_ON_ENFORCE_ERROR;
925          return retval;          return retval;
926  }  }
927    
928  /***** TOMOYO Linux end. *****/  #define MAX_SOCK_ADDR 128 /* net/socket.c */
929    
930    /* Check permission for creating a socket. */
931    int ccs_socket_create_permission(int family, int type, int protocol)
932    {
933            int error = 0;
934            /* Nothing to do if I am a kernel service. */
935            if (segment_eq(get_fs(), KERNEL_DS))
936                    return 0;
937            if (family == PF_PACKET && !ccs_capable(CCS_USE_PACKET_SOCKET))
938                    return -EPERM;
939            if (family == PF_ROUTE && !ccs_capable(CCS_USE_ROUTE_SOCKET))
940                    return -EPERM;
941            if (family != PF_INET && family != PF_INET6)
942                    return 0;
943            switch (type) {
944            case SOCK_STREAM:
945                    if (!ccs_capable(CCS_INET_STREAM_SOCKET_CREATE))
946                            error = -EPERM;
947                    break;
948            case SOCK_DGRAM:
949                    if (!ccs_capable(CCS_USE_INET_DGRAM_SOCKET))
950                            error = -EPERM;
951                    break;
952            case SOCK_RAW:
953                    if (!ccs_capable(CCS_USE_INET_RAW_SOCKET))
954                            error = -EPERM;
955                    break;
956            }
957            return error;
958    }
959    
960    /* Check permission for listening a TCP socket. */
961    int ccs_socket_listen_permission(struct socket *sock)
962    {
963            int error = 0;
964            char addr[MAX_SOCK_ADDR];
965            int addr_len;
966            /* Nothing to do if I am a kernel service. */
967            if (segment_eq(get_fs(), KERNEL_DS))
968                    return 0;
969            if (sock->type != SOCK_STREAM)
970                    return 0;
971            switch (sock->sk->sk_family) {
972            case PF_INET:
973            case PF_INET6:
974                    break;
975            default:
976                    return 0;
977            }
978            if (!ccs_capable(CCS_INET_STREAM_SOCKET_LISTEN))
979                    return -EPERM;
980            if (sock->ops->getname(sock, (struct sockaddr *) addr, &addr_len, 0))
981                    return -EPERM;
982            switch (((struct sockaddr *) addr)->sa_family) {
983                    struct sockaddr_in6 *addr6;
984                    struct sockaddr_in *addr4;
985            case AF_INET6:
986                    addr6 = (struct sockaddr_in6 *) addr;
987                    error = ccs_check_network_listen_acl(true,
988                                                         addr6->sin6_addr.s6_addr,
989                                                         addr6->sin6_port);
990                    break;
991            case AF_INET:
992                    addr4 = (struct sockaddr_in *) addr;
993                    error = ccs_check_network_listen_acl(false,
994                                                         (u8 *) &addr4->sin_addr,
995                                                         addr4->sin_port);
996                    break;
997            }
998            return error;
999    }
1000    
1001    /* Check permission for setting the remote IP address/port pair of a socket. */
1002    int ccs_socket_connect_permission(struct socket *sock, struct sockaddr *addr,
1003                                      int addr_len)
1004    {
1005            int error = 0;
1006            const unsigned int type = sock->type;
1007            /* Nothing to do if I am a kernel service. */
1008            if (segment_eq(get_fs(), KERNEL_DS))
1009                    return 0;
1010            switch (type) {
1011            case SOCK_STREAM:
1012            case SOCK_DGRAM:
1013            case SOCK_RAW:
1014                    break;
1015            default:
1016                    return 0;
1017            }
1018            switch (addr->sa_family) {
1019                    struct sockaddr_in6 *addr6;
1020                    struct sockaddr_in *addr4;
1021                    u16 port;
1022            case AF_INET6:
1023                    if (addr_len < SIN6_LEN_RFC2133)
1024                            break;
1025                    addr6 = (struct sockaddr_in6 *) addr;
1026                    if (type != SOCK_RAW)
1027                            port = addr6->sin6_port;
1028                    else
1029                            port = htons(sock->sk->sk_protocol);
1030                    error = ccs_check_network_connect_acl(true, type,
1031                                                          addr6->sin6_addr.s6_addr,
1032                                                          port);
1033                    break;
1034            case AF_INET:
1035                    if (addr_len < sizeof(struct sockaddr_in))
1036                            break;
1037                    addr4 = (struct sockaddr_in *) addr;
1038                    if (type != SOCK_RAW)
1039                            port = addr4->sin_port;
1040                    else
1041                            port = htons(sock->sk->sk_protocol);
1042                    error = ccs_check_network_connect_acl(false, type,
1043                                                          (u8 *) &addr4->sin_addr,
1044                                                          port);
1045                    break;
1046            }
1047            if (type != SOCK_STREAM)
1048                    return error;
1049            switch (sock->sk->sk_family) {
1050            case PF_INET:
1051            case PF_INET6:
1052                    if (!ccs_capable(CCS_INET_STREAM_SOCKET_CONNECT))
1053                            error = -EPERM;
1054                    break;
1055            }
1056            return error;
1057    }
1058    
1059    /* Check permission for setting the local IP address/port pair of a socket. */
1060    int ccs_socket_bind_permission(struct socket *sock, struct sockaddr *addr,
1061                                   int addr_len)
1062    {
1063            int error = 0;
1064            const unsigned int type = sock->type;
1065            /* Nothing to do if I am a kernel service. */
1066            if (segment_eq(get_fs(), KERNEL_DS))
1067                    return 0;
1068            switch (type) {
1069            case SOCK_STREAM:
1070            case SOCK_DGRAM:
1071            case SOCK_RAW:
1072                    break;
1073            default:
1074                    return 0;
1075            }
1076            switch (addr->sa_family) {
1077                    struct sockaddr_in6 *addr6;
1078                    struct sockaddr_in *addr4;
1079                    u16 port;
1080            case AF_INET6:
1081                    if (addr_len < SIN6_LEN_RFC2133)
1082                            break;
1083                    addr6 = (struct sockaddr_in6 *) addr;
1084                    if (type != SOCK_RAW)
1085                            port = addr6->sin6_port;
1086                    else
1087                            port = htons(sock->sk->sk_protocol);
1088                    error = ccs_check_network_bind_acl(true, type,
1089                                                       addr6->sin6_addr.s6_addr,
1090                                                       port);
1091                    break;
1092            case AF_INET:
1093                    if (addr_len < sizeof(struct sockaddr_in))
1094                            break;
1095                    addr4 = (struct sockaddr_in *) addr;
1096                    if (type != SOCK_RAW)
1097                            port = addr4->sin_port;
1098                    else
1099                            port = htons(sock->sk->sk_protocol);
1100                    error = ccs_check_network_bind_acl(false, type,
1101                                                       (u8 *) &addr4->sin_addr,
1102                                                       port);
1103                    break;
1104            }
1105            return error;
1106    }
1107    
1108    /*
1109     * Check permission for accepting a TCP socket.
1110     *
1111     * Currently, the LSM hook for this purpose is not provided.
1112     */
1113    int ccs_socket_accept_permission(struct socket *sock, struct sockaddr *addr)
1114    {
1115            int error = 0;
1116            int addr_len;
1117            /* Nothing to do if I am a kernel service. */
1118            if (segment_eq(get_fs(), KERNEL_DS))
1119                    return 0;
1120            switch (sock->sk->sk_family) {
1121            case PF_INET:
1122            case PF_INET6:
1123                    break;
1124            default:
1125                    return 0;
1126            }
1127            error = sock->ops->getname(sock, addr, &addr_len, 2);
1128            if (error)
1129                    return error;
1130            switch (addr->sa_family) {
1131                    struct sockaddr_in6 *addr6;
1132                    struct sockaddr_in *addr4;
1133            case AF_INET6:
1134                    addr6 = (struct sockaddr_in6 *) addr;
1135                    error = ccs_check_network_accept_acl(true,
1136                                                         addr6->sin6_addr.s6_addr,
1137                                                         addr6->sin6_port);
1138                    break;
1139            case AF_INET:
1140                    addr4 = (struct sockaddr_in *) addr;
1141                    error = ccs_check_network_accept_acl(false,
1142                                                         (u8 *) &addr4->sin_addr,
1143                                                         addr4->sin_port);
1144                    break;
1145            }
1146            return error;
1147    }
1148    
1149    /* Check permission for sending a datagram via a UDP or RAW socket. */
1150    int ccs_socket_sendmsg_permission(struct socket *sock, struct sockaddr *addr,
1151                                      int addr_len)
1152    {
1153            int error = 0;
1154            const int type = sock->type;
1155            /* Nothing to do if I am a kernel service. */
1156            if (segment_eq(get_fs(), KERNEL_DS))
1157                    return 0;
1158            if (!addr || (type != SOCK_DGRAM && type != SOCK_RAW))
1159                    return 0;
1160            switch (addr->sa_family) {
1161                    struct sockaddr_in6 *addr6;
1162                    struct sockaddr_in *addr4;
1163                    u16 port;
1164            case AF_INET6:
1165                    if (addr_len < SIN6_LEN_RFC2133)
1166                            break;
1167                    addr6 = (struct sockaddr_in6 *) addr;
1168                    if (type == SOCK_DGRAM)
1169                            port = addr6->sin6_port;
1170                    else
1171                            port = htons(sock->sk->sk_protocol);
1172                    error = ccs_check_network_sendmsg_acl(true, type,
1173                                                          addr6->sin6_addr.s6_addr,
1174                                                          port);
1175                    break;
1176            case AF_INET:
1177                    if (addr_len < sizeof(struct sockaddr_in))
1178                            break;
1179                    addr4 = (struct sockaddr_in *) addr;
1180                    if (type == SOCK_DGRAM)
1181                            port = addr4->sin_port;
1182                    else
1183                            port = htons(sock->sk->sk_protocol);
1184                    error = ccs_check_network_sendmsg_acl(false, type,
1185                                                          (u8 *) &addr4->sin_addr,
1186                                                          port);
1187                    break;
1188            }
1189            return error;
1190    }
1191    
1192    #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 22)
1193    #if !defined(RHEL_MAJOR) || RHEL_MAJOR != 5
1194    
1195    static inline struct iphdr *ip_hdr(const struct sk_buff *skb)
1196    {
1197            return skb->nh.iph;
1198    }
1199    
1200    static inline struct udphdr *udp_hdr(const struct sk_buff *skb)
1201    {
1202            return skb->h.uh;
1203    }
1204    
1205    static inline struct ipv6hdr *ipv6_hdr(const struct sk_buff *skb)
1206    {
1207            return skb->nh.ipv6h;
1208    }
1209    
1210    #endif
1211    #endif
1212    
1213    #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 12)
1214    static void skb_kill_datagram(struct sock *sk, struct sk_buff *skb,
1215                                  unsigned int flags)
1216    {
1217            /* Clear queue. */
1218            if (flags & MSG_PEEK) {
1219                    int clear = 0;
1220                    spin_lock_irq(&sk->sk_receive_queue.lock);
1221                    if (skb == skb_peek(&sk->sk_receive_queue)) {
1222                            __skb_unlink(skb, &sk->sk_receive_queue);
1223                            clear = 1;
1224                    }
1225                    spin_unlock_irq(&sk->sk_receive_queue.lock);
1226                    if (clear)
1227                            kfree_skb(skb);
1228            }
1229            skb_free_datagram(sk, skb);
1230    }
1231    #elif LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 16)
1232    static void skb_kill_datagram(struct sock *sk, struct sk_buff *skb,
1233                                  unsigned int flags)
1234    {
1235            /* Clear queue. */
1236            if (flags & MSG_PEEK) {
1237                    int clear = 0;
1238                    spin_lock_bh(&sk->sk_receive_queue.lock);
1239                    if (skb == skb_peek(&sk->sk_receive_queue)) {
1240                            __skb_unlink(skb, &sk->sk_receive_queue);
1241                            clear = 1;
1242                    }
1243                    spin_unlock_bh(&sk->sk_receive_queue.lock);
1244                    if (clear)
1245                            kfree_skb(skb);
1246            }
1247            skb_free_datagram(sk, skb);
1248    }
1249    #endif
1250    
1251    /*
1252     * Check permission for receiving a datagram via a UDP or RAW socket.
1253     *
1254     * Currently, the LSM hook for this purpose is not provided.
1255     */
1256    int ccs_socket_recvmsg_permission(struct sock *sk, struct sk_buff *skb,
1257                                      const unsigned int flags)
1258    {
1259            int error = 0;
1260            const unsigned int type = sk->sk_type;
1261            if (type != SOCK_DGRAM && type != SOCK_RAW)
1262                    return 0;
1263            /* Nothing to do if I am a kernel service. */
1264            if (segment_eq(get_fs(), KERNEL_DS))
1265                    return 0;
1266    
1267            switch (sk->sk_family) {
1268                    struct in6_addr sin6;
1269                    struct in_addr sin4;
1270                    u16 port;
1271            case PF_INET6:
1272                    if (type == SOCK_DGRAM) { /* UDP IPv6 */
1273                            if (skb->protocol == htons(ETH_P_IP)) {
1274                                    ipv6_addr_set(&sin6, 0, 0, htonl(0xffff),
1275                                                  ip_hdr(skb)->saddr);
1276                            } else {
1277                                    ipv6_addr_copy(&sin6, &ipv6_hdr(skb)->saddr);
1278                            }
1279                            port = udp_hdr(skb)->source;
1280                    } else { /* RAW IPv6 */
1281                            ipv6_addr_copy(&sin6, &ipv6_hdr(skb)->saddr);
1282                            port = htons(sk->sk_protocol);
1283                    }
1284                    error = ccs_check_network_recvmsg_acl(true, type,
1285                                                          (u8 *) &sin6, port);
1286                    break;
1287            case PF_INET:
1288                    if (type == SOCK_DGRAM) { /* UDP IPv4 */
1289                            sin4.s_addr = ip_hdr(skb)->saddr;
1290                            port = udp_hdr(skb)->source;
1291                    } else { /* RAW IPv4 */
1292                            sin4.s_addr = ip_hdr(skb)->saddr;
1293                            port = htons(sk->sk_protocol);
1294                    }
1295                    error = ccs_check_network_recvmsg_acl(false, type,
1296                                                          (u8 *) &sin4, port);
1297                    break;
1298            }
1299            if (!error)
1300                    return 0;
1301            /*
1302             * Remove from queue if MSG_PEEK is used so that
1303             * the head message from unwanted source in receive queue will not
1304             * prevent the caller from picking up next message from wanted source
1305             * when the caller is using MSG_PEEK flag for picking up.
1306             */
1307    #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)
1308            if (type == SOCK_DGRAM)
1309                    lock_sock(sk);
1310    #endif
1311            skb_kill_datagram(sk, skb, flags);
1312    #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)
1313            if (type == SOCK_DGRAM)
1314                    release_sock(sk);
1315    #endif
1316            /* Hope less harmful than -EPERM. */
1317            return -ENOMEM;
1318    }
1319    EXPORT_SYMBOL(ccs_socket_recvmsg_permission);

Legend:
Removed from v.853  
changed lines
  Added in v.2727

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