Package: release.debian.org Severity: normal Tags: jessie User: release.debian....@packages.debian.org Usertags: pu
Hi, I would like to upload postgresql-common/165+deb8u2 with the diff quoted below to jessie. It's fixing a data-loss bug, and a security issue. The issues are already addresses in unstable (both in 178). Is that ok? diff --git a/debian/changelog b/debian/changelog index 0d6bd4f..1d583cb 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,15 @@ +postgresql-common (165+deb8u2) jessie; urgency=medium + + * pg_upgradecluster: Properly upgrade databases with non-login role owners. + (Closes: #614374, #838812) + * pg_ctlcluster, t/020_create_sql_remove.t: Protect against symlink in + /var/log/postgresql/ allowing the creation of arbitrary files elsewhere. + Discovered by Dawid Golunski, thanks! (CVE-2016-1255) + * t/TestLib.pm: Cherry-pick program_ok() from master for use in + t/020_create_sql_remove.t. + + -- Christoph Berg <m...@debian.org> Sun, 01 Jan 2017 18:48:30 +0100 + postgresql-common (165+deb8u1) jessie; urgency=medium * pg_upgradecluster: Set default dynamic_shared_memory_type = mmap. diff --git a/pg_ctlcluster b/pg_ctlcluster index 924f878..d2bb897 100755 --- a/pg_ctlcluster +++ b/pg_ctlcluster @@ -23,7 +23,7 @@ use warnings; use Getopt::Long; use POSIX qw/setsid dup2 setlocale LC_ALL :sys_wait_h/; use PgCommon; -use Fcntl 'SEEK_SET'; +use Fcntl qw(SEEK_SET O_RDWR O_CREAT O_EXCL); my ($version, $cluster, $pg_ctl, $force); my (@postmaster_auxoptions, @pg_ctl_opts_from_cli); @@ -394,17 +394,20 @@ if ($> == 0 && ! -e '/var/log/postgresql' && # recreate missing log file if ($action ne 'stop' && $info{'logfile'} && ! -e $info{'logfile'}) { - open L, '>', $info{'logfile'} or + if ($> == 0) { # drop privileges; this is important if logfile + # was determined via an /etc/postgresql/.../log symlink + change_ugid $info{'owneruid'}, $info{'ownergid'}; + } + sysopen (L, $info{'logfile'}, O_RDWR|O_CREAT|O_EXCL) or error 'Could not create log file ' . $info{'logfile'}; + close L; chmod 0640, $info{'logfile'}; - my $g; + $< = $> = 0; # will silently fail if we were not root before, that's intended + $( = $) = 0; if ($info{'owneruid'} < 500) { - $g = (getgrnam 'adm')[2]; - } else { - $g = $info{'ownergid'}; + my $g = (getgrnam 'adm')[2]; + chown $info{'owneruid'}, $g, $info{'logfile'} if (defined $g); } - chown $info{'owneruid'}, $g, $info{'logfile'}; - close L; } # recreate /var/run/postgresql diff --git a/pg_upgradecluster b/pg_upgradecluster index 876a0af..04c59c6 100755 --- a/pg_upgradecluster +++ b/pg_upgradecluster @@ -433,18 +433,16 @@ if (!fork) { error 'automatic upgrade of tablespaces is not supported'; } - # get list of databases, owners, and allowed connections + # get list of databases (value = datallowconn) my %databases; open F, '-|', $oldpsql, '-h', $oldsocket, '-p', $info{'port'}, '-F|', '-d', 'template1', '-Atc', - 'SELECT datname, datallowconn, pg_catalog.pg_encoding_to_char(encoding), usename FROM pg_database, pg_user WHERE datdba = usesysid' or + 'SELECT datname, datallowconn FROM pg_database' or error 'Could not get pg_database list'; while (<F>) { chomp; - my ($n, $a, $e, $o) = split '\|'; - ($o) = $o =~ /^(.*)$/; # untaint - ($e) = $e =~ /^([\w_]+)$/; # untaint - $databases{$n} = [$a eq 't', $o, $e]; + my ($n, $a) = split '\|'; + $databases{$n} = ($a eq 't'); } close F; error 'could not get list of databases' if $?; @@ -453,7 +451,7 @@ if (!fork) { for my $db (keys %databases) { next if $db eq 'template0'; - unless (${$databases{$db}}[0]) { + unless ($databases{$db}) { print "Temporarily enabling access to database $db\n"; (system $oldpsql, '-h', $oldsocket, '-p', $info{'port'}, '-q', '-d', 'template1', '-c', @@ -546,8 +544,8 @@ if (!fork) { '-d', $db, '-c', 'ANALYZE') == 0 or error 'Could not ANALZYE database'; - unless (${$databases{$db}}[0]) { - print "Disabling access to database $db\n"; + unless ($databases{$db}) { + print "Disabling access to database $db again\n"; (system $oldpsql, '-h', $oldsocket, '-p', $info{'port'}, '-q', '-d', 'template1', '-c', "BEGIN READ WRITE; UPDATE pg_database SET datallowconn = 'f' where datname = '$db'; COMMIT") == 0 or diff --git a/t/020_create_sql_remove.t b/t/020_create_sql_remove.t index 457bf9a..f71b4cf 100644 --- a/t/020_create_sql_remove.t +++ b/t/020_create_sql_remove.t @@ -10,7 +10,7 @@ use lib 't'; use TestLib; use PgCommon; -use Test::More tests => 127 * ($#MAJORS+1); +use Test::More tests => 131 * ($#MAJORS+1); sub check_major { my $v = $_[0]; @@ -142,6 +142,15 @@ sub check_major { PgCommon::disable_conf_value $v, 'main', 'postgresql.conf', 'log_filename', ''; unlink "/etc/postgresql/$v/main/log"; + # check that log creation does not escalate privileges + program_ok 'root', "pg_ctlcluster $v main stop", 0, 'stopping cluster'; + unlink $default_log; + symlink "/etc/postgres-hack", $default_log; + program_ok 'root', "pg_ctlcluster $v main start", 1, 'starting cluster with rouge /var/log/postgresql symlink fails'; + ok !-f "/etc/postgres-hack", "/etc/postgres-hack was not created"; + unlink $default_log; + program_ok 'root', "pg_ctlcluster $v main start", 0, 'restarting cluster'; + # verify that the postmaster does not have an associated terminal unlike_program_out 0, 'ps -o tty -U postgres h', 0, qr/tty|pts/, 'postmaster processes do not have an associated terminal'; diff --git a/t/TestLib.pm b/t/TestLib.pm index 2c9a9d0..62f2268 100644 --- a/t/TestLib.pm +++ b/t/TestLib.pm @@ -22,7 +22,7 @@ use PgCommon qw/get_versions change_ugid/; our $VERSION = 1.00; our @ISA = ('Exporter'); our @EXPORT = qw/ps ok_dir exec_as deb_installed rpm_installed package_version - version_ge is_program_out like_program_out unlike_program_out pidof pid_env check_clean + version_ge program_ok is_program_out like_program_out unlike_program_out pidof pid_env check_clean @ALL_MAJORS @MAJORS $delay/; our @ALL_MAJORS = sort (get_versions()); # not affected by PG_VERSIONS/-v @@ -177,6 +177,16 @@ sub exec_as { return $result; } +# Execute a command as a particular user, and check the exit code +# Arguments: <user> <command> [<expected exit code>] [<description>] +sub program_ok { + my ($user, $cmd, $exit, $description) = @_; + $exit ||= 0; + $description ||= $cmd; + my $outref; + ok ((exec_as $user, $cmd, \$outref, $exit) == $exit, $description); +} + # Execute a command as a particular user, and check the exit code and output # (merged stdout/stderr). # Arguments: <user> <command> <expected exit code> <expected output> [<description>] Thanks, Christoph
signature.asc
Description: PGP signature