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

Subversion リポジトリの参照

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

Parent Directory Parent Directory | Revision Log Revision Log


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

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