mirror of
				https://github.com/postgres/postgres.git
				synced 2025-11-03 09:13:20 +03:00 
			
		
		
		
	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:
		@@ -898,6 +898,18 @@ 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));
 | 
			
		||||
 
 | 
			
		||||
@@ -1189,6 +1189,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 
 | 
			
		||||
--------
 | 
			
		||||
@@ -1284,6 +1292,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
 | 
			
		||||
 
 | 
			
		||||
@@ -753,6 +753,9 @@ SET SESSION AUTHORIZATION regressuser2;
 | 
			
		||||
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);
 | 
			
		||||
@@ -792,6 +795,7 @@ SET SESSION AUTHORIZATION regressuser4;
 | 
			
		||||
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
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user