• Eric Biggers's avatar
    crypto: skcipher - fix crash flushing dcache in error path · 7e179bff
    Eric Biggers authored
    commit 8088d3dd upstream.
    scatterwalk_done() is only meant to be called after a nonzero number of
    bytes have been processed, since scatterwalk_pagedone() will flush the
    dcache of the *previous* page.  But in the error case of
    skcipher_walk_done(), e.g. if the input wasn't an integer number of
    blocks, scatterwalk_done() was actually called after advancing 0 bytes.
    This caused a crash ("BUG: unable to handle kernel paging request")
    during '!PageSlab(page)' on architectures like arm and arm64 that define
    ARCH_IMPLEMENTS_FLUSH_DCACHE_PAGE, provided that the input was
    page-aligned as in that case walk->offset == 0.
    Fix it by reorganizing skcipher_walk_done() to skip the
    scatterwalk_advance() and scatterwalk_done() if an error has occurred.
    This bug was found by syzkaller fuzzing.
    	#include <linux/if_alg.h>
    	#include <sys/socket.h>
    	#include <unistd.h>
    	int main()
    		struct sockaddr_alg addr = {
    			.salg_type = "skcipher",
    			.salg_name = "cbc(aes-generic)",
    		char buffer[4096] __attribute__((aligned(4096))) = { 0 };
    		int fd;
    		fd = socket(AF_ALG, SOCK_SEQPACKET, 0);
    		bind(fd, (void *)&addr, sizeof(addr));
    		setsockopt(fd, SOL_ALG, ALG_SET_KEY, buffer, 16);
    		fd = accept(fd, NULL, NULL);
    		write(fd, buffer, 15);
    		read(fd, buffer, 15);
    Reported-by: default avatarLiu Chao <liuchao741@huawei.com>
    Fixes: b286d8b1 ("crypto: skcipher - Add skcipher walk interface")
    Cc: <stable@vger.kernel.org> # v4.10+
    Signed-off-by: default avatarEric Biggers <ebiggers@google.com>
    Signed-off-by: default avatarHerbert Xu <herbert@gondor.apana.org.au>
    Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
skcipher.c 26 KB