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

Subversion リポジトリの参照

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 2037 - (hide annotations) (download) (as text)
Mon Jan 5 05:56:56 2009 UTC (15 years, 4 months ago) by kumaneko
Original Path: trunk/1.6.x/ccs-patch/fs/tomoyo_network.c
File MIME type: text/x-csrc
File size: 35497 byte(s)


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

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