Skip to content
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

Fixed directory creation to ignore umask, and allow cross process loc… #1078

Merged
merged 5 commits into from
Nov 16, 2023
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 42 additions & 6 deletions source/posix/cross_process_lock.c
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
#include <errno.h>
#include <fcntl.h>
#include <sys/file.h>
#include <sys/stat.h>
#include <unistd.h>

#include <aws/common/error.h>
Expand Down Expand Up @@ -41,14 +42,20 @@ struct aws_cross_process_lock *aws_cross_process_lock_try_acquire(
* The unix standard says /tmp has to be there and be writable. However, while it may be tempting to just use the
* /tmp/ directory, it often has the sticky bit set which would prevent a subprocess from being able to call open
* with create on the file. The solution is simple, just write it to a subdirectory inside
* /tmp using the same perms as the current process.
* /tmp and override umask via. chmod of 0777.
*/
struct aws_byte_cursor path_prefix = aws_byte_cursor_from_c_str("/tmp/aws_crt_cross_process_lock/");
struct aws_string *path_to_create = aws_string_new_from_cursor(allocator, &path_prefix);
/* it's probably there already and we don't care if it is. The open will fail and we will handle it there
* if we can't open it due to permissions. */
aws_directory_create(path_to_create);

/* It's probably there already and we don't care if it is. */
if (!aws_directory_exists(path_to_create)) {
/* if this call fails just let it fail on open below. */
aws_directory_create(path_to_create);
/* bypass umask by setting the perms we actually requested */
chmod(aws_string_c_str(path_to_create), S_IRWXU | S_IRWXG | S_IRWXO);
}
aws_string_destroy(path_to_create);

struct aws_byte_cursor path_suffix = aws_byte_cursor_from_c_str(".lock");

struct aws_byte_buf nonce_buf;
Expand All @@ -59,16 +66,45 @@ struct aws_cross_process_lock *aws_cross_process_lock_try_acquire(

struct aws_cross_process_lock *instance_lock = NULL;

errno = 0;
int fd = open((const char *)nonce_buf.buffer, O_CREAT | O_RDWR, 0666);
if (fd < 0) {
AWS_LOGF_ERROR(
AWS_LOGF_DEBUG(
AWS_LS_COMMON_GENERAL,
"static: Lock file %s failed to open with errno %d",
(const char *)nonce_buf.buffer,
errno);

aws_translate_and_raise_io_error_or(errno, AWS_ERROR_MUTEX_FAILED);
goto cleanup;

if (aws_last_error() == AWS_ERROR_NO_PERMISSION) {
AWS_LOGF_DEBUG(
AWS_LS_COMMON_GENERAL,
"static: Lock file %s couldn't be opened due to file ownership permissions. Attempting to open as read "
"only",
(const char *)nonce_buf.buffer);

errno = 0;
fd = open((const char *)nonce_buf.buffer, O_RDONLY);

if (fd < 0) {
AWS_LOGF_ERROR(
AWS_LS_COMMON_GENERAL,
"static: Lock file %s failed to open with read-only permissions with errno %d",
(const char *)nonce_buf.buffer,
errno);
aws_translate_and_raise_io_error_or(errno, AWS_ERROR_MUTEX_FAILED);
goto cleanup;
}
} else {
AWS_LOGF_ERROR(
AWS_LS_COMMON_GENERAL,
"static: Lock file %s failed to open. The lock cannot be acquired.",
(const char *)nonce_buf.buffer);
goto cleanup;
}
}

if (flock(fd, LOCK_EX | LOCK_NB) == -1) {
AWS_LOGF_TRACE(
AWS_LS_COMMON_GENERAL,
Expand Down