On 09/01/2014 05:22 PM, Ondrej Kozina wrote:
Attaching simple reproducer.
Sigh. Mondays... Sending fixed reproducer. Excuse my mistake. Kind regards Ondrej
#include <errno.h> #include <malloc.h> #include <stdint.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <linux/if_alg.h> #include <sys/socket.h> #include <sys/types.h> #ifndef SOL_ALG #define SOL_ALG 279 #endif #define IN_SIZE 1024 #define MODE "ecb" #define CIPHER "aes" const char key[] = "0123456789abcdef"; const size_t key_len = sizeof(key) - 1; static unsigned _getpagesize(void) { static unsigned ps; if (ps) return ps; long r = sysconf(_SC_PAGESIZE); ps = r < 0 ? 4096 : r; return ps; } static void fail(const char *msg) { fprintf(stderr, "%s. Couldn't verify the skcipher bug!\n", msg); } int main(void) { char *in = NULL; int err, r = 1; /* r == 0 => the bug in skcipher */ int opfd = -1; int tfmfd = -1; uint32_t *type; struct iovec iov; struct cmsghdr *hdr; struct sockaddr_alg sa = { .salg_family = AF_ALG, .salg_type = "skcipher", }; char buffer[CMSG_SPACE(sizeof(*type))]; struct msghdr msg = { .msg_control = buffer, .msg_controllen = sizeof(buffer), .msg_iov = &iov, .msg_iovlen = 1, }; printf("compare folowing page_size value with net.core.optmem_max value\n"); printf("detected system's page_size: %zu\n", _getpagesize()); if (posix_memalign((void **)&in, _getpagesize(), IN_SIZE)) { perror("posix_memalign()"); fail("memalign failed"); goto out; } memset((void *)in, 0, IN_SIZE); iov.iov_base = (void*)(uintptr_t)in; iov.iov_len = IN_SIZE; hdr = CMSG_FIRSTHDR(&msg); if (!hdr) { fail("small msg_control"); goto out; } hdr->cmsg_level = SOL_ALG; hdr->cmsg_type = ALG_SET_OP; hdr->cmsg_len = CMSG_LEN(sizeof(*type)); type = (void*)CMSG_DATA(hdr); *type = ALG_OP_ENCRYPT; if ((tfmfd = socket(AF_ALG, SOCK_SEQPACKET, 0)) == -1) { perror("socket()"); fail("socket() failed supported"); goto out; } snprintf((char *)sa.salg_name, sizeof(sa.salg_name), "%s(%s)", MODE, CIPHER); if (bind(tfmfd, (struct sockaddr *)&sa, sizeof(sa)) == -1) { perror("bind()"); fail("bind failed"); goto out; } if ((opfd = accept(tfmfd, NULL, 0)) == -1) { perror("accept()"); fail("accept failed"); goto out; } /* about to test aes-ecb with key size == 128b */ printf("calling setsockopt(), setting key with keylen==%zu\n", key_len); if (setsockopt(tfmfd, SOL_ALG, ALG_SET_KEY, key, key_len) == -1) { perror("setsockopt()"); fail("setsockopt failed"); goto out; } if (sendmsg(opfd, &msg, 0) != IN_SIZE) { err = errno; perror("sendmsg()"); if (err == ENOMEM) { printf("the kernel has a bug in a skcipher.\n"); r = 0; } else fail("sendmsg() failed w/ different error than expected. " "Can't verify the skcipher bug.\n"); } else fprintf(stderr, "sendmsg() passed. No bug in skcipher.\n"); out: if (in) free((void *)in); if (tfmfd >= 0) close(tfmfd); if (opfd >= 0) close(opfd); return r; }