Re: gnome-keyring Quantifying non-pageable memory and expanding if necessary



 Hi Stef,

it looks like the allocation of locked pages is governed by a specific process capability: CAP_IPC_LOCK. Capabilities can be set on the executable at install time:

sudo setcap CAP_IPC_LOCK+ep <file>

Maybe setting this flag on the demon at install time will solve the problem (you do NOT have to be fully privileged). Note that this mechanism is very OS/version specific. I tried it successfully on the attached piece of code.

Thanks,
    Yaron

On 12/10/10 23:21, Stef Walter wrote:
I hope it's okay if I CC this to gnome-keyring-list.

On 2010-10-12 13:51, Yaron Sheffer wrote:
I'm running Ubuntu (just been through a catastrophic upgrade to 10.10,
but that's a different story). The ulimit is 64 - does this count as
super-low?
On my machine 64 = 64 KBytes. It seems low, because I'm always running
out in my gnome-keyring. But we need to quantify usage.

‎To take this forward, I will need to get educated:

     * How large is a page? Is it constant? Is it different on 64-bit
       kernels?
It's usually constant, but not sure across architectures. Would need
some research online or by testing it yourself. You can use the
getpagesize() + tiny C app to get the page size.

     * What's a typical size of an app's use?
Most apps don't use any. gnome-keyring-daemon uses it for all secrets,
and hooks up libgcrypt to the non-pageable memory so that it's crypto
algorithms are done in such memory.

I think one important thing for us to do would be to modify our
allocator (egg/egg-secure-memory.c) to have a short name associated with
each allocation. On receipt of a signal, the daemon could dump this
information to the logs and we could see the usage of non-pageable clearly.

Having such hard data is very important when asking downstream to be
accommodating with such subjective configuration changes.

I've seen other projects do this by having a macro which defines a
custom wrapper allocator function which always calls the real allocator
with a certain string, the name of the allocation.

     * Can apps share pages? Is there a security issue with sharing?
Well I don't think it's possible at all for two applications to share
non-pageable memory. It's certainly not the default. Each app has it's
own amount of non-pageable memory (usually same for each app, I guess).

     * What determines the ulimit? I suppose it's a kernel parameter that
       can be set by the distro.
On my machine it looks like it has something to do with
/etc/security/limits.conf + defaults.

     * What do we do when we overflow the ulimit? Do we inform the app?
We write something to the logs. You can test this by writing

     * Who are other users of non-pageable memory?
Gnupg maybe?

     * What is the downside: do all these pages have to be preallocated
       (and so go to waste), or is there a way to block waiting for
       memory to become available, allocate and use it and eventually
       release it?
I think the downside is that memory allocated like this can't be swapped
(paged) out. So if the system is low on memory, then having apps locking
up physical RAM is a liability. Our allocator allocates generally
allocates in 16K chunks and tries to free those chunks, but
fragmentation may prevent stuff from being freed.

     * Is there a way to exempt a specific application from the limit?
Not sure. If this is possible this would be an awesome solution to the
problem.

     * Who do we want to fight with? Ubuntu, Red Hat? Maybe start with
       Gentoo who are more serious on security?
Could be, but I would do it on a distro that I was familiar with. If
you're familiar with all of the above

I'd appreciate a few answers or pointers to where I can research it.
I hope that was helpful. If not clear, shout out. Asking on ubuntu or
gnome's IRC may give you more hints. There are probably some Fedora guys
who know this stuff inside and out.

Of course everyone has different expectations to security. So you may
get some "why are you doing that" questions, heh :)

Cheers,

Stef
#include <stdio.h>
#include <stdlib.h>
#include <sys/mman.h>

int main(int ac, char **av) {
	int pg = 1024;
	
	char *p = malloc(512*pg); // allocate half a meg
	if (p==NULL) {
		printf("malloc failed\n");
		exit(1);
	}
	
	p += pg;
	p = (char *)(((int) p) &~(pg-1)); // round up to next page
	
	int lockpages = 100;
	int ret = mlock(p, lockpages*pg);
	
	if (ret == -1) {
		perror("mlock failed");
		exit(1);
	} else {
		printf("mlock successful\n");
	}
	
	exit(0);
}
	


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]