Skip to content

Commit 20634d9

Browse files
authored
tracing: disable regular expression matching in log filters (#1580)
[`tracing-subscriber` v0.3.10][1] introduces a new [builder API][2] for configuring the `EnvFilter` type. One of the configurations that can now be set using the builder is whether span field value filters for `fmt::Debug` fields are interpreted as precise string matching or as regular expressions. Disabling regular expressions is strongly recommended in cases where filter configurations can come from an untrusted source, as a malicious regular expression is a potential denial-of-service vector. In the proxy, we already implement a form of access control for setting the filter --- the `/admin/log-level` endpoint denies requests that did not originate from localhost, so it's only possible to set the log level when SSHed into the pod. However, it's probably wise to disable regex filters here as well, as a form of additional defense in depth. Therefore, this branch updates the `tracing-subscriber` dependency to v0.3.10, and disables regular expression filters. [1]: https://github.com/tokio-rs/tracing/releases/tag/tracing-subscriber-0.3.10 [2]: https://docs.rs/tracing-subscriber/latest/tracing_subscriber/filter/struct.Builder.html
1 parent befb200 commit 20634d9

File tree

3 files changed

+22
-6
lines changed

3 files changed

+22
-6
lines changed

linkerd/tracing/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,6 @@ tracing = "0.1"
1717
tracing-log = "0.1"
1818

1919
[dependencies.tracing-subscriber]
20-
version = "0.3"
20+
version = "0.3.10"
2121
default-features = false
2222
features = ["env-filter", "fmt", "smallvec", "tracing-log", "json", "parking_lot", "registry"]

linkerd/tracing/src/level.rs

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,23 @@
11
use linkerd_error::Error;
22
use tracing::trace;
3-
use tracing_subscriber::{reload, EnvFilter, Registry};
3+
use tracing_subscriber::{
4+
filter::{self, EnvFilter, LevelFilter},
5+
reload, Registry,
6+
};
47

58
#[derive(Clone)]
69
pub struct Handle(reload::Handle<EnvFilter, Registry>);
710

11+
/// Returns an `EnvFilter` builder with the configuration used for parsing new
12+
/// filter strings.
13+
pub(crate) fn filter_builder() -> filter::Builder {
14+
EnvFilter::builder()
15+
.with_default_directive(LevelFilter::WARN.into())
16+
// Disable regular expression matching for `fmt::Debug` fields, use
17+
// exact string matching instead.
18+
.with_regex(false)
19+
}
20+
821
impl Handle {
922
pub(crate) fn new(handle: reload::Handle<EnvFilter, Registry>) -> Self {
1023
Self(handle)
@@ -18,7 +31,7 @@ impl Handle {
1831

1932
pub fn set_level(&self, level: impl AsRef<str>) -> Result<(), Error> {
2033
let level = level.as_ref();
21-
let filter = level.parse::<EnvFilter>()?;
34+
let filter = filter_builder().parse(level)?;
2235
self.0.reload(filter)?;
2336
tracing::info!(%level, "set new log level");
2437
Ok(())

linkerd/tracing/src/lib.rs

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ use linkerd_error::Error;
1616
use std::str;
1717
use tracing::{Dispatch, Subscriber};
1818
use tracing_subscriber::{
19-
filter::{EnvFilter, FilterFn},
19+
filter::{FilterFn, LevelFilter},
2020
fmt::format,
2121
prelude::*,
2222
registry::LookupSpan,
@@ -60,7 +60,6 @@ pub fn init() -> Result<Handle, Error> {
6060

6161
#[inline]
6262
pub(crate) fn update_max_level() {
63-
use tracing::level_filters::LevelFilter;
6463
use tracing_log::{log, AsLog};
6564
log::set_max_level(LevelFilter::current().as_log());
6665
}
@@ -167,7 +166,11 @@ impl Settings {
167166
pub fn build(self) -> (Dispatch, Handle) {
168167
let log_level = self.filter.as_deref().unwrap_or(DEFAULT_LOG_LEVEL);
169168

170-
let mut filter = EnvFilter::new(log_level);
169+
let mut filter = level::filter_builder()
170+
// When parsing the initial filter configuration from the
171+
// environment variable, use `parse_lossy` to skip any invalid
172+
// filter directives and print an error.
173+
.parse_lossy(log_level);
171174

172175
// If access logging is enabled, build the access log layer.
173176
let access_log = if let Some(format) = self.access_log {

0 commit comments

Comments
 (0)