Index: stable/12/usr.sbin/pw/rm_r.c =================================================================== --- stable/12/usr.sbin/pw/rm_r.c (revision 359588) +++ stable/12/usr.sbin/pw/rm_r.c (revision 359589) @@ -1,75 +1,78 @@ /*- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD * * Copyright (C) 1996 * David L. Nugent. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY DAVID L. NUGENT AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL DAVID L. NUGENT OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #ifndef lint static const char rcsid[] = "$FreeBSD$"; #endif /* not lint */ #include #include #include #include #include #include "pwupd.h" void rm_r(int rootfd, const char *path, uid_t uid) { int dirfd; DIR *d; struct dirent *e; struct stat st; if (*path == '/') path++; dirfd = openat(rootfd, path, O_DIRECTORY); if (dirfd == -1) { return; } d = fdopendir(dirfd); while ((e = readdir(d)) != NULL) { if (strcmp(e->d_name, ".") == 0 || strcmp(e->d_name, "..") == 0) continue; if (fstatat(dirfd, e->d_name, &st, AT_SYMLINK_NOFOLLOW) != 0) continue; if (S_ISDIR(st.st_mode)) rm_r(dirfd, e->d_name, uid); else if (S_ISLNK(st.st_mode) || st.st_uid == uid) unlinkat(dirfd, e->d_name, 0); } closedir(d); if (fstatat(rootfd, path, &st, AT_SYMLINK_NOFOLLOW) != 0) return; - unlinkat(rootfd, path, S_ISDIR(st.st_mode) ? AT_REMOVEDIR : 0); + if (S_ISLNK(st.st_mode)) + unlinkat(rootfd, path, 0); + else if (st.st_uid == uid) + unlinkat(rootfd, path, AT_REMOVEDIR); } Index: stable/12/usr.sbin/pw/tests/pw_userdel_test.sh =================================================================== --- stable/12/usr.sbin/pw/tests/pw_userdel_test.sh (revision 359588) +++ stable/12/usr.sbin/pw/tests/pw_userdel_test.sh (revision 359589) @@ -1,76 +1,96 @@ # $FreeBSD$ # Import helper functions . $(atf_get_srcdir)/helper_functions.shin # Test that a user can be deleted when another user is part of this # user's default group and does not go into an infinate loop. # PR: 191427 atf_test_case rmuser_seperate_group cleanup rmuser_seperate_group_head() { atf_set "timeout" "30" } rmuser_seperate_group_body() { populate_etc_skel ${PW} useradd test || atf_fail "Creating test user" ${PW} groupmod test -M 'test,root' || \ atf_fail "Modifying the group" ${PW} userdel test || atf_fail "Delete the test user" } atf_test_case user_do_not_try_to_delete_root_if_user_unknown user_do_not_try_to_delete_root_if_user_unknown_head() { atf_set "descr" \ "Make sure not to try to remove root if deleting an unknown user" } user_do_not_try_to_delete_root_if_user_unknown_body() { populate_etc_skel atf_check -e inline:"pw: Bad id 'plop': invalid\n" -s exit:64 -x \ ${PW} userdel -u plop } atf_test_case delete_files delete_files_body() { populate_root_etc_skel mkdir -p ${HOME}/skel touch ${HOME}/skel/a mkdir -p ${HOME}/home mkdir -p ${HOME}/var/mail echo "foo wedontcare" > ${HOME}/etc/opiekeys atf_check -s exit:0 ${RPW} useradd foo -k /skel -m test -d ${HOME}/home || atf_fail "Fail to create home directory" test -f ${HOME}/var/mail/foo || atf_fail "Mail file not created" atf_check -s exit:0 ${RPW} userdel foo -r atf_check -s exit:0 -o inline:"#oo wedontcare\n" cat ${HOME}/etc/opiekeys if test -f ${HOME}/var/mail/foo; then atf_fail "Mail file not removed" fi } atf_test_case delete_numeric_name delete_numeric_name_body() { populate_etc_skel atf_check ${PW} useradd -n foo -u 4001 atf_check -e inline:"pw: no such user \`4001'\n" -s exit:67 \ ${PW} userdel -n 4001 } atf_test_case home_not_a_dir home_not_a_dir_body() { populate_root_etc_skel touch ${HOME}/foo atf_check ${RPW} useradd foo -d /foo atf_check ${RPW} userdel foo -r } +atf_test_case home_shared +home_shared_body() { + populate_root_etc_skel + mkdir ${HOME}/shared + atf_check ${RPW} useradd -n testuser1 -d /shared + atf_check ${RPW} useradd -n testuser2 -d /shared + atf_check ${RPW} userdel -n testuser1 -r + test -d ${HOME}/shared || atf_fail "Shared home has been removed" +} + +atf_test_case home_regular_dir +home_regular_dir_body() { + populate_root_etc_skel + atf_check ${RPW} useradd -n foo -d /foo + atf_check ${RPW} userdel -n foo -r + [ ! -d ${HOME}/foo ] || atf_fail "Home has not been removed" +} + atf_init_test_cases() { atf_add_test_case rmuser_seperate_group atf_add_test_case user_do_not_try_to_delete_root_if_user_unknown atf_add_test_case delete_files atf_add_test_case delete_numeric_name atf_add_test_case home_not_a_dir + atf_add_test_case home_shared + atf_add_test_case home_regular_dir } Index: stable/12 =================================================================== --- stable/12 (revision 359588) +++ stable/12 (revision 359589) Property changes on: stable/12 ___________________________________________________________________ Modified: svn:mergeinfo ## -0,0 +0,1 ## Merged /head:r359232