Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit8f6278d

Browse files
committed
Put in place some defenses against being fooled by accidental match of
shared memory segment ID. If we can't access the existing shmem segment,it must not be relevant to our data directory. If we can access it,then attach to it and check for an actual match to the data directory.This should avoid some cases of failure-to-restart-after-boot withoutintroducing any significant risk of failing to detect a still-runningold backend.
1 parent58825b8 commit8f6278d

File tree

2 files changed

+91
-29
lines changed

2 files changed

+91
-29
lines changed

‎src/backend/port/sysv_shmem.c

Lines changed: 85 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
* Portions Copyright (c) 1994, Regents of the University of California
1111
*
1212
* IDENTIFICATION
13-
* $PostgreSQL: pgsql/src/backend/port/sysv_shmem.c,v 1.39 2004/10/13 01:25:11 neilc Exp $
13+
* $PostgreSQL: pgsql/src/backend/port/sysv_shmem.c,v 1.40 2004/11/09 21:30:13 tgl Exp $
1414
*
1515
*-------------------------------------------------------------------------
1616
*/
@@ -20,6 +20,7 @@
2020
#include<signal.h>
2121
#include<unistd.h>
2222
#include<sys/file.h>
23+
#include<sys/stat.h>
2324
#ifdefHAVE_SYS_IPC_H
2425
#include<sys/ipc.h>
2526
#endif
@@ -40,6 +41,12 @@ typedef int IpcMemoryId;/* shared memory ID returned by shmget(2) */
4041

4142
#defineIPCProtection(0600)/* access/modify by user only */
4243

44+
#ifdefSHM_SHARE_MMU/* use intimate shared memory on Solaris */
45+
#definePG_SHMAT_FLAGSSHM_SHARE_MMU
46+
#else
47+
#definePG_SHMAT_FLAGS0
48+
#endif
49+
4350

4451
unsigned longUsedShmemSegID=0;
4552
void*UsedShmemSegAddr=NULL;
@@ -135,16 +142,10 @@ InternalIpcMemoryCreate(IpcMemoryKey memKey, uint32 size)
135142
on_shmem_exit(IpcMemoryDelete,Int32GetDatum(shmid));
136143

137144
/* OK, should be able to attach to the segment */
138-
#ifdefSHM_SHARE_MMU
139-
/* use intimate shared memory on Solaris */
140-
memAddress=shmat(shmid,0,SHM_SHARE_MMU);
141-
#else
142-
143145
#ifdefEXEC_BACKEND
144-
memAddress=shmat(shmid,UsedShmemSegAddr,0);
146+
memAddress=shmat(shmid,UsedShmemSegAddr,PG_SHMAT_FLAGS);
145147
#else
146-
memAddress=shmat(shmid,NULL,0);
147-
#endif
148+
memAddress=shmat(shmid,NULL,PG_SHMAT_FLAGS);
148149
#endif
149150

150151
if (memAddress== (void*)-1)
@@ -188,20 +189,26 @@ IpcMemoryDelete(int status, Datum shmId)
188189
* PGSharedMemoryIsInUse
189190
*
190191
* Is a previously-existing shmem segment still existing and in use?
192+
*
193+
* The point of this exercise is to detect the case where a prior postmaster
194+
* crashed, but it left child backends that are still running. Therefore
195+
* we only care about shmem segments that are associated with the intended
196+
* DataDir. This is an important consideration since accidental matches of
197+
* shmem segment IDs are reasonably common.
191198
*/
192199
bool
193200
PGSharedMemoryIsInUse(unsigned longid1,unsigned longid2)
194201
{
195202
IpcMemoryIdshmId= (IpcMemoryId)id2;
196203
structshmid_dsshmStat;
204+
#ifndefWIN32
205+
structstatstatbuf;
206+
PGShmemHeader*hdr;
207+
#endif
197208

198209
/*
199210
* We detect whether a shared memory segment is in use by seeing
200211
* whether it (a) exists and (b) has any processes are attached to it.
201-
*
202-
* If we are unable to perform the stat operation for a reason other than
203-
* nonexistence of the segment (most likely, because it doesn't belong
204-
* to our userid), assume it is in use.
205212
*/
206213
if (shmctl(shmId,IPC_STAT,&shmStat)<0)
207214
{
@@ -212,13 +219,58 @@ PGSharedMemoryIsInUse(unsigned long id1, unsigned long id2)
212219
*/
213220
if (errno==EINVAL)
214221
return false;
215-
/* Else assume segment is in use */
222+
/*
223+
* EACCES implies that the segment belongs to some other userid,
224+
* which means it is not a Postgres shmem segment (or at least,
225+
* not one that is relevant to our data directory).
226+
*/
227+
if (errno==EACCES)
228+
return false;
229+
/*
230+
* Otherwise, we had better assume that the segment is in use.
231+
* The only likely case is EIDRM, which implies that the segment
232+
* has been IPC_RMID'd but there are still processes attached to it.
233+
*/
216234
return true;
217235
}
218-
/* If it has attached processes, it's in use */
219-
if (shmStat.shm_nattch!=0)
220-
return true;
221-
return false;
236+
237+
/* If it has no attached processes, it's not in use */
238+
if (shmStat.shm_nattch==0)
239+
return false;
240+
241+
/*
242+
* Try to attach to the segment and see if it matches our data directory.
243+
* This avoids shmid-conflict problems on machines that are running
244+
* several postmasters under the same userid. On Windows, which doesn't
245+
* have useful inode numbers, we can't do this so we punt and assume there
246+
* is a conflict.
247+
*/
248+
#ifndefWIN32
249+
if (stat(DataDir,&statbuf)<0)
250+
return true;/* if can't stat, be conservative */
251+
252+
hdr= (PGShmemHeader*)shmat(shmId,NULL,PG_SHMAT_FLAGS);
253+
254+
if (hdr== (PGShmemHeader*)-1)
255+
return true;/* if can't attach, be conservative */
256+
257+
if (hdr->magic!=PGShmemMagic||
258+
hdr->device!=statbuf.st_dev||
259+
hdr->inode!=statbuf.st_ino)
260+
{
261+
/*
262+
* It's either not a Postgres segment, or not one for my data
263+
* directory. In either case it poses no threat.
264+
*/
265+
shmdt((void*)hdr);
266+
return false;
267+
}
268+
269+
/* Trouble --- looks a lot like there's still live backends */
270+
shmdt((void*)hdr);
271+
#endif
272+
273+
return true;
222274
}
223275

224276

@@ -247,6 +299,9 @@ PGSharedMemoryCreate(uint32 size, bool makePrivate, int port)
247299
void*memAddress;
248300
PGShmemHeader*hdr;
249301
IpcMemoryIdshmid;
302+
#ifndefWIN32
303+
structstatstatbuf;
304+
#endif
250305

251306
#ifdefEXEC_BACKEND
252307
/* If Exec case, just attach and return the pointer */
@@ -345,6 +400,17 @@ PGSharedMemoryCreate(uint32 size, bool makePrivate, int port)
345400
hdr->creatorPID=getpid();
346401
hdr->magic=PGShmemMagic;
347402

403+
#ifndefWIN32
404+
/* Fill in the data directory ID info, too */
405+
if (stat(DataDir,&statbuf)<0)
406+
ereport(FATAL,
407+
(errcode_for_file_access(),
408+
errmsg("could not stat data directory \"%s\": %m",
409+
DataDir)));
410+
hdr->device=statbuf.st_dev;
411+
hdr->inode=statbuf.st_ino;
412+
#endif
413+
348414
/*
349415
* Initialize space allocation status for segment.
350416
*/
@@ -397,15 +463,7 @@ PGSharedMemoryAttach(IpcMemoryKey key, IpcMemoryId *shmid)
397463
if ((*shmid=shmget(key,sizeof(PGShmemHeader),0))<0)
398464
returnNULL;
399465

400-
hdr= (PGShmemHeader*)shmat(*shmid,
401-
UsedShmemSegAddr,
402-
#ifdefSHM_SHARE_MMU
403-
/* use intimate shared memory on Solaris */
404-
SHM_SHARE_MMU
405-
#else
406-
0
407-
#endif
408-
);
466+
hdr= (PGShmemHeader*)shmat(*shmid,UsedShmemSegAddr,PG_SHMAT_FLAGS);
409467

410468
if (hdr== (PGShmemHeader*)-1)
411469
returnNULL;/* failed: must be some other app's */

‎src/include/storage/pg_shmem.h

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
* Portions Copyright (c) 1996-2004, PostgreSQL Global Development Group
1818
* Portions Copyright (c) 1994, Regents of the University of California
1919
*
20-
* $PostgreSQL: pgsql/src/include/storage/pg_shmem.h,v 1.11 2004/08/29 04:13:10 momjian Exp $
20+
* $PostgreSQL: pgsql/src/include/storage/pg_shmem.h,v 1.12 2004/11/09 21:30:18 tgl Exp $
2121
*
2222
*-------------------------------------------------------------------------
2323
*/
@@ -27,10 +27,14 @@
2727
typedefstructPGShmemHeader/* standard header for all Postgres shmem */
2828
{
2929
int32magic;/* magic # to identify Postgres segments */
30-
#definePGShmemMagic679834892
30+
#definePGShmemMagic679834893
3131
pid_tcreatorPID;/* PID of creating process */
3232
uint32totalsize;/* total size of segment */
3333
uint32freeoffset;/* offset to first free space */
34+
#ifndefWIN32/* Windows doesn't have useful inode#s */
35+
dev_tdevice;/* device data directory is on */
36+
ino_tinode;/* inode number of data directory */
37+
#endif
3438
}PGShmemHeader;
3539

3640

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp