mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2025-01-11 15:27:47 +00:00
nwfilter: avoid failure with noexec /tmp
If /tmp is mounted with the noexec flag (common on security-conscious systems), then nwfilter will fail to initialize, because we cannot run any temporary script via virRun("/tmp/script"); but we _can_ use "/bin/sh /tmp/script". For that matter, using /tmp risks collisions with other unrelated programs; we already have /var/run/libvirt as a dedicated temporary directory for use by libvirt. * src/nwfilter/nwfilter_ebiptables_driver.c (ebiptablesWriteToTempFile): Use internal directory, not /tmp; drop attempts to make script executable; and detect close error. (ebiptablesExecCLI): Switch to virCommand, and invoke the shell to read the script, rather than requiring an executable script.
This commit is contained in:
parent
0eee075dc7
commit
bd6083c9ba
@ -40,6 +40,7 @@
|
|||||||
#include "nwfilter_ebiptables_driver.h"
|
#include "nwfilter_ebiptables_driver.h"
|
||||||
#include "virfile.h"
|
#include "virfile.h"
|
||||||
#include "command.h"
|
#include "command.h"
|
||||||
|
#include "configmake.h"
|
||||||
|
|
||||||
|
|
||||||
#define VIR_FROM_THIS VIR_FROM_NWFILTER
|
#define VIR_FROM_THIS VIR_FROM_NWFILTER
|
||||||
@ -2482,29 +2483,17 @@ ebiptablesDisplayRuleInstance(virConnectPtr conn ATTRIBUTE_UNUSED,
|
|||||||
* NULL in case of error with the error reported.
|
* NULL in case of error with the error reported.
|
||||||
*
|
*
|
||||||
* Write the string into a temporary file and return the name of
|
* Write the string into a temporary file and return the name of
|
||||||
* the temporary file. The string is assumed to contain executable
|
* the temporary file. The file can then be read as a /bin/sh script.
|
||||||
* commands. A line '#!/bin/sh' will automatically be written
|
* No '#!/bin/sh' header is needed, since the file will be read and not
|
||||||
* as the first line in the file. The permissions of the file are
|
* directly executed.
|
||||||
* set so that the file can be run as an executable script.
|
|
||||||
*/
|
*/
|
||||||
static char *
|
static char *
|
||||||
ebiptablesWriteToTempFile(const char *string) {
|
ebiptablesWriteToTempFile(const char *string) {
|
||||||
char filename[] = "/tmp/virtdXXXXXX";
|
char filename[] = LOCALSTATEDIR "/run/libvirt/nwfilt-XXXXXX";
|
||||||
int len;
|
size_t len;
|
||||||
char *filnam;
|
char *filnam;
|
||||||
virBuffer buf = VIR_BUFFER_INITIALIZER;
|
|
||||||
char *header;
|
|
||||||
size_t written;
|
size_t written;
|
||||||
|
|
||||||
virBufferAddLit(&buf, "#!/bin/sh\n");
|
|
||||||
|
|
||||||
if (virBufferError(&buf)) {
|
|
||||||
virBufferFreeAndReset(&buf);
|
|
||||||
virReportOOMError();
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
header = virBufferContentAndReset(&buf);
|
|
||||||
|
|
||||||
int fd = mkstemp(filename);
|
int fd = mkstemp(filename);
|
||||||
|
|
||||||
if (fd < 0) {
|
if (fd < 0) {
|
||||||
@ -2514,22 +2503,6 @@ ebiptablesWriteToTempFile(const char *string) {
|
|||||||
goto err_exit;
|
goto err_exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fchmod(fd, S_IXUSR| S_IRUSR | S_IWUSR) < 0) {
|
|
||||||
virNWFilterReportError(VIR_ERR_INTERNAL_ERROR,
|
|
||||||
"%s",
|
|
||||||
_("cannot change permissions on temp. file"));
|
|
||||||
goto err_exit;
|
|
||||||
}
|
|
||||||
|
|
||||||
len = strlen(header);
|
|
||||||
written = safewrite(fd, header, len);
|
|
||||||
if (written != len) {
|
|
||||||
virNWFilterReportError(VIR_ERR_INTERNAL_ERROR,
|
|
||||||
"%s",
|
|
||||||
_("cannot write string to file"));
|
|
||||||
goto err_exit;
|
|
||||||
}
|
|
||||||
|
|
||||||
len = strlen(string);
|
len = strlen(string);
|
||||||
written = safewrite(fd, string, len);
|
written = safewrite(fd, string, len);
|
||||||
if (written != len) {
|
if (written != len) {
|
||||||
@ -2539,18 +2512,22 @@ ebiptablesWriteToTempFile(const char *string) {
|
|||||||
goto err_exit;
|
goto err_exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (VIR_CLOSE(fd) < 0) {
|
||||||
|
virNWFilterReportError(VIR_ERR_INTERNAL_ERROR,
|
||||||
|
"%s",
|
||||||
|
_("cannot write string to file"));
|
||||||
|
goto err_exit;
|
||||||
|
}
|
||||||
|
|
||||||
filnam = strdup(filename);
|
filnam = strdup(filename);
|
||||||
if (!filnam) {
|
if (!filnam) {
|
||||||
virReportOOMError();
|
virReportOOMError();
|
||||||
goto err_exit;
|
goto err_exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
VIR_FREE(header);
|
|
||||||
VIR_FORCE_CLOSE(fd);
|
|
||||||
return filnam;
|
return filnam;
|
||||||
|
|
||||||
err_exit:
|
err_exit:
|
||||||
VIR_FREE(header);
|
|
||||||
VIR_FORCE_CLOSE(fd);
|
VIR_FORCE_CLOSE(fd);
|
||||||
unlink(filename);
|
unlink(filename);
|
||||||
return NULL;
|
return NULL;
|
||||||
@ -2564,7 +2541,7 @@ err_exit:
|
|||||||
* @status: Pointer to an integer for returning the WEXITSTATUS of the
|
* @status: Pointer to an integer for returning the WEXITSTATUS of the
|
||||||
* commands executed via the script the was run.
|
* commands executed via the script the was run.
|
||||||
*
|
*
|
||||||
* Returns 0 in case of success, != 0 in case of an error. The returned
|
* Returns 0 in case of success, < 0 in case of an error. The returned
|
||||||
* value is NOT the result of running the commands inside the shell
|
* value is NOT the result of running the commands inside the shell
|
||||||
* script.
|
* script.
|
||||||
*
|
*
|
||||||
@ -2577,53 +2554,42 @@ ebiptablesExecCLI(virBufferPtr buf,
|
|||||||
{
|
{
|
||||||
char *cmds;
|
char *cmds;
|
||||||
char *filename;
|
char *filename;
|
||||||
int rc;
|
int rc = -1;
|
||||||
const char *argv[] = {NULL, NULL};
|
virCommandPtr cmd;
|
||||||
|
|
||||||
if (virBufferError(buf)) {
|
if (virBufferError(buf)) {
|
||||||
virReportOOMError();
|
virReportOOMError();
|
||||||
virBufferFreeAndReset(buf);
|
virBufferFreeAndReset(buf);
|
||||||
return 1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
*status = 0;
|
*status = 0;
|
||||||
|
|
||||||
cmds = virBufferContentAndReset(buf);
|
cmds = virBufferContentAndReset(buf);
|
||||||
|
|
||||||
VIR_DEBUG("%s", NULLSTR(cmds));
|
VIR_DEBUG("%s", NULLSTR(cmds));
|
||||||
|
|
||||||
if (!cmds)
|
if (!cmds)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
filename = ebiptablesWriteToTempFile(cmds);
|
filename = ebiptablesWriteToTempFile(cmds);
|
||||||
VIR_FREE(cmds);
|
|
||||||
|
|
||||||
if (!filename)
|
if (!filename)
|
||||||
return 1;
|
goto cleanup;
|
||||||
|
|
||||||
argv[0] = filename;
|
cmd = virCommandNew("/bin/sh");
|
||||||
|
virCommandAddArg(cmd, filename);
|
||||||
|
|
||||||
virMutexLock(&execCLIMutex);
|
virMutexLock(&execCLIMutex);
|
||||||
|
|
||||||
rc = virRun(argv, status);
|
rc = virCommandRun(cmd, status);
|
||||||
|
|
||||||
virMutexUnlock(&execCLIMutex);
|
virMutexUnlock(&execCLIMutex);
|
||||||
|
|
||||||
if (rc == 0) {
|
|
||||||
if (WIFEXITED(*status)) {
|
|
||||||
*status = WEXITSTATUS(*status);
|
|
||||||
} else {
|
|
||||||
rc = -1;
|
|
||||||
*status = 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
VIR_DEBUG("rc = %d, status = %d", rc, *status);
|
|
||||||
|
|
||||||
unlink(filename);
|
unlink(filename);
|
||||||
|
|
||||||
VIR_FREE(filename);
|
VIR_FREE(filename);
|
||||||
|
|
||||||
|
cleanup:
|
||||||
|
VIR_FREE(cmds);
|
||||||
|
virCommandFree(cmd);
|
||||||
|
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user