linux-api.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* mmap a file without an overwrite risk?
@ 2023-10-17  0:56 Levo D
  0 siblings, 0 replies; only message in thread
From: Levo D @ 2023-10-17  0:56 UTC (permalink / raw)
  To: linux-api

[-- Attachment #1: Type: text/plain, Size: 826 bytes --]

Attached are 2 c files with main.c having reproduce instructions

I noticed if I try to read a large file it's a bit slow and mallocing/mmap a large amount of memory waits hundreds of milliseconds from the OS. However mmap is incredibly fast but leaves my software open to memory corruption. I attached a reproducable

I tried various MAP flags and couldn't think of a way to get rid of the risk. The gist of the problem is if I mmap a file another process can overwrite data which appears in mine, or delete the file causing my code to have a bus error. Not shown in the code is me trying to write to every page in hopes it'd prevent my memory from being overwritten, it didn't work either.

If there's nothing I can do is there an alternative way to load a file quicker than malloc+read? Files can be >100MB or GBs in size


[-- Attachment #2: main.c --]
[-- Type: application/octet-stream, Size: 1456 bytes --]

/* Reproducable steps
gcc main.c -o app1
gcc app2.c -o app2
fn=/tmp/uB2kCDFlDoRA56gdeuvOVKbL1KHXxMhDXc3pFnhjbhc
dd if=/dev/zero of=$fn count=5120 bs=4096; ./app1 $fn 1 | ./app2 $fn
You'll see "Result was 72" instead of "Result was 0"
dd if=/dev/zero of=$fn count=5120 bs=4096; ./app1 $fn 0 | ./app2 $fn
You'll see the desired "Result was 0"
In app2.c uncomment/comment line 13 and 12
gcc app2.c -o app2
Now this will have a bus error and last line written is waking
dd if=/dev/zero of=$fn count=5120 bs=4096; ./app1 $fn 1 | ./app2 $fn
read is unaffected
dd if=/dev/zero of=$fn count=5120 bs=4096; ./app1 $fn 0 | ./app2 $fn
*/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/mman.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/stat.h>
int main(int argc, char *argv[])
{
	//a.out filename 1
	if (argc != 3) {
		fprintf(stderr, "Bad args\n");
		return 1;
	}
	
	int fd = open(argv[1], O_RDONLY);
	struct stat s={0};
	fstat(fd, &s);
	char*p;
	if (argv[2][0] == '1')
		p = (char*)mmap(0, s.st_size, PROT_READ , MAP_PRIVATE, fd, 0);
	else {
		p = (char*)malloc(s.st_size);
		read(fd, p, s.st_size);
	}
	write(2, "Sleeping\n", 9);
	write(1, "Sleeping\n", 9); //Triggers the other app to write
	sleep(1);
	write(2, "Waking\n", 7);

	//read first byte of every 4k page
	int sum = 0;
	for (long i=0; i<s.st_size; i+=4096) {
		if (p[i] != 0) {
			int z=0;
		}
		sum += p[i];
	}
	fprintf(stderr, "Result was %d\n", sum);
	return 0;
}

[-- Attachment #3: app2.c --]
[-- Type: application/octet-stream, Size: 401 bytes --]

#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
int main(int argc, char *argv[])
{
	if (argc != 2) {
		fprintf(stderr, "Bad args\n");
		return 1;
	}
	char buf[4096];
	read(0, buf, 4096);
	int fd = open(argv[1], O_WRONLY|O_CREAT);
	//int fd = open(argv[1], O_WRONLY|O_CREAT|O_TRUNC|O_CLOEXEC); //<-- This one causes a bus error
	write(fd, "Hello", 5);
	fprintf(stderr, "Written %d\n", fd);
}

^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2023-10-17  1:03 UTC | newest]

Thread overview: (only message) (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2023-10-17  0:56 mmap a file without an overwrite risk? Levo D

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).