Compare commits

..
8 Commits
Author SHA1 Message Date
Joachim Wiberg b69d8a6013 Fix copyfile() not preserving source mode with restrictive umask
copyfile() passes the source mode to open(2), which applies the umask,
so a 0644 file copied with umask 0027 ends up 0640.

Apply the source mode with fchmod() after creating the destination.

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2026-09-13 18:53:40 +02:00
Joachim Wiberg e874608b76 Fix mkpath() ignoring mode when umask is more restrictive
mkpath(dir, 0755) with umask 0027 silently creates a 0750 directory,
since mkdir(2) applies the umask to the requested mode.  Callers pass
an explicit mode and expect exactly that.

Apply the mode with chmod() after each successful mkdir().

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2026-09-13 17:17:37 +02:00
Joachim Wiberg c1e050f93c Update ChangeLog and bump version for v2.6.2 release
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2025-11-22 21:59:46 +01:00
Joachim Wiberg 0e45929323 Make note of possible extensions
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2025-11-22 21:44:20 +01:00
Joachim Wiberg 958502d982 Fix memory leak in which() on realloc() failure
Avoid leaking memory when realloc() fails by using a temporary pointer
and only updating the original on success. Also remove redundant NULL
check before free().

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2025-11-22 20:48:35 +01:00
Joachim Wiberg f0cb0b7bf2 .github: bump actions
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2025-04-28 08:34:00 +02:00
Joachim Wiberg ee5788d49b Create SECURITY.md policy 2025-04-28 07:54:35 +02:00
Joachim Wiberg 9bfe54f959 pidfile(): ensure prefix path ends with slash
For some builds using Buildroot, the system default _PATH_VARRUN did not
include a trailing slas '/', which cause the pidfile() function to fail.

Example:
  pidfile("arg") => "/var/runarg.pid"

Since the __pidfile_path can be overridden we add a check if that prefix
path ends with '/', if not we add one in the path composition.

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2024-03-25 05:23:41 +01:00
13 changed files with 141 additions and 20 deletions

No files matched your search

+12
View File
@@ -0,0 +1,12 @@
# Security Policy
## Supported Versions
libite (-lite) is a small project, as such we have no possibility to support older versions.
The only supported version is the latest released on GitHub:
<https://github.com/troglobit/libite/releases>
## Reporting a Vulnerability
Contact the project's main author and owner to report and discuss vulnerabilities.
+3 -3
View File
@@ -28,7 +28,7 @@ jobs:
run: |
sudo apt-get -y update
sudo apt-get -y install tree doxygen
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Configure
run: |
./autogen.sh
@@ -44,7 +44,7 @@ jobs:
run: |
make check || (cat test/test-suite.log; false)
- name: Upload Test Results
uses: actions/upload-artifact@v3
uses: actions/upload-artifact@v4
with:
name: libite-test-${{ matrix.compiler }}
path: test/*
@@ -55,7 +55,7 @@ jobs:
env:
MAKEFLAGS: -j3
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Installing dependencies
run: |
apt-get update
+3 -3
View File
@@ -15,7 +15,7 @@ jobs:
coverity:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Fetch latest Coverity Scan MD5
id: var
env:
@@ -25,7 +25,7 @@ jobs:
--post-data "token=$TOKEN&project=${COVERITY_PROJ}&md5=1" \
-O coverity-latest.tar.gz.md5
echo "md5=$(cat coverity-latest.tar.gz.md5)" | tee -a $GITHUB_OUTPUT
- uses: actions/cache@v3
- uses: actions/cache@v4
id: cache
with:
path: coverity-latest.tar.gz
@@ -74,7 +74,7 @@ jobs:
--form description="${PROJECT_NAME} $(git rev-parse HEAD)" \
https://scan.coverity.com/builds?project=${COVERITY_PROJ}
- name: Upload build.log
uses: actions/upload-artifact@v3
uses: actions/upload-artifact@v4
with:
name: coverity-build.log
path: cov-int/build-log.txt
+1 -1
View File
@@ -11,7 +11,7 @@ jobs:
if: startsWith(github.ref, 'refs/tags/')
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Installing dependencies ...
run: |
sudo apt-get -y update
+20 -1
View File
@@ -4,6 +4,24 @@ Change Log
All notable changes to the project are documented in this file.
[UNRELEASED][]
--------------
### Fixes
- Fix `copyfile()` not preserving the source file mode when the process
umask is more restrictive
- Fix `mkpath()`, and `fmkpath()`, not applying the given mode when the
process umask is more restrictive, e.g., requesting 0755 with umask
0027 silently created a 0750 directory
[v2.6.2][] - 2025-11-22
-----------------------
### Fixes
- Fix memory leak in `which()` on `realloc()` failure
- Fix `pidfile()` to handle missing trailing slash in prefix path
[v2.6.1][] - 2023-10-15
-----------------------
@@ -511,7 +529,8 @@ problems this may cause!
Initial extraction of frog DNA from [Finit][]. See [README][] for API details.
[UNRELEASED]: https://github.com/troglobit/libite/compare/v2.6.1...HEAD
[UNRELEASED]: https://github.com/troglobit/libite/compare/v2.6.2...HEAD
[v2.6.2]: https://github.com/troglobit/libite/compare/v2.6.1...v2.6.2
[v2.6.1]: https://github.com/troglobit/libite/compare/v2.6.0...v2.6.1
[v2.6.0]: https://github.com/troglobit/libite/compare/v2.5.3...v2.6.0
[v2.5.3]: https://github.com/troglobit/libite/compare/v2.5.2...v2.5.3
+14
View File
@@ -1 +1,15 @@
* TODO Write tests for new APIs
* More formatted variants?
- symlinkf()
- accessf()
- statf() / lstatf()
* Relocate from Finit
- fnread()
- fnwrite()
- fngetint()
- paste()
- unquote()
+1 -1
View File
@@ -1,4 +1,4 @@
AC_INIT(libite, 2.6.1, https://github.com/troglobit/libite/issues)
AC_INIT(libite, 2.6.2, https://github.com/troglobit/libite/issues)
AC_CONFIG_AUX_DIR(aux)
AM_INIT_AUTOMAKE([1.11 foreign dist-xz])
AM_SILENT_RULES([yes])
+8
View File
@@ -208,12 +208,20 @@ ssize_t copyfile(const char *src, const char *dst, int len, int opt)
goto exit;
}
/* open(2) applies umask, we want the source file mode */
if (fchmod(out, st.st_mode & 07777)) {
saved_errno = errno;
size = -1;
goto close_exit;
}
size = do_copy(in, out, num, buffer, BUFSIZ);
if (size < 0)
saved_errno = errno;
else if (keep_mtim)
set_mtime(in, out);
close_exit:
close(out);
close(in);
+7 -1
View File
@@ -35,6 +35,9 @@
* @param dir Directory to created, relative or absolute
* @param mode A &mode_t mode to create @a dir with
*
* Directories are created with exactly @a mode, the process umask is
* not applied like it is for mkdir(2).
*
* @returns POSIX OK(0) on success, otherwise -1 with @a errno set.
*/
int mkpath(const char *dir, mode_t mode)
@@ -51,7 +54,10 @@ int mkpath(const char *dir, mode_t mode)
mkpath(dirname(strdupa(dir)), mode);
return mkdir(dir, mode);
if (mkdir(dir, mode))
return -1;
return chmod(dir, mode);
}
/**
+5 -1
View File
@@ -45,6 +45,7 @@
#include <paths.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#ifndef pidfile
@@ -93,7 +94,10 @@ int pidfile(const char *basename)
}
if (basename[0] != '/') {
if (asprintf(&pidfile_path, "%s%s.pid", __pidfile_path, basename) == -1)
size_t len = strlen(__pidfile_path);
int slash = __pidfile_path[len > 0 ? len - 1 : 0] != '/';
if (asprintf(&pidfile_path, "%s%s%s.pid", __pidfile_path, slash ? "/" : "", basename) == -1)
return (-1);
} else {
if (asprintf(&pidfile_path, "%s", basename) == -1)
+9 -6
View File
@@ -53,8 +53,9 @@ static char *strip_args(char *path)
*/
char *which(const char *cmd)
{
char *ptr, *env, *path = NULL;
size_t pathlen = 0;
char *ptr, *tok, *env, *path = NULL;
const char *tok;
if (!cmd) {
errno = EINVAL;
@@ -69,9 +70,7 @@ char *which(const char *cmd)
if (!access(path, X_OK))
return path;
if (path)
free(path);
free(path);
return NULL;
}
@@ -88,11 +87,15 @@ char *which(const char *cmd)
size_t len = strlen(tok) + strlen(cmd) + 2;
if (pathlen < len) {
path = realloc(path, len);
if (!path) {
char *tmp = realloc(path, len);
if (!tmp) {
free(path);
free(env);
return NULL;
}
path = tmp;
pathlen = len;
}
+24 -1
View File
@@ -123,9 +123,32 @@ static int _copyfile()
return rc;
}
/* copyfile() must preserve source mode, even with a restrictive umask */
static int _mode(void)
{
const char *src = "/tmp/libite-mode-src", *dst = "/tmp/libite-mode-dst";
struct stat st;
mode_t old;
int rc = 1;
if (touch(src) || chmod(src, 0644))
return test(1, "copyfile() mode, prepare %s", src);
old = umask(0077);
if (copyfile(src, dst, 0, 0) >= 0 && !stat(dst, &st))
rc = (st.st_mode & 07777) != 0644;
umask(old);
erase(src);
erase(dst);
return test(rc, "copyfile() preserves mode 0644 with umask 0077");
}
int main(void)
{
return _fcopyfile() ||
_copyfile() ||
_sz();
_sz() ||
_mode();
}
+34 -2
View File
@@ -50,6 +50,34 @@ int test_fmkpath(const char *subdir)
return ret;
}
/* mkpath() must apply mode as given, not mode & ~umask */
int test_umask(void)
{
const char *dirs[] = { BASEDIR "/um", BASEDIR "/um/sub", NULL };
mode_t old = umask(0077);
struct stat sb;
int i, ret;
ret = mkpath(dirs[1], 0755);
umask(old);
if (ret) {
perror("Failed");
return ret;
}
for (i = 0; dirs[i]; i++) {
if (checkpath(dirs[i]) || stat(dirs[i], &sb))
return 1;
if ((sb.st_mode & 07777) != 0755) {
fprintf(stderr, "Failed: %s mode %04o, expected 0755\n",
dirs[i], sb.st_mode & 07777);
return 1;
}
}
return 0;
}
int main(void)
{
int i, ret = 0;
@@ -66,14 +94,18 @@ int main(void)
mkdir(BASEDIR, 0755);
printf("Pass 1/2: makepath() =========================\n");
printf("Pass 1/3: makepath() =========================\n");
for (i = 0; list[i] && !ret; i++)
ret |= test_makepath(list[i]);
printf("Pass 2/2: fmkpath() ==========================\n");
printf("Pass 2/3: fmkpath() ==========================\n");
for (i = 0; list[i] && !ret; i++)
ret |= test_fmkpath(list[i] + strlen(BASEDIR) + 1);
printf("Pass 3/3: mkpath() with umask ================\n");
if (!ret)
ret |= test_umask();
printf("Done: Cleaning up ============================\n");
system("rm -rf " BASEDIR);