memcached with access controls

25 views
Skip to first unread message

KaiGai Kohei

unread,
Jul 21, 2010, 5:03:11 AM7/21/10
to Trond Norbye, Dustin Sallings, Toru Maesaka, Memcached, KaiGai Kohei
Sorry for the late.

I tried to implement an engine module which also provides access control
feature based on SELinux. Right now, it does not have any design problems
and works fine.

At the first, I had a plan that selinux_engine.so provides only access
control features, so any actual key/value stores are pushed to any other
engine modules like the bucket system.
However, it was a hard way because here is no guarantee an item which
contains security label in text representation being never wiped out.
So, I also implement its own storage engine that enables to associate
a security label for each items.

Step to use:
(we assume engine based memcached is installed at: /usr/local/memcached )

% svn co http://sepgsql.googlecode.com/svn/trunk/memcached selinux-engine
% cd selinux-engine
% make && make install

% /usr/local/memcached/bin/memcached -E selinux_engine.so \
-s /tmp/memcached.sock

Example of usage:

[kaigai@saba ~]$ runcon -l s0 mcdclient.php add abc 'hello world' unix:///tmp/memcached.sock
success to add [key:abc, value:hello world]
[kaigai@saba ~]$ runcon -l s0:c0 -- mcdclient.php add xyz 'i like curry' unix:///tmp/memcached.sock
success to add [key:xyz, value:i like curry]
[kaigai@saba ~]$ runcon -l s0:c1 -- mcdclient.php add zzz 'i like coke' unix:///tmp/memcached.sock
success to add [key:zzz, value:i like coke]

(*) runcon allows to launch a program with more restrict privileges.
In this case, default label of the item is same as client's label.

[kaigai@saba ~]$ runcon -l s0 -- mcdclient.php get abc unix:///tmp/memcached.sock
'abc' => 'hello world'
[kaigai@saba ~]$ runcon -l s0 -- mcdclient.php get xyz unix:///tmp/memcached.sock
no entry for 'xyz'
[kaigai@saba ~]$ runcon -l s0 -- mcdclient.php get zzz unix:///tmp/memcached.sock
no entry for 'zzz'

The 's0' domain dominates 's0', but not both of 's0:c0' and 's0:c1', so 'xyz' and 'zzz'
are invisible.

The debug log also shows:
uavc: denied { read } for scontext=unconfined_u:unconfined_r:unconfined_t:s0 \
tcontext=unconfined_u:object_r:sepgsql_blob_t:s0:c0 tclass=db_blob

[kaigai@saba ~]$ runcon -l s0:c0 -- mcdclient.php get abc unix:///tmp/memcached.sock
'abc' => 'hello world'
[kaigai@saba ~]$ runcon -l s0:c0 -- mcdclient.php get xyz unix:///tmp/memcached.sock
'xyz' => 'i like curry'
[kaigai@saba ~]$ runcon -l s0:c0 -- mcdclient.php get zzz unix:///tmp/memcached.sock
no entry for 'zzz'

The 's0:c0' domain dominates 's0' and 's0:c0', but not 's0:c1', so 'zzz' is invisible.

[kaigai@saba ~]$ runcon -l s0:c1 -- mcdclient.php get abc unix:///tmp/memcached.sock
'abc' => 'hello world'
[kaigai@saba ~]$ runcon -l s0:c1 -- mcdclient.php get xyz unix:///tmp/memcached.sock
no entry for 'xyz'
[kaigai@saba ~]$ runcon -l s0:c1 -- mcdclient.php get zzz unix:///tmp/memcached.sock
'zzz' => 'i like coke'

The 's0:c1' domain dominates 's0' and 's0:c1', but not 's0:c0', so 'xyz' is invisible.

Thanks,
--
KaiGai Kohei <kai...@ak.jp.nec.com>

KaiGai Kohei

unread,
Jul 21, 2010, 8:38:28 PM7/21/10
to Trond Norbye, memc...@googlegroups.com, Dustin Sallings, Toru Maesaka, KaiGai Kohei
BTW, I have noticed a few symbols are not available unexpectedly when
I've been under development.

1. create_instance() of the default_engine.c is not available, even if
--enable-default-engine was provided.
2. safe_strtoull() of the util.c is not available from the engine module.

It seems to me lack of the -rdynamic option drops these unreferenced
symbols (at the build time) from the binary.

The gcc man page says as follows:
| -rdynamic
| Pass the flag -export-dynamic to the ELF linker, on targets that
| support it. This instructs the linker to add all symbols, not only
| used ones, to the dynamic symbol table. This option is needed
| for some uses of "dlopen" or to allow obtaining backtraces from
| within a program.
and
| -dynamic
| These options are passed to the Darwin linker. The Darwin linker
| man page describes them in detail.

How about the attached patch?

And, I have a question. Do we have an explicit release schedule of
the memcached with engine interfaces?

Thanks,

(2010/07/21 18:03), KaiGai Kohei wrote:
> Sorry for the late.
>
> I tried to implement an engine module which also provides access control
> feature based on SELinux. Right now, it does not have any design problems
> and works fine.
>
> At the first, I had a plan that selinux_engine.so provides only access
> control features, so any actual key/value stores are pushed to any other
> engine modules like the bucket system.
> However, it was a hard way because here is no guarantee an item which
> contains security label in text representation being never wiped out.
> So, I also implement its own storage engine that enables to associate
> a security label for each items.
>
> Step to use:
> (we assume engine based memcached is installed at: /usr/local/memcached )
>
> % svn co http://sepgsql.googlecode.com/svn/trunk/memcached selinux-engine
> % cd selinux-engine

> % make&& make install

memcached-add-rdynamic.patch

KaiGai Kohei

unread,
Jul 22, 2010, 12:51:06 AM7/22/10
to SELinux ML, memc...@googlegroups.com, Trond Norbye, Dustin Sallings, Toru Maesaka, KaiGai Kohei
SELinux folks,

I had a series of discussion with memcached developers.

Memcached is one of the most widely used key-value-store. Nowadays, it is
not out of common to utilize memcached to boost web-app's performance.
However, we have unignorable problem from the perspective of system security.
It does not provide any access control features, although it allows two
different domains to communicate each other through KVS, because it assumes
only trusted users and softwares can connect to the memcached server.
(Yes, it is correct as long as all the clients being trusted.)

As you may know, I've been working on web-application's security with
LAPP/SELinux stack[1] for a few years. Our assumption is web-applications
are NOT bug-free, so it may be abused by malicious attackers.
Thus, I motivated to run web-application with more restricted privileges
based on centralized, fine-grained and mandatory access control policy.

While the discussion thread, I was informed that the upcoming memcached
will support a set of interfaces for loadable modules, just called "engine".
It allows to override the default storage engine which manages key/value
pairs on the memory. It also means we can apply access controls when it
tries to access a certain key/value pair within engine modules.

Then, I tries to implement a proof-of-concept module:
http://sepgsql.googlecode.com/svn/trunk/memcached/
(*) Also see, step to execute [2] below.

Because selinux-policy does not have definitions for key/value pairs now,
it *abuses* the db_blob object class. So, we need to has a discussion what
permissions are necessary to control key/value store. Perhaps, its concept
should be extendable for any other KVS, rather than memcached.

As a draft, I'd like to propose the following set of permissions.

* kvs_item class
- create ... shall be checked when we try to create a new items.
- unlink ... shall be checked when we try to unlink an existing items.
- getattr ... shall be checked when we try to get properties of items.
(but operations are not defined yet)
- setattr ... shall be checked when we try to set properties of items.
(but operations are not defined yet)
- relabelfrom
- relabelto ... shall be checked when we try to relabel items.
- read ... shall be checked when we try to read contents of items.
- write ... shall be checked when we try to update contents of items.
- append ... shall be checked when we try to append/prepend something
on tail/head of existing items. In this case, the contents
of existing item shall be maintained, unlike 'write'.
- arithmetic ... shall be checked when we try to add/sub a certain value
to/from the contents of items, and return the result.
(Perhaps, it is equivalent to combination of read and write)
- flush ... shall be checked when we try to execute 'flush' command
which unlinks all (of expired) items.
It shall be checked on memcached server process, rather
than individual items.

- default security context
Any item does not have its parent object, so we need to decide the way to
determine the base context. I think here is two ideas, and my preference
is the later one.
1. using security context of the memcached process
2. using selabel_lookup() facility to set up base context of the memcached.

Please any comments,

Thanks,


* memcached and access control
http://groups.google.com/group/memcached/browse_frm/thread/69560cb93240a3cc
* A few ideas of engine framework
http://groups.google.com/group/memcached/browse_frm/thread/cddf18ce141312f1
* memcached with access controls
http://groups.google.com/group/memcached/browse_frm/thread/fecb589d945278c9

[1] LAPP/SELinux
http://sepgsql.googlecode.com/files/PGcon2010-KaiGai-LAPP_SELinux.pdf

[2] Step to execute
-------------------
2-1) build memcached
$ git clone git://github.com/trondn/memcached.git -b engine
$ cd memcached
$ ./config/autorun.sh
$ ./configure --prefix=/usr/local/memcached
$ make && make install
$ cd ..
2-2) build selinux_engine.so module
$ svn co http://sepgsql.googlecode.com/svn/trunk/memcached/ selinux_engine
$ cd selinux_engine
$ make && make install
$ cd ..
2-3) start memcached daemon
$ /usr/local/memcached/bin/memcached -E selinux_engine.so -s /tmp/memcached.sock

2-4) example of memcached with selinux
$ runcon -l s0 -- mcdclient.php add key_x 'this is public info' unix:///tmp/memcached.sock
success to add [key:key_x, value:this is public info]
$ runcon -l s0:c0 -- mcdclient.php add key_y 'this is private info' unix:///tmp/memcached.sock
success to add [key:key_y, value:this is private info]

-> key_x has 's0', and key_y has 's0:c0' in the default.

$ runcon -l s0 -- mcdclient.php get key_x unix:///tmp/memcached.sock
'key_x' => 'this is public info'
$ runcon -l s0 -- mcdclient.php get key_y unix:///tmp/memcached.sock
no entry for 'key_y'
^^^^^^^^^^^^^^^^^^^^ -> access violation, although error message is incorrect.
-> So, 's0' domain can reference key_x, but not key_y.

$ runcon -l s0:c0 -- mcdclient.php get key_x unix:///tmp/memcached.sock
'key_x' => 'this is public info'
$ runcon -l s0:c0 -- mcdclient.php get key_y unix:///tmp/memcached.sock
'key_y' => 'this is private info'

-> 's0:c0' domain can reference both key_x and key_y.

--
KaiGai Kohei <kai...@ak.jp.nec.com>

Trond Norbye

unread,
Jul 22, 2010, 4:09:08 AM7/22/10
to KaiGai Kohei, memc...@googlegroups.com, Dustin Sallings, Toru Maesaka, KaiGai Kohei
On 07/22/10 02:38 AM, KaiGai Kohei wrote:
> BTW, I have noticed a few symbols are not available unexpectedly when
> I've been under development.
>
> 1. create_instance() of the default_engine.c is not available, even if
> --enable-default-engine was provided.
> 2. safe_strtoull() of the util.c is not available from the engine module.
>
> It seems to me lack of the -rdynamic option drops these unreferenced
> symbols (at the build time) from the binary.
>
> The gcc man page says as follows:
> | -rdynamic
> | Pass the flag -export-dynamic to the ELF linker, on targets that
> | support it. This instructs the linker to add all symbols, not only
> | used ones, to the dynamic symbol table. This option is needed
> | for some uses of "dlopen" or to allow obtaining backtraces from
> | within a program.
> and
> | -dynamic
> | These options are passed to the Darwin linker. The Darwin linker
> | man page describes them in detail.
>
> How about the attached patch?
>
>

The patch failed to build on my Solaris machine (not using gcc), but I
just took a quick look in the libtool manual and pushed another fix for
the problem in rev 456a9afd5ae007b9b3f8679b89a16f16ffe01689


> And, I have a question. Do we have an explicit release schedule of
> the memcached with engine interfaces?
>
>

I'm currently working on cleaning up the builds on all of the platforms
we got builders for...

Cheers,

Trond

KaiGai Kohei

unread,
Jul 22, 2010, 9:35:00 AM7/22/10
to Trond Norbye, KaiGai Kohei, memc...@googlegroups.com, Dustin Sallings, Toru Maesaka
(2010/07/22 17:09), Trond Norbye wrote:
> On 07/22/10 02:38 AM, KaiGai Kohei wrote:
>> BTW, I have noticed a few symbols are not available unexpectedly when
>> I've been under development.
>>
>> 1. create_instance() of the default_engine.c is not available, even if
>> --enable-default-engine was provided.
>> 2. safe_strtoull() of the util.c is not available from the engine module.
>>
>> It seems to me lack of the -rdynamic option drops these unreferenced
>> symbols (at the build time) from the binary.
>>
>> The gcc man page says as follows:
>> | -rdynamic
>> | Pass the flag -export-dynamic to the ELF linker, on targets that
>> | support it. This instructs the linker to add all symbols, not only
>> | used ones, to the dynamic symbol table. This option is needed
>> | for some uses of "dlopen" or to allow obtaining backtraces from
>> | within a program.
>> and
>> | -dynamic
>> | These options are passed to the Darwin linker. The Darwin linker
>> | man page describes them in detail.
>>
>> How about the attached patch?
>>
>>
>
> The patch failed to build on my Solaris machine (not using gcc), but I
> just took a quick look in the libtool manual and pushed another fix for
> the problem in rev 456a9afd5ae007b9b3f8679b89a16f16ffe01689
>
It works for me, on the Fedora rawhide.

>> And, I have a question. Do we have an explicit release schedule of
>> the memcached with engine interfaces?
>
> I'm currently working on cleaning up the builds on all of the platforms
> we got builders for...
>

Thanks for your efforts.
--
KaiGai Kohei <kai...@kaigai.gr.jp>

Reply all
Reply to author
Forward
0 new messages