diff --git a/NEWS b/NEWS index 189fbd66..492c80c5 100644 --- a/NEWS +++ b/NEWS @@ -1,5 +1,9 @@ xbps-0.33 (???): + * While checking file permissions for package files removal, make sure + to not dereference symbolic links, because a symlink might point to + a file in the rootfs, which won't have the same uid/gid. + * Fixed issue #31: https://github.com/voidlinux/xbps/issues/31 * New configuration file format with a custom C parser, simpler diff --git a/lib/package_remove.c b/lib/package_remove.c index 607c44fb..372383bf 100644 --- a/lib/package_remove.c +++ b/lib/package_remove.c @@ -30,6 +30,8 @@ #include #include #include +#include +#include #include "xbps_api_impl.h" @@ -44,6 +46,7 @@ check_remove_pkg_files(struct xbps_handle *xhp, const char *file; char *path = NULL; bool fail = false; + int fd = 0; for (uint8_t i = 0; i < __arraycount(objs); i++) { array = xbps_dictionary_get(pkgd, objs[i]); @@ -57,7 +60,7 @@ check_remove_pkg_files(struct xbps_handle *xhp, while ((obj = xbps_object_iterator_next(iter))) { xbps_dictionary_get_cstring_nocopy(obj, "file", &file); path = xbps_xasprintf("%s/%s", xhp->rootdir, file); - if (access(path, W_OK) == -1) { + if (faccessat(fd, path, W_OK, AT_SYMLINK_NOFOLLOW) == -1) { if (errno != ENOENT) { /* * only bail out if something else than ENOENT diff --git a/tests/xbps/libxbps/shell/remove_test.sh b/tests/xbps/libxbps/shell/remove_test.sh index d049f6e4..1c793e71 100644 --- a/tests/xbps/libxbps/shell/remove_test.sh +++ b/tests/xbps/libxbps/shell/remove_test.sh @@ -67,7 +67,38 @@ remove_symlinks_body() { atf_check_equal $rv 0 } +# 3rd test: make sure that symlinks to the rootfs are also removed. +atf_test_case remove_symlinks_from_root + +remove_symlinks_from_root_head() { + atf_set "descr" "Tests for package removal: symlink from root test" +} + +remove_symlinks_from_root_body() { + mkdir some_repo + mkdir -p pkg_A/bin + ln -sf /bin/bash pkg_A/bin/bash + ln -sf /bin/bash pkg_A/bin/sh + + cd some_repo + xbps-create -A noarch -n A-1.0_1 -s "A pkg" ../pkg_A + atf_check_equal $? 0 + xbps-rindex -a *.xbps + atf_check_equal $? 0 + cd .. + xbps-install -r root -C null.conf --repository=$PWD/some_repo -y A + atf_check_equal $? 0 + xbps-remove -r root -Ryv A + atf_check_equal $? 0 + rv=0 + if [ -h root/bin/bash -o -h root/bin/sh ]; then + rv=1 + fi + atf_check_equal $rv 0 +} + atf_init_test_cases() { atf_add_test_case keep_base_symlinks atf_add_test_case remove_symlinks + atf_add_test_case remove_symlinks_from_root }