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);
}
}
|