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

Subversion リポジトリの参照

Contents of /branches/ccs-patch/security/ccsecurity/network.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 2540 - (show annotations) (download) (as text)
Thu May 14 00:08:32 2009 UTC (15 years ago) by kumaneko
Original Path: branches/ccs-patch/fs/tomoyo_network.c
File MIME type: text/x-csrc
File size: 35946 byte(s)


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

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