diff mbox series

[3/5] libselinux/utils/selabel_digest: avoid buffer overflow

Message ID 20240313111025.43720-3-cgzones@googlemail.com (mailing list archive)
State Accepted
Commit 994b9b205e36
Delegated to: Petr Lautrbach
Headers show
Series [1/5] libselinux/utils/selabel_digest: drop unsupported option -d | expand

Commit Message

Christian Göttsche March 13, 2024, 11:10 a.m. UTC
In case the specfiles have very long paths or there are too many abort
instead of writing past the stack buffer.

Signed-off-by: Christian Göttsche <cgzones@googlemail.com>
---
 libselinux/utils/selabel_digest.c | 45 ++++++++++++++++++++++++-------
 1 file changed, 36 insertions(+), 9 deletions(-)
diff mbox series

Patch

diff --git a/libselinux/utils/selabel_digest.c b/libselinux/utils/selabel_digest.c
index db0d443a..64051070 100644
--- a/libselinux/utils/selabel_digest.c
+++ b/libselinux/utils/selabel_digest.c
@@ -66,7 +66,7 @@  int main(int argc, char **argv)
 
 	char cmd_buf[4096];
 	char *cmd_ptr;
-	char *sha1_buf;
+	char *sha1_buf = NULL;
 
 	struct selabel_handle *hnd;
 	struct selinux_opt selabel_option[] = {
@@ -167,23 +167,50 @@  int main(int argc, char **argv)
 	printf("calculated using the following specfile(s):\n");
 
 	if (specfiles) {
-		cmd_ptr = &cmd_buf[0];
-		sprintf(cmd_ptr, "/usr/bin/cat ");
-		cmd_ptr = &cmd_buf[0] + strlen(cmd_buf);
+		size_t cmd_rem = sizeof(cmd_buf);
+		int ret;
+
+		if (validate) {
+			cmd_ptr = &cmd_buf[0];
+			ret = snprintf(cmd_ptr, cmd_rem, "/usr/bin/cat ");
+			if (ret < 0 || (size_t)ret >= cmd_rem) {
+				fprintf(stderr, "Could not format validate command\n");
+				rc = -1;
+				goto err;
+			}
+			cmd_ptr += ret;
+			cmd_rem -= ret;
+		}
 
 		for (i = 0; i < num_specfiles; i++) {
-			sprintf(cmd_ptr, "%s ", specfiles[i]);
-			cmd_ptr += strlen(specfiles[i]) + 1;
+			if (validate) {
+				ret = snprintf(cmd_ptr, cmd_rem, "%s ", specfiles[i]);
+				if (ret < 0 || (size_t)ret >= cmd_rem) {
+					fprintf(stderr, "Could not format validate command\n");
+					rc = -1;
+					goto err;
+				}
+				cmd_ptr += ret;
+				cmd_rem -= ret;
+			}
+
 			printf("%s\n", specfiles[i]);
 		}
-		sprintf(cmd_ptr, "| /usr/bin/openssl dgst -sha1 -hex");
 
-		if (validate)
+		if (validate) {
+			ret = snprintf(cmd_ptr, cmd_rem, "| /usr/bin/openssl dgst -sha1 -hex");
+			if (ret < 0 || (size_t)ret >= cmd_rem) {
+				fprintf(stderr, "Could not format validate command\n");
+				rc = -1;
+				goto err;
+			}
+
 			rc = run_check_digest(cmd_buf, sha1_buf, digest_len);
+		}
 	}
 
-	free(sha1_buf);
 err:
+	free(sha1_buf);
 	selabel_close(hnd);
 	return rc;
 }