-
Notifications
You must be signed in to change notification settings - Fork 232
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
try to create rundir before using them #436
Conversation
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.
The if (access(...))
is not needed and racy in theory, as the path can be created between the call to access
and mkdir
Better check for and ignore EEXIST, and warn on all other errors to mkdir
|
b621730
to
163485d
Compare
Thanks for the review!
I had assumed that PR would be merged first as that seemed to be the core of the issue (as discussed in #419) but if this goes first this whole section does not even make sense, I've removed this and added a word about lock dir.
I've added the title in parenthesis, is that enough? the commit message should be enough to understand the problem regardless of the actual issue anyway. |
Change here looks fine. Though I want to ask the question, is the permission mask of 755 what we want here for the folder? Who needs to access this (another instance of pppd?) If so, should one consider a least privilege approach, e.g. only user or group of pppd has access to this folder / file? |
Come to think about it, this code fails if the path needs to be created recursively. E.g. if someone passed configure --with-lock-dir=/opt/var/locks, and /opt/var doesn't exist where you are trying to create /opt/var/lock/ The chances for this happening is likely low. But keep in mind that the default is to key off the /usr prefix. So you'll end up with /usr/etc/ and /usr/var/locks if you are not careful with the configure switches. |
fedora seems to use 755 for /run/ppp: https://src.fedoraproject.org/rpms/ppp/blob/rawhide/f/ppp-tmpfiles.conf
Right, the default path for lock would actually be Anyway, if you really prefer a thorough mkdir-with-parents sure, I can change this path to add a mkdir_p helper somewhere (pppd/utils.c?) and use that in both place? |
hi @enaess -- sorry for the direct ping, would you have a minute to answer my reply? |
The default path if not configured otherwise would fail to be created. I think if you'd taken just a bit more time to fix this, it would be a long lasting fix.
The fact that the default case would fail is bad. If the default config would succeed, but an other corner case not ... then maybe. Again, quick and dirty fixes may be appropriate for package scrips, distro patches, but if you want to make a long lasting contribution; it would be good to engineer a good fix for all and commit it upstream |
No problem, I just wanted to make sure that's the way you want to go before taking the time to do it. |
113a454
to
98a929b
Compare
Updated this PR as suggested. While I was at it I tried to make it clever and only try to mkdir the parent directory if open failed with ENOENT, but that's more likely to backfire than anything else so happy to just make it unconditional instead. (BTW if you want my opinion I don't think this problem warrants the complexity this brings, but it's your call; I still have the old commit around if you change your mind) EDIT: (sorry for update spam on mails; some indentations were a bit weird as I reindented everything automatically after noticed the shiftwidth of 4 space at the end) |
8fd2a19
to
5bfd754
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.
I think if you take a look at the review feedback the change could need a few improvements.
|
||
#include "pppd-private.h" | ||
|
||
/* globals used in test.c... */ |
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.
Why do you need to declare these globals, they are not used in this file.
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.
These are declared as extern int
in headers and used in utils.c -- the test program won't link without these.
@@ -1728,7 +1728,12 @@ TDB_CONTEXT *tdb_open_ex(const char *name, int hash_size, int tdb_flags, | |||
goto internal; | |||
} | |||
|
|||
again: |
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.
I am not sure I like the use of label again: and goto, could this be made to fail if it fails and then bail, e.g. use goto fail when it fails to create it recursively.
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.
Can put the whole thing in a while loop but that's a much bigger refactor for something that ought to be a "quick fix"; at this rate it's probably better to just call mkdir_recursive inconditonally first before the open, as it won't fail if the directory already exists.
What do you think?
char *copy; | ||
int rc; | ||
|
||
// optimistically try on full path first to avoid allocation |
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.
You could just copy the path into a temporary buffer, and then iterate over that buffer instead of allocating a copy of it. In fact, maybe a quick google search turned up a much more compact solution here: https://stackoverflow.com/questions/2336242/recursive-mkdir-system-call-on-unix
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.
Eh? This will fail with a path bigger than 256 (there's a MAXPATHLEN variable that's usually 4k on unix, but paths can actually be much longer on many filesystems; there's no limit to how long a path can be); you can't get around this without an allocation at which point strdup is just as good.
As for the rest; yes and no. There are two differences between the version you linked and this commit.
This commit starts from the end, and only creates required directories e.g. /var/lock/ppp/ would try to mkdir /var/lock/ppp, if that fails try /var/lock etc and go back. It also checks the result is a directory and checks for errors.
The version you linked would mkdir /var, then /var/lock, then /var/lock/ppp without checking anything.
Now these are just sequels from the lustre filesystem but it's just pushing the work to the kernel, mkdir(/var) when /var already exists should be cheap but it's still more costly than not doing it.
I'm a filesystem developer and don't want my name anywhere near that stackoverflow snippet; if you prefer that version I'll remove this commit so feel free to add it in your name.
Anyway, in our case the parent directory will always exist on distro installs so it makes more sense to go straight for the end -- we'll never allocate anything and use the recursive call, except on very odd setups where the rundir or lockdir is specified somewhere either deeper than usual or mis/not configured.
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.
(Sorry, I do have strong opinions on POSIX filesystem API and this triggered me when I saw this first thing in the morning. For pppd this will only ever be called at init anyway so nothing really matters, but if you prefer an iterative version let's at least keep some error codes... The "improved" version listed in a comment of your stackoverflow link really isn't much shorter than this, the main difference is whether it starts from the start or the end)
pppd/utils.c
Outdated
@@ -844,6 +926,10 @@ lock(char *dev) | |||
#endif | |||
|
|||
while ((fd = open(lock_file, O_EXCL | O_CREAT | O_RDWR, 0644)) < 0) { | |||
if (errno == ENOENT && mkdir_recursive(PPP_PATH_LOCKDIR) == 0) { | |||
/* parent dir was missing, retry now */ | |||
continue; |
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.
So what happens when mkdir_recursive fails? Should we at least log a message?
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.
It'll fall through to errno != EEXIST and print it couldn't create lock file; that's probably enough.
Looking back mkdir_recursive can leave errno set to EEXIST so we probably want to save the original ENOENT errno in that case; I'll adjust this later today.
|
||
rmdir(base_dir); | ||
return failure; | ||
} |
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.
Seems like you have covered a number of test-cases. Also, you added a new test-suite, that's good.
d4dd0a9
to
b39c834
Compare
7d0dc31
to
1ee1505
Compare
(rebased after #435 -- I still would prefer a simple mkdir() as in the original version, but this isn't critical anymore as lock dir got moved back to /var/lock. The patch is still useful for /run/pppd for the pppdb so keeping the PR open.) |
1ee1505
to
d72931e
Compare
This will be used in the next commit. A test file for utils has also been added to check mkdir works as intended. Signed-off-by: Dominique Martinet <[email protected]>
d72931e
to
ea7950a
Compare
Looks like tdb.c needs to include pppd-private.h to get the declaration of mkdir_recursive. |
Runtime dir changed from /run to /run/pppd in commit 66a8c74 ("Let ./configure control the paths for pppd") and is likely to not exist on some distros, in which case the pppdb will not be created. See: ppp-project#419 (lock directory moved in ppp-2.5.0) Signed-off-by: Dominique Martinet <[email protected]>
ea7950a
to
3a4fec9
Compare
Good catch, thank you. |
PR #435 makes lockdir default go back to /var/lock, but runtime dir still changed from /run to /run/pppd in commit 66a8c74 ("Let ./configure control the paths for pppd") and is likely to not exist on some distros, in which case the pppdb will not be created.
This is not a big problem but might as well just try to create the directory if it is missing.
Return code of mkdir does not need to be checked as the following open will fail anyway if mkdir failed.
See: #419