-
Notifications
You must be signed in to change notification settings - Fork 16
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
refactor path resolving #265
Conversation
b8e6905
to
d560418
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hey, I have done some research on this change and I found some issues within this change and in current implementation. @damianloew I have described current issue in section 2 of this comment. I will also make an issue on this.
Section 1, issue in proposed change
Test code below works on host and current implementation but causes segmentation fault on proposed change.
Section 2, error in current implementation
Makeshift code that I have produced to check Section 1 error has found a discrepancy between current implementation of resolve_path()
(via realpath()
) and the host one.
Test code below resolves to /etc
on host, but /symShort
on phoenix, which is in violation with goal of realpath()
which should remove symlinks.
Edit: not valid, current implementation works according to POSIX
Test code
Test code tries to resolve very long path that starts with symlink. It instantiates:
- symlink
symNameLong
with long name that points to "/" - symlink
symNameShort
that points tosymNameLong
basePath
path that goes like:"symShort/etc/../etc/<and so on up to almost PATH_MAX length>/../etc"
that should finally land inetc
.
#include <stdio.h>
#include <unistd.h>
#include <sys/stat.h>
#include <stdlib.h>
#include <limits.h>
#include <string.h>
#include <errno.h>
#define NAME_LEN (NAME_MAX / 2)
int main(int argc, char **argv) {
char symNameShort[] = "symShort";
char symNameLong[NAME_LEN];
char basePath[] = "symShort/etc/../etc/../etc/../etc/../etc/../etc/../etc/../etc/../etc/../etc/../etc/../etc/../etc/../etc/../etc/../etc/../etc/../etc/../etc/../etc/../etc/../etc/../etc/../etc/../etc/../etc/../etc/../etc/../etc/../etc/../etc/../etc/../etc/../etc/../etc/../etc/../etc/../etc/../etc/../etc/../etc/../etc/../etc/../etc/../etc/../etc/../etc/../etc/../etc/../etc/../etc/../etc/../etc/../etc/../etc/../etc/../etc/../etc/../etc/../etc/../etc/../etc/../etc/../etc/../etc/../etc/../etc/../etc/../etc/../etc/../etc/../etc/../etc/../etc/../etc/../etc/../etc/../etc/../etc/../etc/../etc/../etc/../etc/../etc/../etc/../etc/../etc/../etc/../etc/../etc/../etc/../etc/../etc/../etc/../etc/../etc/../etc/../etc/../etc/../etc/../etc/../etc/../etc/../etc/../etc/../etc/../etc/../etc/../etc/../etc/../etc/../etc/../etc/../etc/../etc/../etc/../etc/../etc/../etc/../etc/../etc/../etc/../etc/../etc/../etc/../etc/../etc/../etc/../etc/../etc/../etc/../etc/../etc/../etc/../etc/../etc/../etc/../etc/../etc/../etc/../etc/../etc/../etc/../etc/../etc/";
char resolved[PATH_MAX + 1];
memset(symNameLong, 'a', NAME_LEN);
symNameLong[NAME_LEN - 1] = 0;
if (symlink("/", symNameLong) < 0)
printf("%s\n", strerror(errno));
if (symlink(symNameLong, symNameShort) < 0)
printf("%s\n", strerror(errno));
realpath(basePath, resolved);
resolved[PATH_MAX] = 0;
printf("%s\n", resolved);
/* cleanup */
remove(symNameShort);
remove(symNameLong);
}
basePath
is resolved to:
/etc
on host/symShort
on phoenix (tested on zturn, and confimed by @damianloew on ia32)segmentation fault
on proposed change
small notes from me:
|
|
Yeah, the issue will be created and we will add tests to cover this issue. |
If the current code works, there is no need to create the issue. Please just add the test case to help @xvuko narrow down the issue :) |
@xvuko Hmmm, I don't know... Doesn't this solution cause us to be unable to on a long path not being able to solve even longer symlink? Total path length being shorter than PATH_MAX in both cases, but us being unable to solve it anyway |
I think the original solution would also fail if symlink resolved length + remaining (unresolved) path len exceeds PATH_MAX (while resolving, even if the expected resolve result would be < PATH_MAX). |
We checked it and in fact there is no issue in the current libphoenix implementation as you mentioned @nalajcie So I've updated the issue and closed it. However the exception shouldn't be raised when applying changes from the PR when running code from the mentioned case. |
Thanks for testing this. There was a bug in my code: assert(symlink_len <= path - p);
if (symlink_len == path - p) {
return SET_ERRNO(-ENAMETOOLONG);
} I changed |
|
Yes, I will add this test.
Yeah, I was thinking about that. Added as it is a good place for comment.
'/' at the and is not an issue as trailing slashes are always ignored. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Some MISRA-flavored nitpicks, otherwise LGTM
The test is already added and it's now running during CI. |
PATH_MAX buffer is removed from stack frame. This reduces stack usage and makes it more uniform between platforms. This should give same output as before. Only change is case of empty symlink as it was setting errno to 0. JIRA: RTOS-504 Change-Id: I6402583e76f3bd12a951fe78830d48ac0c126af3
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
Main point of this is to remove
char tmp_buf[PATH_MAX];
from stack. I refactored rest of the function to make it (hopefully) easier to read.This should give same output as before. Only change is case of empty symlink as it was setting errno to 0.
Description
Motivation and Context
Types of changes
How Has This Been Tested?
Checklist:
Special treatment