Skip to content

Commit

Permalink
Avoid undefined behaviour if uid_t/gid_t is signed.
Browse files Browse the repository at this point in the history
This drops support for CentOS 7 because its GCC is too old
to support `__builtin_add_overflow`, and its EOL'ing in about
half a year anyway.

Fixes #143
  • Loading branch information
mpartel committed Nov 10, 2023
1 parent 3f57fa6 commit 165d5ab
Show file tree
Hide file tree
Showing 3 changed files with 47 additions and 55 deletions.
5 changes: 5 additions & 0 deletions ChangeLog
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
2023-11-10 Martin Pärtel <martin dot partel at gmail dot com>

* Fixed undefined behaviour on platforms where `uid_t` or `gid_t`
is signed (issue #143, thanks @hartwork!)

2023-11-09 Martin Pärtel <martin dot partel at gmail dot com>

* Support negative --{uid,gid}-offset (issue #142)
Expand Down
74 changes: 42 additions & 32 deletions src/bindfs.c
Original file line number Diff line number Diff line change
Expand Up @@ -243,10 +243,11 @@ static int chown_new_file(const char *path, struct fuse_context *fc, int (*chown
static int delete_file(const char *path, int (*target_delete_func)(const char *));

/* Apply offsets with overflow checking. */
static int apply_uid_offset(uid_t *uid);
static int apply_gid_offset(gid_t *gid);
static int unapply_uid_offset(uid_t *uid);
static int unapply_gid_offset(gid_t *gid);
static bool apply_uid_offset(uid_t *uid);
static bool apply_gid_offset(gid_t *gid);
static bool unapply_uid_offset(uid_t *uid);
static bool unapply_gid_offset(gid_t *gid);
static bool bounded_add(int64_t* a, int64_t b, int64_t max);

#ifdef __linux__
static size_t round_up_buffer_size_for_direct_io(size_t size);
Expand Down Expand Up @@ -635,48 +636,57 @@ static int delete_file(const char *path, int (*target_delete_func)(const char *)
return 0;
}

static int apply_uid_offset(uid_t *uid) {
uid_t result = *uid + (uid_t)settings.uid_offset;
if (0 <= result && result <= UID_T_MAX) {
*uid = result;
return 1;
static bool apply_uid_offset(uid_t *uid) {
int64_t value = (int64_t)*uid;
if (bounded_add(&value, settings.uid_offset, UID_T_MAX)) {
*uid = (uid_t)value;
return true;
} else {
DPRINTF("UID %ld overflowed while applying offset", (int64_t)*uid);
return 0;
DPRINTF("UID %ld out of bounds after applying offset", value);
return false;
}
}

static int apply_gid_offset(gid_t *gid) {
gid_t result = *gid + (gid_t)settings.gid_offset;
if (0 <= result && result <= GID_T_MAX) {
*gid = result;
return 1;
static bool apply_gid_offset(gid_t *gid) {
int64_t value = (int64_t)*gid;
if (bounded_add(&value, settings.gid_offset, GID_T_MAX)) {
*gid = (uid_t)value;
return true;
} else {
DPRINTF("GID %ld overflowed while applying offset", (int64_t)*gid);
return 0;
DPRINTF("GID %ld out of bounds after applying offset", value);
return false;
}
}

static int unapply_uid_offset(uid_t *uid) {
uid_t result = *uid - (uid_t)settings.uid_offset;
if (0 <= result && result <= UID_T_MAX) {
*uid = result;
return 1;
static bool unapply_uid_offset(uid_t *uid) {
int64_t value = (int64_t)*uid;
if (bounded_add(&value, -settings.uid_offset, UID_T_MAX)) {
*uid = (uid_t)value;
return true;
} else {
DPRINTF("UID %ld underflowed while applying offset", (int64_t)*uid);
return 0;
DPRINTF("UID %ld out of bounds after unapplying offset", value);
return false;
}
}

static int unapply_gid_offset(gid_t *gid) {
gid_t result = *gid - (gid_t)settings.gid_offset;
if (0 <= result && result <= GID_T_MAX) {
*gid = result;
return 1;
static bool unapply_gid_offset(gid_t *gid) {
int64_t value = (int64_t)*gid;
if (bounded_add(&value, -settings.gid_offset, GID_T_MAX)) {
*gid = (uid_t)value;
return true;
} else {
DPRINTF("GID %ld underflowed while applying offset", (int64_t)*gid);
return 0;
DPRINTF("GID %ld out of bounds after unapplying offset", value);
return false;
}
}

static bool bounded_add(int64_t* a, int64_t b, int64_t max) {
int64_t result;
if (!__builtin_add_overflow(*a, b, &result) && 0 <= result && result <= max) {
*a = result;
return true;
}
return false;
}

#ifdef __linux__
Expand Down
23 changes: 0 additions & 23 deletions vagrant/centos7/Vagrantfile

This file was deleted.

0 comments on commit 165d5ab

Please sign in to comment.