Fix rename trustee rights and invalidate trustee cache
All checks were successful
Source release / source-package (push) Successful in 39s

Align rename permission checks with NetWare trustee semantics. A same-directory
rename should be controlled by the Modify right instead of requiring a broader
R/W/M combination. For moves to another parent directory, require Create rights
on the destination parent.

Also invalidate the trustee rights cache after adding or deleting trustee
assignments so newly granted rights are visible immediately to subsequent
operations.

This fixes the MARIO trustee test where rename failed with R/W/M/F and even
R/W/C/E/M/F, while the same operation succeeded only with the broader all-rights
set.
This commit is contained in:
Mario Fetka
2026-05-26 14:29:51 +02:00
parent 121ca79bc7
commit 181c20620c
2 changed files with 37 additions and 6 deletions

View File

@@ -2395,12 +2395,37 @@ static int nw_rename_file_dir(int namespace,
uint8 *unname_d =
(uint8*)alloc_nwpath2unix_extra(&(dbe_d->nwpath), 0, last_part);
if (tru_eff_rights_exists(dbe_s->nwpath.volume, unname_s,
&dbe_s->nwpath.statb, TRUSTEE_W|TRUSTEE_M|TRUSTEE_R))
result=-0x8b;
else if (tru_eff_rights_exists(dbe_d->nwpath.volume, unname_dp,
&dbe_d->nwpath.statb, TRUSTEE_W))
/* NetWare trustee semantics: M (Modify) is the right for renaming
* files/directories. A is for trustee/IRM changes, not rename.
*
* The old check required R|W|M on the source and W on the destination
* parent. That is stricter than NetWare for a same-directory rename and
* makes REN fail for users with Modify rights.
*/
if (tru_eff_rights_exists(dbe_s->nwpath.volume, unname_s,
&dbe_s->nwpath.statb, TRUSTEE_M)) {
XDPRINTF((5, 0, "Rename denied: missing M on source `%s`", unname_s));
result=-0x8b;
} else {
char src_parent[1024];
char *slash;
strmaxcpy((uint8*)src_parent, unname_s, sizeof(src_parent)-1);
slash = strrchr(src_parent, '/');
if (slash && slash > src_parent)
*slash = '\0';
/* Only require destination Create rights when this is a move to a
* different parent directory. Same-directory rename is covered by M.
*/
if (slash && strcmp(src_parent, (char*)unname_dp) &&
tru_eff_rights_exists(dbe_d->nwpath.volume, unname_dp,
&dbe_d->nwpath.statb, TRUSTEE_C)) {
XDPRINTF((5, 0, "Rename denied: missing C on dest parent `%s`",
unname_dp));
result=-0x8b;
}
}
if (result > -1) {
if (seteuid(0)) {}

View File

@@ -465,8 +465,11 @@ int tru_del_trustee(int volume, uint8 *unixname, struct stat *stb, uint32 id)
( (tru_get_eff_rights(volume, unixname, stb) & TRUSTEE_A)
|| (act_id_flags&1)) ) {
result=del_trustee_from_disk(volume, stb->st_dev, stb->st_ino, id);
if (!result)
if (!result) {
tru_vol_sernum(volume, 1); /* trustee sernum needs updated */
/* Trustee data changed on disk; cached effective rights are stale. */
tru_free_cache(volume);
}
}
MDEBUG(D_TRUSTEES, {
xdprintf(1,0, "tru_del_trustee: id=%08lx, volume=%d, file=`%s`, result=-0x%x",
@@ -677,6 +680,9 @@ int tru_add_trustee_set(int volume, uint8 *unixname,
}
(void)reseteuid();
tru_vol_sernum(volume, 1); /* trustee sernum needs updated */
/* local_tru_add_trustee_set() built/read the cache before writing the
* new trustee entry. Drop it so the next user sees the new rights. */
tru_free_cache(volume);
}
return (result);
}