Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -7668,23 +7668,6 @@ object SQLConf {
.booleanConf
.createWithDefault(true)

// Deprecate "spark.connect.copyFromLocalToFs.allowDestLocal" in favor of this config. This is
// currently optional because we don't want to break existing users who are using the old config.
// If this config is set, then we override the deprecated config.
val ARTIFACT_COPY_FROM_LOCAL_TO_FS_ALLOW_DEST_LOCAL =
buildConf("spark.sql.artifact.copyFromLocalToFs.allowDestLocal")
.internal()
.doc("""
|Allow `spark.copyFromLocalToFs` destination to be local file system
| path on spark driver node when
|`spark.sql.artifact.copyFromLocalToFs.allowDestLocal` is true.
|This will allow user to overwrite arbitrary file on spark
|driver node we should only enable it for testing purpose.
|""".stripMargin)
.version("4.0.0")
.booleanConf
.createOptional

val LEGACY_RETAIN_FRACTION_DIGITS_FIRST =
buildConf("spark.sql.legacy.decimal.retainFractionDigitsOnTruncate")
.internal()
Expand Down Expand Up @@ -8239,7 +8222,7 @@ object SQLConf {
DeprecatedConfig(ESCAPED_STRING_LITERALS.key, "4.0",
"Use raw string literals with the `r` prefix instead. "),
DeprecatedConfig("spark.connect.copyFromLocalToFs.allowDestLocal", "4.0",
s"Use '${ARTIFACT_COPY_FROM_LOCAL_TO_FS_ALLOW_DEST_LOCAL.key}' instead."),
s"Use '${StaticSQLConf.ARTIFACT_COPY_FROM_LOCAL_TO_FS_ALLOW_DEST_LOCAL.key}' instead."),
DeprecatedConfig(ALLOW_ZERO_INDEX_IN_FORMAT_STRING.key, "4.0", "Increase indexes by 1 " +
"in `strfmt` of the `format_string` function. Refer to the first argument by \"1$\"."),
DeprecatedConfig(SHUFFLE_DEPENDENCY_FILE_CLEANUP_ENABLED.key, "4.1",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -338,6 +338,18 @@ object StaticSQLConf {
.booleanConf
.createWithDefault(true)

val ARTIFACT_COPY_FROM_LOCAL_TO_FS_ALLOW_DEST_LOCAL =
buildStaticConf("spark.sql.artifact.copyFromLocalToFs.allowDestLocal")
.internal()
.doc("Allow the `copyFromLocalToFs` destination to be a local file system path on the " +
"driver node. This lets the caller overwrite arbitrary files on the driver node, so it " +
"should only be enabled for testing purposes. This is a static conf: it can only be set " +
"when starting the driver, and not from a session.")
.version("4.3.0")
.withBindingPolicy(ConfigBindingPolicy.NOT_APPLICABLE)
.booleanConf
.createWithDefault(false)

val REFLECT_ALLOW_LIST = buildStaticConf("spark.sql.reflect.allowList")
.doc("A comma-separated allow list of regular expressions matched against the canonical " +
"static method name (in the form `class.method`, e.g. `java.util.UUID.randomUUID`) " +
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ import java.util.concurrent.TimeUnit
import org.apache.spark.SparkEnv
import org.apache.spark.network.util.ByteUnit
import org.apache.spark.sql.connect.common.config.ConnectCommon
import org.apache.spark.sql.internal.SQLConf
import org.apache.spark.sql.internal.SQLConf.buildConf

object Connect {
Expand Down Expand Up @@ -302,17 +301,6 @@ object Connect {
.intConf
.createWithDefault(200)

val CONNECT_COPY_FROM_LOCAL_TO_FS_ALLOW_DEST_LOCAL =
buildStaticConf("spark.connect.copyFromLocalToFs.allowDestLocal")
.internal()
.doc(s"""
|(Deprecated since Spark 4.0, please set
|'${SQLConf.ARTIFACT_COPY_FROM_LOCAL_TO_FS_ALLOW_DEST_LOCAL.key}' instead.
|""".stripMargin)
.version("3.5.0")
.booleanConf
.createWithDefault(false)

val CONNECT_UI_SESSION_LIMIT = buildStaticConf("spark.sql.connect.ui.retainedSessions")
.doc("The number of client sessions kept in the Spark Connect UI history.")
.version("3.5.0")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ import org.apache.spark.internal.{Logging, LogKeys}
import org.apache.spark.internal.config.{CONNECT_SCALA_UDF_STUB_PREFIXES, EXECUTOR_USER_CLASS_PATH_FIRST}
import org.apache.spark.sql.Artifact
import org.apache.spark.sql.classic.SparkSession
import org.apache.spark.sql.internal.SQLConf
import org.apache.spark.sql.internal.{SQLConf, StaticSQLConf}
import org.apache.spark.sql.util.ArtifactUtils
import org.apache.spark.storage.{BlockManager, CacheId, StorageLevel}
import org.apache.spark.util.{ChildFirstURLClassLoader, StubClassLoader, Utils}
Expand Down Expand Up @@ -504,10 +504,8 @@ class ArtifactManager(session: SparkSession) extends AutoCloseable with Logging
val localPath = serverLocalStagingPath
val fs = destFSPath.getFileSystem(hadoopConf)
if (fs.isInstanceOf[LocalFileSystem]) {
val allowDestLocalConf =
session.sessionState.conf.getConf(SQLConf.ARTIFACT_COPY_FROM_LOCAL_TO_FS_ALLOW_DEST_LOCAL)
.getOrElse(
session.conf.get("spark.connect.copyFromLocalToFs.allowDestLocal").contains("true"))
val allowDestLocalConf = session.sessionState.conf.getConf(
StaticSQLConf.ARTIFACT_COPY_FROM_LOCAL_TO_FS_ALLOW_DEST_LOCAL)

if (!allowDestLocalConf) {
// To avoid security issue, by default,
Expand All @@ -517,7 +515,7 @@ class ArtifactManager(session: SparkSession) extends AutoCloseable with Logging
// We can temporarily allow the behavior by setting spark config
// `spark.sql.artifact.copyFromLocalToFs.allowDestLocal`
// to `true` when starting spark driver, we should only enable it for testing
// purpose.
// purpose. It is a static conf, so it cannot be set from a session.
throw new SparkUnsupportedOperationException("_LEGACY_ERROR_TEMP_3161")
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,10 @@ import java.nio.file.{Files, Path, Paths}

import org.apache.spark.{SparkConf, SparkException, SparkRuntimeException}
import org.apache.spark.metrics.source.CodegenMetrics
import org.apache.spark.sql.Artifact
import org.apache.spark.sql.{AnalysisException, Artifact}
import org.apache.spark.sql.classic.SparkSession
import org.apache.spark.sql.functions.col
import org.apache.spark.sql.internal.SQLConf
import org.apache.spark.sql.internal.{SQLConf, StaticSQLConf}
import org.apache.spark.sql.test.SharedSparkSession
import org.apache.spark.sql.types.DataTypes
import org.apache.spark.storage.CacheId
Expand Down Expand Up @@ -253,6 +253,18 @@ class ArtifactManagerSuite extends SharedSparkSession {
assert(copiedClassFile.exists())
}

test("SPARK-58531: allowDestLocal cannot be set from a session") {
// The conf gates writes to a local filesystem destination on the driver, so it must stay a
// static conf: a session that could turn it on would be able to write to arbitrary paths on
// the driver. Guard against it being made session-settable again.
val key = StaticSQLConf.ARTIFACT_COPY_FROM_LOCAL_TO_FS_ALLOW_DEST_LOCAL.key
assert(SQLConf.isStaticConfigKey(key))
checkError(
exception = intercept[AnalysisException](spark.conf.set(key, "true")),
condition = "CANNOT_MODIFY_STATIC_CONFIG",
parameters = Map("key" -> s""""$key""""))
}

test("Removal of resources") {

withTempPath { path =>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -453,7 +453,6 @@ spark.sql.ansi.enabled
spark.sql.ansi.enforceReservedKeywords
spark.sql.ansi.relationPrecedence
spark.sql.artifact.cacheStorageLevel
spark.sql.artifact.copyFromLocalToFs.allowDestLocal
spark.sql.artifact.isolation.alwaysApplyClassloader
spark.sql.artifact.isolation.enabled
spark.sql.assumeAnsiFalseIfNotPersisted.enabled
Expand Down