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 (???):
|
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
|
* xbps-create(8): xz compressed packages now use default compression
|
||||||
level (-6) rather than max level (-9); max compression level uses
|
level (-6) rather than max level (-9); max compression level uses
|
||||||
too much memory and it's much slower; by Christian Neukirchen.
|
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 next update xbps-install will automatically replace the broken release by
|
||||||
the new downgraded release.
|
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):
|
xbps-0.40 (2014-09-18):
|
||||||
|
|
||||||
|
@ -37,8 +37,9 @@
|
|||||||
|
|
||||||
static bool
|
static bool
|
||||||
check_remove_pkg_files(struct xbps_handle *xhp,
|
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_array_t array;
|
||||||
xbps_object_iterator_t iter;
|
xbps_object_iterator_t iter;
|
||||||
xbps_object_t obj;
|
xbps_object_t obj;
|
||||||
@ -46,7 +47,6 @@ check_remove_pkg_files(struct xbps_handle *xhp,
|
|||||||
const char *file;
|
const char *file;
|
||||||
char path[PATH_MAX];
|
char path[PATH_MAX];
|
||||||
bool fail = false;
|
bool fail = false;
|
||||||
int fd = 0;
|
|
||||||
|
|
||||||
for (uint8_t i = 0; i < __arraycount(objs); i++) {
|
for (uint8_t i = 0; i < __arraycount(objs); i++) {
|
||||||
array = xbps_dictionary_get(pkgd, 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))) {
|
while ((obj = xbps_object_iterator_next(iter))) {
|
||||||
xbps_dictionary_get_cstring_nocopy(obj, "file", &file);
|
xbps_dictionary_get_cstring_nocopy(obj, "file", &file);
|
||||||
snprintf(path, sizeof(path), "%s/%s", xhp->rootdir, 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) {
|
if (errno != ENOENT) {
|
||||||
/*
|
/*
|
||||||
* only bail out if something else than ENOENT
|
* only bail out if something else than ENOENT
|
||||||
* is returned.
|
* is returned.
|
||||||
*/
|
*/
|
||||||
|
int rv = errno;
|
||||||
|
if (rv == 0) {
|
||||||
|
/* lstat succeeds but euid != uid */
|
||||||
|
rv = EPERM;
|
||||||
|
}
|
||||||
fail = true;
|
fail = true;
|
||||||
xbps_set_cb_state(xhp, XBPS_STATE_REMOVE_FILE_FAIL,
|
xbps_set_cb_state(xhp, XBPS_STATE_REMOVE_FILE_FAIL,
|
||||||
errno, pkgver,
|
errno, pkgver,
|
||||||
"%s: cannot remove `%s': %s",
|
"%s: cannot remove `%s': %s",
|
||||||
pkgver, file, strerror(errno));
|
pkgver, file, strerror(rv));
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
xbps_object_iterator_release(iter);
|
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];
|
char *pkgname, metafile[PATH_MAX];
|
||||||
int rv = 0;
|
int rv = 0;
|
||||||
pkg_state_t state = 0;
|
pkg_state_t state = 0;
|
||||||
|
uid_t euid;
|
||||||
|
|
||||||
assert(xhp);
|
assert(xhp);
|
||||||
assert(pkgver);
|
assert(pkgver);
|
||||||
@ -226,6 +239,8 @@ xbps_remove_pkg(struct xbps_handle *xhp, const char *pkgver, bool update)
|
|||||||
pkgname = xbps_pkg_name(pkgver);
|
pkgname = xbps_pkg_name(pkgver);
|
||||||
assert(pkgname);
|
assert(pkgname);
|
||||||
|
|
||||||
|
euid = geteuid();
|
||||||
|
|
||||||
if ((pkgd = xbps_pkgdb_get_pkg(xhp, pkgname)) == NULL) {
|
if ((pkgd = xbps_pkgdb_get_pkg(xhp, pkgname)) == NULL) {
|
||||||
rv = errno;
|
rv = errno;
|
||||||
xbps_dbg_printf(xhp, "[remove] cannot find %s in pkgdb: %s\n",
|
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
|
* 1- check if user has enough perms to remove all entries
|
||||||
* 2- perform removal
|
* 2- perform removal
|
||||||
*/
|
*/
|
||||||
if (check_remove_pkg_files(xhp, pkgfilesd, pkgver)) {
|
if (check_remove_pkg_files(xhp, pkgfilesd, pkgver, euid)) {
|
||||||
rv = EPERM;
|
rv = EPERM;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user