Skip to content

Commit fa1e5af

Browse files
committed
Run pg_upgrade and pg_resetxlog with restricted token on Windows
As with initdb these programs need to run with a restricted token, and if they don't pg_upgrade will fail when run as a user with Adminstrator privileges. Backpatch to all live branches. On the development branch the code is reorganized so that the restricted token code is now in a single location. On the stable bramches a less invasive change is made by simply copying the relevant code to pg_upgrade.c and pg_resetxlog.c. Patches and bug report from Muhammad Asif Naeem, reviewed by Michael Paquier, slightly edited by me.
1 parent ed9cc2b commit fa1e5af

File tree

8 files changed

+235
-268
lines changed

8 files changed

+235
-268
lines changed

contrib/pg_upgrade/pg_upgrade.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
#include "postgres_fe.h"
3838

3939
#include "pg_upgrade.h"
40+
#include "common/restricted_token.h"
4041

4142
#ifdef HAVE_LANGINFO_H
4243
#include <langinfo.h>
@@ -75,6 +76,8 @@ main(int argc, char **argv)
7576

7677
parseCommandLine(argc, argv);
7778

79+
get_restricted_token(os_info.progname);
80+
7881
adjust_data_dir(&old_cluster);
7982
adjust_data_dir(&new_cluster);
8083

src/bin/initdb/initdb.c

Lines changed: 2 additions & 168 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@
6161
#endif
6262

6363
#include "catalog/catalog.h"
64+
#include "common/restricted_token.h"
6465
#include "common/username.h"
6566
#include "mb/pg_wchar.h"
6667
#include "getaddrinfo.h"
@@ -178,9 +179,6 @@ static char *authwarning = NULL;
178179
static const char *boot_options = "-F";
179180
static const char *backend_options = "--single -F -O -c search_path=pg_catalog -c exit_on_error=true";
180181

181-
#ifdef WIN32
182-
char *restrict_env;
183-
#endif
184182
static const char *subdirs[] = {
185183
"global",
186184
"pg_xlog",
@@ -260,7 +258,6 @@ static void check_locale_name(int category, const char *locale,
260258
static bool check_locale_encoding(const char *locale, int encoding);
261259
static void setlocales(void);
262260
static void usage(const char *progname);
263-
void get_restricted_token(void);
264261
void setup_pgdata(void);
265262
void setup_bin_paths(const char *argv0);
266263
void setup_data_file_paths(void);
@@ -272,12 +269,6 @@ void create_xlog_symlink(void);
272269
void warn_on_mount_point(int error);
273270
void initialize_data_directory(void);
274271

275-
276-
#ifdef WIN32
277-
static int CreateRestrictedProcess(char *cmd, PROCESS_INFORMATION *processInfo);
278-
#endif
279-
280-
281272
/*
282273
* macros for running pipes to postgres
283274
*/
@@ -2754,116 +2745,6 @@ setlocales(void)
27542745
#endif
27552746
}
27562747

2757-
#ifdef WIN32
2758-
typedef BOOL (WINAPI * __CreateRestrictedToken) (HANDLE, DWORD, DWORD, PSID_AND_ATTRIBUTES, DWORD, PLUID_AND_ATTRIBUTES, DWORD, PSID_AND_ATTRIBUTES, PHANDLE);
2759-
2760-
/* Windows API define missing from some versions of MingW headers */
2761-
#ifndef DISABLE_MAX_PRIVILEGE
2762-
#define DISABLE_MAX_PRIVILEGE 0x1
2763-
#endif
2764-
2765-
/*
2766-
* Create a restricted token and execute the specified process with it.
2767-
*
2768-
* Returns 0 on failure, non-zero on success, same as CreateProcess().
2769-
*
2770-
* On NT4, or any other system not containing the required functions, will
2771-
* NOT execute anything.
2772-
*/
2773-
static int
2774-
CreateRestrictedProcess(char *cmd, PROCESS_INFORMATION *processInfo)
2775-
{
2776-
BOOL b;
2777-
STARTUPINFO si;
2778-
HANDLE origToken;
2779-
HANDLE restrictedToken;
2780-
SID_IDENTIFIER_AUTHORITY NtAuthority = {SECURITY_NT_AUTHORITY};
2781-
SID_AND_ATTRIBUTES dropSids[2];
2782-
__CreateRestrictedToken _CreateRestrictedToken = NULL;
2783-
HANDLE Advapi32Handle;
2784-
2785-
ZeroMemory(&si, sizeof(si));
2786-
si.cb = sizeof(si);
2787-
2788-
Advapi32Handle = LoadLibrary("ADVAPI32.DLL");
2789-
if (Advapi32Handle != NULL)
2790-
{
2791-
_CreateRestrictedToken = (__CreateRestrictedToken) GetProcAddress(Advapi32Handle, "CreateRestrictedToken");
2792-
}
2793-
2794-
if (_CreateRestrictedToken == NULL)
2795-
{
2796-
fprintf(stderr, _("%s: WARNING: cannot create restricted tokens on this platform\n"), progname);
2797-
if (Advapi32Handle != NULL)
2798-
FreeLibrary(Advapi32Handle);
2799-
return 0;
2800-
}
2801-
2802-
/* Open the current token to use as a base for the restricted one */
2803-
if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ALL_ACCESS, &origToken))
2804-
{
2805-
fprintf(stderr, _("%s: could not open process token: error code %lu\n"), progname, GetLastError());
2806-
return 0;
2807-
}
2808-
2809-
/* Allocate list of SIDs to remove */
2810-
ZeroMemory(&dropSids, sizeof(dropSids));
2811-
if (!AllocateAndInitializeSid(&NtAuthority, 2,
2812-
SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0,
2813-
0, &dropSids[0].Sid) ||
2814-
!AllocateAndInitializeSid(&NtAuthority, 2,
2815-
SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_POWER_USERS, 0, 0, 0, 0, 0,
2816-
0, &dropSids[1].Sid))
2817-
{
2818-
fprintf(stderr, _("%s: could not allocate SIDs: error code %lu\n"),
2819-
progname, GetLastError());
2820-
return 0;
2821-
}
2822-
2823-
b = _CreateRestrictedToken(origToken,
2824-
DISABLE_MAX_PRIVILEGE,
2825-
sizeof(dropSids) / sizeof(dropSids[0]),
2826-
dropSids,
2827-
0, NULL,
2828-
0, NULL,
2829-
&restrictedToken);
2830-
2831-
FreeSid(dropSids[1].Sid);
2832-
FreeSid(dropSids[0].Sid);
2833-
CloseHandle(origToken);
2834-
FreeLibrary(Advapi32Handle);
2835-
2836-
if (!b)
2837-
{
2838-
fprintf(stderr, _("%s: could not create restricted token: error code %lu\n"), progname, GetLastError());
2839-
return 0;
2840-
}
2841-
2842-
#ifndef __CYGWIN__
2843-
AddUserToTokenDacl(restrictedToken);
2844-
#endif
2845-
2846-
if (!CreateProcessAsUser(restrictedToken,
2847-
NULL,
2848-
cmd,
2849-
NULL,
2850-
NULL,
2851-
TRUE,
2852-
CREATE_SUSPENDED,
2853-
NULL,
2854-
NULL,
2855-
&si,
2856-
processInfo))
2857-
2858-
{
2859-
fprintf(stderr, _("%s: could not start process for command \"%s\": error code %lu\n"), progname, cmd, GetLastError());
2860-
return 0;
2861-
}
2862-
2863-
return ResumeThread(processInfo->hThread);
2864-
}
2865-
#endif
2866-
28672748
/*
28682749
* print help text
28692750
*/
@@ -2957,53 +2838,6 @@ check_need_password(const char *authmethodlocal, const char *authmethodhost)
29572838
}
29582839
}
29592840

2960-
void
2961-
get_restricted_token(void)
2962-
{
2963-
#ifdef WIN32
2964-
2965-
/*
2966-
* Before we execute another program, make sure that we are running with a
2967-
* restricted token. If not, re-execute ourselves with one.
2968-
*/
2969-
2970-
if ((restrict_env = getenv("PG_RESTRICT_EXEC")) == NULL
2971-
|| strcmp(restrict_env, "1") != 0)
2972-
{
2973-
PROCESS_INFORMATION pi;
2974-
char *cmdline;
2975-
2976-
ZeroMemory(&pi, sizeof(pi));
2977-
2978-
cmdline = pg_strdup(GetCommandLine());
2979-
2980-
putenv("PG_RESTRICT_EXEC=1");
2981-
2982-
if (!CreateRestrictedProcess(cmdline, &pi))
2983-
{
2984-
fprintf(stderr, _("%s: could not re-execute with restricted token: error code %lu\n"), progname, GetLastError());
2985-
}
2986-
else
2987-
{
2988-
/*
2989-
* Successfully re-execed. Now wait for child process to capture
2990-
* exitcode.
2991-
*/
2992-
DWORD x;
2993-
2994-
CloseHandle(pi.hThread);
2995-
WaitForSingleObject(pi.hProcess, INFINITE);
2996-
2997-
if (!GetExitCodeProcess(pi.hProcess, &x))
2998-
{
2999-
fprintf(stderr, _("%s: could not get exit code from subprocess: error code %lu\n"), progname, GetLastError());
3000-
exit(1);
3001-
}
3002-
exit(x);
3003-
}
3004-
}
3005-
#endif
3006-
}
30072841

30082842
void
30092843
setup_pgdata(void)
@@ -3759,7 +3593,7 @@ main(int argc, char *argv[])
37593593

37603594
check_need_password(authmethodlocal, authmethodhost);
37613595

3762-
get_restricted_token();
3596+
get_restricted_token(progname);
37633597

37643598
setup_pgdata();
37653599

src/bin/pg_resetxlog/pg_resetxlog.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@
5353
#include "catalog/catversion.h"
5454
#include "catalog/pg_control.h"
5555
#include "common/fe_memutils.h"
56+
#include "common/restricted_token.h"
5657
#include "storage/large_object.h"
5758
#include "pg_getopt.h"
5859

@@ -310,6 +311,8 @@ main(int argc, char *argv[])
310311
}
311312
#endif
312313

314+
get_restricted_token(progname);
315+
313316
if (chdir(DataDir) < 0)
314317
{
315318
fprintf(stderr, _("%s: could not change directory to \"%s\": %s\n"),

src/common/Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ LIBS += $(PTHREAD_LIBS)
2626
OBJS_COMMON = exec.o pg_crc.o pg_lzcompress.o pgfnames.o psprintf.o relpath.o \
2727
rmtree.o string.o username.o wait_error.o
2828

29-
OBJS_FRONTEND = $(OBJS_COMMON) fe_memutils.o
29+
OBJS_FRONTEND = $(OBJS_COMMON) fe_memutils.o restricted_token.o
3030

3131
OBJS_SRV = $(OBJS_COMMON:%.o=%_srv.o)
3232

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