Skip to content

Commit 74686b6

Browse files
committed
Get rid of some unnecessary dependencies on DataDir: wherever possible,
the backend should rely on its working-directory setting instead. Also do some message-style police work in contrib/adminpack.
1 parent 62fe410 commit 74686b6

File tree

3 files changed

+83
-102
lines changed

3 files changed

+83
-102
lines changed

contrib/adminpack/adminpack.c

Lines changed: 56 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
* Author: Andreas Pflug <pgadmin@pse-consulting.de>
99
*
1010
* IDENTIFICATION
11-
* $PostgreSQL: pgsql/contrib/adminpack/adminpack.c,v 1.7 2006/10/20 00:59:03 tgl Exp $
11+
* $PostgreSQL: pgsql/contrib/adminpack/adminpack.c,v 1.8 2006/11/06 03:06:40 tgl Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -60,43 +60,47 @@ typedef struct
6060
*/
6161

6262
/*
63-
* Return an absolute path. Argument may be absolute or
64-
* relative to the DataDir.
63+
* Convert a "text" filename argument to C string, and check it's allowable.
64+
*
65+
* Filename may be absolute or relative to the DataDir, but we only allow
66+
* absolute paths that match DataDir or Log_directory.
6567
*/
6668
static char *
67-
absClusterPath(text *arg, bool logAllowed)
69+
convert_and_check_filename(text *arg, bool logAllowed)
6870
{
69-
char *filename;
70-
int len = VARSIZE(arg) - VARHDRSZ;
71-
int dlen = strlen(DataDir);
71+
int input_len = VARSIZE(arg) - VARHDRSZ;
72+
char *filename = palloc(input_len + 1);
73+
74+
memcpy(filename, VARDATA(arg), input_len);
75+
filename[input_len] = '\0';
7276

73-
filename = palloc(len + 1);
74-
memcpy(filename, VARDATA(arg), len);
75-
filename[len] = 0;
77+
canonicalize_path(filename); /* filename can change length here */
7678

77-
if (strstr(filename, "..") != NULL)
79+
/* Disallow ".." in the path */
80+
if (path_contains_parent_reference(filename))
7881
ereport(ERROR,
7982
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
80-
(errmsg("No .. allowed in filenames"))));
83+
(errmsg("reference to parent directory (\"..\") not allowed"))));
8184

8285
if (is_absolute_path(filename))
8386
{
84-
if (logAllowed && !strncmp(filename, Log_directory, strlen(Log_directory)))
87+
/* Allow absolute references within DataDir */
88+
if (path_is_prefix_of_path(DataDir, filename))
89+
return filename;
90+
/* The log directory might be outside our datadir, but allow it */
91+
if (logAllowed &&
92+
is_absolute_path(Log_directory) &&
93+
path_is_prefix_of_path(Log_directory, filename))
8594
return filename;
86-
if (strncmp(filename, DataDir, dlen))
87-
ereport(ERROR,
88-
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
89-
(errmsg("Absolute path not allowed"))));
9095

91-
return filename;
96+
ereport(ERROR,
97+
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
98+
(errmsg("absolute path not allowed"))));
99+
return NULL; /* keep compiler quiet */
92100
}
93101
else
94102
{
95-
char *absname = palloc(dlen + len + 2);
96-
97-
sprintf(absname, "%s/%s", DataDir, filename);
98-
pfree(filename);
99-
return absname;
103+
return filename;
100104
}
101105
}
102106

@@ -129,29 +133,28 @@ pg_file_write(PG_FUNCTION_ARGS)
129133

130134
requireSuperuser();
131135

132-
filename = absClusterPath(PG_GETARG_TEXT_P(0), false);
136+
filename = convert_and_check_filename(PG_GETARG_TEXT_P(0), false);
133137
data = PG_GETARG_TEXT_P(1);
134138

135-
if (PG_ARGISNULL(2) || !PG_GETARG_BOOL(2))
139+
if (!PG_GETARG_BOOL(2))
136140
{
137141
struct stat fst;
138142

139143
if (stat(filename, &fst) >= 0)
140144
ereport(ERROR,
141145
(ERRCODE_DUPLICATE_FILE,
142-
errmsg("file %s exists", filename)));
146+
errmsg("file \"%s\" exists", filename)));
143147

144148
f = fopen(filename, "wb");
145149
}
146150
else
147151
f = fopen(filename, "ab");
148152

149153
if (!f)
150-
{
151154
ereport(ERROR,
152155
(errcode_for_file_access(),
153-
errmsg("could open file %s for writing: %m", filename)));
154-
}
156+
errmsg("could not open file \"%s\" for writing: %m",
157+
filename)));
155158

156159
if (VARSIZE(data) != 0)
157160
{
@@ -160,7 +163,7 @@ pg_file_write(PG_FUNCTION_ARGS)
160163
if (count != VARSIZE(data) - VARHDRSZ)
161164
ereport(ERROR,
162165
(errcode_for_file_access(),
163-
errmsg("error writing file %s: %m", filename)));
166+
errmsg("could not write file \"%s\": %m", filename)));
164167
}
165168
fclose(f);
166169

@@ -181,18 +184,18 @@ pg_file_rename(PG_FUNCTION_ARGS)
181184
if (PG_ARGISNULL(0) || PG_ARGISNULL(1))
182185
PG_RETURN_NULL();
183186

184-
fn1 = absClusterPath(PG_GETARG_TEXT_P(0), false);
185-
fn2 = absClusterPath(PG_GETARG_TEXT_P(1), false);
187+
fn1 = convert_and_check_filename(PG_GETARG_TEXT_P(0), false);
188+
fn2 = convert_and_check_filename(PG_GETARG_TEXT_P(1), false);
186189
if (PG_ARGISNULL(2))
187190
fn3 = 0;
188191
else
189-
fn3 = absClusterPath(PG_GETARG_TEXT_P(2), false);
192+
fn3 = convert_and_check_filename(PG_GETARG_TEXT_P(2), false);
190193

191194
if (access(fn1, W_OK) < 0)
192195
{
193196
ereport(WARNING,
194197
(errcode_for_file_access(),
195-
errmsg("file %s not accessible: %m", fn1)));
198+
errmsg("file \"%s\" is not accessible: %m", fn1)));
196199

197200
PG_RETURN_BOOL(false);
198201
}
@@ -201,18 +204,18 @@ pg_file_rename(PG_FUNCTION_ARGS)
201204
{
202205
ereport(WARNING,
203206
(errcode_for_file_access(),
204-
errmsg("file %s not accessible: %m", fn2)));
207+
errmsg("file \"%s\" is not accessible: %m", fn2)));
205208

206209
PG_RETURN_BOOL(false);
207210
}
208211

209-
210212
rc = access(fn3 ? fn3 : fn2, 2);
211213
if (rc >= 0 || errno != ENOENT)
212214
{
213215
ereport(ERROR,
214216
(ERRCODE_DUPLICATE_FILE,
215-
errmsg("cannot rename to target file %s", fn3 ? fn3 : fn2)));
217+
errmsg("cannot rename to target file \"%s\"",
218+
fn3 ? fn3 : fn2)));
216219
}
217220

218221
if (fn3)
@@ -221,37 +224,37 @@ pg_file_rename(PG_FUNCTION_ARGS)
221224
{
222225
ereport(ERROR,
223226
(errcode_for_file_access(),
224-
errmsg("could not rename %s to %s: %m", fn2, fn3)));
227+
errmsg("could not rename \"%s\" to \"%s\": %m",
228+
fn2, fn3)));
225229
}
226230
if (rename(fn1, fn2) != 0)
227231
{
228232
ereport(WARNING,
229233
(errcode_for_file_access(),
230-
errmsg("could not rename %s to %s: %m", fn1, fn2)));
234+
errmsg("could not rename \"%s\" to \"%s\": %m",
235+
fn1, fn2)));
231236

232237
if (rename(fn3, fn2) != 0)
233238
{
234239
ereport(ERROR,
235240
(errcode_for_file_access(),
236-
errmsg("could not rename %s back to %s: %m", fn3, fn2)));
241+
errmsg("could not rename \"%s\" back to \"%s\": %m",
242+
fn3, fn2)));
237243
}
238244
else
239245
{
240246
ereport(ERROR,
241247
(ERRCODE_UNDEFINED_FILE,
242-
errmsg("renaming %s to %s was reverted", fn2, fn3)));
243-
248+
errmsg("renaming \"%s\" to \"%s\" was reverted",
249+
fn2, fn3)));
244250
}
245251
}
246252
}
247253
else if (rename(fn1, fn2) != 0)
248254
{
249-
ereport(WARNING,
250-
(errcode_for_file_access(),
251-
errmsg("renaming %s to %s %m", fn1, fn2)));
252255
ereport(ERROR,
253256
(errcode_for_file_access(),
254-
errmsg("could not rename %s to %s: %m", fn1, fn2)));
257+
errmsg("could not rename \"%s\" to \"%s\": %m", fn1, fn2)));
255258
}
256259

257260
PG_RETURN_BOOL(true);
@@ -265,7 +268,7 @@ pg_file_unlink(PG_FUNCTION_ARGS)
265268

266269
requireSuperuser();
267270

268-
filename = absClusterPath(PG_GETARG_TEXT_P(0), false);
271+
filename = convert_and_check_filename(PG_GETARG_TEXT_P(0), false);
269272

270273
if (access(filename, W_OK) < 0)
271274
{
@@ -274,15 +277,14 @@ pg_file_unlink(PG_FUNCTION_ARGS)
274277
else
275278
ereport(ERROR,
276279
(errcode_for_file_access(),
277-
errmsg("file %s not accessible: %m", filename)));
278-
280+
errmsg("file \"%s\" is not accessible: %m", filename)));
279281
}
280282

281283
if (unlink(filename) < 0)
282284
{
283285
ereport(WARNING,
284286
(errcode_for_file_access(),
285-
errmsg("could not unlink file %s: %m", filename)));
287+
errmsg("could not unlink file \"%s\": %m", filename)));
286288

287289
PG_RETURN_BOOL(false);
288290
}
@@ -316,13 +318,7 @@ pg_logdir_ls(PG_FUNCTION_ARGS)
316318
oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
317319

318320
fctx = palloc(sizeof(directory_fctx));
319-
if (is_absolute_path(Log_directory))
320-
fctx->location = pstrdup(Log_directory);
321-
else
322-
{
323-
fctx->location = palloc(strlen(DataDir) + strlen(Log_directory) + 2);
324-
sprintf(fctx->location, "%s/%s", DataDir, Log_directory);
325-
}
321+
326322
tupdesc = CreateTemplateTupleDesc(2, false);
327323
TupleDescInitEntry(tupdesc, (AttrNumber) 1, "starttime",
328324
TIMESTAMPOID, -1, 0);
@@ -331,12 +327,14 @@ pg_logdir_ls(PG_FUNCTION_ARGS)
331327

332328
funcctx->attinmeta = TupleDescGetAttInMetadata(tupdesc);
333329

330+
fctx->location = pstrdup(Log_directory);
334331
fctx->dirdesc = AllocateDir(fctx->location);
335332

336333
if (!fctx->dirdesc)
337334
ereport(ERROR,
338335
(errcode_for_file_access(),
339-
errmsg("%s is not browsable: %m", fctx->location)));
336+
errmsg("could not read directory \"%s\": %m",
337+
fctx->location)));
340338

341339
funcctx->user_fctx = fctx;
342340
MemoryContextSwitchTo(oldcontext);

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy