@@ -15,14 +15,18 @@ use crate::utils::{as_ptr, check_raw_pointer};
1515use alloc:: vec:: Vec ;
1616use core:: mem:: size_of;
1717use core:: ptr:: { null_mut, read_unaligned, NonNull } ;
18+ #[ cfg( feature = "runtime" ) ]
19+ use core:: sync:: atomic:: AtomicU8 ;
1820use core:: sync:: atomic:: Ordering :: Relaxed ;
1921use core:: sync:: atomic:: { AtomicPtr , AtomicUsize } ;
2022use linux_raw_sys:: elf:: * ;
2123use linux_raw_sys:: general:: {
2224 AT_BASE , AT_CLKTCK , AT_EXECFN , AT_HWCAP , AT_HWCAP2 , AT_NULL , AT_PAGESZ , AT_SYSINFO_EHDR ,
2325} ;
2426#[ cfg( feature = "runtime" ) ]
25- use linux_raw_sys:: general:: { AT_ENTRY , AT_PHDR , AT_PHENT , AT_PHNUM } ;
27+ use linux_raw_sys:: general:: {
28+ AT_EGID , AT_ENTRY , AT_EUID , AT_GID , AT_PHDR , AT_PHENT , AT_PHNUM , AT_SECURE , AT_UID ,
29+ } ;
2630
2731#[ cfg( feature = "param" ) ]
2832#[ inline]
@@ -80,6 +84,23 @@ pub(crate) fn linux_execfn() -> &'static CStr {
8084 unsafe { CStr :: from_ptr ( execfn. cast ( ) ) }
8185}
8286
87+ #[ cfg( feature = "runtime" ) ]
88+ #[ inline]
89+ pub ( crate ) fn linux_secure ( ) -> bool {
90+ let mut secure = SECURE . load ( Relaxed ) ;
91+
92+ // 0 means not initialized yet.
93+ if secure == 0 {
94+ init_auxv ( ) ;
95+ secure = SECURE . load ( Relaxed ) ;
96+ }
97+
98+ // 0 means not present. Libc `getauxval(AT_SECURE)` would return 0.
99+ // 1 means not in secure mode.
100+ // 2 means in secure mode.
101+ secure > 1
102+ }
103+
83104#[ cfg( feature = "runtime" ) ]
84105#[ inline]
85106pub ( crate ) fn exe_phdrs ( ) -> ( * const c:: c_void , usize , usize ) {
@@ -131,6 +152,8 @@ static HWCAP2: AtomicUsize = AtomicUsize::new(0);
131152static EXECFN : AtomicPtr < c:: c_char > = AtomicPtr :: new ( null_mut ( ) ) ;
132153static SYSINFO_EHDR : AtomicPtr < Elf_Ehdr > = AtomicPtr :: new ( null_mut ( ) ) ;
133154#[ cfg( feature = "runtime" ) ]
155+ static SECURE : AtomicU8 = AtomicU8 :: new ( 0 ) ;
156+ #[ cfg( feature = "runtime" ) ]
134157static PHDR : AtomicPtr < Elf_Phdr > = AtomicPtr :: new ( null_mut ( ) ) ;
135158#[ cfg( feature = "runtime" ) ]
136159static PHENT : AtomicUsize = AtomicUsize :: new ( 0 ) ;
@@ -256,13 +279,23 @@ unsafe fn init_from_aux_iter(aux_iter: impl Iterator<Item = Elf_auxv_t>) -> Opti
256279 let mut execfn = null_mut ( ) ;
257280 let mut sysinfo_ehdr = null_mut ( ) ;
258281 #[ cfg( feature = "runtime" ) ]
282+ let mut secure = 0 ;
283+ #[ cfg( feature = "runtime" ) ]
259284 let mut phdr = null_mut ( ) ;
260285 #[ cfg( feature = "runtime" ) ]
261286 let mut phnum = 0 ;
262287 #[ cfg( feature = "runtime" ) ]
263288 let mut phent = 0 ;
264289 #[ cfg( feature = "runtime" ) ]
265290 let mut entry = 0 ;
291+ #[ cfg( feature = "runtime" ) ]
292+ let mut uid = None ;
293+ #[ cfg( feature = "runtime" ) ]
294+ let mut euid = None ;
295+ #[ cfg( feature = "runtime" ) ]
296+ let mut gid = None ;
297+ #[ cfg( feature = "runtime" ) ]
298+ let mut egid = None ;
266299
267300 for Elf_auxv_t { a_type, a_val } in aux_iter {
268301 match a_type as _ {
@@ -277,6 +310,16 @@ unsafe fn init_from_aux_iter(aux_iter: impl Iterator<Item = Elf_auxv_t>) -> Opti
277310 let _ = check_elf_base ( a_val. cast ( ) ) ?;
278311 }
279312
313+ #[ cfg( feature = "runtime" ) ]
314+ AT_SECURE => secure = ( a_val as usize != 0 ) as u8 + 1 ,
315+ #[ cfg( feature = "runtime" ) ]
316+ AT_UID => uid = Some ( a_val) ,
317+ #[ cfg( feature = "runtime" ) ]
318+ AT_EUID => euid = Some ( a_val) ,
319+ #[ cfg( feature = "runtime" ) ]
320+ AT_GID => gid = Some ( a_val) ,
321+ #[ cfg( feature = "runtime" ) ]
322+ AT_EGID => egid = Some ( a_val) ,
280323 #[ cfg( feature = "runtime" ) ]
281324 AT_PHDR => phdr = check_raw_pointer :: < Elf_Phdr > ( a_val as * mut _ ) ?. as_ptr ( ) ,
282325 #[ cfg( feature = "runtime" ) ]
@@ -294,15 +337,25 @@ unsafe fn init_from_aux_iter(aux_iter: impl Iterator<Item = Elf_auxv_t>) -> Opti
294337 #[ cfg( feature = "runtime" ) ]
295338 assert_eq ! ( phent, size_of:: <Elf_Phdr >( ) ) ;
296339
297- // The base and sysinfo_ehdr (if present) matches our platform. Accept
298- // the aux values.
340+ // If we're running set-uid or set-gid, enable "secure execution" mode,
341+ // which doesn't do much, but users may be depending on the things that
342+ // it does do.
343+ #[ cfg( feature = "runtime" ) ]
344+ if uid != euid || gid != egid {
345+ secure = 2 ;
346+ }
347+
348+ // The base and sysinfo_ehdr (if present) matches our platform. Accept the
349+ // aux values.
299350 PAGE_SIZE . store ( pagesz, Relaxed ) ;
300351 CLOCK_TICKS_PER_SECOND . store ( clktck, Relaxed ) ;
301352 HWCAP . store ( hwcap, Relaxed ) ;
302353 HWCAP2 . store ( hwcap2, Relaxed ) ;
303354 EXECFN . store ( execfn, Relaxed ) ;
304355 SYSINFO_EHDR . store ( sysinfo_ehdr, Relaxed ) ;
305356 #[ cfg( feature = "runtime" ) ]
357+ SECURE . store ( secure, Relaxed ) ;
358+ #[ cfg( feature = "runtime" ) ]
306359 PHDR . store ( phdr, Relaxed ) ;
307360 #[ cfg( feature = "runtime" ) ]
308361 PHNUM . store ( phnum, Relaxed ) ;
0 commit comments