[libvirt] [PATCH 1/2] nwfilter: avoid failure with noexec /tmp
Stefan Berger
stefanb at linux.vnet.ibm.com
Wed Nov 9 18:38:53 UTC 2011
On 11/09/2011 12:46 PM, Eric Blake wrote:
> 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.
> ---
> src/nwfilter/nwfilter_ebiptables_driver.c | 76 ++++++++---------------------
> 1 files changed, 21 insertions(+), 55 deletions(-)
>
> diff --git a/src/nwfilter/nwfilter_ebiptables_driver.c b/src/nwfilter/nwfilter_ebiptables_driver.c
> index f87cfa1..c9c194c 100644
> --- a/src/nwfilter/nwfilter_ebiptables_driver.c
> +++ b/src/nwfilter/nwfilter_ebiptables_driver.c
> @@ -40,6 +40,7 @@
> #include "nwfilter_ebiptables_driver.h"
> #include "virfile.h"
> #include "command.h"
> +#include "configmake.h"
>
>
> #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.
> *
> * Write the string into a temporary file and return the name of
> - * the temporary file. The string is assumed to contain executable
> - * commands. A line '#!/bin/sh' will automatically be written
> - * as the first line in the file. The permissions of the file are
> - * set so that the file can be run as an executable script.
> + * the temporary file. The file can then be read as a /bin/sh script.
> + * No '#!/bin/sh' header is needed, since the file will be read and not
> + * directly executed.
> */
> static char *
> ebiptablesWriteToTempFile(const char *string) {
> - char filename[] = "/tmp/virtdXXXXXX";
> - int len;
> + char filename[] = LOCALSTATEDIR "/run/libvirt/nwfilt-XXXXXX";
> + size_t len;
> char *filnam;
> - virBuffer buf = VIR_BUFFER_INITIALIZER;
> - char *header;
> size_t written;
>
> - virBufferAddLit(&buf, "#!/bin/sh\n");
> -
> - if (virBufferError(&buf)) {
> - virBufferFreeAndReset(&buf);
> - virReportOOMError();
> - return NULL;
> - }
> - header = virBufferContentAndReset(&buf);
> -
> int fd = mkstemp(filename);
>
> if (fd< 0) {
> @@ -2514,15 +2503,8 @@ ebiptablesWriteToTempFile(const char *string) {
> 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);
> + len = strlen(string);
> + written = safewrite(fd, string, len);
> if (written != len) {
> virNWFilterReportError(VIR_ERR_INTERNAL_ERROR,
> "%s",
> @@ -2530,9 +2512,7 @@ ebiptablesWriteToTempFile(const char *string) {
> goto err_exit;
> }
>
> - len = strlen(string);
> - written = safewrite(fd, string, len);
> - if (written != len) {
> + if (VIR_CLOSE(fd)< 0) {
> virNWFilterReportError(VIR_ERR_INTERNAL_ERROR,
> "%s",
> _("cannot write string to file"));
> @@ -2545,12 +2525,9 @@ ebiptablesWriteToTempFile(const char *string) {
> goto err_exit;
> }
>
> - VIR_FREE(header);
> - VIR_FORCE_CLOSE(fd);
> return filnam;
>
> err_exit:
> - VIR_FREE(header);
> VIR_FORCE_CLOSE(fd);
> unlink(filename);
> return NULL;
> @@ -2564,7 +2541,7 @@ err_exit:
> * @status: Pointer to an integer for returning the WEXITSTATUS of the
> * 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
> * script.
> *
> @@ -2577,53 +2554,42 @@ ebiptablesExecCLI(virBufferPtr buf,
> {
> char *cmds;
> char *filename;
> - int rc;
> - const char *argv[] = {NULL, NULL};
> + int rc = -1;
> + virCommandPtr cmd;
>
> if (virBufferError(buf)) {
> virReportOOMError();
> virBufferFreeAndReset(buf);
> - return 1;
> + return -1;
> }
>
> *status = 0;
>
> cmds = virBufferContentAndReset(buf);
> -
> VIR_DEBUG("%s", NULLSTR(cmds));
> -
> if (!cmds)
> return 0;
>
> filename = ebiptablesWriteToTempFile(cmds);
> - VIR_FREE(cmds);
> -
> if (!filename)
> - return 1;
> + goto cleanup;
>
> - argv[0] = filename;
> + cmd = virCommandNew("/bin/sh");
> + virCommandAddArg(cmd, filename);
>
> virMutexLock(&execCLIMutex);
>
> - rc = virRun(argv, status);
> + rc = virCommandRun(cmd, status);
>
> 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);
> -
> VIR_FREE(filename);
>
> +cleanup:
> + VIR_FREE(cmds);
> + virCommandFree(cmd);
> +
> return rc;
> }
>
ACK, still works with this one ...
More information about the libvir-list
mailing list