~ubuntu-branches/ubuntu/utopic/postgresql-9.1/utopic

« back to all changes in this revision

Viewing changes to src/backend/commands/async.c

  • Committer: Package Import Robot
  • Author(s): Martin Pitt, CVE-2013-1899
  • Date: 2013-04-02 10:26:14 UTC
  • mfrom: (1.1.11)
  • Revision ID: package-import@ubuntu.com-20130402102614-vyijoo0ba7ulfyom
Tags: 9.1.9-1
* Urgency high because of critical remote data destruction vulnerability.
* New upstream security/bug fix release:
  - Fix insecure parsing of server command-line switches.
    A connection request containing a database name that begins with
    "-" could be crafted to damage or destroy files within the server's
    data directory, even if the request is eventually rejected.
    [CVE-2013-1899] (Closes: #704479)
  - Reset OpenSSL randomness state in each postmaster child process.
    This avoids a scenario wherein random numbers generated by
    "contrib/pgcrypto" functions might be relatively easy for another
    database user to guess. The risk is only significant when the
    postmaster is configured with ssl = on but most connections don't
    use SSL encryption. [CVE-2013-1900]
  - Make REPLICATION privilege checks test current user not
    authenticated user.
    An unprivileged database user could exploit this mistake to call
    pg_start_backup() or pg_stop_backup(), thus possibly interfering
    with creation of routine backups. [CVE-2013-1901]
  - Fix GiST indexes to not use "fuzzy" geometric comparisons when it's
    not appropriate to do so.
    The core geometric types perform comparisons using "fuzzy"
    equality, but gist_box_same must do exact comparisons, else GiST
    indexes using it might become inconsistent. After installing this
    update, users should "REINDEX" any GiST indexes on box, polygon,
    circle, or point columns, since all of these use gist_box_same.
  - Fix erroneous range-union and penalty logic in GiST indexes that
    use "contrib/btree_gist" for variable-width data types, that is
    text, bytea, bit, and numeric columns.
    These errors could result in inconsistent indexes in which some
    keys that are present would not be found by searches, and also in
    useless index bloat. Users are advised to "REINDEX" such indexes
    after installing this update.
  - Fix bugs in GiST page splitting code for multi-column indexes.
    These errors could result in inconsistent indexes in which some
    keys that are present would not be found by searches, and also in
    indexes that are unnecessarily inefficient to search. Users are
    advised to "REINDEX" multi-column GiST indexes after installing
    this update.
  - See HISTORY/changelog.gz for details about the other bug fixes.
* Bump Standards-Version to 3.9.4 (no changes necessary).

Show diffs side-by-side

added added

removed removed

Lines of Context:
349
349
/* True if we've registered an on_shmem_exit cleanup */
350
350
static bool unlistenExitRegistered = false;
351
351
 
 
352
/* True if we're currently registered as a listener in asyncQueueControl */
 
353
static bool amRegisteredListener = false;
 
354
 
352
355
/* has this backend sent notifications in the current transaction? */
353
356
static bool backendHasSentNotifications = false;
354
357
 
355
 
/* has this backend executed its first LISTEN in the current transaction? */
356
 
static bool backendHasExecutedInitialListen = false;
357
 
 
358
358
/* GUC parameter */
359
359
bool            Trace_notify = false;
360
360
 
745
745
Async_UnlistenOnExit(int code, Datum arg)
746
746
{
747
747
        Exec_UnlistenAllCommit();
 
748
        asyncQueueUnregister();
748
749
}
749
750
 
750
751
/*
789
790
        if (Trace_notify)
790
791
                elog(DEBUG1, "PreCommit_Notify");
791
792
 
792
 
        Assert(backendHasExecutedInitialListen == false);
793
 
 
794
793
        /* Preflight for any pending listen/unlisten actions */
795
794
        foreach(p, pendingActions)
796
795
        {
913
912
                }
914
913
        }
915
914
 
916
 
        /*
917
 
         * If we did an initial LISTEN, listenChannels now has the entry, so we no
918
 
         * longer need or want the flag to be set.
919
 
         */
920
 
        backendHasExecutedInitialListen = false;
 
915
        /* If no longer listening to anything, get out of listener array */
 
916
        if (amRegisteredListener && listenChannels == NIL)
 
917
                asyncQueueUnregister();
921
918
 
922
919
        /* And clean up */
923
920
        ClearPendingActionsAndNotifies();
935
932
         * Nothing to do if we are already listening to something, nor if we
936
933
         * already ran this routine in this transaction.
937
934
         */
938
 
        if (listenChannels != NIL || backendHasExecutedInitialListen)
 
935
        if (amRegisteredListener)
939
936
                return;
940
937
 
941
938
        if (Trace_notify)
942
939
                elog(DEBUG1, "Exec_ListenPreCommit(%d)", MyProcPid);
943
940
 
944
941
        /*
945
 
         * We need this variable to detect an aborted initial LISTEN. In that case
946
 
         * we would set up our pointer but not listen on any channel. This flag
947
 
         * gets cleared in AtCommit_Notify or AtAbort_Notify().
948
 
         */
949
 
        backendHasExecutedInitialListen = true;
950
 
 
951
 
        /*
952
942
         * Before registering, make sure we will unlisten before dying. (Note:
953
943
         * this action does not get undone if we abort later.)
954
944
         */
971
961
        QUEUE_BACKEND_PID(MyBackendId) = MyProcPid;
972
962
        LWLockRelease(AsyncQueueLock);
973
963
 
 
964
        /* Now we are listed in the global array, so remember we're listening */
 
965
        amRegisteredListener = true;
 
966
 
974
967
        /*
975
968
         * Try to move our pointer forward as far as possible. This will skip over
976
969
         * already-committed notifications. Still, we could get notifications that
1043
1036
         * We do not complain about unlistening something not being listened;
1044
1037
         * should we?
1045
1038
         */
1046
 
 
1047
 
        /* If no longer listening to anything, get out of listener array */
1048
 
        if (listenChannels == NIL)
1049
 
                asyncQueueUnregister();
1050
1039
}
1051
1040
 
1052
1041
/*
1062
1051
 
1063
1052
        list_free_deep(listenChannels);
1064
1053
        listenChannels = NIL;
1065
 
 
1066
 
        asyncQueueUnregister();
1067
1054
}
1068
1055
 
1069
1056
/*
1181
1168
 
1182
1169
        Assert(listenChannels == NIL);          /* else caller error */
1183
1170
 
 
1171
        if (!amRegisteredListener)                      /* nothing to do */
 
1172
                return;
 
1173
 
1184
1174
        LWLockAcquire(AsyncQueueLock, LW_SHARED);
1185
1175
        /* check if entry is valid and oldest ... */
1186
1176
        advanceTail = (MyProcPid == QUEUE_BACKEND_PID(MyBackendId)) &&
1189
1179
        QUEUE_BACKEND_PID(MyBackendId) = InvalidPid;
1190
1180
        LWLockRelease(AsyncQueueLock);
1191
1181
 
 
1182
        /* mark ourselves as no longer listed in the global array */
 
1183
        amRegisteredListener = false;
 
1184
 
1192
1185
        /* If we were the laziest backend, try to advance the tail pointer */
1193
1186
        if (advanceTail)
1194
1187
                asyncQueueAdvanceTail();
1545
1538
AtAbort_Notify(void)
1546
1539
{
1547
1540
        /*
1548
 
         * If we LISTEN but then roll back the transaction we have set our pointer
1549
 
         * but have not made any entry in listenChannels. In that case, remove our
1550
 
         * pointer again.
 
1541
         * If we LISTEN but then roll back the transaction after PreCommit_Notify,
 
1542
         * we have registered as a listener but have not made any entry in
 
1543
         * listenChannels.  In that case, deregister again.
1551
1544
         */
1552
 
        if (backendHasExecutedInitialListen)
1553
 
        {
1554
 
                /*
1555
 
                 * Checking listenChannels should be redundant but it can't hurt doing
1556
 
                 * it for safety reasons.
1557
 
                 */
1558
 
                if (listenChannels == NIL)
1559
 
                        asyncQueueUnregister();
1560
 
 
1561
 
                backendHasExecutedInitialListen = false;
1562
 
        }
 
1545
        if (amRegisteredListener && listenChannels == NIL)
 
1546
                asyncQueueUnregister();
1563
1547
 
1564
1548
        /* And clean up */
1565
1549
        ClearPendingActionsAndNotifies();