From 6b639194b7be7aa17e9736d1ed034e798d206de2 Mon Sep 17 00:00:00 2001 From: Michael Orlitzky Date: Sun, 17 Jun 2018 19:43:21 -0400 Subject: [PATCH] src/libadacl.c: add a special case for the path "." as an argument. There's a bug (exposed by the most recent test case) in the way the path "." is handled. Specifically, the dirname() function miscomputes its parent path as ".", which is clearly not correct. In this commit, a special case is added for the path ".", and the test suite passes once more. The implementation is a bit of a hack, however, and will be improved once the same issue with ".." has been dealt with. --- src/libadacl.c | 28 ++++++++++++++++++++++++++-- 1 file changed, 26 insertions(+), 2 deletions(-) diff --git a/src/libadacl.c b/src/libadacl.c index f20d4a3..a43afa5 100644 --- a/src/libadacl.c +++ b/src/libadacl.c @@ -1003,7 +1003,22 @@ int apply_default_acl(const char* path, bool recursive) { return ACL_ERROR; } char* parent = dirname(dirname_path_copy); - parent_fd = safe_open(parent, O_DIRECTORY | O_NOFOLLOW); + + /* Just kidding, if the path is ".", then dirname will do the wrong + * thing and give us "." as its parent, too. So, we handle that as a + * special case. + * + * WARNING: it is important that "parent" itself is not used after + * this point; otherwise we would need to store the correct parent + * path in there. But since everything uses file descriptors from + * now on, we only need to ensure that we get the correct parent_fd + * below. */ + if (strcmp(path, ".") == 0 && strcmp(parent, ".") == 0) { + parent_fd = safe_open("..", O_DIRECTORY | O_NOFOLLOW); + } + else { + parent_fd = safe_open(parent, O_DIRECTORY | O_NOFOLLOW); + } if (parent_fd == OPEN_ERROR) { if (errno == ELOOP || errno == ENOTDIR) { /* We hit a symlink, either in the last path component (ELOOP) @@ -1028,7 +1043,16 @@ int apply_default_acl(const char* path, bool recursive) { result = ACL_ERROR; goto cleanup; } - fd = openat(parent_fd, basename(basename_path_copy), O_NOFOLLOW); + + /* If the basename is ".", then we don't want to open "." relative + to the parent_fd, so we need another special case for that + path. */ + if (strcmp(path, ".") == 0 && strcmp(parent, ".") == 0) { + fd = open(".", O_NOFOLLOW); + } + else { + fd = openat(parent_fd, basename(basename_path_copy), O_NOFOLLOW); + } if (fd == OPEN_ERROR) { if (errno == ELOOP || errno == ENOTDIR) { /* We hit a symlink, either in the last path component (ELOOP) -- 2.43.2