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

Subversion リポジトリの参照

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

Parent Directory Parent Directory | Revision Log Revision Log


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

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