Skip to content

Commit 9bc309a

Browse files
mowenrootNipaLocal
authored and
NipaLocal
committed
netlabel: Fix NULL pointer exception caused by CALIPSO on IPv4 sockets
Vulnerability Description: From Linux Kernel v4.0 to the latest version, a type confusion issue exists in the `netlbl_conn_setattr` function (`net/netlabel/netlabel_kapi.c`) within SELinux, which can lead to a local DoS attack. When calling `netlbl_conn_setattr`, `addr->sa_family` is used to determine the function behavior. If `sk` is an IPv4 socket, but the `connect` function is called with an IPv6 address, the function `calipso_sock_setattr()` is triggered. Inside this function, the following code is executed: sk_fullsock(__sk) ? inet_sk(__sk)->pinet6 : NULL; Since `sk` is an IPv4 socket, `pinet6` is `NULL`, leading to a null pointer dereference and triggering a DoS attack. <TASK> calipso_sock_setattr+0x4f/0x80 net/netlabel/netlabel_calipso.c:557 netlbl_conn_setattr+0x12a/0x390 net/netlabel/netlabel_kapi.c:1152 selinux_netlbl_socket_connect_helper selinux_netlbl_socket_connect_locked+0xf5/0x1d0 selinux_netlbl_socket_connect+0x22/0x40 security/selinux/netlabel.c:611 selinux_socket_connect+0x60/0x80 security/selinux/hooks.c:4923 security_socket_connect+0x71/0xb0 security/security.c:2260 __sys_connect_file+0xa4/0x190 net/socket.c:2007 __sys_connect+0x145/0x170 net/socket.c:2028 __do_sys_connect net/socket.c:2038 [inline] __se_sys_connect net/socket.c:2035 [inline] __x64_sys_connect+0x6e/0xb0 net/socket.c:2035 do_syscall_x64 arch/x86/entry/common.c:51 Affected Versions: - Linux 4.0 - Latest Linux Kernel version Reproduction Steps: Use the `netlabelctl` tool and run the following commands to trigger the vulnerability: netlabelctl map del default netlabelctl cipsov4 add pass doi:8 tags:1 netlabelctl map add default address:192.168.1.0/24 protocol:cipsov4,8 netlabelctl calipso add pass doi:7 netlabelctl map add default address:2001:db8::1/32 protocol:calipso,7 Then, execute the following PoC code: int sockfd = socket(AF_INET, SOCK_STREAM, 0); struct sockaddr_in6 server_addr = {0}; server_addr.sin6_family = AF_INET6; server_addr.sin6_port = htons(8080); const char *ipv6_str = "2001:db8::1"; inet_pton(AF_INET6, ipv6_str, &server_addr.sin6_addr); connect(sockfd, (struct sockaddr*)&server_addr, sizeof(server_addr)); Suggested Fix: When using an IPv4 address on an IPv6 UDP/datagram socket, the operation will invoke the IPv4 datagram code through the IPv6 datagram code and execute successfully. It is necessary to check whether the `pinet6` pointer returned by `inet6_sk()` is NULL; otherwise, unexpected issues may occur. Signed-off-by: Debin Zhu <[email protected]> Signed-off-by: Bitao Ouyang <[email protected]> Signed-off-by: NipaLocal <nipa@local>
1 parent 3e20f98 commit 9bc309a

File tree

1 file changed

+18
-3
lines changed

1 file changed

+18
-3
lines changed

net/ipv6/calipso.c

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1072,8 +1072,13 @@ static int calipso_sock_getattr(struct sock *sk,
10721072
struct ipv6_opt_hdr *hop;
10731073
int opt_len, len, ret_val = -ENOMSG, offset;
10741074
unsigned char *opt;
1075-
struct ipv6_txoptions *txopts = txopt_get(inet6_sk(sk));
1075+
struct ipv6_pinfo *pinfo = inet6_sk(sk);
1076+
struct ipv6_txoptions *txopts;
1077+
1078+
if (!pinfo)
1079+
return -EAFNOSUPPORT;
10761080

1081+
txopts = txopt_get(pinfo);
10771082
if (!txopts || !txopts->hopopt)
10781083
goto done;
10791084

@@ -1125,8 +1130,13 @@ static int calipso_sock_setattr(struct sock *sk,
11251130
{
11261131
int ret_val;
11271132
struct ipv6_opt_hdr *old, *new;
1128-
struct ipv6_txoptions *txopts = txopt_get(inet6_sk(sk));
1133+
struct ipv6_pinfo *pinfo = inet6_sk(sk);
1134+
struct ipv6_txoptions *txopts;
1135+
1136+
if (!pinfo)
1137+
return -EAFNOSUPPORT;
11291138

1139+
txopts = txopt_get(pinfo);
11301140
old = NULL;
11311141
if (txopts)
11321142
old = txopts->hopopt;
@@ -1153,8 +1163,13 @@ static int calipso_sock_setattr(struct sock *sk,
11531163
static void calipso_sock_delattr(struct sock *sk)
11541164
{
11551165
struct ipv6_opt_hdr *new_hop;
1156-
struct ipv6_txoptions *txopts = txopt_get(inet6_sk(sk));
1166+
struct ipv6_pinfo *pinfo = inet6_sk(sk);
1167+
struct ipv6_txoptions *txopts;
1168+
1169+
if (!pinfo)
1170+
return;
11571171

1172+
txopts = txopt_get(pinfo);
11581173
if (!txopts || !txopts->hopopt)
11591174
goto done;
11601175

0 commit comments

Comments
 (0)