提交 3afe5d40 编写于 作者: C Cole Robinson

xend: Escape reserved sexpr characters

If we don't escape ' or \ xend can't parse the generated sexpr. This
might over apply the EscapeSexpr routine, but it shouldn't hurt.
上级 0af02cb2
...@@ -24,6 +24,7 @@ virBufferAddChar; ...@@ -24,6 +24,7 @@ virBufferAddChar;
virBufferContentAndReset; virBufferContentAndReset;
virBufferError; virBufferError;
virBufferEscapeString; virBufferEscapeString;
virBufferEscapeSexpr;
virBufferFreeAndReset; virBufferFreeAndReset;
virBufferStrcat; virBufferStrcat;
virBufferURIEncodeString; virBufferURIEncodeString;
......
...@@ -354,6 +354,61 @@ virBufferEscapeString(const virBufferPtr buf, const char *format, const char *st ...@@ -354,6 +354,61 @@ virBufferEscapeString(const virBufferPtr buf, const char *format, const char *st
VIR_FREE(escaped); VIR_FREE(escaped);
} }
/**
* virBufferEscapeSexpr:
* @buf: the buffer to dump
* @format: a printf like format string but with only one %s parameter
* @str: the string argument which need to be escaped
*
* Do a formatted print with a single string to an sexpr buffer. The string
* is escaped to avoid generating a sexpr that xen will choke on. This
* doesn't fully escape the sexpr, just enough for our code to work.
*/
void
virBufferEscapeSexpr(const virBufferPtr buf,
const char *format,
const char *str)
{
int len;
char *escaped, *out;
const char *cur;
if ((format == NULL) || (buf == NULL) || (str == NULL))
return;
if (buf->error)
return;
len = strlen(str);
if (strcspn(str, "\\'") == len) {
virBufferVSprintf(buf, format, str);
return;
}
if (VIR_ALLOC_N(escaped, 2 * len + 1) < 0) {
virBufferNoMemory(buf);
return;
}
cur = str;
out = escaped;
while (*cur != 0) {
switch (*cur) {
case '\\':
case '\'':
*out++ = '\\';
/* fallthrough */
default:
*out++ = *cur;
}
cur++;
}
*out = 0;
virBufferVSprintf(buf, format, escaped);
VIR_FREE(escaped);
}
/** /**
* virBufferURIEncodeString: * virBufferURIEncodeString:
* @buf: the buffer to append to * @buf: the buffer to append to
......
...@@ -45,6 +45,7 @@ void virBufferVSprintf(const virBufferPtr buf, const char *format, ...) ...@@ -45,6 +45,7 @@ void virBufferVSprintf(const virBufferPtr buf, const char *format, ...)
void virBufferStrcat(const virBufferPtr buf, ...) void virBufferStrcat(const virBufferPtr buf, ...)
ATTRIBUTE_SENTINEL; ATTRIBUTE_SENTINEL;
void virBufferEscapeString(const virBufferPtr buf, const char *format, const char *str); void virBufferEscapeString(const virBufferPtr buf, const char *format, const char *str);
void virBufferEscapeSexpr(const virBufferPtr buf, const char *format, const char *str);
void virBufferURIEncodeString (const virBufferPtr buf, const char *str); void virBufferURIEncodeString (const virBufferPtr buf, const char *str);
# define virBufferAddLit(buf_, literal_string_) \ # define virBufferAddLit(buf_, literal_string_) \
......
...@@ -522,6 +522,7 @@ xend_op_ext(virConnectPtr xend, const char *path, const char *key, va_list ap) ...@@ -522,6 +522,7 @@ xend_op_ext(virConnectPtr xend, const char *path, const char *key, va_list ap)
} }
content = virBufferContentAndReset(&buf); content = virBufferContentAndReset(&buf);
DEBUG("xend op: %s\n", content);
ret = http2unix(xend_post(xend, path, content)); ret = http2unix(xend_post(xend, path, content));
VIR_FREE(content); VIR_FREE(content);
...@@ -4605,8 +4606,6 @@ virDomainPtr xenDaemonDomainDefineXML(virConnectPtr conn, const char *xmlDesc) { ...@@ -4605,8 +4606,6 @@ virDomainPtr xenDaemonDomainDefineXML(virConnectPtr conn, const char *xmlDesc) {
goto error; goto error;
} }
DEBUG("Defining w/ sexpr: \n%s", sexpr);
ret = xend_op(conn, "", "op", "new", "config", sexpr, NULL); ret = xend_op(conn, "", "op", "new", "config", sexpr, NULL);
VIR_FREE(sexpr); VIR_FREE(sexpr);
if (ret != 0) { if (ret != 0) {
...@@ -5297,11 +5296,12 @@ xenDaemonFormatSxprChr(virDomainChrDefPtr def, ...@@ -5297,11 +5296,12 @@ xenDaemonFormatSxprChr(virDomainChrDefPtr def,
case VIR_DOMAIN_CHR_TYPE_FILE: case VIR_DOMAIN_CHR_TYPE_FILE:
case VIR_DOMAIN_CHR_TYPE_PIPE: case VIR_DOMAIN_CHR_TYPE_PIPE:
virBufferVSprintf(buf, "%s:%s", type, def->data.file.path); virBufferVSprintf(buf, "%s:", type);
virBufferEscapeSexpr(buf, "%s", def->data.file.path);
break; break;
case VIR_DOMAIN_CHR_TYPE_DEV: case VIR_DOMAIN_CHR_TYPE_DEV:
virBufferVSprintf(buf, "%s", def->data.file.path); virBufferEscapeSexpr(buf, "%s", def->data.file.path);
break; break;
case VIR_DOMAIN_CHR_TYPE_TCP: case VIR_DOMAIN_CHR_TYPE_TCP:
...@@ -5322,9 +5322,10 @@ xenDaemonFormatSxprChr(virDomainChrDefPtr def, ...@@ -5322,9 +5322,10 @@ xenDaemonFormatSxprChr(virDomainChrDefPtr def,
break; break;
case VIR_DOMAIN_CHR_TYPE_UNIX: case VIR_DOMAIN_CHR_TYPE_UNIX:
virBufferVSprintf(buf, "%s:%s%s", type, virBufferVSprintf(buf, "%s:", type);
def->data.nix.path, virBufferEscapeSexpr(buf, "%s", def->data.nix.path);
def->data.nix.listen ? ",server,nowait" : ""); if (def->data.nix.listen)
virBufferAddLit(buf, ",server,nowait");
break; break;
} }
...@@ -5400,39 +5401,42 @@ xenDaemonFormatSxprDisk(virConnectPtr conn ATTRIBUTE_UNUSED, ...@@ -5400,39 +5401,42 @@ xenDaemonFormatSxprDisk(virConnectPtr conn ATTRIBUTE_UNUSED,
if (hvm) { if (hvm) {
/* Xend <= 3.0.2 wants a ioemu: prefix on devices for HVM */ /* Xend <= 3.0.2 wants a ioemu: prefix on devices for HVM */
if (xendConfigVersion == 1) if (xendConfigVersion == 1) {
virBufferVSprintf(buf, "(dev 'ioemu:%s')", def->dst); virBufferEscapeSexpr(buf, "(dev 'ioemu:%s')", def->dst);
else /* But newer does not */ } else {
virBufferVSprintf(buf, "(dev '%s:%s')", def->dst, /* But newer does not */
virBufferEscapeSexpr(buf, "(dev '%s:", def->dst);
virBufferVSprintf(buf, "%s')",
def->device == VIR_DOMAIN_DISK_DEVICE_CDROM ? def->device == VIR_DOMAIN_DISK_DEVICE_CDROM ?
"cdrom" : "disk"); "cdrom" : "disk");
}
} else if (def->device == VIR_DOMAIN_DISK_DEVICE_CDROM) { } else if (def->device == VIR_DOMAIN_DISK_DEVICE_CDROM) {
virBufferVSprintf(buf, "(dev '%s:cdrom')", def->dst); virBufferEscapeSexpr(buf, "(dev '%s:cdrom')", def->dst);
} else { } else {
virBufferVSprintf(buf, "(dev '%s')", def->dst); virBufferEscapeSexpr(buf, "(dev '%s')", def->dst);
} }
if (def->src) { if (def->src) {
if (def->driverName) { if (def->driverName) {
if (STREQ(def->driverName, "tap") || if (STREQ(def->driverName, "tap") ||
STREQ(def->driverName, "tap2")) { STREQ(def->driverName, "tap2")) {
virBufferVSprintf(buf, "(uname '%s:%s:%s')", virBufferEscapeSexpr(buf, "(uname '%s:", def->driverName);
def->driverName, virBufferEscapeSexpr(buf, "%s:",
def->driverType ? def->driverType : "aio", def->driverType ? def->driverType : "aio");
def->src); virBufferEscapeSexpr(buf, "%s')", def->src);
} else { } else {
virBufferVSprintf(buf, "(uname '%s:%s')", virBufferEscapeSexpr(buf, "(uname '%s:", def->driverName);
def->driverName, virBufferEscapeSexpr(buf, "%s')", def->src);
def->src);
} }
} else { } else {
if (def->type == VIR_DOMAIN_DISK_TYPE_FILE) { if (def->type == VIR_DOMAIN_DISK_TYPE_FILE) {
virBufferVSprintf(buf, "(uname 'file:%s')", def->src); virBufferEscapeSexpr(buf, "(uname 'file:%s')", def->src);
} else if (def->type == VIR_DOMAIN_DISK_TYPE_BLOCK) { } else if (def->type == VIR_DOMAIN_DISK_TYPE_BLOCK) {
if (def->src[0] == '/') if (def->src[0] == '/')
virBufferVSprintf(buf, "(uname 'phy:%s')", def->src); virBufferEscapeSexpr(buf, "(uname 'phy:%s')", def->src);
else else
virBufferVSprintf(buf, "(uname 'phy:/dev/%s')", def->src); virBufferEscapeSexpr(buf, "(uname 'phy:/dev/%s')",
def->src);
} else { } else {
virXendError(VIR_ERR_CONFIG_UNSUPPORTED, virXendError(VIR_ERR_CONFIG_UNSUPPORTED,
_("unsupported disk type %s"), _("unsupported disk type %s"),
...@@ -5501,13 +5505,13 @@ xenDaemonFormatSxprNet(virConnectPtr conn, ...@@ -5501,13 +5505,13 @@ xenDaemonFormatSxprNet(virConnectPtr conn,
switch (def->type) { switch (def->type) {
case VIR_DOMAIN_NET_TYPE_BRIDGE: case VIR_DOMAIN_NET_TYPE_BRIDGE:
virBufferVSprintf(buf, "(bridge '%s')", def->data.bridge.brname); virBufferEscapeSexpr(buf, "(bridge '%s')", def->data.bridge.brname);
if (def->data.bridge.script) if (def->data.bridge.script)
script = def->data.bridge.script; script = def->data.bridge.script;
virBufferVSprintf(buf, "(script '%s')", script); virBufferEscapeSexpr(buf, "(script '%s')", script);
if (def->data.bridge.ipaddr != NULL) if (def->data.bridge.ipaddr != NULL)
virBufferVSprintf(buf, "(ip '%s')", def->data.bridge.ipaddr); virBufferEscapeSexpr(buf, "(ip '%s')", def->data.bridge.ipaddr);
break; break;
case VIR_DOMAIN_NET_TYPE_NETWORK: case VIR_DOMAIN_NET_TYPE_NETWORK:
...@@ -5530,17 +5534,18 @@ xenDaemonFormatSxprNet(virConnectPtr conn, ...@@ -5530,17 +5534,18 @@ xenDaemonFormatSxprNet(virConnectPtr conn,
def->data.network.name); def->data.network.name);
return -1; return -1;
} }
virBufferVSprintf(buf, "(bridge '%s')", bridge); virBufferEscapeSexpr(buf, "(bridge '%s')", bridge);
virBufferVSprintf(buf, "(script '%s')", script); virBufferEscapeSexpr(buf, "(script '%s')", script);
VIR_FREE(bridge); VIR_FREE(bridge);
} }
break; break;
case VIR_DOMAIN_NET_TYPE_ETHERNET: case VIR_DOMAIN_NET_TYPE_ETHERNET:
if (def->data.ethernet.script) if (def->data.ethernet.script)
virBufferVSprintf(buf, "(script '%s')", def->data.ethernet.script); virBufferEscapeSexpr(buf, "(script '%s')",
def->data.ethernet.script);
if (def->data.ethernet.ipaddr != NULL) if (def->data.ethernet.ipaddr != NULL)
virBufferVSprintf(buf, "(ip '%s')", def->data.ethernet.ipaddr); virBufferEscapeSexpr(buf, "(ip '%s')", def->data.ethernet.ipaddr);
break; break;
case VIR_DOMAIN_NET_TYPE_USER: case VIR_DOMAIN_NET_TYPE_USER:
...@@ -5555,11 +5560,11 @@ xenDaemonFormatSxprNet(virConnectPtr conn, ...@@ -5555,11 +5560,11 @@ xenDaemonFormatSxprNet(virConnectPtr conn,
if (def->ifname != NULL && if (def->ifname != NULL &&
!STRPREFIX(def->ifname, "vif")) !STRPREFIX(def->ifname, "vif"))
virBufferVSprintf(buf, "(vifname '%s')", def->ifname); virBufferEscapeSexpr(buf, "(vifname '%s')", def->ifname);
if (!hvm) { if (!hvm) {
if (def->model != NULL) if (def->model != NULL)
virBufferVSprintf(buf, "(model '%s')", def->model); virBufferEscapeSexpr(buf, "(model '%s')", def->model);
} }
else if (def->model == NULL) { else if (def->model == NULL) {
/* /*
...@@ -5573,7 +5578,7 @@ xenDaemonFormatSxprNet(virConnectPtr conn, ...@@ -5573,7 +5578,7 @@ xenDaemonFormatSxprNet(virConnectPtr conn,
virBufferAddLit(buf, "(type netfront)"); virBufferAddLit(buf, "(type netfront)");
} }
else { else {
virBufferVSprintf(buf, "(model '%s')", def->model); virBufferEscapeSexpr(buf, "(model '%s')", def->model);
virBufferAddLit(buf, "(type ioemu)"); virBufferAddLit(buf, "(type ioemu)");
} }
...@@ -5680,7 +5685,9 @@ xenDaemonFormatSxprSound(virDomainDefPtr def, ...@@ -5680,7 +5685,9 @@ xenDaemonFormatSxprSound(virDomainDefPtr def,
def->sounds[i]->model); def->sounds[i]->model);
return -1; return -1;
} }
virBufferVSprintf(buf, "%s%s", i ? "," : "", str); if (i)
virBufferAddChar(buf, ',');
virBufferEscapeSexpr(buf, "%s", str);
} }
if (virBufferError(buf)) { if (virBufferError(buf)) {
...@@ -5737,10 +5744,13 @@ xenDaemonFormatSxpr(virConnectPtr conn, ...@@ -5737,10 +5744,13 @@ xenDaemonFormatSxpr(virConnectPtr conn,
virBuffer buf = VIR_BUFFER_INITIALIZER; virBuffer buf = VIR_BUFFER_INITIALIZER;
char uuidstr[VIR_UUID_STRING_BUFLEN]; char uuidstr[VIR_UUID_STRING_BUFLEN];
const char *tmp; const char *tmp;
char *bufout;
int hvm = 0, i; int hvm = 0, i;
DEBUG0("Formatting domain sexpr");
virBufferAddLit(&buf, "(vm "); virBufferAddLit(&buf, "(vm ");
virBufferVSprintf(&buf, "(name '%s')", def->name); virBufferEscapeSexpr(&buf, "(name '%s')", def->name);
virBufferVSprintf(&buf, "(memory %lu)(maxmem %lu)", virBufferVSprintf(&buf, "(memory %lu)(maxmem %lu)",
def->mem.cur_balloon/1024, def->mem.max_balloon/1024); def->mem.cur_balloon/1024, def->mem.max_balloon/1024);
virBufferVSprintf(&buf, "(vcpus %u)", def->maxvcpus); virBufferVSprintf(&buf, "(vcpus %u)", def->maxvcpus);
...@@ -5753,7 +5763,7 @@ xenDaemonFormatSxpr(virConnectPtr conn, ...@@ -5753,7 +5763,7 @@ xenDaemonFormatSxpr(virConnectPtr conn,
char *ranges = virDomainCpuSetFormat(def->cpumask, def->cpumasklen); char *ranges = virDomainCpuSetFormat(def->cpumask, def->cpumasklen);
if (ranges == NULL) if (ranges == NULL)
goto error; goto error;
virBufferVSprintf(&buf, "(cpus '%s')", ranges); virBufferEscapeSexpr(&buf, "(cpus '%s')", ranges);
VIR_FREE(ranges); VIR_FREE(ranges);
} }
...@@ -5761,16 +5771,16 @@ xenDaemonFormatSxpr(virConnectPtr conn, ...@@ -5761,16 +5771,16 @@ xenDaemonFormatSxpr(virConnectPtr conn,
virBufferVSprintf(&buf, "(uuid '%s')", uuidstr); virBufferVSprintf(&buf, "(uuid '%s')", uuidstr);
if (def->description) if (def->description)
virBufferVSprintf(&buf, "(description '%s')", def->description); virBufferEscapeSexpr(&buf, "(description '%s')", def->description);
if (def->os.bootloader) { if (def->os.bootloader) {
if (def->os.bootloader[0]) if (def->os.bootloader[0])
virBufferVSprintf(&buf, "(bootloader '%s')", def->os.bootloader); virBufferEscapeSexpr(&buf, "(bootloader '%s')", def->os.bootloader);
else else
virBufferAddLit(&buf, "(bootloader)"); virBufferAddLit(&buf, "(bootloader)");
if (def->os.bootloaderArgs) if (def->os.bootloaderArgs)
virBufferVSprintf(&buf, "(bootloader_args '%s')", def->os.bootloaderArgs); virBufferEscapeSexpr(&buf, "(bootloader_args '%s')", def->os.bootloaderArgs);
} }
if (!(tmp = virDomainLifecycleTypeToString(def->onPoweroff))) { if (!(tmp = virDomainLifecycleTypeToString(def->onPoweroff))) {
...@@ -5827,20 +5837,20 @@ xenDaemonFormatSxpr(virConnectPtr conn, ...@@ -5827,20 +5837,20 @@ xenDaemonFormatSxpr(virConnectPtr conn,
} }
if (def->os.kernel) if (def->os.kernel)
virBufferVSprintf(&buf, "(kernel '%s')", def->os.kernel); virBufferEscapeSexpr(&buf, "(kernel '%s')", def->os.kernel);
if (def->os.initrd) if (def->os.initrd)
virBufferVSprintf(&buf, "(ramdisk '%s')", def->os.initrd); virBufferEscapeSexpr(&buf, "(ramdisk '%s')", def->os.initrd);
if (def->os.root) if (def->os.root)
virBufferVSprintf(&buf, "(root '%s')", def->os.root); virBufferEscapeSexpr(&buf, "(root '%s')", def->os.root);
if (def->os.cmdline) if (def->os.cmdline)
virBufferVSprintf(&buf, "(args '%s')", def->os.cmdline); virBufferEscapeSexpr(&buf, "(args '%s')", def->os.cmdline);
if (hvm) { if (hvm) {
char bootorder[VIR_DOMAIN_BOOT_LAST+1]; char bootorder[VIR_DOMAIN_BOOT_LAST+1];
if (def->os.kernel) if (def->os.kernel)
virBufferVSprintf(&buf, "(loader '%s')", def->os.loader); virBufferEscapeSexpr(&buf, "(loader '%s')", def->os.loader);
else else
virBufferVSprintf(&buf, "(kernel '%s')", def->os.loader); virBufferEscapeSexpr(&buf, "(kernel '%s')", def->os.loader);
virBufferVSprintf(&buf, "(vcpus %u)", def->maxvcpus); virBufferVSprintf(&buf, "(vcpus %u)", def->maxvcpus);
if (def->vcpus < def->maxvcpus) if (def->vcpus < def->maxvcpus)
...@@ -5883,14 +5893,14 @@ xenDaemonFormatSxpr(virConnectPtr conn, ...@@ -5883,14 +5893,14 @@ xenDaemonFormatSxpr(virConnectPtr conn,
def->disks[i]->src == NULL) def->disks[i]->src == NULL)
break; break;
virBufferVSprintf(&buf, "(cdrom '%s')", virBufferEscapeSexpr(&buf, "(cdrom '%s')",
def->disks[i]->src); def->disks[i]->src);
break; break;
case VIR_DOMAIN_DISK_DEVICE_FLOPPY: case VIR_DOMAIN_DISK_DEVICE_FLOPPY:
/* all xend versions define floppies here */ /* all xend versions define floppies here */
virBufferVSprintf(&buf, "(%s '%s')", def->disks[i]->dst, virBufferEscapeSexpr(&buf, "(%s ", def->disks[i]->dst);
def->disks[i]->src); virBufferEscapeSexpr(&buf, "'%s')", def->disks[i]->src);
break; break;
default: default:
...@@ -5942,7 +5952,7 @@ xenDaemonFormatSxpr(virConnectPtr conn, ...@@ -5942,7 +5952,7 @@ xenDaemonFormatSxpr(virConnectPtr conn,
/* get the device emulation model */ /* get the device emulation model */
if (def->emulator && (hvm || xendConfigVersion >= 3)) if (def->emulator && (hvm || xendConfigVersion >= 3))
virBufferVSprintf(&buf, "(device_model '%s')", def->emulator); virBufferEscapeSexpr(&buf, "(device_model '%s')", def->emulator);
/* PV graphics for xen <= 3.0.4, or HVM graphics for xen <= 3.1.0 */ /* PV graphics for xen <= 3.0.4, or HVM graphics for xen <= 3.1.0 */
...@@ -5986,7 +5996,9 @@ xenDaemonFormatSxpr(virConnectPtr conn, ...@@ -5986,7 +5996,9 @@ xenDaemonFormatSxpr(virConnectPtr conn,
goto error; goto error;
} }
return virBufferContentAndReset(&buf); bufout = virBufferContentAndReset(&buf);
DEBUG("Formatted sexpr: \n%s", bufout);
return bufout;
error: error:
virBufferFreeAndReset(&buf); virBufferFreeAndReset(&buf);
......
(vm (name 'fvtest')(memory 420)(maxmem 420)(vcpus 2)(uuid '596a5d21-71f4-8fb2-e068-e2386a5c413e')(on_poweroff 'destroy')(on_reboot 'destroy')(on_crash 'destroy')(image (hvm (kernel '/var/lib/xen/vmlinuz.2Dn2YT')(ramdisk '/var/lib/xen/initrd.img.0u-Vhq')(args ' method=http://download.fedora.devel.redhat.com/pub/fedora/linux/core/test/5.91/x86_64/os&version="devel" ')(loader '/usr/lib/xen/boot/hvmloader')(vcpus 2)(boot c)(usb 1)(parallel none)(serial pty)(device_model '/usr/lib/xen/bin/qemu-dm')))(device (vbd (dev 'ioemu:xvda')(uname 'file:/root/\'\\some.img')(mode 'w'))))
\ No newline at end of file
<domain type='xen' id='15'>
<name>fvtest</name>
<uuid>596a5d2171f48fb2e068e2386a5c413e</uuid>
<os>
<type>hvm</type>
<kernel>/var/lib/xen/vmlinuz.2Dn2YT</kernel>
<initrd>/var/lib/xen/initrd.img.0u-Vhq</initrd>
<cmdline> method=http://download.fedora.devel.redhat.com/pub/fedora/linux/core/test/5.91/x86_64/os&amp;version="devel" </cmdline>
<loader>/usr/lib/xen/boot/hvmloader</loader>
</os>
<memory>430080</memory>
<vcpu>2</vcpu>
<on_poweroff>destroy</on_poweroff>
<on_reboot>destroy</on_reboot>
<on_crash>destroy</on_crash>
<devices>
<emulator>/usr/lib/xen/bin/qemu-dm</emulator>
<disk type='file' device='disk'>
<source file='/root/&apos;\some.img'/>
<target dev='xvda'/>
</disk>
<console tty='/dev/pts/4'/>
</devices>
</domain>
...@@ -163,6 +163,7 @@ mymain(int argc, char **argv) ...@@ -163,6 +163,7 @@ mymain(int argc, char **argv)
DO_TEST("fv-net-netfront", "fv-net-netfront", "fvtest", 1); DO_TEST("fv-net-netfront", "fv-net-netfront", "fvtest", 1);
DO_TEST("boot-grub", "boot-grub", "fvtest", 1); DO_TEST("boot-grub", "boot-grub", "fvtest", 1);
DO_TEST("escape", "escape", "fvtest", 1);
virCapabilitiesFree(caps); virCapabilitiesFree(caps);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册