[syzbot] [crypto?] KMSAN: uninit-value in des3_ede_decrypt

7 views
Skip to first unread message

syzbot

unread,
Feb 20, 2024, 9:42:20 AMFeb 20
to da...@davemloft.net, her...@gondor.apana.org.au, linux-...@vger.kernel.org, linux-...@vger.kernel.org, syzkall...@googlegroups.com
Hello,

syzbot found the following issue on:

HEAD commit: 4f5e5092fdbf Merge tag 'net-6.8-rc5' of git://git.kernel.o..
git tree: upstream
console output: https://syzkaller.appspot.com/x/log.txt?x=1679e7b2180000
kernel config: https://syzkaller.appspot.com/x/.config?x=e3dd779fba027968
dashboard link: https://syzkaller.appspot.com/bug?extid=b90b904ef6bdfdafec1d
compiler: Debian clang version 15.0.6, GNU ld (GNU Binutils for Debian) 2.40

Unfortunately, I don't have any reproducer for this issue yet.

Downloadable assets:
disk image: https://storage.googleapis.com/syzbot-assets/34924e0466d4/disk-4f5e5092.raw.xz
vmlinux: https://storage.googleapis.com/syzbot-assets/29d0b1935c61/vmlinux-4f5e5092.xz
kernel image: https://storage.googleapis.com/syzbot-assets/2e033c3d8679/bzImage-4f5e5092.xz

IMPORTANT: if you fix the issue, please add the following tag to the commit:
Reported-by: syzbot+b90b90...@syzkaller.appspotmail.com

=====================================================
BUG: KMSAN: uninit-value in des3_ede_decrypt+0x845/0x19a0 lib/crypto/des.c:884
des3_ede_decrypt+0x845/0x19a0 lib/crypto/des.c:884
crypto_des3_ede_decrypt+0x32/0x40 crypto/des_generic.c:82
crypto_ecb_crypt crypto/ecb.c:23 [inline]
crypto_ecb_decrypt2+0x18b/0x2f0 crypto/ecb.c:51
crypto_lskcipher_crypt+0x66d/0x750 crypto/lskcipher.c:160
crypto_lskcipher_decrypt+0x82/0xb0 crypto/lskcipher.c:194
crypto_cbc_decrypt_inplace crypto/cbc.c:108 [inline]
crypto_cbc_decrypt+0x4df/0x8e0 crypto/cbc.c:131
crypto_lskcipher_crypt_sg+0x43f/0x930 crypto/lskcipher.c:229
crypto_lskcipher_decrypt_sg+0x8a/0xc0 crypto/lskcipher.c:258
crypto_skcipher_decrypt+0x10d/0x1c0 crypto/skcipher.c:693
cts_cbc_decrypt+0x51b/0x720 crypto/cts.c:219
crypto_cts_decrypt+0x77f/0x9b0 crypto/cts.c:280
crypto_skcipher_decrypt+0x189/0x1c0 crypto/skcipher.c:695
_skcipher_recvmsg crypto/algif_skcipher.c:199 [inline]
skcipher_recvmsg+0x1691/0x2190 crypto/algif_skcipher.c:221
sock_recvmsg_nosec net/socket.c:1046 [inline]
sock_recvmsg net/socket.c:1068 [inline]
____sys_recvmsg+0x283/0x7f0 net/socket.c:2803
___sys_recvmsg+0x223/0x840 net/socket.c:2845
do_recvmmsg+0x4fc/0xfd0 net/socket.c:2939
__sys_recvmmsg net/socket.c:3018 [inline]
__do_sys_recvmmsg net/socket.c:3041 [inline]
__se_sys_recvmmsg net/socket.c:3034 [inline]
__x64_sys_recvmmsg+0x397/0x490 net/socket.c:3034
do_syscall_x64 arch/x86/entry/common.c:52 [inline]
do_syscall_64+0xcf/0x1e0 arch/x86/entry/common.c:83
entry_SYSCALL_64_after_hwframe+0x63/0x6b

Uninit was stored to memory at:
memcpy_dir crypto/scatterwalk.c:23 [inline]
scatterwalk_copychunks crypto/scatterwalk.c:38 [inline]
scatterwalk_map_and_copy+0x6dc/0x9a0 crypto/scatterwalk.c:67
cts_cbc_decrypt+0x3e2/0x720 crypto/cts.c:211
crypto_cts_decrypt+0x77f/0x9b0 crypto/cts.c:280
crypto_skcipher_decrypt+0x189/0x1c0 crypto/skcipher.c:695
_skcipher_recvmsg crypto/algif_skcipher.c:199 [inline]
skcipher_recvmsg+0x1691/0x2190 crypto/algif_skcipher.c:221
sock_recvmsg_nosec net/socket.c:1046 [inline]
sock_recvmsg net/socket.c:1068 [inline]
____sys_recvmsg+0x283/0x7f0 net/socket.c:2803
___sys_recvmsg+0x223/0x840 net/socket.c:2845
do_recvmmsg+0x4fc/0xfd0 net/socket.c:2939
__sys_recvmmsg net/socket.c:3018 [inline]
__do_sys_recvmmsg net/socket.c:3041 [inline]
__se_sys_recvmmsg net/socket.c:3034 [inline]
__x64_sys_recvmmsg+0x397/0x490 net/socket.c:3034
do_syscall_x64 arch/x86/entry/common.c:52 [inline]
do_syscall_64+0xcf/0x1e0 arch/x86/entry/common.c:83
entry_SYSCALL_64_after_hwframe+0x63/0x6b

Uninit was stored to memory at:
cts_cbc_decrypt+0x3a3/0x720 crypto/cts.c:208
crypto_cts_decrypt+0x77f/0x9b0 crypto/cts.c:280
crypto_skcipher_decrypt+0x189/0x1c0 crypto/skcipher.c:695
_skcipher_recvmsg crypto/algif_skcipher.c:199 [inline]
skcipher_recvmsg+0x1691/0x2190 crypto/algif_skcipher.c:221
sock_recvmsg_nosec net/socket.c:1046 [inline]
sock_recvmsg net/socket.c:1068 [inline]
____sys_recvmsg+0x283/0x7f0 net/socket.c:2803
___sys_recvmsg+0x223/0x840 net/socket.c:2845
do_recvmmsg+0x4fc/0xfd0 net/socket.c:2939
__sys_recvmmsg net/socket.c:3018 [inline]
__do_sys_recvmmsg net/socket.c:3041 [inline]
__se_sys_recvmmsg net/socket.c:3034 [inline]
__x64_sys_recvmmsg+0x397/0x490 net/socket.c:3034
do_syscall_x64 arch/x86/entry/common.c:52 [inline]
do_syscall_64+0xcf/0x1e0 arch/x86/entry/common.c:83
entry_SYSCALL_64_after_hwframe+0x63/0x6b

Uninit was stored to memory at:
__crypto_xor+0x171/0x1310 lib/crypto/utils.c:45
crypto_xor include/crypto/utils.h:31 [inline]
cts_cbc_decrypt+0x2da/0x720 crypto/cts.c:199
crypto_cts_decrypt+0x77f/0x9b0 crypto/cts.c:280
crypto_skcipher_decrypt+0x189/0x1c0 crypto/skcipher.c:695
_skcipher_recvmsg crypto/algif_skcipher.c:199 [inline]
skcipher_recvmsg+0x1691/0x2190 crypto/algif_skcipher.c:221
sock_recvmsg_nosec net/socket.c:1046 [inline]
sock_recvmsg net/socket.c:1068 [inline]
____sys_recvmsg+0x283/0x7f0 net/socket.c:2803
___sys_recvmsg+0x223/0x840 net/socket.c:2845
do_recvmmsg+0x4fc/0xfd0 net/socket.c:2939
__sys_recvmmsg net/socket.c:3018 [inline]
__do_sys_recvmmsg net/socket.c:3041 [inline]
__se_sys_recvmmsg net/socket.c:3034 [inline]
__x64_sys_recvmmsg+0x397/0x490 net/socket.c:3034
do_syscall_x64 arch/x86/entry/common.c:52 [inline]
do_syscall_64+0xcf/0x1e0 arch/x86/entry/common.c:83
entry_SYSCALL_64_after_hwframe+0x63/0x6b

Uninit was stored to memory at:
memcpy_dir crypto/scatterwalk.c:23 [inline]
scatterwalk_copychunks crypto/scatterwalk.c:38 [inline]
scatterwalk_map_and_copy+0x6dc/0x9a0 crypto/scatterwalk.c:67
cts_cbc_decrypt+0x1b9/0x720 crypto/cts.c:197
crypto_cts_decrypt+0x77f/0x9b0 crypto/cts.c:280
crypto_skcipher_decrypt+0x189/0x1c0 crypto/skcipher.c:695
_skcipher_recvmsg crypto/algif_skcipher.c:199 [inline]
skcipher_recvmsg+0x1691/0x2190 crypto/algif_skcipher.c:221
sock_recvmsg_nosec net/socket.c:1046 [inline]
sock_recvmsg net/socket.c:1068 [inline]
____sys_recvmsg+0x283/0x7f0 net/socket.c:2803
___sys_recvmsg+0x223/0x840 net/socket.c:2845
do_recvmmsg+0x4fc/0xfd0 net/socket.c:2939
__sys_recvmmsg net/socket.c:3018 [inline]
__do_sys_recvmmsg net/socket.c:3041 [inline]
__se_sys_recvmmsg net/socket.c:3034 [inline]
__x64_sys_recvmmsg+0x397/0x490 net/socket.c:3034
do_syscall_x64 arch/x86/entry/common.c:52 [inline]
do_syscall_64+0xcf/0x1e0 arch/x86/entry/common.c:83
entry_SYSCALL_64_after_hwframe+0x63/0x6b

Uninit was stored to memory at:
__crypto_xor+0x171/0x1310 lib/crypto/utils.c:45
crypto_xor include/crypto/utils.h:31 [inline]
crypto_cbc_decrypt_segment crypto/cbc.c:81 [inline]
crypto_cbc_decrypt+0x2b1/0x8e0 crypto/cbc.c:133
crypto_lskcipher_crypt_sg+0x43f/0x930 crypto/lskcipher.c:229
crypto_lskcipher_decrypt_sg+0x8a/0xc0 crypto/lskcipher.c:258
crypto_skcipher_decrypt+0x10d/0x1c0 crypto/skcipher.c:693
crypto_cts_decrypt+0x704/0x9b0 crypto/cts.c:279
crypto_skcipher_decrypt+0x189/0x1c0 crypto/skcipher.c:695
_skcipher_recvmsg crypto/algif_skcipher.c:199 [inline]
skcipher_recvmsg+0x1691/0x2190 crypto/algif_skcipher.c:221
sock_recvmsg_nosec net/socket.c:1046 [inline]
sock_recvmsg net/socket.c:1068 [inline]
____sys_recvmsg+0x283/0x7f0 net/socket.c:2803
___sys_recvmsg+0x223/0x840 net/socket.c:2845
do_recvmmsg+0x4fc/0xfd0 net/socket.c:2939
__sys_recvmmsg net/socket.c:3018 [inline]
__do_sys_recvmmsg net/socket.c:3041 [inline]
__se_sys_recvmmsg net/socket.c:3034 [inline]
__x64_sys_recvmmsg+0x397/0x490 net/socket.c:3034
do_syscall_x64 arch/x86/entry/common.c:52 [inline]
do_syscall_64+0xcf/0x1e0 arch/x86/entry/common.c:83
entry_SYSCALL_64_after_hwframe+0x63/0x6b

Uninit was created at:
slab_post_alloc_hook mm/slub.c:3819 [inline]
slab_alloc_node mm/slub.c:3860 [inline]
__do_kmalloc_node mm/slub.c:3980 [inline]
__kmalloc+0x919/0xf80 mm/slub.c:3994
kmalloc include/linux/slab.h:594 [inline]
sock_kmalloc+0x134/0x1f0 net/core/sock.c:2685
af_alg_alloc_areq+0xe4/0x3a0 crypto/af_alg.c:1202
_skcipher_recvmsg crypto/algif_skcipher.c:118 [inline]
skcipher_recvmsg+0x4f0/0x2190 crypto/algif_skcipher.c:221
sock_recvmsg_nosec net/socket.c:1046 [inline]
sock_recvmsg net/socket.c:1068 [inline]
____sys_recvmsg+0x283/0x7f0 net/socket.c:2803
___sys_recvmsg+0x223/0x840 net/socket.c:2845
do_recvmmsg+0x4fc/0xfd0 net/socket.c:2939
__sys_recvmmsg net/socket.c:3018 [inline]
__do_sys_recvmmsg net/socket.c:3041 [inline]
__se_sys_recvmmsg net/socket.c:3034 [inline]
__x64_sys_recvmmsg+0x397/0x490 net/socket.c:3034
do_syscall_x64 arch/x86/entry/common.c:52 [inline]
do_syscall_64+0xcf/0x1e0 arch/x86/entry/common.c:83
entry_SYSCALL_64_after_hwframe+0x63/0x6b

CPU: 0 PID: 11510 Comm: syz-executor.0 Not tainted 6.8.0-rc4-syzkaller-00180-g4f5e5092fdbf #0
Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 01/25/2024
=====================================================


---
This report is generated by a bot. It may contain errors.
See https://goo.gl/tpsmEJ for more information about syzbot.
syzbot engineers can be reached at syzk...@googlegroups.com.

syzbot will keep track of this issue. See:
https://goo.gl/tpsmEJ#status for how to communicate with syzbot.

If the report is already addressed, let syzbot know by replying with:
#syz fix: exact-commit-title

If you want to overwrite report's subsystems, reply with:
#syz set subsystems: new-subsystem
(See the list of subsystem names on the web dashboard)

If the report is a duplicate of another one, reply with:
#syz dup: exact-subject-of-another-report

If you want to undo deduplication, reply with:
#syz undup

Herbert Xu

unread,
Feb 21, 2024, 4:07:42 AMFeb 21
to syzbot, da...@davemloft.net, linux-...@vger.kernel.org, linux-...@vger.kernel.org, syzkall...@googlegroups.com
The lskcipher glue code for skcipher needs to copy the IV every
time rather than only on the first and last request. Otherwise
those algorithms that use IV to perform chaining may break, e.g.,
CBC.

This is because crypto_skcipher_import/export do not include the
IV as part of the saved state.

Reported-by: syzbot+b90b90...@syzkaller.appspotmail.com
Fixes: 662ea18d089b ("crypto: skcipher - Make use of internal state")
Signed-off-by: Herbert Xu <her...@gondor.apana.org.au>

diff --git a/crypto/lskcipher.c b/crypto/lskcipher.c
index 0b6dd8aa21f2..0f1bd7dcde24 100644
--- a/crypto/lskcipher.c
+++ b/crypto/lskcipher.c
@@ -212,13 +212,12 @@ static int crypto_lskcipher_crypt_sg(struct skcipher_request *req,

ivsize = crypto_lskcipher_ivsize(tfm);
ivs = PTR_ALIGN(ivs, crypto_skcipher_alignmask(skcipher) + 1);
+ memcpy(ivs, req->iv, ivsize);

flags = req->base.flags & CRYPTO_TFM_REQ_MAY_SLEEP;

if (req->base.flags & CRYPTO_SKCIPHER_REQ_CONT)
flags |= CRYPTO_LSKCIPHER_FLAG_CONT;
- else
- memcpy(ivs, req->iv, ivsize);

if (!(req->base.flags & CRYPTO_SKCIPHER_REQ_NOTFINAL))
flags |= CRYPTO_LSKCIPHER_FLAG_FINAL;
@@ -234,8 +233,7 @@ static int crypto_lskcipher_crypt_sg(struct skcipher_request *req,
flags |= CRYPTO_LSKCIPHER_FLAG_CONT;
}

- if (flags & CRYPTO_LSKCIPHER_FLAG_FINAL)
- memcpy(req->iv, ivs, ivsize);
+ memcpy(req->iv, ivs, ivsize);

return err;
}
--
Email: Herbert Xu <her...@gondor.apana.org.au>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt

xingwei lee

unread,
Feb 23, 2024, 9:56:17 AMFeb 23
to syzbot+b90b90...@syzkaller.appspotmail.com, da...@davemloft.net, her...@gondor.apana.org.au, linux-...@vger.kernel.org, linux-...@vger.kernel.org, syzkall...@googlegroups.com
Hello, I reproduced this bug in the upstream linux.

If you fix this issue, please add the following tag to the commit:
Reported-by: xingwei lee <xrive...@gmail.com>

Notice: I use the same config with syzbot dashboard.
kernel version: 4f5e5092fdbf5cec6bedc19fbe69cce4f5f08372
kernel config: https://syzkaller.appspot.com/text?tag=KernelConfig&x=e3dd779fba027968
with KASAN enabled
compiler: Debian clang version 15.0.6, GNU ld (GNU Binutils for Debian) 2.40

BTW, I notice the frist patch apply in this bug:
https://lore.kernel.org/all/ZdW9YBgT...@gondor.apana.org.au/T/
and git apply this patch in the kernel. Since the reproducer is an
infinite loop, I run the reproducer for about 20minus it doesn’t
trigger the same issue.

Anyway, the reproducer I’ll provided as below.

=* repro.c =*
// autogenerated by syzkaller (https://github.com/google/syzkaller)
#include <arpa/inet.h>
#include <dirent.h>
#include <endian.h>
#include <errno.h>
#include <fcntl.h>
#include <net/if.h>
#include <netinet/in.h>
#include <pthread.h>
#include <signal.h>
#include <stdarg.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/prctl.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <sys/syscall.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <time.h>
#include <unistd.h>

#include <linux/futex.h>
#include <linux/genetlink.h>
#include <linux/if_addr.h>
#include <linux/if_link.h>
#include <linux/in6.h>
#include <linux/neighbour.h>
#include <linux/net.h>
#include <linux/netlink.h>
#include <linux/rtnetlink.h>
#include <linux/veth.h>

static void sleep_ms(uint64_t ms) {
usleep(ms * 1000);
}

static uint64_t current_time_ms(void) {
struct timespec ts;
if (clock_gettime(CLOCK_MONOTONIC, &ts))
exit(1);
return (uint64_t)ts.tv_sec * 1000 + (uint64_t)ts.tv_nsec / 1000000;
}

static void thread_start(void* (*fn)(void*), void* arg) {
pthread_t th;
pthread_attr_t attr;
pthread_attr_init(&attr);
pthread_attr_setstacksize(&attr, 128 << 10);
int i = 0;
for (; i < 100; i++) {
if (pthread_create(&th, &attr, fn, arg) == 0) {
pthread_attr_destroy(&attr);
return;
}
if (errno == EAGAIN) {
usleep(50);
continue;
}
break;
}
exit(1);
}

typedef struct {
int state;
} event_t;

static void event_init(event_t* ev) {
ev->state = 0;
}

static void event_reset(event_t* ev) {
ev->state = 0;
}

static void event_set(event_t* ev) {
if (ev->state)
exit(1);
__atomic_store_n(&ev->state, 1, __ATOMIC_RELEASE);
syscall(SYS_futex, &ev->state, FUTEX_WAKE | FUTEX_PRIVATE_FLAG, 1000000);
}

static void event_wait(event_t* ev) {
while (!__atomic_load_n(&ev->state, __ATOMIC_ACQUIRE))
syscall(SYS_futex, &ev->state, FUTEX_WAIT | FUTEX_PRIVATE_FLAG, 0, 0);
}

static int event_isset(event_t* ev) {
return __atomic_load_n(&ev->state, __ATOMIC_ACQUIRE);
}

static int event_timedwait(event_t* ev, uint64_t timeout) {
uint64_t start = current_time_ms();
uint64_t now = start;
for (;;) {
uint64_t remain = timeout - (now - start);
struct timespec ts;
ts.tv_sec = remain / 1000;
ts.tv_nsec = (remain % 1000) * 1000 * 1000;
syscall(SYS_futex, &ev->state, FUTEX_WAIT | FUTEX_PRIVATE_FLAG, 0, &ts);
if (__atomic_load_n(&ev->state, __ATOMIC_ACQUIRE))
return 1;
now = current_time_ms();
if (now - start > timeout)
return 0;
}
}

static bool write_file(const char* file, const char* what, ...) {
char buf[1024];
va_list args;
va_start(args, what);
vsnprintf(buf, sizeof(buf), what, args);
va_end(args);
buf[sizeof(buf) - 1] = 0;
int len = strlen(buf);
int fd = open(file, O_WRONLY | O_CLOEXEC);
if (fd == -1)
return false;
if (write(fd, buf, len) != len) {
int err = errno;
close(fd);
errno = err;
return false;
}
close(fd);
return true;
}

struct nlmsg {
char* pos;
int nesting;
struct nlattr* nested[8];
char buf[4096];
};

static void netlink_init(struct nlmsg* nlmsg,
int typ,
int flags,
const void* data,
int size) {
memset(nlmsg, 0, sizeof(*nlmsg));
struct nlmsghdr* hdr = (struct nlmsghdr*)nlmsg->buf;
hdr->nlmsg_type = typ;
hdr->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK | flags;
memcpy(hdr + 1, data, size);
nlmsg->pos = (char*)(hdr + 1) + NLMSG_ALIGN(size);
}

static void netlink_attr(struct nlmsg* nlmsg,
int typ,
const void* data,
int size) {
struct nlattr* attr = (struct nlattr*)nlmsg->pos;
attr->nla_len = sizeof(*attr) + size;
attr->nla_type = typ;
if (size > 0)
memcpy(attr + 1, data, size);
nlmsg->pos += NLMSG_ALIGN(attr->nla_len);
}

static int netlink_send_ext(struct nlmsg* nlmsg,
int sock,
uint16_t reply_type,
int* reply_len,
bool dofail) {
if (nlmsg->pos > nlmsg->buf + sizeof(nlmsg->buf) || nlmsg->nesting)
exit(1);
struct nlmsghdr* hdr = (struct nlmsghdr*)nlmsg->buf;
hdr->nlmsg_len = nlmsg->pos - nlmsg->buf;
struct sockaddr_nl addr;
memset(&addr, 0, sizeof(addr));
addr.nl_family = AF_NETLINK;
ssize_t n = sendto(sock, nlmsg->buf, hdr->nlmsg_len, 0,
(struct sockaddr*)&addr, sizeof(addr));
if (n != (ssize_t)hdr->nlmsg_len) {
if (dofail)
exit(1);
return -1;
}
n = recv(sock, nlmsg->buf, sizeof(nlmsg->buf), 0);
if (reply_len)
*reply_len = 0;
if (n < 0) {
if (dofail)
exit(1);
return -1;
}
if (n < (ssize_t)sizeof(struct nlmsghdr)) {
errno = EINVAL;
if (dofail)
exit(1);
return -1;
}
if (hdr->nlmsg_type == NLMSG_DONE)
return 0;
if (reply_len && hdr->nlmsg_type == reply_type) {
*reply_len = n;
return 0;
}
if (n < (ssize_t)(sizeof(struct nlmsghdr) + sizeof(struct nlmsgerr))) {
errno = EINVAL;
if (dofail)
exit(1);
return -1;
}
if (hdr->nlmsg_type != NLMSG_ERROR) {
errno = EINVAL;
if (dofail)
exit(1);
return -1;
}
errno = -((struct nlmsgerr*)(hdr + 1))->error;
return -errno;
}

static int netlink_query_family_id(struct nlmsg* nlmsg,
int sock,
const char* family_name,
bool dofail) {
struct genlmsghdr genlhdr;
memset(&genlhdr, 0, sizeof(genlhdr));
genlhdr.cmd = CTRL_CMD_GETFAMILY;
netlink_init(nlmsg, GENL_ID_CTRL, 0, &genlhdr, sizeof(genlhdr));
netlink_attr(nlmsg, CTRL_ATTR_FAMILY_NAME, family_name,
strnlen(family_name, GENL_NAMSIZ - 1) + 1);
int n = 0;
int err = netlink_send_ext(nlmsg, sock, GENL_ID_CTRL, &n, dofail);
if (err < 0) {
return -1;
}
uint16_t id = 0;
struct nlattr* attr = (struct nlattr*)(nlmsg->buf + NLMSG_HDRLEN +
NLMSG_ALIGN(sizeof(genlhdr)));
for (; (char*)attr < nlmsg->buf + n;
attr = (struct nlattr*)((char*)attr + NLMSG_ALIGN(attr->nla_len))) {
if (attr->nla_type == CTRL_ATTR_FAMILY_ID) {
id = *(uint16_t*)(attr + 1);
break;
}
}
if (!id) {
errno = EINVAL;
return -1;
}
recv(sock, nlmsg->buf, sizeof(nlmsg->buf), 0);
return id;
}

static long syz_genetlink_get_family_id(volatile long name,
volatile long sock_arg) {
int fd = sock_arg;
if (fd < 0) {
fd = socket(AF_NETLINK, SOCK_RAW, NETLINK_GENERIC);
if (fd == -1) {
return -1;
}
}
struct nlmsg nlmsg_tmp;
int ret = netlink_query_family_id(&nlmsg_tmp, fd, (char*)name, false);
if ((int)sock_arg < 0)
close(fd);
if (ret < 0) {
return -1;
}
return ret;
}

static void kill_and_wait(int pid, int* status) {
kill(-pid, SIGKILL);
kill(pid, SIGKILL);
for (int i = 0; i < 100; i++) {
if (waitpid(-1, status, WNOHANG | __WALL) == pid)
return;
usleep(1000);
}
DIR* dir = opendir("/sys/fs/fuse/connections");
if (dir) {
for (;;) {
struct dirent* ent = readdir(dir);
if (!ent)
break;
if (strcmp(ent->d_name, ".") == 0 || strcmp(ent->d_name, "..") == 0)
continue;
char abort[300];
snprintf(abort, sizeof(abort), "/sys/fs/fuse/connections/%s/abort",
ent->d_name);
int fd = open(abort, O_WRONLY);
if (fd == -1) {
continue;
}
if (write(fd, abort, 1) < 0) {
}
close(fd);
}
closedir(dir);
} else {
}
while (waitpid(-1, status, __WALL) != pid) {
}
}

static void setup_test() {
prctl(PR_SET_PDEATHSIG, SIGKILL, 0, 0, 0);
setpgrp();
write_file("/proc/self/oom_score_adj", "1000");
}

struct thread_t {
int created, call;
event_t ready, done;
};

static struct thread_t threads[16];
static void execute_call(int call);
static int running;

static void* thr(void* arg) {
struct thread_t* th = (struct thread_t*)arg;
for (;;) {
event_wait(&th->ready);
event_reset(&th->ready);
execute_call(th->call);
__atomic_fetch_sub(&running, 1, __ATOMIC_RELAXED);
event_set(&th->done);
}
return 0;
}

static void execute_one(void) {
int i, call, thread;
for (call = 0; call < 7; call++) {
for (thread = 0; thread < (int)(sizeof(threads) / sizeof(threads[0]));
thread++) {
struct thread_t* th = &threads[thread];
if (!th->created) {
th->created = 1;
event_init(&th->ready);
event_init(&th->done);
event_set(&th->done);
thread_start(thr, th);
}
if (!event_isset(&th->done))
continue;
event_reset(&th->done);
th->call = call;
__atomic_fetch_add(&running, 1, __ATOMIC_RELAXED);
event_set(&th->ready);
event_timedwait(&th->done, 50);
break;
}
}
for (i = 0; i < 100 && __atomic_load_n(&running, __ATOMIC_RELAXED); i++)
sleep_ms(1);
}

static void execute_one(void);

#define WAIT_FLAGS __WALL

static void loop(void) {
int iter = 0;
for (;; iter++) {
int pid = fork();
if (pid < 0)
exit(1);
if (pid == 0) {
setup_test();
execute_one();
exit(0);
}
int status = 0;
uint64_t start = current_time_ms();
for (;;) {
if (waitpid(-1, &status, WNOHANG | WAIT_FLAGS) == pid)
break;
sleep_ms(1);
if (current_time_ms() - start < 5000)
continue;
kill_and_wait(pid, &status);
break;
}
}
}

uint64_t r[2] = {0xffffffffffffffff, 0xffffffffffffffff};

void execute_call(int call) {
intptr_t res = 0;
switch (call) {
case 0:
res = syscall(__NR_socket, /*domain=*/0x26ul, /*type=*/5ul, /*proto=*/0);
if (res != -1)
r[0] = res;
break;
case 1:
*(uint16_t*)0x20000000 = 0x26;
memcpy((void*)0x20000002, "skcipher\000\000\000\000\000\000", 14);
*(uint32_t*)0x20000010 = 0;
*(uint32_t*)0x20000014 = 0;
memcpy((void*)0x20000018,
"cts(cbc(des3_ede))"
"\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"
"\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"
"\000\000\000\000\000\000\000\000\000\000\000\000\000\000",
64);
syscall(__NR_bind, /*fd=*/r[0], /*addr=*/0x20000000ul,
/*addrlen=*/0x58ul);
break;
case 2:
memcpy((void*)0x20c18000,
"\xad\x56\xb6\xc5\x82\x0f\xae\x9d\x6d\xcd\x32\x92\xea\x54\xc7\xbe"
"\xef\x91\x5d\x56\x4c\x90\xc2\x00",
24);
syscall(__NR_setsockopt, /*fd=*/r[0], /*level=*/0x117, /*opt=*/1,
/*key=*/0x20c18000ul, /*keylen=*/0x18ul);
break;
case 3:
res = syscall(__NR_accept4, /*fd=*/r[0], /*peer=*/0ul, /*peerlen=*/0ul,
/*flags=*/0ul);
if (res != -1)
r[1] = res;
break;
case 4:
memcpy((void*)0x20000100, "nl80211\000", 8);
syz_genetlink_get_family_id(/*name=*/0x20000100, /*fd=*/r[1]);
break;
case 5:
*(uint64_t*)0x200001c0 = 0;
*(uint32_t*)0x200001c8 = 0;
*(uint64_t*)0x200001d0 = 0x20000180;
*(uint64_t*)0x20000180 = 0x20000140;
*(uint32_t*)0x20000140 = 0x28;
*(uint16_t*)0x20000144 = 0;
*(uint16_t*)0x20000146 = 0;
*(uint32_t*)0x20000148 = 0;
*(uint32_t*)0x2000014c = 0;
*(uint8_t*)0x20000150 = 0x35;
*(uint8_t*)0x20000151 = 0;
*(uint16_t*)0x20000152 = 0;
*(uint16_t*)0x20000154 = 8;
*(uint16_t*)0x20000156 = 3;
*(uint32_t*)0x20000158 = 0;
*(uint16_t*)0x2000015c = 0xc;
*(uint16_t*)0x2000015e = 0x99;
*(uint32_t*)0x20000160 = 0;
*(uint32_t*)0x20000164 = 0;
*(uint64_t*)0x20000188 = 0x28;
*(uint64_t*)0x200001d8 = 1;
*(uint64_t*)0x200001e0 = 0;
*(uint64_t*)0x200001e8 = 0;
*(uint32_t*)0x200001f0 = 0;
syscall(__NR_sendmsg, /*fd=*/r[1], /*msg=*/0x200001c0ul, /*f=*/0x8000ul);
break;
case 6:
*(uint64_t*)0x20003fc0 = 0;
*(uint32_t*)0x20003fc8 = 0;
*(uint64_t*)0x20003fd0 = 0x20000080;
*(uint64_t*)0x20000080 = 0x20000380;
memcpy((void*)0x20000380,
"\x05\xe2\x7d\x49\x1f\xdb\x75\x96\x99\x7a\xf6\xa7", 12);
*(uint64_t*)0x20000088 = 0xc;
*(uint64_t*)0x20003fd8 = 1;
*(uint64_t*)0x20003fe0 = 0;
*(uint64_t*)0x20003fe8 = 0;
*(uint32_t*)0x20003ff0 = 0;
*(uint32_t*)0x20003ff8 = 0;
syscall(__NR_sendmmsg, /*fd=*/r[1], /*mmsg=*/0x20003fc0ul, /*vlen=*/1ul,
/*f=*/0ul);
break;
}
}
int main(void) {
syscall(__NR_mmap, /*addr=*/0x1ffff000ul, /*len=*/0x1000ul, /*prot=*/0ul,
/*flags=*/0x32ul, /*fd=*/-1, /*offset=*/0ul);
syscall(__NR_mmap, /*addr=*/0x20000000ul, /*len=*/0x1000000ul, /*prot=*/7ul,
/*flags=*/0x32ul, /*fd=*/-1, /*offset=*/0ul);
syscall(__NR_mmap, /*addr=*/0x21000000ul, /*len=*/0x1000ul, /*prot=*/0ul,
/*flags=*/0x32ul, /*fd=*/-1, /*offset=*/0ul);
loop();
return 0;
}

Remember to run this repro.txt with the command: syz-execprog -repeat
0 ./repro.txt and wait, the bug triggered very steady.

=* repro.txt =*
r0 = socket$alg(0x26, 0x5, 0x0)
bind$alg(r0, &(0x7f0000000000)={0x26, 'skcipher\x00', 0x0, 0x0,
'cts(cbc(des3_ede))\x00'}, 0x58)
setsockopt$ALG_SET_KEY(r0, 0x117, 0x1,
&(0x7f0000c18000)="ad56b6c5820fae9d6dcd3292ea54c7beef915d564c90c200",
0x18)
r1 = accept4(r0, 0x0, 0x0, 0x0)
syz_genetlink_get_family_id$nl80211(&(0x7f0000000100), r1)
sendmsg$NL80211_CMD_DEL_PMKSA(r1, &(0x7f00000001c0)={0x0, 0x0,
&(0x7f0000000180)={&(0x7f0000000140)={0x28, 0x0, 0x0, 0x0, 0x0, {{},
{@val={0x8}, @val={0xc}}}}, 0x28}}, 0x8000)
sendmmsg$unix(r1, &(0x7f0000003fc0)=[{{0x0, 0x0,
&(0x7f0000000080)=[{&(0x7f0000000380)="05e27d491fdb7596997af6a7",
0xc}], 0x1}}], 0x1, 0x0)

and see also in
https://gist.github.com/xrivendell7/caa81fc506c57143468d8df12e099831.

I hope it helps.
Best regards!
xingwei Lee
Reply all
Reply to author
Forward
0 new messages