LinuxQuestions.org
Latest LQ Deal: Latest LQ Deals
Home Forums Tutorials Articles Register
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.

Notices


Reply
  Search this Thread
Old 09-27-2008, 02:52 AM   #1
dumbsnake
LQ Newbie
 
Registered: Jun 2008
Posts: 3

Rep: Reputation: 0
Question asymmetric priviledges for sharing anonymous mmapped data between processes


Hey,

So, I've been reading for a while trying to figure this one out. What I want to do is this:

1. mmap some memory anonymously
2. fork a child
3. have the child lose write abilities for some of the memory mapped, but allow the parent to maintain them

If it worked, I figure it would look something like this:

Code:
void* rv = mmap(0, num_bytes, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_SHARED, -1, 0);
if(rv == MAP_FAILED){
  // handle error
}
if(fork()){
  // we are the parent...
  // do some stuff
}
else {
  // we are the child, drop priviledges irreversibly
  if(mprotect(rv, num_bytes, PROT_READ) == -1){
    // handle error
  }
  // do more child things
}
Obviously, the above code has some problems. First, if there is a shared object I believe that permissions are probably shared so that the parent and child both would have the same permissions. Second, I don't want the child to be able to undo the mprotect. I'd like to be able to run untrusted code as the client. I'm sure someone that knows more about this stuff can probably help me. I've poured over the syscalls, but clearly I've missed something. Thanks in advance!
 
Old 09-27-2008, 07:33 AM   #2
ta0kira
Senior Member
 
Registered: Sep 2004
Distribution: FreeBSD 9.1, Kubuntu 12.10
Posts: 3,078

Rep: Reputation: Disabled
Is there anything in man 7 capabilities that addresses this type of thing?
ta0kira
 
Old 09-27-2008, 01:31 PM   #3
dumbsnake
LQ Newbie
 
Registered: Jun 2008
Posts: 3

Original Poster
Rep: Reputation: 0
I looked in man 7 capabilities. It is good to know about capget and capset, but none of the capabilities seemed to be what I need. Thanks though, that was a good read that I probably should have done earlier. Particularly interesting that "file system support for attaching capabilities to an executable file, so that a process gains those capabilities when the file is execed" is not implemented. I liked that discussion. Thanks.

Any more ideas anybody?
 
Old 09-27-2008, 05:02 PM   #4
ta0kira
Senior Member
 
Registered: Sep 2004
Distribution: FreeBSD 9.1, Kubuntu 12.10
Posts: 3,078

Rep: Reputation: Disabled
Did you know that with file-backed mmap you could map it twice: once R/W and once R/O? You can map as both in the parent, then unmap the R/W right after fork, before the untrusted code is executed. As far as I know, you can't change the R/O mapping to a R/W mapping with mprotect. You also might consider using a setuid program in conjunction. This would allow you to either protect the underlying file if used with mmap or the share itself if you decide to use shmget (also a consideration.)
ta0kira

PS I'd go with a file-backed mmap if I were you. shm* has the risk of leaving a hanging memory segment even after all processes using it have exited. One process has to flag it for deletion, which then locks out all other mappings to it. It's a real pain, but you don't have to back it with a file. Not worth the trade in my opinion. The last time I used it I had to write a script that I'd call periodically during development to clean up the stray segments.

Last edited by ta0kira; 09-27-2008 at 05:21 PM.
 
Old 09-27-2008, 09:59 PM   #5
ta0kira
Senior Member
 
Registered: Sep 2004
Distribution: FreeBSD 9.1, Kubuntu 12.10
Posts: 3,078

Rep: Reputation: Disabled
Here's an example I made a while ago to test out double mapping:
Code:
#include <stdio.h>
#include <fcntl.h>
#include <signal.h>
#include <errno.h>
#include <string.h>
#include <unistd.h>
#include <sys/mman.h>


static void segv_handler(int sSignal)
{
	if (sSignal == SIGSEGV)
	{
	fprintf(stderr, "SIGSEGV caused by bad memory access!\n");
	signal(sSignal, SIG_DFL);
	raise(sSignal);
	}
}


int main()
{
	int mapping = open("./memory", O_RDWR | O_CREAT | O_TRUNC, 0644);
	if (mapping < 0)
	{
	fprintf(stderr, "mapping error: %s\n", strerror(errno));
	return 1;
	}

	int memory_size = getpagesize();

	ftruncate(mapping, memory_size); //non-standard, but used for convenience

	setlinebuf(stdout);
	signal(SIGSEGV, &segv_handler);


	void *read_only = mmap(NULL, memory_size, PROT_READ, MAP_SHARED, mapping, 0);
	if (!read_only)
	{
	fprintf(stderr, "read error: %s\n", strerror(errno));
	return 1;
	}


	void *read_write = mmap(NULL, memory_size, PROT_READ | PROT_WRITE, MAP_SHARED, mapping, 0);
	if (!read_write)
	{
	fprintf(stderr, "write error: %s\n", strerror(errno));
	return 1;
	}

	close(mapping); //<-- recently added; prevents child from calling 'fstat'


	char *write_to = (char*) read_write;
	snprintf(write_to, memory_size, "hello!");

	char *read_from = (char*) read_only;
	fprintf(stdout, "%s\n", read_from);


	snprintf(read_from, memory_size, "segfault here!");


	return 0;
}
ta0kira

Last edited by ta0kira; 09-27-2008 at 10:03 PM.
 
Old 09-29-2008, 05:13 PM   #6
dumbsnake
LQ Newbie
 
Registered: Jun 2008
Posts: 3

Original Poster
Rep: Reputation: 0
That makes a lot of sense. Your example code is very helpful. I wish I'd been able to find a code sample like the one you gave on my own, but I guess that is why forums exist! Thanks a lot.
 
Old 09-30-2008, 04:09 PM   #7
ta0kira
Senior Member
 
Registered: Sep 2004
Distribution: FreeBSD 9.1, Kubuntu 12.10
Posts: 3,078

Rep: Reputation: Disabled
You're welcome. It helps me, too, since a lot of what I know about *nix programming is a result of figuring out answers to questions in this forum that I have no previous experience with. This one was actually an answer to a similar virtual machine question from a while ago.
ta0kira
 
Old 10-01-2008, 07:41 PM   #8
sundialsvcs
LQ Guru
 
Registered: Feb 2004
Location: SE Tennessee, USA
Distribution: Gentoo, LFS
Posts: 10,659
Blog Entries: 4

Rep: Reputation: 3941Reputation: 3941Reputation: 3941Reputation: 3941Reputation: 3941Reputation: 3941Reputation: 3941Reputation: 3941Reputation: 3941Reputation: 3941Reputation: 3941
ta0kira, I'm sure that right now a lot of people on this forum are "hoping for a bit of elaboration..."
 
Old 10-01-2008, 09:18 PM   #9
ta0kira
Senior Member
 
Registered: Sep 2004
Distribution: FreeBSD 9.1, Kubuntu 12.10
Posts: 3,078

Rep: Reputation: Disabled
Yes, that did sound bad. I didn't mean "I answer questions not knowing what I'm talking about." I mean I've learned a whole lot from questions like "why doesn't this work..." when it has to do with something I haven't used; I figure out why it doesn't work and provide a legitimate answer. Or, "how can I get this functionality..."; I figure out how it can be done, only providing an answer when I've gotten the requested result (e.g. I haven't written an emulator, but I figured out how to have separate R/W and R/O access to the same memory specifically to answer a question.) But my advice-giving always comes from things I have experience with unless I say otherwise specifically. Generally the only things I "learn for the question" are for fixing specific run-time bugs and figuring out how functionality can be implemented, but that normally requires me to use all of my other experience that the asker might not have. It mostly just results in me learning new libc functions or e.g. learning how to socket program to see why a client can't read from a server; if my answer solves the problem it doesn't matter when I learned it, just that I haven't given unsubstantiated advice. If I'm the least bit uncertain about my answer then I point that out, also. You know, it's like the IT guy who fixes the office computers. Half the time he won't know how to fix a problem but he'll learn how to for that specific situation (maybe a bad analogy since sometimes IT fixes are worse than the problem .) Does that help? Thanks for calling me out! Everyone needs that once in a while (some more often.)
ta0kira

Last edited by ta0kira; 10-01-2008 at 09:29 PM.
 
  


Reply



Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off



Similar Threads
Thread Thread Starter Forum Replies Last Post
asymmetric key cryptography leedude General 7 09-19-2008 08:12 AM
Data exchange among processes abgrj Programming 8 04-01-2008 10:48 PM
Anonymous proxy with data encryption? LinuxSeeker Linux - Security 2 08-20-2005 09:21 PM
sharing memory between processes spuzzzzzzz Programming 2 10-13-2004 07:18 AM
C - sharing variables between forked processes? ocularbob Programming 5 03-14-2004 03:29 AM

LinuxQuestions.org > Forums > Non-*NIX Forums > Programming

All times are GMT -5. The time now is 12:46 PM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Open Source Consulting | Domain Registration