Commit 7acfd427 authored by Linus Torvalds's avatar Linus Torvalds

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
parents 571b12dd 1c728719
......@@ -274,6 +274,7 @@ static int xen_blkif_disconnect(struct xen_blkif *blkif)
if (ring->xenblkd) {
kthread_stop(ring->xenblkd);
ring->xenblkd = NULL;
wake_up(&ring->shutdown_wq);
}
......@@ -675,7 +676,8 @@ static int xen_blkbk_probe(struct xenbus_device *dev,
/* setup back pointer */
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");
if (err)
goto fail;
......
......@@ -557,12 +557,14 @@ static int xen_register_credit_watch(struct xenbus_device *dev,
return -ENOMEM;
snprintf(node, maxlen, "%s/rate", dev->nodename);
vif->credit_watch.node = node;
vif->credit_watch.will_handle = NULL;
vif->credit_watch.callback = xen_net_rate_changed;
err = register_xenbus_watch(&vif->credit_watch);
if (err) {
pr_err("Failed to set watcher %s\n", vif->credit_watch.node);
kfree(node);
vif->credit_watch.node = NULL;
vif->credit_watch.will_handle = NULL;
vif->credit_watch.callback = NULL;
}
return err;
......@@ -609,6 +611,7 @@ static int xen_register_mcast_ctrl_watch(struct xenbus_device *dev,
snprintf(node, maxlen, "%s/request-multicast-control",
dev->otherend);
vif->mcast_ctrl_watch.node = node;
vif->mcast_ctrl_watch.will_handle = NULL;
vif->mcast_ctrl_watch.callback = xen_mcast_ctrl_changed;
err = register_xenbus_watch(&vif->mcast_ctrl_watch);
if (err) {
......@@ -616,6 +619,7 @@ static int xen_register_mcast_ctrl_watch(struct xenbus_device *dev,
vif->mcast_ctrl_watch.node);
kfree(node);
vif->mcast_ctrl_watch.node = NULL;
vif->mcast_ctrl_watch.will_handle = NULL;
vif->mcast_ctrl_watch.callback = NULL;
}
return err;
......@@ -820,7 +824,7 @@ static void connect(struct backend_info *be)
xenvif_carrier_on(be->vif);
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,
"%s/%s", dev->nodename, "hotplug-status");
if (!err)
......
......@@ -689,7 +689,7 @@ static int xen_pcibk_xenbus_probe(struct xenbus_device *dev,
/* watch the backend node for backend configuration information */
err = xenbus_watch_path(dev, dev->nodename, &pdev->be_watch,
xen_pcibk_be_watch);
NULL, xen_pcibk_be_watch);
if (err)
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 (*probe)(struct xen_bus_type *bus, const char *type,
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,
const char *token);
struct bus_type bus;
......
......@@ -127,18 +127,22 @@ EXPORT_SYMBOL_GPL(xenbus_strstate);
*/
int xenbus_watch_path(struct xenbus_device *dev, const char *path,
struct xenbus_watch *watch,
bool (*will_handle)(struct xenbus_watch *,
const char *, const char *),
void (*callback)(struct xenbus_watch *,
const char *, const char *))
{
int err;
watch->node = path;
watch->will_handle = will_handle;
watch->callback = callback;
err = register_xenbus_watch(watch);
if (err) {
watch->node = NULL;
watch->will_handle = NULL;
watch->callback = NULL;
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,
struct xenbus_watch *watch,
bool (*will_handle)(struct xenbus_watch *,
const char *, const char *),
void (*callback)(struct xenbus_watch *,
const char *, const char *),
const char *pathfmt, ...)
......@@ -181,7 +187,7 @@ int xenbus_watch_pathfmt(struct xenbus_device *dev,
xenbus_dev_fatal(dev, -ENOMEM, "allocating path for watch");
return -ENOMEM;
}
err = xenbus_watch_path(dev, path, watch, callback);
err = xenbus_watch_path(dev, path, watch, will_handle, callback);
if (err)
kfree(path);
......
......@@ -136,6 +136,7 @@ static int watch_otherend(struct xenbus_device *dev)
container_of(dev->dev.bus, struct xen_bus_type, bus);
return xenbus_watch_pathfmt(dev, &dev->otherend_watch,
bus->otherend_will_handle,
bus->otherend_changed,
"%s/%s", dev->otherend, "state");
}
......
......@@ -180,6 +180,12 @@ static int xenbus_probe_backend(struct xen_bus_type *bus, const char *type,
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,
const char *path, const char *token)
{
......@@ -191,6 +197,7 @@ static struct xen_bus_type xenbus_backend = {
.levels = 3, /* backend/type/<frontend>/<id> */
.get_bus_id = backend_bus_id,
.probe = xenbus_probe_backend,
.otherend_will_handle = frontend_will_handle,
.otherend_changed = frontend_changed,
.bus = {
.name = "xen-backend",
......
......@@ -705,9 +705,13 @@ int xs_watch_msg(struct xs_watch_event *event)
spin_lock(&watches_lock);
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);
list_add_tail(&event->list, &watch_events);
event->handle->nr_pending++;
wake_up(&watch_events_waitq);
spin_unlock(&watch_events_lock);
} else
......@@ -765,6 +769,8 @@ int register_xenbus_watch(struct xenbus_watch *watch)
sprintf(token, "%lX", (long)watch);
watch->nr_pending = 0;
down_read(&xs_watch_rwsem);
spin_lock(&watches_lock);
......@@ -814,11 +820,14 @@ void unregister_xenbus_watch(struct xenbus_watch *watch)
/* Cancel pending watch events. */
spin_lock(&watch_events_lock);
list_for_each_entry_safe(event, tmp, &watch_events, list) {
if (event->handle != watch)
continue;
list_del(&event->list);
kfree(event);
if (watch->nr_pending) {
list_for_each_entry_safe(event, tmp, &watch_events, list) {
if (event->handle != watch)
continue;
list_del(&event->list);
kfree(event);
}
watch->nr_pending = 0;
}
spin_unlock(&watch_events_lock);
......@@ -865,7 +874,6 @@ void xs_suspend_cancel(void)
static int xenwatch_thread(void *unused)
{
struct list_head *ent;
struct xs_watch_event *event;
xenwatch_pid = current->pid;
......@@ -880,13 +888,15 @@ static int xenwatch_thread(void *unused)
mutex_lock(&xenwatch_mutex);
spin_lock(&watch_events_lock);
ent = watch_events.next;
if (ent != &watch_events)
list_del(ent);
event = list_first_entry_or_null(&watch_events,
struct xs_watch_event, list);
if (event) {
list_del(&event->list);
event->handle->nr_pending--;
}
spin_unlock(&watch_events_lock);
if (ent != &watch_events) {
event = list_entry(ent, struct xs_watch_event, list);
if (event) {
event->handle->callback(event->handle, event->path,
event->token);
kfree(event);
......
......@@ -61,6 +61,15 @@ struct xenbus_watch
/* Path being watched. */
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). */
void (*callback)(struct xenbus_watch *,
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,
struct xenbus_watch *watch,
bool (*will_handle)(struct xenbus_watch *,
const char *, const char *),
void (*callback)(struct xenbus_watch *,
const char *, const char *));
__printf(4, 5)
__printf(5, 6)
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 *,
const char *, const char *),
const char *pathfmt, ...);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment