CVE-2016-10156 (published 2017-01-23T07:59Z)

A flaw in systemd v228 in /src/basic/fs-util.c caused world writable suid files to be created when using the systemd timers features, allowing local attackers to escalate their privileges to root. This is fixed in v229.

Severity: HIGH
CVSS v2 base score: 7.2 (AV:L/AC:L/Au:N/C:C/I:C/A:C)
CVSS v3 base score: 7.8, HIGH (CVSS:3.0/AV:L/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H)

Weakness information:
cwe_id: CWE-264
cwe_name: Permissions, Privileges, and Access Controls
description: Weaknesses in this category are related to the management of permissions, privileges, and other security features that are used to perform access control.

Fix information:
repo_url: https://github.com/systemd/systemd
commit_details: repo_url: https://github.com/systemd/systemd
author: Lennart Poettering
author_date: 2015-11-11 22:54:56+01:00
msg: util-lib: use MODE_INVALID as invalid value for mode_t everywhere
repository: repo_url: https://github.com/systemd/systemd
repo_name: systemd/systemd
description: The systemd System and Service Manager 
repo_language: C
owner: systemd
file_changes: filename: fs-util.c
change_type: ModificationType.MODIFY
diff: @@ -311,7 +311,7 @@ int touch_file(const char *path, bool parents, usec_t stamp, uid_t uid, gid_t gi
         if (fd < 0)
                 return -errno;
 
-        if (mode > 0) {
+        if (mode != MODE_INVALID) {
                 r = fchmod(fd, mode);
                 if (r < 0)
                         return -errno;
@@ -338,7 +338,7 @@ int touch_file(const char *path, bool parents, usec_t stamp, uid_t uid, gid_t gi
 }
 
 int touch(const char *path) {
-        return touch_file(path, false, USEC_INFINITY, UID_INVALID, GID_INVALID, 0);
+        return touch_file(path, false, USEC_INFINITY, UID_INVALID, GID_INVALID, MODE_INVALID);
 }
 
 int symlink_idempotent(const char *from, const char *to) {

programming_language: C
filename: timer.c
change_type: ModificationType.MODIFY
diff: @@ -519,7 +519,7 @@ static void timer_enter_running(Timer *t) {
         dual_timestamp_get(&t->last_trigger);
 
         if (t->stamp_path)
-                touch_file(t->stamp_path, true, t->last_trigger.realtime, UID_INVALID, GID_INVALID, 0);
+                touch_file(t->stamp_path, true, t->last_trigger.realtime, UID_INVALID, GID_INVALID, MODE_INVALID);
 
         timer_set_state(t, TIMER_RUNNING);
         return;
@@ -555,7 +555,7 @@ static int timer_start(Unit *u) {
                         /* The timer has never run before,
                          * make sure a stamp file exists.
                          */
-                        touch_file(t->stamp_path, true, USEC_INFINITY, UID_INVALID, GID_INVALID, 0);
+                        touch_file(t->stamp_path, true, USEC_INFINITY, UID_INVALID, GID_INVALID, MODE_INVALID);
         }
 
         t->result = TIMER_SUCCESS;

programming_language: C
filename: test-conf-files.c
change_type: ModificationType.MODIFY
diff: @@ -26,6 +26,7 @@
 #include "conf-files.h"
 #include "fs-util.h"
 #include "macro.h"
+#include "parse-util.h"
 #include "rm-rf.h"
 #include "string-util.h"
 #include "strv.h"
@@ -40,7 +41,7 @@ static void setup_test_dir(char *tmp_dir, const char *files, ...) {
         va_start(ap, files);
         while (files != NULL) {
                 _cleanup_free_ char *path = strappend(tmp_dir, files);
-                assert_se(touch_file(path, true, USEC_INFINITY, UID_INVALID, GID_INVALID, 0) == 0);
+                assert_se(touch_file(path, true, USEC_INFINITY, UID_INVALID, GID_INVALID, MODE_INVALID) == 0);
                 files = va_arg(ap, const char *);
         }
         va_end(ap);

programming_language: C
repo_url: https://github.com/systemd/systemd
commit_details: repo_url: https://github.com/systemd/systemd
author: Mantas Mikulėnas
author_date: 2016-01-29 23:36:08+02:00
msg: basic: fix touch() creating files with 07777 mode

mode_t is unsigned, so MODE_INVALID < 0 can never be true.

This fixes a possible DoS where any user could fill /run by writing to
a world-writable /run/systemd/show-status.
repository: repo_url: https://github.com/systemd/systemd
repo_name: systemd/systemd
description: The systemd System and Service Manager 
repo_language: C
owner: systemd
file_changes: filename: fs-util.c
change_type: ModificationType.MODIFY
diff: @@ -341,7 +341,8 @@ int touch_file(const char *path, bool parents, usec_t stamp, uid_t uid, gid_t gi
         if (parents)
                 mkdir_parents(path, 0755);
 
-        fd = open(path, O_WRONLY|O_CREAT|O_CLOEXEC|O_NOCTTY, mode > 0 ? mode : 0644);
+        fd = open(path, O_WRONLY|O_CREAT|O_CLOEXEC|O_NOCTTY,
+                        (mode == 0 || mode == MODE_INVALID) ? 0644 : mode);
         if (fd < 0)
                 return -errno;
 

programming_language: C