Data-Deque-Shared
view release on metacpan or search on metacpan
/* Securely obtain a fd for the path-based backing store. Either create it fresh
* (O_CREAT|O_EXCL|O_NOFOLLOW at `mode`, default 0600 = owner-only), or, if it
* already exists, attach to it (O_RDWR|O_NOFOLLOW, no O_CREAT). O_EXCL blocks a
* pre-seeded or hard-linked file and O_NOFOLLOW a symlink swap, so a local
* attacker can no longer redirect or poison the backing store through the path.
* Cross-user sharing is opt-in via a wider `mode` (e.g. 0660); the caller still
* validates the file's contents. */
static int deq_secure_open(const char *path, mode_t mode, char *errbuf) {
for (int attempt = 0; attempt < 100; attempt++) {
int fd = open(path, O_RDWR|O_CREAT|O_EXCL|O_NOFOLLOW|O_CLOEXEC, mode);
if (fd >= 0) { (void)fchmod(fd, mode); return fd; } /* exact mode: umask narrowed the O_EXCL create */
if (errno != EEXIST) { DEQ_ERR("create %s: %s", path, strerror(errno)); return -1; }
fd = open(path, O_RDWR|O_NOFOLLOW|O_CLOEXEC);
if (fd >= 0) return fd;
if (errno == ENOENT) continue; /* creator unlinked between our two opens; retry */
DEQ_ERR("open %s: %s", path, strerror(errno)); /* ELOOP => symlink rejected */
return -1;
}
DEQ_ERR("open %s: create/attach kept racing", path);
return -1;
}
( run in 1.204 second using v1.01-cache-2.11-cpan-600a1bdf6e4 )