@@ -13,6 +13,7 @@ use mount_options::{check_option_conflicts, parse_options_from_args};
13
13
use serde:: { Deserialize , Serialize } ;
14
14
use std:: ffi:: OsStr ;
15
15
use std:: io;
16
+ use std:: os:: fd:: AsFd ;
16
17
use std:: path:: Path ;
17
18
#[ cfg( feature = "abi-7-23" ) ]
18
19
use std:: time:: Duration ;
@@ -39,7 +40,7 @@ pub use reply::{
39
40
ReplyStatfs , ReplyWrite ,
40
41
} ;
41
42
pub use request:: Request ;
42
- pub use session:: { BackgroundSession , Session , SessionUnmounter } ;
43
+ pub use session:: { BackgroundSession , Mount , Session , SessionACL , Unmounter } ;
43
44
#[ cfg( feature = "abi-7-28" ) ]
44
45
use std:: cmp:: max;
45
46
#[ cfg( feature = "abi-7-13" ) ]
@@ -1008,7 +1009,8 @@ pub fn mount<FS: Filesystem, P: AsRef<Path>>(
1008
1009
}
1009
1010
1010
1011
/// Mount the given filesystem to the given mountpoint. This function will
1011
- /// not return until the filesystem is unmounted.
1012
+ /// not return until the filesystem is unmounted. This function requires
1013
+ /// CAP_SYS_ADMIN to run.
1012
1014
///
1013
1015
/// NOTE: This will eventually replace mount(), once the API is stable
1014
1016
pub fn mount2 < FS : Filesystem , P : AsRef < Path > > (
@@ -1017,7 +1019,10 @@ pub fn mount2<FS: Filesystem, P: AsRef<Path>>(
1017
1019
options : & [ MountOption ] ,
1018
1020
) -> io:: Result < ( ) > {
1019
1021
check_option_conflicts ( options, false ) ?;
1020
- Session :: new ( filesystem, mountpoint. as_ref ( ) , options) . and_then ( |mut se| se. run ( ) )
1022
+ let mut session = Session :: new ( filesystem, SessionACL :: from_mount_options ( options) ) ?;
1023
+ let _mount = Mount :: new ( session. as_fd ( ) , mountpoint, options) ?;
1024
+
1025
+ session. run ( )
1021
1026
}
1022
1027
1023
1028
/// Mount the given filesystem using fusermount(1). The binary must exist on
@@ -1028,7 +1033,30 @@ pub fn fusermount(
1028
1033
options : & [ MountOption ] ,
1029
1034
) -> io:: Result < ( ) > {
1030
1035
check_option_conflicts ( options, true ) ?;
1031
- Session :: new_fusermount ( filesystem, mountpoint, options) . and_then ( |mut se| se. run ( ) )
1036
+
1037
+ // AutoUnmount requires either AllowRoot or AllowOther; we can inject
1038
+ // that option but still block requests at the library level.
1039
+ let ( device_fd, _mount) = if options. contains ( & MountOption :: AutoUnmount )
1040
+ && !( options. contains ( & MountOption :: AllowRoot )
1041
+ || options. contains ( & MountOption :: AllowOther ) )
1042
+ {
1043
+ warn ! ( "Given auto_unmount without allow_root or allow_other; adding allow_other, with userspace permission handling" ) ;
1044
+
1045
+ let mut modified_options = options. to_vec ( ) ;
1046
+ modified_options. push ( MountOption :: AllowOther ) ;
1047
+
1048
+ Mount :: new_fusermount ( mountpoint. as_ref ( ) , & modified_options) ?
1049
+ } else {
1050
+ Mount :: new_fusermount ( mountpoint. as_ref ( ) , options) ?
1051
+ } ;
1052
+
1053
+ let mut session = Session :: from_fd (
1054
+ device_fd,
1055
+ filesystem,
1056
+ SessionACL :: from_mount_options ( options) ,
1057
+ ) ;
1058
+
1059
+ session. run ( )
1032
1060
}
1033
1061
1034
1062
/// Mount the given filesystem to the given mountpoint. This function spawns
@@ -1066,7 +1094,11 @@ pub fn spawn_mount2<'a, FS: Filesystem + Send + 'static + 'a, P: AsRef<Path>>(
1066
1094
options : & [ MountOption ] ,
1067
1095
) -> io:: Result < BackgroundSession > {
1068
1096
check_option_conflicts ( options, false ) ?;
1069
- Session :: new ( filesystem, mountpoint. as_ref ( ) , options) . and_then ( |se| se. spawn ( ) )
1097
+
1098
+ let session = Session :: new ( filesystem, SessionACL :: from_mount_options ( options) ) ?;
1099
+ let mount = Mount :: new ( session. as_fd ( ) , & mountpoint, options) ?;
1100
+
1101
+ BackgroundSession :: new ( session, mount, mountpoint)
1070
1102
}
1071
1103
1072
1104
/// Mount the given filesystem to the given mountpoint. This function spawns
@@ -1084,5 +1116,28 @@ pub fn spawn_fusermount<'a, FS: Filesystem + Send + 'static + 'a>(
1084
1116
options : & [ MountOption ] ,
1085
1117
) -> io:: Result < BackgroundSession > {
1086
1118
check_option_conflicts ( options, true ) ?;
1087
- Session :: new_fusermount ( filesystem, mountpoint, options) . and_then ( |se| se. spawn ( ) )
1119
+
1120
+ // AutoUnmount requires either AllowRoot or AllowOther; we can inject
1121
+ // that option but still block requests at the library level.
1122
+ let ( device_fd, mount) = if options. contains ( & MountOption :: AutoUnmount )
1123
+ && !( options. contains ( & MountOption :: AllowRoot )
1124
+ || options. contains ( & MountOption :: AllowOther ) )
1125
+ {
1126
+ warn ! ( "Given auto_unmount without allow_root or allow_other; adding allow_other, with userspace permission handling" ) ;
1127
+
1128
+ let mut modified_options = options. to_vec ( ) ;
1129
+ modified_options. push ( MountOption :: AllowOther ) ;
1130
+
1131
+ Mount :: new_fusermount ( mountpoint. as_ref ( ) , & modified_options) ?
1132
+ } else {
1133
+ Mount :: new_fusermount ( mountpoint. as_ref ( ) , options) ?
1134
+ } ;
1135
+
1136
+ let session = Session :: from_fd (
1137
+ device_fd,
1138
+ filesystem,
1139
+ SessionACL :: from_mount_options ( options) ,
1140
+ ) ;
1141
+
1142
+ BackgroundSession :: new ( session, mount, mountpoint)
1088
1143
}
0 commit comments