Recent changes (master)
Jens Axboe <[email protected]> Fri, 1 May 2026 06:00:01 -0600
| Newsgroups | org.kernel.vger.fio |
|---|---|
| Message-ID | <[email protected]> |
The following changes since commit a95f84caad2300e73ec9bf7077879f30246f3185:
sprandom: relax power of 2 block size requirement (2026-04-28 12:25:01 -0400)
are available in the Git repository at:
git://git.kernel.dk/fio.git master
for you to fetch changes up to 72156dca3d41df7d05ea4e5a4e59623c2d393a92:
Merge branch 'codex/cgroup-path-overflows' of https://github.com/linuxholic/fio (2026-04-30 06:53:46 -0600)
----------------------------------------------------------------
Jens Axboe (1):
Merge branch 'codex/cgroup-path-overflows' of https://github.com/linuxholic/fio
yangpeng (1):
cgroup: fix path buffer overflows for long cgroup names
Makefile | 6 ++
cgroup.c | 48 +++++++++++++---
unittests/cgroup.c | 160 +++++++++++++++++++++++++++++++++++++++++++++++++++
unittests/unittest.c | 3 +
unittests/unittest.h | 3 +
5 files changed, 212 insertions(+), 8 deletions(-)
create mode 100644 unittests/cgroup.c
---
Diff of recent changes:
diff --git a/Makefile b/Makefile
index 099e2f94..e3960ece 100644
--- a/Makefile
+++ b/Makefile
@@ -455,6 +455,12 @@ UT_OBJS += unittests/oslib/strlcat.o
UT_OBJS += unittests/oslib/strndup.o
UT_OBJS += unittests/oslib/strcasestr.o
UT_OBJS += unittests/oslib/strsep.o
+ifeq ($(CONFIG_TARGET_OS), Linux)
+UT_OBJS += unittests/cgroup.o
+endif
+ifeq ($(CONFIG_TARGET_OS), Android)
+UT_OBJS += unittests/cgroup.o
+endif
UT_TARGET_OBJS = lib/memalign.o
UT_TARGET_OBJS += lib/num2str.o
UT_TARGET_OBJS += lib/strntol.o
diff --git a/cgroup.c b/cgroup.c
index 77e31a4d..0a26fc8d 100644
--- a/cgroup.c
+++ b/cgroup.c
@@ -18,6 +18,32 @@ struct cgroup_member {
unsigned int cgroup_nodelete;
};
+static char *cgroup_path(struct thread_data *td, const char *path,
+ const char *name, const char *onerr)
+{
+ size_t path_len = strlen(path);
+ size_t name_len = strlen(name);
+ size_t len;
+ char *str;
+ int err;
+
+ if (path_len > SIZE_MAX - name_len - 2) {
+ td_verror(td, ENAMETOOLONG, onerr);
+ return NULL;
+ }
+
+ len = path_len + name_len + 2;
+ str = malloc(len);
+ if (!str) {
+ err = errno;
+ td_verror(td, err, onerr);
+ return NULL;
+ }
+
+ snprintf(str, len, "%s/%s", path, name);
+ return str;
+}
+
static struct cgroup_mnt *find_cgroup_mnt(struct thread_data *td)
{
struct cgroup_mnt *cgroup_mnt = NULL;
@@ -113,32 +139,35 @@ void cgroup_kill(struct flist_head *clist)
static char *get_cgroup_root(struct thread_data *td, struct cgroup_mnt *mnt)
{
- char *str = malloc(64);
-
if (td->o.cgroup)
- sprintf(str, "%s/%s", mnt->path, td->o.cgroup);
+ return cgroup_path(td, mnt->path, td->o.cgroup,
+ "cgroup root path");
else
- sprintf(str, "%s/%s", mnt->path, td->o.name);
-
- return str;
+ return cgroup_path(td, mnt->path, td->o.name,
+ "cgroup root path");
}
static int write_int_to_file(struct thread_data *td, const char *path,
const char *filename, unsigned int val,
const char *onerr)
{
- char tmp[256];
+ char *tmp;
FILE *f;
- sprintf(tmp, "%s/%s", path, filename);
+ tmp = cgroup_path(td, path, filename, onerr);
+ if (!tmp)
+ return 1;
+
f = fopen(tmp, "w");
if (!f) {
+ free(tmp);
td_verror(td, errno, onerr);
return 1;
}
fprintf(f, "%u", val);
fclose(f);
+ free(tmp);
return 0;
}
@@ -178,6 +207,9 @@ int cgroup_setup(struct thread_data *td, struct flist_head *clist, struct cgroup
* Create container, if it doesn't exist
*/
root = get_cgroup_root(td, *mnt);
+ if (!root)
+ return 1;
+
if (mkdir(root, 0755) < 0) {
int __e = errno;
diff --git a/unittests/cgroup.c b/unittests/cgroup.c
new file mode 100644
index 00000000..cc99c3d1
--- /dev/null
+++ b/unittests/cgroup.c
@@ -0,0 +1,160 @@
+#include "../fio.h"
+#include "./unittest.h"
+
+ssize_t log_err(const char *format, ...)
+{
+ return 0;
+}
+
+void *smalloc(size_t size)
+{
+ return malloc(size);
+}
+
+void *scalloc(size_t nmemb, size_t size)
+{
+ return calloc(nmemb, size);
+}
+
+void sfree(void *ptr)
+{
+ free(ptr);
+}
+
+char *smalloc_strdup(const char *str)
+{
+ return strdup(str);
+}
+
+void sinit(void)
+{
+}
+
+void scleanup(void)
+{
+}
+
+void smalloc_debug(size_t size)
+{
+}
+
+unsigned int smalloc_pool_size;
+
+struct fio_sem *fio_sem_init(int value)
+{
+ return NULL;
+}
+
+void fio_sem_remove(struct fio_sem *sem)
+{
+}
+
+void fio_sem_down(struct fio_sem *sem)
+{
+}
+
+void fio_sem_up(struct fio_sem *sem)
+{
+}
+
+#include "../cgroup.c"
+
+static char *test_path_join(const char *path, const char *name)
+{
+ size_t path_len = strlen(path);
+ size_t name_len = strlen(name);
+ size_t len = path_len + name_len + 2;
+ char *joined = malloc(len);
+
+ CU_ASSERT_PTR_NOT_NULL_FATAL(joined);
+ snprintf(joined, len, "%s/%s", path, name);
+ return joined;
+}
+
+static void test_get_cgroup_root_long_path(void)
+{
+ struct thread_data td = { 0 };
+ char mnt_path[] = "/sys/fs/cgroup/blkio";
+ char cgroup_name[] =
+ "/system/pod51ec34a2-12b8-4a51-8b98-b49dace8366f/"
+ "af7853ad741dee19af1b8e14ee2142a7a9314b2dc98a091a29f8aa96106c0a22";
+ struct cgroup_mnt mnt = {
+ .path = mnt_path,
+ .cgroup2 = false,
+ };
+ char *root;
+ char *expected;
+
+ td.o.cgroup = cgroup_name;
+
+ root = get_cgroup_root(&td, &mnt);
+ CU_ASSERT_PTR_NOT_NULL_FATAL(root);
+
+ expected = test_path_join(mnt.path, td.o.cgroup);
+ CU_ASSERT_STRING_EQUAL(root, expected);
+ CU_ASSERT(strlen(root) > 64);
+ CU_ASSERT_EQUAL(td.error, 0);
+
+ free(expected);
+ free(root);
+}
+
+static void test_write_int_to_file_long_path(void)
+{
+ struct thread_data td = { 0 };
+ char tmpdir[] = "/tmp/fio-cgroup-XXXXXX";
+ char leaf[231];
+ char *dir;
+ char *file_path;
+ FILE *f;
+ char buf[32];
+
+ CU_ASSERT_PTR_NOT_NULL_FATAL(mkdtemp(tmpdir));
+
+ memset(leaf, 'x', sizeof(leaf) - 1);
+ leaf[sizeof(leaf) - 1] = '\0';
+
+ dir = test_path_join(tmpdir, leaf);
+ CU_ASSERT_EQUAL_FATAL(mkdir(dir, 0700), 0);
+
+ file_path = test_path_join(dir, "blkio.weight");
+ CU_ASSERT(strlen(file_path) > 256);
+ free(file_path);
+
+ CU_ASSERT_EQUAL(write_int_to_file(&td, dir, "blkio.weight", 1234,
+ "write_int_to_file"), 0);
+ CU_ASSERT_EQUAL(td.error, 0);
+
+ file_path = test_path_join(dir, "blkio.weight");
+ f = fopen(file_path, "r");
+ CU_ASSERT_PTR_NOT_NULL_FATAL(f);
+ CU_ASSERT_PTR_NOT_NULL(fgets(buf, sizeof(buf), f));
+ CU_ASSERT_STRING_EQUAL(buf, "1234");
+ fclose(f);
+
+ CU_ASSERT_EQUAL(unlink(file_path), 0);
+ CU_ASSERT_EQUAL(rmdir(dir), 0);
+ CU_ASSERT_EQUAL(rmdir(tmpdir), 0);
+
+ free(file_path);
+ free(dir);
+}
+
+static struct fio_unittest_entry tests[] = {
+ {
+ .name = "cgroup/get-root-long-path",
+ .fn = test_get_cgroup_root_long_path,
+ },
+ {
+ .name = "cgroup/write-int-to-file-long-path",
+ .fn = test_write_int_to_file_long_path,
+ },
+ {
+ .name = NULL,
+ },
+};
+
+CU_ErrorCode fio_unittest_cgroup(void)
+{
+ return fio_unittest_add_suite("cgroup.c", NULL, NULL, tests);
+}
diff --git a/unittests/unittest.c b/unittests/unittest.c
index 4a034b40..c4316322 100644
--- a/unittests/unittest.c
+++ b/unittests/unittest.c
@@ -55,6 +55,9 @@ int main(void)
fio_unittest_register(fio_unittest_oslib_strndup);
fio_unittest_register(fio_unittest_oslib_strcasestr);
fio_unittest_register(fio_unittest_oslib_strsep);
+#if defined(__linux__) || defined(__ANDROID__)
+ fio_unittest_register(fio_unittest_cgroup);
+#endif
CU_basic_set_mode(CU_BRM_VERBOSE);
CU_basic_run_tests();
diff --git a/unittests/unittest.h b/unittests/unittest.h
index 0f45bfbd..6f2ac776 100644
--- a/unittests/unittest.h
+++ b/unittests/unittest.h
@@ -22,5 +22,8 @@ CU_ErrorCode fio_unittest_oslib_strlcat(void);
CU_ErrorCode fio_unittest_oslib_strndup(void);
CU_ErrorCode fio_unittest_oslib_strcasestr(void);
CU_ErrorCode fio_unittest_oslib_strsep(void);
+#if defined(__linux__) || defined(__ANDROID__)
+CU_ErrorCode fio_unittest_cgroup(void);
+#endif
#endif