mirror of
https://gitlab.com/apparmor/apparmor
synced 2025-08-29 13:28:19 +00:00
Fix a race between path lookup and removal of " (deleted)" that could
result in incorrect removal of " (deleted)" from the pathname. The race is as follows: the path contains " (deleted)", which is unlikely but valid during path lookup the path is valid after path lookup before the deleted test the dentry is unhashed the deleted test now succeeds but the pathname never had " (deleted)" appended by d_path. The paths " (deleted)" string is removed and an incorrect path is returned
This commit is contained in:
parent
38fe3a0bf6
commit
0060caec1a
@ -779,6 +779,7 @@ out:
|
||||
char *aa_get_name(struct dentry *dentry, struct vfsmount *mnt)
|
||||
{
|
||||
char *page, *name;
|
||||
int deleted = !IS_ROOT(dentry) && d_unhashed(dentry);
|
||||
|
||||
page = (char *)__get_free_page(GFP_KERNEL);
|
||||
if (!page) {
|
||||
@ -786,20 +787,30 @@ char *aa_get_name(struct dentry *dentry, struct vfsmount *mnt)
|
||||
goto out;
|
||||
}
|
||||
|
||||
retry:
|
||||
name = d_path(dentry, mnt, page, PAGE_SIZE);
|
||||
/* check for (deleted) that d_path appends to pathnames if the dentry
|
||||
* has been removed from the cache.
|
||||
* The size > deleted_size and strcmp checks are redundant safe guards.
|
||||
*/
|
||||
|
||||
if (IS_ERR(name)) {
|
||||
free_page((unsigned long)page);
|
||||
} else if (!deleted && (!IS_ROOT(dentry) && d_unhashed(dentry))) {
|
||||
/* test for race of name lookup against the dentry being
|
||||
* deleted. If a race is detected then redo the lookup,
|
||||
* so that the (deleted) suffix can be unambiguously removed
|
||||
*/
|
||||
deleted = 1;
|
||||
goto retry;
|
||||
} else {
|
||||
const char deleted_str[] = " (deleted)";
|
||||
const size_t deleted_size = sizeof(deleted_str) - 1;
|
||||
size_t size;
|
||||
size = strlen(name);
|
||||
if (!IS_ROOT(dentry) && d_unhashed(dentry) &&
|
||||
size > deleted_size &&
|
||||
|
||||
/* check for (deleted) that d_path appends to pathnames if
|
||||
* the dentry has been removed from the cache.
|
||||
* The size > deleted_size and strcmp checks are redundant
|
||||
* safe guards.
|
||||
*/
|
||||
if (deleted && size > deleted_size &&
|
||||
strcmp(name + size - deleted_size, deleted_str) == 0)
|
||||
name[size - deleted_size] = '\0';
|
||||
AA_DEBUG("%s: full_path=%s\n", __FUNCTION__, name);
|
||||
|
Loading…
x
Reference in New Issue
Block a user