From 0f7c1ef8e06413679928746c7206786210d3df1e Mon Sep 17 00:00:00 2001 From: Dominic Cleal Date: Mon, 2 Dec 2013 17:49:35 +0000 Subject: [PATCH] Fix umask handling when creating new files * src/transform.c (transform_save): faulty umask arithmetic would cause overly-open file modes when the umask contains "7", as the umask was incorrectly subtracted from the target file mode Fixes CVE-2013-6412, RHBZ#1034261 (cherry picked from commit f5b4fc0ceb0e5a2be5f3a19f63ad936897a3ac26) --- src/transform.c | 2 +- tests/test-save.c | 48 ++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 49 insertions(+), 1 deletion(-) diff --git a/src/transform.c b/src/transform.c index ccbe422..b0288fc 100644 --- a/src/transform.c +++ b/src/transform.c @@ -1144,7 +1144,7 @@ int transform_save(struct augeas *aug, struct tree *xfm, mode_t curumsk = umask(022); umask(curumsk); - if (fchmod(fileno(fp), 0666 - curumsk) < 0) { + if (fchmod(fileno(fp), 0666 & ~curumsk) < 0) { err_status = "create_chmod"; return -1; } diff --git a/tests/test-save.c b/tests/test-save.c index 617ef31..f28f626 100644 --- a/tests/test-save.c +++ b/tests/test-save.c @@ -26,6 +26,7 @@ #include "cutest.h" #include +#include #include #include @@ -51,6 +52,7 @@ static void setup(CuTest *tc) { if (asprintf(&lensdir, "%s/lenses", abs_top_srcdir) < 0) CuFail(tc, "asprintf lensdir failed"); + umask(0022); run(tc, "test -d %s && chmod -R u+w %s || :", root, root); run(tc, "rm -rf %s", root); run(tc, "mkdir -p %s", root); @@ -221,6 +223,49 @@ static void testDoubleSlashPath(CuTest *tc) { CuAssertIntEquals(tc, 1, r); } +/* Check the umask is followed when creating files + */ +static void testUmask(CuTest *tc, int tumask, mode_t expected_mode) { + int r; + struct stat buf; + char* fpath = NULL; + + if (asprintf(&fpath, "%s/etc/test", root) < 0) { + CuFail(tc, "failed to set root"); + } + + umask(tumask); + + r = aug_rm(aug, "/augeas/load/*"); + CuAssertPositive(tc, r); + + r = aug_set(aug, "/augeas/load/Test/lens", "Simplelines.lns"); + CuAssertRetSuccess(tc, r); + r = aug_set(aug, "/augeas/load/Test/incl", "/etc/test"); + CuAssertRetSuccess(tc, r); + r = aug_load(aug); + CuAssertRetSuccess(tc, r); + r = aug_set(aug, "/files/etc/test/1", "test"); + CuAssertRetSuccess(tc, r); + + r = aug_save(aug); + CuAssertRetSuccess(tc, r); + r = aug_match(aug, "/augeas//error", NULL); + CuAssertIntEquals(tc, 0, r); + + CuAssertIntEquals(tc, 0, stat(fpath, &buf)); + CuAssertIntEquals(tc, expected_mode, buf.st_mode & 0777); +} +static void testUmask077(CuTest *tc) { + testUmask(tc, 0077, 0600); +} +static void testUmask027(CuTest *tc) { + testUmask(tc, 0027, 0640); +} +static void testUmask022(CuTest *tc) { + testUmask(tc, 0022, 0644); +} + int main(void) { char *output = NULL; CuSuite* suite = CuSuiteNew(); @@ -245,6 +290,9 @@ int main(void) { SUITE_ADD_TEST(suite, testMtime); SUITE_ADD_TEST(suite, testRelPath); SUITE_ADD_TEST(suite, testDoubleSlashPath); + SUITE_ADD_TEST(suite, testUmask077); + SUITE_ADD_TEST(suite, testUmask027); + SUITE_ADD_TEST(suite, testUmask022); CuSuiteRun(suite); CuSuiteSummary(suite, &output); -- 1.8.4.2