User-Id Tracking when Portal was started

Lists: pgsql-hackers
From: Kohei KaiGai <kaigai(at)kaigai(dot)gr(dot)jp>
To: PgHacker <pgsql-hackers(at)postgresql(dot)org>
Cc: Tom Lane <tgl(at)sss(dot)pgh(dot)pa(dot)us>, Florian Pflug <fgp(at)phlo(dot)org>, Robert Haas <robertmhaas(at)gmail(dot)com>
Subject: User-Id Tracking when Portal was started
Date: 2012-07-02 14:55:39
Message-ID: CADyhKSVXDZY7yy3LXy6kgLaKi4mAPMYqP5w7bc4mXMUpQZTB5w@mail.gmail.com
Views: Raw Message | Whole Thread | Download mbox | Resend email
Lists: pgsql-hackers

The attached patch is delivered from the discussion around row-level
access control feature. A problem Florian pointed out is refcursor
declared in security definer function. Even though all the permission
checks are applied based on privilege of the owner of security-definer
function in case when it tries to define a cursor bound to a particular
query, it shall be executed under the credential of executor.
In the result, "current_user" or "has_table_privilege()" will return
unexpected result, even if it would be used in as a part of security
policy for each row.

This patch enables to switch user-id when user tried to execute
a portal being started under the different user's credential.

postgres=# CREATE FUNCTION f1(refcursor) RETURNS refcursor
postgres-# SECURITY DEFINER LANGUAGE plpgsql
postgres-# AS 'BEGIN OPEN $1 FOR SELECT current_user,* FROM t1;
postgres'# RETURN $1; END';
CREATE FUNCTION

postgres=# SET SESSION AUTHORIZATION alice;
SET
postgres=> BEGIN;
BEGIN
postgres=> SELECT f1('abc');
f1
-----
abc
(1 row)

postgres=> FETCH abc;
current_user | a | b
--------------+---+-----
kaigai | 1 | aaa <=== 'abc' was started under the
kaigai's privilege
(1 row)

postgres=> SELECT current_user;
current_user
--------------
alice
(1 row)

postgres=> DECLARE xyz CURSOR FOR SELECT current_user, * FROM t1;
DECLARE CURSOR
postgres=> FETCH xyz;
current_user | a | b
--------------+---+-----
alice | 1 | aaa
(1 row)

postgres=> RESET SESSION AUTHORIZATION;
RESET
postgres=# FETCH xyz; <=== 'xyz' was started under the
kaigai's privilege
current_user | a | b
--------------+---+-----
alice | 2 | bbb
(1 row)

BTW, same problem will be caused in case when security label of
the client would be switched. Probably, a hook should be injected
around the places where I patched with this patch.

Thanks,
--
KaiGai Kohei <kaigai(at)kaigai(dot)gr(dot)jp>

Attachment Content-Type Size
pgsql-v9.3-track-userid-of-portal.v1.patch application/octet-stream 10.3 KB

From: Robert Haas <robertmhaas(at)gmail(dot)com>
To: Kohei KaiGai <kaigai(at)kaigai(dot)gr(dot)jp>
Cc: PgHacker <pgsql-hackers(at)postgresql(dot)org>, Tom Lane <tgl(at)sss(dot)pgh(dot)pa(dot)us>, Florian Pflug <fgp(at)phlo(dot)org>
Subject: Re: User-Id Tracking when Portal was started
Date: 2012-07-03 14:58:21
Message-ID: CA+Tgmobwff9vmkAOge=OrtyDbQgQ_F5oUfp=BhOzo3xxoq2Vcg@mail.gmail.com
Views: Raw Message | Whole Thread | Download mbox | Resend email
Lists: pgsql-hackers

On Mon, Jul 2, 2012 at 10:55 AM, Kohei KaiGai <kaigai(at)kaigai(dot)gr(dot)jp> wrote:
> The attached patch is delivered from the discussion around row-level
> access control feature. A problem Florian pointed out is refcursor
> declared in security definer function. Even though all the permission
> checks are applied based on privilege of the owner of security-definer
> function in case when it tries to define a cursor bound to a particular
> query, it shall be executed under the credential of executor.
> In the result, "current_user" or "has_table_privilege()" will return
> unexpected result, even if it would be used in as a part of security
> policy for each row.

Why not just save and restore the user ID and security context
unconditionally, instead of doing this kind of dance?

+ if (portal->userId != GetUserId())
+ SetUserIdAndSecContext(portal->userId, portal->secCo
+ else
+ saveUserId = InvalidOid;

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


From: Kohei KaiGai <kaigai(at)kaigai(dot)gr(dot)jp>
To: Robert Haas <robertmhaas(at)gmail(dot)com>
Cc: PgHacker <pgsql-hackers(at)postgresql(dot)org>, Tom Lane <tgl(at)sss(dot)pgh(dot)pa(dot)us>, Florian Pflug <fgp(at)phlo(dot)org>
Subject: Re: User-Id Tracking when Portal was started
Date: 2012-07-03 15:33:09
Message-ID: CADyhKSXJ7-n53unMnjQQMt4sDjUVcmKb7MZMTnwvZain=mVrkg@mail.gmail.com
Views: Raw Message | Whole Thread | Download mbox | Resend email
Lists: pgsql-hackers

2012/7/3 Robert Haas <robertmhaas(at)gmail(dot)com>:
> On Mon, Jul 2, 2012 at 10:55 AM, Kohei KaiGai <kaigai(at)kaigai(dot)gr(dot)jp> wrote:
>> The attached patch is delivered from the discussion around row-level
>> access control feature. A problem Florian pointed out is refcursor
>> declared in security definer function. Even though all the permission
>> checks are applied based on privilege of the owner of security-definer
>> function in case when it tries to define a cursor bound to a particular
>> query, it shall be executed under the credential of executor.
>> In the result, "current_user" or "has_table_privilege()" will return
>> unexpected result, even if it would be used in as a part of security
>> policy for each row.
>
> Why not just save and restore the user ID and security context
> unconditionally, instead of doing this kind of dance?
>
> + if (portal->userId != GetUserId())
> + SetUserIdAndSecContext(portal->userId, portal->secCo
> + else
> + saveUserId = InvalidOid;
>
In case when CurrentUserId was updated during the code block
(E.g, execution of SET SESSION AUTHORIZATION), it overwrites
this update on restoring user-id and security-context.

Comparison of user-id is a simple marker to check whether this
portal contain an operation to switch user-id, because these
operations are prohibited within security restricted context.
(Is there some other good criteria?)

Thanks,
--
KaiGai Kohei <kaigai(at)kaigai(dot)gr(dot)jp>


From: Tom Lane <tgl(at)sss(dot)pgh(dot)pa(dot)us>
To: Kohei KaiGai <kaigai(at)kaigai(dot)gr(dot)jp>
Cc: Robert Haas <robertmhaas(at)gmail(dot)com>, PgHacker <pgsql-hackers(at)postgresql(dot)org>, Florian Pflug <fgp(at)phlo(dot)org>
Subject: Re: User-Id Tracking when Portal was started
Date: 2012-07-03 15:36:42
Message-ID: 8018.1341329802@sss.pgh.pa.us
Views: Raw Message | Whole Thread | Download mbox | Resend email
Lists: pgsql-hackers

Kohei KaiGai <kaigai(at)kaigai(dot)gr(dot)jp> writes:
> 2012/7/3 Robert Haas <robertmhaas(at)gmail(dot)com>:
>> Why not just save and restore the user ID and security context
>> unconditionally, instead of doing this kind of dance?
>>
>> + if (portal->userId != GetUserId())
>> + SetUserIdAndSecContext(portal->userId, portal->secCo
>> + else
>> + saveUserId = InvalidOid;
>>
> In case when CurrentUserId was updated during the code block
> (E.g, execution of SET SESSION AUTHORIZATION), it overwrites
> this update on restoring user-id and security-context.

Um... what should happen if there was a SET SESSION AUTHORIZATION
to the portal's userId? This test will think nothing happened.

regards, tom lane


From: Kohei KaiGai <kaigai(at)kaigai(dot)gr(dot)jp>
To: Tom Lane <tgl(at)sss(dot)pgh(dot)pa(dot)us>
Cc: Robert Haas <robertmhaas(at)gmail(dot)com>, PgHacker <pgsql-hackers(at)postgresql(dot)org>, Florian Pflug <fgp(at)phlo(dot)org>
Subject: Re: User-Id Tracking when Portal was started
Date: 2012-07-03 15:42:17
Message-ID: CADyhKSX6U5UbGznkXe5iNaWG+ADAsuqdUbAkbhLTd+QXH=2_9g@mail.gmail.com
Views: Raw Message | Whole Thread | Download mbox | Resend email
Lists: pgsql-hackers

2012/7/3 Tom Lane <tgl(at)sss(dot)pgh(dot)pa(dot)us>:
> Kohei KaiGai <kaigai(at)kaigai(dot)gr(dot)jp> writes:
>> 2012/7/3 Robert Haas <robertmhaas(at)gmail(dot)com>:
>>> Why not just save and restore the user ID and security context
>>> unconditionally, instead of doing this kind of dance?
>>>
>>> + if (portal->userId != GetUserId())
>>> + SetUserIdAndSecContext(portal->userId, portal->secCo
>>> + else
>>> + saveUserId = InvalidOid;
>>>
>> In case when CurrentUserId was updated during the code block
>> (E.g, execution of SET SESSION AUTHORIZATION), it overwrites
>> this update on restoring user-id and security-context.
>
> Um... what should happen if there was a SET SESSION AUTHORIZATION
> to the portal's userId? This test will think nothing happened.
>
In my test, all the jobs by SET SESSION AUTHORIZATION was cleaned-up...
It makes nothing happen from viewpoint of users.

Thanks,
--
KaiGai Kohei <kaigai(at)kaigai(dot)gr(dot)jp>


From: Tom Lane <tgl(at)sss(dot)pgh(dot)pa(dot)us>
To: Kohei KaiGai <kaigai(at)kaigai(dot)gr(dot)jp>
Cc: Robert Haas <robertmhaas(at)gmail(dot)com>, PgHacker <pgsql-hackers(at)postgresql(dot)org>, Florian Pflug <fgp(at)phlo(dot)org>
Subject: Re: User-Id Tracking when Portal was started
Date: 2012-07-03 16:08:47
Message-ID: 8813.1341331727@sss.pgh.pa.us
Views: Raw Message | Whole Thread | Download mbox | Resend email
Lists: pgsql-hackers

Kohei KaiGai <kaigai(at)kaigai(dot)gr(dot)jp> writes:
> 2012/7/3 Tom Lane <tgl(at)sss(dot)pgh(dot)pa(dot)us>:
>> Um... what should happen if there was a SET SESSION AUTHORIZATION
>> to the portal's userId? This test will think nothing happened.

> In my test, all the jobs by SET SESSION AUTHORIZATION was cleaned-up...
> It makes nothing happen from viewpoint of users.

My point is that it seems like a bug that the secContext gets restored
in one case and not the other, depending on which user ID was specified
in SET SESSION AUTHORIZATION.

regards, tom lane


From: Kohei KaiGai <kaigai(at)kaigai(dot)gr(dot)jp>
To: Tom Lane <tgl(at)sss(dot)pgh(dot)pa(dot)us>
Cc: Robert Haas <robertmhaas(at)gmail(dot)com>, PgHacker <pgsql-hackers(at)postgresql(dot)org>, Florian Pflug <fgp(at)phlo(dot)org>
Subject: Re: User-Id Tracking when Portal was started
Date: 2012-07-03 16:46:13
Message-ID: CADyhKSX+Btth0dJa5L1niFO8d-+ZprO+61jLyE64En5oVwcgfA@mail.gmail.com
Views: Raw Message | Whole Thread | Download mbox | Resend email
Lists: pgsql-hackers

2012/7/3 Tom Lane <tgl(at)sss(dot)pgh(dot)pa(dot)us>:
> Kohei KaiGai <kaigai(at)kaigai(dot)gr(dot)jp> writes:
>> 2012/7/3 Tom Lane <tgl(at)sss(dot)pgh(dot)pa(dot)us>:
>>> Um... what should happen if there was a SET SESSION AUTHORIZATION
>>> to the portal's userId? This test will think nothing happened.
>
>> In my test, all the jobs by SET SESSION AUTHORIZATION was cleaned-up...
>> It makes nothing happen from viewpoint of users.
>
> My point is that it seems like a bug that the secContext gets restored
> in one case and not the other, depending on which user ID was specified
> in SET SESSION AUTHORIZATION.
>
Sorry, the above description mention about a case when it does not use
the marker to distinguish a case to switch user-id from a case not to switch.
(I though I was asked the behavior if this logic always switches /
restores ids.)

The patch itself works correctly, no regression test failed even though
several tests switches user-id using SET SESSION AUTHORIZATION.

Thanks,
--
KaiGai Kohei <kaigai(at)kaigai(dot)gr(dot)jp>


From: Robert Haas <robertmhaas(at)gmail(dot)com>
To: Kohei KaiGai <kaigai(at)kaigai(dot)gr(dot)jp>
Cc: Tom Lane <tgl(at)sss(dot)pgh(dot)pa(dot)us>, PgHacker <pgsql-hackers(at)postgresql(dot)org>, Florian Pflug <fgp(at)phlo(dot)org>
Subject: Re: User-Id Tracking when Portal was started
Date: 2012-07-04 19:44:41
Message-ID: CA+TgmoZiHtC_HuETFd=QsKXh7ydcN9s1HWAL+8vG+2hndkxy1Q@mail.gmail.com
Views: Raw Message | Whole Thread | Download mbox | Resend email
Lists: pgsql-hackers

On Tue, Jul 3, 2012 at 12:46 PM, Kohei KaiGai <kaigai(at)kaigai(dot)gr(dot)jp> wrote:
>> My point is that it seems like a bug that the secContext gets restored
>> in one case and not the other, depending on which user ID was specified
>> in SET SESSION AUTHORIZATION.
>>
> Sorry, the above description mention about a case when it does not use
> the marker to distinguish a case to switch user-id from a case not to switch.
> (I though I was asked the behavior if this logic always switches /
> restores ids.)
>
> The patch itself works correctly, no regression test failed even though
> several tests switches user-id using SET SESSION AUTHORIZATION.

I don't believe that proves anything. There are lots of things that
aren't tested by the regression tests, and there's no guarantee that
any you've added cover all bases, either. We always treat user-ID and
security context as a unit; you haven't given any reason why this case
should be handled differently, and I bet it shouldn't.

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


From: Kohei KaiGai <kaigai(at)kaigai(dot)gr(dot)jp>
To: Robert Haas <robertmhaas(at)gmail(dot)com>
Cc: Tom Lane <tgl(at)sss(dot)pgh(dot)pa(dot)us>, PgHacker <pgsql-hackers(at)postgresql(dot)org>, Florian Pflug <fgp(at)phlo(dot)org>
Subject: Re: User-Id Tracking when Portal was started
Date: 2012-07-04 20:24:07
Message-ID: CADyhKSUUtCFc27extrqejvYZKPAHP_ovvipU7vG9NOfTeksG2Q@mail.gmail.com
Views: Raw Message | Whole Thread | Download mbox | Resend email
Lists: pgsql-hackers

2012/7/4 Robert Haas <robertmhaas(at)gmail(dot)com>:
> On Tue, Jul 3, 2012 at 12:46 PM, Kohei KaiGai <kaigai(at)kaigai(dot)gr(dot)jp> wrote:
>>> My point is that it seems like a bug that the secContext gets restored
>>> in one case and not the other, depending on which user ID was specified
>>> in SET SESSION AUTHORIZATION.
>>>
>> Sorry, the above description mention about a case when it does not use
>> the marker to distinguish a case to switch user-id from a case not to switch.
>> (I though I was asked the behavior if this logic always switches /
>> restores ids.)
>>
>> The patch itself works correctly, no regression test failed even though
>> several tests switches user-id using SET SESSION AUTHORIZATION.
>
> I don't believe that proves anything. There are lots of things that
> aren't tested by the regression tests, and there's no guarantee that
> any you've added cover all bases, either. We always treat user-ID and
> security context as a unit; you haven't given any reason why this case
> should be handled differently, and I bet it shouldn't.
>
This patch always handles user-id and security context as a unit.
In case when it was switched, then it shall be always restored.
And, in case when it was not switched, then it shall never be restored.

Was my explanation confusing?
--
KaiGai Kohei <kaigai(at)kaigai(dot)gr(dot)jp>


From: Robert Haas <robertmhaas(at)gmail(dot)com>
To: Kohei KaiGai <kaigai(at)kaigai(dot)gr(dot)jp>
Cc: Tom Lane <tgl(at)sss(dot)pgh(dot)pa(dot)us>, PgHacker <pgsql-hackers(at)postgresql(dot)org>, Florian Pflug <fgp(at)phlo(dot)org>
Subject: Re: User-Id Tracking when Portal was started
Date: 2012-07-05 17:05:30
Message-ID: CA+TgmoaKUBxECi15AEzUh627VDFHNQ+BVVmXAOn4AYOeqdn98g@mail.gmail.com
Views: Raw Message | Whole Thread | Download mbox | Resend email
Lists: pgsql-hackers

On Wed, Jul 4, 2012 at 4:24 PM, Kohei KaiGai <kaigai(at)kaigai(dot)gr(dot)jp> wrote:
> 2012/7/4 Robert Haas <robertmhaas(at)gmail(dot)com>:
>> On Tue, Jul 3, 2012 at 12:46 PM, Kohei KaiGai <kaigai(at)kaigai(dot)gr(dot)jp> wrote:
>>>> My point is that it seems like a bug that the secContext gets restored
>>>> in one case and not the other, depending on which user ID was specified
>>>> in SET SESSION AUTHORIZATION.
>>>>
>>> Sorry, the above description mention about a case when it does not use
>>> the marker to distinguish a case to switch user-id from a case not to switch.
>>> (I though I was asked the behavior if this logic always switches /
>>> restores ids.)
>>>
>>> The patch itself works correctly, no regression test failed even though
>>> several tests switches user-id using SET SESSION AUTHORIZATION.
>>
>> I don't believe that proves anything. There are lots of things that
>> aren't tested by the regression tests, and there's no guarantee that
>> any you've added cover all bases, either. We always treat user-ID and
>> security context as a unit; you haven't given any reason why this case
>> should be handled differently, and I bet it shouldn't.
>>
> This patch always handles user-id and security context as a unit.
> In case when it was switched, then it shall be always restored.
> And, in case when it was not switched, then it shall never be restored.
>
> Was my explanation confusing?

It's not that your explanation is confusing; it's that it doesn't
match the code.

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