SE-PostgreSQL Specifications
Here is the initial draft of SE-PostgreSQL specifications:
http://wiki.postgresql.org/wiki/SEPostgreSQL_Draft
I've described it from the scratch again with paying attention
for the people knowing nothing about SELinux.
In some points, it uses comparison between the database privilege
mechanism and SE-PostgreSQL for easy understanding.
Please point out, if ...
- Its composition can be improved.
- Here is not enough introductions for what user wants to know.
- Here is too much explanations, more brief one will be available.
- Here is not easy understandable for database folks.
- Here is not enough English quality.
- And so on...
In addition, I would like to fix its specifications during the discussion.
Thanks,
--
OSS Platform Development Division, NEC
KaiGai Kohei <kaigai@ak.jp.nec.com>
Excellent ... I'll try to have something tomorrow (Friday PDT) but I've got some non-work related issues which may keep from giving this a good look until the weekend (FWIW). I'll post any questions I have.
Thanks,
Greg W.
----- Original Message ----
From: KaiGai Kohei <kaigai@ak.jp.nec.com>
To: Robert Haas <robertmhaas@gmail.com>
Cc: pgsql-hackers@postgresql.org; KaiGai Kohei <kaigai@kaigai.gr.jp>; Greg Williamson <gwilliamson39@yahoo.com>; Sam Mason <sam@samason.me.uk>; Joshua Brindle <method@manicmethod.com>
Sent: Thursday, July 23, 2009 9:54:10 PM
Subject: SE-PostgreSQL Specifications
Here is the initial draft of SE-PostgreSQL specifications:
http://wiki.postgresql.org/wiki/SEPostgreSQL_Draft
I've described it from the scratch again with paying attention
for the people knowing nothing about SELinux.
In some points, it uses comparison between the database privilege
mechanism and SE-PostgreSQL for easy understanding.
Please point out, if ...
- Its composition can be improved.
- Here is not enough introductions for what user wants to know.
- Here is too much explanations, more brief one will be available.
- Here is not easy understandable for database folks.
- Here is not enough English quality.
- And so on...
In addition, I would like to fix its specifications during the discussion.
Thanks,
--
OSS Platform Development Division, NEC
KaiGai Kohei <kaigai@ak.jp.nec.com>
On Fri, Jul 24, 2009 at 01:07:54AM -0700, Greg Williamson wrote:
Here is the initial draft of SE-PostgreSQL specifications:
Hey, this is really cool. Think it is a nice introduction. Fixed some
of the really obvious language stuff and an example but the English is
quite good.
One thing I know people are going to ask: why did you use names like
"create" and "delete" and not the usual names that postgresql itself
uses. I suspect the answer is because that's the standard naming used
in SELinux, but I think you need to spell that out somewhere.
The same for the db_* convention. Do you have a reference to naming
conventions for SELinux permissions?
I need to think it over some more, but it's a really good start.
Have a nice day,
--
Martijn van Oosterhout <kleptog@svana.org> http://svana.org/kleptog/
Show quoted text
Please line up in a tree and maintain the heap invariant while
boarding. Thank you for flying nlogn airlines.
Martijn van Oosterhout wrote:
On Fri, Jul 24, 2009 at 01:07:54AM -0700, Greg Williamson wrote:
Here is the initial draft of SE-PostgreSQL specifications:
Hey, this is really cool. Think it is a nice introduction. Fixed some
of the really obvious language stuff and an example but the English is
quite good.
Thanks, but I found an incorrect change at the trusted procedure section.
Old)
CREATE TABLE customer (
cid integer primary key,
cname varchar(32),
credit varchar(32)
- SECURITY_LABEL = 'system_u:object_r:sepgsql_secret_table_t:s0'
- );
New)
CREATE TABLE customer (
cid integer primary key,
cname varchar(32),
credit varchar(32)
+ ) SECURITY_LABEL = 'system_u:object_r:sepgsql_secret_table_t:s0';
This example intends to assign "secret" label on the credit column,
not whole of the table. Note that the default security context shall
be assigned on the table and rest of columns in this case.
| For example, when the customer table is defined as follows,
| unprivileged users cannot see the contents of customer.credit
| because it is labeled as sepgsql_secret_table_t which means
| all the accesses are denied from confined domains.
Is the description inadequate to note the example tries to assign
a certain security context on the customer.credit column?
BTW, in the later case, the table is labeled as "secret", then columns
inherit table's security context in the default, so the table and all
the columns are labeled as "secret".
One thing I know people are going to ask: why did you use names like
"create" and "delete" and not the usual names that postgresql itself
uses. I suspect the answer is because that's the standard naming used
in SELinux, but I think you need to spell that out somewhere.The same for the db_* convention. Do you have a reference to naming
conventions for SELinux permissions?
http://oss.tresys.com/repos/refpolicy/trunk/policy/flask/access_vectors
All the object classes managed in userspace object manager have its prefix.
For example, X-window objects has x_* prefix.
Kenel objects don't have any prefix, such as "file".
Referring the other base object classes, it uses "create", "getattr",
"setattr", "relabelfrom" and "relabelto" commonly. However, a permission
to remove the object itself is named reflecting to the characteristics of
the object.
For example, file:{unlink} and ipc:{destroy} mean a permission to remove
itself. I believe "drop" is an appropriate naming for database objects.
TODO: add description at the "Object classes and permissions" why object
classes are prefixed by db_*
I need to think it over some more, but it's a really good start.
Have a nice day,
--
KaiGai Kohei <kaigai@kaigai.gr.jp>
KaiGai,
* KaiGai Kohei (kaigai@ak.jp.nec.com) wrote:
Here is the initial draft of SE-PostgreSQL specifications:
Thanks for this, it really does help, I believe. I've been reviewing it
and am also planning on helping refine and improve upon it. I'd like to
spend time working on the patch as well but I'm hesitant to commit to
that right now due to other obligations. We'll see how it goes.
Thanks again,
Stephen
On Fri, Jul 24, 2009 at 6:35 PM, Stephen Frost<sfrost@snowman.net> wrote:
Thanks for this, it really does help, I believe. I've been reviewing it
and am also planning on helping refine and improve upon it. I'd like to
spend time working on the patch as well but I'm hesitant to commit to
that right now due to other obligations. We'll see how it goes.
At this point, I think refining and improving the spec is probably
considerably more important than writing the code.
...Robert
On Sat, Jul 25, 2009 at 07:23:22AM +0900, KaiGai Kohei wrote:
Thanks, but I found an incorrect change at the trusted procedure section.
Old)
CREATE TABLE customer (
cid integer primary key,
cname varchar(32),
credit varchar(32)
- SECURITY_LABEL = 'system_u:object_r:sepgsql_secret_table_t:s0'
- );New)
CREATE TABLE customer (
cid integer primary key,
cname varchar(32),
credit varchar(32)
+ ) SECURITY_LABEL = 'system_u:object_r:sepgsql_secret_table_t:s0';This example intends to assign "secret" label on the credit column,
not whole of the table. Note that the default security context shall
be assigned on the table and rest of columns in this case.
The show_credit() function in this section would seem to leak authority
as well; it seems possible to determine if customers exist that
otherwise may otherwise hidden. For example, imagine we have a row
in the customer table with cid=1 whose security label would normally
prevent. We can perform:
SELECT show_credit(1);
and, as far as I can tell, this call would succeed.
--
Sam http://samason.me.uk/
Sam Mason wrote:
On Sat, Jul 25, 2009 at 07:23:22AM +0900, KaiGai Kohei wrote:
Thanks, but I found an incorrect change at the trusted procedure section.
Old)
CREATE TABLE customer (
cid integer primary key,
cname varchar(32),
credit varchar(32)
- SECURITY_LABEL = 'system_u:object_r:sepgsql_secret_table_t:s0'
- );New)
CREATE TABLE customer (
cid integer primary key,
cname varchar(32),
credit varchar(32)
+ ) SECURITY_LABEL = 'system_u:object_r:sepgsql_secret_table_t:s0';This example intends to assign "secret" label on the credit column,
not whole of the table. Note that the default security context shall
be assigned on the table and rest of columns in this case.The show_credit() function in this section would seem to leak authority
as well; it seems possible to determine if customers exist that
otherwise may otherwise hidden. For example, imagine we have a row
in the customer table with cid=1 whose security label would normally
prevent. We can perform:SELECT show_credit(1);
and, as far as I can tell, this call would succeed.
This example shows that confined client cannot read credit card number
without using trusted procedure, but trusted procedure returns masked one.
It does not intend to hide existence of entries within customer table.
See the third box in the section.
postgres=# SELECT cid, cname FROM customer;
cid | cname
-----+-------
10 | jack
13 | adam
14 | liza
(3 rows)
This query does not read from customer.credit, so it should be succeeded.
Thanks,
--
KaiGai Kohei <kaigai@kaigai.gr.jp>
On Sat, Jul 25, 2009 at 09:16:47AM +0900, KaiGai Kohei wrote:
Sam Mason wrote:
The show_credit() function in this section would seem to leak authority
as well; it seems possible to determine if customers exist that
otherwise may otherwise hidden. For example, imagine we have a row
in the customer table with cid=1 whose security label would normally
prevent. We can perform:SELECT show_credit(1);
and, as far as I can tell, this call would succeed.
This example shows that confined client cannot read credit card number
without using trusted procedure, but trusted procedure returns masked one.
It does not intend to hide existence of entries within customer table.
This would seem to imply that all user defined trusted code has to
perform its own permission checks. How is MAC any different from DAC in
the presence of code such as:
CREATE OR REPLACE FUNCTION show_customers () RETURNS SETOF RECORD
LANGUAGE 'sql'
SECURITY_LABEL = 'system_u:object_r:sepgsql_trusted_proc_exec_t:s0'
AS 'SELECT * FROM customer';
(I hope I've modified the example correctly!)
--
Sam http://samason.me.uk/
Sam Mason wrote:
On Sat, Jul 25, 2009 at 09:16:47AM +0900, KaiGai Kohei wrote:
Sam Mason wrote:
The show_credit() function in this section would seem to leak authority
as well; it seems possible to determine if customers exist that
otherwise may otherwise hidden. For example, imagine we have a row
in the customer table with cid=1 whose security label would normally
prevent. We can perform:SELECT show_credit(1);
and, as far as I can tell, this call would succeed.
This example shows that confined client cannot read credit card number
without using trusted procedure, but trusted procedure returns masked one.
It does not intend to hide existence of entries within customer table.This would seem to imply that all user defined trusted code has to
perform its own permission checks. How is MAC any different from DAC in
the presence of code such as:CREATE OR REPLACE FUNCTION show_customers () RETURNS SETOF RECORD
LANGUAGE 'sql'
SECURITY_LABEL = 'system_u:object_r:sepgsql_trusted_proc_exec_t:s0'
AS 'SELECT * FROM customer';(I hope I've modified the example correctly!)
In this case, confined users cannot create a function labeled as
'system_u:object_r:sepgsql_trusted_proc_exec_t:s0', because it is
controlled by db_procedure:{create} permission.
Confined user can create a function with "user_sepgsql_proc_exec_t"
(which is the default one for confined users), but it is not a trusted procedure,
so the "SELECT * FROM customer" is executed with confined user's privileges as is,
then it will be failed due to the lack of permission on the customer.credit.
Thanks,
--
KaiGai Kohei <kaigai@kaigai.gr.jp>
On Sat, Jul 25, 2009 at 10:43:05AM +0900, KaiGai Kohei wrote:
Sam Mason wrote:
This would seem to imply that all user defined trusted code has to
perform its own permission checks. How is MAC any different from DAC in
the presence of code such as:CREATE OR REPLACE FUNCTION show_customers () RETURNS SETOF RECORD
LANGUAGE 'sql'
SECURITY_LABEL = 'system_u:object_r:sepgsql_trusted_proc_exec_t:s0'
AS 'SELECT * FROM customer';In this case, confined users cannot create a function labeled as
'system_u:object_r:sepgsql_trusted_proc_exec_t:s0', because it is
controlled by db_procedure:{create} permission.
Yes, that seems reasonable. The fact that you're still talking about
"confined users" is slightly worrying and would seem to imply that
there is still a superuser/normal user divide--it's probably just a
terminology thing though.
One thing I know I don't understand is what the security labels actually
mean; I've had a couple of searches through your pages now and can't see
anything described nor pointers to external documentation.
Confined user can create a function with "user_sepgsql_proc_exec_t"
(which is the default one for confined users), but it is not a trusted
procedure, so the "SELECT * FROM customer" is executed with confined
user's privileges as is, then it will be failed due to the lack of
permission on the customer.credit.
So an "unconfined user" (whatever that means??) is basically working
with DACs then?
--
Sam http://samason.me.uk/
Sam Mason wrote:
On Sat, Jul 25, 2009 at 10:43:05AM +0900, KaiGai Kohei wrote:
Sam Mason wrote:
This would seem to imply that all user defined trusted code has to
perform its own permission checks. How is MAC any different from DAC in
the presence of code such as:CREATE OR REPLACE FUNCTION show_customers () RETURNS SETOF RECORD
LANGUAGE 'sql'
SECURITY_LABEL = 'system_u:object_r:sepgsql_trusted_proc_exec_t:s0'
AS 'SELECT * FROM customer';In this case, confined users cannot create a function labeled as
'system_u:object_r:sepgsql_trusted_proc_exec_t:s0', because it is
controlled by db_procedure:{create} permission.Yes, that seems reasonable. The fact that you're still talking about
"confined users" is slightly worrying and would seem to imply that
there is still a superuser/normal user divide--it's probably just a
terminology thing though.One thing I know I don't understand is what the security labels actually
mean; I've had a couple of searches through your pages now and can't see
anything described nor pointers to external documentation.
I assume the wikipage (SEPostgreSQL_Draft) is a draft for the PostgreSQL
official documentation. However, the list of security labels originates
from the default security policy in SELinux.
So, I think an external link will be preferable for the references.
TODO: I'll make the list of security labels we can assign on.
Confined user can create a function with "user_sepgsql_proc_exec_t"
(which is the default one for confined users), but it is not a trusted
procedure, so the "SELECT * FROM customer" is executed with confined
user's privileges as is, then it will be failed due to the lack of
permission on the customer.credit.So an "unconfined user" (whatever that means??) is basically working
with DACs then?
Sorry for using the undefined terminology.
The default security policy provides several security contexts that we
can assign on user's shell process, such as user_t, staff_t and unconfined_t.
(Please note that the security context of processes means its privileges.)
SELinux checks privileges of processes without any exceptions.
However, the default security policy allows anything on unconfined_t label.
It means "unconfined" users are allowed anything according to the policy.
(BTW, we can unplug the "unconfined" label using modular policy stuff.)
On the other hand, rest of security context (user_t, staff_t or httpd_t for
web servers) are "confined", because the security policy does not allow
such widespread permissions.
Thanks,
--
KaiGai Kohei <kaigai@kaigai.gr.jp>
Sam Mason <sam@samason.me.uk> writes:
Yes, that seems reasonable. The fact that you're still talking about
"confined users" is slightly worrying and would seem to imply that
there is still a superuser/normal user divide--it's probably just a
terminology thing though.
There had better still be superusers. Or do you want the correctness
of your backups to depend on whether your SELinux policy is correct?
The first time somebody loses critical data because SELinux suppressed
it from their pg_dump output, they're going to be on the warpath.
regards, tom lane
On Jul 25, 2009, at 11:06 AM, Tom Lane wrote:
Sam Mason <sam@samason.me.uk> writes:
Yes, that seems reasonable. The fact that you're still talking about
"confined users" is slightly worrying and would seem to imply that
there is still a superuser/normal user divide--it's probably just a
terminology thing though.There had better still be superusers. Or do you want the correctness
of your backups to depend on whether your SELinux policy is correct?
The first time somebody loses critical data because SELinux suppressed
it from their pg_dump output, they're going to be on the warpath.
This behavior is no different than when taking/using an SE-enabled
filesystem backup. And woe to the "admin" who doesn't test his
backups- caveat emptor.
Still, it would be nice if pg_dump warned or stopped if the backup it
created was completely useless (missing data dependencies), no?
Cheers,
M
On Sat, Jul 25, 2009 at 09:50:08PM +0900, KaiGai Kohei wrote:
Sorry for using the undefined terminology.
I think this is the largest missing part of the docs at the moment;
there is a whole new world of definitions that need to be understood
before the SE-PG stuff is understandable/usable by anyone and none of it
is explained in a way I can understand. External links are fine at the
moment (I think) but descriptions will need to exist.
For example you currently define a "security context" as "a formatted
short string"---how does that tell me why I would want one or what it
does! As an example, PG currently has the following to describe what a
"role" is:
http://www.postgresql.org/docs/current/static/database-roles.html
I'd expect a similar definition for each of the major terms in SE-PG;
at the moment these seem to be "security label", "security context",
"security policy" and others? What do others think?
Hope that helps explain my confusion! If you point me at some docs I'll
be happy to write/edit things to make them more relevant to PG.
--
Sam http://samason.me.uk/
On Sat, Jul 25, 2009 at 11:06:37AM -0400, Tom Lane wrote:
There had better still be superusers. Or do you want the correctness
of your backups to depend on whether your SELinux policy is correct?
I thought the whole point of MAC was that superusers don't exist any
more--at least not with the power they currently do. Organizations may
well not trust specific parts of their database to certain types of
backups, SE-PG should allow this to be controlled somewhat.
The first time somebody loses critical data because SELinux suppressed
it from their pg_dump output, they're going to be on the warpath.
That should be solved by different methods; as "A.M" said pg_dump can
complain if it doesn't see everything it expected to (which should
handle the naive user case) and backdoors can be put in the scheme
that will (by default?) initially allow a "backup" subject unfettered
read-only access to each object. I'm expecting that this access can be
revoked as needed from sensitive tables.
--
Sam http://samason.me.uk/
On Sat, Jul 25, 2009 at 4:27 PM, Sam Mason<sam@samason.me.uk> wrote:
On Sat, Jul 25, 2009 at 11:06:37AM -0400, Tom Lane wrote:
There had better still be superusers. Or do you want the correctness
of your backups to depend on whether your SELinux policy is correct?I thought the whole point of MAC was that superusers don't exist any
more--at least not with the power they currently do.
It's been billed that way, but it's not really accurate. A more
accurate statement would be that it's possible to create a system in
which there is no unconfined role.
Organizations may
well not trust specific parts of their database to certain types of
backups, SE-PG should allow this to be controlled somewhat.
I imagine it would be possible to run pg_dump on a database where you
couldn't see all of the objects, and get a dump of just those, but
that's only tangentially related to whether such things as superusers
exist. If superusers DON'T exist, that would be making the opposite
statement, namely, that there isn't ANY WAY to get a backup that you
can be sure DOES contain all of the objects. And while I believe
SE-Linux/SE-PostgreSQL would allow you to configure such a system, you
might want to think carefully before you decide to do so, and the
system certainly shouldn't (and can't) force you to set it up that
way.
The first time somebody loses critical data because SELinux suppressed
it from their pg_dump output, they're going to be on the warpath.That should be solved by different methods; as "A.M" said pg_dump can
complain if it doesn't see everything it expected to (which should
handle the naive user case) and backdoors can be put in the scheme
that will (by default?) initially allow a "backup" subject unfettered
read-only access to each object. I'm expecting that this access can be
revoked as needed from sensitive tables.
If pg_dump can tell that there is information missing, the system
hasn't done a very good job of hiding its existence, which is surely
the whole point here. Even if SE-PostgreSQL isn't explicitly worried
about eliminating covert channels, it seems like a terrible idea to
design a database backup tool that operates by exploiting ones we
haven't chosen to eliminate.
...Robert
On Sat, Jul 25, 2009 at 04:39:29PM -0400, Robert Haas wrote:
On Sat, Jul 25, 2009 at 4:27 PM, Sam Mason<sam@samason.me.uk> wrote:
I thought the whole point of MAC was that superusers don't exist any
more--at least not with the power they currently do.It's been billed that way, but it's not really accurate. A more
accurate statement would be that it's possible to create a system in
which there is no unconfined role.
Yes, that sounds more precise!
I'm still unsure of terminology; what's a "unconfined role"? I guess
the layman's description is similar to a "superuser", but I'm sure
there's a more refined definition somewhere. Hum, I've just found
Fedora's guide, is the following considered a reasonable picture:
Organizations may
well not trust specific parts of their database to certain types of
backups, SE-PG should allow this to be controlled somewhat.I imagine it would be possible to run pg_dump on a database where you
couldn't see all of the objects, and get a dump of just those, but
that's only tangentially related to whether such things as superusers
exist.
I'm not sure what point you're trying to make; in my understanding
superusers can see and do anything--hence they can make a backup.
If superusers DON'T exist, that would be making the opposite
statement, namely, that there isn't ANY WAY to get a backup that you
can be sure DOES contain all of the objects.
The traditional approach would be to maintain multiple physically
separate databases; in this setup it's obvious that when you perform a
backup of one of these databases you're only seeing a subset of "all of
the objects". Isn't SE-PG just allowing you to do this within a single
PG database?
And while I believe
SE-Linux/SE-PostgreSQL would allow you to configure such a system, you
might want to think carefully before you decide to do so, and the
system certainly shouldn't (and can't) force you to set it up that
way.
I agree that this would seem to make the resulting system easier to
manage, however I can also imagine scenarios where the converse would
be true. This is a fuzzy engineering decision of the sort that I don't
like making without a use case---and it would be nice to have several
here.
pg_dump can complain if it doesn't see everything it expected to
If pg_dump can tell that there is information missing, the system
hasn't done a very good job of hiding its existence, which is surely
the whole point here.
Hum, good point--scratch that idea then!
--
Sam http://samason.me.uk/
Sam Mason wrote:
On Sat, Jul 25, 2009 at 09:50:08PM +0900, KaiGai Kohei wrote:
Sorry for using the undefined terminology.
I think this is the largest missing part of the docs at the moment;
there is a whole new world of definitions that need to be understood
before the SE-PG stuff is understandable/usable by anyone and none of it
is explained in a way I can understand. External links are fine at the
moment (I think) but descriptions will need to exist.For example you currently define a "security context" as "a formatted
short string"---how does that tell me why I would want one or what it
does! As an example, PG currently has the following to describe what a
"role" is:http://www.postgresql.org/docs/current/static/database-roles.html
Indeed, the draft used the term of "security context" with minimum
introductions, but not enough friendliness for database folks.
The purpose of security context is an identifier of any subject and
object to describe them in the security policy. Because the security
policy is common for operating system, databases, x-window and others,
any managed database objects needs its security context.
Anyway, I need to introduce them in the security model section.
I'd expect a similar definition for each of the major terms in SE-PG;
at the moment these seem to be "security label", "security context",
"security policy" and others? What do others think?
The "security label" is an identical one with "security context".
Due to the historical reason, I uses a term of "SECURITY_LABEL" for
interfaces, but it might be more easy understandable to use
"SECURITY_CONTEXT" instead.
For the security policy, I introduce it at the security model section:
| Access control is conceptually to decide a set of allowed (or denied)
| actions between a certain subject (such as a database client) and an
| object (such as a table), and to apply the decision on user's requests.
| At the database privilege system, ACL stored in database objects itself
| holds a list of allowed actions to certain database roles, and it is
| applied on the user's request.
| SELinux also holds massive sets of allowed actions between a certain
| subject and a certain object, we call them security policy.
Is it obscure?
In addition, I also think it needs to define some other terms explicitly.
For example, what the term of "labeled" means.
Hope that helps explain my confusion! If you point me at some docs I'll
be happy to write/edit things to make them more relevant to PG.
At this point, the SELinux user's guide in Fedora is the most comprehensive
documentation. It is described from the viewpoint of SELinux users, not
experts or developers.
http://docs.fedoraproject.org/selinux-user-guide/
Thanks,
--
KaiGai Kohei <kaigai@kaigai.gr.jp>
On Sat, Jul 25, 2009 at 11:27 PM, KaiGai Kohei<kaigai@kaigai.gr.jp> wrote:
| Access control is conceptually to decide a set of allowed (or denied)
| actions between a certain subject (such as a database client) and an
| object (such as a table), and to apply the decision on user's requests.
| At the database privilege system, ACL stored in database objects itself
| holds a list of allowed actions to certain database roles, and it is
| applied on the user's request.
| SELinux also holds massive sets of allowed actions between a certain
| subject and a certain object, we call them security policy.Is it obscure?
It's obscure to me. :-)
I think you need to define security policy more precisely and give at
least one or two examples of security policy entries.
...Robert