jerryshao opened a new issue, #13371:
URL: https://github.com/apache/gravitino/issues/13371

   ### Version
   
   main branch
   
   ### Describe what's wrong
   
   Job template names are only required to be non-blank 
(`JobTemplateDTO#validate`) and not to start with `builtin-` 
(`JobTemplateValidationDispatcher`). `JobManager` builds a job's staging 
directory by string concatenation, without normalizing the result or checking 
that it stays under `gravitino.job.stagingDir`:
   
   ```java
   stagingDir.getAbsolutePath() + String.format(JOB_STAGING_DIR, metalake, 
jobTemplateName, jobId)
   // JOB_STAGING_DIR = "/%s/%s/job-%s"
   ```
   
   So a template named `../../escape` resolves to 
`<stagingDir>/<metalake>/../../escape/job-<id>`, i.e. `<parent of 
stagingDir>/escape/job-<id>`. Once `<stagingDir>/<metalake>` exists (after any 
other job ran in that metalake), running a job from this template:
   
   - creates the job directory outside the staging directory, and downloads the 
template's executable, scripts, jars, files and archives into it (`runJob` / 
`createRuntimeJobTemplate`);
   - runs the job there, with the local job executor writing `output.log` / 
`error.log` into it;
   - later deletes that outside directory recursively, in `deleteJobTemplate` 
and `cleanUpStagingDirs`.
   
   If `<stagingDir>/<metalake>` doesn't exist yet, the directory is still 
created outside and the executable is still downloaded there, but the job fails 
to start and the directory is never cleaned up.
   
   Whoever can register a job template, or rename one through 
`alterJobTemplate`, chooses where on the server's file system this happens. The 
last path component of the deleted directory is always `job-<id>`.
   
   ### Error message and/or stacktrace
   
   None. The requests succeed. When `<stagingDir>/<metalake>` doesn't exist 
yet, the job fails with `Failed to start shell process ... output.log (No such 
file or directory)`.
   
   ### How to reproduce
   
   Verified on main by calling `JobManager` directly (`registerJobTemplate` → 
`runJob` → `deleteJobTemplate`). The REST requests below are the equivalent, 
with the default `gravitino.job.stagingDir=/tmp/gravitino/jobs/staging`:
   
   1. Run any job in metalake `example`, so that 
`/tmp/gravitino/jobs/staging/example` exists.
   2. Register a template whose name escapes the staging directory:
      ```shell
      curl -X POST -H "Accept: application/vnd.gravitino.v1+json" -H 
"Content-Type: application/json" -d '{
        "jobTemplate": {"name": "../../escape", "jobType": "shell", 
"executable": "/bin/echo", "arguments": ["hello"]}
      }' http://localhost:8090/api/metalakes/example/jobs/templates
      ```
   3. Run a job from it:
      ```shell
      curl -X POST -H "Accept: application/vnd.gravitino.v1+json" -H 
"Content-Type: application/json" -d '{
        "jobTemplateName": "../../escape", "jobConf": {}
      }' http://localhost:8090/api/metalakes/example/jobs/runs
      ```
   4. `/tmp/gravitino/jobs/escape/job-<id>/` now contains `echo`, `output.log` 
and `error.log`, outside the staging directory.
   5. Deleting the template, or the job expiring after 
`gravitino.job.stagingDirKeepTimeInMs`, deletes 
`/tmp/gravitino/jobs/escape/job-<id>`.
   
   ### Additional context
   
   Found while working on multi-node job output retrieval (#12716), part of 
epic #12667.
   
   Possible fix:
   - Validate job template names on register and rename.
   - Add a containment check when building the staging path: normalize it, and 
fail the run if it's outside `gravitino.job.stagingDir`.
   
   Names containing `/` currently work (they create nested directories), so the 
validation should decide whether to reject only traversal (`..` segments), or 
all path separators.
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to