Skip to content

Commit 8f2539a

Browse files
committed
Explain why there is no use after free vulnerability
When looking at the code I initially thought that commit b8f0031 introduced a use after free vulnerability. It does not, but this was not clear from reading the code, so add comments to explain why the buffer (unlike stdin_buf) can just be uninitialized memory and will always be valid throughout process_io() until it is freed. Also avoid allocating two buffers when one will do.
1 parent a2e0deb commit 8f2539a

File tree

2 files changed

+19
-9
lines changed

2 files changed

+19
-9
lines changed

libqrexec/process_io.c

+2-9
Original file line numberDiff line numberDiff line change
@@ -110,12 +110,6 @@ int process_io(const struct process_io_request *req) {
110110
};
111111
if (remote_buffer.data == NULL)
112112
handle_vchan_error("remote buffer alloc");
113-
struct buffer stdin_buffer = {
114-
.data = malloc(max_chunk_size),
115-
.buflen = max_chunk_size,
116-
};
117-
if (stdin_buffer.data == NULL)
118-
handle_vchan_error("stdin buffer alloc");
119113

120114
sigemptyset(&pollmask);
121115
sigaddset(&pollmask, SIGCHLD);
@@ -279,7 +273,7 @@ int process_io(const struct process_io_request *req) {
279273
if (prefix.len > 0 || (stdout_fd >= 0 && fds[FD_STDOUT].revents)) {
280274
switch (handle_input_v2(
281275
vchan, stdout_fd, stdout_msg_type,
282-
&prefix, &stdin_buffer)) {
276+
&prefix, &remote_buffer)) {
283277
case REMOTE_ERROR:
284278
handle_vchan_error("send(handle_input stdout)");
285279
break;
@@ -291,7 +285,7 @@ int process_io(const struct process_io_request *req) {
291285
if (stderr_fd >= 0 && fds[FD_STDERR].revents) {
292286
switch (handle_input_v2(
293287
vchan, stderr_fd, MSG_DATA_STDERR,
294-
&empty, &stdin_buffer)) {
288+
&empty, &remote_buffer)) {
295289
case REMOTE_ERROR:
296290
handle_vchan_error("send(handle_input stderr)");
297291
break;
@@ -321,7 +315,6 @@ int process_io(const struct process_io_request *req) {
321315
}
322316

323317
free(remote_buffer.data);
324-
free(stdin_buffer.data);
325318

326319
if (!is_service && remote_status)
327320
return remote_status;

libqrexec/remote.h

+17
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,17 @@
4040
* Options:
4141
* replace_chars_stdout, replace_chars_stderr - remove non-printable
4242
* characters from stdout/stderr
43+
*
44+
* stdin_buf is the buffer holding data to be written to stdin, and may
45+
* be modified or reallocated. Its content must be valid data, and on
46+
* return it will be a valid buffer pointing to valid (generally different)
47+
* data.
48+
*
49+
* buffer is scratch space _only_. Its size must be the maximum data
50+
* chunk size. Its contents (the data pointed to) does _not_ need to be
51+
* initialized, and will _not_ be anything meaningful on return. The
52+
* buffer pointer and length will not be changed and will remain valid,
53+
* though. In Rust terms: this is an &mut [MaybeUninit<u8>].
4354
*/
4455
int handle_remote_data_v2(
4556
libvchan_t *data_vchan, int stdin_fd, int *status,
@@ -56,6 +67,12 @@ int handle_remote_data_v2(
5667
* REMOTE_EOF - EOF received, do not access this FD again
5768
* REMOTE_OK - some data processed, call it again when buffer space and
5869
* more data availabla
70+
*
71+
* buffer is scratch space _only_. Its size must be the maximum data
72+
* chunk size. Its contents (the data pointed to) does _not_ need to be
73+
* initialized, and will _not_ be anything meaningful on return. The
74+
* buffer pointer and length will not be freed or reallocated, though.
75+
* In Rust terms: this is an &mut [MaybeUninit<u8>].
5976
*/
6077
int handle_input_v2(
6178
libvchan_t *vchan, int fd, int msg_type,

0 commit comments

Comments
 (0)