Actually, I need to move data from the "mmaped V4L2 buffer" to a "Pipe" in the "User Space".
To ease the debugging, I created a simple test code to mimic the exact situation with the "V4L2" with the same results but using a reserved physical memory range as shown in the shown code.
The Issue:
The problem is that I am always getting "Bad Address (14)" error knowing that when I pass the address of a "Memory Region" allocated dynamically using "malloc()", it works fine!
I am afraid that "vmsplice()" doesn't work with "Mapped Memory". If so, the alternative such as using "writev()" takes a huge time violating my timing constraints so, what do you recommend in this case?
Is this behavior related to "CVE-2008-0600" security vulnerability?
Notes:
- The "Reserved Memory" is assured to be reserved in the "Device Tree" correctly.
- All addresses (physical/virtual) are perfectly aligned.
- "CONFIG_HARDENED_USERCOPY" and "CONFIG_STRICT_DEVMEM" are not set in the kernel.
- Kernel version = 5.10
Thank you very much.
/*****************************************************************************/
/* INCLUDE FILES */
/*****************************************************************************/
#ifdef __cplusplus
extern "C"
{
#endif
#include <string.h>
#include <pthread.h>
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <stdbool.h>
#include <stdint.h>
#include <errno.h>
#include <stdarg.h>
#include <limits.h>
#include <linux/if_alg.h>
#include <arpa/inet.h>
#include <fcntl.h>
#include <sys/uio.h>
#include "Platform_Types.h"
#include <sys/mman.h>
#ifdef __cplusplus
}
#endif
/*****************************************************************************/
/* CONSTANTS, MACROS */
/*****************************************************************************/
#define u32FRAME_SIZE ((uint32_t)(1024U * 1024U))
/*****************************************************************************/
/* TYPES */
/*****************************************************************************/
/*****************************************************************************/
/* PRIVATE VARIABLES */
/*****************************************************************************/
static uint8_t * SysStart_pu8Buffer = NULL;
/*****************************************************************************/
/* PRIVATE FUNCTIONS PROTOTYPES */
/*****************************************************************************/
/*****************************************************************************/
/* PRIVATE FUNCTIONS IMPLEMENTATION */
/*****************************************************************************/
int32_t main(int argc, char *argv[])
{
int32_t fd;
int s32Error;
int as32CrcPipes[2];
struct iovec iovBufferAddress;
fd = open("/dev/mem", (int32_t)O_RDWR|(int32_t)O_SYNC);
if(fd != -1)
{
printf("[OK] /dev/mem is opened .. \n");
}
SysStart_pu8Buffer = (uint8_t*)mmap(0,
0x100000,
(uint8)PROT_READ|(uint8)PROT_WRITE,
(uint8)MAP_SHARED,
fd,
0x85F00000);
if (SysStart_pu8Buffer != NULL)
{
printf("[OK] Memory Allocation ..\n");
}
s32Error = pipe(as32CrcPipes);
if (s32Error == (int)0)
{
printf("[OK] Pipe Creation ..\n");
}
s32Error = fcntl(as32CrcPipes[0], F_SETPIPE_SZ, u32FRAME_SIZE);
if (s32Error == (int)0)
{
printf("[OK] Pipe Set Size ..\n");
}
s32Error = fcntl(as32CrcPipes[1], F_SETPIPE_SZ, u32FRAME_SIZE);
if (s32Error == (int)0)
{
printf("[OK] Pipe Set Size ..\n");
}
iovBufferAddress.iov_base = SysStart_pu8Buffer;
iovBufferAddress.iov_len = u32FRAME_SIZE;
ssize_t size = vmsplice(as32CrcPipes[1],
(const struct iovec *)&iovBufferAddress,
(size_t)1,
(unsigned int)SPLICE_F_MOVE);
if (size < 0)
{
printf("[NOK] Error writing buffer to pipe => %s\n", strerror(errno));
}
return (int32_t)0;
}