Thread: [v9.2] Object access hooks with arguments support (v1)

[v9.2] Object access hooks with arguments support (v1)

From
Kohei KaiGai
Date:
The attached patch is a draft to support arguments in addition to
OAT_* enum and object identifiers.

The existing object_access_hook enables loadable modules to acquire
control when objects are referenced. The first guest of this hook is
contrib/sepgsql for assignment of default security label on newly
created objects. Right now, OAT_POST_CREATE is the all supported
object access type. However, we plan to enhance this mechanism onto
other widespread purpose; such as comprehensive DDL permissions
supported by loadable modules.

This patch is a groundwork to utilize this hook for object creation
permission checks, not only default labeling.
At the v9.1 development cycle, I proposed an idea that defines both
OAT_CREATE hook prior to system catalog modification and
OAT_POST_CREATE hook as currently we have. This design enables to
check permission next to the existing pg_xxx_aclcheck() or
pg_xxx_ownercheck(), and raise an error before system catalog updates.
However, it was painful to deliver private datum set on OAT_CREATE to
the OAT_POST_CREATE due to the code complexity.

The other idea tried to do all the necessary things in OAT_POST_CREATE
hook, and it had been merged, because loadable modules can pull
properties of the new object from system catalogs by the supplied
object identifiers. Thus, contrib/sepgsql assigns a default security
label on new object using OAT_POST_CREATE hook.
However, I have two concern on the existing hook to implement
permission check for object creation. The first one is the entry of
system catalog is not visible using SnaphotNow, so we had to open and
scan system catalog again, instead of syscache mechanism. The second
one is more significant. A part of information to make access control
decision is not available within contents of the system catalog
entries. For example, we hope to skip permission check when
heap_create_with_catalog() was launched by make_new_heap() because the
new relation is just used to swap later.

Thus, I'd like to propose to support argument of object_access_hook to
inform the loadable modules additional contextual information on its
invocations; to solve these concerns.

Regarding to the first concern, fortunately, most of existing
OAT_POST_CREATE hook is deployed just after insert or update of system
catalogs, but before CCI. So, it is helpful for the loadable modules
to deliver Form_pg_xxxx data to reference properties of the new
object, instead of open and scan the catalog again.
In the draft patch, I enhanced OAT_POST_CREATE hook commonly to take
an argument that points to the Form_pg_xxxx data of the new object.

Regarding to the second concern, I added a few contextual information
as second or later arguments in a part of object classes. Right now, I
hope the following contextual information shall be provided to
OAT_POST_CREATE hook to implement permission checks of object
creation.

* pg_class - TupleDesc structure of the new relation
I want to reference of pg_attribute, not only pg_class.

* pg_class - A flag to show whether the relation is defined for
rebuilding, or not.
I want not to apply permission check in the case when it is invoked
from make_new_heap(), because it just create a dummy table as a part
of internal process. All the necessary permission checks should be
done at ALTER TABLE or CLUSTER.

* pg_class - A flag to show whether the relation is created with
SELECT INTO, or not.
I want to check "insert" permission of the new table, created by
SELECT INTO, because DML hook is not available to check this case.

* pg_type - A flag to show whether the type is defined as implicit
array, or not.
I want not to apply permission check on creation of implicit array type.

* pg_database - Oid of the source (template) database.
I want to fetch security label of the source database to compute a
default label of the new database.

* pg_trigger - A flag to show whether the trigger is used to FK
constraint, or not.
I want not to apply permission check on creation of FK constraint. It
should be done in ALTER TABLE level.

Sorry for this long explanation. Right now, I tend to consider it is
the best way to implement permission checks on object creation with
least invasive way.

Thanks, Any comments welcome.
--
KaiGai Kohei <kaigai@kaigai.gr.jp>

Attachment

Re: [v9.2] Object access hooks with arguments support (v1)

From
Kohei KaiGai
Date:
I noticed that the previous revision does not provide any way to inform
the modules name of foreign server, even if foreign table was created,
on the OAT_POST_CREATE hook.
So, I modified the invocation at heap_create_with_catalog to deliver
this information to the modules.

Rest of parts were unchanged, except for rebasing to the latest git
master.

2011/8/28 Kohei KaiGai <kaigai@kaigai.gr.jp>:
> The attached patch is a draft to support arguments in addition to
> OAT_* enum and object identifiers.
>
> The existing object_access_hook enables loadable modules to acquire
> control when objects are referenced. The first guest of this hook is
> contrib/sepgsql for assignment of default security label on newly
> created objects. Right now, OAT_POST_CREATE is the all supported
> object access type. However, we plan to enhance this mechanism onto
> other widespread purpose; such as comprehensive DDL permissions
> supported by loadable modules.
>
> This patch is a groundwork to utilize this hook for object creation
> permission checks, not only default labeling.
> At the v9.1 development cycle, I proposed an idea that defines both
> OAT_CREATE hook prior to system catalog modification and
> OAT_POST_CREATE hook as currently we have. This design enables to
> check permission next to the existing pg_xxx_aclcheck() or
> pg_xxx_ownercheck(), and raise an error before system catalog updates.
> However, it was painful to deliver private datum set on OAT_CREATE to
> the OAT_POST_CREATE due to the code complexity.
>
> The other idea tried to do all the necessary things in OAT_POST_CREATE
> hook, and it had been merged, because loadable modules can pull
> properties of the new object from system catalogs by the supplied
> object identifiers. Thus, contrib/sepgsql assigns a default security
> label on new object using OAT_POST_CREATE hook.
> However, I have two concern on the existing hook to implement
> permission check for object creation. The first one is the entry of
> system catalog is not visible using SnaphotNow, so we had to open and
> scan system catalog again, instead of syscache mechanism. The second
> one is more significant. A part of information to make access control
> decision is not available within contents of the system catalog
> entries. For example, we hope to skip permission check when
> heap_create_with_catalog() was launched by make_new_heap() because the
> new relation is just used to swap later.
>
> Thus, I'd like to propose to support argument of object_access_hook to
> inform the loadable modules additional contextual information on its
> invocations; to solve these concerns.
>
> Regarding to the first concern, fortunately, most of existing
> OAT_POST_CREATE hook is deployed just after insert or update of system
> catalogs, but before CCI. So, it is helpful for the loadable modules
> to deliver Form_pg_xxxx data to reference properties of the new
> object, instead of open and scan the catalog again.
> In the draft patch, I enhanced OAT_POST_CREATE hook commonly to take
> an argument that points to the Form_pg_xxxx data of the new object.
>
> Regarding to the second concern, I added a few contextual information
> as second or later arguments in a part of object classes. Right now, I
> hope the following contextual information shall be provided to
> OAT_POST_CREATE hook to implement permission checks of object
> creation.
>
> * pg_class - TupleDesc structure of the new relation
> I want to reference of pg_attribute, not only pg_class.
>
> * pg_class - A flag to show whether the relation is defined for
> rebuilding, or not.
> I want not to apply permission check in the case when it is invoked
> from make_new_heap(), because it just create a dummy table as a part
> of internal process. All the necessary permission checks should be
> done at ALTER TABLE or CLUSTER.
>
And, name of the foreign server being used by the foreign table
being created just a moment before.

> * pg_class - A flag to show whether the relation is created with
> SELECT INTO, or not.
> I want to check "insert" permission of the new table, created by
> SELECT INTO, because DML hook is not available to check this case.
>
> * pg_type - A flag to show whether the type is defined as implicit
> array, or not.
> I want not to apply permission check on creation of implicit array type.
>
> * pg_database - Oid of the source (template) database.
> I want to fetch security label of the source database to compute a
> default label of the new database.
>
> * pg_trigger - A flag to show whether the trigger is used to FK
> constraint, or not.
> I want not to apply permission check on creation of FK constraint. It
> should be done in ALTER TABLE level.
>
> Sorry for this long explanation. Right now, I tend to consider it is
> the best way to implement permission checks on object creation with
> least invasive way.
>
> Thanks, Any comments welcome.
> --
> KaiGai Kohei <kaigai@kaigai.gr.jp>
>
--
KaiGai Kohei <kaigai@kaigai.gr.jp>

Attachment

Re: [v9.2] Object access hooks with arguments support (v1)

From
Kohei KaiGai
Date:
BTW, I remember that I was suggested the object-access-hooks to acquire
controls around changes of system catalogs are also useful to implement
clustering features, not only enhanced security features, when I had a talk
at PGcon2001.

It might be my mistake that I categorized this patch at the "security" topic.
If someone volunteers to review this patch from the different viewpoint, not
only security features, it is quite helpful for us.

Thanks,

2011/9/29 Kohei KaiGai <kaigai@kaigai.gr.jp>:
> I noticed that the previous revision does not provide any way to inform
> the modules name of foreign server, even if foreign table was created,
> on the OAT_POST_CREATE hook.
> So, I modified the invocation at heap_create_with_catalog to deliver
> this information to the modules.
>
> Rest of parts were unchanged, except for rebasing to the latest git
> master.
>
> 2011/8/28 Kohei KaiGai <kaigai@kaigai.gr.jp>:
>> The attached patch is a draft to support arguments in addition to
>> OAT_* enum and object identifiers.
>>
>> The existing object_access_hook enables loadable modules to acquire
>> control when objects are referenced. The first guest of this hook is
>> contrib/sepgsql for assignment of default security label on newly
>> created objects. Right now, OAT_POST_CREATE is the all supported
>> object access type. However, we plan to enhance this mechanism onto
>> other widespread purpose; such as comprehensive DDL permissions
>> supported by loadable modules.
>>
>> This patch is a groundwork to utilize this hook for object creation
>> permission checks, not only default labeling.
>> At the v9.1 development cycle, I proposed an idea that defines both
>> OAT_CREATE hook prior to system catalog modification and
>> OAT_POST_CREATE hook as currently we have. This design enables to
>> check permission next to the existing pg_xxx_aclcheck() or
>> pg_xxx_ownercheck(), and raise an error before system catalog updates.
>> However, it was painful to deliver private datum set on OAT_CREATE to
>> the OAT_POST_CREATE due to the code complexity.
>>
>> The other idea tried to do all the necessary things in OAT_POST_CREATE
>> hook, and it had been merged, because loadable modules can pull
>> properties of the new object from system catalogs by the supplied
>> object identifiers. Thus, contrib/sepgsql assigns a default security
>> label on new object using OAT_POST_CREATE hook.
>> However, I have two concern on the existing hook to implement
>> permission check for object creation. The first one is the entry of
>> system catalog is not visible using SnaphotNow, so we had to open and
>> scan system catalog again, instead of syscache mechanism. The second
>> one is more significant. A part of information to make access control
>> decision is not available within contents of the system catalog
>> entries. For example, we hope to skip permission check when
>> heap_create_with_catalog() was launched by make_new_heap() because the
>> new relation is just used to swap later.
>>
>> Thus, I'd like to propose to support argument of object_access_hook to
>> inform the loadable modules additional contextual information on its
>> invocations; to solve these concerns.
>>
>> Regarding to the first concern, fortunately, most of existing
>> OAT_POST_CREATE hook is deployed just after insert or update of system
>> catalogs, but before CCI. So, it is helpful for the loadable modules
>> to deliver Form_pg_xxxx data to reference properties of the new
>> object, instead of open and scan the catalog again.
>> In the draft patch, I enhanced OAT_POST_CREATE hook commonly to take
>> an argument that points to the Form_pg_xxxx data of the new object.
>>
>> Regarding to the second concern, I added a few contextual information
>> as second or later arguments in a part of object classes. Right now, I
>> hope the following contextual information shall be provided to
>> OAT_POST_CREATE hook to implement permission checks of object
>> creation.
>>
>> * pg_class - TupleDesc structure of the new relation
>> I want to reference of pg_attribute, not only pg_class.
>>
>> * pg_class - A flag to show whether the relation is defined for
>> rebuilding, or not.
>> I want not to apply permission check in the case when it is invoked
>> from make_new_heap(), because it just create a dummy table as a part
>> of internal process. All the necessary permission checks should be
>> done at ALTER TABLE or CLUSTER.
>>
> And, name of the foreign server being used by the foreign table
> being created just a moment before.
>
>> * pg_class - A flag to show whether the relation is created with
>> SELECT INTO, or not.
>> I want to check "insert" permission of the new table, created by
>> SELECT INTO, because DML hook is not available to check this case.
>>
>> * pg_type - A flag to show whether the type is defined as implicit
>> array, or not.
>> I want not to apply permission check on creation of implicit array type.
>>
>> * pg_database - Oid of the source (template) database.
>> I want to fetch security label of the source database to compute a
>> default label of the new database.
>>
>> * pg_trigger - A flag to show whether the trigger is used to FK
>> constraint, or not.
>> I want not to apply permission check on creation of FK constraint. It
>> should be done in ALTER TABLE level.
>>
>> Sorry for this long explanation. Right now, I tend to consider it is
>> the best way to implement permission checks on object creation with
>> least invasive way.
>>
>> Thanks, Any comments welcome.
>> --
>> KaiGai Kohei <kaigai@kaigai.gr.jp>
>>
> --
> KaiGai Kohei <kaigai@kaigai.gr.jp>
>



-- 
KaiGai Kohei <kaigai@kaigai.gr.jp>


Re: [v9.2] Object access hooks with arguments support (v1)

From
Robert Haas
Date:
On Thu, Sep 29, 2011 at 4:52 PM, Kohei KaiGai <kaigai@kaigai.gr.jp> wrote:
> I noticed that the previous revision does not provide any way to inform
> the modules name of foreign server, even if foreign table was created,
> on the OAT_POST_CREATE hook.
> So, I modified the invocation at heap_create_with_catalog to deliver
> this information to the modules.
>
> Rest of parts were unchanged, except for rebasing to the latest git
> master.

I've never really been totally sanguine with the idea of making object
access hooks take arguments, and all of my general concerns seem to
apply to the way you've set this patch up.  In particular:

1. Type safety goes out the window.  What you're essentially proposing
here is that we should have one hook function can be used for almost
anything at all and can be getting up to 9 arguments of any type
whatsoever.  The hook will need to know how to interpret all of its
arguments depending on the context in which it was called.  The
compiler will be totally unable to do any static type-checking, so
there will be absolutely no warning if the interface is changed
incompatibly on either side.  Instead, you'll probably just crash the
database server at runtime.

2. The particular choice of data being passed to the object access
hooks appears capricious and arbitrary.  Here's an example:
       /* Post creation hook for new relation */
-       InvokeObjectAccessHook(OAT_POST_CREATE, RelationRelationId, relid, 0);
+       InvokeObjectAccessHook4(OAT_POST_CREATE,
+
RelationRelationId, relid, 0,
+
PointerGetDatum(new_rel_tup),
+
PointerGetDatum(tupdesc),
+
BoolGetDatum(is_select_into),
+
CStringGetDatum(fdw_srvname));

Now, I am sure that you have good reasons for wanting to pass those
particular things to the object access hook rather than any other
local variable or argument that might happen to be lying around at
this point in the code, but they are not documented.  If someone adds
a new argument to this function, or removes an argument that's being
passed, they will have no idea what to do about this.  Moreover, if
you did document it, I think it would boil down to "this is what
sepgsql happens to need", and I don't think that's an acceptable
answer.  We have repeatedly refused to adopt that approach in the
past.

(This particular case is worse than average, because new_rel_tup is
coming from InsertPgClassTuple, which therefore has to be modified,
along with AddNewRelationTuple and index_create, to get the tuple back
up to the call site where, apparently, it is needed.)

I am not exactly sure what the right way to solve this problem is, but
I don't think this is it.

-- 
Robert Haas
EnterpriseDB: http://www.enterprisedb.com
The Enterprise PostgreSQL Company


Re: [v9.2] Object access hooks with arguments support (v1)

From
Kohei KaiGai
Date:
Robert,

I agree with it is a reasonable argument that compiler cannot raise warnings
if all the arguments are delivered as Datum. In fact, I also tried to implement
this feature with InvokeObjectAccessHook() defined as function.

The first needed point to be improved is that we hope compiler to raise
warnnings if and when number or type of arguments are changed in the
future version.
If so, how about an idea to define data types to inform modules the context
information in, such as:
   struct ObjectAccessInfoData {       ObjectAccessType   oa_type;       ObjectAddress         oa_address;       union
{          struct {               HeapTuple       newtuple;               TupleDesc       tupdesc;  /* only if create a
newrelation */                   :           } post_create;      /* additional info for OAT_POST_CREATE event */
}  } 

Even if its invocation shall be wrapped up by macro, compiler can
raise warnings when caller set values on the ObjectAccessInfoData
structure.

It will also help the second points partially. The objectaccess.h will perform
a placeholder to describe specification of the argument. That clearly informs
developers what informations are available on the hook and what was lacked.

> Moreover, if
> you did document it, I think it would boil down to "this is what
> sepgsql happens to need", and I don't think that's an acceptable
> answer. ?We have repeatedly refused to adopt that approach in the
> past.
>
Unfortunately, I still don't have a clear answer for this point.
However, in general terms, it is impossible to design any interface without
knowledge of its usage more or less.

We have several other hooks being available to loadable modules,
but I don't believe that we designed these hooks without knowledge
of use-cases, more or less.

At least, this proposition enables modules being informed using
commonly used data type (such as HeapTuple, TupleDesc), compared
to the past approach that tried to push all the necessary information
into argument list individually.

I think the answer of this matter is on the middle-of-position between
"we should not know anything about sepgsql" and "we should know
everything about sepgsql", neither of them....

> (This particular case is worse than average, because new_rel_tup is
> coming from InsertPgClassTuple, which therefore has to be modified,
> along with AddNewRelationTuple and index_create, to get the tuple back
> up to the call site where, apparently, it is needed.)
>
It might be a wrong design. All we want to inform was stored within
new_rel_desc in heap_create_with_catalog(). So, I should design the
hook to deliver new_rel_desc, instead of HeapTuple itself that need to
pull up from InsertPgClassTuple.

Thanks,

2011/10/12 Robert Haas <robertmhaas@gmail.com>:
> On Thu, Sep 29, 2011 at 4:52 PM, Kohei KaiGai <kaigai@kaigai.gr.jp> wrote:
>> I noticed that the previous revision does not provide any way to inform
>> the modules name of foreign server, even if foreign table was created,
>> on the OAT_POST_CREATE hook.
>> So, I modified the invocation at heap_create_with_catalog to deliver
>> this information to the modules.
>>
>> Rest of parts were unchanged, except for rebasing to the latest git
>> master.
>
> I've never really been totally sanguine with the idea of making object
> access hooks take arguments, and all of my general concerns seem to
> apply to the way you've set this patch up.  In particular:
>
> 1. Type safety goes out the window.  What you're essentially proposing
> here is that we should have one hook function can be used for almost
> anything at all and can be getting up to 9 arguments of any type
> whatsoever.  The hook will need to know how to interpret all of its
> arguments depending on the context in which it was called.  The
> compiler will be totally unable to do any static type-checking, so
> there will be absolutely no warning if the interface is changed
> incompatibly on either side.  Instead, you'll probably just crash the
> database server at runtime.
>
> 2. The particular choice of data being passed to the object access
> hooks appears capricious and arbitrary.  Here's an example:
>
>        /* Post creation hook for new relation */
> -       InvokeObjectAccessHook(OAT_POST_CREATE, RelationRelationId, relid, 0);
> +       InvokeObjectAccessHook4(OAT_POST_CREATE,
> +
> RelationRelationId, relid, 0,
> +
> PointerGetDatum(new_rel_tup),
> +
> PointerGetDatum(tupdesc),
> +
> BoolGetDatum(is_select_into),
> +
> CStringGetDatum(fdw_srvname));
>
> Now, I am sure that you have good reasons for wanting to pass those
> particular things to the object access hook rather than any other
> local variable or argument that might happen to be lying around at
> this point in the code, but they are not documented.  If someone adds
> a new argument to this function, or removes an argument that's being
> passed, they will have no idea what to do about this.  Moreover, if
> you did document it, I think it would boil down to "this is what
> sepgsql happens to need", and I don't think that's an acceptable
> answer.  We have repeatedly refused to adopt that approach in the
> past.
>
> (This particular case is worse than average, because new_rel_tup is
> coming from InsertPgClassTuple, which therefore has to be modified,
> along with AddNewRelationTuple and index_create, to get the tuple back
> up to the call site where, apparently, it is needed.)
>
> I am not exactly sure what the right way to solve this problem is, but
> I don't think this is it.
>
--
KaiGai Kohei <kaigai@kaigai.gr.jp>


Re: [v9.2] Object access hooks with arguments support (v1)

From
Robert Haas
Date:
On Thu, Oct 13, 2011 at 6:48 AM, Kohei KaiGai <kaigai@kaigai.gr.jp> wrote:
>    struct ObjectAccessInfoData {
>        ObjectAccessType   oa_type;
>        ObjectAddress         oa_address;
>        union {
>            struct {
>                HeapTuple       newtuple;
>                TupleDesc       tupdesc;  /* only if create a new relation */
>                    :
>            } post_create;      /* additional info for OAT_POST_CREATE event */
>        }
>    }

That's possibly an improvement over just passing everything opaquely,
but it still doesn't seem very good.  I mean, this is C, not Perl or
Python.  Anything where you pass a bunch of arguments of indeterminate
type and hope that the person you're calling can figure it out is
inherently pretty dangerous.  I had it in mind that the object access
hook mechanism could serve as a simple and generic way of letting an
external module know that an event of a certain type has occurred on a
certain object, and to let that module gain control.  But if we have
to pass a raft of arguments in, then it's not generic any more - it's
just a bunch of things that are probably really need to be separate
hooks shoved into a single function.

>> Moreover, if
>> you did document it, I think it would boil down to "this is what
>> sepgsql happens to need", and I don't think that's an acceptable
>> answer. ?We have repeatedly refused to adopt that approach in the
>> past.
>>
> Unfortunately, I still don't have a clear answer for this point.
> However, in general terms, it is impossible to design any interface without
> knowledge of its usage more or less.

Well, that's true.  But the hook also has to be maintainable.  ISTM
that there's no reasonable way for someone making a modification to
the code to know whether the additional local variable that they just
added to the function should be passed to the hook, or not.  Here, at
least as far as I can see, there's no guiding principle that would
enable future contributors to make an intelligent decision about that.And if someone wanted to write another client for
thehook, it's not 
very obvious whether the particular things you've chosen to pass here
would be relevant or not.  I think if you look over the code you'll
find that there's nowhere else that we have a hook that looks anything
like what you're proposing here.

> At least, this proposition enables modules being informed using
> commonly used data type (such as HeapTuple, TupleDesc), compared
> to the past approach that tried to push all the necessary information
> into argument list individually.

That does seem like a good direction to go in, but you're still
passing a lot of other stuff in there.  I guess my feeling is that if
we can't boil down the argument list to a short list of things that
are more-or-less common to all the call sites, we probably need to
rethink the whole design.

--
Robert Haas
EnterpriseDB: http://www.enterprisedb.com
The Enterprise PostgreSQL Company


Re: [v9.2] Object access hooks with arguments support (v1)

From
Kohei KaiGai
Date:
2011/10/18 Robert Haas <robertmhaas@gmail.com>:
> On Thu, Oct 13, 2011 at 6:48 AM, Kohei KaiGai <kaigai@kaigai.gr.jp> wrote:
>>    struct ObjectAccessInfoData {
>>        ObjectAccessType   oa_type;
>>        ObjectAddress         oa_address;
>>        union {
>>            struct {
>>                HeapTuple       newtuple;
>>                TupleDesc       tupdesc;  /* only if create a new relation */
>>                    :
>>            } post_create;      /* additional info for OAT_POST_CREATE event */
>>        }
>>    }
>
> That's possibly an improvement over just passing everything opaquely,
> but it still doesn't seem very good.  I mean, this is C, not Perl or
> Python.  Anything where you pass a bunch of arguments of indeterminate
> type and hope that the person you're calling can figure it out is
> inherently pretty dangerous.  I had it in mind that the object access
> hook mechanism could serve as a simple and generic way of letting an
> external module know that an event of a certain type has occurred on a
> certain object, and to let that module gain control.  But if we have
> to pass a raft of arguments in, then it's not generic any more - it's
> just a bunch of things that are probably really need to be separate
> hooks shoved into a single function.
>
I got an inspiration of this idea from APIs of foreign-data-wrapper that
trusts values of each fields that contains function pointers.
Indeed, we may have a risk of backend crash, if we try to run modules
built towards v9.1 on the pgsql-v9.2devel. However, it is not avoidable,
unless we rewrite whole of the code by Java?, Python? or something? :-(

At least, we don't promise binary compatible across major versions?
If so, I don't think dangerousness is a reasonable reason why the hook
does not take any additional arguments, as long as auther of modules
can be noticed by compiler warnings.

The point to be focused on is how do we implement the target feature
(DDL permissions by sepgsql in my case) with simpleness.

>>> Moreover, if
>>> you did document it, I think it would boil down to "this is what
>>> sepgsql happens to need", and I don't think that's an acceptable
>>> answer. ?We have repeatedly refused to adopt that approach in the
>>> past.
>>>
>> Unfortunately, I still don't have a clear answer for this point.
>> However, in general terms, it is impossible to design any interface without
>> knowledge of its usage more or less.
>
> Well, that's true.  But the hook also has to be maintainable.  ISTM
> that there's no reasonable way for someone making a modification to
> the code to know whether the additional local variable that they just
> added to the function should be passed to the hook, or not.  Here, at
> least as far as I can see, there's no guiding principle that would
> enable future contributors to make an intelligent decision about that.
>  And if someone wanted to write another client for the hook, it's not
> very obvious whether the particular things you've chosen to pass here
> would be relevant or not.  I think if you look over the code you'll
> find that there's nowhere else that we have a hook that looks anything
> like what you're proposing here.
>
In the case when the second client of the hook is proposed, a straight-
forward approach is to expand the above ObjectAccessInfoData to
satisfy the requirement of new one, if existing arguments are not enough.
Because existing modules ignore the new fields, it is harmless.

Linux adopts this approch to host multiple security modules without
confusion, although one makes decision by security label and one
other makes decision by pathname of files; they require different
information on the point to make its decision, because they ignore
unrelevant arguments; such as pathname in selinux.

I remember you worry about the number of arguments getting increased
infinity, however, it is an extreme situation. We are not an A.I to commit
proposed patches automatically, so auther of modules (including me)
will explain why the new arguments are additionally needed here, like as
pathname based security module did in Linux kernel development.

>> At least, this proposition enables modules being informed using
>> commonly used data type (such as HeapTuple, TupleDesc), compared
>> to the past approach that tried to push all the necessary information
>> into argument list individually.
>
> That does seem like a good direction to go in, but you're still
> passing a lot of other stuff in there.  I guess my feeling is that if
> we can't boil down the argument list to a short list of things that
> are more-or-less common to all the call sites, we probably need to
> rethink the whole design.
>
Honestly, the arguments of object_access_hook is a method to implement
security model of sepgsql, not a purpose of mine. So, an alternative idea is
quite welcome to implement sepgsql.
However, I think it is less invasive way than other ideas right now.

For example, I hope sepgsql to perform as follows when user create a new table.
- It computes a default security label that needs Oid of the namespace.
- It checks db_table:{create} permission on the security label being computed.
- In addition, it checks db_table:{insert} permission when SELECT INTO
- Also, it checks these permissions on columns being newly created.
- However, It does not check permissions when the tables are internally created, such as toast tables or temporary
relationscreated by make_new_heap(). 

Although table creation is the most complex case, it allows us to implement
with just three additional aguments. I tried to implement to deploy separate
hooks on the code path on DefineRelation and OpenIntoRel, but I didn't feel
it is enough simple than the latest approach.

Unfortunately, I have no idea to find out these "contextual information" being
commonly used for all the object classes, so I tried to define my example
ObjectAccessInfoData structure with optional fields depending on event
type and object class.

Thanks,
--
KaiGai Kohei <kaigai@kaigai.gr.jp>


Re: [v9.2] Object access hooks with arguments support (v1)

From
Robert Haas
Date:
On Tue, Oct 18, 2011 at 11:25 AM, Kohei KaiGai <kaigai@kaigai.gr.jp> wrote:
> For example, I hope sepgsql to perform as follows when user create a new table.
> - It computes a default security label that needs Oid of the namespace.
> - It checks db_table:{create} permission on the security label being computed.
> - In addition, it checks db_table:{insert} permission when SELECT INTO
> - Also, it checks these permissions on columns being newly created.
> - However, It does not check permissions when the tables are internally created,
>  such as toast tables or temporary relations created by make_new_heap().

That's superficially reasonable, but I don't feel good about passing
is_select_info to the object access hook here.  If insert permission
is required there, then it ought to be getting checked by selinux at
the same place that it's getting checked for at the DAC level.  If we
get into a situation where sepgsql is checking permissions using some
system that's totally different from what we do for DAC, I think
that's going to produce confusing and illogical results.  This is
ground we've been over before.  Similarly with fdw_srvname.  The only
excuse for passing that is to handle a permissions check for foreign
data wrappers that isn't being done for DAC: if there is a DAC
permissions check, then the MAC one should be done there also, not
someplace totally different.

--
Robert Haas
EnterpriseDB: http://www.enterprisedb.com
The Enterprise PostgreSQL Company


Re: [v9.2] Object access hooks with arguments support (v1)

From
Kohei KaiGai
Date:
2011/10/18 Robert Haas <robertmhaas@gmail.com>:
> On Tue, Oct 18, 2011 at 11:25 AM, Kohei KaiGai <kaigai@kaigai.gr.jp> wrote:
>> For example, I hope sepgsql to perform as follows when user create a new table.
>> - It computes a default security label that needs Oid of the namespace.
>> - It checks db_table:{create} permission on the security label being computed.
>> - In addition, it checks db_table:{insert} permission when SELECT INTO
>> - Also, it checks these permissions on columns being newly created.
>> - However, It does not check permissions when the tables are internally created,
>>  such as toast tables or temporary relations created by make_new_heap().
>
> That's superficially reasonable, but I don't feel good about passing
> is_select_info to the object access hook here.  If insert permission
> is required there, then it ought to be getting checked by selinux at
> the same place that it's getting checked for at the DAC level.  If we
> get into a situation where sepgsql is checking permissions using some
> system that's totally different from what we do for DAC, I think
> that's going to produce confusing and illogical results.  This is
> ground we've been over before.  Similarly with fdw_srvname.  The only
> excuse for passing that is to handle a permissions check for foreign
> data wrappers that isn't being done for DAC: if there is a DAC
> permissions check, then the MAC one should be done there also, not
> someplace totally different.
>
If you are suggesting DAC and MAC permissions should be checked
on the same place like as we already doing at ExecCheckRTPerms(),
I'd like to agree with the suggestion, rather than all the checks within
object_access_hook, although it will take code reworking around
access controls.

In the example table creation, heap_create_with_catalog() is invoked
by 5 routines, however, 3 of them are just internal usages, so it is not
preferable to apply permission checks on table creation....

If we may have a hook on table creation next to the place currently
we checks permission on the namespace being created, it is quite
helpful to implement sepgsql.


BTW, it seems to me SELECT INTO should also check insert permission
on DAC level, because it become an incorrect assumption that owner of
table has insert permission on its creation time.

postgres=# ALTER DEFAULT PRIVILEGES FOR USER tak GRANT select ON TABLES TO tak;
ALTER DEFAULT PRIVILEGES
postgres=# \ddp        Default access privilegesOwner | Schema | Type  | Access privileges
-------+--------+-------+-------------------tak   |        | table | tak=r/tak
(1 row)

postgres=# SET SESSION AUTHORIZATION tak;
SET
postgres=> SELECT * INTO t1 FROM (VALUES(1,'aaa'), (2,'bbb'), (3,'ccc')) AS v;
SELECT 3
postgres=> SELECT * FROM t1;column1 | column2
---------+---------      1 | aaa      2 | bbb      3 | ccc
(3 rows)

postgres=> INSERT INTO t1 VALUES (4,'ddd');
ERROR:  permission denied for relation t1

Oops!
--
KaiGai Kohei <kaigai@kaigai.gr.jp>


Re: [v9.2] Object access hooks with arguments support (v1)

From
Robert Haas
Date:
On Tue, Oct 18, 2011 at 1:23 PM, Kohei KaiGai <kaigai@kaigai.gr.jp> wrote:
> If you are suggesting DAC and MAC permissions should be checked
> on the same place like as we already doing at ExecCheckRTPerms(),
> I'd like to agree with the suggestion, rather than all the checks within
> object_access_hook, although it will take code reworking around
> access controls.

Agreed.

> In the example table creation, heap_create_with_catalog() is invoked
> by 5 routines, however, 3 of them are just internal usages, so it is not
> preferable to apply permission checks on table creation....

Some wit once made the remark that if a function has 10 arguments, it
has 11 arguments, meaning that functions with very large numbers of
arguments typically indicate a poor choice of abstraction boundary.
That's pretty much what I think is going on with
heap_create_with_catalog().  I think maybe some refactoring is in
order there, though I am not sure quite what.

> If we may have a hook on table creation next to the place currently
> we checks permission on the namespace being created, it is quite
> helpful to implement sepgsql.

Makes sense.

> BTW, it seems to me SELECT INTO should also check insert permission
> on DAC level, because it become an incorrect assumption that owner of
> table has insert permission on its creation time.
>
> postgres=# ALTER DEFAULT PRIVILEGES FOR USER tak GRANT select ON TABLES TO tak;
> ALTER DEFAULT PRIVILEGES
> postgres=# \ddp
>         Default access privileges
>  Owner | Schema | Type  | Access privileges
> -------+--------+-------+-------------------
>  tak   |        | table | tak=r/tak
> (1 row)
>
> postgres=# SET SESSION AUTHORIZATION tak;
> SET
> postgres=> SELECT * INTO t1 FROM (VALUES(1,'aaa'), (2,'bbb'), (3,'ccc')) AS v;
> SELECT 3
> postgres=> SELECT * FROM t1;
>  column1 | column2
> ---------+---------
>       1 | aaa
>       2 | bbb
>       3 | ccc
> (3 rows)
>
> postgres=> INSERT INTO t1 VALUES (4,'ddd');
> ERROR:  permission denied for relation t1
>
> Oops!

You could make the argument that there's no real security hole there,
because the user could give himself those same privileges right back.
You could also make the argument that a SELECT .. INTO is not the same
as an INSERT and therefore INSERT privileges shouldn't be checked.  I
think there are valid arguments on both sides, but my main point is
that we shouldn't have core do it one way and sepgsql do it the other
way.  That's going to be impossible to maintain and doesn't really
make any logical sense anyway.

--
Robert Haas
EnterpriseDB: http://www.enterprisedb.com
The Enterprise PostgreSQL Company


Re: [v9.2] Object access hooks with arguments support (v1)

From
Kohei KaiGai
Date:
2011/10/18 Robert Haas <robertmhaas@gmail.com>:
>> In the example table creation, heap_create_with_catalog() is invoked
>> by 5 routines, however, 3 of them are just internal usages, so it is not
>> preferable to apply permission checks on table creation....
>
> Some wit once made the remark that if a function has 10 arguments, it
> has 11 arguments, meaning that functions with very large numbers of
> arguments typically indicate a poor choice of abstraction boundary.
> That's pretty much what I think is going on with
> heap_create_with_catalog().  I think maybe some refactoring is in
> order there, though I am not sure quite what.
>
Sorry, are you complained about the number of arguments in
heap_create_with_catalog? or hooks of security checks?

If we try to rework access control logic around DefineRelation and
OpenIntoRel to host both of DAC and MAC, it will takes a long
arguments list because an entry of pg_class catalog is not
constructed at the timing, so we need to inform the routine
all the parameters of new relation required to both DAC and MAC.
Thus, it takes a long argument list, however, number of arguments
of heap_create_with_catalog will not increased so much. (Maybe,
it additionally requires a private data to deliver security labels to be
assigned on the new relation.)

If we relocate logics of DAC into heap_create_with_catalog(), it will
need additional two arguments, though it has 19 arguments right now.
It is not a strange idea to inform routines that modified catalogs
whether this context needs permission checks, or not, because
CreateTrigger has a flag of "isInternal" to skip permission check.

>> BTW, it seems to me SELECT INTO should also check insert permission
>> on DAC level, because it become an incorrect assumption that owner of
>> table has insert permission on its creation time.  :
> You could make the argument that there's no real security hole there,
> because the user could give himself those same privileges right back.
> You could also make the argument that a SELECT .. INTO is not the same
> as an INSERT and therefore INSERT privileges shouldn't be checked.  I
> think there are valid arguments on both sides, but my main point is
> that we shouldn't have core do it one way and sepgsql do it the other
> way.  That's going to be impossible to maintain and doesn't really
> make any logical sense anyway.
>
My point is that we should minimize the code complexity, redundancy
or others between DAC and MAC implementation, however, it is not
possible to get their different to zero due to the differences of their
standpoint.

Yes, I never say SELECT INTO without DAC checks cause actual
security hole, because owner can change its access permissions by
himself, unlike MAC.
Please suppose that there are two security labels: confidential table
(TC) and public table (PT). Typical MAC policy (including selinux)
does not allow users who can read from tables with TC to write out
data into tables with PT, because PT is readable for public as literal,
so confidential data may be leaked to public domain in the result.

It is a significant characteristic of MAC; called as data-flow-control.
So, it damages significant part of its worth, if MAC could not distinct
CREATE TABLE from SELECT INTO in PostgreSQL, and it is the
reason why I strongly requires a flag of contextual information here.

Although you say it is not possible to maintain, doesn't the above
introduction help us to understand nothing why MAC needs to
distinct SELECT INTO from CREATE TABLE?, and why it needs
a flag to distinct two cases?

Thanks,
--
KaiGai Kohei <kaigai@kaigai.gr.jp>


Re: [v9.2] Object access hooks with arguments support (v1)

From
Robert Haas
Date:
On Wed, Oct 19, 2011 at 6:18 AM, Kohei KaiGai <kaigai@kaigai.gr.jp> wrote:
> 2011/10/18 Robert Haas <robertmhaas@gmail.com>:
>>> In the example table creation, heap_create_with_catalog() is invoked
>>> by 5 routines, however, 3 of them are just internal usages, so it is not
>>> preferable to apply permission checks on table creation....
>>
>> Some wit once made the remark that if a function has 10 arguments, it
>> has 11 arguments, meaning that functions with very large numbers of
>> arguments typically indicate a poor choice of abstraction boundary.
>> That's pretty much what I think is going on with
>> heap_create_with_catalog().  I think maybe some refactoring is in
>> order there, though I am not sure quite what.
>>
> Sorry, are you complained about the number of arguments in
> heap_create_with_catalog? or hooks of security checks?

I'm just saying that heap_create_with_catalog() is big and complex and
does a lot of different things.  The fact it does security checks even
though it's also sometimes called as an internal function strikes me
as a modularity violation.  Normally I would expect to have a
high-level routine (which is invoked more or less directly from SQL)
that does security checks and then calls a low-level routine (that
actually does the work) if they pass.  Other parts of the code that
want to perform the same operation without the security checks can
call the low-level function directly.  But that's not the way it's set
up here.

> Yes, I never say SELECT INTO without DAC checks cause actual
> security hole, because owner can change its access permissions by
> himself, unlike MAC.
> Please suppose that there are two security labels: confidential table
> (TC) and public table (PT). Typical MAC policy (including selinux)
> does not allow users who can read from tables with TC to write out
> data into tables with PT, because PT is readable for public as literal,
> so confidential data may be leaked to public domain in the result.
>
> It is a significant characteristic of MAC; called as data-flow-control.
> So, it damages significant part of its worth, if MAC could not distinct
> CREATE TABLE from SELECT INTO in PostgreSQL, and it is the
> reason why I strongly requires a flag of contextual information here.
>
> Although you say it is not possible to maintain, doesn't the above
> introduction help us to understand nothing why MAC needs to
> distinct SELECT INTO from CREATE TABLE?, and why it needs
> a flag to distinct two cases?

Sure.  But what is going to happen when someone needs to modify that
code in a year or two?  In order to understand what to do with the
object access hook, they're going to need to understand all those
details you just mentioned.  And those details do not exist in the
patch as submitted.  Worse, let's suppose we'd committed a patch like
the one you have here before foreign tables went in.  Then, whoever
added foreign tables would have needed to know to add the foreign
table server name to the object access hook invocation, because
apparently sepgsql needs that.  How would they know they needed to do
that?  I've committed practically all of the sepgsql-related patches,
and I would not have known that, so it seems likely to me that other
people adding new functionality to the server wouldn't know it either.

When someone comes along in another year or two and adds materialized
views, will they need to pass some additional data to the object
access hook?  Probably, but I bet you're the only one who can quickly
figure out what it is.  That's no good.  We're not going to make
changes to PostgreSQL core that only you can maintain, and that are
likely to be broken by future commits.  At this point I feel pretty
good that someone can look at the stuff that we've done so far with
SECURITY LABEL and the object access hooks, and if they add a new
object type, they can make those things apply to the new object type
too by copying what's already there, without making any reference to
the sepgsql code.  There's a clear abstraction boundary, and people
who are working on one side of the boundary do not need to understand
the details of what happens on the other side of the boundary.

In this particular case, I think it might be reasonable to change the
DAC behavior, so that a CREATE TABLE AS SELECT or SELECT INTO requires
insert privileges on the new table as well as permission to create it
in the first place.  I don't particularly see any reason to require
different privileges for CREATE TABLE followed by INSERT .. SELECT
than what we require when the two commands are rolled into one.  Prior
to 9.0, this case couldn't arise, because we didn't have default
privileges, so I'm inclined to think that the way it works now is a
historical accident rather than a deliberate design decision.

--
Robert Haas
EnterpriseDB: http://www.enterprisedb.com
The Enterprise PostgreSQL Company


Re: [v9.2] Object access hooks with arguments support (v1)

From
Kohei KaiGai
Date:
> When someone comes along in another year or two and adds materialized
> views, will they need to pass some additional data to the object
> access hook?  Probably, but I bet you're the only one who can quickly
> figure out what it is.  That's no good.  We're not going to make
> changes to PostgreSQL core that only you can maintain, and that are
> likely to be broken by future commits.  At this point I feel pretty
> good that someone can look at the stuff that we've done so far with
> SECURITY LABEL and the object access hooks, and if they add a new
> object type, they can make those things apply to the new object type
> too by copying what's already there, without making any reference to
> the sepgsql code.  There's a clear abstraction boundary, and people
> who are working on one side of the boundary do not need to understand
> the details of what happens on the other side of the boundary.
>
I had checked my older implementation based on 8.4.x or 9.0.x that
includes all the features that I want to implement.
At least, it does not require so much different information from ones
needed by DAC model, although SELECT INTO was an exception.
It might be quite natural because both works similar things.

For example, sepgsql required Oid of source database to compute
default security label on new database at createdb(). It was used to
permission checks in DAC model also.
For another example, sepgsql also required Oids of type-functions
to check permissions on them at DefineType(). It was also used to
DAC model except for these checks were commented out by
#ifdef NOT_USED because of superuser() was already checked.


So, how do we launch this efforts according to the principles:
- Hooks being used to security checks also should be deployed around existing DAC checks.
- The delivered arguments should not be model specific.

I don't have clear idea to rework existing routines like as I proposed
long before; that wrap-up a series of DAC checks and entrypoint of
MAC hooks into a single function.

A straightforward idea is to deploy object-access-hook around existing
DAC checks with new OAT_* label, such as OAT_CREATE.
In the case of relation creation, it shall be DefineRelation() and OpenIntoRel()
to bypass "internal" invocation of heap_create_with_catalog().

Please tell me if we have different idea of code reworking to simplify
deployment of the hooks.

> In this particular case, I think it might be reasonable to change the
> DAC behavior, so that a CREATE TABLE AS SELECT or SELECT INTO requires
> insert privileges on the new table as well as permission to create it
> in the first place.  I don't particularly see any reason to require
> different privileges for CREATE TABLE followed by INSERT .. SELECT
> than what we require when the two commands are rolled into one.  Prior
> to 9.0, this case couldn't arise, because we didn't have default
> privileges, so I'm inclined to think that the way it works now is a
> historical accident rather than a deliberate design decision.
>
It will help this mismatch between DAC and MAC.
I'll submit it as a separate patch to handle this behavior.
Probably, all we need to do here is invocation of ExecCheckRTPerms().

Thanks,
--
KaiGai Kohei <kaigai@kaigai.gr.jp>


Re: [v9.2] Object access hooks with arguments support (v1)

From
Robert Haas
Date:
On Fri, Oct 21, 2011 at 12:44 PM, Kohei KaiGai <kaigai@kaigai.gr.jp> wrote:
> I had checked my older implementation based on 8.4.x or 9.0.x that
> includes all the features that I want to implement.
> At least, it does not require so much different information from ones
> needed by DAC model, although SELECT INTO was an exception.
> It might be quite natural because both works similar things.

OK.  It seems like it might be helpful to put together a list of all
of the things you want to check permissions on, maybe on a wiki page
somewhere, and indicate in there which ones are done and which ones
are not done, and what additional information you think is needed in
each case, and flag any MAC/DAC discrepancies that you are concerned
about.  I think that might help us reach agreement on the best way
forward.  Also, then, as we get things committed, we can track
progress versus that roadmap.

-- 
Robert Haas
EnterpriseDB: http://www.enterprisedb.com
The Enterprise PostgreSQL Company


Re: [v9.2] Object access hooks with arguments support (v1)

From
Kohei KaiGai
Date:
2011/10/21 Robert Haas <robertmhaas@gmail.com>:
> On Fri, Oct 21, 2011 at 12:44 PM, Kohei KaiGai <kaigai@kaigai.gr.jp> wrote:
>> I had checked my older implementation based on 8.4.x or 9.0.x that
>> includes all the features that I want to implement.
>> At least, it does not require so much different information from ones
>> needed by DAC model, although SELECT INTO was an exception.
>> It might be quite natural because both works similar things.
>
> OK.  It seems like it might be helpful to put together a list of all
> of the things you want to check permissions on, maybe on a wiki page
> somewhere, and indicate in there which ones are done and which ones
> are not done, and what additional information you think is needed in
> each case, and flag any MAC/DAC discrepancies that you are concerned
> about.  I think that might help us reach agreement on the best way
> forward.  Also, then, as we get things committed, we can track
> progress versus that roadmap.
>
I tried to summarize permission checks of DAC/MAC on several object classes
that are allowed to assign security label right now.
http://wiki.postgresql.org/index.php?title=SEPostgreSQL/Permissions

In most of checks, required contextual information by SELinux are commonly
used to DAC also, as listed.

On the creation of relations, SELinux requires relkind and TupleDesc to
identify relation type and columns. Unlike a flag of select-into, I'm not sure
whether it is a model specific and hard to manage without knowledge about
sepgsql internal.

In some cases, DAC uses superuser privilege as a substitute for individual
permission checks, such as DefineType().
It seems to me its original implementation checked CREATE permission of
the namespace and ownership of the functions that implements type input,
output or others, then, we commented out these code because superuser
is obviously allowed these checks.
However, MAC does not have concept of superuser, so, SELinux wants to
check db_procedure:{install} for each functions, thus, it requires oid of
the functions to be used for the new type.
Of course, we can see here is no difference between DAC and MAC, if we
consider DAC implicitly allows these checks by superuser().

I think it is a good start to implement first ddl permissions on creation of
the seven object classes as listed; also to proof the concept; 1) we put
permission checks around existing DAC checks, 2) we deliver contextual
data (basically) used in existing DAC also.

I guess DROP or some of ALTER code reworking should be done prior to
deploy object_access_hook around their permission checks, to minimize
maintain efforts.

Thanks,
--
KaiGai Kohei <kaigai@kaigai.gr.jp>


Re: [v9.2] Object access hooks with arguments support (v1)

From
Robert Haas
Date:
On Tue, Nov 1, 2011 at 1:32 PM, Kohei KaiGai <kaigai@kaigai.gr.jp> wrote:
> I tried to summarize permission checks of DAC/MAC on several object classes
> that are allowed to assign security label right now.
> http://wiki.postgresql.org/index.php?title=SEPostgreSQL/Permissions
>
> In most of checks, required contextual information by SELinux are commonly
> used to DAC also, as listed.

What's up with this:

"a flag to inform whether CASCADE or RESTRICT"

That doesn't seem like it should be needed.

We should consider whether CREATE TABLE should be considered to
consist of creating a table and then n attributes, rather than trying
to shove the attribute information wholesale into the create table
check.

> I guess DROP or some of ALTER code reworking should be done prior to
> deploy object_access_hook around their permission checks, to minimize
> maintain efforts.

+1.

-- 
Robert Haas
EnterpriseDB: http://www.enterprisedb.com
The Enterprise PostgreSQL Company


Re: [v9.2] Object access hooks with arguments support (v1)

From
Kohei KaiGai
Date:
2011/11/1 Robert Haas <robertmhaas@gmail.com>:
> On Tue, Nov 1, 2011 at 1:32 PM, Kohei KaiGai <kaigai@kaigai.gr.jp> wrote:
>> I tried to summarize permission checks of DAC/MAC on several object classes
>> that are allowed to assign security label right now.
>> http://wiki.postgresql.org/index.php?title=SEPostgreSQL/Permissions
>>
>> In most of checks, required contextual information by SELinux are commonly
>> used to DAC also, as listed.
>
> What's up with this:
>
> "a flag to inform whether CASCADE or RESTRICT"
>
> That doesn't seem like it should be needed.
>
Ah, it is needed to determine the scope of objects to be deleted.
If a table being referenced by views, deletion of this table with cascade
involves the views, even if these are owned by others.
DAC does not check permissions to drop on depending objects,
so, it is a headache for me.

However, the worth of drop permission checks on involved objects
is not perfectly clear, because the user is allowed to drop the table
being reference by views at least in above example. If so, views to
reference non-existent table is nonsense.
I'm not 100% sure why existing DAC does not check permissions
on depending objects even if these are owned by other users.
I'd like to know the reason of this behavior.

> We should consider whether CREATE TABLE should be considered to
> consist of creating a table and then n attributes, rather than trying
> to shove the attribute information wholesale into the create table
> check.
>
I don't see tangible difference between them except for simpleness of
implementation. One point we should consider is the timing to store
security label of table and columns.

If creation checks of table/columns are consolidated into one hook,
we can check permissions to create them and write-back default
security labels of them into one private datum to be delivered to
post-creation hook.

If creation checks of table/columns are separated into individual
invocation, the later column-checks needs security label of the
new table as contextual information, however, it requires us to
know internals of sepgsql why it needs table's label to check
permission to create a column, because both of checks shall
be done DefineRelation / OpenIntoRel prior to heap_create_with_catalog
that invokes post-creation hook.

So, I think it works better with the approach that also delivers
TupleDesc on creation of relation checks, rather than separated
invocations.

Thanks,
-- 
KaiGai Kohei <kaigai@kaigai.gr.jp>


Re: [v9.2] Object access hooks with arguments support (v1)

From
Kohei KaiGai
Date:
I'm under works on the prep-object-creation hook with contextual
arguments that are
commonly used to existing DAC checks.

One heahache of mine is that some object classes takes long distance to collect
all the information being necessary on creation check; such as DefineType().
In this function, it checks superuser privilege (and CREATE on the namespace
implicitly), then it makes a shell type or a base type after name
resolve of type
handlers (that also checks ownership of functions implicitly). It
means the place
where we can put a prep-creation hook is restricted to the point next to all the
oid of type-handlers are looked-up, however, it is too late to apply checks
before TypeShellMake().

I hope to make clear the matter again. The reason why we didn't want to put
permission check on OAT_POST_CREATE hook is that it takes random
flags (like "is_select_into") on its argument to avoid unnecessary permission
checks.

If sepgsql would apply permission checks db_procedure:{install} on the
OAT_POST_CREATE hook based on the funcion-oid within new entry of
system catalog, we can relocate OAT_PREP_CREATE hook more conceptually
right place, such as just after the pg_namespace_aclcheck() of DefineType().
On the other hand, we may need to answer why these information are NOT
delivered on the OAT_PREP_CREATE hook without knowledge of sepgsql
internal.

Please some ideas.

Thanks,

2011/11/1 Kohei KaiGai <kaigai@kaigai.gr.jp>:
> 2011/11/1 Robert Haas <robertmhaas@gmail.com>:
>> On Tue, Nov 1, 2011 at 1:32 PM, Kohei KaiGai <kaigai@kaigai.gr.jp> wrote:
>>> I tried to summarize permission checks of DAC/MAC on several object classes
>>> that are allowed to assign security label right now.
>>> http://wiki.postgresql.org/index.php?title=SEPostgreSQL/Permissions
>>>
>>> In most of checks, required contextual information by SELinux are commonly
>>> used to DAC also, as listed.
>>
>> What's up with this:
>>
>> "a flag to inform whether CASCADE or RESTRICT"
>>
>> That doesn't seem like it should be needed.
>>
> Ah, it is needed to determine the scope of objects to be deleted.
> If a table being referenced by views, deletion of this table with cascade
> involves the views, even if these are owned by others.
> DAC does not check permissions to drop on depending objects,
> so, it is a headache for me.
>
> However, the worth of drop permission checks on involved objects
> is not perfectly clear, because the user is allowed to drop the table
> being reference by views at least in above example. If so, views to
> reference non-existent table is nonsense.
> I'm not 100% sure why existing DAC does not check permissions
> on depending objects even if these are owned by other users.
> I'd like to know the reason of this behavior.
>
>> We should consider whether CREATE TABLE should be considered to
>> consist of creating a table and then n attributes, rather than trying
>> to shove the attribute information wholesale into the create table
>> check.
>>
> I don't see tangible difference between them except for simpleness of
> implementation. One point we should consider is the timing to store
> security label of table and columns.
>
> If creation checks of table/columns are consolidated into one hook,
> we can check permissions to create them and write-back default
> security labels of them into one private datum to be delivered to
> post-creation hook.
>
> If creation checks of table/columns are separated into individual
> invocation, the later column-checks needs security label of the
> new table as contextual information, however, it requires us to
> know internals of sepgsql why it needs table's label to check
> permission to create a column, because both of checks shall
> be done DefineRelation / OpenIntoRel prior to heap_create_with_catalog
> that invokes post-creation hook.
>
> So, I think it works better with the approach that also delivers
> TupleDesc on creation of relation checks, rather than separated
> invocations.
>
> Thanks,
> --
> KaiGai Kohei <kaigai@kaigai.gr.jp>
>



--
KaiGai Kohei <kaigai@kaigai.gr.jp>

Attachment

Re: [v9.2] Object access hooks with arguments support (v1)

From
Robert Haas
Date:
On Mon, Nov 7, 2011 at 12:20 PM, Kohei KaiGai <kaigai@kaigai.gr.jp> wrote:
> If sepgsql would apply permission checks db_procedure:{install} on the
> OAT_POST_CREATE hook based on the funcion-oid within new entry of
> system catalog, we can relocate OAT_PREP_CREATE hook more conceptually
> right place, such as just after the pg_namespace_aclcheck() of DefineType().
> On the other hand, we may need to answer why these information are NOT
> delivered on the OAT_PREP_CREATE hook without knowledge of sepgsql
> internal.

I'm having a hard time understanding this.

Can you strip this patch down so it just applies to a single object
type (tables, maybe, or functions, or whatever you like) and then
submit the corresponding sepgsql changes with it?  Just as a demo
patch, so I can understand where you're trying to go with this.

-- 
Robert Haas
EnterpriseDB: http://www.enterprisedb.com
The Enterprise PostgreSQL Company


Re: [v9.2] Object access hooks with arguments support (v1)

From
Kohei KaiGai
Date:
2011/11/8 Robert Haas <robertmhaas@gmail.com>:
> On Mon, Nov 7, 2011 at 12:20 PM, Kohei KaiGai <kaigai@kaigai.gr.jp> wrote:
>> If sepgsql would apply permission checks db_procedure:{install} on the
>> OAT_POST_CREATE hook based on the funcion-oid within new entry of
>> system catalog, we can relocate OAT_PREP_CREATE hook more conceptually
>> right place, such as just after the pg_namespace_aclcheck() of DefineType().
>> On the other hand, we may need to answer why these information are NOT
>> delivered on the OAT_PREP_CREATE hook without knowledge of sepgsql
>> internal.
>
> I'm having a hard time understanding this.
>
> Can you strip this patch down so it just applies to a single object
> type (tables, maybe, or functions, or whatever you like) and then
> submit the corresponding sepgsql changes with it?  Just as a demo
> patch, so I can understand where you're trying to go with this.
>
I tried to strip the previous patch into small portion per object types.
Part-1 for database, Part-2 for schema, Part-3 for relations, and
Part-4 for functions.

The basic idea is the prep-creation hook informs the sepgsql module
properties of the new object being constructed. According to the
previous discussion, all the arguments are commonly used to existing
DAC checks also. Then, this hook allows to write back its private
opaque to be delivered to the post-creation hook; likely used to deliver
security label of the new object to be assigned.

However, I become unsure whether it is a good idea to put prep-creation
hook on all the object, because it takes many boring interface changes
to deliver private datum, and we're probably able to implement similar
stuff with post-creation hook except for a few object types.

I guess the following (A) and (B) are the only case that needs prep-
creation hooks for permission checks. Elsewhere, sepgsql will be
able to make its decision based on the entry of system catalogs
on post-creation hook.

(A) In the case when we want to apply checks based on information
that is not contained within system catalogs.
E.g, Oid of source database on CREATE DATABASE. Existing DAC
checks ownership of the database, if not template.

(B) In the case when we want to distinguish code path between user's
query and system internal stuff.
E.g, heap_create_with_catalog() is also called by make_new_heap()
as a part of ALTER TABLE, but it is quite internal stuff, so not suitable
to apply permission checks here.

It seems to me, using post-creation hooks makes the patch mode simple
to implement permission checks; except for above two object types.
So, I'd like to adopt approach to put prep-creation hooks on limited number
of object types, not symmetric with post-creation hook.
How about your opinion about this?

Thanks,
--
KaiGai Kohei <kaigai@kaigai.gr.jp>

Attachment