@@ -3,11 +3,17 @@ pub mod capability_map;
33pub mod config_test;
44pub mod path;
55
6- use std:: io:: { self , Read } ;
6+ use std:: {
7+ fs:: File ,
8+ io:: { self , Read } ,
9+ os:: fd:: OwnedFd ,
10+ path:: Path ,
11+ } ;
712
813use :: procfs:: CpuInfo ;
914use capability_map:: CapabilityConfig ;
1015use glob_match:: glob_match;
16+ use nix:: fcntl:: { fcntl, FcntlArg , OFlag } ;
1117
1218use serde:: { Deserialize , Serialize } ;
1319use thiserror:: Error ;
@@ -30,6 +36,8 @@ pub enum LoadError {
3036 DeserializeError ( #[ from] serde_yaml:: Error ) ,
3137 #[ error( "Config too large, reached maximum size of {0} bytes" ) ]
3238 MaximumSizeReached ( usize ) ,
39+ #[ error( "Operation failed: {0}" ) ]
40+ Os ( #[ from] nix:: errno:: Errno ) ,
3341}
3442
3543#[ derive( Debug , Deserialize , Serialize , Clone ) ]
@@ -46,16 +54,30 @@ pub struct DeviceProfile {
4654}
4755
4856impl DeviceProfile {
49- /// Load a [CapabilityProfile ] from the given YAML string
57+ /// Load a [DeviceProfile ] from the given YAML string
5058 pub fn from_yaml ( content : String ) -> Result < DeviceProfile , LoadError > {
5159 let device: DeviceProfile = serde_yaml:: from_str ( content. as_str ( ) ) ?;
5260 Ok ( device)
5361 }
5462
55- /// Load a [CapabilityProfile] from the given YAML file
56- pub fn from_yaml_file ( path : String ) -> Result < DeviceProfile , LoadError > {
57- let file = std:: fs:: File :: open ( path) ?;
63+ /// Load a [DeviceProfile] from the given YAML file descriptor
64+ pub fn from_yaml_fd ( fd : OwnedFd ) -> Result < Self , LoadError > {
65+ validate_fd_flags ( & fd) ?;
66+ let file = File :: from ( fd) ;
67+ Self :: from_yaml_file ( file)
68+ }
69+
70+ /// Load a [DeviceProfile] from the given YAML file path
71+ pub fn from_yaml_path < P > ( path : P ) -> Result < Self , LoadError >
72+ where
73+ P : AsRef < Path > ,
74+ {
75+ let file = File :: open ( path) ?;
76+ Self :: from_yaml_file ( file)
77+ }
5878
79+ /// Load a [DeviceProfile] from the given YAML file
80+ pub fn from_yaml_file ( file : File ) -> Result < DeviceProfile , LoadError > {
5981 // Read up to a defined maximum size to prevent denial of service
6082 const MAX_SIZE : usize = 512 * 1024 ;
6183 let mut reader = file. take ( MAX_SIZE as u64 ) ;
@@ -466,16 +488,30 @@ pub struct CompositeDeviceConfig {
466488}
467489
468490impl CompositeDeviceConfig {
469- /// Load a [CompositeDevice ] from the given YAML string
470- pub fn from_yaml ( content : String ) -> Result < CompositeDeviceConfig , LoadError > {
491+ /// Load a [CompositeDeviceConfig ] from the given YAML string
492+ pub fn from_yaml ( content : String ) -> Result < Self , LoadError > {
471493 let device: CompositeDeviceConfig = serde_yaml:: from_str ( content. as_str ( ) ) ?;
472494 Ok ( device)
473495 }
474496
475- /// Load a [CompositeDevice] from the given YAML file
476- pub fn from_yaml_file ( path : String ) -> Result < CompositeDeviceConfig , LoadError > {
477- let file = std:: fs:: File :: open ( path) ?;
497+ /// Load a [CompositeDeviceConfig] from the given YAML file descriptor
498+ pub fn from_yaml_fd ( fd : OwnedFd ) -> Result < Self , LoadError > {
499+ validate_fd_flags ( & fd) ?;
500+ let file = File :: from ( fd) ;
501+ Self :: from_yaml_file ( file)
502+ }
478503
504+ /// Load a [CompositeDeviceConfig] from the given YAML file path
505+ pub fn from_yaml_path < P > ( path : P ) -> Result < Self , LoadError >
506+ where
507+ P : AsRef < Path > ,
508+ {
509+ let file = File :: open ( path) ?;
510+ Self :: from_yaml_file ( file)
511+ }
512+
513+ /// Load a [CompositeDeviceConfig] from the given YAML file
514+ pub fn from_yaml_file ( file : File ) -> Result < Self , LoadError > {
479515 // Read up to a defined maximum size to prevent denial of service
480516 const MAX_SIZE : usize = 512 * 1024 ;
481517 let mut reader = file. take ( MAX_SIZE as u64 ) ;
@@ -987,3 +1023,17 @@ impl CompositeDeviceConfig {
9871023 Some ( matches)
9881024 }
9891025}
1026+
1027+ /// Ensures the given file descriptor has valid flags set
1028+ fn validate_fd_flags ( fd : & OwnedFd ) -> Result < ( ) , LoadError > {
1029+ // Validate the flags for the fd
1030+ let flags = fcntl ( & fd, FcntlArg :: F_GETFL ) ?;
1031+ let Some ( flags) = OFlag :: from_bits ( flags) else {
1032+ return Err ( LoadError :: Os ( nix:: errno:: Errno :: EIO ) ) ;
1033+ } ;
1034+ if flags. contains ( OFlag :: O_PATH ) {
1035+ return Err ( LoadError :: Os ( nix:: errno:: Errno :: EIO ) ) ;
1036+ }
1037+
1038+ Ok ( ( ) )
1039+ }
0 commit comments