@@ -8,8 +8,10 @@ use crate::container::{Config, ExportOpts, ImageReference, Transport};
8
8
use crate :: objectsource:: { ObjectMeta , ObjectSourceMeta } ;
9
9
use crate :: objgv:: gv_dirtree;
10
10
use crate :: prelude:: * ;
11
+ use crate :: tar:: SECURITY_SELINUX_XATTR_C ;
11
12
use crate :: { gio, glib} ;
12
13
use anyhow:: { anyhow, Context , Result } ;
14
+ use bootc_utils:: CommandRunExt ;
13
15
use camino:: { Utf8Component , Utf8Path , Utf8PathBuf } ;
14
16
use cap_std:: fs:: Dir ;
15
17
use cap_std_ext:: cap_std;
@@ -25,6 +27,7 @@ use ocidir::oci_spec::image::ImageConfigurationBuilder;
25
27
use once_cell:: sync:: Lazy ;
26
28
use regex:: Regex ;
27
29
use std:: borrow:: Cow ;
30
+ use std:: ffi:: CString ;
28
31
use std:: fmt:: Write as _;
29
32
use std:: io:: { self , Write } ;
30
33
use std:: ops:: Add ;
@@ -46,12 +49,19 @@ enum FileDefType {
46
49
Directory ,
47
50
}
48
51
52
+ #[ derive( Debug ) ]
53
+ struct Xattr {
54
+ key : CString ,
55
+ value : Box < [ u8 ] > ,
56
+ }
57
+
49
58
#[ derive( Debug ) ]
50
59
pub struct FileDef {
51
60
uid : u32 ,
52
61
gid : u32 ,
53
62
mode : u32 ,
54
63
path : Cow < ' static , Utf8Path > ,
64
+ xattrs : Box < [ Xattr ] > ,
55
65
ty : FileDefType ,
56
66
}
57
67
@@ -66,9 +76,21 @@ impl TryFrom<&'static str> for FileDef {
66
76
let name = parts. next ( ) . ok_or_else ( || anyhow ! ( "Missing file name" ) ) ?;
67
77
let contents = parts. next ( ) ;
68
78
let contents = move || contents. ok_or_else ( || anyhow ! ( "Missing file contents: {}" , value) ) ;
69
- if parts. next ( ) . is_some ( ) {
70
- anyhow:: bail!( "Invalid filedef: {}" , value) ;
71
- }
79
+ let xattrs: Result < Vec < _ > > = parts
80
+ . map ( |xattr| -> Result < Xattr > {
81
+ let ( k, v) = xattr
82
+ . split_once ( '=' )
83
+ . ok_or_else ( || anyhow:: anyhow!( "Invalid xattr: {xattr}" ) ) ?;
84
+ let mut k: Vec < u8 > = k. to_owned ( ) . into ( ) ;
85
+ k. push ( 0 ) ;
86
+ let r = Xattr {
87
+ key : CString :: from_vec_with_nul ( k) . unwrap ( ) ,
88
+ value : Vec :: from ( v. to_owned ( ) ) . into ( ) ,
89
+ } ;
90
+ Ok ( r)
91
+ } )
92
+ . collect ( ) ;
93
+ let xattrs = xattrs?. into ( ) ;
72
94
let ty = match tydef {
73
95
"r" => FileDefType :: Regular ( contents ( ) ?. into ( ) ) ,
74
96
"l" => FileDefType :: Symlink ( Cow :: Borrowed ( contents ( ) ?. into ( ) ) ) ,
@@ -80,6 +102,7 @@ impl TryFrom<&'static str> for FileDef {
80
102
gid : 0 ,
81
103
mode : 0o644 ,
82
104
path : Cow :: Borrowed ( name. into ( ) ) ,
105
+ xattrs,
83
106
ty,
84
107
} )
85
108
}
@@ -165,6 +188,7 @@ static OWNERS: Lazy<Vec<(Regex, &str)>> = Lazy::new(|| {
165
188
( "usr/lib/modules/.*/initramfs" , "initramfs" ) ,
166
189
( "usr/lib/modules" , "kernel" ) ,
167
190
( "usr/bin/(ba)?sh" , "bash" ) ,
191
+ ( "usr/bin/arping" , "arping" ) ,
168
192
( "usr/lib.*/emptyfile.*" , "bash" ) ,
169
193
( "usr/bin/hardlink.*" , "testlink" ) ,
170
194
( "usr/etc/someconfig.conf" , "someconfig" ) ,
@@ -184,6 +208,7 @@ r usr/lib/modules/5.10.18-200.x86_64/initramfs this-is-an-initramfs
184
208
m 0 0 755
185
209
r usr/bin/bash the-bash-shell
186
210
l usr/bin/sh bash
211
+ r usr/bin/arping arping-binary security.capability=0sAAAAAgAgAAAAAAAAAAAAAAAAAAA=
187
212
m 0 0 644
188
213
# Some empty files
189
214
r usr/lib/emptyfile
@@ -206,7 +231,7 @@ m 0 0 1755
206
231
d tmp
207
232
"## } ;
208
233
pub const CONTENTS_CHECKSUM_V0 : & str =
209
- "acc42fb5c796033f034941dc688643bf8beddfd9068d87165344d2b99906220a " ;
234
+ "bd3d13c3059e63e6f8a3d6d046923ded730d90bd7a055c9ad93312111ea7d395 " ;
210
235
// 1 for ostree commit, 2 for max frequency packages, 3 as empty layer
211
236
pub const LAYERS_V0_LEN : usize = 3usize ;
212
237
pub const PKGS_V0_LEN : usize = 7usize ;
@@ -267,11 +292,10 @@ impl SeLabel {
267
292
}
268
293
269
294
pub fn xattrs ( & self ) -> Vec < ( & [ u8 ] , & [ u8 ] ) > {
270
- vec ! [ ( b"security.selinux\0 " , self . to_str( ) . as_bytes( ) ) ]
271
- }
272
-
273
- pub fn new_xattrs ( & self ) -> glib:: Variant {
274
- self . xattrs ( ) . to_variant ( )
295
+ vec ! [ (
296
+ SECURITY_SELINUX_XATTR_C . to_bytes_with_nul( ) ,
297
+ self . to_str( ) . as_bytes( ) ,
298
+ ) ]
275
299
}
276
300
}
277
301
@@ -286,7 +310,7 @@ pub fn create_dirmeta(path: &Utf8Path, selinux: bool) -> glib::Variant {
286
310
} else {
287
311
None
288
312
} ;
289
- let xattrs = label. map ( |v| v. new_xattrs ( ) ) ;
313
+ let xattrs = label. map ( |v| v. xattrs ( ) . to_variant ( ) ) ;
290
314
ostree:: create_directory_metadata ( & finfo, xattrs. as_ref ( ) )
291
315
}
292
316
@@ -632,7 +656,18 @@ impl Fixture {
632
656
} else {
633
657
None
634
658
} ;
635
- let xattrs = label. map ( |v| v. new_xattrs ( ) ) ;
659
+ let mut xattrs = label. as_ref ( ) . map ( |v| v. xattrs ( ) ) . unwrap_or_default ( ) ;
660
+ xattrs. extend (
661
+ def. xattrs
662
+ . iter ( )
663
+ . map ( |xattr| ( xattr. key . as_bytes_with_nul ( ) , & xattr. value [ ..] ) ) ,
664
+ ) ;
665
+ let xattrs = if xattrs. is_empty ( ) {
666
+ None
667
+ } else {
668
+ xattrs. sort_by ( |a, b| a. 0 . cmp ( b. 0 ) ) ;
669
+ Some ( xattrs. to_variant ( ) )
670
+ } ;
636
671
let xattrs = xattrs. as_ref ( ) ;
637
672
let checksum = match & def. ty {
638
673
FileDefType :: Regular ( contents) => self
@@ -724,6 +759,21 @@ impl Fixture {
724
759
gio:: Cancellable :: NONE ,
725
760
) ?;
726
761
762
+ // Verify that this is what is expected.
763
+ let commit_object = self . srcrepo . load_commit ( & commit) ?. 0 ;
764
+ let content_checksum = ostree:: commit_get_content_checksum ( & commit_object) . unwrap ( ) ;
765
+ if content_checksum != CONTENTS_CHECKSUM_V0 {
766
+ // Only spew this once
767
+ static DUMP_OSTREE : std:: sync:: Once = std:: sync:: Once :: new ( ) ;
768
+ DUMP_OSTREE . call_once ( || {
769
+ let _ = Command :: new ( "ostree" )
770
+ . arg ( format ! ( "--repo={}" , self . path. join( "src/repo" ) ) )
771
+ . args ( [ "ls" , "-X" , "-C" , "-R" , commit. as_str ( ) ] )
772
+ . run ( ) ;
773
+ } ) ;
774
+ }
775
+ assert_eq ! ( CONTENTS_CHECKSUM_V0 , content_checksum. as_str( ) ) ;
776
+
727
777
Ok ( ( ) )
728
778
}
729
779
0 commit comments