Hi,

I noticed the Debian postgresql-common instance management wrappers do
not work properly on the Hurd. If an instance is started via the
pg_ctcluster wrapper (which is written in perl) via sudo, the wrapper
properly changes uid/gid of the resulting processes to postgres, but
then the postgres user cannot send signals to it:

|postgres@debian:~$ ps -ef | grep ^postgres.*17.main | head -1
|postgres 14971     1   -  0:00.07 /usr/lib/postgresql/17/bin/postgres -D 
/var/lib/postgresql/17/main -c 
config_file=/etc/postgresql/17/main/postgresql.conf
|postgres@debian:~$ LANG=C kill -s HUP 14971
|-bash: kill: (14971) - Operation not permitted

I can reproduce it with the attached minimal Perl script (101 is the
postgres uid/gid on my Hurd VM), which exhibits the same behaviour as
the pg_ctlcluster wrapper on the Hurd but works on Linux.

So I thought this was a bug in the Hurd Perl code, but then I ran the
perl script under strace on Linux, and it calls the following relevant
syscalls:

|setregid(101, -1)                       = 0
|setreuid(101, -1)                       = 0
|setresuid(-1, 101, -1)                  = 0

If I run those in a minimal C program (also attached), I can reproduce
the problem in C as well. That program issues to following auth_makeauth
calls via rpctrace:

|  8<--39(pid16773)->auth_makeauth ( 0 {0 0 1000} 0 {101 0}) = 0    
52<--47(pid16773)
|  52<--47(pid16773)->auth_makeauth ( 0 {101 0 1000} 0 {101 0}) = 0    
40<--62(pid16773)
|  40<--62(pid16773)->auth_makeauth ( 101 {101 0 1000} 0 {101 0}) = 0    
61<--58(pid16773)

So is this a bug or just undefined behaviour in auth?


Michael
#!/bin/perl

my $uid = 101; # postgres pid
my $gid = 101; # postgres gid

print("switching to uid $uid and gid $gid\n");

$( = $gid;
$< = $uid;
$> = $uid;

die 'Could not change user id' if $< != $uid;
die 'Could not change group id' if $( != $gid;

print("euid: $>, uid: $<, gid: $( \n");

sleep(1000);
#define _GNU_SOURCE

#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>

int main (void) {

	setregid(101, -1);
	setreuid(101, -1);
	setresuid(-1, 101, -1);
	printf("euid: %d, uid: %d, gid: %d\n", geteuid(), getuid(), getgid());
	sleep(10000);
}

Reply via email to