ksud: su supports set gid and groups (#1240)
- When no gid is provided, use uid as gid.
This commit is contained in:
@@ -58,10 +58,12 @@ fn print_usage(program: &str, opts: Options) {
|
|||||||
print!("{}", opts.usage(&brief));
|
print!("{}", opts.usage(&brief));
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_identity(uid: u32, gid: u32) {
|
fn set_identity(uid: u32, gid: u32, groups: &Vec<u32>) {
|
||||||
#[cfg(any(target_os = "linux", target_os = "android"))]
|
#[cfg(any(target_os = "linux", target_os = "android"))]
|
||||||
unsafe {
|
unsafe {
|
||||||
libc::seteuid(uid);
|
if !groups.is_empty() {
|
||||||
|
libc::setgroups(groups.len(), groups.as_ptr());
|
||||||
|
}
|
||||||
libc::setresgid(gid, gid, gid);
|
libc::setresgid(gid, gid, gid);
|
||||||
libc::setresuid(uid, uid, uid);
|
libc::setresuid(uid, uid, uid);
|
||||||
}
|
}
|
||||||
@@ -117,6 +119,13 @@ pub fn root_shell() -> Result<()> {
|
|||||||
"mount-master",
|
"mount-master",
|
||||||
"force run in the global mount namespace",
|
"force run in the global mount namespace",
|
||||||
);
|
);
|
||||||
|
opts.optopt("g", "group", "Specify the primary group", "GROUP");
|
||||||
|
opts.optmulti(
|
||||||
|
"G",
|
||||||
|
"supp-group",
|
||||||
|
"Specify a supplementary group. The first specified supplementary group is also used as a primary group if the option -g is not specified.",
|
||||||
|
"GROUP",
|
||||||
|
);
|
||||||
|
|
||||||
// Replace -cn with -z, -mm with -M for supporting getopt_long
|
// Replace -cn with -z, -mm with -M for supporting getopt_long
|
||||||
let args = args
|
let args = args
|
||||||
@@ -160,6 +169,31 @@ pub fn root_shell() -> Result<()> {
|
|||||||
let mut is_login = matches.opt_present("l");
|
let mut is_login = matches.opt_present("l");
|
||||||
let preserve_env = matches.opt_present("p");
|
let preserve_env = matches.opt_present("p");
|
||||||
let mount_master = matches.opt_present("M");
|
let mount_master = matches.opt_present("M");
|
||||||
|
let mut groups = Vec::<u32>::new();
|
||||||
|
for g in matches.opt_strs("G") {
|
||||||
|
if let core::result::Result::Ok(id) = g.parse::<u32>() {
|
||||||
|
groups.push(id);
|
||||||
|
} else {
|
||||||
|
println!("Invalid GID: {g}");
|
||||||
|
print_usage(&program, opts);
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let mut gid: Option<u32> = None;
|
||||||
|
// if -g provided, use it.
|
||||||
|
if let Some(g) = matches.opt_str("g") {
|
||||||
|
if let core::result::Result::Ok(id) = g.parse::<u32>() {
|
||||||
|
gid = Some(id);
|
||||||
|
} else {
|
||||||
|
println!("Invalid GID: {g}");
|
||||||
|
print_usage(&program, opts);
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// otherwise, use the first gid of groups.
|
||||||
|
if gid.is_none() && !groups.is_empty() {
|
||||||
|
gid = Some(groups[0]);
|
||||||
|
}
|
||||||
|
|
||||||
// we've make sure that -c is the last option and it already contains the whole command, no need to construct it again
|
// we've make sure that -c is the last option and it already contains the whole command, no need to construct it again
|
||||||
let args = matches
|
let args = matches
|
||||||
@@ -175,7 +209,6 @@ pub fn root_shell() -> Result<()> {
|
|||||||
|
|
||||||
// use current uid if no user specified, these has been done in kernel!
|
// use current uid if no user specified, these has been done in kernel!
|
||||||
let mut uid = unsafe { libc::getuid() };
|
let mut uid = unsafe { libc::getuid() };
|
||||||
let gid = unsafe { libc::getgid() };
|
|
||||||
if free_idx < matches.free.len() {
|
if free_idx < matches.free.len() {
|
||||||
let name = &matches.free[free_idx];
|
let name = &matches.free[free_idx];
|
||||||
uid = unsafe {
|
uid = unsafe {
|
||||||
@@ -191,6 +224,8 @@ pub fn root_shell() -> Result<()> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// if there is no gid provided, use uid.
|
||||||
|
let gid = gid.unwrap_or(uid);
|
||||||
// https://github.com/topjohnwu/Magisk/blob/master/native/src/su/su_daemon.cpp#L408
|
// https://github.com/topjohnwu/Magisk/blob/master/native/src/su/su_daemon.cpp#L408
|
||||||
let arg0 = if is_login { "-" } else { &shell };
|
let arg0 = if is_login { "-" } else { &shell };
|
||||||
|
|
||||||
@@ -241,7 +276,7 @@ pub fn root_shell() -> Result<()> {
|
|||||||
let _ = utils::unshare_mnt_ns();
|
let _ = utils::unshare_mnt_ns();
|
||||||
}
|
}
|
||||||
|
|
||||||
set_identity(uid, gid);
|
set_identity(uid, gid, &groups);
|
||||||
|
|
||||||
std::result::Result::Ok(())
|
std::result::Result::Ok(())
|
||||||
})
|
})
|
||||||
|
|||||||
Reference in New Issue
Block a user