1- use libc;
2-
31use std:: env;
42use std:: ffi:: CString ;
53use std:: fs;
@@ -22,7 +20,8 @@ use crate::signal;
2220use crate :: unshare:: { setns, unshare} ;
2321use anyhow:: { Result , anyhow, bail} ;
2422use libc:: {
25- PR_CAP_AMBIENT , PR_CAP_AMBIENT_LOWER , PR_CAP_AMBIENT_RAISE , PR_CAPBSET_DROP , c_int, prctl,
23+ self , PR_CAP_AMBIENT , PR_CAP_AMBIENT_LOWER , PR_CAP_AMBIENT_RAISE , PR_CAPBSET_DROP ,
24+ PR_SET_NO_NEW_PRIVS , c_int, prctl,
2625} ;
2726
2827use log:: { debug, error, warn} ;
@@ -569,6 +568,10 @@ impl ExecutableSpec {
569568 env:: set_current_dir ( wd. clone ( ) ) ?;
570569 }
571570
571+ if self . no_new_privs {
572+ self . set_no_new_privs ( ) ?;
573+ }
574+
572575 unsafe {
573576 if libc:: execvpe (
574577 program_cstring. as_ptr ( ) ,
@@ -611,6 +614,21 @@ impl ExecutableSpec {
611614
612615 Ok ( ( ) )
613616 }
617+
618+ // Note that `PR_SET_NO_NEW_PRIVS` is *not* a foolproof privilege escalation
619+ // setting - it just "locks" the privilege set. If the process is granted
620+ // CAP_ADMIN or similar elsewhere, it is trivial to escalate privs in spite of this flag.
621+ fn set_no_new_privs ( & self ) -> Result < ( ) > {
622+ let error = unsafe { prctl ( PR_SET_NO_NEW_PRIVS , 1 , 0 , 0 , 0 ) } ;
623+ if error != 0 {
624+ bail ! (
625+ "failed to set no_new_privs flag: {}" ,
626+ Error :: last_os_error( )
627+ ) ;
628+ }
629+
630+ Ok ( ( ) )
631+ }
614632}
615633
616634impl AttachRequest {
0 commit comments