mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2024-12-22 21:55:25 +00:00
Fix virt-aa-helper when host and os.type arch differ
* src/security/virt-aa-helper.c: get_definition() now calls the new caps_mockup() function which will parse the XML for os.type, os.type.arch and then sets the wordsize. These attributes are needed only to get a valid virCapsPtr for virDomainDefParseString(). The -H and -b options are now removed from virt-aa-helper (they weren't used yet anyway). * tests/virt-aa-helper-test: extend and fixes tests, chmod'ed 755
This commit is contained in:
parent
7023663873
commit
308b85330a
@ -50,6 +50,7 @@ typedef struct {
|
|||||||
virDomainDefPtr def; /* VM definition */
|
virDomainDefPtr def; /* VM definition */
|
||||||
virCapsPtr caps; /* VM capabilities */
|
virCapsPtr caps; /* VM capabilities */
|
||||||
char *hvm; /* type of hypervisor (eg hvm, xen) */
|
char *hvm; /* type of hypervisor (eg hvm, xen) */
|
||||||
|
char *arch; /* machine architecture */
|
||||||
int bits; /* bits in the guest */
|
int bits; /* bits in the guest */
|
||||||
char *newdisk; /* newly added disk */
|
char *newdisk; /* newly added disk */
|
||||||
} vahControl;
|
} vahControl;
|
||||||
@ -65,6 +66,7 @@ vahDeinit(vahControl * ctl)
|
|||||||
virCapabilitiesFree(ctl->caps);
|
virCapabilitiesFree(ctl->caps);
|
||||||
free(ctl->files);
|
free(ctl->files);
|
||||||
free(ctl->hvm);
|
free(ctl->hvm);
|
||||||
|
free(ctl->arch);
|
||||||
free(ctl->newdisk);
|
free(ctl->newdisk);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@ -85,8 +87,6 @@ vah_usage(void)
|
|||||||
" -R | --remove unload profile\n"
|
" -R | --remove unload profile\n"
|
||||||
" -h | --help this help\n"
|
" -h | --help this help\n"
|
||||||
" -u | --uuid <uuid> uuid (profile name)\n"
|
" -u | --uuid <uuid> uuid (profile name)\n"
|
||||||
" -H | --hvm <hvm> hypervisor type\n"
|
|
||||||
" -b | --bits <bits> architecture bits\n"
|
|
||||||
"\n", progname);
|
"\n", progname);
|
||||||
|
|
||||||
fprintf(stdout, "This command is intended to be used by libvirtd "
|
fprintf(stdout, "This command is intended to be used by libvirtd "
|
||||||
@ -551,35 +551,132 @@ valid_path(const char *path, const bool readonly)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Called from SAX on parsing errors in the XML. */
|
||||||
|
static void
|
||||||
|
catchXMLError (void *ctx, const char *msg ATTRIBUTE_UNUSED, ...)
|
||||||
|
{
|
||||||
|
xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
|
||||||
|
|
||||||
|
if (ctxt) {
|
||||||
|
if (virGetLastError() == NULL &&
|
||||||
|
ctxt->lastError.level == XML_ERR_FATAL &&
|
||||||
|
ctxt->lastError.message != NULL) {
|
||||||
|
char *err_str = NULL;
|
||||||
|
if (virAsprintf(&err_str, "XML error at line %d: %s",
|
||||||
|
ctxt->lastError.line,
|
||||||
|
ctxt->lastError.message) == -1)
|
||||||
|
vah_error(NULL, 0, "Could not get XML error");
|
||||||
|
else {
|
||||||
|
vah_error(NULL, 0, err_str);
|
||||||
|
VIR_FREE(err_str);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Parse the xml we received to fill in the following:
|
||||||
|
* ctl->hvm
|
||||||
|
* ctl->arch
|
||||||
|
* ctl->bits
|
||||||
|
*
|
||||||
|
* These are suitable for setting up a virCapsPtr
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
caps_mockup(vahControl * ctl, const char *xmlStr)
|
||||||
|
{
|
||||||
|
int rc = -1;
|
||||||
|
xmlParserCtxtPtr pctxt = NULL;
|
||||||
|
xmlDocPtr xml = NULL;
|
||||||
|
xmlXPathContextPtr ctxt = NULL;
|
||||||
|
xmlNodePtr root;
|
||||||
|
|
||||||
|
/* Set up a parser context so we can catch the details of XML errors. */
|
||||||
|
pctxt = xmlNewParserCtxt ();
|
||||||
|
if (!pctxt || !pctxt->sax)
|
||||||
|
goto cleanup;
|
||||||
|
pctxt->sax->error = catchXMLError;
|
||||||
|
|
||||||
|
xml = xmlCtxtReadDoc (pctxt, BAD_CAST xmlStr, "domain.xml", NULL,
|
||||||
|
XML_PARSE_NOENT | XML_PARSE_NONET |
|
||||||
|
XML_PARSE_NOWARNING);
|
||||||
|
if (!xml) {
|
||||||
|
if (virGetLastError() == NULL)
|
||||||
|
vah_error(NULL, 0, "failed to parse xml document");
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((root = xmlDocGetRootElement(xml)) == NULL) {
|
||||||
|
vah_error(NULL, 0, "missing root element");
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!xmlStrEqual(root->name, BAD_CAST "domain")) {
|
||||||
|
vah_error(NULL, 0, "incorrect root element");
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((ctxt = xmlXPathNewContext(xml)) == NULL) {
|
||||||
|
vah_error(ctl, 0, "could not allocate memory");
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
ctxt->node = root;
|
||||||
|
|
||||||
|
ctl->hvm = virXPathString(NULL, "string(./os/type[1])", ctxt);
|
||||||
|
if (!ctl->hvm || STRNEQ(ctl->hvm, "hvm")) {
|
||||||
|
vah_error(ctl, 0, "os.type is not 'hvm'");
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
ctl->arch = virXPathString(NULL, "string(./os/type[1]/@arch)", ctxt);
|
||||||
|
if (!ctl->arch) {
|
||||||
|
/* The XML we are given should have an arch, but in case it doesn't,
|
||||||
|
* just use the host's arch.
|
||||||
|
*/
|
||||||
|
struct utsname utsname;
|
||||||
|
|
||||||
|
/* Really, this never fails - look at the man-page. */
|
||||||
|
uname (&utsname);
|
||||||
|
if ((ctl->arch = strdup(utsname.machine)) == NULL) {
|
||||||
|
vah_error(ctl, 0, "could not allocate memory");
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (STREQ(ctl->arch, "x86_64"))
|
||||||
|
ctl->bits = 64;
|
||||||
|
else
|
||||||
|
ctl->bits = 32;
|
||||||
|
|
||||||
|
rc = 0;
|
||||||
|
|
||||||
|
cleanup:
|
||||||
|
xmlFreeParserCtxt (pctxt);
|
||||||
|
xmlFreeDoc (xml);
|
||||||
|
xmlXPathFreeContext(ctxt);
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
get_definition(vahControl * ctl, const char *xmlStr)
|
get_definition(vahControl * ctl, const char *xmlStr)
|
||||||
{
|
{
|
||||||
int rc = -1;
|
int rc = -1;
|
||||||
struct utsname utsname;
|
|
||||||
virCapsGuestPtr guest; /* this is freed when caps is freed */
|
virCapsGuestPtr guest; /* this is freed when caps is freed */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* mock up some capabilities. We don't currently use these explicitly,
|
* mock up some capabilities. We don't currently use these explicitly,
|
||||||
* but need them for virDomainDefParseString().
|
* but need them for virDomainDefParseString().
|
||||||
*/
|
*/
|
||||||
|
if (caps_mockup(ctl, xmlStr) != 0)
|
||||||
|
goto exit;
|
||||||
|
|
||||||
/* Really, this never fails - look at the man-page. */
|
if ((ctl->caps = virCapabilitiesNew(ctl->arch, 1, 1)) == NULL) {
|
||||||
uname (&utsname);
|
|
||||||
|
|
||||||
/* set some defaults if not specified */
|
|
||||||
if (!ctl->bits)
|
|
||||||
ctl->bits = 32;
|
|
||||||
if (!ctl->hvm)
|
|
||||||
ctl->hvm = strdup("hvm");
|
|
||||||
|
|
||||||
if ((ctl->caps = virCapabilitiesNew(utsname.machine, 1, 1)) == NULL) {
|
|
||||||
vah_error(ctl, 0, "could not allocate memory");
|
vah_error(ctl, 0, "could not allocate memory");
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((guest = virCapabilitiesAddGuest(ctl->caps,
|
if ((guest = virCapabilitiesAddGuest(ctl->caps,
|
||||||
ctl->hvm,
|
ctl->hvm,
|
||||||
utsname.machine,
|
ctl->arch,
|
||||||
ctl->bits,
|
ctl->bits,
|
||||||
NULL,
|
NULL,
|
||||||
NULL,
|
NULL,
|
||||||
@ -794,11 +891,8 @@ vahParseArgv(vahControl * ctl, int argc, char **argv)
|
|||||||
{"replace", 0, 0, 'r'},
|
{"replace", 0, 0, 'r'},
|
||||||
{"remove", 0, 0, 'R'},
|
{"remove", 0, 0, 'R'},
|
||||||
{"uuid", 1, 0, 'u'},
|
{"uuid", 1, 0, 'u'},
|
||||||
{"hvm", 1, 0, 'H'},
|
|
||||||
{"bits", 1, 0, 'b'},
|
|
||||||
{0, 0, 0, 0}
|
{0, 0, 0, 0}
|
||||||
};
|
};
|
||||||
int bits;
|
|
||||||
|
|
||||||
while ((arg = getopt_long(argc, argv, "acdDhrRH:b:u:f:", opt,
|
while ((arg = getopt_long(argc, argv, "acdDhrRH:b:u:f:", opt,
|
||||||
&idx)) != -1) {
|
&idx)) != -1) {
|
||||||
@ -806,13 +900,6 @@ vahParseArgv(vahControl * ctl, int argc, char **argv)
|
|||||||
case 'a':
|
case 'a':
|
||||||
ctl->cmd = 'a';
|
ctl->cmd = 'a';
|
||||||
break;
|
break;
|
||||||
case 'b':
|
|
||||||
bits = atoi(optarg);
|
|
||||||
if (bits == 32 || bits == 64)
|
|
||||||
ctl->bits = bits;
|
|
||||||
else
|
|
||||||
vah_error(ctl, 1, "invalid bits (should be 32 or 64)");
|
|
||||||
break;
|
|
||||||
case 'c':
|
case 'c':
|
||||||
ctl->cmd = 'c';
|
ctl->cmd = 'c';
|
||||||
break;
|
break;
|
||||||
@ -830,10 +917,6 @@ vahParseArgv(vahControl * ctl, int argc, char **argv)
|
|||||||
vah_usage();
|
vah_usage();
|
||||||
exit(EXIT_SUCCESS);
|
exit(EXIT_SUCCESS);
|
||||||
break;
|
break;
|
||||||
case 'H':
|
|
||||||
if ((ctl->hvm = strdup(optarg)) == NULL)
|
|
||||||
vah_error(ctl, 1, "could not allocate memory for hvm");
|
|
||||||
break;
|
|
||||||
case 'r':
|
case 'r':
|
||||||
ctl->cmd = 'r';
|
ctl->cmd = 'r';
|
||||||
break;
|
break;
|
||||||
|
28
tests/virt-aa-helper-test
Normal file → Executable file
28
tests/virt-aa-helper-test
Normal file → Executable file
@ -155,13 +155,11 @@ testme "1" "no -u with -R" "-R"
|
|||||||
testme "1" "non-existent uuid" "-R -u $nonexistent_uuid"
|
testme "1" "non-existent uuid" "-R -u $nonexistent_uuid"
|
||||||
testme "1" "no -u with -r" "-r"
|
testme "1" "no -u with -r" "-r"
|
||||||
testme "1" "old '-n' option" "-c -n foo -u $valid_uuid" "$test_xml"
|
testme "1" "old '-n' option" "-c -n foo -u $valid_uuid" "$test_xml"
|
||||||
testme "1" "invalid bits" "-c -b 15 -u $valid_uuid" "$test_xml"
|
|
||||||
testme "1" "invalid bits2" "-c -b a -u $valid_uuid" "$test_xml"
|
|
||||||
|
|
||||||
cat "$template_xml" | sed "s,###UUID###,$uuid,g" | sed "s,###DISK###,$bad_disk,g" > "$test_xml"
|
cat "$template_xml" | sed "s,###UUID###,$uuid,g" | sed "s,###DISK###,$bad_disk,g" > "$test_xml"
|
||||||
testme "1" "bad disk" "-c -u $valid_uuid" "$test_xml"
|
testme "1" "bad disk" "-c -u $valid_uuid" "$test_xml"
|
||||||
|
|
||||||
cat "$template_xml" | sed "s,###UUID###,$uuid,g" | sed "s,###DISK###,$bad_disk,g" | sed "s,</devices>,<disk type='file' device='disk'><source file='$disk2'<target dev='hda' bus='ide'/></disk></devices>,g" > "$test_xml"
|
cat "$template_xml" | sed "s,###UUID###,$uuid,g" | sed "s,###DISK###,$bad_disk,g" | sed "s,</devices>,<disk type='file' device='disk'><source file='$disk2'/><target dev='hda' bus='ide'/></disk></devices>,g" > "$test_xml"
|
||||||
testme "1" "bad disk2" "-c -u $valid_uuid" "$test_xml"
|
testme "1" "bad disk2" "-c -u $valid_uuid" "$test_xml"
|
||||||
|
|
||||||
cat "$template_xml" | sed "s,###UUID###,$uuid,g" | sed "s,###DISK###,$disk1,g" | sed "s,</devices>,<devices>,g" > "$test_xml"
|
cat "$template_xml" | sed "s,###UUID###,$uuid,g" | sed "s,###DISK###,$disk1,g" | sed "s,</devices>,<devices>,g" > "$test_xml"
|
||||||
@ -173,14 +171,28 @@ testme "1" "disk in /boot" "-r -u $valid_uuid" "$test_xml"
|
|||||||
cat "$template_xml" | sed "s,###UUID###,$uuid,g" | sed "s,###DISK###,/boot/initrd,g" > "$test_xml"
|
cat "$template_xml" | sed "s,###UUID###,$uuid,g" | sed "s,###DISK###,/boot/initrd,g" > "$test_xml"
|
||||||
testme "1" "-r with invalid -f" "-r -u $valid_uuid -f $bad_disk" "$test_xml"
|
testme "1" "-r with invalid -f" "-r -u $valid_uuid -f $bad_disk" "$test_xml"
|
||||||
|
|
||||||
|
cat "$template_xml" | sed "s,###UUID###,$uuid,g" | sed "s,###DISK###,$disk1</disk>,g" > "$test_xml"
|
||||||
|
testme "1" "-c with malformed xml" "-c -u $valid_uuid" "$test_xml"
|
||||||
|
|
||||||
|
cat "$template_xml" | sed "s,###UUID###,$uuid,g" | sed "s,###DISK###,$disk1,g" | sed "s,<type arch='x86_64' machine='pc'>hvm</type>,,g" > "$test_xml"
|
||||||
|
testme "1" "-c with no os.type" "-c -u $valid_uuid" "$test_xml"
|
||||||
|
|
||||||
|
cat "$template_xml" | sed "s,###UUID###,$uuid,g" | sed "s,###DISK###,$disk1,g" | sed "s,<type arch='x86_64' machine='pc'>hvm</type>,<type>hvm</type>,g" > "$test_xml"
|
||||||
|
testme "1" "-c with no architecture" "-c -u $valid_uuid" "$test_xml"
|
||||||
|
|
||||||
|
cat "$template_xml" | sed "s,###UUID###,$uuid,g" | sed "s,###DISK###,$disk1,g" | sed "s,hvm</type>,hvm_invalid</type>,g" > "$test_xml"
|
||||||
|
testme "1" "-c with invalid hvm" "-c -u $valid_uuid" "$test_xml"
|
||||||
|
|
||||||
|
|
||||||
echo "Expected pass:" >$output
|
echo "Expected pass:" >$output
|
||||||
cat "$template_xml" | sed "s,###UUID###,$uuid,g" | sed "s,###DISK###,$disk1,g" > "$test_xml"
|
cat "$template_xml" | sed "s,###UUID###,$uuid,g" | sed "s,###DISK###,$disk1,g" > "$test_xml"
|
||||||
testme "0" "create" "-c -u $valid_uuid" "$test_xml"
|
testme "0" "create (x86_64)" "-c -u $valid_uuid" "$test_xml"
|
||||||
testme "0" "create with bits (32)" "-c -b 32 -u $valid_uuid" "$test_xml"
|
|
||||||
testme "0" "create with bits (64)" "-c -b 64 -u $valid_uuid" "$test_xml"
|
cat "$template_xml" | sed "s,###UUID###,$uuid,g" | sed "s,###DISK###,$disk1,g" | sed "s,arch='x86_64',arch='i686',g" > "$test_xml"
|
||||||
testme "0" "create with hvm" "-c -H hvm -u $valid_uuid" "$test_xml"
|
testme "0" "create (i686)" "-c -u $valid_uuid" "$test_xml"
|
||||||
testme "0" "create with hvm and bits" "-c -H hvm --bits 32 -u $valid_uuid" "$test_xml"
|
|
||||||
|
cat "$template_xml" | sed "s,###UUID###,$uuid,g" | sed "s,###DISK###,$disk1,g" | sed "s,arch='x86_64',arch='ppc',g" > "$test_xml"
|
||||||
|
testme "0" "create (ppc)" "-c -u $valid_uuid" "$test_xml"
|
||||||
|
|
||||||
cat "$template_xml" | sed "s,###UUID###,$uuid,g" | sed "s,###DISK###,$disk1,g" | sed "s,</disk>,</disk><disk type='file' device='disk'><source file='$disk2'/><target dev='hdb' bus='ide'/></disk>,g" > "$test_xml"
|
cat "$template_xml" | sed "s,###UUID###,$uuid,g" | sed "s,###DISK###,$disk1,g" | sed "s,</disk>,</disk><disk type='file' device='disk'><source file='$disk2'/><target dev='hdb' bus='ide'/></disk>,g" > "$test_xml"
|
||||||
testme "0" "create multiple disks" "-c -u $valid_uuid" "$test_xml"
|
testme "0" "create multiple disks" "-c -u $valid_uuid" "$test_xml"
|
||||||
|
Loading…
Reference in New Issue
Block a user