diff --git a/configure b/configure
index 4af0eae3686..854ce5a71b2 100755
--- a/configure
+++ b/configure
@@ -796,6 +796,7 @@ CLANG
LLVM_CONFIG
AWK
with_llvm
+with_copy_program
SUN_STUDIO_CC
ac_ct_CXX
CXXFLAGS
@@ -904,6 +905,7 @@ with_segsize_blocks
with_wal_blocksize
with_CC
with_llvm
+with_copy_program
enable_depend
enable_cassert
enable_orca
@@ -1670,6 +1672,7 @@ Optional Packages:
set WAL block size in kB [8]
--with-CC=CMD set compiler (deprecated)
--with-llvm build with LLVM based JIT support
+ --without-copy-program build without COPY TO/FROM PROGRAM support
--without-icu build without ICU support
--with-tcl build Tcl modules (PL/Tcl)
--with-tclconfig=DIR tclConfig.sh is in DIR
@@ -5380,6 +5383,31 @@ else
fi
+# Check whether --with-copy-program was given.
+if test "${with_copy_program+set}" = set; then :
+ withval=$with_copy_program;
+ case $withval in
+ yes)
+
+$as_echo "#define USE_COPY_PROGRAM 1" >>confdefs.h
+
+ ;;
+ no)
+ :
+ ;;
+ *)
+ as_fn_error $? "no argument expected for --with-copy-program option" "$LINENO" 5
+ ;;
+ esac
+
+else
+ with_copy_program=yes
+
+$as_echo "#define USE_COPY_PROGRAM 1" >>confdefs.h
+
+fi
+
+
for ac_prog in gawk mawk nawk awk
do
diff --git a/configure.ac b/configure.ac
index 20ac3aa0f6d..1fadaa128dd 100644
--- a/configure.ac
+++ b/configure.ac
@@ -468,6 +468,16 @@ AS_IF([test "$with_llvm" = yes], [
PGAC_LLVM_SUPPORT()
]) # fi
+#
+# --without-copy-program disables COPY TO/FROM PROGRAM
+#
+PGAC_ARG_BOOL(with, copy-program, yes,
+ [build with COPY TO/FROM PROGRAM support],
+ [AC_DEFINE([USE_COPY_PROGRAM], 1,
+ [Define to 1 to build with COPY TO/FROM PROGRAM support. (--with-copy-program)])])
+AC_MSG_RESULT([checking whether to build with COPY PROGRAM... $with_copy_program])
+AC_SUBST(with_copy_program)
+
unset CFLAGS
unset CXXFLAGS
diff --git a/contrib/file_fdw/file_fdw.c b/contrib/file_fdw/file_fdw.c
index b5ffde4131b..70511892349 100644
--- a/contrib/file_fdw/file_fdw.c
+++ b/contrib/file_fdw/file_fdw.c
@@ -413,10 +413,18 @@ fileGetOptions(Oid foreigntableid,
}
else if (strcmp(def->defname, "program") == 0)
{
+#ifndef USE_COPY_PROGRAM
+ ereport(ERROR,
+ (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
+ errmsg("permission denied to use program option in file_fdw"),
+ errhint("Anyone can COPY to stdout or from stdin. "
+ "psql's \\copy command also works for anyone.")));
+#else
*filename = defGetString(def);
*is_program = true;
options = foreach_delete_current(options, lc);
break;
+#endif
}
}
diff --git a/doc/src/sgml/installation.sgml b/doc/src/sgml/installation.sgml
index c9904193d40..59c590c3d41 100644
--- a/doc/src/sgml/installation.sgml
+++ b/doc/src/sgml/installation.sgml
@@ -989,9 +989,23 @@ build-postgresql:
environment variable).
-
+
+
+
+
+
+
+ Build without support for COPY TO/FROM PROGRAM.
+ By default, this feature is enabled. When built with
+ , any attempt to use
+ COPY with the PROGRAM
+ option will result in an error, regardless of the user's
+ privileges.
+
+
+
-
+
diff --git a/meson.build b/meson.build
index 929d6c27be6..2bf8d5d70d7 100644
--- a/meson.build
+++ b/meson.build
@@ -817,6 +817,16 @@ endif
+###############################################################
+# Option: copy_program
+###############################################################
+
+if get_option('copy_program').enabled()
+ cdata.set('USE_COPY_PROGRAM', 1)
+endif
+
+
+
###############################################################
# Library: icu
###############################################################
diff --git a/meson_options.txt b/meson_options.txt
index d2f95cfec36..d9d16829fa4 100644
--- a/meson_options.txt
+++ b/meson_options.txt
@@ -115,6 +115,9 @@ option('llvm', type: 'feature', value: 'disabled',
option('lz4', type: 'feature', value: 'auto',
description: 'LZ4 support')
+option('copy_program', type: 'feature', value: 'enabled',
+ description: 'COPY TO/FROM PROGRAM support')
+
option('nls', type: 'feature', value: 'auto',
description: 'Native language support')
diff --git a/src/Makefile.global.in b/src/Makefile.global.in
index f00f0be7091..ee1c76e0276 100644
--- a/src/Makefile.global.in
+++ b/src/Makefile.global.in
@@ -204,6 +204,7 @@ with_ldap = @with_ldap@
with_libxml = @with_libxml@
with_libxslt = @with_libxslt@
with_llvm ?= @with_llvm@
+with_copy_program ?= @with_copy_program@
with_system_tzdata = @with_system_tzdata@
with_uuid = @with_uuid@
with_zlib = @with_zlib@
diff --git a/src/backend/commands/copy.c b/src/backend/commands/copy.c
index 30915b2a4cc..d037acca211 100644
--- a/src/backend/commands/copy.c
+++ b/src/backend/commands/copy.c
@@ -146,6 +146,7 @@ DoCopy(ParseState *pstate, const CopyStmt *stmt,
{
if (stmt->is_program)
{
+#ifdef USE_COPY_PROGRAM
if (!has_privs_of_role(GetUserId(), ROLE_PG_EXECUTE_SERVER_PROGRAM))
ereport(ERROR,
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
@@ -154,6 +155,13 @@ DoCopy(ParseState *pstate, const CopyStmt *stmt,
"pg_execute_server_program"),
errhint("Anyone can COPY to stdout or from stdin. "
"psql's \\copy command also works for anyone.")));
+#else
+ ereport(ERROR,
+ (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
+ errmsg("permission denied to COPY to or from an external program"),
+ errhint("Anyone can COPY to stdout or from stdin. "
+ "psql's \\copy command also works for anyone.")));
+#endif
}
else
{
diff --git a/src/include/pg_config.h.in b/src/include/pg_config.h.in
index 72a27f363b4..677e5e7e423 100644
--- a/src/include/pg_config.h.in
+++ b/src/include/pg_config.h.in
@@ -880,6 +880,9 @@
(--enable-link-postgres-with-shared) */
#undef USE_LINK_POSTGRES_WITH_SHARED
+/* Define to 1 to build with COPY TO/FROM PROGRAM support. (--with-copy-program) */
+#undef USE_COPY_PROGRAM
+
/* Define to 1 to build with LLVM based JIT support. (--with-llvm) */
#undef USE_LLVM
diff --git a/src/include/pg_config.h.win32 b/src/include/pg_config.h.win32
index dc80f4ba040..291991258be 100644
--- a/src/include/pg_config.h.win32
+++ b/src/include/pg_config.h.win32
@@ -762,6 +762,9 @@
/* Define to 1 to build with LDAP support. (--with-ldap) */
/* #undef USE_LDAP */
+/* Define to 1 to build with COPY TO/FROM PROGRAM support. (--with-copy-program) */
+#define USE_COPY_PROGRAM 1
+
/* Define to 1 to build with LLVM based JIT support. (--with-llvm) */
/* #undef USE_LLVM */
diff --git a/src/tools/msvc/Solution.pm b/src/tools/msvc/Solution.pm
index db0b27e1067..7d5a759941d 100644
--- a/src/tools/msvc/Solution.pm
+++ b/src/tools/msvc/Solution.pm
@@ -435,6 +435,7 @@ sub GenerateFiles
USE_LZ4 => undef,
USE_LDAP => $self->{options}->{ldap} ? 1 : undef,
USE_LLVM => undef,
+ USE_COPY_PROGRAM => 1,
USE_NAMED_POSIX_SEMAPHORES => undef,
USE_OPENSSL => undef,
USE_PAM => undef,