Skip to content

Commit

Permalink
Merge tag 'for-linus-5.11-rc1-tag' of git://git.kernel.org/pub/scm/li…
Browse files Browse the repository at this point in the history
…nux/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
  • Loading branch information
torvalds committed Dec 16, 2020
2 parents 571b12d + 1c72871 commit 7acfd42
Show file tree
Hide file tree
Showing 9 changed files with 62 additions and 17 deletions.
4 changes: 3 additions & 1 deletion drivers/block/xen-blkback/xenbus.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}

Expand Down Expand Up @@ -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;
Expand Down
6 changes: 5 additions & 1 deletion drivers/net/xen-netback/xenbus.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -609,13 +611,15 @@ 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) {
pr_err("Failed to set watcher %s\n",
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;
Expand Down Expand Up @@ -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)
Expand Down
2 changes: 1 addition & 1 deletion drivers/xen/xen-pciback/xenbus.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down
2 changes: 2 additions & 0 deletions drivers/xen/xenbus/xenbus.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
8 changes: 7 additions & 1 deletion drivers/xen/xenbus/xenbus_client.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
Expand All @@ -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, ...)
Expand All @@ -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);
Expand Down
1 change: 1 addition & 0 deletions drivers/xen/xenbus/xenbus_probe.c
Original file line number Diff line number Diff line change
Expand Up @@ -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");
}
Expand Down
7 changes: 7 additions & 0 deletions drivers/xen/xenbus/xenbus_probe_backend.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
{
Expand All @@ -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",
Expand Down
34 changes: 22 additions & 12 deletions drivers/xen/xenbus/xenbus_xs.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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);

Expand Down Expand Up @@ -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;
Expand All @@ -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);
Expand Down
15 changes: 14 additions & 1 deletion include/xen/xenbus.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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, ...);
Expand Down

0 comments on commit 7acfd42

Please sign in to comment.