@@ -123,6 +123,20 @@ pub enum LinuxCapabilityType {
123123 CAP_AUDIT_READ ,
124124}
125125
126+ #[ derive( Serialize , Deserialize , Debug ) ]
127+ pub struct LinuxCapabilities {
128+ #[ serde( default , skip_serializing_if = "Vec::is_empty" ) ]
129+ pub bounding : Vec < LinuxCapabilityType > ,
130+ #[ serde( default , skip_serializing_if = "Vec::is_empty" ) ]
131+ pub effective : Vec < LinuxCapabilityType > ,
132+ #[ serde( default , skip_serializing_if = "Vec::is_empty" ) ]
133+ pub inheritable : Vec < LinuxCapabilityType > ,
134+ #[ serde( default , skip_serializing_if = "Vec::is_empty" ) ]
135+ pub permitted : Vec < LinuxCapabilityType > ,
136+ #[ serde( default , skip_serializing_if = "Vec::is_empty" ) ]
137+ pub ambient : Vec < LinuxCapabilityType > ,
138+ }
139+
126140#[ derive( Serialize , Deserialize , Debug ) ]
127141pub struct Process {
128142 #[ serde( default , skip_serializing_if = "is_false" ) ]
@@ -136,8 +150,9 @@ pub struct Process {
136150 pub env : Vec < String > ,
137151 #[ serde( default , skip_serializing_if = "String::is_empty" ) ]
138152 pub cwd : String ,
139- #[ serde( default , skip_serializing_if = "Vec::is_empty" ) ]
140- pub capabilities : Vec < LinuxCapabilityType > ,
153+ #[ serde( default , deserialize_with = "deserialize_capabilities" ,
154+ skip_serializing_if = "Option::is_none" ) ]
155+ pub capabilities : Option < LinuxCapabilities > ,
141156 #[ serde( default , skip_serializing_if = "Vec::is_empty" ) ]
142157 pub rlimits : Vec < LinuxRlimit > ,
143158 #[ serde( default , skip_serializing_if = "is_false" ,
@@ -151,6 +166,84 @@ pub struct Process {
151166 pub selinux_label : String ,
152167}
153168
169+ use serde:: Deserialize ;
170+
171+ fn cap_from_array < D > (
172+ a : & [ serde_json:: Value ] ,
173+ ) -> Result < Vec < LinuxCapabilityType > , D :: Error >
174+ where
175+ D : serde:: Deserializer ,
176+ {
177+ let mut caps = Vec :: new ( ) ;
178+ for c in a {
179+ match LinuxCapabilityType :: deserialize ( c) {
180+ Ok ( val) => caps. push ( val) ,
181+ Err ( _) => {
182+ let msg = format ! ( "Capability '{}' is not valid" , c) ;
183+ return Err ( serde:: de:: Error :: custom ( msg) ) ;
184+ }
185+ }
186+ }
187+ Ok ( caps)
188+ }
189+
190+ fn cap_from_object < D > (
191+ o : & serde_json:: Map < String , serde_json:: Value > ,
192+ key : & str ,
193+ ) -> Result < Vec < LinuxCapabilityType > , D :: Error >
194+ where
195+ D : serde:: Deserializer ,
196+ {
197+ if let Some ( v) = o. get ( key) {
198+ match * v {
199+ serde_json:: Value :: Null => Ok ( Vec :: new ( ) ) ,
200+ serde_json:: Value :: Array ( ref a) => cap_from_array :: < D > ( a) ,
201+ _ => Err ( serde:: de:: Error :: custom (
202+ "Unexpected value in capability set" ,
203+ ) ) ,
204+ }
205+ } else {
206+ Ok ( Vec :: new ( ) )
207+ }
208+ }
209+
210+ // handle the old case where caps was just a list of caps
211+ fn deserialize_capabilities < D > (
212+ de : D ,
213+ ) -> Result < Option < LinuxCapabilities > , D :: Error >
214+ where
215+ D : serde:: Deserializer ,
216+ {
217+ let r: serde_json:: Value = serde:: Deserialize :: deserialize ( de) ?;
218+ match r {
219+ serde_json:: Value :: Null => Ok ( None ) ,
220+ serde_json:: Value :: Array ( a) => {
221+ let caps = cap_from_array :: < D > ( & a) ?;
222+ let capabilities = LinuxCapabilities {
223+ bounding : caps. clone ( ) ,
224+ effective : caps. clone ( ) ,
225+ inheritable : caps. clone ( ) ,
226+ permitted : caps. clone ( ) ,
227+ ambient : caps. clone ( ) ,
228+ } ;
229+
230+ Ok ( Some ( capabilities) )
231+ }
232+ serde_json:: Value :: Object ( o) => {
233+ let capabilities = LinuxCapabilities {
234+ bounding : cap_from_object :: < D > ( & o, "bounding" ) ?,
235+ effective : cap_from_object :: < D > ( & o, "effective" ) ?,
236+ inheritable : cap_from_object :: < D > ( & o, "inheritable" ) ?,
237+ permitted : cap_from_object :: < D > ( & o, "permitted" ) ?,
238+ ambient : cap_from_object :: < D > ( & o, "ambient" ) ?,
239+ } ;
240+
241+ Ok ( Some ( capabilities) )
242+ }
243+ _ => Err ( serde:: de:: Error :: custom ( "Unexpected value in capabilites" ) ) ,
244+ }
245+ }
246+
154247#[ derive( Serialize , Deserialize , Debug ) ]
155248pub struct Root {
156249 #[ serde( default ) ]
@@ -467,8 +560,11 @@ pub struct LinuxSeccompArg {
467560
468561#[ derive( Serialize , Deserialize , Debug ) ]
469562pub struct LinuxSyscall {
563+ // old version used name
470564 #[ serde( default , skip_serializing_if = "String::is_empty" ) ]
471565 pub name : String ,
566+ #[ serde( default , skip_serializing_if = "Vec::is_empty" ) ]
567+ pub names : Vec < String > ,
472568 pub action : LinuxSeccompAction ,
473569 #[ serde( default , skip_serializing_if = "Vec::is_empty" ) ]
474570 pub args : Vec < LinuxSeccompArg > ,
0 commit comments