Right now it is possible to undefine an active interface, or destroy inactive. This patch add some checking to these operations to prevent this. Also fix test driver. --- src/interface/netcf_driver.c | 83 ++++++++++++++++++++++++++++++++++++------ src/test/test_driver.c | 5 +++ 2 files changed, 76 insertions(+), 12 deletions(-)
diff --git a/src/interface/netcf_driver.c b/src/interface/netcf_driver.c index 855b5a3..bf590f3 100644 --- a/src/interface/netcf_driver.c +++ b/src/interface/netcf_driver.c @@ -119,6 +119,40 @@ static struct netcf_if *interfaceDriverGetNetcfIF(struct netcf *ncf, virInterfac return iface; } +/* + * interfaceObjIsActive: + * @iface - interface + * + * Caller MUST have driver locked to prevent race condition. + * Returns: + * -1 on error + * 0 on inactive interface + * 1 on active interface + */ +static int ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3) +interfaceObjIsActive(struct interface_driver *driver, + struct netcf_if *iface, + virInterfacePtr ifinfo) +{ + int ret = -1; + unsigned int flags = 0; + + if (ncf_if_status(iface, &flags) < 0) { + const char *errmsg, *details; + int errcode = ncf_error(driver->netcf, &errmsg, &details); + interfaceReportError(netcf_to_vir_err(errcode), + _("failed to get status of interface %s: %s%s%s"), + ifinfo->name, errmsg, details ? " - " : "", + details ? details : ""); + goto cleanup; + } + + ret = flags & NETCF_IFACE_ACTIVE ? 1 : 0; + +cleanup: + return ret; +} + static virDrvOpenStatus interfaceOpenInterface(virConnectPtr conn, virConnectAuthPtr auth ATTRIBUTE_UNUSED, unsigned int flags) @@ -438,6 +472,7 @@ static int interfaceUndefine(virInterfacePtr ifinfo) { struct interface_driver *driver = ifinfo->conn->interfacePrivateData; struct netcf_if *iface = NULL; int ret = -1; + int active; interfaceDriverLock(driver); @@ -447,6 +482,17 @@ static int interfaceUndefine(virInterfacePtr ifinfo) { goto cleanup; } + active = interfaceObjIsActive(driver, iface, ifinfo); + if (active < 0) { + /* helper already reported error */ + goto cleanup; + } else if (active) { + interfaceReportError(VIR_ERR_OPERATION_INVALID, + _("interface %s is active"), + ifinfo->name); + goto cleanup; + } + ret = ncf_if_undefine(iface); if (ret < 0) { const char *errmsg, *details; @@ -470,6 +516,7 @@ static int interfaceCreate(virInterfacePtr ifinfo, struct interface_driver *driver = ifinfo->conn->interfacePrivateData; struct netcf_if *iface = NULL; int ret = -1; + int active; virCheckFlags(0, -1); @@ -481,6 +528,17 @@ static int interfaceCreate(virInterfacePtr ifinfo, goto cleanup; } + active = interfaceObjIsActive(driver, iface, ifinfo); + if (active < 0) { + /* helper already reported error */ + goto cleanup; + } else if (active) { + interfaceReportError(VIR_ERR_OPERATION_INVALID, + _("interface %s is already active"), + ifinfo->name); + goto cleanup; + } + ret = ncf_if_up(iface); if (ret < 0) { const char *errmsg, *details; @@ -504,6 +562,7 @@ static int interfaceDestroy(virInterfacePtr ifinfo, struct interface_driver *driver = ifinfo->conn->interfacePrivateData; struct netcf_if *iface = NULL; int ret = -1; + int active; virCheckFlags(0, -1); @@ -515,6 +574,17 @@ static int interfaceDestroy(virInterfacePtr ifinfo, goto cleanup; } + active = interfaceObjIsActive(driver, iface, ifinfo); + if (active < 0) { + /* helper already reported error */ + goto cleanup; + } else if (!active) { + interfaceReportError(VIR_ERR_OPERATION_INVALID, + _("interface %s is not active"), + ifinfo->name); + goto cleanup; + } + ret = ncf_if_down(iface); if (ret < 0) { const char *errmsg, *details; @@ -536,7 +606,6 @@ static int interfaceIsActive(virInterfacePtr ifinfo) { struct interface_driver *driver = ifinfo->conn->interfacePrivateData; struct netcf_if *iface = NULL; - unsigned int flags = 0; int ret = -1; interfaceDriverLock(driver); @@ -547,17 +616,7 @@ static int interfaceIsActive(virInterfacePtr ifinfo) goto cleanup; } - if (ncf_if_status(iface, &flags) < 0) { - const char *errmsg, *details; - int errcode = ncf_error(driver->netcf, &errmsg, &details); - interfaceReportError(netcf_to_vir_err(errcode), - _("failed to get status of interface %s: %s%s%s"), - ifinfo->name, errmsg, details ? " - " : "", - details ? details : ""); - goto cleanup; - } - - ret = flags & NETCF_IFACE_ACTIVE ? 1 : 0; + ret = interfaceObjIsActive(driver, iface, ifinfo); cleanup: ncf_if_free(iface); diff --git a/src/test/test_driver.c b/src/test/test_driver.c index f3fb320..d165586 100644 --- a/src/test/test_driver.c +++ b/src/test/test_driver.c @@ -3648,6 +3648,11 @@ static int testInterfaceUndefine(virInterfacePtr iface) goto cleanup; } + if (privinterface->active != 0) { + testError(VIR_ERR_OPERATION_INVALID, NULL); + goto cleanup; + } + virInterfaceRemove(&privconn->ifaces, privinterface); ret = 0; -- 1.7.5.rc3 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list