Skip to content

Commit f4c68ba

Browse files
Address comments
Single auth checkpoint for every current and future RPC. Dropped the redundant calls in Controller. Add comment for remote storages. Harden validateAppId
1 parent 1c79a19 commit f4c68ba

5 files changed

Lines changed: 16 additions & 8 deletions

File tree

common/src/main/scala/org/apache/celeborn/common/rpc/RpcEndpoint.scala

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ package org.apache.celeborn.common.rpc
2020
import org.apache.celeborn.common.exception.CelebornException
2121
import org.apache.celeborn.common.network.client.TransportClient
2222
import org.apache.celeborn.common.rpc.netty.RemoteNettyRpcCallContext
23+
import org.apache.celeborn.common.util.Utils
2324

2425
/**
2526
* A factory class to create the [[RpcEnv]]. It must have an empty constructor so that it can be
@@ -138,6 +139,11 @@ trait RpcEndpoint {
138139
}
139140

140141
def checkAuth(context: RpcCallContext, appId: String): Unit = {
142+
// Validate the application id at the single auth chokepoint so every current
143+
// and future RPC handler that calls checkAuth is covered, and so it runs even
144+
// when auth is disabled (clientId == null). This guards the worker against
145+
// path traversal via appId (e.g. "../foo") before any filesystem path is built.
146+
Utils.validateAppId(appId)
141147
context match {
142148
case remoteContext: RemoteNettyRpcCallContext =>
143149
checkAuth(remoteContext.transportClient, appId)

common/src/main/scala/org/apache/celeborn/common/util/Utils.scala

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -700,11 +700,12 @@ object Utils extends Logging {
700700
(appId, shuffleId)
701701
}
702702

703-
private val appIdPattern = "^[A-Za-z0-9_-]+$".r
703+
private val appIdPattern = "[A-Za-z0-9_-]+".r.pattern
704704

705705
def validateAppId(applicationId: String): Unit = {
706-
if (applicationId == null || applicationId.isEmpty ||
707-
appIdPattern.findFirstIn(applicationId).isEmpty) {
706+
// matches() anchors the whole input, so a trailing newline (which `$` would
707+
// otherwise tolerate) is rejected along with any other traversal character.
708+
if (applicationId == null || !appIdPattern.matcher(applicationId).matches()) {
708709
throw new IllegalArgumentException(
709710
s"Invalid application id: '$applicationId'. " +
710711
"Application id must be non-empty and match [A-Za-z0-9_-]+.")

common/src/test/scala/org/apache/celeborn/common/util/UtilsSuite.scala

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -306,6 +306,8 @@ class UtilsSuite extends CelebornFunSuite {
306306
"app/id",
307307
"app\\id",
308308
"app id",
309+
"app\n",
310+
"valid_app\n",
309311
"",
310312
null).foreach { id =>
311313
intercept[IllegalArgumentException] {

worker/src/main/scala/org/apache/celeborn/service/deploy/worker/Controller.scala

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,6 @@ private[deploy] class Controller(
115115
pushDataTimeout,
116116
partitionSplitEnabled,
117117
isSegmentGranularityVisible) =>
118-
Utils.validateAppId(applicationId)
119118
checkAuth(context, applicationId)
120119
val shuffleKey = Utils.makeShuffleKey(applicationId, shuffleId)
121120
workerSource.sample(WorkerSource.RESERVE_SLOTS_TIME, shuffleKey) {
@@ -147,7 +146,6 @@ private[deploy] class Controller(
147146
mapAttempts,
148147
epoch,
149148
mockFailure) =>
150-
Utils.validateAppId(applicationId)
151149
checkAuth(context, applicationId)
152150
val shuffleKey = Utils.makeShuffleKey(applicationId, shuffleId)
153151
logDebug(s"Received CommitFiles request, $shuffleKey, primary files" +
@@ -166,9 +164,7 @@ private[deploy] class Controller(
166164
s"$commitFilesTimeMs ms.")
167165

168166
case DestroyWorkerSlots(shuffleKey, primaryLocations, replicaLocations, mockFailure) =>
169-
val applicationId = Utils.splitShuffleKey(shuffleKey)._1
170-
Utils.validateAppId(applicationId)
171-
checkAuth(context, applicationId)
167+
checkAuth(context, Utils.splitShuffleKey(shuffleKey)._1)
172168
handleDestroy(context, shuffleKey, primaryLocations, replicaLocations, mockFailure)
173169
}
174170

worker/src/main/scala/org/apache/celeborn/service/deploy/worker/storage/StorageManager.scala

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1161,6 +1161,9 @@ final private[worker] class StorageManager(conf: CelebornConf, workerSource: Abs
11611161
throw new IOException(s"No available disks! suggested mountPoint $suggestedMountPoint")
11621162
}
11631163

1164+
// NOTE: the DFS branches below (HDFS/S3/OSS) also build "$appId/$shuffleId"
1165+
// paths but rely solely on the upstream Utils.validateAppId guard at the RPC
1166+
// entry points
11641167
if (storageType == Type.HDFS && location.getStorageInfo.HDFSAvailable()) {
11651168
val shuffleDir =
11661169
new Path(new Path(hdfsDir, conf.workerWorkingDir), s"$appId/$shuffleId")

0 commit comments

Comments
 (0)