1
1
// Copyright 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved.
2
2
// SPDX-License-Identifier: Apache-2.0
3
3
4
- use std:: ffi:: { CString , OsString } ;
4
+ use std:: ffi:: { CStr , CString , OsString } ;
5
5
use std:: fs:: { self , canonicalize, read_to_string, File , OpenOptions , Permissions } ;
6
6
use std:: io;
7
7
use std:: io:: Write ;
@@ -30,19 +30,19 @@ const STDERR_FILENO: libc::c_int = 2;
30
30
// Kernel-based virtual machine (hardware virtualization extensions)
31
31
// minor/major numbers are taken from
32
32
// 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";
34
34
const DEV_KVM_MAJOR : u32 = 10 ;
35
35
const DEV_KVM_MINOR : u32 = 232 ;
36
36
37
37
// TUN/TAP device minor/major numbers are taken from
38
38
// 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";
40
40
const DEV_NET_TUN_MAJOR : u32 = 10 ;
41
41
const DEV_NET_TUN_MINOR : u32 = 200 ;
42
42
43
43
// Random number generator device minor/major numbers are taken from
44
44
// 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";
46
46
const DEV_URANDOM_MAJOR : u32 = 1 ;
47
47
const DEV_URANDOM_MINOR : u32 = 9 ;
48
48
@@ -54,7 +54,7 @@ const DEV_URANDOM_MINOR: u32 = 9;
54
54
// so we will have to find it at initialization time parsing /proc/misc.
55
55
// What we do know is the major number for misc devices:
56
56
// 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";
58
58
const DEV_UFFD_MAJOR : u32 = 10 ;
59
59
60
60
// Relevant folders inside the jail that we create or/and for which we change ownership.
@@ -425,18 +425,17 @@ impl Env {
425
425
426
426
fn mknod_and_own_dev (
427
427
& self ,
428
- dev_path_str : & ' static str ,
428
+ dev_path : & CStr ,
429
429
dev_major : u32 ,
430
430
dev_minor : u32 ,
431
431
) -> Result < ( ) , JailerError > {
432
- let dev_path = CString :: new ( dev_path_str) . unwrap ( ) ;
433
432
// As per sysstat.h:
434
433
// S_IFCHR -> character special device
435
434
// S_IRUSR -> read permission, owner
436
435
// S_IWUSR -> write permission, owner
437
436
// See www.kernel.org/doc/Documentation/networking/tuntap.txt, 'Configuration' chapter for
438
437
// 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.
440
439
SyscallReturnCode ( unsafe {
441
440
libc:: mknod (
442
441
dev_path. as_ptr ( ) ,
@@ -445,7 +444,7 @@ impl Env {
445
444
)
446
445
} )
447
446
. 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 ( ) ) ) ?;
449
448
450
449
// SAFETY: This is safe because dev_path is CStr, and hence null-terminated.
451
450
SyscallReturnCode ( unsafe { libc:: chown ( dev_path. as_ptr ( ) , self . uid ( ) , self . gid ( ) ) } )
@@ -663,14 +662,14 @@ impl Env {
663
662
// $: mknod $dev_net_tun_path c 10 200
664
663
// www.kernel.org/doc/Documentation/networking/tuntap.txt specifies 10 and 200 as the major
665
664
// 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 ) ?;
667
666
// 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 ) ?;
669
668
// And for /dev/urandom with (major, minor) = (1, 9).
670
669
// If the device is not accessible on the host, output a warning to inform user that MMDS
671
670
// version 2 will not be available to use.
672
671
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 )
674
673
. map_err ( |err| {
675
674
println ! (
676
675
"Warning! Could not create /dev/urandom device inside jailer: {}." ,
@@ -1116,14 +1115,14 @@ mod tests {
1116
1115
// process management; it can't be isolated from side effects.
1117
1116
}
1118
1117
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 ) {
1120
1119
use std:: os:: unix:: fs:: FileTypeExt ;
1121
1120
1122
1121
// Create a new device node.
1123
1122
env. mknod_and_own_dev ( dev_path, major, minor) . unwrap ( ) ;
1124
1123
1125
1124
// Ensure device's properties.
1126
- let metadata = fs:: metadata ( dev_path) . unwrap ( ) ;
1125
+ let metadata = fs:: metadata ( dev_path. to_str ( ) . unwrap ( ) ) . unwrap ( ) ;
1127
1126
assert ! ( metadata. file_type( ) . is_char_device( ) ) ;
1128
1127
assert_eq ! ( get_major( metadata. st_rdev( ) ) , major) ;
1129
1128
assert_eq ! ( get_minor( metadata. st_rdev( ) ) , minor) ;
@@ -1140,7 +1139,7 @@ mod tests {
1140
1139
) ,
1141
1140
format!(
1142
1141
"Failed to create {} via mknod inside the jail: File exists (os error 17)" ,
1143
- dev_path
1142
+ dev_path. to_str ( ) . unwrap ( )
1144
1143
)
1145
1144
) ;
1146
1145
}
@@ -1152,25 +1151,25 @@ mod tests {
1152
1151
let env = create_env ( mock_cgroups. proc_mounts_path . as_str ( ) ) ;
1153
1152
1154
1153
// 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 ) ,
1158
1157
] ;
1159
1158
1160
1159
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) ) ;
1162
1161
}
1163
1162
1164
1163
for ( dev, major, minor) in dev_infos {
1165
1164
// Checking this just to be super sure there's no file at `dev_str` path (though
1166
1165
// 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 ( ) ;
1169
1168
}
1170
1169
1171
1170
ensure_mknod_and_own_dev ( & env, dev, major, minor) ;
1172
1171
// 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." ) ;
1174
1173
}
1175
1174
}
1176
1175
@@ -1180,7 +1179,7 @@ mod tests {
1180
1179
mock_cgroups. add_v1_mounts ( ) . unwrap ( ) ;
1181
1180
let env = create_env ( mock_cgroups. proc_mounts_path . as_str ( ) ) ;
1182
1181
1183
- if !Path :: new ( DEV_UFFD_PATH ) . exists ( ) {
1182
+ if !Path :: new ( DEV_UFFD_PATH . to_str ( ) . unwrap ( ) ) . exists ( ) {
1184
1183
assert_eq ! ( env. uffd_dev_minor, None ) ;
1185
1184
} else {
1186
1185
assert ! ( env. uffd_dev_minor. is_some( ) ) ;
0 commit comments