Skip to content

Commit f1cda6d

Browse files
committed
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 c50b7c0; backpatch to 9.4 where that was introduced. Tom Lane and Michael Paquier Security: CVE-2017-7548
1 parent b6e39ca commit f1cda6d

File tree

3 files changed

+26
-0
lines changed

3 files changed

+26
-0
lines changed

src/backend/libpq/be-fsstubs.c

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -898,6 +898,18 @@ lo_put(PG_FUNCTION_ARGS)
898898
CreateFSContext();
899899

900900
loDesc = inv_open(loOid, INV_WRITE, fscxt);
901+
902+
/* Permission check */
903+
if (!lo_compat_privileges &&
904+
pg_largeobject_aclcheck_snapshot(loDesc->id,
905+
GetUserId(),
906+
ACL_UPDATE,
907+
loDesc->snapshot) != ACLCHECK_OK)
908+
ereport(ERROR,
909+
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
910+
errmsg("permission denied for large object %u",
911+
loDesc->id)));
912+
901913
inv_seek(loDesc, offset, SEEK_SET);
902914
written = inv_write(loDesc, VARDATA_ANY(str), VARSIZE_ANY_EXHDR(str));
903915
Assert(written == VARSIZE_ANY_EXHDR(str));

src/test/regress/expected/privileges.out

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1189,6 +1189,14 @@ SELECT lo_create(2002);
11891189
2002
11901190
(1 row)
11911191

1192+
SELECT loread(lo_open(1001, x'20000'::int), 32); -- allowed, for now
1193+
loread
1194+
--------
1195+
\x
1196+
(1 row)
1197+
1198+
SELECT lowrite(lo_open(1001, x'40000'::int), 'abcd'); -- fail, wrong mode
1199+
ERROR: large object descriptor 0 was not opened for writing
11921200
SELECT loread(lo_open(1001, x'40000'::int), 32);
11931201
loread
11941202
--------
@@ -1284,6 +1292,8 @@ SELECT lowrite(lo_open(1002, x'20000'::int), 'abcd'); -- to be denied
12841292
ERROR: permission denied for large object 1002
12851293
SELECT lo_truncate(lo_open(1002, x'20000'::int), 10); -- to be denied
12861294
ERROR: permission denied for large object 1002
1295+
SELECT lo_put(1002, 1, 'abcd'); -- to be denied
1296+
ERROR: permission denied for large object 1002
12871297
SELECT lo_unlink(1002); -- to be denied
12881298
ERROR: must be owner of large object 1002
12891299
SELECT lo_export(1001, '/dev/null'); -- to be denied

src/test/regress/sql/privileges.sql

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -753,6 +753,9 @@ SET SESSION AUTHORIZATION regressuser2;
753753
SELECT lo_create(2001);
754754
SELECT lo_create(2002);
755755

756+
SELECT loread(lo_open(1001, x'20000'::int), 32); -- allowed, for now
757+
SELECT lowrite(lo_open(1001, x'40000'::int), 'abcd'); -- fail, wrong mode
758+
756759
SELECT loread(lo_open(1001, x'40000'::int), 32);
757760
SELECT loread(lo_open(1002, x'40000'::int), 32); -- to be denied
758761
SELECT loread(lo_open(1003, x'40000'::int), 32);
@@ -792,6 +795,7 @@ SET SESSION AUTHORIZATION regressuser4;
792795
SELECT loread(lo_open(1002, x'40000'::int), 32); -- to be denied
793796
SELECT lowrite(lo_open(1002, x'20000'::int), 'abcd'); -- to be denied
794797
SELECT lo_truncate(lo_open(1002, x'20000'::int), 10); -- to be denied
798+
SELECT lo_put(1002, 1, 'abcd'); -- to be denied
795799
SELECT lo_unlink(1002); -- to be denied
796800
SELECT lo_export(1001, '/dev/null'); -- to be denied
797801

0 commit comments

Comments
 (0)