Fix package files removal with only read bit set.
The previous code was checking incorrectly if the file had the write bit set, and this is wrong because a package could have files with only the read bit set (0444).
This commit is contained in:
parent
2a89552375
commit
2711b07b77
9
NEWS
9
NEWS
@ -1,5 +1,11 @@
|
||||
xbps-0.41 (???):
|
||||
|
||||
* libxbps: rather than checking if user has write permission on
|
||||
package files for removal, check if the files are owned by the
|
||||
same user ID. This fixes a new issue where files with only the read
|
||||
bit set cannot be removed. Added a new test case to verify its
|
||||
correctness.
|
||||
|
||||
* xbps-create(8): xz compressed packages now use default compression
|
||||
level (-6) rather than max level (-9); max compression level uses
|
||||
too much memory and it's much slower; by Christian Neukirchen.
|
||||
@ -15,7 +21,8 @@ xbps-0.41 (???):
|
||||
the next update xbps-install will automatically replace the broken release by
|
||||
the new downgraded release.
|
||||
|
||||
* replace xbps-package directory by the new void-packages, by Enno Boland.
|
||||
* Replace xbps-packages directory by void-packages in xbps-checkvers(8),
|
||||
xbps-uchroot(8) and others, by Enno Boland.
|
||||
|
||||
xbps-0.40 (2014-09-18):
|
||||
|
||||
|
@ -37,8 +37,9 @@
|
||||
|
||||
static bool
|
||||
check_remove_pkg_files(struct xbps_handle *xhp,
|
||||
xbps_dictionary_t pkgd, const char *pkgver)
|
||||
xbps_dictionary_t pkgd, const char *pkgver, uid_t euid)
|
||||
{
|
||||
struct stat st;
|
||||
xbps_array_t array;
|
||||
xbps_object_iterator_t iter;
|
||||
xbps_object_t obj;
|
||||
@ -46,7 +47,6 @@ check_remove_pkg_files(struct xbps_handle *xhp,
|
||||
const char *file;
|
||||
char path[PATH_MAX];
|
||||
bool fail = false;
|
||||
int fd = 0;
|
||||
|
||||
for (uint8_t i = 0; i < __arraycount(objs); i++) {
|
||||
array = xbps_dictionary_get(pkgd, objs[i]);
|
||||
@ -60,18 +60,30 @@ check_remove_pkg_files(struct xbps_handle *xhp,
|
||||
while ((obj = xbps_object_iterator_next(iter))) {
|
||||
xbps_dictionary_get_cstring_nocopy(obj, "file", &file);
|
||||
snprintf(path, sizeof(path), "%s/%s", xhp->rootdir, file);
|
||||
if (faccessat(fd, path, W_OK, AT_SYMLINK_NOFOLLOW) == -1) {
|
||||
/*
|
||||
* Check if effective user ID owns the file; this is
|
||||
* enough to ensure the user has write permissions
|
||||
* on the directory.
|
||||
*/
|
||||
if (!lstat(path, &st) && euid == st.st_uid) {
|
||||
/* success */
|
||||
continue;
|
||||
}
|
||||
if (errno != ENOENT) {
|
||||
/*
|
||||
* only bail out if something else than ENOENT
|
||||
* is returned.
|
||||
*/
|
||||
int rv = errno;
|
||||
if (rv == 0) {
|
||||
/* lstat succeeds but euid != uid */
|
||||
rv = EPERM;
|
||||
}
|
||||
fail = true;
|
||||
xbps_set_cb_state(xhp, XBPS_STATE_REMOVE_FILE_FAIL,
|
||||
errno, pkgver,
|
||||
"%s: cannot remove `%s': %s",
|
||||
pkgver, file, strerror(errno));
|
||||
}
|
||||
pkgver, file, strerror(rv));
|
||||
}
|
||||
}
|
||||
xbps_object_iterator_release(iter);
|
||||
@ -219,6 +231,7 @@ xbps_remove_pkg(struct xbps_handle *xhp, const char *pkgver, bool update)
|
||||
char *pkgname, metafile[PATH_MAX];
|
||||
int rv = 0;
|
||||
pkg_state_t state = 0;
|
||||
uid_t euid;
|
||||
|
||||
assert(xhp);
|
||||
assert(pkgver);
|
||||
@ -226,6 +239,8 @@ xbps_remove_pkg(struct xbps_handle *xhp, const char *pkgver, bool update)
|
||||
pkgname = xbps_pkg_name(pkgver);
|
||||
assert(pkgname);
|
||||
|
||||
euid = geteuid();
|
||||
|
||||
if ((pkgd = xbps_pkgdb_get_pkg(xhp, pkgname)) == NULL) {
|
||||
rv = errno;
|
||||
xbps_dbg_printf(xhp, "[remove] cannot find %s in pkgdb: %s\n",
|
||||
@ -293,7 +308,7 @@ xbps_remove_pkg(struct xbps_handle *xhp, const char *pkgver, bool update)
|
||||
* 1- check if user has enough perms to remove all entries
|
||||
* 2- perform removal
|
||||
*/
|
||||
if (check_remove_pkg_files(xhp, pkgfilesd, pkgver)) {
|
||||
if (check_remove_pkg_files(xhp, pkgfilesd, pkgver, euid)) {
|
||||
rv = EPERM;
|
||||
goto out;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user