summaryrefslogtreecommitdiffstats
path: root/debian/patches/Sanity-check-size-when-converting-the-first-record-t.patch
blob: c0964be2c3c6a9b612e27716a81a69355561021d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
From 586b418ad85ff8c2e756eff7063ffaeca631fa02 Mon Sep 17 00:00:00 2001
From: "Todd C. Miller" <Todd.Miller@sudo.ws>
Date: Sun, 5 Jan 2020 09:37:09 -0700
Subject: [PATCH] Sanity check size when converting the first record to
 TS_LOCKEXCL Coverity CID 206591

[Salvatore Bonaccorso: Backport to 1.8.27:
 - Context changes
 - Drop hunk about copyright years update
 - Cast sizeof(struct timestamp_entry_v1) into ssize_t as 1.8.27 does
   not contain the "Add ssizeof macro that returns ssize_t" change.
]
---
 plugins/sudoers/timestamp.c | 65 ++++++++++++++++++++++++++++---------
 1 file changed, 49 insertions(+), 16 deletions(-)

--- a/plugins/sudoers/timestamp.c
+++ b/plugins/sudoers/timestamp.c
@@ -611,6 +611,25 @@ done:
 }
 
 /*
+ * Write a TS_LOCKEXCL record at the beginning of the time stamp file.
+ */
+bool
+timestamp_lock_write(struct ts_cookie *cookie)
+{
+    struct timestamp_entry entry;
+    bool ret = true;
+    debug_decl(timestamp_lock_write, SUDOERS_DEBUG_AUTH);
+
+    memset(&entry, 0, sizeof(entry));
+    entry.version = TS_VERSION;
+    entry.size = sizeof(entry);
+    entry.type = TS_LOCKEXCL;
+    if (ts_write(cookie->fd, cookie->fname, &entry, -1) == -1)
+	ret = false;
+    debug_return_bool(ret);
+}
+
+/*
  * Lock a record in the time stamp file for exclusive access.
  * If the record does not exist, it is created (as disabled).
  */
@@ -619,6 +638,7 @@ timestamp_lock(void *vcookie, struct pas
 {
     struct ts_cookie *cookie = vcookie;
     struct timestamp_entry entry;
+    bool overwrite = false;
     off_t lock_pos;
     ssize_t nread;
     debug_decl(timestamp_lock, SUDOERS_DEBUG_AUTH)
@@ -640,26 +660,39 @@ timestamp_lock(void *vcookie, struct pas
     /* Make sure the first record is of type TS_LOCKEXCL. */
     memset(&entry, 0, sizeof(entry));
     nread = read(cookie->fd, &entry, sizeof(entry));
-    if (nread == 0) {
-	/* New file, add TS_LOCKEXCL record. */
-	entry.version = TS_VERSION;
-	entry.size = sizeof(entry);
-	entry.type = TS_LOCKEXCL;
-	if (ts_write(cookie->fd, cookie->fname, &entry, -1) == -1)
-	    debug_return_bool(false);
+    if (nread < (ssize_t)sizeof(struct timestamp_entry_v1)) {
+	/* New or invalid time stamp file. */
+	overwrite = true;
     } else if (entry.type != TS_LOCKEXCL) {
-	/* Old sudo record, convert it to TS_LOCKEXCL. */
-	entry.type = TS_LOCKEXCL;
-	memset((char *)&entry + offsetof(struct timestamp_entry, type), 0,
-	    nread - offsetof(struct timestamp_entry, type));
-	if (ts_write(cookie->fd, cookie->fname, &entry, 0) == -1)
-	    debug_return_bool(false);
+	if (entry.size == sizeof(struct timestamp_entry_v1)) {
+	    /* Old sudo record, convert it to TS_LOCKEXCL. */
+	    entry.type = TS_LOCKEXCL;
+	    memset((char *)&entry + offsetof(struct timestamp_entry, type), 0,
+		nread - offsetof(struct timestamp_entry, type));
+	    if (ts_write(cookie->fd, cookie->fname, &entry, 0) == -1)
+		debug_return_bool(false);
+	} else {
+	    /* Corrupted time stamp file?  Just overwrite it. */
+	    sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_ERRNO|SUDO_DEBUG_LINENO,
+		"corrupt initial record, type: %hu, size: %hu (expected %zu)",
+		entry.type, entry.size, sizeof(struct timestamp_entry_v1));
+	    overwrite = true;
+	}
     }
-    if (entry.size != sizeof(entry)) {
+    if (overwrite) {
+	/* Rewrite existing time stamp file or create new one. */
+	if (ftruncate(cookie->fd, 0) != 0) {
+	    sudo_warn(U_("unable to truncate time stamp file to %lld bytes"),
+		0LL);
+	    debug_return_bool(false);
+	}
+	if (!timestamp_lock_write(cookie))
+	    debug_return_bool(false);
+    } else if (entry.size != sizeof(entry)) {
 	/* Reset position if the lock record has an unexpected size. */
 	if (lseek(cookie->fd, entry.size, SEEK_SET) == -1) {
 	    sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_ERRNO|SUDO_DEBUG_LINENO,
-		"unable to seek to %lld", (long long)entry.size);
+		"unable to seek to %hu", entry.size);
 	    debug_return_bool(false);
 	}
     }