~ubuntu-branches/ubuntu/oneiric/postgresql-9.1/oneiric-security

« back to all changes in this revision

Viewing changes to src/backend/storage/smgr/smgr.c

  • Committer: Package Import Robot
  • Author(s): Martin Pitt
  • Date: 2013-02-05 18:13:52 UTC
  • mfrom: (1.1.10) (10.1.5 oneiric-proposed)
  • Revision ID: package-import@ubuntu.com-20130205181352-3kw4f94ilqklzm7c
Tags: 9.1.8-0ubuntu11.10
* New upstream security/bug fix release: (LP: #1116336)
  - Prevent execution of enum_recv from SQL
    The function was misdeclared, allowing a simple SQL command to crash the
    server.  In principle an attacker might be able to use it to examine the
    contents of server memory.  Our thanks to Sumit Soni (via Secunia SVCRP)
    for reporting this issue. (CVE-2013-0255)
  - See HISTORY/changelog.gz for the other bug fixes.

Show diffs side-by-side

added added

removed removed

Lines of Context:
78
78
 
79
79
/*
80
80
 * Each backend has a hashtable that stores all extant SMgrRelation objects.
 
81
 * In addition, "unowned" SMgrRelation objects are chained together in a list.
81
82
 */
82
83
static HTAB *SMgrRelationHash = NULL;
83
84
 
 
85
static SMgrRelation first_unowned_reln = NULL;
 
86
 
84
87
/* local function prototypes */
85
88
static void smgrshutdown(int code, Datum arg);
 
89
static void remove_from_unowned_list(SMgrRelation reln);
86
90
 
87
91
 
88
92
/*
126
130
/*
127
131
 *      smgropen() -- Return an SMgrRelation object, creating it if need be.
128
132
 *
129
 
 *              This does not attempt to actually open the object.
 
133
 *              This does not attempt to actually open the underlying file.
130
134
 */
131
135
SMgrRelation
132
136
smgropen(RelFileNode rnode, BackendId backend)
146
150
                ctl.hash = tag_hash;
147
151
                SMgrRelationHash = hash_create("smgr relation table", 400,
148
152
                                                                           &ctl, HASH_ELEM | HASH_FUNCTION);
 
153
                first_unowned_reln = NULL;
149
154
        }
150
155
 
151
156
        /* Look up or create an entry */
165
170
                reln->smgr_targblock = InvalidBlockNumber;
166
171
                reln->smgr_fsm_nblocks = InvalidBlockNumber;
167
172
                reln->smgr_vm_nblocks = InvalidBlockNumber;
168
 
                reln->smgr_transient = false;
169
173
                reln->smgr_which = 0;   /* we only have md.c at present */
170
174
 
171
175
                /* mark it not open */
172
176
                for (forknum = 0; forknum <= MAX_FORKNUM; forknum++)
173
177
                        reln->md_fd[forknum] = NULL;
 
178
 
 
179
                /* place it at head of unowned list (to make smgrsetowner cheap) */
 
180
                reln->next_unowned_reln = first_unowned_reln;
 
181
                first_unowned_reln = reln;
174
182
        }
175
 
        else
176
 
                /* if it was transient before, it no longer is */
177
 
                reln->smgr_transient = false;
178
183
 
179
184
        return reln;
180
185
}
181
186
 
182
187
/*
183
 
 * smgrsettransient() -- mark an SMgrRelation object as transaction-bound
184
 
 *
185
 
 * The main effect of this is that all opened files are marked to be
186
 
 * kernel-level closed (but not necessarily VFD-closed) when the current
187
 
 * transaction ends.
188
 
 */
189
 
void
190
 
smgrsettransient(SMgrRelation reln)
191
 
{
192
 
        reln->smgr_transient = true;
193
 
}
194
 
 
195
 
/*
196
188
 * smgrsetowner() -- Establish a long-lived reference to an SMgrRelation object
197
189
 *
198
190
 * There can be only one owner at a time; this is sufficient since currently
201
193
void
202
194
smgrsetowner(SMgrRelation *owner, SMgrRelation reln)
203
195
{
 
196
        /* We don't currently support "disowning" an SMgrRelation here */
 
197
        Assert(owner != NULL);
 
198
 
204
199
        /*
205
200
         * First, unhook any old owner.  (Normally there shouldn't be any, but it
206
201
         * seems possible that this can happen during swap_relation_files()
207
202
         * depending on the order of processing.  It's ok to close the old
208
203
         * relcache entry early in that case.)
 
204
         *
 
205
         * If there isn't an old owner, then the reln should be in the unowned
 
206
         * list, and we need to remove it.
209
207
         */
210
208
        if (reln->smgr_owner)
211
209
                *(reln->smgr_owner) = NULL;
 
210
        else
 
211
                remove_from_unowned_list(reln);
212
212
 
213
213
        /* Now establish the ownership relationship. */
214
214
        reln->smgr_owner = owner;
216
216
}
217
217
 
218
218
/*
 
219
 * remove_from_unowned_list -- unlink an SMgrRelation from the unowned list
 
220
 *
 
221
 * If the reln is not present in the list, nothing happens.  Typically this
 
222
 * would be caller error, but there seems no reason to throw an error.
 
223
 *
 
224
 * In the worst case this could be rather slow; but in all the cases that seem
 
225
 * likely to be performance-critical, the reln being sought will actually be
 
226
 * first in the list.  Furthermore, the number of unowned relns touched in any
 
227
 * one transaction shouldn't be all that high typically.  So it doesn't seem
 
228
 * worth expending the additional space and management logic needed for a
 
229
 * doubly-linked list.
 
230
 */
 
231
static void
 
232
remove_from_unowned_list(SMgrRelation reln)
 
233
{
 
234
        SMgrRelation *link;
 
235
        SMgrRelation cur;
 
236
 
 
237
        for (link = &first_unowned_reln, cur = *link;
 
238
                 cur != NULL;
 
239
                 link = &cur->next_unowned_reln, cur = *link)
 
240
        {
 
241
                if (cur == reln)
 
242
                {
 
243
                        *link = cur->next_unowned_reln;
 
244
                        cur->next_unowned_reln = NULL;
 
245
                        break;
 
246
                }
 
247
        }
 
248
}
 
249
 
 
250
/*
219
251
 *      smgrexists() -- Does the underlying file for a fork exist?
220
252
 */
221
253
bool
238
270
 
239
271
        owner = reln->smgr_owner;
240
272
 
 
273
        if (!owner)
 
274
                remove_from_unowned_list(reln);
 
275
 
241
276
        if (hash_search(SMgrRelationHash,
242
277
                                        (void *) &(reln->smgr_rnode),
243
278
                                        HASH_REMOVE, NULL) == NULL)
563
598
                        (*(smgrsw[i].smgr_post_ckpt)) ();
564
599
        }
565
600
}
 
601
 
 
602
/*
 
603
 * AtEOXact_SMgr
 
604
 *
 
605
 * This routine is called during transaction commit or abort (it doesn't
 
606
 * particularly care which).  All transient SMgrRelation objects are closed.
 
607
 *
 
608
 * We do this as a compromise between wanting transient SMgrRelations to
 
609
 * live awhile (to amortize the costs of blind writes of multiple blocks)
 
610
 * and needing them to not live forever (since we're probably holding open
 
611
 * a kernel file descriptor for the underlying file, and we need to ensure
 
612
 * that gets closed reasonably soon if the file gets deleted).
 
613
 */
 
614
void
 
615
AtEOXact_SMgr(void)
 
616
{
 
617
        /*
 
618
         * Zap all unowned SMgrRelations.  We rely on smgrclose() to remove each
 
619
         * one from the list.
 
620
         */
 
621
        while (first_unowned_reln != NULL)
 
622
        {
 
623
                Assert(first_unowned_reln->smgr_owner == NULL);
 
624
                smgrclose(first_unowned_reln);
 
625
        }
 
626
}