Re: [PATCH] crypto: af_alg - Remove zero-copy support from AF_ALG

Eric Biggers
2026-05-04T22:25:25Z

On Mon, May 04, 2026 at 06:26:10PM +0000, Ⓐlï P☮latel wrote:
> On Monday, 4 May 2026 at 19:51, Eric Biggers <ebiggers@kernel.org> wrote:
>
> > On Mon, May 04, 2026 at 04:07:45PM +0000, Ⓐlï P☮latel wrote:
> > > Syd sandbox uses AF_ALG zero-copy for its Force Sandboxing[1] and Crypt Sandboxing[1].
> > > Zero-copy means Syd does not have to copy sandbox process data into its own address
> > > space providing safety and security. Switching to read/write rather than pipes and
> > > splice breaks a fundamental safety guarantee for the sandbox. Please do not break
> > > userspace.
> > >
> > > Will sendfile(2) continue to work?
> > >
> > > [1]: https://man.exherbo.org/syd.7.html#Force_Sandboxing
> > > [2]: https://man.exherbo.org/syd.7.html#Crypt_Sandboxing
> >
>
> > It's very unclear what that feature (which I don't think anyone knew
> > even existed) is trying to accomplish. Regardless, this patch doesn't
> > break the splice or sendfile syscalls. It just makes them run a bit
> > more slowly since the kernel will copy the data internally. So I think
> > your concern isn't justified.
> >
>
> > > How can i test? Please help me.
> >
>
> > If this is a feature you care about, perhaps you know how to test it?
>
> Thank you very much for the explanation and excuse me I panicked.
>
> > - Eric

I've tested that all three cases of read/write, sendfile, and
vmsplice+splice still work. The difference is just in how the kernel
implements them internally. See the following test program.

#define _GNU_SOURCE
#include <assert.h>
#include <fcntl.h>
#include <linux/if_alg.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <sys/sendfile.h>
#include <sys/socket.h>
#include <unistd.h>

int main(void)
{
for (int test = 0; test < 3; test++) {
uint8_t msg[32] = {};
uint8_t key[16] = {1,2,3,4};
struct sockaddr_alg addr = {
.salg_family = AF_ALG,
.salg_type = "skcipher",
.salg_name = "cbc(aes)",
};
int filefd, algfd, reqfd, pipefd[2], ret;

filefd = open("msg_file", O_RDWR|O_CREAT|O_TRUNC, 0600);
assert(filefd >= 0);
ret = pwrite(filefd, msg, sizeof(msg), 0);
assert(ret == sizeof(msg));

algfd = socket(AF_ALG, SOCK_SEQPACKET, 0);
assert(algfd >= 0);
ret = bind(algfd, (struct sockaddr *)&addr, sizeof(addr));
assert(ret == 0);
ret = setsockopt(algfd, SOL_ALG, ALG_SET_KEY, key, sizeof(key));
assert(ret == 0);

reqfd = accept(algfd, NULL, NULL);
assert(reqfd >= 0);

switch (test) {
case 0:
printf("read/write test\n");
ret = read(filefd, msg, sizeof(msg));
assert(ret == sizeof(msg));
ret = write(reqfd, msg, sizeof(msg));
assert(ret == sizeof(msg));
break;
case 1:
printf("sendfile test\n");
ret = sendfile(reqfd, filefd, NULL, sizeof(msg));
assert(ret == sizeof(msg));
break;
case 2:
printf("splice test\n");
ret = pipe(pipefd);
assert(ret == 0);
struct iovec iov = { .iov_base = msg, .iov_len = sizeof(msg) };
ret = vmsplice(pipefd[1], &iov, 1, SPLICE_F_GIFT);
assert(ret == sizeof(msg));
ret = splice(pipefd[0], NULL, reqfd, NULL, sizeof(msg), SPLICE_F_MOVE);
assert(ret == sizeof(msg));
break;
}
ret = read(reqfd, msg, sizeof(msg));
assert(ret == sizeof(msg));
for (int i = 0; i < sizeof(msg); i++)
printf("%02x ", msg[i]);
printf("\n");
}
}