From a228b256f7460084573c69552ac02199c41b2c1b Mon Sep 17 00:00:00 2001 From: Liangbin Lian Date: Thu, 6 Jun 2024 16:00:54 +0800 Subject: [PATCH] package/uci: prevent writing empty configuration files when disk is full Signed-off-by: Liangbin Lian (cherry picked from commit 2408c5fdeead2d77529a6306a5d1b5a6c2fcf663) --- package/system/uci/Makefile | 2 +- .../001-1-dont-save-broken-config.patch | 97 +++++++++++++++++++ ...ush-delta-only-after-successful-save.patch | 46 +++++++++ 3 files changed, 144 insertions(+), 1 deletion(-) create mode 100644 package/system/uci/patches/001-1-dont-save-broken-config.patch create mode 100644 package/system/uci/patches/001-2-flush-delta-only-after-successful-save.patch diff --git a/package/system/uci/Makefile b/package/system/uci/Makefile index c8f661c684..c1b6a0bbbc 100644 --- a/package/system/uci/Makefile +++ b/package/system/uci/Makefile @@ -9,7 +9,7 @@ include $(TOPDIR)/rules.mk PKG_NAME:=uci -PKG_RELEASE:=1 +PKG_RELEASE:=2 PKG_SOURCE_URL=$(PROJECT_GIT)/project/uci.git PKG_SOURCE_PROTO:=git diff --git a/package/system/uci/patches/001-1-dont-save-broken-config.patch b/package/system/uci/patches/001-1-dont-save-broken-config.patch new file mode 100644 index 0000000000..ef8c2f5314 --- /dev/null +++ b/package/system/uci/patches/001-1-dont-save-broken-config.patch @@ -0,0 +1,97 @@ +From 237d5542986ddb00733e172e638339544058d2d8 Mon Sep 17 00:00:00 2001 +From: Liangbin Lian +Date: Thu, 6 Jun 2024 15:42:11 +0800 +Subject: [PATCH] file: don't save broken uci config + +Signed-off-by: Liangbin Lian +--- + file.c | 32 +++++++++++++++++++++++--------- + 1 file changed, 23 insertions(+), 9 deletions(-) + +diff --git a/file.c b/file.c +index 93abfae..5c942b8 100644 +--- a/file.c ++++ b/file.c +@@ -607,7 +607,7 @@ static const char *uci_escape(struct uci_context *ctx, const char *str) + /* + * export a single config package to a file stream + */ +-static void uci_export_package(struct uci_package *p, FILE *stream, bool header) ++static int uci_export_package(struct uci_package *p, FILE *stream, bool header) + { + struct uci_context *ctx = p->ctx; + struct uci_element *s, *o, *i; +@@ -639,7 +639,8 @@ static void uci_export_package(struct uci_package *p, FILE *stream, bool header) + } + } + } +- fprintf(stream, "\n"); ++ /* return last fprintf to check 'No space left on device' error */ ++ return fprintf(stream, "\n"); + } + + int uci_export(struct uci_context *ctx, FILE *stream, struct uci_package *package, bool header) +@@ -649,11 +650,15 @@ int uci_export(struct uci_context *ctx, FILE *stream, struct uci_package *packag + UCI_HANDLE_ERR(ctx); + UCI_ASSERT(ctx, stream != NULL); + +- if (package) +- uci_export_package(package, stream, header); +- else { ++ if (package) { ++ if (uci_export_package(package, stream, header) < 0) { ++ return UCI_ERR_IO; ++ } ++ } else { + uci_foreach_element(&ctx->root, e) { +- uci_export_package(uci_to_package(e), stream, header); ++ if (uci_export_package(uci_to_package(e), stream, header) < 0) { ++ return UCI_ERR_IO; ++ } + } + } + +@@ -739,6 +744,7 @@ static void uci_file_commit(struct uci_context *ctx, struct uci_package **packag + char *filename = NULL; + struct stat statbuf; + volatile bool do_rename = false; ++ volatile bool clean_temp = false; + int fd, sz; + + if (!p->path) { +@@ -800,14 +806,19 @@ static void uci_file_commit(struct uci_context *ctx, struct uci_package **packag + if (!f2) + UCI_THROW(ctx, UCI_ERR_IO); + +- uci_export(ctx, f2, p, false); ++ clean_temp = true; ++ if (uci_export(ctx, f2, p, false)) ++ goto no_space; + +- fflush(f2); ++ if (fflush(f2)) ++ goto no_space; + fsync(fileno(f2)); +- uci_close_stream(f2); + + do_rename = true; + ++no_space: ++ uci_close_stream(f2); ++ + UCI_TRAP_RESTORE(ctx); + + done: +@@ -821,6 +832,9 @@ done: + UCI_THROW(ctx, UCI_ERR_IO); + } + free(path); ++ } else if (clean_temp) { ++ unlink(filename); ++ UCI_THROW(ctx, UCI_ERR_IO); + } + if (ctx->err) + UCI_THROW(ctx, ctx->err); +-- +2.41.0 + diff --git a/package/system/uci/patches/001-2-flush-delta-only-after-successful-save.patch b/package/system/uci/patches/001-2-flush-delta-only-after-successful-save.patch new file mode 100644 index 0000000000..119b54ccde --- /dev/null +++ b/package/system/uci/patches/001-2-flush-delta-only-after-successful-save.patch @@ -0,0 +1,46 @@ +From 17586039934498210dc0a10bbe5a21cc042cdcd2 Mon Sep 17 00:00:00 2001 +From: Liangbin Lian +Date: Thu, 6 Jun 2024 15:42:46 +0800 +Subject: [PATCH] file: flush delta only after successful save + +Signed-off-by: Liangbin Lian +--- + file.c | 15 +++++++++++++-- + 1 file changed, 13 insertions(+), 2 deletions(-) + +diff --git a/file.c b/file.c +index 5c942b8..a6f30fe 100644 +--- a/file.c ++++ b/file.c +@@ -787,8 +787,8 @@ static void uci_file_commit(struct uci_context *ctx, struct uci_package **packag + path = NULL; + } + +- /* flush delta */ +- if (!uci_load_delta(ctx, p, true)) ++ /* flush delta after successful save */ ++ if (!uci_load_delta(ctx, p, false)) + goto done; + } + +@@ -830,6 +830,17 @@ done: + if (!path || stat(path, &statbuf) || chmod(filename, statbuf.st_mode) || rename(filename, path)) { + unlink(filename); + UCI_THROW(ctx, UCI_ERR_IO); ++ } else if (p->has_delta) { ++ /* flush delta */ ++ filename = NULL; ++ if ((asprintf(&filename, "%s/%s", ctx->savedir, p->e.name) < 0) || !filename) ++ UCI_THROW(ctx, UCI_ERR_MEM); ++ f1 = uci_open_stream(ctx, filename, NULL, SEEK_SET, true, false); ++ if (f1) { ++ ftruncate(fileno(f1), 0); ++ uci_close_stream(f1); ++ } ++ free(filename); + } + free(path); + } else if (clean_temp) { +-- +2.41.0 +