swid-gen: Use process_t to avoid potential command injection

In a targeted request, the software ID is provided by the IMV.  If no
database is used (which is not the recommended setup), the ID is not
validated and could potentially contain special characters.  With the
previous command string construction and use of popen(), which runs a
shell, that could potentially allow running arbitrary commands.
This commit is contained in:
Tobias Brunner
2026-05-19 17:27:33 +02:00
parent ac703e48c3
commit 9ac3db8e63
+37 -15
View File
@@ -16,10 +16,12 @@
#define _GNU_SOURCE #define _GNU_SOURCE
#include <stdio.h> #include <stdio.h>
#include <unistd.h>
#include "swid_gen.h" #include "swid_gen.h"
#include <bio/bio_writer.h> #include <bio/bio_writer.h>
#include <utils/process.h>
#define SWID_GENERATOR "/usr/local/bin/swid_generator" #define SWID_GENERATOR "/usr/local/bin/swid_generator"
@@ -57,31 +59,50 @@ METHOD(swid_gen_t, generate_tag, char*,
private_swid_gen_t *this, char *sw_id, char *package, char *version, private_swid_gen_t *this, char *sw_id, char *package, char *version,
bool full, bool pretty) bool full, bool pretty)
{ {
process_t *process;
char *tag = NULL; char *tag = NULL;
size_t tag_buf_len = 8192; size_t tag_buf_len = 8192;
char tag_buf[tag_buf_len], command[BUF_LEN]; char tag_buf[tag_buf_len], *argv[12] = {};
bio_writer_t *writer; bio_writer_t *writer;
chunk_t swid_tag; chunk_t swid_tag;
FILE *file; FILE *file;
int i = 0, out;
argv[i++] = this->generator;
argv[i++] = "swid";
argv[i++] = "--entity-name";
argv[i++] = this->entity;
argv[i++] = "--regid";
argv[i++] = this->regid;
/* Compose the SWID generator command */
if (full || !package || !version) if (full || !package || !version)
{ {
snprintf(command, BUF_LEN, "%s swid --entity-name \"%s\" " argv[i++] = "--software-id";
"--regid %s --software-id %s%s%s", argv[i++] = sw_id;
this->generator, this->entity, this->regid, sw_id, if (full)
full ? " --full" : "", pretty ? " --pretty" : ""); {
argv[i++] = "--full";
}
} }
else else
{ {
snprintf(command, BUF_LEN, "%s swid --entity-name \"%s\" " argv[i++] = "--name";
"--regid %s --name %s --version-string %s%s", argv[i++] = package;
this->generator, this->entity, this->regid, package, argv[i++] = "--version-string";
version, pretty ? " --pretty" : ""); argv[i++] = version;
}
if (pretty)
{
argv[i++] = "--pretty";
} }
/* Open a pipe stream for reading the SWID generator output */ process = process_start(argv, NULL, NULL, &out, NULL, TRUE);
file = popen(command, "r"); if (!process)
{
DBG1(DBG_IMC, "failed to run swid_generator command");
return NULL;
}
file = fdopen(out, "r");
if (file) if (file)
{ {
writer = bio_writer_create(tag_buf_len); writer = bio_writer_create(tag_buf_len);
@@ -93,7 +114,8 @@ METHOD(swid_gen_t, generate_tag, char*,
} }
writer->write_data(writer, chunk_create(tag_buf, strlen(tag_buf))); writer->write_data(writer, chunk_create(tag_buf, strlen(tag_buf)));
} }
pclose(file); fclose(file);
swid_tag = writer->extract_buf(writer); swid_tag = writer->extract_buf(writer);
writer->destroy(writer); writer->destroy(writer);
@@ -109,9 +131,9 @@ METHOD(swid_gen_t, generate_tag, char*,
} }
else else
{ {
DBG1(DBG_IMC, "failed to run swid_generator command"); close(out);
} }
process->wait(process, NULL);
return tag; return tag;
} }