Skip to content
Merged
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
11 changes: 9 additions & 2 deletions src/config/capability_map.rs
Original file line number Diff line number Diff line change
Expand Up @@ -67,9 +67,16 @@ impl CapabilityMapConfig {
where
P: AsRef<Path>,
{
let mut file = std::fs::File::open(path)?;
let file = std::fs::File::open(path)?;

// Read up to a defined maximum size to prevent denial of service
const MAX_SIZE: usize = 512 * 1024;
let mut reader = file.take(MAX_SIZE as u64);
let mut content = String::default();
file.read_to_string(&mut content)?;
let bytes_read = reader.read_to_string(&mut content)?;
if bytes_read == MAX_SIZE {
return Err(LoadError::MaximumSizeReached(MAX_SIZE));
}
Self::from_yaml(content)
}

Expand Down
30 changes: 24 additions & 6 deletions src/config/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ pub mod capability_map;
pub mod config_test;
pub mod path;

use std::io;
use std::io::{self, Read};

use ::procfs::CpuInfo;
use capability_map::CapabilityConfig;
Expand All @@ -28,6 +28,8 @@ pub enum LoadError {
IoError(#[from] io::Error),
#[error("Unable to deserialize: {0}")]
DeserializeError(#[from] serde_yaml::Error),
#[error("Config too large, reached maximum size of {0} bytes")]
MaximumSizeReached(usize),
}

#[derive(Debug, Deserialize, Serialize, Clone)]
Expand All @@ -51,8 +53,16 @@ impl DeviceProfile {
/// Load a [CapabilityProfile] from the given YAML file
pub fn from_yaml_file(path: String) -> Result<DeviceProfile, LoadError> {
let file = std::fs::File::open(path)?;
let device: DeviceProfile = serde_yaml::from_reader(file)?;
Ok(device)

// Read up to a defined maximum size to prevent denial of service
const MAX_SIZE: usize = 512 * 1024;
let mut reader = file.take(MAX_SIZE as u64);
let mut content = String::default();
let bytes_read = reader.read_to_string(&mut content)?;
if bytes_read == MAX_SIZE {
return Err(LoadError::MaximumSizeReached(MAX_SIZE));
}
Self::from_yaml(content)
}
}

Expand Down Expand Up @@ -372,16 +382,24 @@ pub struct CompositeDeviceConfig {

impl CompositeDeviceConfig {
/// Load a [CompositeDevice] from the given YAML string
pub fn _from_yaml(content: String) -> Result<CompositeDeviceConfig, LoadError> {
pub fn from_yaml(content: String) -> Result<CompositeDeviceConfig, LoadError> {
let device: CompositeDeviceConfig = serde_yaml::from_str(content.as_str())?;
Ok(device)
}

/// Load a [CompositeDevice] from the given YAML file
pub fn from_yaml_file(path: String) -> Result<CompositeDeviceConfig, LoadError> {
let file = std::fs::File::open(path)?;
let device: CompositeDeviceConfig = serde_yaml::from_reader(file)?;
Ok(device)

// Read up to a defined maximum size to prevent denial of service
const MAX_SIZE: usize = 512 * 1024;
let mut reader = file.take(MAX_SIZE as u64);
let mut content = String::default();
let bytes_read = reader.read_to_string(&mut content)?;
if bytes_read == MAX_SIZE {
return Err(LoadError::MaximumSizeReached(MAX_SIZE));
}
Self::from_yaml(content)
}

/// Returns an array of all defined hidraw source devices
Expand Down
11 changes: 8 additions & 3 deletions src/dbus/interface/manager.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use zbus::{fdo, message::Header, Connection};
use zbus_macros::interface;

use crate::{
config::CompositeDeviceConfig,
config::{CompositeDeviceConfig, LoadError},
constants::BUS_PREFIX,
dbus::{interface::Unregisterable, polkit::check_polkit},
input::{manager::ManagerCommand, target::TargetDeviceTypeId},
Expand Down Expand Up @@ -148,8 +148,13 @@ impl ManagerInterface {
"org.shadowblip.InputPlumber.CreateCompositeDevice",
)
.await?;
let device = CompositeDeviceConfig::from_yaml_file(config_path)
.map_err(|err| fdo::Error::Failed(err.to_string()))?;
let device = CompositeDeviceConfig::from_yaml_file(config_path).map_err(|e| match e {
LoadError::IoError(error) => fdo::Error::Failed(error.to_string()),
LoadError::MaximumSizeReached(error) => fdo::Error::Failed(error.to_string()),
LoadError::DeserializeError(_) => {
fdo::Error::InvalidFileContent("Failed to parse file".to_string())
}
})?;
self.tx
.send_timeout(
ManagerCommand::CreateCompositeDevice { config: device },
Expand Down
11 changes: 9 additions & 2 deletions src/input/composite_device/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ use zbus::{object_server::Interface, Connection};
use crate::{
config::{
capability_map::CapabilityMapConfig, path::get_profiles_path, CompositeDeviceConfig,
DeviceProfile, ProfileMapping,
DeviceProfile, LoadError, ProfileMapping,
},
dbus::interface::{
composite_device::CompositeDeviceInterface, force_feedback::ForceFeedbackInterface,
Expand Down Expand Up @@ -446,7 +446,14 @@ impl CompositeDevice {
let profile = match DeviceProfile::from_yaml_file(path.clone()) {
Ok(p) => p,
Err(e) => {
if let Err(er) = sender.send(Err(e.to_string())).await {
let err = match e {
LoadError::IoError(_) => e.to_string(),
LoadError::MaximumSizeReached(_) => e.to_string(),
LoadError::DeserializeError(_) => {
"Failed to parse file".to_string()
}
};
if let Err(er) = sender.send(Err(err)).await {
log::error!("Failed to send failed to load profile: {er:?}");
}
continue;
Expand Down