@@ -355,6 +355,29 @@ fn capset(result: &CapInternalResult) -> anyhow::Result<()> {
355355 }
356356}
357357
358+ fn cap_data_to_result ( data : & [ CapInternalData ; 2 ] ) -> CapResult {
359+ CapResult {
360+ effective : ( ( data[ 1 ] . effective as u64 ) << 32 ) | data[ 0 ] . effective as u64 ,
361+ permitted : ( ( data[ 1 ] . permitted as u64 ) << 32 ) | data[ 0 ] . permitted as u64 ,
362+ inheritable : ( ( data[ 1 ] . inheritable as u64 ) << 32 ) | data[ 0 ] . inheritable as u64 ,
363+ }
364+ }
365+
366+ fn cap_result_to_data ( caps : & CapResult ) -> [ CapInternalData ; 2 ] {
367+ [
368+ CapInternalData {
369+ effective : caps. effective as u32 ,
370+ permitted : caps. permitted as u32 ,
371+ inheritable : caps. inheritable as u32 ,
372+ } ,
373+ CapInternalData {
374+ effective : ( caps. effective >> 32 ) as u32 ,
375+ permitted : ( caps. permitted >> 32 ) as u32 ,
376+ inheritable : ( caps. inheritable >> 32 ) as u32 ,
377+ } ,
378+ ]
379+ }
380+
358381pub fn get_caps ( ) -> anyhow:: Result < CapResult > {
359382 let pid = std:: process:: id ( ) as i32 ;
360383 let mut iresult = CapInternalResult {
@@ -367,23 +390,14 @@ pub fn get_caps() -> anyhow::Result<CapResult> {
367390
368391 capget ( & mut iresult) ?;
369392
370- let effective = ( ( iresult. data [ 0 ] . effective as u64 ) << 32 ) | iresult. data [ 1 ] . effective as u64 ;
371- let permitted = ( ( iresult. data [ 0 ] . permitted as u64 ) << 32 ) | iresult. data [ 1 ] . permitted as u64 ;
372- let inheritable =
373- ( ( iresult. data [ 0 ] . inheritable as u64 ) << 32 ) | iresult. data [ 1 ] . inheritable as u64 ;
374-
375- let finalresult = CapResult {
376- effective,
377- permitted,
378- inheritable,
379- } ;
393+ let result = cap_data_to_result ( & iresult. data ) ;
380394
381395 debug ! (
382- "get capabilities of pid {}: eff={:x} perm={:x} inh={:? }" ,
383- iresult. header. pid, effective, permitted, inheritable
396+ "get capabilities of pid {}: eff={:x} perm={:x} inh={:x }" ,
397+ iresult. header. pid, result . effective, result . permitted, result . inheritable
384398 ) ;
385399
386- Ok ( finalresult )
400+ Ok ( result )
387401}
388402
389403pub fn set_caps ( caps : CapResult ) -> anyhow:: Result < ( ) > {
@@ -399,18 +413,7 @@ pub fn set_caps(caps: CapResult) -> anyhow::Result<()> {
399413 version : _LINUX_CAPABILITY_VERSION_3,
400414 pid,
401415 } ,
402- data : [
403- CapInternalData {
404- effective : ( caps. effective >> 32 ) as u32 ,
405- permitted : ( caps. permitted >> 32 ) as u32 ,
406- inheritable : ( caps. inheritable >> 32 ) as u32 ,
407- } ,
408- CapInternalData {
409- effective : caps. effective as u32 ,
410- permitted : caps. permitted as u32 ,
411- inheritable : caps. inheritable as u32 ,
412- } ,
413- ] ,
416+ data : cap_result_to_data ( & caps) ,
414417 } ;
415418
416419 capset ( & iresult) ?;
@@ -429,3 +432,72 @@ pub fn set_keep_caps() -> anyhow::Result<()> {
429432 Ok ( ( ) )
430433 }
431434}
435+
436+ #[ cfg( test) ]
437+ mod tests {
438+ use super :: * ;
439+
440+ #[ test]
441+ fn test_cap_encoding_word_order ( ) {
442+ // Low caps only (0-31): CAP_CHOWN=0, CAP_NET_RAW=13, CAP_SETFCAP=31
443+ let low_caps = CapabilityBit :: raw_bits ( & [
444+ CapabilityBit :: Chown ,
445+ CapabilityBit :: NetRaw ,
446+ CapabilityBit :: Setfcap ,
447+ ] ) ;
448+ let input = CapResult {
449+ effective : low_caps,
450+ permitted : low_caps,
451+ inheritable : low_caps,
452+ } ;
453+ let data = cap_result_to_data ( & input) ;
454+ assert_eq ! (
455+ data[ 0 ] . effective, low_caps as u32 ,
456+ "data[0] must hold low 32 bits (caps 0-31)"
457+ ) ;
458+ assert_eq ! (
459+ data[ 1 ] . effective, 0u32 ,
460+ "data[1] must be zero for low-only caps"
461+ ) ;
462+ let rt = cap_data_to_result ( & data) ;
463+ assert_eq ! ( rt. effective, low_caps) ;
464+
465+ // High caps only (32-63): CAP_MAC_OVERRIDE=32, CAP_CHECKPOINT_RESTORE=40
466+ let high_caps = CapabilityBit :: raw_bits ( & [
467+ CapabilityBit :: MacOverride ,
468+ CapabilityBit :: CheckpointRestore ,
469+ ] ) ;
470+ let input = CapResult {
471+ effective : high_caps,
472+ permitted : high_caps,
473+ inheritable : high_caps,
474+ } ;
475+ let data = cap_result_to_data ( & input) ;
476+ assert_eq ! (
477+ data[ 0 ] . effective, 0u32 ,
478+ "data[0] must be zero for high-only caps"
479+ ) ;
480+ assert_eq ! (
481+ data[ 1 ] . effective,
482+ ( high_caps >> 32 ) as u32 ,
483+ "data[1] must hold high 32 bits (caps 32-63)"
484+ ) ;
485+ let rt = cap_data_to_result ( & data) ;
486+ assert_eq ! ( rt. effective, high_caps) ;
487+
488+ // All caps: bits 0-40
489+ let all_caps = CapabilityBit :: raw_bits ( CapabilityBit :: ALL ) ;
490+ let input = CapResult {
491+ effective : all_caps,
492+ permitted : all_caps,
493+ inheritable : all_caps,
494+ } ;
495+ let data = cap_result_to_data ( & input) ;
496+ assert_eq ! ( data[ 0 ] . effective, all_caps as u32 ) ;
497+ assert_eq ! ( data[ 1 ] . effective, ( all_caps >> 32 ) as u32 ) ;
498+ let rt = cap_data_to_result ( & data) ;
499+ assert_eq ! ( rt. effective, all_caps) ;
500+ assert_eq ! ( rt. permitted, all_caps) ;
501+ assert_eq ! ( rt. inheritable, all_caps) ;
502+ }
503+ }
0 commit comments