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

Subversion リポジトリの参照

Contents of /trunk/1.8.x/ccs-patch/security/ccsecurity/network.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 2854 - (show annotations) (download) (as text)
Wed Aug 5 11:57:20 2009 UTC (14 years, 10 months ago) by kumaneko
Original Path: branches/ccs-patch/fs/ccsecurity/network.c
File MIME type: text/x-csrc
File size: 35919 byte(s)


1 /*
2 * fs/ccsecurity/network.c
3 *
4 * Copyright (C) 2005-2009 NTT DATA CORPORATION
5 *
6 * Version: 1.7.0-pre 2009/07/03
7 *
8 * This file is applicable to both 2.4.30 and 2.6.11 and later.
9 * See README.ccs for ChangeLog.
10 *
11 */
12
13 #include <linux/net.h>
14 #include <linux/inet.h>
15 #include <linux/in.h>
16 #include <linux/in6.h>
17 #include <net/ip.h>
18 #include <net/ipv6.h>
19 #include <net/udp.h>
20 #include "internal.h"
21 #include <linux/ccsecurity.h>
22 #include <linux/ccsecurity_socket.h>
23
24 /* Index numbers for Network Controls. */
25 enum ccs_network_acl_index {
26 NETWORK_ACL_UDP_BIND,
27 NETWORK_ACL_UDP_CONNECT,
28 NETWORK_ACL_TCP_BIND,
29 NETWORK_ACL_TCP_LISTEN,
30 NETWORK_ACL_TCP_CONNECT,
31 NETWORK_ACL_TCP_ACCEPT,
32 NETWORK_ACL_RAW_BIND,
33 NETWORK_ACL_RAW_CONNECT
34 };
35
36 /**
37 * ccs_audit_network_log - Audit network log.
38 *
39 * @r: Pointer to "struct ccs_request_info".
40 * @operation: The name of operation.
41 * @address: An IPv4 or IPv6 address.
42 * @port: Port number.
43 * @is_granted: True if this is a granted log.
44 *
45 * Returns 0 on success, negative value otherwise.
46 */
47 static int ccs_audit_network_log(struct ccs_request_info *r,
48 const char *operation, const char *address,
49 const u16 port, const bool is_granted)
50 {
51 if (!is_granted && ccs_verbose_mode(r->domain))
52 printk(KERN_WARNING "TOMOYO-%s: %s to %s %u denied for %s\n",
53 ccs_get_msg(r->mode == 3), operation, address, port,
54 ccs_get_last_name(r->domain));
55 return ccs_write_audit_log(is_granted, r, KEYWORD_ALLOW_NETWORK
56 "%s %s %u\n", operation, address, port);
57 }
58
59 /* The list for "struct ccs_address_group_entry". */
60 LIST_HEAD(ccs_address_group_list);
61
62 /**
63 * ccs_get_address_group - Allocate memory for "struct ccs_address_group_entry".
64 *
65 * @group_name: The name of address group.
66 *
67 * Returns pointer to "struct ccs_address_group_entry" on success,
68 * NULL otherwise.
69 */
70 static struct ccs_address_group_entry *ccs_get_address_group(const char *
71 group_name)
72 {
73 struct ccs_address_group_entry *entry = NULL;
74 struct ccs_address_group_entry *group;
75 const struct ccs_path_info *saved_group_name;
76 int error = -ENOMEM;
77 if (!ccs_is_correct_path(group_name, 0, 0, 0) ||
78 !group_name[0])
79 return NULL;
80 saved_group_name = ccs_get_name(group_name);
81 if (!saved_group_name)
82 return NULL;
83 entry = kzalloc(sizeof(*entry), GFP_KERNEL);
84 mutex_lock(&ccs_policy_lock);
85 list_for_each_entry_rcu(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, sizeof(*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_rcu(&entry->list, &ccs_address_group_list);
98 group = entry;
99 entry = NULL;
100 error = 0;
101 }
102 mutex_unlock(&ccs_policy_lock);
103 ccs_put_name(saved_group_name);
104 kfree(entry);
105 return !error ? group : NULL;
106 }
107
108 /**
109 * ccs_update_address_group_entry - Update "struct ccs_address_group_entry" list.
110 *
111 * @group_name: The name of address group.
112 * @is_ipv6: True if @min_address and @max_address are IPv6 addresses.
113 * @min_address: Start of IPv4 or IPv6 address range.
114 * @max_address: End of IPv4 or IPv6 address range.
115 * @is_delete: True if it is a delete request.
116 *
117 * Returns 0 on success, negative value otherwise.
118 */
119 static int ccs_update_address_group_entry(const char *group_name,
120 const bool is_ipv6,
121 const u16 *min_address,
122 const u16 *max_address,
123 const bool is_delete)
124 {
125 struct ccs_address_group_entry *group;
126 struct ccs_address_group_member *entry = NULL;
127 struct ccs_address_group_member *member;
128 const struct in6_addr *saved_min_address = NULL;
129 const struct in6_addr *saved_max_address = NULL;
130 int error = is_delete ? -ENOENT : -ENOMEM;
131 const u32 min_ipv4_address = ntohl(*(u32 *) min_address);
132 const u32 max_ipv4_address = ntohl(*(u32 *) max_address);
133 group = ccs_get_address_group(group_name);
134 if (!group)
135 return -ENOMEM;
136 if (is_ipv6) {
137 saved_min_address
138 = ccs_get_ipv6_address((struct in6_addr *)
139 min_address);
140 saved_max_address
141 = ccs_get_ipv6_address((struct in6_addr *)
142 max_address);
143 if (!saved_min_address || !saved_max_address)
144 goto out;
145 }
146 if (!is_delete)
147 entry = kzalloc(sizeof(*entry), GFP_KERNEL);
148 mutex_lock(&ccs_policy_lock);
149 list_for_each_entry_rcu(member, &group->address_group_member_list,
150 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, sizeof(*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_rcu(&entry->list,
178 &group->address_group_member_list);
179 entry = NULL;
180 error = 0;
181 }
182 mutex_unlock(&ccs_policy_lock);
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 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 char *w[2];
244 bool is_ipv6;
245 u16 min_address[8];
246 u16 max_address[8];
247 if (!ccs_tokenize(data, w, sizeof(w)) || !w[1][0])
248 return -EINVAL;
249 switch (ccs_parse_ip_address(w[1], 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(w[0], 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 ccs_read_lock().
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 ccs_check_read_lock();
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 ccs_read_lock().
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 ccs_check_read_lock();
319 list_for_each_cookie(gpos, head->read_var1, &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,
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 return done;
369 }
370
371 #if !defined(NIP6)
372 #define NIP6(addr) \
373 ntohs((addr).s6_addr16[0]), ntohs((addr).s6_addr16[1]), \
374 ntohs((addr).s6_addr16[2]), ntohs((addr).s6_addr16[3]), \
375 ntohs((addr).s6_addr16[4]), ntohs((addr).s6_addr16[5]), \
376 ntohs((addr).s6_addr16[6]), ntohs((addr).s6_addr16[7])
377 #endif
378
379 /**
380 * ccs_print_ipv6 - Print an IPv6 address.
381 *
382 * @buffer: Buffer to write to.
383 * @buffer_len: Size of @buffer.
384 * @ip: Pointer to "struct in6_addr".
385 *
386 * Returns nothing.
387 */
388 void ccs_print_ipv6(char *buffer, const int buffer_len,
389 const struct in6_addr *ip)
390 {
391 memset(buffer, 0, buffer_len);
392 snprintf(buffer, buffer_len - 1, "%x:%x:%x:%x:%x:%x:%x:%x", NIP6(*ip));
393 }
394
395 /**
396 * ccs_net2keyword - Convert network operation index to network operation name.
397 *
398 * @operation: Type of operation.
399 *
400 * Returns the name of operation.
401 */
402 const char *ccs_net2keyword(const u8 operation)
403 {
404 const char *keyword = "unknown";
405 switch (operation) {
406 case NETWORK_ACL_UDP_BIND:
407 keyword = "UDP bind";
408 break;
409 case NETWORK_ACL_UDP_CONNECT:
410 keyword = "UDP connect";
411 break;
412 case NETWORK_ACL_TCP_BIND:
413 keyword = "TCP bind";
414 break;
415 case NETWORK_ACL_TCP_LISTEN:
416 keyword = "TCP listen";
417 break;
418 case NETWORK_ACL_TCP_CONNECT:
419 keyword = "TCP connect";
420 break;
421 case NETWORK_ACL_TCP_ACCEPT:
422 keyword = "TCP accept";
423 break;
424 case NETWORK_ACL_RAW_BIND:
425 keyword = "RAW bind";
426 break;
427 case NETWORK_ACL_RAW_CONNECT:
428 keyword = "RAW connect";
429 break;
430 }
431 return keyword;
432 }
433
434 /**
435 * ccs_update_network_entry - Update "struct ccs_ip_network_acl_record" list.
436 *
437 * @operation: Type of operation.
438 * @record_type: Type of address.
439 * @group: Name of group. May be NULL.
440 * @min_address: Start of IPv4 or IPv6 address range.
441 * @max_address: End of IPv4 or IPv6 address range.
442 * @min_port: Start of port number range.
443 * @max_port: End of port number range.
444 * @domain: Pointer to "struct ccs_domain_info".
445 * @condition: Pointer to "struct ccs_condition". May be NULL.
446 * @is_delete: True if it is a delete request.
447 *
448 * Returns 0 on success, negative value otherwise.
449 */
450 static int ccs_update_network_entry(const u8 operation, const u8 record_type,
451 const char *group_name,
452 const u32 *min_address,
453 const u32 *max_address,
454 const u16 min_port, const u16 max_port,
455 struct ccs_domain_info *domain,
456 struct ccs_condition *condition,
457 const bool is_delete)
458 {
459 struct ccs_ip_network_acl_record *entry = NULL;
460 struct ccs_acl_info *ptr;
461 int error = is_delete ? -ENOENT : -ENOMEM;
462 /* using host byte order to allow u32 comparison than memcmp().*/
463 const u32 min_ip = ntohl(*min_address);
464 const u32 max_ip = ntohl(*max_address);
465 const struct in6_addr *saved_min_address = NULL;
466 const struct in6_addr *saved_max_address = NULL;
467 struct ccs_address_group_entry *group = NULL;
468 if (!domain)
469 return -EINVAL;
470 if (group_name) {
471 group = ccs_get_address_group(group_name);
472 if (!group)
473 return -ENOMEM;
474 } else if (record_type == IP_RECORD_TYPE_IPv6) {
475 saved_min_address = ccs_get_ipv6_address((struct in6_addr *)
476 min_address);
477 saved_max_address = ccs_get_ipv6_address((struct in6_addr *)
478 max_address);
479 if (!saved_min_address || !saved_max_address)
480 goto out;
481 }
482 if (is_delete)
483 goto delete;
484 entry = kzalloc(sizeof(*entry), GFP_KERNEL);
485 mutex_lock(&ccs_policy_lock);
486 list_for_each_entry_rcu(ptr, &domain->acl_info_list, list) {
487 struct ccs_ip_network_acl_record *acl;
488 if (ccs_acl_type1(ptr) != TYPE_IP_NETWORK_ACL)
489 continue;
490 if (ptr->cond != condition)
491 continue;
492 acl = container_of(ptr, struct ccs_ip_network_acl_record, head);
493 if (acl->operation_type != operation ||
494 acl->record_type != record_type ||
495 acl->min_port != min_port || max_port != acl->max_port)
496 continue;
497 if (record_type == IP_RECORD_TYPE_ADDRESS_GROUP) {
498 if (acl->u.group != group)
499 continue;
500 } else if (record_type == IP_RECORD_TYPE_IPv4) {
501 if (acl->u.ipv4.min != min_ip ||
502 max_ip != acl->u.ipv4.max)
503 continue;
504 } else if (record_type == IP_RECORD_TYPE_IPv6) {
505 if (acl->u.ipv6.min != saved_min_address ||
506 saved_max_address != acl->u.ipv6.max)
507 continue;
508 }
509 error = ccs_add_domain_acl(NULL, ptr);
510 break;
511 }
512 if (error && ccs_memory_ok(entry, sizeof(*entry))) {
513 entry->head.type = TYPE_IP_NETWORK_ACL;
514 entry->head.cond = condition;
515 entry->operation_type = operation;
516 entry->record_type = record_type;
517 if (record_type == IP_RECORD_TYPE_ADDRESS_GROUP) {
518 entry->u.group = group;
519 group = NULL;
520 } else if (record_type == IP_RECORD_TYPE_IPv4) {
521 entry->u.ipv4.min = min_ip;
522 entry->u.ipv4.max = max_ip;
523 } else {
524 entry->u.ipv6.min = saved_min_address;
525 saved_min_address = NULL;
526 entry->u.ipv6.max = saved_max_address;
527 saved_max_address = NULL;
528 }
529 entry->min_port = min_port;
530 entry->max_port = max_port;
531 error = ccs_add_domain_acl(domain, &entry->head);
532 entry = NULL;
533 }
534 mutex_unlock(&ccs_policy_lock);
535 goto out;
536 delete:
537 mutex_lock(&ccs_policy_lock);
538 list_for_each_entry_rcu(ptr, &domain->acl_info_list, list) {
539 struct ccs_ip_network_acl_record *acl;
540 if (ccs_acl_type2(ptr) != TYPE_IP_NETWORK_ACL)
541 continue;
542 if (ptr->cond != condition)
543 continue;
544 acl = container_of(ptr, struct ccs_ip_network_acl_record, head);
545 if (acl->operation_type != operation ||
546 acl->record_type != record_type ||
547 acl->min_port != min_port || max_port != acl->max_port)
548 continue;
549 if (record_type == IP_RECORD_TYPE_ADDRESS_GROUP) {
550 if (acl->u.group != group)
551 continue;
552 } else if (record_type == IP_RECORD_TYPE_IPv4) {
553 if (acl->u.ipv4.min != min_ip ||
554 max_ip != acl->u.ipv4.max)
555 continue;
556 } else if (record_type == IP_RECORD_TYPE_IPv6) {
557 if (acl->u.ipv6.min != saved_min_address ||
558 saved_max_address != acl->u.ipv6.max)
559 continue;
560 }
561 error = ccs_del_domain_acl(ptr);
562 break;
563 }
564 mutex_unlock(&ccs_policy_lock);
565 out:
566 ccs_put_ipv6_address(saved_min_address);
567 ccs_put_ipv6_address(saved_max_address);
568 ccs_put_address_group(group);
569 kfree(entry);
570 return error;
571 }
572
573 /**
574 * ccs_check_network_entry2 - Check permission for network operation.
575 *
576 * @is_ipv6: True if @address is an IPv6 address.
577 * @operation: Type of operation.
578 * @address: An IPv4 or IPv6 address.
579 * @port: Port number.
580 *
581 * Returns 0 on success, negative value otherwise.
582 *
583 * Caller holds ccs_read_lock().
584 */
585 static int ccs_check_network_entry2(const bool is_ipv6, const u8 operation,
586 const u32 *address, const u16 port)
587 {
588 struct ccs_request_info r;
589 struct ccs_acl_info *ptr;
590 const char *keyword = ccs_net2keyword(operation);
591 bool is_enforce;
592 /* using host byte order to allow u32 comparison than memcmp().*/
593 const u32 ip = ntohl(*address);
594 bool found = false;
595 char buf[64];
596 ccs_check_read_lock();
597 if (!ccs_can_sleep())
598 return 0;
599 ccs_init_request_info(&r, NULL, CCS_MAC_FOR_NETWORK);
600 is_enforce = (r.mode == 3);
601 if (!r.mode)
602 return 0;
603 retry:
604 list_for_each_entry_rcu(ptr, &r.domain->acl_info_list, list) {
605 struct ccs_ip_network_acl_record *acl;
606 if (ccs_acl_type2(ptr) != TYPE_IP_NETWORK_ACL)
607 continue;
608 acl = container_of(ptr, struct ccs_ip_network_acl_record, head);
609 if (acl->operation_type != operation || port < acl->min_port ||
610 acl->max_port < port || !ccs_check_condition(&r, ptr))
611 continue;
612 if (acl->record_type == IP_RECORD_TYPE_ADDRESS_GROUP) {
613 if (!ccs_address_matches_group(is_ipv6, address,
614 acl->u.group))
615 continue;
616 } else if (acl->record_type == IP_RECORD_TYPE_IPv4) {
617 if (is_ipv6 ||
618 ip < acl->u.ipv4.min || acl->u.ipv4.max < ip)
619 continue;
620 } else {
621 if (!is_ipv6 ||
622 memcmp(acl->u.ipv6.min, address, 16) > 0 ||
623 memcmp(address, acl->u.ipv6.max, 16) > 0)
624 continue;
625 }
626 r.cond = ptr->cond;
627 found = true;
628 break;
629 }
630 memset(buf, 0, sizeof(buf));
631 if (is_ipv6)
632 ccs_print_ipv6(buf, sizeof(buf),
633 (const struct in6_addr *) address);
634 else
635 snprintf(buf, sizeof(buf) - 1, "%u.%u.%u.%u", HIPQUAD(ip));
636 ccs_audit_network_log(&r, keyword, buf, port, found);
637 if (found)
638 return 0;
639 if (is_enforce) {
640 int err = ccs_check_supervisor(&r, KEYWORD_ALLOW_NETWORK
641 "%s %s %u\n", keyword, buf,
642 port);
643 if (err == 1)
644 goto retry;
645 return err;
646 } else if (ccs_domain_quota_ok(&r)) {
647 struct ccs_condition *cond = ccs_handler_cond();
648 ccs_update_network_entry(operation, is_ipv6 ?
649 IP_RECORD_TYPE_IPv6 :
650 IP_RECORD_TYPE_IPv4,
651 NULL, address, address, port, port,
652 r.domain, cond, false);
653 ccs_put_condition(cond);
654 }
655 return 0;
656 }
657
658 /**
659 * ccs_check_network_entry - Check permission for network operation.
660 *
661 * @is_ipv6: True if @address is an IPv6 address.
662 * @operation: Type of operation.
663 * @address: An IPv4 or IPv6 address.
664 * @port: Port number.
665 *
666 * Returns 0 on success, negative value otherwise.
667 */
668 static int ccs_check_network_entry(const bool is_ipv6, const u8 operation,
669 const u32 *address, const u16 port)
670 {
671 const int idx = ccs_read_lock();
672 const int error = ccs_check_network_entry2(is_ipv6, operation,
673 address, port);
674 ccs_read_unlock(idx);
675 return error;
676 }
677
678 /**
679 * ccs_write_network_policy - Write "struct ccs_ip_network_acl_record" list.
680 *
681 * @data: String to parse.
682 * @domain: Pointer to "struct ccs_domain_info".
683 * @condition: Pointer to "struct ccs_condition". May be NULL.
684 * @is_delete: True if it is a delete request.
685 *
686 * Returns 0 on success, negative value otherwise.
687 */
688 int ccs_write_network_policy(char *data, struct ccs_domain_info *domain,
689 struct ccs_condition *condition,
690 const bool is_delete)
691 {
692 char *w[4];
693 u8 sock_type;
694 u8 operation;
695 u8 record_type;
696 u16 min_address[8];
697 u16 max_address[8];
698 const char *group_name = NULL;
699 u16 min_port;
700 u16 max_port;
701 u8 count;
702 if (!ccs_tokenize(data, w, sizeof(w)) || !w[3][0])
703 return -EINVAL;
704 if (!strcmp(w[0], "TCP"))
705 sock_type = SOCK_STREAM;
706 else if (!strcmp(w[0], "UDP"))
707 sock_type = SOCK_DGRAM;
708 else if (!strcmp(w[0], "RAW"))
709 sock_type = SOCK_RAW;
710 else
711 goto out;
712 if (!strcmp(w[1], "bind"))
713 switch (sock_type) {
714 case SOCK_STREAM:
715 operation = NETWORK_ACL_TCP_BIND;
716 break;
717 case SOCK_DGRAM:
718 operation = NETWORK_ACL_UDP_BIND;
719 break;
720 default:
721 operation = NETWORK_ACL_RAW_BIND;
722 }
723 else if (!strcmp(w[1], "connect"))
724 switch (sock_type) {
725 case SOCK_STREAM:
726 operation = NETWORK_ACL_TCP_CONNECT;
727 break;
728 case SOCK_DGRAM:
729 operation = NETWORK_ACL_UDP_CONNECT;
730 break;
731 default:
732 operation = NETWORK_ACL_RAW_CONNECT;
733 }
734 else if (sock_type == SOCK_STREAM && !strcmp(w[1], "listen"))
735 operation = NETWORK_ACL_TCP_LISTEN;
736 else if (sock_type == SOCK_STREAM && !strcmp(w[1], "accept"))
737 operation = NETWORK_ACL_TCP_ACCEPT;
738 else
739 goto out;
740 switch (ccs_parse_ip_address(w[2], 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 (w[2][0] != '@')
749 goto out;
750 group_name = w[2] + 1;
751 record_type = IP_RECORD_TYPE_ADDRESS_GROUP;
752 break;
753 }
754 count = sscanf(w[3], "%hu-%hu", &min_port, &max_port);
755 if (count != 1 && count != 2)
756 goto out;
757 if (count == 1)
758 max_port = min_port;
759 return ccs_update_network_entry(operation, record_type, group_name,
760 (u32 *) min_address,
761 (u32 *) max_address,
762 min_port, max_port, domain, condition,
763 is_delete);
764 out:
765 return -EINVAL;
766 }
767
768 /**
769 * ccs_check_network_listen_acl - Check permission for listen() operation.
770 *
771 * @is_ipv6: True if @address is an IPv6 address.
772 * @address: An IPv4 or IPv6 address.
773 * @port: Port number.
774 *
775 * Returns 0 on success, negative value otherwise.
776 */
777 static inline int ccs_check_network_listen_acl(const bool is_ipv6,
778 const u8 *address,
779 const u16 port)
780 {
781 return ccs_check_network_entry(is_ipv6, NETWORK_ACL_TCP_LISTEN,
782 (const u32 *) address, ntohs(port));
783 }
784
785 /**
786 * ccs_check_network_connect_acl - Check permission for connect() operation.
787 *
788 * @is_ipv6: True if @address is an IPv6 address.
789 * @sock_type: Type of socket. (TCP or UDP or RAW)
790 * @address: An IPv4 or IPv6 address.
791 * @port: Port number.
792 *
793 * Returns 0 on success, negative value otherwise.
794 */
795 static inline int ccs_check_network_connect_acl(const bool is_ipv6,
796 const int sock_type,
797 const u8 *address,
798 const u16 port)
799 {
800 u8 operation;
801 switch (sock_type) {
802 case SOCK_STREAM:
803 operation = NETWORK_ACL_TCP_CONNECT;
804 break;
805 case SOCK_DGRAM:
806 operation = NETWORK_ACL_UDP_CONNECT;
807 break;
808 default:
809 operation = NETWORK_ACL_RAW_CONNECT;
810 }
811 return ccs_check_network_entry(is_ipv6, operation,
812 (const u32 *) address, ntohs(port));
813 }
814
815 /**
816 * ccs_check_network_bind_acl - Check permission for bind() operation.
817 *
818 * @is_ipv6: True if @address is an IPv6 address.
819 * @sock_type: Type of socket. (TCP or UDP or RAW)
820 * @address: An IPv4 or IPv6 address.
821 * @port: Port number.
822 *
823 * Returns 0 on success, negative value otherwise.
824 */
825 static int ccs_check_network_bind_acl(const bool is_ipv6, const int sock_type,
826 const u8 *address, const u16 port)
827 {
828 u8 operation;
829 switch (sock_type) {
830 case SOCK_STREAM:
831 operation = NETWORK_ACL_TCP_BIND;
832 break;
833 case SOCK_DGRAM:
834 operation = NETWORK_ACL_UDP_BIND;
835 break;
836 default:
837 operation = NETWORK_ACL_RAW_BIND;
838 }
839 return ccs_check_network_entry(is_ipv6, operation,
840 (const u32 *) address, ntohs(port));
841 }
842
843 /**
844 * ccs_check_network_accept_acl - Check permission for accept() operation.
845 *
846 * @is_ipv6: True if @address is an IPv6 address.
847 * @address: An IPv4 or IPv6 address.
848 * @port: Port number.
849 *
850 * Returns 0 on success, negative value otherwise.
851 */
852 static inline int ccs_check_network_accept_acl(const bool is_ipv6,
853 const u8 *address,
854 const u16 port)
855 {
856 int retval;
857 current->ccs_flags |= CCS_DONT_SLEEP_ON_ENFORCE_ERROR;
858 retval = ccs_check_network_entry(is_ipv6, NETWORK_ACL_TCP_ACCEPT,
859 (const u32 *) address, ntohs(port));
860 current->ccs_flags &= ~CCS_DONT_SLEEP_ON_ENFORCE_ERROR;
861 return retval;
862 }
863
864 /**
865 * ccs_check_network_sendmsg_acl - Check permission for sendmsg() operation.
866 *
867 * @is_ipv6: True if @address is an IPv6 address.
868 * @sock_type: Type of socket. (UDP or RAW)
869 * @address: An IPv4 or IPv6 address.
870 * @port: Port number.
871 *
872 * Returns 0 on success, negative value otherwise.
873 */
874 static inline int ccs_check_network_sendmsg_acl(const bool is_ipv6,
875 const int sock_type,
876 const u8 *address,
877 const u16 port)
878 {
879 u8 operation;
880 if (sock_type == SOCK_DGRAM)
881 operation = NETWORK_ACL_UDP_CONNECT;
882 else
883 operation = NETWORK_ACL_RAW_CONNECT;
884 return ccs_check_network_entry(is_ipv6, operation,
885 (const u32 *) address, ntohs(port));
886 }
887
888 /**
889 * ccs_check_network_recvmsg_acl - Check permission for recvmsg() operation.
890 *
891 * @is_ipv6: True if @address is an IPv6 address.
892 * @sock_type: Type of socket. (UDP or RAW)
893 * @address: An IPv4 or IPv6 address.
894 * @port: Port number.
895 *
896 * Returns 0 on success, negative value otherwise.
897 */
898 static inline int ccs_check_network_recvmsg_acl(const bool is_ipv6,
899 const int sock_type,
900 const u8 *address,
901 const u16 port)
902 {
903 int retval;
904 const u8 operation
905 = (sock_type == SOCK_DGRAM) ?
906 NETWORK_ACL_UDP_CONNECT : NETWORK_ACL_RAW_CONNECT;
907 current->ccs_flags |= CCS_DONT_SLEEP_ON_ENFORCE_ERROR;
908 retval = ccs_check_network_entry(is_ipv6, operation,
909 (const u32 *) address, ntohs(port));
910 current->ccs_flags &= ~CCS_DONT_SLEEP_ON_ENFORCE_ERROR;
911 return retval;
912 }
913
914 #define MAX_SOCK_ADDR 128 /* net/socket.c */
915
916 /* Check permission for creating a socket. */
917 int ccs_socket_create_permission(int family, int type, int protocol)
918 {
919 int error = 0;
920 /* Nothing to do if I am a kernel service. */
921 if (segment_eq(get_fs(), KERNEL_DS))
922 return 0;
923 if (family == PF_PACKET && !ccs_capable(CCS_USE_PACKET_SOCKET))
924 return -EPERM;
925 if (family == PF_ROUTE && !ccs_capable(CCS_USE_ROUTE_SOCKET))
926 return -EPERM;
927 if (family != PF_INET && family != PF_INET6)
928 return 0;
929 switch (type) {
930 case SOCK_STREAM:
931 if (!ccs_capable(CCS_INET_STREAM_SOCKET_CREATE))
932 error = -EPERM;
933 break;
934 case SOCK_DGRAM:
935 if (!ccs_capable(CCS_USE_INET_DGRAM_SOCKET))
936 error = -EPERM;
937 break;
938 case SOCK_RAW:
939 if (!ccs_capable(CCS_USE_INET_RAW_SOCKET))
940 error = -EPERM;
941 break;
942 }
943 return error;
944 }
945
946 /* Check permission for listening a TCP socket. */
947 int ccs_socket_listen_permission(struct socket *sock)
948 {
949 int error = 0;
950 char addr[MAX_SOCK_ADDR];
951 int addr_len;
952 /* Nothing to do if I am a kernel service. */
953 if (segment_eq(get_fs(), KERNEL_DS))
954 return 0;
955 if (sock->type != SOCK_STREAM)
956 return 0;
957 switch (sock->sk->sk_family) {
958 case PF_INET:
959 case PF_INET6:
960 break;
961 default:
962 return 0;
963 }
964 if (!ccs_capable(CCS_INET_STREAM_SOCKET_LISTEN))
965 return -EPERM;
966 if (sock->ops->getname(sock, (struct sockaddr *) addr, &addr_len, 0))
967 return -EPERM;
968 switch (((struct sockaddr *) addr)->sa_family) {
969 struct sockaddr_in6 *addr6;
970 struct sockaddr_in *addr4;
971 case AF_INET6:
972 addr6 = (struct sockaddr_in6 *) addr;
973 error = ccs_check_network_listen_acl(true,
974 addr6->sin6_addr.s6_addr,
975 addr6->sin6_port);
976 break;
977 case AF_INET:
978 addr4 = (struct sockaddr_in *) addr;
979 error = ccs_check_network_listen_acl(false,
980 (u8 *) &addr4->sin_addr,
981 addr4->sin_port);
982 break;
983 }
984 return error;
985 }
986
987 /* Check permission for setting the remote IP address/port pair of a socket. */
988 int ccs_socket_connect_permission(struct socket *sock, struct sockaddr *addr,
989 int addr_len)
990 {
991 int error = 0;
992 const unsigned int type = sock->type;
993 /* Nothing to do if I am a kernel service. */
994 if (segment_eq(get_fs(), KERNEL_DS))
995 return 0;
996 switch (type) {
997 case SOCK_STREAM:
998 case SOCK_DGRAM:
999 case SOCK_RAW:
1000 break;
1001 default:
1002 return 0;
1003 }
1004 switch (addr->sa_family) {
1005 struct sockaddr_in6 *addr6;
1006 struct sockaddr_in *addr4;
1007 u16 port;
1008 case AF_INET6:
1009 if (addr_len < SIN6_LEN_RFC2133)
1010 break;
1011 addr6 = (struct sockaddr_in6 *) addr;
1012 if (type != SOCK_RAW)
1013 port = addr6->sin6_port;
1014 else
1015 port = htons(sock->sk->sk_protocol);
1016 error = ccs_check_network_connect_acl(true, type,
1017 addr6->sin6_addr.s6_addr,
1018 port);
1019 break;
1020 case AF_INET:
1021 if (addr_len < sizeof(struct sockaddr_in))
1022 break;
1023 addr4 = (struct sockaddr_in *) addr;
1024 if (type != SOCK_RAW)
1025 port = addr4->sin_port;
1026 else
1027 port = htons(sock->sk->sk_protocol);
1028 error = ccs_check_network_connect_acl(false, type,
1029 (u8 *) &addr4->sin_addr,
1030 port);
1031 break;
1032 }
1033 if (type != SOCK_STREAM)
1034 return error;
1035 switch (sock->sk->sk_family) {
1036 case PF_INET:
1037 case PF_INET6:
1038 if (!ccs_capable(CCS_INET_STREAM_SOCKET_CONNECT))
1039 error = -EPERM;
1040 break;
1041 }
1042 return error;
1043 }
1044
1045 /* Check permission for setting the local IP address/port pair of a socket. */
1046 int ccs_socket_bind_permission(struct socket *sock, struct sockaddr *addr,
1047 int addr_len)
1048 {
1049 int error = 0;
1050 const unsigned int type = sock->type;
1051 /* Nothing to do if I am a kernel service. */
1052 if (segment_eq(get_fs(), KERNEL_DS))
1053 return 0;
1054 switch (type) {
1055 case SOCK_STREAM:
1056 case SOCK_DGRAM:
1057 case SOCK_RAW:
1058 break;
1059 default:
1060 return 0;
1061 }
1062 switch (addr->sa_family) {
1063 struct sockaddr_in6 *addr6;
1064 struct sockaddr_in *addr4;
1065 u16 port;
1066 case AF_INET6:
1067 if (addr_len < SIN6_LEN_RFC2133)
1068 break;
1069 addr6 = (struct sockaddr_in6 *) addr;
1070 if (type != SOCK_RAW)
1071 port = addr6->sin6_port;
1072 else
1073 port = htons(sock->sk->sk_protocol);
1074 error = ccs_check_network_bind_acl(true, type,
1075 addr6->sin6_addr.s6_addr,
1076 port);
1077 break;
1078 case AF_INET:
1079 if (addr_len < sizeof(struct sockaddr_in))
1080 break;
1081 addr4 = (struct sockaddr_in *) addr;
1082 if (type != SOCK_RAW)
1083 port = addr4->sin_port;
1084 else
1085 port = htons(sock->sk->sk_protocol);
1086 error = ccs_check_network_bind_acl(false, type,
1087 (u8 *) &addr4->sin_addr,
1088 port);
1089 break;
1090 }
1091 return error;
1092 }
1093
1094 /*
1095 * Check permission for accepting a TCP socket.
1096 *
1097 * Currently, the LSM hook for this purpose is not provided.
1098 */
1099 int ccs_socket_accept_permission(struct socket *sock, struct sockaddr *addr)
1100 {
1101 int error = 0;
1102 int addr_len;
1103 /* Nothing to do if I am a kernel service. */
1104 if (segment_eq(get_fs(), KERNEL_DS))
1105 return 0;
1106 switch (sock->sk->sk_family) {
1107 case PF_INET:
1108 case PF_INET6:
1109 break;
1110 default:
1111 return 0;
1112 }
1113 error = sock->ops->getname(sock, addr, &addr_len, 2);
1114 if (error)
1115 return error;
1116 switch (addr->sa_family) {
1117 struct sockaddr_in6 *addr6;
1118 struct sockaddr_in *addr4;
1119 case AF_INET6:
1120 addr6 = (struct sockaddr_in6 *) addr;
1121 error = ccs_check_network_accept_acl(true,
1122 addr6->sin6_addr.s6_addr,
1123 addr6->sin6_port);
1124 break;
1125 case AF_INET:
1126 addr4 = (struct sockaddr_in *) addr;
1127 error = ccs_check_network_accept_acl(false,
1128 (u8 *) &addr4->sin_addr,
1129 addr4->sin_port);
1130 break;
1131 }
1132 return error;
1133 }
1134
1135 /* Check permission for sending a datagram via a UDP or RAW socket. */
1136 int ccs_socket_sendmsg_permission(struct socket *sock, struct sockaddr *addr,
1137 int addr_len)
1138 {
1139 int error = 0;
1140 const int type = sock->type;
1141 /* Nothing to do if I am a kernel service. */
1142 if (segment_eq(get_fs(), KERNEL_DS))
1143 return 0;
1144 if (!addr || (type != SOCK_DGRAM && type != SOCK_RAW))
1145 return 0;
1146 switch (addr->sa_family) {
1147 struct sockaddr_in6 *addr6;
1148 struct sockaddr_in *addr4;
1149 u16 port;
1150 case AF_INET6:
1151 if (addr_len < SIN6_LEN_RFC2133)
1152 break;
1153 addr6 = (struct sockaddr_in6 *) addr;
1154 if (type == SOCK_DGRAM)
1155 port = addr6->sin6_port;
1156 else
1157 port = htons(sock->sk->sk_protocol);
1158 error = ccs_check_network_sendmsg_acl(true, type,
1159 addr6->sin6_addr.s6_addr,
1160 port);
1161 break;
1162 case AF_INET:
1163 if (addr_len < sizeof(struct sockaddr_in))
1164 break;
1165 addr4 = (struct sockaddr_in *) addr;
1166 if (type == SOCK_DGRAM)
1167 port = addr4->sin_port;
1168 else
1169 port = htons(sock->sk->sk_protocol);
1170 error = ccs_check_network_sendmsg_acl(false, type,
1171 (u8 *) &addr4->sin_addr,
1172 port);
1173 break;
1174 }
1175 return error;
1176 }
1177
1178 #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 22)
1179 #if !defined(RHEL_MAJOR) || RHEL_MAJOR != 5
1180
1181 static inline struct iphdr *ip_hdr(const struct sk_buff *skb)
1182 {
1183 return skb->nh.iph;
1184 }
1185
1186 static inline struct udphdr *udp_hdr(const struct sk_buff *skb)
1187 {
1188 return skb->h.uh;
1189 }
1190
1191 static inline struct ipv6hdr *ipv6_hdr(const struct sk_buff *skb)
1192 {
1193 return skb->nh.ipv6h;
1194 }
1195
1196 #endif
1197 #endif
1198
1199 #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 12)
1200 static void skb_kill_datagram(struct sock *sk, struct sk_buff *skb,
1201 unsigned int flags)
1202 {
1203 /* Clear queue. */
1204 if (flags & MSG_PEEK) {
1205 int clear = 0;
1206 spin_lock_irq(&sk->sk_receive_queue.lock);
1207 if (skb == skb_peek(&sk->sk_receive_queue)) {
1208 __skb_unlink(skb, &sk->sk_receive_queue);
1209 clear = 1;
1210 }
1211 spin_unlock_irq(&sk->sk_receive_queue.lock);
1212 if (clear)
1213 kfree_skb(skb);
1214 }
1215 skb_free_datagram(sk, skb);
1216 }
1217 #elif LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 16)
1218 static void skb_kill_datagram(struct sock *sk, struct sk_buff *skb,
1219 unsigned int flags)
1220 {
1221 /* Clear queue. */
1222 if (flags & MSG_PEEK) {
1223 int clear = 0;
1224 spin_lock_bh(&sk->sk_receive_queue.lock);
1225 if (skb == skb_peek(&sk->sk_receive_queue)) {
1226 __skb_unlink(skb, &sk->sk_receive_queue);
1227 clear = 1;
1228 }
1229 spin_unlock_bh(&sk->sk_receive_queue.lock);
1230 if (clear)
1231 kfree_skb(skb);
1232 }
1233 skb_free_datagram(sk, skb);
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