Require update permission for the large object written by lo_put().

lo_put() surely should require UPDATE permission, the same as lowrite(),
but it failed to check for that, as reported by Chapman Flack.  Oversight
in commit c50b7c09d; backpatch to 9.4 where that was introduced.

Tom Lane and Michael Paquier

Security: CVE-2017-7548
This commit is contained in:
Tom Lane 2017-08-07 10:19:01 -04:00
parent e568e1eee4
commit 8d9881911f
3 changed files with 26 additions and 0 deletions

View File

@ -896,6 +896,18 @@ be_lo_put(PG_FUNCTION_ARGS)
CreateFSContext();
loDesc = inv_open(loOid, INV_WRITE, fscxt);
/* Permission check */
if (!lo_compat_privileges &&
pg_largeobject_aclcheck_snapshot(loDesc->id,
GetUserId(),
ACL_UPDATE,
loDesc->snapshot) != ACLCHECK_OK)
ereport(ERROR,
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
errmsg("permission denied for large object %u",
loDesc->id)));
inv_seek(loDesc, offset, SEEK_SET);
written = inv_write(loDesc, VARDATA_ANY(str), VARSIZE_ANY_EXHDR(str));
Assert(written == VARSIZE_ANY_EXHDR(str));

View File

@ -1238,6 +1238,14 @@ SELECT lo_create(2002);
2002
(1 row)
SELECT loread(lo_open(1001, x'20000'::int), 32); -- allowed, for now
loread
--------
\x
(1 row)
SELECT lowrite(lo_open(1001, x'40000'::int), 'abcd'); -- fail, wrong mode
ERROR: large object descriptor 0 was not opened for writing
SELECT loread(lo_open(1001, x'40000'::int), 32);
loread
--------
@ -1333,6 +1341,8 @@ SELECT lowrite(lo_open(1002, x'20000'::int), 'abcd'); -- to be denied
ERROR: permission denied for large object 1002
SELECT lo_truncate(lo_open(1002, x'20000'::int), 10); -- to be denied
ERROR: permission denied for large object 1002
SELECT lo_put(1002, 1, 'abcd'); -- to be denied
ERROR: permission denied for large object 1002
SELECT lo_unlink(1002); -- to be denied
ERROR: must be owner of large object 1002
SELECT lo_export(1001, '/dev/null'); -- to be denied

View File

@ -779,6 +779,9 @@ SET SESSION AUTHORIZATION regress_user2;
SELECT lo_create(2001);
SELECT lo_create(2002);
SELECT loread(lo_open(1001, x'20000'::int), 32); -- allowed, for now
SELECT lowrite(lo_open(1001, x'40000'::int), 'abcd'); -- fail, wrong mode
SELECT loread(lo_open(1001, x'40000'::int), 32);
SELECT loread(lo_open(1002, x'40000'::int), 32); -- to be denied
SELECT loread(lo_open(1003, x'40000'::int), 32);
@ -818,6 +821,7 @@ SET SESSION AUTHORIZATION regress_user4;
SELECT loread(lo_open(1002, x'40000'::int), 32); -- to be denied
SELECT lowrite(lo_open(1002, x'20000'::int), 'abcd'); -- to be denied
SELECT lo_truncate(lo_open(1002, x'20000'::int), 10); -- to be denied
SELECT lo_put(1002, 1, 'abcd'); -- to be denied
SELECT lo_unlink(1002); -- to be denied
SELECT lo_export(1001, '/dev/null'); -- to be denied