149 |
} |
} |
150 |
|
|
151 |
/** |
/** |
152 |
* ccs_check_network_entry2 - Check permission for network operation. |
* ccs_network_entry2 - Check permission for network operation. |
153 |
* |
* |
154 |
* @is_ipv6: True if @address is an IPv6 address. |
* @is_ipv6: True if @address is an IPv6 address. |
155 |
* @operation: Type of operation. |
* @operation: Type of operation. |
160 |
* |
* |
161 |
* Caller holds ccs_read_lock(). |
* Caller holds ccs_read_lock(). |
162 |
*/ |
*/ |
163 |
static int ccs_check_network_entry2(const bool is_ipv6, const u8 operation, |
static int ccs_network_entry2(const bool is_ipv6, const u8 operation, |
164 |
const u32 *address, const u16 port) |
const u32 *address, const u16 port) |
165 |
{ |
{ |
166 |
struct ccs_request_info r; |
struct ccs_request_info r; |
172 |
const u32 ip = ntohl(*address); |
const u32 ip = ntohl(*address); |
173 |
int error; |
int error; |
174 |
char buf[64]; |
char buf[64]; |
175 |
ccs_check_read_lock(); |
ccs_assert_read_lock(); |
176 |
if (!ccs_can_sleep() || |
if (!ccs_can_sleep() || |
177 |
!ccs_init_request_info(&r, NULL, CCS_MAC_NETWORK)) |
!ccs_init_request_info(&r, NULL, CCS_MAC_NETWORK)) |
178 |
return 0; |
return 0; |
187 |
if (!(acl->perm & perm)) |
if (!(acl->perm & perm)) |
188 |
continue; |
continue; |
189 |
if (!ccs_compare_number_union(port, &acl->port) || |
if (!ccs_compare_number_union(port, &acl->port) || |
190 |
!ccs_check_condition(&r, ptr)) |
!ccs_condition(&r, ptr)) |
191 |
continue; |
continue; |
192 |
if (acl->address_type == CCS_IP_ADDRESS_TYPE_ADDRESS_GROUP) { |
if (acl->address_type == CCS_IP_ADDRESS_TYPE_ADDRESS_GROUP) { |
193 |
if (!ccs_address_matches_group(is_ipv6, address, |
if (!ccs_address_matches_group(is_ipv6, address, |
216 |
snprintf(buf, sizeof(buf) - 1, "%u.%u.%u.%u", HIPQUAD(ip)); |
snprintf(buf, sizeof(buf) - 1, "%u.%u.%u.%u", HIPQUAD(ip)); |
217 |
ccs_audit_network_log(&r, keyword, buf, port, !error); |
ccs_audit_network_log(&r, keyword, buf, port, !error); |
218 |
if (error) |
if (error) |
219 |
error = ccs_check_supervisor(&r, CCS_KEYWORD_ALLOW_NETWORK |
error = ccs_supervisor(&r, CCS_KEYWORD_ALLOW_NETWORK |
220 |
"%s %s %u\n", keyword, buf, port); |
"%s %s %u\n", keyword, buf, port); |
221 |
if (error == 1) |
if (error == 1) |
222 |
goto retry; |
goto retry; |
226 |
} |
} |
227 |
|
|
228 |
/** |
/** |
229 |
* ccs_check_network_entry - Check permission for network operation. |
* ccs_network_entry - Check permission for network operation. |
230 |
* |
* |
231 |
* @is_ipv6: True if @address is an IPv6 address. |
* @is_ipv6: True if @address is an IPv6 address. |
232 |
* @operation: Type of operation. |
* @operation: Type of operation. |
235 |
* |
* |
236 |
* Returns 0 on success, negative value otherwise. |
* Returns 0 on success, negative value otherwise. |
237 |
*/ |
*/ |
238 |
static int ccs_check_network_entry(const bool is_ipv6, const u8 operation, |
static int ccs_network_entry(const bool is_ipv6, const u8 operation, |
239 |
const u32 *address, const u16 port) |
const u32 *address, const u16 port) |
240 |
{ |
{ |
241 |
const int idx = ccs_read_lock(); |
const int idx = ccs_read_lock(); |
242 |
const int error = ccs_check_network_entry2(is_ipv6, operation, |
const int error = ccs_network_entry2(is_ipv6, operation, |
243 |
address, port); |
address, port); |
244 |
ccs_read_unlock(idx); |
ccs_read_unlock(idx); |
245 |
return error; |
return error; |
381 |
} |
} |
382 |
|
|
383 |
/** |
/** |
384 |
* ccs_check_network_listen_acl - Check permission for listen() operation. |
* ccs_network_listen_acl - Check permission for listen() operation. |
385 |
* |
* |
386 |
* @is_ipv6: True if @address is an IPv6 address. |
* @is_ipv6: True if @address is an IPv6 address. |
387 |
* @address: An IPv4 or IPv6 address. |
* @address: An IPv4 or IPv6 address. |
389 |
* |
* |
390 |
* Returns 0 on success, negative value otherwise. |
* Returns 0 on success, negative value otherwise. |
391 |
*/ |
*/ |
392 |
static inline int ccs_check_network_listen_acl(const bool is_ipv6, |
static inline int ccs_network_listen_acl(const bool is_ipv6, |
393 |
const u8 *address, |
const u8 *address, |
394 |
const u16 port) |
const u16 port) |
395 |
{ |
{ |
396 |
return ccs_check_network_entry(is_ipv6, CCS_NETWORK_TCP_LISTEN, |
return ccs_network_entry(is_ipv6, CCS_NETWORK_TCP_LISTEN, |
397 |
(const u32 *) address, ntohs(port)); |
(const u32 *) address, ntohs(port)); |
398 |
} |
} |
399 |
|
|
400 |
/** |
/** |
401 |
* ccs_check_network_connect_acl - Check permission for connect() operation. |
* ccs_network_connect_acl - Check permission for connect() operation. |
402 |
* |
* |
403 |
* @is_ipv6: True if @address is an IPv6 address. |
* @is_ipv6: True if @address is an IPv6 address. |
404 |
* @sock_type: Type of socket. (TCP or UDP or RAW) |
* @sock_type: Type of socket. (TCP or UDP or RAW) |
407 |
* |
* |
408 |
* Returns 0 on success, negative value otherwise. |
* Returns 0 on success, negative value otherwise. |
409 |
*/ |
*/ |
410 |
static inline int ccs_check_network_connect_acl(const bool is_ipv6, |
static inline int ccs_network_connect_acl(const bool is_ipv6, |
411 |
const int sock_type, |
const int sock_type, |
412 |
const u8 *address, |
const u8 *address, |
413 |
const u16 port) |
const u16 port) |
423 |
default: |
default: |
424 |
operation = CCS_NETWORK_RAW_CONNECT; |
operation = CCS_NETWORK_RAW_CONNECT; |
425 |
} |
} |
426 |
return ccs_check_network_entry(is_ipv6, operation, |
return ccs_network_entry(is_ipv6, operation, |
427 |
(const u32 *) address, ntohs(port)); |
(const u32 *) address, ntohs(port)); |
428 |
} |
} |
429 |
|
|
430 |
/** |
/** |
431 |
* ccs_check_network_bind_acl - Check permission for bind() operation. |
* ccs_network_bind_acl - Check permission for bind() operation. |
432 |
* |
* |
433 |
* @is_ipv6: True if @address is an IPv6 address. |
* @is_ipv6: True if @address is an IPv6 address. |
434 |
* @sock_type: Type of socket. (TCP or UDP or RAW) |
* @sock_type: Type of socket. (TCP or UDP or RAW) |
437 |
* |
* |
438 |
* Returns 0 on success, negative value otherwise. |
* Returns 0 on success, negative value otherwise. |
439 |
*/ |
*/ |
440 |
static int ccs_check_network_bind_acl(const bool is_ipv6, const int sock_type, |
static int ccs_network_bind_acl(const bool is_ipv6, const int sock_type, |
441 |
const u8 *address, const u16 port) |
const u8 *address, const u16 port) |
442 |
{ |
{ |
443 |
u8 operation; |
u8 operation; |
451 |
default: |
default: |
452 |
operation = CCS_NETWORK_RAW_BIND; |
operation = CCS_NETWORK_RAW_BIND; |
453 |
} |
} |
454 |
return ccs_check_network_entry(is_ipv6, operation, |
return ccs_network_entry(is_ipv6, operation, |
455 |
(const u32 *) address, ntohs(port)); |
(const u32 *) address, ntohs(port)); |
456 |
} |
} |
457 |
|
|
458 |
/** |
/** |
459 |
* ccs_check_network_accept_acl - Check permission for accept() operation. |
* ccs_network_accept_acl - Check permission for accept() operation. |
460 |
* |
* |
461 |
* @is_ipv6: True if @address is an IPv6 address. |
* @is_ipv6: True if @address is an IPv6 address. |
462 |
* @address: An IPv4 or IPv6 address. |
* @address: An IPv4 or IPv6 address. |
464 |
* |
* |
465 |
* Returns 0 on success, negative value otherwise. |
* Returns 0 on success, negative value otherwise. |
466 |
*/ |
*/ |
467 |
static inline int ccs_check_network_accept_acl(const bool is_ipv6, |
static inline int ccs_network_accept_acl(const bool is_ipv6, |
468 |
const u8 *address, |
const u8 *address, |
469 |
const u16 port) |
const u16 port) |
470 |
{ |
{ |
471 |
int retval; |
int retval; |
472 |
current->ccs_flags |= CCS_DONT_SLEEP_ON_ENFORCE_ERROR; |
current->ccs_flags |= CCS_DONT_SLEEP_ON_ENFORCE_ERROR; |
473 |
retval = ccs_check_network_entry(is_ipv6, CCS_NETWORK_TCP_ACCEPT, |
retval = ccs_network_entry(is_ipv6, CCS_NETWORK_TCP_ACCEPT, |
474 |
(const u32 *) address, ntohs(port)); |
(const u32 *) address, ntohs(port)); |
475 |
current->ccs_flags &= ~CCS_DONT_SLEEP_ON_ENFORCE_ERROR; |
current->ccs_flags &= ~CCS_DONT_SLEEP_ON_ENFORCE_ERROR; |
476 |
return retval; |
return retval; |
477 |
} |
} |
478 |
|
|
479 |
/** |
/** |
480 |
* ccs_check_network_sendmsg_acl - Check permission for sendmsg() operation. |
* ccs_network_sendmsg_acl - Check permission for sendmsg() operation. |
481 |
* |
* |
482 |
* @is_ipv6: True if @address is an IPv6 address. |
* @is_ipv6: True if @address is an IPv6 address. |
483 |
* @sock_type: Type of socket. (UDP or RAW) |
* @sock_type: Type of socket. (UDP or RAW) |
486 |
* |
* |
487 |
* Returns 0 on success, negative value otherwise. |
* Returns 0 on success, negative value otherwise. |
488 |
*/ |
*/ |
489 |
static inline int ccs_check_network_sendmsg_acl(const bool is_ipv6, |
static inline int ccs_network_sendmsg_acl(const bool is_ipv6, |
490 |
const int sock_type, |
const int sock_type, |
491 |
const u8 *address, |
const u8 *address, |
492 |
const u16 port) |
const u16 port) |
496 |
operation = CCS_NETWORK_UDP_CONNECT; |
operation = CCS_NETWORK_UDP_CONNECT; |
497 |
else |
else |
498 |
operation = CCS_NETWORK_RAW_CONNECT; |
operation = CCS_NETWORK_RAW_CONNECT; |
499 |
return ccs_check_network_entry(is_ipv6, operation, |
return ccs_network_entry(is_ipv6, operation, |
500 |
(const u32 *) address, ntohs(port)); |
(const u32 *) address, ntohs(port)); |
501 |
} |
} |
502 |
|
|
503 |
/** |
/** |
504 |
* ccs_check_network_recvmsg_acl - Check permission for recvmsg() operation. |
* ccs_network_recvmsg_acl - Check permission for recvmsg() operation. |
505 |
* |
* |
506 |
* @is_ipv6: True if @address is an IPv6 address. |
* @is_ipv6: True if @address is an IPv6 address. |
507 |
* @sock_type: Type of socket. (UDP or RAW) |
* @sock_type: Type of socket. (UDP or RAW) |
510 |
* |
* |
511 |
* Returns 0 on success, negative value otherwise. |
* Returns 0 on success, negative value otherwise. |
512 |
*/ |
*/ |
513 |
static inline int ccs_check_network_recvmsg_acl(const bool is_ipv6, |
static inline int ccs_network_recvmsg_acl(const bool is_ipv6, |
514 |
const int sock_type, |
const int sock_type, |
515 |
const u8 *address, |
const u8 *address, |
516 |
const u16 port) |
const u16 port) |
520 |
= (sock_type == SOCK_DGRAM) ? |
= (sock_type == SOCK_DGRAM) ? |
521 |
CCS_NETWORK_UDP_CONNECT : CCS_NETWORK_RAW_CONNECT; |
CCS_NETWORK_UDP_CONNECT : CCS_NETWORK_RAW_CONNECT; |
522 |
current->ccs_flags |= CCS_DONT_SLEEP_ON_ENFORCE_ERROR; |
current->ccs_flags |= CCS_DONT_SLEEP_ON_ENFORCE_ERROR; |
523 |
retval = ccs_check_network_entry(is_ipv6, operation, |
retval = ccs_network_entry(is_ipv6, operation, |
524 |
(const u32 *) address, ntohs(port)); |
(const u32 *) address, ntohs(port)); |
525 |
current->ccs_flags &= ~CCS_DONT_SLEEP_ON_ENFORCE_ERROR; |
current->ccs_flags &= ~CCS_DONT_SLEEP_ON_ENFORCE_ERROR; |
526 |
return retval; |
return retval; |
585 |
struct sockaddr_in *addr4; |
struct sockaddr_in *addr4; |
586 |
case AF_INET6: |
case AF_INET6: |
587 |
addr6 = (struct sockaddr_in6 *) addr; |
addr6 = (struct sockaddr_in6 *) addr; |
588 |
error = ccs_check_network_listen_acl(true, |
error = ccs_network_listen_acl(true, |
589 |
addr6->sin6_addr.s6_addr, |
addr6->sin6_addr.s6_addr, |
590 |
addr6->sin6_port); |
addr6->sin6_port); |
591 |
break; |
break; |
592 |
case AF_INET: |
case AF_INET: |
593 |
addr4 = (struct sockaddr_in *) addr; |
addr4 = (struct sockaddr_in *) addr; |
594 |
error = ccs_check_network_listen_acl(false, |
error = ccs_network_listen_acl(false, |
595 |
(u8 *) &addr4->sin_addr, |
(u8 *) &addr4->sin_addr, |
596 |
addr4->sin_port); |
addr4->sin_port); |
597 |
break; |
break; |
628 |
port = addr6->sin6_port; |
port = addr6->sin6_port; |
629 |
else |
else |
630 |
port = htons(sock->sk->sk_protocol); |
port = htons(sock->sk->sk_protocol); |
631 |
error = ccs_check_network_connect_acl(true, type, |
error = ccs_network_connect_acl(true, type, |
632 |
addr6->sin6_addr.s6_addr, |
addr6->sin6_addr.s6_addr, |
633 |
port); |
port); |
634 |
break; |
break; |
640 |
port = addr4->sin_port; |
port = addr4->sin_port; |
641 |
else |
else |
642 |
port = htons(sock->sk->sk_protocol); |
port = htons(sock->sk->sk_protocol); |
643 |
error = ccs_check_network_connect_acl(false, type, |
error = ccs_network_connect_acl(false, type, |
644 |
(u8 *) &addr4->sin_addr, |
(u8 *) &addr4->sin_addr, |
645 |
port); |
port); |
646 |
break; |
break; |
686 |
port = addr6->sin6_port; |
port = addr6->sin6_port; |
687 |
else |
else |
688 |
port = htons(sock->sk->sk_protocol); |
port = htons(sock->sk->sk_protocol); |
689 |
error = ccs_check_network_bind_acl(true, type, |
error = ccs_network_bind_acl(true, type, |
690 |
addr6->sin6_addr.s6_addr, |
addr6->sin6_addr.s6_addr, |
691 |
port); |
port); |
692 |
break; |
break; |
698 |
port = addr4->sin_port; |
port = addr4->sin_port; |
699 |
else |
else |
700 |
port = htons(sock->sk->sk_protocol); |
port = htons(sock->sk->sk_protocol); |
701 |
error = ccs_check_network_bind_acl(false, type, |
error = ccs_network_bind_acl(false, type, |
702 |
(u8 *) &addr4->sin_addr, |
(u8 *) &addr4->sin_addr, |
703 |
port); |
port); |
704 |
break; |
break; |
733 |
struct sockaddr_in *addr4; |
struct sockaddr_in *addr4; |
734 |
case AF_INET6: |
case AF_INET6: |
735 |
addr6 = (struct sockaddr_in6 *) addr; |
addr6 = (struct sockaddr_in6 *) addr; |
736 |
error = ccs_check_network_accept_acl(true, |
error = ccs_network_accept_acl(true, |
737 |
addr6->sin6_addr.s6_addr, |
addr6->sin6_addr.s6_addr, |
738 |
addr6->sin6_port); |
addr6->sin6_port); |
739 |
break; |
break; |
740 |
case AF_INET: |
case AF_INET: |
741 |
addr4 = (struct sockaddr_in *) addr; |
addr4 = (struct sockaddr_in *) addr; |
742 |
error = ccs_check_network_accept_acl(false, |
error = ccs_network_accept_acl(false, |
743 |
(u8 *) &addr4->sin_addr, |
(u8 *) &addr4->sin_addr, |
744 |
addr4->sin_port); |
addr4->sin_port); |
745 |
break; |
break; |
770 |
port = addr6->sin6_port; |
port = addr6->sin6_port; |
771 |
else |
else |
772 |
port = htons(sock->sk->sk_protocol); |
port = htons(sock->sk->sk_protocol); |
773 |
error = ccs_check_network_sendmsg_acl(true, type, |
error = ccs_network_sendmsg_acl(true, type, |
774 |
addr6->sin6_addr.s6_addr, |
addr6->sin6_addr.s6_addr, |
775 |
port); |
port); |
776 |
break; |
break; |
782 |
port = addr4->sin_port; |
port = addr4->sin_port; |
783 |
else |
else |
784 |
port = htons(sock->sk->sk_protocol); |
port = htons(sock->sk->sk_protocol); |
785 |
error = ccs_check_network_sendmsg_acl(false, type, |
error = ccs_network_sendmsg_acl(false, type, |
786 |
(u8 *) &addr4->sin_addr, |
(u8 *) &addr4->sin_addr, |
787 |
port); |
port); |
788 |
break; |
break; |
882 |
ipv6_addr_copy(&sin6, &ipv6_hdr(skb)->saddr); |
ipv6_addr_copy(&sin6, &ipv6_hdr(skb)->saddr); |
883 |
port = htons(sk->sk_protocol); |
port = htons(sk->sk_protocol); |
884 |
} |
} |
885 |
error = ccs_check_network_recvmsg_acl(true, type, |
error = ccs_network_recvmsg_acl(true, type, |
886 |
(u8 *) &sin6, port); |
(u8 *) &sin6, port); |
887 |
break; |
break; |
888 |
case PF_INET: |
case PF_INET: |
893 |
sin4.s_addr = ip_hdr(skb)->saddr; |
sin4.s_addr = ip_hdr(skb)->saddr; |
894 |
port = htons(sk->sk_protocol); |
port = htons(sk->sk_protocol); |
895 |
} |
} |
896 |
error = ccs_check_network_recvmsg_acl(false, type, |
error = ccs_network_recvmsg_acl(false, type, |
897 |
(u8 *) &sin4, port); |
(u8 *) &sin4, port); |
898 |
break; |
break; |
899 |
} |
} |