From 0f7c1ef8e06413679928746c7206786210d3df1e Mon Sep 17 00:00:00 2001
From: Dominic Cleal <dcleal@redhat.com>
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 <stdio.h>
+#include <sys/stat.h>
#include <sys/types.h>
#include <sys/wait.h>
@@ -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