From cb5805803da60a61d95d148a8afa853c76f90875 Mon Sep 17 00:00:00 2001 From: Alejandro Colomar Date: Sun, 1 Sep 2024 16:38:07 +0200 Subject: [PATCH] userdel: --force: Allow the flag to be specified twice, for more granularity Previously, with a single --force, one could only chose between not forcing, and forcing (which could destroy one's system entirely). Now one can pass --force, with only a small danger, to skip some checks, and a double --force --force with the meaning of the previous --force, which will possibly destroy the entire system. Closes: Reported-by: Matthew Horsfall Cc: Lennart Poettering Cc: Serge Hallyn Signed-off-by: Alejandro Colomar --- man/userdel.8.xml | 11 ++++++++++- src/userdel.c | 16 ++++++++-------- 2 files changed, 18 insertions(+), 9 deletions(-) diff --git a/man/userdel.8.xml b/man/userdel.8.xml index 32851f112..0d505f442 100644 --- a/man/userdel.8.xml +++ b/man/userdel.8.xml @@ -79,7 +79,16 @@ This option forces the removal of the user account and any other requested actions, - skipping any safety checks. + skipping safety checks. + + + If specified once, + a user is removed + even if it's still logged in, + and its primary group is removed + even if it's the primary group of another user. + If specified twice, + it skips all safety checks. Note: This option is dangerous and may leave diff --git a/src/userdel.c b/src/userdel.c index ead696041..c6af55b0c 100644 --- a/src/userdel.c +++ b/src/userdel.c @@ -79,7 +79,7 @@ static uid_t user_id; static gid_t user_gid; static char *user_home; -static bool fflg = false; +static int fflg = 0; static bool rflg = false; #ifdef WITH_SELINUX static bool Zflg = false; @@ -312,7 +312,7 @@ static void remove_usergroup (void) return; } - if (!fflg) { + if (fflg < 1) { /* * Scan the passwd file to check if this group is still * used as a primary group. @@ -832,7 +832,7 @@ static int remove_mailbox (void) } } - if (fflg) { + if (fflg >= 2) { if (unlink (mailfile) != 0) { fprintf (stderr, _("%s: warning: can't remove %s: %s\n"), @@ -997,8 +997,8 @@ int main (int argc, char **argv) #endif /* !WITH_SELINUX */ long_options, NULL)) != -1) { switch (c) { - case 'f': /* force remove even if not owned by user */ - fflg = true; + case 'f': + fflg++; break; case 'h': usage (E_SUCCESS); @@ -1131,7 +1131,7 @@ int main (int argc, char **argv) * a cron job may be started on her behalf, etc. */ if ((prefix[0] == '\0') && !Rflg && user_busy (user_name, user_id) != 0) { - if (!fflg) { + if (fflg < 1) { #ifdef WITH_AUDIT audit_logger (AUDIT_DEL_USER, Prog, "deleting user logged in", @@ -1160,7 +1160,7 @@ int main (int argc, char **argv) _("%s: %s home directory (%s) not found\n"), Prog, user_name, user_home); rflg = 0; - } else if ((0 == home_owned) && !fflg) { + } else if ((0 == home_owned) && fflg < 2) { fprintf (stderr, _("%s: %s not owned by %s, not removing\n"), Prog, user_home, user_name); @@ -1172,7 +1172,7 @@ int main (int argc, char **argv) #ifdef EXTRA_CHECK_HOME_DIR /* This may be slow, the above should be good enough. */ - if (rflg && !fflg) { + if (rflg && fflg < 2) { struct passwd *pwd; /* * For safety, refuse to remove the home directory if it