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

Subversion リポジトリの参照

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

Parent Directory Parent Directory | Revision Log Revision Log


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

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