2010-05-25 11:14:06 +00:00
|
|
|
/*
|
2012-12-12 16:27:01 +00:00
|
|
|
* vircommand.h: Child command execution
|
2010-05-25 11:14:06 +00:00
|
|
|
*
|
2014-07-15 15:07:02 +00:00
|
|
|
* Copyright (C) 2010-2014 Red Hat, Inc.
|
2010-05-25 11:14:06 +00:00
|
|
|
*
|
|
|
|
* This library is free software; you can redistribute it and/or
|
|
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
|
|
* License as published by the Free Software Foundation; either
|
|
|
|
* version 2.1 of the License, or (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This library is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
|
* Lesser General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU Lesser General Public
|
2012-09-20 22:30:55 +00:00
|
|
|
* License along with this library. If not, see
|
2012-07-21 10:06:23 +00:00
|
|
|
* <http://www.gnu.org/licenses/>.
|
2010-05-25 11:14:06 +00:00
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
2019-06-18 16:12:58 +00:00
|
|
|
#pragma once
|
2010-05-25 11:14:06 +00:00
|
|
|
|
2019-06-18 16:12:58 +00:00
|
|
|
#include "internal.h"
|
|
|
|
#include "virbuffer.h"
|
|
|
|
#include "virautoclean.h"
|
2010-05-25 11:14:06 +00:00
|
|
|
|
|
|
|
typedef struct _virCommand virCommand;
|
|
|
|
typedef virCommand *virCommandPtr;
|
|
|
|
|
2011-05-10 18:42:59 +00:00
|
|
|
/* This will execute in the context of the first child
|
2011-07-14 19:47:25 +00:00
|
|
|
* after fork() but before execve(). As such, it is unsafe to
|
|
|
|
* call any function that is not async-signal-safe. */
|
2011-05-10 18:42:59 +00:00
|
|
|
typedef int (*virExecHook)(void *data);
|
|
|
|
|
virFork: simplify semantics
The old semantics of virFork() violates the priciple of good
usability: it requires the caller to check the pid argument
after use, *even when virFork returned -1*, in order to properly
abort a child process that failed setup done immediately after
fork() - that is, the caller must call _exit() in the child.
While uses in virfile.c did this correctly, uses in 'virsh
lxc-enter-namespace' and 'virt-login-shell' would happily return
from the calling function in both the child and the parent,
leading to very confusing results. [Thankfully, I found the
problem by inspection, and can't actually trigger the double
return on error without an LD_PRELOAD library.]
It is much better if the semantics of virFork are impossible
to abuse. Looking at virFork(), the parent could only ever
return -1 with a non-negative pid if it misused pthread_sigmask,
but this never happens. Up until this patch series, the child
could return -1 with non-negative pid if it fails to set up
signals correctly, but we recently fixed that to make the child
call _exit() at that point instead of forcing the caller to do
it. Thus, the return value and contents of the pid argument are
now redundant (a -1 return now happens only for failure to fork,
a child 0 return only happens for a successful 0 pid, and a
parent 0 return only happens for a successful non-zero pid),
so we might as well return the pid directly rather than an
integer of whether it succeeded or failed; this is also good
from the interface design perspective as users are already
familiar with fork() semantics.
One last change in this patch: before returning the pid directly,
I found cases where using virProcessWait unconditionally on a
cleanup path of a virFork's -1 pid return would be nicer if there
were a way to avoid it overwriting an earlier message. While
such paths are a bit harder to come by with my change to a direct
pid return, I decided to keep the virProcessWait change in this
patch.
* src/util/vircommand.h (virFork): Change signature.
* src/util/vircommand.c (virFork): Guarantee that child will only
return on success, to simplify callers. Return pid rather than
status, now that the situations are always the same.
(virExec): Adjust caller, also avoid open-coding process death.
* src/util/virprocess.c (virProcessWait): Tweak semantics when pid
is -1.
(virProcessRunInMountNamespace): Adjust caller.
* src/util/virfile.c (virFileAccessibleAs, virFileOpenForked)
(virDirCreate): Likewise.
* tools/virt-login-shell.c (main): Likewise.
* tools/virsh-domain.c (cmdLxcEnterNamespace): Likewise.
* tests/commandtest.c (test23): Likewise.
Signed-off-by: Eric Blake <eblake@redhat.com>
2013-12-22 00:54:33 +00:00
|
|
|
pid_t virFork(void) ATTRIBUTE_RETURN_CHECK;
|
2011-05-10 18:42:59 +00:00
|
|
|
|
|
|
|
int virRun(const char *const*argv, int *status) ATTRIBUTE_RETURN_CHECK;
|
|
|
|
|
2010-05-25 11:14:06 +00:00
|
|
|
virCommandPtr virCommandNew(const char *binary) ATTRIBUTE_NONNULL(1);
|
|
|
|
|
|
|
|
virCommandPtr virCommandNewArgs(const char *const*args) ATTRIBUTE_NONNULL(1);
|
|
|
|
|
|
|
|
virCommandPtr virCommandNewArgList(const char *binary, ...)
|
|
|
|
ATTRIBUTE_NONNULL(1) ATTRIBUTE_SENTINEL;
|
|
|
|
|
2012-07-31 18:56:06 +00:00
|
|
|
virCommandPtr virCommandNewVAList(const char *binary, va_list list)
|
|
|
|
ATTRIBUTE_NONNULL(1);
|
|
|
|
|
2010-05-25 11:14:06 +00:00
|
|
|
/* All error report from these setup APIs is
|
|
|
|
* delayed until the Run/RunAsync methods
|
|
|
|
*/
|
|
|
|
|
2018-03-21 16:17:54 +00:00
|
|
|
typedef enum {
|
2013-07-11 10:31:56 +00:00
|
|
|
/* Close the FD in the parent */
|
|
|
|
VIR_COMMAND_PASS_FD_CLOSE_PARENT = (1 << 0),
|
2018-03-21 16:17:54 +00:00
|
|
|
} virCommandPassFDFlags;
|
2010-05-25 11:14:06 +00:00
|
|
|
|
2013-07-11 10:31:56 +00:00
|
|
|
void virCommandPassFD(virCommandPtr cmd,
|
|
|
|
int fd,
|
2017-07-12 10:07:17 +00:00
|
|
|
unsigned int flags) ATTRIBUTE_NOINLINE;
|
2010-05-25 11:14:06 +00:00
|
|
|
|
2015-03-05 23:57:06 +00:00
|
|
|
int virCommandPassFDGetFDIndex(virCommandPtr cmd,
|
|
|
|
int fd);
|
|
|
|
|
2010-05-25 11:14:06 +00:00
|
|
|
void virCommandSetPidFile(virCommandPtr cmd,
|
|
|
|
const char *pidfile) ATTRIBUTE_NONNULL(2);
|
|
|
|
|
2017-10-09 19:14:55 +00:00
|
|
|
gid_t virCommandGetGID(virCommandPtr cmd) ATTRIBUTE_NONNULL(1);
|
|
|
|
|
|
|
|
uid_t virCommandGetUID(virCommandPtr cmd) ATTRIBUTE_NONNULL(1);
|
|
|
|
|
2013-01-30 19:47:56 +00:00
|
|
|
void virCommandSetGID(virCommandPtr cmd, gid_t gid);
|
|
|
|
|
|
|
|
void virCommandSetUID(virCommandPtr cmd, uid_t uid);
|
|
|
|
|
2013-04-25 16:10:10 +00:00
|
|
|
void virCommandSetMaxMemLock(virCommandPtr cmd, unsigned long long bytes);
|
|
|
|
void virCommandSetMaxProcesses(virCommandPtr cmd, unsigned int procs);
|
|
|
|
void virCommandSetMaxFiles(virCommandPtr cmd, unsigned int files);
|
2015-03-18 11:14:55 +00:00
|
|
|
void virCommandSetMaxCoreSize(virCommandPtr cmd, unsigned long long bytes);
|
qemu: ensure sane umask for qemu process
Add umask to _virCommand, allow user to set umask to command.
Set umask(002) to qemu process to overwrite the default umask
of 022 set by many distros, so that unix sockets created for
virtio-serial has expected permissions.
Fix problem reported here:
https://sourceware.org/bugzilla/show_bug.cgi?id=13078#c11
https://bugzilla.novell.com/show_bug.cgi?id=888166
To use virtio-serial device, unix socket created for chardev with
default umask(022) has insufficient permissions.
e.g.:
-device virtio-serial \
-chardev socket,path=/tmp/foo,server,nowait,id=foo \
-device virtserialport,chardev=foo,name=org.fedoraproject.port.0
srwxr-xr-x 1 qemu qemu 0 21. Jul 14:19 /tmp/somefile.sock
Other users in the same group (like real user, test engines, etc)
cannot write to this socket.
Signed-off-by: Chunyan Liu <cyliu@suse.com>
Signed-off-by: Eric Blake <eblake@redhat.com>
2014-09-03 06:18:07 +00:00
|
|
|
void virCommandSetUmask(virCommandPtr cmd, int umask);
|
2013-04-25 16:10:10 +00:00
|
|
|
|
2010-05-25 11:14:06 +00:00
|
|
|
void virCommandClearCaps(virCommandPtr cmd);
|
|
|
|
|
|
|
|
void virCommandAllowCap(virCommandPtr cmd,
|
|
|
|
int capability);
|
|
|
|
|
2013-02-01 19:32:37 +00:00
|
|
|
void virCommandSetSELinuxLabel(virCommandPtr cmd,
|
|
|
|
const char *label);
|
|
|
|
|
|
|
|
void virCommandSetAppArmorProfile(virCommandPtr cmd,
|
|
|
|
const char *profile);
|
|
|
|
|
2010-05-25 11:14:06 +00:00
|
|
|
void virCommandDaemonize(virCommandPtr cmd);
|
|
|
|
|
|
|
|
void virCommandNonblockingFDs(virCommandPtr cmd);
|
|
|
|
|
2014-02-20 00:32:19 +00:00
|
|
|
void virCommandRawStatus(virCommandPtr cmd);
|
|
|
|
|
2011-07-14 19:47:25 +00:00
|
|
|
void virCommandAddEnvFormat(virCommandPtr cmd, const char *format, ...)
|
|
|
|
ATTRIBUTE_NONNULL(2) ATTRIBUTE_FMT_PRINTF(2, 3);
|
2011-05-05 20:32:52 +00:00
|
|
|
|
2010-05-25 11:14:06 +00:00
|
|
|
void virCommandAddEnvPair(virCommandPtr cmd,
|
|
|
|
const char *name,
|
|
|
|
const char *value) ATTRIBUTE_NONNULL(2);
|
|
|
|
|
|
|
|
void virCommandAddEnvString(virCommandPtr cmd,
|
|
|
|
const char *str) ATTRIBUTE_NONNULL(2);
|
2010-12-10 18:33:53 +00:00
|
|
|
|
|
|
|
void virCommandAddEnvBuffer(virCommandPtr cmd,
|
|
|
|
virBufferPtr buf);
|
|
|
|
|
2013-10-09 10:03:02 +00:00
|
|
|
void virCommandAddEnvPassBlockSUID(virCommandPtr cmd,
|
|
|
|
const char *name,
|
|
|
|
const char *defvalue) ATTRIBUTE_NONNULL(2);
|
|
|
|
|
|
|
|
void virCommandAddEnvPassAllowSUID(virCommandPtr cmd,
|
|
|
|
const char *name) ATTRIBUTE_NONNULL(2);
|
2011-07-14 19:47:25 +00:00
|
|
|
|
2010-05-25 11:14:06 +00:00
|
|
|
void virCommandAddEnvPassCommon(virCommandPtr cmd);
|
|
|
|
|
2019-03-04 11:47:08 +00:00
|
|
|
void virCommandAddEnvXDG(virCommandPtr cmd, const char *baseDir);
|
|
|
|
|
2010-05-25 11:14:06 +00:00
|
|
|
void virCommandAddArg(virCommandPtr cmd,
|
|
|
|
const char *val) ATTRIBUTE_NONNULL(2);
|
|
|
|
|
2010-12-10 18:33:53 +00:00
|
|
|
void virCommandAddArgBuffer(virCommandPtr cmd,
|
|
|
|
virBufferPtr buf);
|
|
|
|
|
2010-05-25 11:14:06 +00:00
|
|
|
void virCommandAddArgFormat(virCommandPtr cmd,
|
|
|
|
const char *format, ...)
|
|
|
|
ATTRIBUTE_NONNULL(2) ATTRIBUTE_FMT_PRINTF(2, 3);
|
|
|
|
|
|
|
|
void virCommandAddArgPair(virCommandPtr cmd,
|
|
|
|
const char *name,
|
|
|
|
const char *val)
|
|
|
|
ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3);
|
2011-07-14 19:47:25 +00:00
|
|
|
|
2010-05-25 11:14:06 +00:00
|
|
|
void virCommandAddArgSet(virCommandPtr cmd,
|
|
|
|
const char *const*vals) ATTRIBUTE_NONNULL(2);
|
2011-07-14 19:47:25 +00:00
|
|
|
|
2010-05-25 11:14:06 +00:00
|
|
|
void virCommandAddArgList(virCommandPtr cmd,
|
|
|
|
... /* const char *arg, ..., NULL */)
|
|
|
|
ATTRIBUTE_SENTINEL;
|
|
|
|
|
|
|
|
void virCommandSetWorkingDirectory(virCommandPtr cmd,
|
|
|
|
const char *pwd) ATTRIBUTE_NONNULL(2);
|
|
|
|
|
2019-07-25 18:22:06 +00:00
|
|
|
int virCommandSetSendBuffer(virCommandPtr cmd,
|
|
|
|
int fd,
|
|
|
|
unsigned char *buffer, size_t buflen)
|
|
|
|
ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(3);
|
|
|
|
|
2010-05-25 11:14:06 +00:00
|
|
|
void virCommandSetInputBuffer(virCommandPtr cmd,
|
|
|
|
const char *inbuf) ATTRIBUTE_NONNULL(2);
|
2011-07-14 19:47:25 +00:00
|
|
|
|
2010-05-25 11:14:06 +00:00
|
|
|
void virCommandSetOutputBuffer(virCommandPtr cmd,
|
|
|
|
char **outbuf) ATTRIBUTE_NONNULL(2);
|
2011-07-14 19:47:25 +00:00
|
|
|
|
2010-05-25 11:14:06 +00:00
|
|
|
void virCommandSetErrorBuffer(virCommandPtr cmd,
|
|
|
|
char **errbuf) ATTRIBUTE_NONNULL(2);
|
|
|
|
|
|
|
|
void virCommandSetInputFD(virCommandPtr cmd,
|
|
|
|
int infd);
|
2011-07-14 19:47:25 +00:00
|
|
|
|
2010-05-25 11:14:06 +00:00
|
|
|
void virCommandSetOutputFD(virCommandPtr cmd,
|
|
|
|
int *outfd) ATTRIBUTE_NONNULL(2);
|
2011-07-14 19:47:25 +00:00
|
|
|
|
2010-05-25 11:14:06 +00:00
|
|
|
void virCommandSetErrorFD(virCommandPtr cmd,
|
|
|
|
int *errfd) ATTRIBUTE_NONNULL(2);
|
|
|
|
|
|
|
|
void virCommandSetPreExecHook(virCommandPtr cmd,
|
|
|
|
virExecHook hook,
|
|
|
|
void *opaque) ATTRIBUTE_NONNULL(2);
|
|
|
|
|
|
|
|
void virCommandWriteArgLog(virCommandPtr cmd,
|
|
|
|
int logfd);
|
|
|
|
|
qemu: use line breaks in command line args written to log
The QEMU command line arguments are very long and currently all written
on a single line to /var/log/libvirt/qemu/$GUEST.log. This introduces
logic to add line breaks after every env variable and "-" optional
argument, and every positional argument. This will create a clearer log
file, which will in turn present better in bug reports when people cut +
paste from the log into a bug comment.
An example log file entry now looks like this:
2018-12-14 12:57:03.677+0000: starting up libvirt version: 5.0.0, qemu version: 3.0.0qemu-3.0.0-1.fc29, kernel: 4.19.5-300.fc29.x86_64, hostname: localhost.localdomain
LC_ALL=C \
PATH=/usr/local/bin:/usr/local/sbin:/usr/bin:/usr/sbin \
HOME=/home/berrange \
USER=berrange \
LOGNAME=berrange \
QEMU_AUDIO_DRV=none \
/usr/bin/qemu-system-ppc64 \
-name guest=guest,debug-threads=on \
-S \
-object secret,id=masterKey0,format=raw,file=/home/berrange/.config/libvirt/qemu/lib/domain-33-guest/master-key.aes \
-machine pseries-2.10,accel=tcg,usb=off,dump-guest-core=off \
-m 1024 \
-realtime mlock=off \
-smp 1,sockets=1,cores=1,threads=1 \
-uuid c8a74977-ab18-41d0-ae3b-4041c7fffbcd \
-display none \
-no-user-config \
-nodefaults \
-chardev socket,id=charmonitor,fd=23,server,nowait \
-mon chardev=charmonitor,id=monitor,mode=control \
-rtc base=utc \
-no-shutdown \
-boot strict=on \
-device qemu-xhci,id=usb,bus=pci.0,addr=0x1 \
-device virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x2 \
-sandbox on,obsolete=deny,elevateprivileges=deny,spawn=deny,resourcecontrol=deny \
-msg timestamp=on
2018-12-14 12:57:03.730+0000: shutting down, reason=failed
Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
2018-12-14 12:07:08 +00:00
|
|
|
char *virCommandToString(virCommandPtr cmd, bool linebreaks) ATTRIBUTE_RETURN_CHECK;
|
2010-05-25 11:14:06 +00:00
|
|
|
|
2017-10-09 19:14:56 +00:00
|
|
|
int virCommandExec(virCommandPtr cmd, gid_t *groups, int ngroups) ATTRIBUTE_RETURN_CHECK;
|
2011-05-06 14:37:36 +00:00
|
|
|
|
2010-05-25 11:14:06 +00:00
|
|
|
int virCommandRun(virCommandPtr cmd,
|
|
|
|
int *exitstatus) ATTRIBUTE_RETURN_CHECK;
|
|
|
|
|
|
|
|
int virCommandRunAsync(virCommandPtr cmd,
|
|
|
|
pid_t *pid) ATTRIBUTE_RETURN_CHECK;
|
|
|
|
|
|
|
|
int virCommandWait(virCommandPtr cmd,
|
|
|
|
int *exitstatus) ATTRIBUTE_RETURN_CHECK;
|
|
|
|
|
2010-11-22 13:31:35 +00:00
|
|
|
void virCommandRequireHandshake(virCommandPtr cmd);
|
|
|
|
|
|
|
|
int virCommandHandshakeWait(virCommandPtr cmd)
|
|
|
|
ATTRIBUTE_RETURN_CHECK;
|
|
|
|
|
|
|
|
int virCommandHandshakeNotify(virCommandPtr cmd)
|
|
|
|
ATTRIBUTE_RETURN_CHECK;
|
|
|
|
|
2011-03-22 22:22:37 +00:00
|
|
|
void virCommandAbort(virCommandPtr cmd);
|
|
|
|
|
2010-05-25 11:14:06 +00:00
|
|
|
void virCommandFree(virCommandPtr cmd);
|
|
|
|
|
2013-01-16 10:33:17 +00:00
|
|
|
void virCommandDoAsyncIO(virCommandPtr cmd);
|
2014-03-07 11:39:48 +00:00
|
|
|
|
2014-03-18 14:35:01 +00:00
|
|
|
typedef int (*virCommandRunRegexFunc)(char **const groups,
|
|
|
|
void *data);
|
|
|
|
typedef int (*virCommandRunNulFunc)(size_t n_tokens,
|
|
|
|
char **const groups,
|
|
|
|
void *data);
|
|
|
|
|
|
|
|
int virCommandRunRegex(virCommandPtr cmd,
|
|
|
|
int nregex,
|
|
|
|
const char **regex,
|
|
|
|
int *nvars,
|
|
|
|
virCommandRunRegexFunc func,
|
|
|
|
void *data,
|
2016-05-13 16:36:39 +00:00
|
|
|
const char *cmd_to_ignore,
|
|
|
|
int *exitstatus);
|
2014-03-18 14:35:01 +00:00
|
|
|
|
|
|
|
int virCommandRunNul(virCommandPtr cmd,
|
|
|
|
size_t n_columns,
|
|
|
|
virCommandRunNulFunc func,
|
|
|
|
void *data);
|
|
|
|
|
2019-02-07 17:18:52 +00:00
|
|
|
VIR_DEFINE_AUTOPTR_FUNC(virCommand, virCommandFree);
|