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

Subversion リポジトリの参照

Contents of /trunk/1.6.x/ccs-patch/fs/tomoyo_network.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1657 - (show annotations) (download) (as text)
Tue Oct 7 02:21:32 2008 UTC (15 years, 7 months ago) by kumaneko
File MIME type: text/x-csrc
File size: 25049 byte(s)


1 /*
2 * fs/tomoyo_network.c
3 *
4 * Implementation of the Domain-Based Mandatory Access Control.
5 *
6 * Copyright (C) 2005-2008 NTT DATA CORPORATION
7 *
8 * Version: 1.6.5-pre 2008/10/07
9 *
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 #include <linux/net.h>
19 #include <linux/inet.h>
20 #include <linux/in.h>
21 #include <linux/in6.h>
22
23 /**
24 * audit_network_log - Audit network log.
25 *
26 * @r: Pointer to "struct ccs_request_info".
27 * @operation: The name of operation.
28 * @address: An IPv4 or IPv6 address.
29 * @port: Port number.
30 * @is_granted: True if this is a granted log.
31 *
32 * Returns 0 on success, negative value otherwise.
33 */
34 static int audit_network_log(struct ccs_request_info *r, const char *operation,
35 const char *address, const u16 port,
36 const bool is_granted)
37 {
38 return ccs_write_audit_log(is_granted, r, KEYWORD_ALLOW_NETWORK
39 "%s %s %u\n", operation, address, port);
40 }
41
42 /**
43 * save_ipv6_address - Keep the given IPv6 address on the RAM.
44 *
45 * @addr: Pointer to "struct in6_addr".
46 *
47 * Returns pointer to "struct in6_addr" on success, NULL otherwise.
48 *
49 * The RAM is shared, so NEVER try to modify or kfree() the returned address.
50 */
51 static const struct in6_addr *save_ipv6_address(const struct in6_addr *addr)
52 {
53 static const u8 block_size = 16;
54 struct addr_list {
55 /* Workaround for gcc 4.3's bug. */
56 struct in6_addr addr[16]; /* = block_size */
57 struct list1_head list;
58 u32 in_use_count;
59 };
60 static LIST1_HEAD(address_list);
61 struct addr_list *ptr;
62 static DEFINE_MUTEX(lock);
63 u8 i = block_size;
64 if (!addr)
65 return NULL;
66 mutex_lock(&lock);
67 list1_for_each_entry(ptr, &address_list, list) {
68 for (i = 0; i < ptr->in_use_count; i++) {
69 if (!memcmp(&ptr->addr[i], addr, sizeof(*addr)))
70 goto ok;
71 }
72 if (i < block_size)
73 break;
74 }
75 if (i == block_size) {
76 ptr = ccs_alloc_element(sizeof(*ptr));
77 if (!ptr)
78 goto ok;
79 list1_add_tail_mb(&ptr->list, &address_list);
80 i = 0;
81 }
82 ptr->addr[ptr->in_use_count++] = *addr;
83 ok:
84 mutex_unlock(&lock);
85 return ptr ? &ptr->addr[i] : NULL;
86 }
87
88 /* The list for "struct address_group_entry". */
89 static LIST1_HEAD(address_group_list);
90
91 /**
92 * update_address_group_entry - Update "struct address_group_entry" list.
93 *
94 * @group_name: The name of address group.
95 * @is_ipv6: True if @min_address and @max_address are IPv6 addresses.
96 * @min_address: Start of IPv4 or IPv6 address range.
97 * @max_address: End of IPv4 or IPv6 address range.
98 * @is_delete: True if it is a delete request.
99 *
100 * Returns 0 on success, negative value otherwise.
101 */
102 static int update_address_group_entry(const char *group_name,
103 const bool is_ipv6,
104 const u16 *min_address,
105 const u16 *max_address,
106 const bool is_delete)
107 {
108 static DEFINE_MUTEX(lock);
109 struct address_group_entry *new_group;
110 struct address_group_entry *group;
111 struct address_group_member *new_member;
112 struct address_group_member *member;
113 const struct path_info *saved_group_name;
114 const struct in6_addr *saved_min_address = NULL;
115 const struct in6_addr *saved_max_address = NULL;
116 int error = -ENOMEM;
117 bool found = false;
118 if (!ccs_is_correct_path(group_name, 0, 0, 0, __func__) ||
119 !group_name[0])
120 return -EINVAL;
121 saved_group_name = ccs_save_name(group_name);
122 if (!saved_group_name)
123 return -ENOMEM;
124 if (!is_ipv6)
125 goto not_ipv6;
126 saved_min_address
127 = save_ipv6_address((struct in6_addr *) min_address);
128 saved_max_address
129 = save_ipv6_address((struct in6_addr *) max_address);
130 if (!saved_min_address || !saved_max_address)
131 return -ENOMEM;
132 not_ipv6:
133 mutex_lock(&lock);
134 list1_for_each_entry(group, &address_group_list, list) {
135 if (saved_group_name != group->group_name)
136 continue;
137 list1_for_each_entry(member, &group->address_group_member_list,
138 list) {
139 if (member->is_ipv6 != is_ipv6)
140 continue;
141 if (is_ipv6) {
142 if (member->min.ipv6 != saved_min_address ||
143 member->max.ipv6 != saved_max_address)
144 continue;
145 } else {
146 if (member->min.ipv4 != *(u32 *) min_address ||
147 member->max.ipv4 != *(u32 *) max_address)
148 continue;
149 }
150 member->is_deleted = is_delete;
151 error = 0;
152 goto out;
153 }
154 found = true;
155 break;
156 }
157 if (is_delete) {
158 error = -ENOENT;
159 goto out;
160 }
161 if (!found) {
162 new_group = ccs_alloc_element(sizeof(*new_group));
163 if (!new_group)
164 goto out;
165 INIT_LIST1_HEAD(&new_group->address_group_member_list);
166 new_group->group_name = saved_group_name;
167 list1_add_tail_mb(&new_group->list, &address_group_list);
168 group = new_group;
169 }
170 new_member = ccs_alloc_element(sizeof(*new_member));
171 if (!new_member)
172 goto out;
173 new_member->is_ipv6 = is_ipv6;
174 if (is_ipv6) {
175 new_member->min.ipv6 = saved_min_address;
176 new_member->max.ipv6 = saved_max_address;
177 } else {
178 new_member->min.ipv4 = *(u32 *) min_address;
179 new_member->max.ipv4 = *(u32 *) max_address;
180 }
181 list1_add_tail_mb(&new_member->list, &group->address_group_member_list);
182 error = 0;
183 out:
184 mutex_unlock(&lock);
185 ccs_update_counter(CCS_UPDATES_COUNTER_EXCEPTION_POLICY);
186 return error;
187 }
188
189 /**
190 * 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 parse_ip_address(char *address, u16 *min, u16 *max)
199 {
200 int count = sscanf(address, "%hx:%hx:%hx:%hx:%hx:%hx:%hx:%hx"
201 "-%hx:%hx:%hx:%hx:%hx:%hx:%hx:%hx",
202 &min[0], &min[1], &min[2], &min[3],
203 &min[4], &min[5], &min[6], &min[7],
204 &max[0], &max[1], &max[2], &max[3],
205 &max[4], &max[5], &max[6], &max[7]);
206 if (count == 8 || count == 16) {
207 u8 i;
208 if (count == 8)
209 memmove(max, min, sizeof(u16) * 8);
210 for (i = 0; i < 8; i++) {
211 min[i] = htons(min[i]);
212 max[i] = htons(max[i]);
213 }
214 return 2;
215 }
216 count = sscanf(address, "%hu.%hu.%hu.%hu-%hu.%hu.%hu.%hu",
217 &min[0], &min[1], &min[2], &min[3],
218 &max[0], &max[1], &max[2], &max[3]);
219 if (count == 4 || count == 8) {
220 u8 *p = (void *) min;
221 *p++ = min[0];
222 *p++ = min[1];
223 *p++ = min[2];
224 *p = min[3];
225 if (count == 4)
226 memmove(max, min, sizeof(u16) * 4);
227 p = (void *) max;
228 *p++ = max[0];
229 *p++ = max[1];
230 *p++ = max[2];
231 *p = max[3];
232 return 1;
233 }
234 return 0;
235 }
236
237 /**
238 * ccs_write_address_group_policy - Write "struct address_group_entry" list.
239 *
240 * @data: String to parse.
241 * @is_delete: True if it is a delete request.
242 *
243 * Returns 0 on success, negative value otherwise.
244 */
245 int ccs_write_address_group_policy(char *data, const bool is_delete)
246 {
247 bool is_ipv6;
248 u16 min_address[8];
249 u16 max_address[8];
250 char *cp = strchr(data, ' ');
251 if (!cp)
252 return -EINVAL;
253 *cp++ = '\0';
254 switch (parse_ip_address(cp, min_address, max_address)) {
255 case 2:
256 is_ipv6 = true;
257 break;
258 case 1:
259 is_ipv6 = false;
260 break;
261 default:
262 return -EINVAL;
263 }
264 return update_address_group_entry(data, is_ipv6,
265 min_address, max_address, is_delete);
266 }
267
268 /**
269 * find_or_assign_new_address_group - Create address group.
270 *
271 * @group_name: The name of address group.
272 *
273 * Returns pointer to "struct address_group_entry" on success, NULL otherwise.
274 */
275 static struct address_group_entry *
276 find_or_assign_new_address_group(const char *group_name)
277 {
278 u8 i;
279 struct address_group_entry *group;
280 for (i = 0; i <= 1; i++) {
281 list1_for_each_entry(group, &address_group_list, list) {
282 if (!strcmp(group_name, group->group_name->name))
283 return group;
284 }
285 if (!i) {
286 const u16 dummy[2] = { 0, 0 };
287 update_address_group_entry(group_name, false,
288 dummy, dummy, false);
289 update_address_group_entry(group_name, false,
290 dummy, dummy, true);
291 }
292 }
293 return NULL;
294 }
295
296 /**
297 * address_matches_to_group - Check whether the given address matches members of the given address group.
298 *
299 * @is_ipv6: True if @address is an IPv6 address.
300 * @address: An IPv4 or IPv6 address.
301 * @group: Pointer to "struct address_group_entry".
302 *
303 * Returns true if @address matches addresses in @group group, false otherwise.
304 */
305 static bool address_matches_to_group(const bool is_ipv6, const u32 *address,
306 const struct address_group_entry *group)
307 {
308 struct address_group_member *member;
309 const u32 ip = ntohl(*address);
310 list1_for_each_entry(member, &group->address_group_member_list, list) {
311 if (member->is_deleted)
312 continue;
313 if (member->is_ipv6) {
314 if (is_ipv6 &&
315 memcmp(member->min.ipv6, address, 16) <= 0 &&
316 memcmp(address, member->max.ipv6, 16) <= 0)
317 return true;
318 } else {
319 if (!is_ipv6 &&
320 member->min.ipv4 <= ip && ip <= member->max.ipv4)
321 return true;
322 }
323 }
324 return false;
325 }
326
327 /**
328 * ccs_read_address_group_policy - Read "struct address_group_entry" list.
329 *
330 * @head: Pointer to "struct ccs_io_buffer".
331 *
332 * Returns true on success, false otherwise.
333 */
334 bool ccs_read_address_group_policy(struct ccs_io_buffer *head)
335 {
336 struct list1_head *gpos;
337 struct list1_head *mpos;
338 list1_for_each_cookie(gpos, head->read_var1, &address_group_list) {
339 struct address_group_entry *group;
340 group = list1_entry(gpos, struct address_group_entry, list);
341 list1_for_each_cookie(mpos, head->read_var2,
342 &group->address_group_member_list) {
343 char buf[128];
344 struct address_group_member *member;
345 member = list1_entry(mpos, struct address_group_member,
346 list);
347 if (member->is_deleted)
348 continue;
349 if (member->is_ipv6) {
350 const struct in6_addr *min_address
351 = member->min.ipv6;
352 const struct in6_addr *max_address
353 = member->max.ipv6;
354 ccs_print_ipv6(buf, sizeof(buf), min_address);
355 if (min_address != max_address) {
356 int len;
357 char *cp = strchr(buf, '\0');
358 *cp++ = '-';
359 len = strlen(buf);
360 ccs_print_ipv6(cp, sizeof(buf) - len,
361 max_address);
362 }
363 } else {
364 const u32 min_address = member->min.ipv4;
365 const u32 max_address = member->max.ipv4;
366 memset(buf, 0, sizeof(buf));
367 snprintf(buf, sizeof(buf) - 1, "%u.%u.%u.%u",
368 HIPQUAD(min_address));
369 if (min_address != max_address) {
370 const int len = strlen(buf);
371 snprintf(buf + len,
372 sizeof(buf) - 1 - len,
373 "-%u.%u.%u.%u",
374 HIPQUAD(max_address));
375 }
376 }
377 if (!ccs_io_printf(head, KEYWORD_ADDRESS_GROUP
378 "%s %s\n", group->group_name->name,
379 buf))
380 goto out;
381 }
382 }
383 return true;
384 out:
385 return false;
386 }
387
388 #if !defined(NIP6)
389 #define NIP6(addr) \
390 ntohs((addr).s6_addr16[0]), ntohs((addr).s6_addr16[1]), \
391 ntohs((addr).s6_addr16[2]), ntohs((addr).s6_addr16[3]), \
392 ntohs((addr).s6_addr16[4]), ntohs((addr).s6_addr16[5]), \
393 ntohs((addr).s6_addr16[6]), ntohs((addr).s6_addr16[7])
394 #endif
395
396 /**
397 * ccs_print_ipv6 - Print an IPv6 address.
398 *
399 * @buffer: Buffer to write to.
400 * @buffer_len: Size of @buffer.
401 * @ip: Pointer to "struct in6_addr".
402 *
403 * Returns nothing.
404 */
405 void ccs_print_ipv6(char *buffer, const int buffer_len,
406 const struct in6_addr *ip)
407 {
408 memset(buffer, 0, buffer_len);
409 snprintf(buffer, buffer_len - 1, "%x:%x:%x:%x:%x:%x:%x:%x", NIP6(*ip));
410 }
411
412 /**
413 * ccs_net2keyword - Convert network operation index to network operation name.
414 *
415 * @operation: Type of operation.
416 *
417 * Returns the name of operation.
418 */
419 const char *ccs_net2keyword(const u8 operation)
420 {
421 const char *keyword = "unknown";
422 switch (operation) {
423 case NETWORK_ACL_UDP_BIND:
424 keyword = "UDP bind";
425 break;
426 case NETWORK_ACL_UDP_CONNECT:
427 keyword = "UDP connect";
428 break;
429 case NETWORK_ACL_TCP_BIND:
430 keyword = "TCP bind";
431 break;
432 case NETWORK_ACL_TCP_LISTEN:
433 keyword = "TCP listen";
434 break;
435 case NETWORK_ACL_TCP_CONNECT:
436 keyword = "TCP connect";
437 break;
438 case NETWORK_ACL_TCP_ACCEPT:
439 keyword = "TCP accept";
440 break;
441 case NETWORK_ACL_RAW_BIND:
442 keyword = "RAW bind";
443 break;
444 case NETWORK_ACL_RAW_CONNECT:
445 keyword = "RAW connect";
446 break;
447 }
448 return keyword;
449 }
450
451 /**
452 * update_network_entry - Update "struct ip_network_acl_record" list.
453 *
454 * @operation: Type of operation.
455 * @record_type: Type of address.
456 * @group: Pointer to "struct address_group_entry". May be NULL.
457 * @min_address: Start of IPv4 or IPv6 address range.
458 * @max_address: End of IPv4 or IPv6 address range.
459 * @min_port: Start of port number range.
460 * @max_port: End of port number range.
461 * @domain: Pointer to "struct domain_info".
462 * @condition: Pointer to "struct condition_list". May be NULL.
463 * @is_delete: True if it is a delete request.
464 *
465 * Returns 0 on success, negative value otherwise.
466 */
467 static int update_network_entry(const u8 operation, const u8 record_type,
468 const struct address_group_entry *group,
469 const u32 *min_address, const u32 *max_address,
470 const u16 min_port, const u16 max_port,
471 struct domain_info *domain,
472 const struct condition_list *condition,
473 const bool is_delete)
474 {
475 struct acl_info *ptr;
476 struct ip_network_acl_record *acl;
477 int error = -ENOMEM;
478 /* using host byte order to allow u32 comparison than memcmp().*/
479 const u32 min_ip = ntohl(*min_address);
480 const u32 max_ip = ntohl(*max_address);
481 const struct in6_addr *saved_min_address = NULL;
482 const struct in6_addr *saved_max_address = NULL;
483 if (!domain)
484 return -EINVAL;
485 if (record_type != IP_RECORD_TYPE_IPv6)
486 goto not_ipv6;
487 saved_min_address = save_ipv6_address((struct in6_addr *) min_address);
488 saved_max_address = save_ipv6_address((struct in6_addr *) max_address);
489 if (!saved_min_address || !saved_max_address)
490 return -ENOMEM;
491 not_ipv6:
492 mutex_lock(&domain_acl_lock);
493 if (is_delete)
494 goto delete;
495 list1_for_each_entry(ptr, &domain->acl_info_list, list) {
496 if (ccs_acl_type1(ptr) != TYPE_IP_NETWORK_ACL)
497 continue;
498 if (ccs_get_condition_part(ptr) != condition)
499 continue;
500 acl = container_of(ptr, struct ip_network_acl_record, head);
501 if (acl->operation_type != operation ||
502 acl->record_type != record_type ||
503 acl->min_port != min_port || max_port != acl->max_port)
504 continue;
505 if (record_type == IP_RECORD_TYPE_ADDRESS_GROUP) {
506 if (acl->u.group != group)
507 continue;
508 } else if (record_type == IP_RECORD_TYPE_IPv4) {
509 if (acl->u.ipv4.min != min_ip ||
510 max_ip != acl->u.ipv4.max)
511 continue;
512 } else if (record_type == IP_RECORD_TYPE_IPv6) {
513 if (acl->u.ipv6.min != saved_min_address ||
514 saved_max_address != acl->u.ipv6.max)
515 continue;
516 }
517 error = ccs_add_domain_acl(NULL, ptr);
518 goto out;
519 }
520 /* Not found. Append it to the tail. */
521 acl = ccs_alloc_acl_element(TYPE_IP_NETWORK_ACL, condition);
522 if (!acl)
523 goto out;
524 acl->operation_type = operation;
525 acl->record_type = record_type;
526 if (record_type == IP_RECORD_TYPE_ADDRESS_GROUP) {
527 acl->u.group = group;
528 } else if (record_type == IP_RECORD_TYPE_IPv4) {
529 acl->u.ipv4.min = min_ip;
530 acl->u.ipv4.max = max_ip;
531 } else {
532 acl->u.ipv6.min = saved_min_address;
533 acl->u.ipv6.max = saved_max_address;
534 }
535 acl->min_port = min_port;
536 acl->max_port = max_port;
537 error = ccs_add_domain_acl(domain, &acl->head);
538 goto out;
539 delete:
540 error = -ENOENT;
541 list1_for_each_entry(ptr, &domain->acl_info_list, list) {
542 if (ccs_acl_type2(ptr) != TYPE_IP_NETWORK_ACL)
543 continue;
544 if (ccs_get_condition_part(ptr) != condition)
545 continue;
546 acl = container_of(ptr, struct ip_network_acl_record, head);
547 if (acl->operation_type != operation ||
548 acl->record_type != record_type ||
549 acl->min_port != min_port || max_port != acl->max_port)
550 continue;
551 if (record_type == IP_RECORD_TYPE_ADDRESS_GROUP) {
552 if (acl->u.group != group)
553 continue;
554 } else if (record_type == IP_RECORD_TYPE_IPv4) {
555 if (acl->u.ipv4.min != min_ip ||
556 max_ip != acl->u.ipv4.max)
557 continue;
558 } else if (record_type == IP_RECORD_TYPE_IPv6) {
559 if (acl->u.ipv6.min != saved_min_address ||
560 saved_max_address != acl->u.ipv6.max)
561 continue;
562 }
563 error = ccs_del_domain_acl(ptr);
564 break;
565 }
566 out:
567 mutex_unlock(&domain_acl_lock);
568 return error;
569 }
570
571 /**
572 * check_network_entry - 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 static int check_network_entry(const bool is_ipv6, const u8 operation,
582 const u32 *address, const u16 port)
583 {
584 struct ccs_request_info r;
585 struct acl_info *ptr;
586 const char *keyword = ccs_net2keyword(operation);
587 bool is_enforce;
588 /* using host byte order to allow u32 comparison than memcmp().*/
589 const u32 ip = ntohl(*address);
590 bool found = false;
591 char buf[64];
592 if (!ccs_can_sleep())
593 return 0;
594 ccs_init_request_info(&r, NULL, CCS_TOMOYO_MAC_FOR_NETWORK);
595 is_enforce = (r.mode == 3);
596 if (!r.mode)
597 return 0;
598 retry:
599 list1_for_each_entry(ptr, &r.domain->acl_info_list, list) {
600 struct ip_network_acl_record *acl;
601 if (ccs_acl_type2(ptr) != TYPE_IP_NETWORK_ACL)
602 continue;
603 acl = container_of(ptr, struct ip_network_acl_record, head);
604 if (acl->operation_type != operation || port < acl->min_port ||
605 acl->max_port < port || !ccs_check_condition(&r, ptr))
606 continue;
607 if (acl->record_type == IP_RECORD_TYPE_ADDRESS_GROUP) {
608 if (!address_matches_to_group(is_ipv6, address,
609 acl->u.group))
610 continue;
611 } else if (acl->record_type == IP_RECORD_TYPE_IPv4) {
612 if (is_ipv6 ||
613 ip < acl->u.ipv4.min || acl->u.ipv4.max < ip)
614 continue;
615 } else {
616 if (!is_ipv6 ||
617 memcmp(acl->u.ipv6.min, address, 16) > 0 ||
618 memcmp(address, acl->u.ipv6.max, 16) > 0)
619 continue;
620 }
621 ccs_update_condition(ptr);
622 found = true;
623 break;
624 }
625 memset(buf, 0, sizeof(buf));
626 if (is_ipv6)
627 ccs_print_ipv6(buf, sizeof(buf),
628 (const struct in6_addr *) address);
629 else
630 snprintf(buf, sizeof(buf) - 1, "%u.%u.%u.%u", HIPQUAD(ip));
631 audit_network_log(&r, keyword, buf, port, found);
632 if (found)
633 return 0;
634 if (ccs_verbose_mode(r.domain))
635 printk(KERN_WARNING "TOMOYO-%s: %s to %s %u denied for %s\n",
636 ccs_get_msg(is_enforce), keyword, buf, port,
637 ccs_get_last_name(r.domain));
638 if (is_enforce) {
639 int error = ccs_check_supervisor(&r, KEYWORD_ALLOW_NETWORK
640 "%s %s %u\n", keyword, buf,
641 port);
642 if (error == 1) {
643 r.retry++;
644 goto retry;
645 }
646 return error;
647 }
648 if (r.mode == 1 && ccs_check_domain_quota(r.domain))
649 update_network_entry(operation, is_ipv6 ?
650 IP_RECORD_TYPE_IPv6 : IP_RECORD_TYPE_IPv4,
651 NULL, address, address, port, port,
652 r.domain, NULL, 0);
653 return 0;
654 }
655
656 /**
657 * ccs_write_network_policy - Write "struct ip_network_acl_record" list.
658 *
659 * @data: String to parse.
660 * @domain: Pointer to "struct domain_info".
661 * @condition: Pointer to "struct condition_list". May be NULL.
662 * @is_delete: True if it is a delete request.
663 *
664 * Returns 0 on success, negative value otherwise.
665 */
666 int ccs_write_network_policy(char *data, struct domain_info *domain,
667 const struct condition_list *condition,
668 const bool is_delete)
669 {
670 u8 sock_type;
671 u8 operation;
672 u8 record_type;
673 u16 min_address[8];
674 u16 max_address[8];
675 struct address_group_entry *group = NULL;
676 u16 min_port;
677 u16 max_port;
678 u8 count;
679 char *cp1 = strchr(data, ' ');
680 char *cp2;
681 if (!cp1)
682 goto out;
683 cp1++;
684 if (!strncmp(data, "TCP ", 4))
685 sock_type = SOCK_STREAM;
686 else if (!strncmp(data, "UDP ", 4))
687 sock_type = SOCK_DGRAM;
688 else if (!strncmp(data, "RAW ", 4))
689 sock_type = SOCK_RAW;
690 else
691 goto out;
692 cp2 = strchr(cp1, ' ');
693 if (!cp2)
694 goto out;
695 cp2++;
696 if (!strncmp(cp1, "bind ", 5))
697 switch (sock_type) {
698 case SOCK_STREAM:
699 operation = NETWORK_ACL_TCP_BIND;
700 break;
701 case SOCK_DGRAM:
702 operation = NETWORK_ACL_UDP_BIND;
703 break;
704 default:
705 operation = NETWORK_ACL_RAW_BIND;
706 }
707 else if (!strncmp(cp1, "connect ", 8))
708 switch (sock_type) {
709 case SOCK_STREAM:
710 operation = NETWORK_ACL_TCP_CONNECT;
711 break;
712 case SOCK_DGRAM:
713 operation = NETWORK_ACL_UDP_CONNECT;
714 break;
715 default:
716 operation = NETWORK_ACL_RAW_CONNECT;
717 }
718 else if (sock_type == SOCK_STREAM && !strncmp(cp1, "listen ", 7))
719 operation = NETWORK_ACL_TCP_LISTEN;
720 else if (sock_type == SOCK_STREAM && !strncmp(cp1, "accept ", 7))
721 operation = NETWORK_ACL_TCP_ACCEPT;
722 else
723 goto out;
724 cp1 = strchr(cp2, ' ');
725 if (!cp1)
726 goto out;
727 *cp1++ = '\0';
728 switch (parse_ip_address(cp2, min_address, max_address)) {
729 case 2:
730 record_type = IP_RECORD_TYPE_IPv6;
731 break;
732 case 1:
733 record_type = IP_RECORD_TYPE_IPv4;
734 break;
735 default:
736 if (*cp2 != '@')
737 goto out;
738 group = find_or_assign_new_address_group(cp2 + 1);
739 if (!group)
740 return -ENOMEM;
741 record_type = IP_RECORD_TYPE_ADDRESS_GROUP;
742 break;
743 }
744 if (strchr(cp1, ' '))
745 goto out;
746 count = sscanf(cp1, "%hu-%hu", &min_port, &max_port);
747 if (count != 1 && count != 2)
748 goto out;
749 if (count == 1)
750 max_port = min_port;
751 return update_network_entry(operation, record_type, group,
752 (u32 *) min_address, (u32 *) max_address,
753 min_port, max_port, domain, condition,
754 is_delete);
755 out:
756 return -EINVAL;
757 }
758
759 /**
760 * ccs_check_network_listen_acl - Check permission for listen() operation.
761 *
762 * @is_ipv6: True if @address is an IPv6 address.
763 * @address: An IPv4 or IPv6 address.
764 * @port: Port number.
765 *
766 * Returns 0 on success, negative value otherwise.
767 */
768 int ccs_check_network_listen_acl(const _Bool is_ipv6, const u8 *address,
769 const u16 port)
770 {
771 return check_network_entry(is_ipv6, NETWORK_ACL_TCP_LISTEN,
772 (const u32 *) address, ntohs(port));
773 }
774
775 /**
776 * ccs_check_network_connect_acl - Check permission for connect() operation.
777 *
778 * @is_ipv6: True if @address is an IPv6 address.
779 * @sock_type: Type of socket. (TCP or UDP or RAW)
780 * @address: An IPv4 or IPv6 address.
781 * @port: Port number.
782 *
783 * Returns 0 on success, negative value otherwise.
784 */
785 int ccs_check_network_connect_acl(const _Bool is_ipv6, const int sock_type,
786 const u8 *address, const u16 port)
787 {
788 u8 operation;
789 switch (sock_type) {
790 case SOCK_STREAM:
791 operation = NETWORK_ACL_TCP_CONNECT;
792 break;
793 case SOCK_DGRAM:
794 operation = NETWORK_ACL_UDP_CONNECT;
795 break;
796 default:
797 operation = NETWORK_ACL_RAW_CONNECT;
798 }
799 return check_network_entry(is_ipv6, operation, (const u32 *) address,
800 ntohs(port));
801 }
802
803 /**
804 * ccs_check_network_bind_acl - Check permission for bind() operation.
805 *
806 * @is_ipv6: True if @address is an IPv6 address.
807 * @sock_type: Type of socket. (TCP or UDP or RAW)
808 * @address: An IPv4 or IPv6 address.
809 * @port: Port number.
810 *
811 * Returns 0 on success, negative value otherwise.
812 */
813 int ccs_check_network_bind_acl(const _Bool is_ipv6, const int sock_type,
814 const u8 *address, const u16 port)
815 {
816 u8 operation;
817 switch (sock_type) {
818 case SOCK_STREAM:
819 operation = NETWORK_ACL_TCP_BIND;
820 break;
821 case SOCK_DGRAM:
822 operation = NETWORK_ACL_UDP_BIND;
823 break;
824 default:
825 operation = NETWORK_ACL_RAW_BIND;
826 }
827 return check_network_entry(is_ipv6, operation, (const u32 *) address,
828 ntohs(port));
829 }
830
831 /**
832 * ccs_check_network_accept_acl - Check permission for accept() operation.
833 *
834 * @is_ipv6: True if @address is an IPv6 address.
835 * @address: An IPv4 or IPv6 address.
836 * @port: Port number.
837 *
838 * Returns 0 on success, negative value otherwise.
839 */
840 int ccs_check_network_accept_acl(const _Bool is_ipv6, const u8 *address,
841 const u16 port)
842 {
843 int retval;
844 current->tomoyo_flags |= CCS_DONT_SLEEP_ON_ENFORCE_ERROR;
845 retval = check_network_entry(is_ipv6, NETWORK_ACL_TCP_ACCEPT,
846 (const u32 *) address, ntohs(port));
847 current->tomoyo_flags &= ~CCS_DONT_SLEEP_ON_ENFORCE_ERROR;
848 return retval;
849 }
850
851 /**
852 * ccs_check_network_sendmsg_acl - Check permission for sendmsg() operation.
853 *
854 * @is_ipv6: True if @address is an IPv6 address.
855 * @sock_type: Type of socket. (UDP or RAW)
856 * @address: An IPv4 or IPv6 address.
857 * @port: Port number.
858 *
859 * Returns 0 on success, negative value otherwise.
860 */
861 int ccs_check_network_sendmsg_acl(const _Bool is_ipv6, const int sock_type,
862 const u8 *address, const u16 port)
863 {
864 u8 operation;
865 if (sock_type == SOCK_DGRAM)
866 operation = NETWORK_ACL_UDP_CONNECT;
867 else
868 operation = NETWORK_ACL_RAW_CONNECT;
869 return check_network_entry(is_ipv6, operation, (const u32 *) address,
870 ntohs(port));
871 }
872
873 /**
874 * ccs_check_network_recvmsg_acl - Check permission for recvmsg() operation.
875 *
876 * @is_ipv6: True if @address is an IPv6 address.
877 * @sock_type: Type of socket. (UDP or RAW)
878 * @address: An IPv4 or IPv6 address.
879 * @port: Port number.
880 *
881 * Returns 0 on success, negative value otherwise.
882 */
883 int ccs_check_network_recvmsg_acl(const _Bool is_ipv6, const int sock_type,
884 const u8 *address, const u16 port)
885 {
886 int retval;
887 const u8 operation
888 = (sock_type == SOCK_DGRAM) ?
889 NETWORK_ACL_UDP_CONNECT : NETWORK_ACL_RAW_CONNECT;
890 current->tomoyo_flags |= CCS_DONT_SLEEP_ON_ENFORCE_ERROR;
891 retval = check_network_entry(is_ipv6, operation, (const u32 *) address,
892 ntohs(port));
893 current->tomoyo_flags &= ~CCS_DONT_SLEEP_ON_ENFORCE_ERROR;
894 return retval;
895 }

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