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

Subversion リポジトリの参照

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

Parent Directory Parent Directory | Revision Log Revision Log


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

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