mmap bug?

Hello,

the next example look curious for me.
plz, tell me : where i wrong:

in this example
server allocates memory with mmap() call with flags
MAP_ANON|MAP_PHYS|MAP_NOX64K
(see: w/o MAP_SHARED!!!)
but in any case (also if MAP_PRIVATE is set)
client (separate process) could read/write this memory!!!
Q: WHY???


// EXAMPLE --------------------------------
#include <stdio.h>
#include <errno.h>
#include <stdlib.h>
#include <sys/dispatch.h>
#include <sys/mman.h>

#define ATTACH_POINT “myname”

#define ALLOCMEM(len) mmap(NULL, len, PROT_READ | PROT_WRITE |
PROT_NOCACHE, MAP_ANON|MAP_PHYS|MAP_NOX64K, NOFD, 0)

#define MMAPMEM(len,phys) mmap_device_memory( 0, len, PROT_READ | PROT_WRITE
| PROT_NOCACHE, 0, phys);

paddr_t mphys(void *addr) {
off64_t offset;
if(mem_offset64(addr, NOFD, 1, &offset, 0) == -1) {
return -1;
}
return offset;
}

/* We specify the header as being at least a pulse */
typedef struct _pulse msg_header_t;

/* Our real data comes after the header /
typedef struct _my_data {
msg_header_t hdr;
int data;
void
shared_buf;
unsigned buflen;
uint64_t physical;
} my_data_t;

static uint64_t physical = (uint64_t)-1;
static char * shared_buf;
#define BUF_LEN 0x1000000

/*** Server Side of the code ***/
int server() {
name_attach_t *attach;
my_data_t msg;
int rcvid;

/* Create a local name (/dev/name/local/…) */
if ((attach = name_attach(NULL, ATTACH_POINT, 0)) == NULL) {
perror(“name_attach”);
return EXIT_FAILURE;
}

shared_buf = ALLOCMEM(BUF_LEN);
if (shared_buf == MAP_FAILED){
perror(“mmap”);
return EXIT_FAILURE;
}
physical = mphys (shared_buf);
printf (“Server: physical:%llX shared_buf:%p\n”, physical, shared_buf);
if (physical == (paddr_t)-1){
perror(“mphys”);
return EXIT_FAILURE;
}
memset (shared_buf, 0, BUF_LEN);
memset (&msg, 0, sizeof msg);

/* Do your MsgReceive’s here now with the chid */
while (1) {

strcpy (shared_buf, “server”);

rcvid = MsgReceive(attach->chid, &msg, sizeof(msg), NULL);

if (rcvid == -1) {/* Error condition, exit */
break;
}

if (rcvid == 0) {/* Pulse received /
switch (msg.hdr.code) {
case _PULSE_CODE_DISCONNECT:
/

  • A client disconnected all its connections (called
  • name_close() for each name_open() of our name) or
  • terminated
    /
    ConnectDetach(msg.hdr.scoid);
    break;
    case _PULSE_CODE_UNBLOCK:
    /
  • REPLY blocked client wants to unblock (was hit by
  • a signal or timed out). It’s up to you if you
  • reply now or later.
    /
    break;
    default:
    /
  • A pulse sent by one of your processes or a
  • _PULSE_CODE_COIDDEATH or _PULSE_CODE_THREADDEATH
  • from the kernel?
    */
    }
    continue;
    }

/* A QNX IO message received, reject */
if (msg.hdr.type >= _IO_BASE && msg.hdr.type <= _IO_MAX) {
MsgError(rcvid, ENOSYS);
continue;
}

/* A message (presumable ours) received, handle */
printf(“Server receive %d \n”, msg.data);
msg.physical = physical;
msg.buflen = BUF_LEN;
msg.shared_buf = shared_buf;
printf (“physical:%llX shared_buf:%p\n”, msg.physical, msg.shared_buf);
MsgReply(rcvid, EOK, &msg, sizeof msg);
printf (“shared_buf:[%s]\n”,shared_buf);
}

/* Remove the name from the space */
name_detach(attach, 0);

return EXIT_SUCCESS;
}

/*** Client Side of the code ***/
int client() {
my_data_t msg;
my_data_t omsg;
int fd;

if ((fd = name_open(ATTACH_POINT, 0)) == -1) {
return EXIT_FAILURE;
}

memset (&msg, 0, sizeof msg);
memset (&omsg, 0, sizeof omsg);
/* We would have pre-defined data to stuff here */
msg.hdr.type = 0x00;
msg.hdr.subtype = 0x00;

/* Do whatever work you wanted with server connection */
for (msg.data=0; msg.data < 5; msg.data++) {
printf(“Client sending %d \n”, msg.data);
if (MsgSend(fd, &msg, sizeof(msg), &omsg, sizeof omsg) == -1) {
break;
}
if (shared_buf)
break;
printf (“physical:%llX shared_buf:%p buflen:%u\n”,
omsg.physical, omsg.shared_buf, omsg.buflen);
if (omsg.physical != (paddr_t)-1){
// shared_buf = mmap_device_memory( 0, BUF_LEN, PROT_READ | PROT_WRITE |
PROT_NOCACHE, 0, omsg.physical);
shared_buf = MMAPMEM (omsg.buflen, omsg.physical);
if (shared_buf == MAP_FAILED){
perror(“mmap_device_memory”);
}else{
printf (“shared_buf:[%s]\n”,shared_buf);
strcpy (shared_buf, “client”);
}
}
}

/* Close the connection */
name_close(fd);
return 0;//EXIT_SUCCESS;
}

int main(int argc, char **argv) {
int ret;

if (argc < 2) {
// printf(“Running Server … \n”);
// ret = server(); /* see name_attach() for this code /
printf(“Usage %s -s | -c \n”, argv[0]);
ret = EXIT_FAILURE;
}else if (strcmp(argv[1], “-c”) == 0) {
printf(“Running Client … \n”);
ret = client(); /
see name_open() for this code /
}else if (strcmp(argv[1], “-s”) == 0) {
printf(“Running Server … \n”);
ret = server(); /
see name_attach() for this code */
}else{
printf(“Usage %s -s | -c \n”, argv[0]);
ret = EXIT_FAILURE;
}
return ret;
}

vasilii <vv40in@rambler.ru> wrote:

Hello,

the next example look curious for me.
plz, tell me : where i wrong:

The example does what it should.

in this example
server allocates memory with mmap() call with flags
MAP_ANON|MAP_PHYS|MAP_NOX64K
(see: w/o MAP_SHARED!!!)
but in any case (also if MAP_PRIVATE is set)

That allocates some physically contiguous RAM. As expected.

client (separate process) could read/write this memory!!!
Q: WHY???

Because of how the client gains access to the memory. He goes and
maps in the PHYSICAL RAM already allocated to the server. Of course,
changes by one are going to be seen by both – the client explicitly
set out to get the same physical memory.

-David

// EXAMPLE --------------------------------
#include <stdio.h
#include <errno.h
#include <stdlib.h
#include <sys/dispatch.h
#include <sys/mman.h

#define ATTACH_POINT “myname”

#define ALLOCMEM(len) mmap(NULL, len, PROT_READ | PROT_WRITE |
PROT_NOCACHE, MAP_ANON|MAP_PHYS|MAP_NOX64K, NOFD, 0)

#define MMAPMEM(len,phys) mmap_device_memory( 0, len, PROT_READ | PROT_WRITE
| PROT_NOCACHE, 0, phys);

paddr_t mphys(void *addr) {
off64_t offset;
if(mem_offset64(addr, NOFD, 1, &offset, 0) == -1) {
return -1;
}
return offset;
}

/* We specify the header as being at least a pulse */
typedef struct _pulse msg_header_t;

/* Our real data comes after the header /
typedef struct _my_data {
msg_header_t hdr;
int data;
void
shared_buf;
unsigned buflen;
uint64_t physical;
} my_data_t;

static uint64_t physical = (uint64_t)-1;
static char * shared_buf;
#define BUF_LEN 0x1000000

/*** Server Side of the code ***/
int server() {
name_attach_t *attach;
my_data_t msg;
int rcvid;

/* Create a local name (/dev/name/local/…) */
if ((attach = name_attach(NULL, ATTACH_POINT, 0)) == NULL) {
perror(“name_attach”);
return EXIT_FAILURE;
}

shared_buf = ALLOCMEM(BUF_LEN);
if (shared_buf == MAP_FAILED){
perror(“mmap”);
return EXIT_FAILURE;
}
physical = mphys (shared_buf);
printf (“Server: physical:%llX shared_buf:%p\n”, physical, shared_buf);
if (physical == (paddr_t)-1){
perror(“mphys”);
return EXIT_FAILURE;
}
memset (shared_buf, 0, BUF_LEN);
memset (&msg, 0, sizeof msg);

/* Do your MsgReceive’s here now with the chid */
while (1) {

strcpy (shared_buf, “server”);

rcvid = MsgReceive(attach->chid, &msg, sizeof(msg), NULL);

if (rcvid == -1) {/* Error condition, exit */
break;
}

if (rcvid == 0) {/* Pulse received /
switch (msg.hdr.code) {
case _PULSE_CODE_DISCONNECT:
/

  • A client disconnected all its connections (called
  • name_close() for each name_open() of our name) or
  • terminated
    /
    ConnectDetach(msg.hdr.scoid);
    break;
    case _PULSE_CODE_UNBLOCK:
    /
  • REPLY blocked client wants to unblock (was hit by
  • a signal or timed out). It’s up to you if you
  • reply now or later.
    /
    break;
    default:
    /
  • A pulse sent by one of your processes or a
  • _PULSE_CODE_COIDDEATH or _PULSE_CODE_THREADDEATH
  • from the kernel?
    */
    }
    continue;
    }

/* A QNX IO message received, reject */
if (msg.hdr.type >= _IO_BASE && msg.hdr.type <= _IO_MAX) {
MsgError(rcvid, ENOSYS);
continue;
}

/* A message (presumable ours) received, handle */
printf(“Server receive %d \n”, msg.data);
msg.physical = physical;
msg.buflen = BUF_LEN;
msg.shared_buf = shared_buf;
printf (“physical:%llX shared_buf:%p\n”, msg.physical, msg.shared_buf);
MsgReply(rcvid, EOK, &msg, sizeof msg);
printf (“shared_buf:[%s]\n”,shared_buf);
}

/* Remove the name from the space */
name_detach(attach, 0);

return EXIT_SUCCESS;
}

/*** Client Side of the code ***/
int client() {
my_data_t msg;
my_data_t omsg;
int fd;

if ((fd = name_open(ATTACH_POINT, 0)) == -1) {
return EXIT_FAILURE;
}

memset (&msg, 0, sizeof msg);
memset (&omsg, 0, sizeof omsg);
/* We would have pre-defined data to stuff here */
msg.hdr.type = 0x00;
msg.hdr.subtype = 0x00;

/* Do whatever work you wanted with server connection */
for (msg.data=0; msg.data < 5; msg.data++) {
printf(“Client sending %d \n”, msg.data);
if (MsgSend(fd, &msg, sizeof(msg), &omsg, sizeof omsg) == -1) {
break;
}
if (shared_buf)
break;
printf (“physical:%llX shared_buf:%p buflen:%u\n”,
omsg.physical, omsg.shared_buf, omsg.buflen);
if (omsg.physical != (paddr_t)-1){
// shared_buf = mmap_device_memory( 0, BUF_LEN, PROT_READ | PROT_WRITE |
PROT_NOCACHE, 0, omsg.physical);
shared_buf = MMAPMEM (omsg.buflen, omsg.physical);
if (shared_buf == MAP_FAILED){
perror(“mmap_device_memory”);
}else{
printf (“shared_buf:[%s]\n”,shared_buf);
strcpy (shared_buf, “client”);
}
}
}

/* Close the connection */
name_close(fd);
return 0;//EXIT_SUCCESS;
}

int main(int argc, char **argv) {
int ret;

if (argc < 2) {
// printf(“Running Server … \n”);
// ret = server(); /* see name_attach() for this code /
printf(“Usage %s -s | -c \n”, argv[0]);
ret = EXIT_FAILURE;
}else if (strcmp(argv[1], “-c”) == 0) {
printf(“Running Client … \n”);
ret = client(); /
see name_open() for this code /
}else if (strcmp(argv[1], “-s”) == 0) {
printf(“Running Server … \n”);
ret = server(); /
see name_attach() for this code */
}else{
printf(“Usage %s -s | -c \n”, argv[0]);
ret = EXIT_FAILURE;
}
return ret;
}


QNX Training Services
http://www.qnx.com/support/training/
Please followup in this newsgroup if you have further questions.