[<prev] [next>] [<thread-prev] [day] [month] [year] [list]
Message-ID: <1585770.1688485992@warthog.procyon.org.uk>
Date: Tue, 04 Jul 2023 16:53:12 +0100
From: David Howells <dhowells@...hat.com>
To: Ondrej Mosnáček <omosnacek@...il.com>
Cc: dhowells@...hat.com,
Linux Crypto Mailing List <linux-crypto@...r.kernel.org>,
Herbert Xu <herbert@...dor.apana.org.au>,
Paolo Abeni <pabeni@...hat.com>, netdev@...r.kernel.org
Subject: Re: Regression bisected to "crypto: af_alg: Convert af_alg_sendpage() to use MSG_SPLICE_PAGES"
Here's a smaller test program. If it works correctly, it will print:
000: 5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a
020: 5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a
...
With the merging problem, it will print:
000: 5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a
020: 5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a
040: 6162636465666768696a6b6c6d6e6f707172737475767778797a313233343536
060: 4142434445464748494a4b4c4d4e4f505152535455565758595a313233343536
...
You can see the data from the send() ("abcd...") got appended to the page
passed by vmsplice() ("5a" x 64).
Arguably, if vmsplice() is given SPLICE_F_GIFT, AF_ALG would be within its
rights to remove the page from the caller's address space (as fuse will do
with SPLICE_F_MOVE), attach it to its scatterlist and append data to it. In
such a case, however, the calling process should no longer be able to access
the page - and in the case of libkcapi, the heap would be corrupted.
David
---
// SPDX-License-Identifier: GPL-2.0-or-later
/* AF_ALG vmsplice test
*
* Copyright (C) 2023 Red Hat, Inc. All Rights Reserved.
* Written by David Howells (dhowells@...hat.com)
*/
#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>
#include <limits.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/socket.h>
#include <sys/mman.h>
#include <linux/if_alg.h>
#define OSERROR(X, Y) \
do { if ((long)(X) == -1) { perror(Y); exit(1); } } while (0)
#define min(x, y) ((x) < (y) ? (x) : (y))
static unsigned char buffer[4096 * 32] __attribute__((aligned(4096)));
static unsigned char iv[16];
static unsigned char key[16];
static const struct sockaddr_alg sa = {
.salg_family = AF_ALG,
.salg_type = "skcipher",
.salg_name = "cbc(aes)",
};
static void algif_add_set_op(struct msghdr *msg, unsigned int op)
{
struct cmsghdr *__cmsg;
__cmsg = msg->msg_control + msg->msg_controllen;
__cmsg->cmsg_len = CMSG_LEN(sizeof(unsigned int));
__cmsg->cmsg_level = SOL_ALG;
__cmsg->cmsg_type = ALG_SET_OP;
*(unsigned int *)CMSG_DATA(__cmsg) = op;
msg->msg_controllen += CMSG_ALIGN(__cmsg->cmsg_len);
}
static void algif_add_set_iv(struct msghdr *msg, const void *iv, size_t ivlen)
{
struct af_alg_iv *ivbuf;
struct cmsghdr *__cmsg;
__cmsg = msg->msg_control + msg->msg_controllen;
__cmsg->cmsg_len = CMSG_LEN(sizeof(*ivbuf) + ivlen);
__cmsg->cmsg_level = SOL_ALG;
__cmsg->cmsg_type = ALG_SET_IV;
ivbuf = (struct af_alg_iv *)CMSG_DATA(__cmsg);
ivbuf->ivlen = ivlen;
memcpy(ivbuf->iv, iv, ivlen);
msg->msg_controllen += CMSG_ALIGN(__cmsg->cmsg_len);
}
void check(const unsigned char *p)
{
unsigned int i, j;
int blank = 0;
for (i = 0; i < 4096; i += 32) {
for (j = 0; j < 32; j++)
if (p[i + j])
break;
if (j == 32) {
if (!blank) {
printf("...\n");
blank = 1;
}
continue;
}
printf("%03x: ", i);
for (j = 0; j < 32; j++)
printf("%02x", p[i + j]);
printf("\n");
blank = 0;
}
}
int main(int argc, char *argv[])
{
struct iovec iov;
struct msghdr msg;
unsigned char ctrl[4096];
ssize_t ret;
size_t total = 0, i, out = 160;
unsigned char *buf;
int alg, sock, pfd[2];
alg = socket(AF_ALG, SOCK_SEQPACKET, 0);
OSERROR(alg, "AF_ALG");
OSERROR(bind(alg, (struct sockaddr *)&sa, sizeof(sa)), "bind");
OSERROR(setsockopt(alg, SOL_ALG, ALG_SET_KEY, key, sizeof(key)),
"ALG_SET_KEY");
sock = accept(alg, NULL, 0);
OSERROR(sock, "accept");
memset(&msg, 0, sizeof(msg));
msg.msg_control = ctrl;
algif_add_set_op(&msg, ALG_OP_ENCRYPT);
algif_add_set_iv(&msg, iv, sizeof(iv));
OSERROR(sendmsg(sock, &msg, MSG_MORE), "sock/sendmsg");
OSERROR(pipe(pfd), "pipe");
buf = mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_SHARED|MAP_ANON, -1, 0);
OSERROR(buf, "mmap");
memset(buf, 0x5a, 64);
iov.iov_base = buf;
iov.iov_len = 64;
OSERROR(vmsplice(pfd[1], &iov, 1, SPLICE_F_MORE), "vmsplice");
OSERROR(splice(pfd[0], NULL, sock, NULL, 64, SPLICE_F_MORE), "splice");
OSERROR(send(sock, "abcdefghijklmnopqrstuvwxyz123456ABCDEFGHIJKLMNOPQRSTUVWXYZ123456",
64, 0), "sock/send");
while (total > 0) {
ret = read(sock, buffer, min(sizeof(buffer), total));
OSERROR(ret, "sock/read");
if (ret == 0)
break;
total -= ret;
if (out > 0) {
ret = min(out, ret);
out -= ret;
for (i = 0; i < ret; i++)
printf("%02x", (unsigned char)buffer[i]);
}
printf("...\n");
}
check(buf);
OSERROR(close(sock), "sock/close");
OSERROR(close(alg), "alg/close");
OSERROR(close(pfd[0]), "close/p0");
OSERROR(close(pfd[1]), "close/p1");
return 0;
}
Powered by blists - more mailing lists