11// Copyright 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved.
22// SPDX-License-Identifier: Apache-2.0
33
4- use std:: ffi:: { CString , OsString } ;
4+ use std:: ffi:: { CStr , CString , OsString } ;
55use std:: fs:: { self , canonicalize, read_to_string, File , OpenOptions , Permissions } ;
66use std:: io;
77use std:: io:: Write ;
@@ -30,19 +30,19 @@ const STDERR_FILENO: libc::c_int = 2;
3030// Kernel-based virtual machine (hardware virtualization extensions)
3131// minor/major numbers are taken from
3232// https://www.kernel.org/doc/html/latest/admin-guide/devices.html
33- const DEV_KVM_WITH_NUL : & str = "/dev/kvm" ;
33+ const DEV_KVM : & CStr = c "/dev/kvm";
3434const DEV_KVM_MAJOR : u32 = 10 ;
3535const DEV_KVM_MINOR : u32 = 232 ;
3636
3737// TUN/TAP device minor/major numbers are taken from
3838// www.kernel.org/doc/Documentation/networking/tuntap.txt
39- const DEV_NET_TUN_WITH_NUL : & str = "/dev/net/tun" ;
39+ const DEV_NET_TUN : & CStr = c "/dev/net/tun";
4040const DEV_NET_TUN_MAJOR : u32 = 10 ;
4141const DEV_NET_TUN_MINOR : u32 = 200 ;
4242
4343// Random number generator device minor/major numbers are taken from
4444// https://www.kernel.org/doc/Documentation/admin-guide/devices.txt
45- const DEV_URANDOM_WITH_NUL : & str = "/dev/urandom" ;
45+ const DEV_URANDOM : & CStr = c "/dev/urandom";
4646const DEV_URANDOM_MAJOR : u32 = 1 ;
4747const DEV_URANDOM_MINOR : u32 = 9 ;
4848
@@ -54,7 +54,7 @@ const DEV_URANDOM_MINOR: u32 = 9;
5454// so we will have to find it at initialization time parsing /proc/misc.
5555// What we do know is the major number for misc devices:
5656// https://elixir.bootlin.com/linux/v6.1.51/source/Documentation/admin-guide/devices.txt
57- const DEV_UFFD_PATH : & str = "/dev/userfaultfd" ;
57+ const DEV_UFFD_PATH : & CStr = c "/dev/userfaultfd";
5858const DEV_UFFD_MAJOR : u32 = 10 ;
5959
6060// Relevant folders inside the jail that we create or/and for which we change ownership.
@@ -425,18 +425,17 @@ impl Env {
425425
426426 fn mknod_and_own_dev (
427427 & self ,
428- dev_path_str : & ' static str ,
428+ dev_path : & CStr ,
429429 dev_major : u32 ,
430430 dev_minor : u32 ,
431431 ) -> Result < ( ) , JailerError > {
432- let dev_path = CString :: new ( dev_path_str) . unwrap ( ) ;
433432 // As per sysstat.h:
434433 // S_IFCHR -> character special device
435434 // S_IRUSR -> read permission, owner
436435 // S_IWUSR -> write permission, owner
437436 // See www.kernel.org/doc/Documentation/networking/tuntap.txt, 'Configuration' chapter for
438437 // more clarity.
439- // SAFETY: This is safe because dev_path is CString , and hence null-terminated.
438+ // SAFETY: This is safe because dev_path is CStr , and hence null-terminated.
440439 SyscallReturnCode ( unsafe {
441440 libc:: mknod (
442441 dev_path. as_ptr ( ) ,
@@ -445,7 +444,7 @@ impl Env {
445444 )
446445 } )
447446 . into_empty_result ( )
448- . map_err ( |err| JailerError :: MknodDev ( err, dev_path_str . to_owned ( ) ) ) ?;
447+ . map_err ( |err| JailerError :: MknodDev ( err, dev_path . to_str ( ) . unwrap ( ) . to_owned ( ) ) ) ?;
449448
450449 // SAFETY: This is safe because dev_path is CStr, and hence null-terminated.
451450 SyscallReturnCode ( unsafe { libc:: chown ( dev_path. as_ptr ( ) , self . uid ( ) , self . gid ( ) ) } )
@@ -663,14 +662,14 @@ impl Env {
663662 // $: mknod $dev_net_tun_path c 10 200
664663 // www.kernel.org/doc/Documentation/networking/tuntap.txt specifies 10 and 200 as the major
665664 // and minor for the /dev/net/tun device.
666- self . mknod_and_own_dev ( DEV_NET_TUN_WITH_NUL , DEV_NET_TUN_MAJOR , DEV_NET_TUN_MINOR ) ?;
665+ self . mknod_and_own_dev ( DEV_NET_TUN , DEV_NET_TUN_MAJOR , DEV_NET_TUN_MINOR ) ?;
667666 // Do the same for /dev/kvm with (major, minor) = (10, 232).
668- self . mknod_and_own_dev ( DEV_KVM_WITH_NUL , DEV_KVM_MAJOR , DEV_KVM_MINOR ) ?;
667+ self . mknod_and_own_dev ( DEV_KVM , DEV_KVM_MAJOR , DEV_KVM_MINOR ) ?;
669668 // And for /dev/urandom with (major, minor) = (1, 9).
670669 // If the device is not accessible on the host, output a warning to inform user that MMDS
671670 // version 2 will not be available to use.
672671 let _ = self
673- . mknod_and_own_dev ( DEV_URANDOM_WITH_NUL , DEV_URANDOM_MAJOR , DEV_URANDOM_MINOR )
672+ . mknod_and_own_dev ( DEV_URANDOM , DEV_URANDOM_MAJOR , DEV_URANDOM_MINOR )
674673 . map_err ( |err| {
675674 println ! (
676675 "Warning! Could not create /dev/urandom device inside jailer: {}." ,
@@ -1116,14 +1115,14 @@ mod tests {
11161115 // process management; it can't be isolated from side effects.
11171116 }
11181117
1119- fn ensure_mknod_and_own_dev ( env : & Env , dev_path : & ' static str , major : u32 , minor : u32 ) {
1118+ fn ensure_mknod_and_own_dev ( env : & Env , dev_path : & CStr , major : u32 , minor : u32 ) {
11201119 use std:: os:: unix:: fs:: FileTypeExt ;
11211120
11221121 // Create a new device node.
11231122 env. mknod_and_own_dev ( dev_path, major, minor) . unwrap ( ) ;
11241123
11251124 // Ensure device's properties.
1126- let metadata = fs:: metadata ( dev_path) . unwrap ( ) ;
1125+ let metadata = fs:: metadata ( dev_path. to_str ( ) . unwrap ( ) ) . unwrap ( ) ;
11271126 assert ! ( metadata. file_type( ) . is_char_device( ) ) ;
11281127 assert_eq ! ( get_major( metadata. st_rdev( ) ) , major) ;
11291128 assert_eq ! ( get_minor( metadata. st_rdev( ) ) , minor) ;
@@ -1140,7 +1139,7 @@ mod tests {
11401139 ) ,
11411140 format!(
11421141 "Failed to create {} via mknod inside the jail: File exists (os error 17)" ,
1143- dev_path
1142+ dev_path. to_str ( ) . unwrap ( )
11441143 )
11451144 ) ;
11461145 }
@@ -1152,25 +1151,25 @@ mod tests {
11521151 let env = create_env ( mock_cgroups. proc_mounts_path . as_str ( ) ) ;
11531152
11541153 // Ensure device nodes are created with correct major/minor numbers and permissions.
1155- let mut dev_infos: Vec < ( & str , u32 , u32 ) > = vec ! [
1156- ( "/dev/net/tun-test" , DEV_NET_TUN_MAJOR , DEV_NET_TUN_MINOR ) ,
1157- ( "/dev/kvm-test" , DEV_KVM_MAJOR , DEV_KVM_MINOR ) ,
1154+ let mut dev_infos: Vec < ( & CStr , u32 , u32 ) > = vec ! [
1155+ ( c "/dev/net/tun-test", DEV_NET_TUN_MAJOR , DEV_NET_TUN_MINOR ) ,
1156+ ( c "/dev/kvm-test", DEV_KVM_MAJOR , DEV_KVM_MINOR ) ,
11581157 ] ;
11591158
11601159 if let Some ( uffd_dev_minor) = env. uffd_dev_minor {
1161- dev_infos. push ( ( "/dev/userfaultfd-test" , DEV_UFFD_MAJOR , uffd_dev_minor) ) ;
1160+ dev_infos. push ( ( c "/dev/userfaultfd-test", DEV_UFFD_MAJOR , uffd_dev_minor) ) ;
11621161 }
11631162
11641163 for ( dev, major, minor) in dev_infos {
11651164 // Checking this just to be super sure there's no file at `dev_str` path (though
11661165 // it shouldn't be as we deleted it at the end of the previous test run).
1167- if Path :: new ( dev) . exists ( ) {
1168- fs:: remove_file ( dev) . unwrap ( ) ;
1166+ if Path :: new ( dev. to_str ( ) . unwrap ( ) ) . exists ( ) {
1167+ fs:: remove_file ( dev. to_str ( ) . unwrap ( ) ) . unwrap ( ) ;
11691168 }
11701169
11711170 ensure_mknod_and_own_dev ( & env, dev, major, minor) ;
11721171 // Remove the device node.
1173- fs:: remove_file ( dev) . expect ( "Could not remove file." ) ;
1172+ fs:: remove_file ( dev. to_str ( ) . unwrap ( ) ) . expect ( "Could not remove file." ) ;
11741173 }
11751174 }
11761175
@@ -1180,7 +1179,7 @@ mod tests {
11801179 mock_cgroups. add_v1_mounts ( ) . unwrap ( ) ;
11811180 let env = create_env ( mock_cgroups. proc_mounts_path . as_str ( ) ) ;
11821181
1183- if !Path :: new ( DEV_UFFD_PATH ) . exists ( ) {
1182+ if !Path :: new ( DEV_UFFD_PATH . to_str ( ) . unwrap ( ) ) . exists ( ) {
11841183 assert_eq ! ( env. uffd_dev_minor, None ) ;
11851184 } else {
11861185 assert ! ( env. uffd_dev_minor. is_some( ) ) ;
0 commit comments