chenBright opened a new pull request, #3523:
URL: https://github.com/apache/brpc/pull/3523

   ### What problem does this PR solve?
   
   Issue Number: resolve 
   
   Problem Summary:
   
     Two builtin services let whoever reaches them do more than the surrounding
     configuration intends.
   
     #### `/flags` can repoint the bvar dump files.
   
     The bvar dump flags carry an accept-anything validator whose only job is 
to 
     wake the dumping thread:
   
     ```cpp
     // src/bvar/variable.cpp
     static bool wakeup_dumping_thread(const char*, const std::string&) {
         pthread_cond_signal(&dump_cond);
         return true;
     }
     ```
   
     The dumping thread re-reads those flags every round and ends up in
     `FileDumper::dump_impl()`:
   
     ```cpp
     butil::CreateDirectoryAndGetError(dir, &error);   // recursive mkdir
     _fp = fopen(_filename.c_str(), "w");              // truncate
     ```
   
     So two requests against a server with default options:
   
     ```
     GET /flags/bvar_dump_file?setvalue=/victim/dir/target
     GET /flags/bvar_dump?setvalue=true
     ```
   
     create a directory chain anywhere and truncate a file inside it, with the
     privileges of the server. `setvalue` is a GET, so this is reachable from a
     browser as well.
   
     The primitive is bounded but real. `bvar_dump_file` and `bvar_dump_tabs` 
get a
     `.data` suffix forced on them by `FilePath::AddExtension()`, and the bytes
     written are bvar names and values, not attacker input. `mbvar_dump_file` is
     used verbatim with no suffix. `bvar_dump_tabs` names files too: its tab 
names
     go through the same `AddExtension()`, which appends them to the path with 
no
     sanitization, so `../` in a tab name escapes the configured directory. The
     recursive mkdir and the truncation are unrestricted in every case.
   
     #### `/pprof` ignores `FLAGS_max_profiling_seconds`, which `/hotspots` 
enforces.
   
     ```cpp
     // src/brpc/builtin/pprof_service.cpp, ReadSeconds(), before this PR
         return seconds;                                        // no upper 
bound
     ```
     ```cpp
     // src/brpc/builtin/hotspots_service.cpp:233
         seconds = std::min(seconds, FLAGS_max_profiling_seconds);
     ```
   
     `?seconds=2147483647` reaches `bthread_usleep(sleep_sec * 1000000L)`, 
roughly
     68 years. The profilers are process wide -- gperftools' `ProfilerStart` and
     bthread's `g_cp` are each a single global, so this is not merely one hung
     RPC: it holds the only CPU or contention profiler for as long as it asked 
for,
     and `/hotspots/cpu` and `/hotspots/contention` answer 503 the whole time. 
The
     300 second limit was enforced on only one of the two paths to the same
     resource, so the path without it decides the limit for both.
   
   ### What is changed and the side effects?
   
   Changed:
   
   - drop the validator registration for -bvar_dump_file`, `-bvar_dump_tabs` 
and 
      `-mbvar_dump_file`.
   - `src/brpc/builtin/pprof_service.cpp`: clamp `ReadSeconds()` to
       `-max_profiling_seconds`.
   
   Side effects:
   - Performance effects:
   
   - Breaking backward compatibility: 
   
   ---
   ### Check List:
   - Please make sure your changes are compilable.
   - When providing us with a new feature, it is best to add related tests.
   - Please follow [Contributor Covenant Code of 
Conduct](https://github.com/apache/brpc/blob/master/CODE_OF_CONDUCT.md).
   


-- 
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]


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to