xen: branch for v5.11-rc1
-----BEGIN PGP SIGNATURE----- iHUEABYIAB0WIQRTLbB6QfY48x44uB6AXGG7T9hjvgUCX9iqjQAKCRCAXGG7T9hj vvNXAQCNirQi0LTN7LGZvL2eDTg1SDcq7XII8YomcJl8UFBwvQD9HtRo5CwGzVKc PbDqGdvZdl9+VyVyeEvZTv/baaollAo= =MPh4 -----END PGP SIGNATURE----- Merge tag 'for-linus-5.11-rc1-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/xen/tip Pull xen updates from Juergen Gross: "Fixes for security issues just having been disclosed: - a five patch series for fixing of XSA-349 (DoS via resource depletion in Xen dom0) - a patch fixing XSA-350 (access of stale pointer in a Xen dom0)" * tag 'for-linus-5.11-rc1-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/xen/tip: xen-blkback: set ring->xenblkd to NULL after kthread_stop() xenbus/xenbus_backend: Disallow pending watch messages xen/xenbus: Count pending messages for each watch xen/xenbus/xen_bus_type: Support will_handle watch callback xen/xenbus: Add 'will_handle' callback support in xenbus_watch_path() xen/xenbus: Allow watches discard events before queueing
This commit is contained in:
commit
7acfd4274e
@ -274,6 +274,7 @@ static int xen_blkif_disconnect(struct xen_blkif *blkif)
|
|||||||
|
|
||||||
if (ring->xenblkd) {
|
if (ring->xenblkd) {
|
||||||
kthread_stop(ring->xenblkd);
|
kthread_stop(ring->xenblkd);
|
||||||
|
ring->xenblkd = NULL;
|
||||||
wake_up(&ring->shutdown_wq);
|
wake_up(&ring->shutdown_wq);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -675,7 +676,8 @@ static int xen_blkbk_probe(struct xenbus_device *dev,
|
|||||||
/* setup back pointer */
|
/* setup back pointer */
|
||||||
be->blkif->be = be;
|
be->blkif->be = be;
|
||||||
|
|
||||||
err = xenbus_watch_pathfmt(dev, &be->backend_watch, backend_changed,
|
err = xenbus_watch_pathfmt(dev, &be->backend_watch, NULL,
|
||||||
|
backend_changed,
|
||||||
"%s/%s", dev->nodename, "physical-device");
|
"%s/%s", dev->nodename, "physical-device");
|
||||||
if (err)
|
if (err)
|
||||||
goto fail;
|
goto fail;
|
||||||
|
@ -557,12 +557,14 @@ static int xen_register_credit_watch(struct xenbus_device *dev,
|
|||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
snprintf(node, maxlen, "%s/rate", dev->nodename);
|
snprintf(node, maxlen, "%s/rate", dev->nodename);
|
||||||
vif->credit_watch.node = node;
|
vif->credit_watch.node = node;
|
||||||
|
vif->credit_watch.will_handle = NULL;
|
||||||
vif->credit_watch.callback = xen_net_rate_changed;
|
vif->credit_watch.callback = xen_net_rate_changed;
|
||||||
err = register_xenbus_watch(&vif->credit_watch);
|
err = register_xenbus_watch(&vif->credit_watch);
|
||||||
if (err) {
|
if (err) {
|
||||||
pr_err("Failed to set watcher %s\n", vif->credit_watch.node);
|
pr_err("Failed to set watcher %s\n", vif->credit_watch.node);
|
||||||
kfree(node);
|
kfree(node);
|
||||||
vif->credit_watch.node = NULL;
|
vif->credit_watch.node = NULL;
|
||||||
|
vif->credit_watch.will_handle = NULL;
|
||||||
vif->credit_watch.callback = NULL;
|
vif->credit_watch.callback = NULL;
|
||||||
}
|
}
|
||||||
return err;
|
return err;
|
||||||
@ -609,6 +611,7 @@ static int xen_register_mcast_ctrl_watch(struct xenbus_device *dev,
|
|||||||
snprintf(node, maxlen, "%s/request-multicast-control",
|
snprintf(node, maxlen, "%s/request-multicast-control",
|
||||||
dev->otherend);
|
dev->otherend);
|
||||||
vif->mcast_ctrl_watch.node = node;
|
vif->mcast_ctrl_watch.node = node;
|
||||||
|
vif->mcast_ctrl_watch.will_handle = NULL;
|
||||||
vif->mcast_ctrl_watch.callback = xen_mcast_ctrl_changed;
|
vif->mcast_ctrl_watch.callback = xen_mcast_ctrl_changed;
|
||||||
err = register_xenbus_watch(&vif->mcast_ctrl_watch);
|
err = register_xenbus_watch(&vif->mcast_ctrl_watch);
|
||||||
if (err) {
|
if (err) {
|
||||||
@ -616,6 +619,7 @@ static int xen_register_mcast_ctrl_watch(struct xenbus_device *dev,
|
|||||||
vif->mcast_ctrl_watch.node);
|
vif->mcast_ctrl_watch.node);
|
||||||
kfree(node);
|
kfree(node);
|
||||||
vif->mcast_ctrl_watch.node = NULL;
|
vif->mcast_ctrl_watch.node = NULL;
|
||||||
|
vif->mcast_ctrl_watch.will_handle = NULL;
|
||||||
vif->mcast_ctrl_watch.callback = NULL;
|
vif->mcast_ctrl_watch.callback = NULL;
|
||||||
}
|
}
|
||||||
return err;
|
return err;
|
||||||
@ -820,7 +824,7 @@ static void connect(struct backend_info *be)
|
|||||||
xenvif_carrier_on(be->vif);
|
xenvif_carrier_on(be->vif);
|
||||||
|
|
||||||
unregister_hotplug_status_watch(be);
|
unregister_hotplug_status_watch(be);
|
||||||
err = xenbus_watch_pathfmt(dev, &be->hotplug_status_watch,
|
err = xenbus_watch_pathfmt(dev, &be->hotplug_status_watch, NULL,
|
||||||
hotplug_status_changed,
|
hotplug_status_changed,
|
||||||
"%s/%s", dev->nodename, "hotplug-status");
|
"%s/%s", dev->nodename, "hotplug-status");
|
||||||
if (!err)
|
if (!err)
|
||||||
|
@ -689,7 +689,7 @@ static int xen_pcibk_xenbus_probe(struct xenbus_device *dev,
|
|||||||
|
|
||||||
/* watch the backend node for backend configuration information */
|
/* watch the backend node for backend configuration information */
|
||||||
err = xenbus_watch_path(dev, dev->nodename, &pdev->be_watch,
|
err = xenbus_watch_path(dev, dev->nodename, &pdev->be_watch,
|
||||||
xen_pcibk_be_watch);
|
NULL, xen_pcibk_be_watch);
|
||||||
if (err)
|
if (err)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
|
@ -44,6 +44,8 @@ struct xen_bus_type {
|
|||||||
int (*get_bus_id)(char bus_id[XEN_BUS_ID_SIZE], const char *nodename);
|
int (*get_bus_id)(char bus_id[XEN_BUS_ID_SIZE], const char *nodename);
|
||||||
int (*probe)(struct xen_bus_type *bus, const char *type,
|
int (*probe)(struct xen_bus_type *bus, const char *type,
|
||||||
const char *dir);
|
const char *dir);
|
||||||
|
bool (*otherend_will_handle)(struct xenbus_watch *watch,
|
||||||
|
const char *path, const char *token);
|
||||||
void (*otherend_changed)(struct xenbus_watch *watch, const char *path,
|
void (*otherend_changed)(struct xenbus_watch *watch, const char *path,
|
||||||
const char *token);
|
const char *token);
|
||||||
struct bus_type bus;
|
struct bus_type bus;
|
||||||
|
@ -127,18 +127,22 @@ EXPORT_SYMBOL_GPL(xenbus_strstate);
|
|||||||
*/
|
*/
|
||||||
int xenbus_watch_path(struct xenbus_device *dev, const char *path,
|
int xenbus_watch_path(struct xenbus_device *dev, const char *path,
|
||||||
struct xenbus_watch *watch,
|
struct xenbus_watch *watch,
|
||||||
|
bool (*will_handle)(struct xenbus_watch *,
|
||||||
|
const char *, const char *),
|
||||||
void (*callback)(struct xenbus_watch *,
|
void (*callback)(struct xenbus_watch *,
|
||||||
const char *, const char *))
|
const char *, const char *))
|
||||||
{
|
{
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
watch->node = path;
|
watch->node = path;
|
||||||
|
watch->will_handle = will_handle;
|
||||||
watch->callback = callback;
|
watch->callback = callback;
|
||||||
|
|
||||||
err = register_xenbus_watch(watch);
|
err = register_xenbus_watch(watch);
|
||||||
|
|
||||||
if (err) {
|
if (err) {
|
||||||
watch->node = NULL;
|
watch->node = NULL;
|
||||||
|
watch->will_handle = NULL;
|
||||||
watch->callback = NULL;
|
watch->callback = NULL;
|
||||||
xenbus_dev_fatal(dev, err, "adding watch on %s", path);
|
xenbus_dev_fatal(dev, err, "adding watch on %s", path);
|
||||||
}
|
}
|
||||||
@ -165,6 +169,8 @@ EXPORT_SYMBOL_GPL(xenbus_watch_path);
|
|||||||
*/
|
*/
|
||||||
int xenbus_watch_pathfmt(struct xenbus_device *dev,
|
int xenbus_watch_pathfmt(struct xenbus_device *dev,
|
||||||
struct xenbus_watch *watch,
|
struct xenbus_watch *watch,
|
||||||
|
bool (*will_handle)(struct xenbus_watch *,
|
||||||
|
const char *, const char *),
|
||||||
void (*callback)(struct xenbus_watch *,
|
void (*callback)(struct xenbus_watch *,
|
||||||
const char *, const char *),
|
const char *, const char *),
|
||||||
const char *pathfmt, ...)
|
const char *pathfmt, ...)
|
||||||
@ -181,7 +187,7 @@ int xenbus_watch_pathfmt(struct xenbus_device *dev,
|
|||||||
xenbus_dev_fatal(dev, -ENOMEM, "allocating path for watch");
|
xenbus_dev_fatal(dev, -ENOMEM, "allocating path for watch");
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
err = xenbus_watch_path(dev, path, watch, callback);
|
err = xenbus_watch_path(dev, path, watch, will_handle, callback);
|
||||||
|
|
||||||
if (err)
|
if (err)
|
||||||
kfree(path);
|
kfree(path);
|
||||||
|
@ -136,6 +136,7 @@ static int watch_otherend(struct xenbus_device *dev)
|
|||||||
container_of(dev->dev.bus, struct xen_bus_type, bus);
|
container_of(dev->dev.bus, struct xen_bus_type, bus);
|
||||||
|
|
||||||
return xenbus_watch_pathfmt(dev, &dev->otherend_watch,
|
return xenbus_watch_pathfmt(dev, &dev->otherend_watch,
|
||||||
|
bus->otherend_will_handle,
|
||||||
bus->otherend_changed,
|
bus->otherend_changed,
|
||||||
"%s/%s", dev->otherend, "state");
|
"%s/%s", dev->otherend, "state");
|
||||||
}
|
}
|
||||||
|
@ -180,6 +180,12 @@ static int xenbus_probe_backend(struct xen_bus_type *bus, const char *type,
|
|||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool frontend_will_handle(struct xenbus_watch *watch,
|
||||||
|
const char *path, const char *token)
|
||||||
|
{
|
||||||
|
return watch->nr_pending == 0;
|
||||||
|
}
|
||||||
|
|
||||||
static void frontend_changed(struct xenbus_watch *watch,
|
static void frontend_changed(struct xenbus_watch *watch,
|
||||||
const char *path, const char *token)
|
const char *path, const char *token)
|
||||||
{
|
{
|
||||||
@ -191,6 +197,7 @@ static struct xen_bus_type xenbus_backend = {
|
|||||||
.levels = 3, /* backend/type/<frontend>/<id> */
|
.levels = 3, /* backend/type/<frontend>/<id> */
|
||||||
.get_bus_id = backend_bus_id,
|
.get_bus_id = backend_bus_id,
|
||||||
.probe = xenbus_probe_backend,
|
.probe = xenbus_probe_backend,
|
||||||
|
.otherend_will_handle = frontend_will_handle,
|
||||||
.otherend_changed = frontend_changed,
|
.otherend_changed = frontend_changed,
|
||||||
.bus = {
|
.bus = {
|
||||||
.name = "xen-backend",
|
.name = "xen-backend",
|
||||||
|
@ -705,9 +705,13 @@ int xs_watch_msg(struct xs_watch_event *event)
|
|||||||
|
|
||||||
spin_lock(&watches_lock);
|
spin_lock(&watches_lock);
|
||||||
event->handle = find_watch(event->token);
|
event->handle = find_watch(event->token);
|
||||||
if (event->handle != NULL) {
|
if (event->handle != NULL &&
|
||||||
|
(!event->handle->will_handle ||
|
||||||
|
event->handle->will_handle(event->handle,
|
||||||
|
event->path, event->token))) {
|
||||||
spin_lock(&watch_events_lock);
|
spin_lock(&watch_events_lock);
|
||||||
list_add_tail(&event->list, &watch_events);
|
list_add_tail(&event->list, &watch_events);
|
||||||
|
event->handle->nr_pending++;
|
||||||
wake_up(&watch_events_waitq);
|
wake_up(&watch_events_waitq);
|
||||||
spin_unlock(&watch_events_lock);
|
spin_unlock(&watch_events_lock);
|
||||||
} else
|
} else
|
||||||
@ -765,6 +769,8 @@ int register_xenbus_watch(struct xenbus_watch *watch)
|
|||||||
|
|
||||||
sprintf(token, "%lX", (long)watch);
|
sprintf(token, "%lX", (long)watch);
|
||||||
|
|
||||||
|
watch->nr_pending = 0;
|
||||||
|
|
||||||
down_read(&xs_watch_rwsem);
|
down_read(&xs_watch_rwsem);
|
||||||
|
|
||||||
spin_lock(&watches_lock);
|
spin_lock(&watches_lock);
|
||||||
@ -814,11 +820,14 @@ void unregister_xenbus_watch(struct xenbus_watch *watch)
|
|||||||
|
|
||||||
/* Cancel pending watch events. */
|
/* Cancel pending watch events. */
|
||||||
spin_lock(&watch_events_lock);
|
spin_lock(&watch_events_lock);
|
||||||
list_for_each_entry_safe(event, tmp, &watch_events, list) {
|
if (watch->nr_pending) {
|
||||||
if (event->handle != watch)
|
list_for_each_entry_safe(event, tmp, &watch_events, list) {
|
||||||
continue;
|
if (event->handle != watch)
|
||||||
list_del(&event->list);
|
continue;
|
||||||
kfree(event);
|
list_del(&event->list);
|
||||||
|
kfree(event);
|
||||||
|
}
|
||||||
|
watch->nr_pending = 0;
|
||||||
}
|
}
|
||||||
spin_unlock(&watch_events_lock);
|
spin_unlock(&watch_events_lock);
|
||||||
|
|
||||||
@ -865,7 +874,6 @@ void xs_suspend_cancel(void)
|
|||||||
|
|
||||||
static int xenwatch_thread(void *unused)
|
static int xenwatch_thread(void *unused)
|
||||||
{
|
{
|
||||||
struct list_head *ent;
|
|
||||||
struct xs_watch_event *event;
|
struct xs_watch_event *event;
|
||||||
|
|
||||||
xenwatch_pid = current->pid;
|
xenwatch_pid = current->pid;
|
||||||
@ -880,13 +888,15 @@ static int xenwatch_thread(void *unused)
|
|||||||
mutex_lock(&xenwatch_mutex);
|
mutex_lock(&xenwatch_mutex);
|
||||||
|
|
||||||
spin_lock(&watch_events_lock);
|
spin_lock(&watch_events_lock);
|
||||||
ent = watch_events.next;
|
event = list_first_entry_or_null(&watch_events,
|
||||||
if (ent != &watch_events)
|
struct xs_watch_event, list);
|
||||||
list_del(ent);
|
if (event) {
|
||||||
|
list_del(&event->list);
|
||||||
|
event->handle->nr_pending--;
|
||||||
|
}
|
||||||
spin_unlock(&watch_events_lock);
|
spin_unlock(&watch_events_lock);
|
||||||
|
|
||||||
if (ent != &watch_events) {
|
if (event) {
|
||||||
event = list_entry(ent, struct xs_watch_event, list);
|
|
||||||
event->handle->callback(event->handle, event->path,
|
event->handle->callback(event->handle, event->path,
|
||||||
event->token);
|
event->token);
|
||||||
kfree(event);
|
kfree(event);
|
||||||
|
@ -61,6 +61,15 @@ struct xenbus_watch
|
|||||||
/* Path being watched. */
|
/* Path being watched. */
|
||||||
const char *node;
|
const char *node;
|
||||||
|
|
||||||
|
unsigned int nr_pending;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Called just before enqueing new event while a spinlock is held.
|
||||||
|
* The event will be discarded if this callback returns false.
|
||||||
|
*/
|
||||||
|
bool (*will_handle)(struct xenbus_watch *,
|
||||||
|
const char *path, const char *token);
|
||||||
|
|
||||||
/* Callback (executed in a process context with no locks held). */
|
/* Callback (executed in a process context with no locks held). */
|
||||||
void (*callback)(struct xenbus_watch *,
|
void (*callback)(struct xenbus_watch *,
|
||||||
const char *path, const char *token);
|
const char *path, const char *token);
|
||||||
@ -197,10 +206,14 @@ void xenbus_probe(struct work_struct *);
|
|||||||
|
|
||||||
int xenbus_watch_path(struct xenbus_device *dev, const char *path,
|
int xenbus_watch_path(struct xenbus_device *dev, const char *path,
|
||||||
struct xenbus_watch *watch,
|
struct xenbus_watch *watch,
|
||||||
|
bool (*will_handle)(struct xenbus_watch *,
|
||||||
|
const char *, const char *),
|
||||||
void (*callback)(struct xenbus_watch *,
|
void (*callback)(struct xenbus_watch *,
|
||||||
const char *, const char *));
|
const char *, const char *));
|
||||||
__printf(4, 5)
|
__printf(5, 6)
|
||||||
int xenbus_watch_pathfmt(struct xenbus_device *dev, struct xenbus_watch *watch,
|
int xenbus_watch_pathfmt(struct xenbus_device *dev, struct xenbus_watch *watch,
|
||||||
|
bool (*will_handle)(struct xenbus_watch *,
|
||||||
|
const char *, const char *),
|
||||||
void (*callback)(struct xenbus_watch *,
|
void (*callback)(struct xenbus_watch *,
|
||||||
const char *, const char *),
|
const char *, const char *),
|
||||||
const char *pathfmt, ...);
|
const char *pathfmt, ...);
|
||||||
|
Loading…
Reference in New Issue
Block a user