Skip to content

Commit 7acfd42

Browse files
committed
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
2 parents 571b12d + 1c72871 commit 7acfd42

File tree

9 files changed

+62
-17
lines changed

9 files changed

+62
-17
lines changed

drivers/block/xen-blkback/xenbus.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -274,6 +274,7 @@ static int xen_blkif_disconnect(struct xen_blkif *blkif)
274274

275275
if (ring->xenblkd) {
276276
kthread_stop(ring->xenblkd);
277+
ring->xenblkd = NULL;
277278
wake_up(&ring->shutdown_wq);
278279
}
279280

@@ -675,7 +676,8 @@ static int xen_blkbk_probe(struct xenbus_device *dev,
675676
/* setup back pointer */
676677
be->blkif->be = be;
677678

678-
err = xenbus_watch_pathfmt(dev, &be->backend_watch, backend_changed,
679+
err = xenbus_watch_pathfmt(dev, &be->backend_watch, NULL,
680+
backend_changed,
679681
"%s/%s", dev->nodename, "physical-device");
680682
if (err)
681683
goto fail;

drivers/net/xen-netback/xenbus.c

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -557,12 +557,14 @@ static int xen_register_credit_watch(struct xenbus_device *dev,
557557
return -ENOMEM;
558558
snprintf(node, maxlen, "%s/rate", dev->nodename);
559559
vif->credit_watch.node = node;
560+
vif->credit_watch.will_handle = NULL;
560561
vif->credit_watch.callback = xen_net_rate_changed;
561562
err = register_xenbus_watch(&vif->credit_watch);
562563
if (err) {
563564
pr_err("Failed to set watcher %s\n", vif->credit_watch.node);
564565
kfree(node);
565566
vif->credit_watch.node = NULL;
567+
vif->credit_watch.will_handle = NULL;
566568
vif->credit_watch.callback = NULL;
567569
}
568570
return err;
@@ -609,13 +611,15 @@ static int xen_register_mcast_ctrl_watch(struct xenbus_device *dev,
609611
snprintf(node, maxlen, "%s/request-multicast-control",
610612
dev->otherend);
611613
vif->mcast_ctrl_watch.node = node;
614+
vif->mcast_ctrl_watch.will_handle = NULL;
612615
vif->mcast_ctrl_watch.callback = xen_mcast_ctrl_changed;
613616
err = register_xenbus_watch(&vif->mcast_ctrl_watch);
614617
if (err) {
615618
pr_err("Failed to set watcher %s\n",
616619
vif->mcast_ctrl_watch.node);
617620
kfree(node);
618621
vif->mcast_ctrl_watch.node = NULL;
622+
vif->mcast_ctrl_watch.will_handle = NULL;
619623
vif->mcast_ctrl_watch.callback = NULL;
620624
}
621625
return err;
@@ -820,7 +824,7 @@ static void connect(struct backend_info *be)
820824
xenvif_carrier_on(be->vif);
821825

822826
unregister_hotplug_status_watch(be);
823-
err = xenbus_watch_pathfmt(dev, &be->hotplug_status_watch,
827+
err = xenbus_watch_pathfmt(dev, &be->hotplug_status_watch, NULL,
824828
hotplug_status_changed,
825829
"%s/%s", dev->nodename, "hotplug-status");
826830
if (!err)

drivers/xen/xen-pciback/xenbus.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -689,7 +689,7 @@ static int xen_pcibk_xenbus_probe(struct xenbus_device *dev,
689689

690690
/* watch the backend node for backend configuration information */
691691
err = xenbus_watch_path(dev, dev->nodename, &pdev->be_watch,
692-
xen_pcibk_be_watch);
692+
NULL, xen_pcibk_be_watch);
693693
if (err)
694694
goto out;
695695

drivers/xen/xenbus/xenbus.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,8 @@ struct xen_bus_type {
4444
int (*get_bus_id)(char bus_id[XEN_BUS_ID_SIZE], const char *nodename);
4545
int (*probe)(struct xen_bus_type *bus, const char *type,
4646
const char *dir);
47+
bool (*otherend_will_handle)(struct xenbus_watch *watch,
48+
const char *path, const char *token);
4749
void (*otherend_changed)(struct xenbus_watch *watch, const char *path,
4850
const char *token);
4951
struct bus_type bus;

drivers/xen/xenbus/xenbus_client.c

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -127,18 +127,22 @@ EXPORT_SYMBOL_GPL(xenbus_strstate);
127127
*/
128128
int xenbus_watch_path(struct xenbus_device *dev, const char *path,
129129
struct xenbus_watch *watch,
130+
bool (*will_handle)(struct xenbus_watch *,
131+
const char *, const char *),
130132
void (*callback)(struct xenbus_watch *,
131133
const char *, const char *))
132134
{
133135
int err;
134136

135137
watch->node = path;
138+
watch->will_handle = will_handle;
136139
watch->callback = callback;
137140

138141
err = register_xenbus_watch(watch);
139142

140143
if (err) {
141144
watch->node = NULL;
145+
watch->will_handle = NULL;
142146
watch->callback = NULL;
143147
xenbus_dev_fatal(dev, err, "adding watch on %s", path);
144148
}
@@ -165,6 +169,8 @@ EXPORT_SYMBOL_GPL(xenbus_watch_path);
165169
*/
166170
int xenbus_watch_pathfmt(struct xenbus_device *dev,
167171
struct xenbus_watch *watch,
172+
bool (*will_handle)(struct xenbus_watch *,
173+
const char *, const char *),
168174
void (*callback)(struct xenbus_watch *,
169175
const char *, const char *),
170176
const char *pathfmt, ...)
@@ -181,7 +187,7 @@ int xenbus_watch_pathfmt(struct xenbus_device *dev,
181187
xenbus_dev_fatal(dev, -ENOMEM, "allocating path for watch");
182188
return -ENOMEM;
183189
}
184-
err = xenbus_watch_path(dev, path, watch, callback);
190+
err = xenbus_watch_path(dev, path, watch, will_handle, callback);
185191

186192
if (err)
187193
kfree(path);

drivers/xen/xenbus/xenbus_probe.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,7 @@ static int watch_otherend(struct xenbus_device *dev)
136136
container_of(dev->dev.bus, struct xen_bus_type, bus);
137137

138138
return xenbus_watch_pathfmt(dev, &dev->otherend_watch,
139+
bus->otherend_will_handle,
139140
bus->otherend_changed,
140141
"%s/%s", dev->otherend, "state");
141142
}

drivers/xen/xenbus/xenbus_probe_backend.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -180,6 +180,12 @@ static int xenbus_probe_backend(struct xen_bus_type *bus, const char *type,
180180
return err;
181181
}
182182

183+
static bool frontend_will_handle(struct xenbus_watch *watch,
184+
const char *path, const char *token)
185+
{
186+
return watch->nr_pending == 0;
187+
}
188+
183189
static void frontend_changed(struct xenbus_watch *watch,
184190
const char *path, const char *token)
185191
{
@@ -191,6 +197,7 @@ static struct xen_bus_type xenbus_backend = {
191197
.levels = 3, /* backend/type/<frontend>/<id> */
192198
.get_bus_id = backend_bus_id,
193199
.probe = xenbus_probe_backend,
200+
.otherend_will_handle = frontend_will_handle,
194201
.otherend_changed = frontend_changed,
195202
.bus = {
196203
.name = "xen-backend",

drivers/xen/xenbus/xenbus_xs.c

Lines changed: 22 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -705,9 +705,13 @@ int xs_watch_msg(struct xs_watch_event *event)
705705

706706
spin_lock(&watches_lock);
707707
event->handle = find_watch(event->token);
708-
if (event->handle != NULL) {
708+
if (event->handle != NULL &&
709+
(!event->handle->will_handle ||
710+
event->handle->will_handle(event->handle,
711+
event->path, event->token))) {
709712
spin_lock(&watch_events_lock);
710713
list_add_tail(&event->list, &watch_events);
714+
event->handle->nr_pending++;
711715
wake_up(&watch_events_waitq);
712716
spin_unlock(&watch_events_lock);
713717
} else
@@ -765,6 +769,8 @@ int register_xenbus_watch(struct xenbus_watch *watch)
765769

766770
sprintf(token, "%lX", (long)watch);
767771

772+
watch->nr_pending = 0;
773+
768774
down_read(&xs_watch_rwsem);
769775

770776
spin_lock(&watches_lock);
@@ -814,11 +820,14 @@ void unregister_xenbus_watch(struct xenbus_watch *watch)
814820

815821
/* Cancel pending watch events. */
816822
spin_lock(&watch_events_lock);
817-
list_for_each_entry_safe(event, tmp, &watch_events, list) {
818-
if (event->handle != watch)
819-
continue;
820-
list_del(&event->list);
821-
kfree(event);
823+
if (watch->nr_pending) {
824+
list_for_each_entry_safe(event, tmp, &watch_events, list) {
825+
if (event->handle != watch)
826+
continue;
827+
list_del(&event->list);
828+
kfree(event);
829+
}
830+
watch->nr_pending = 0;
822831
}
823832
spin_unlock(&watch_events_lock);
824833

@@ -865,7 +874,6 @@ void xs_suspend_cancel(void)
865874

866875
static int xenwatch_thread(void *unused)
867876
{
868-
struct list_head *ent;
869877
struct xs_watch_event *event;
870878

871879
xenwatch_pid = current->pid;
@@ -880,13 +888,15 @@ static int xenwatch_thread(void *unused)
880888
mutex_lock(&xenwatch_mutex);
881889

882890
spin_lock(&watch_events_lock);
883-
ent = watch_events.next;
884-
if (ent != &watch_events)
885-
list_del(ent);
891+
event = list_first_entry_or_null(&watch_events,
892+
struct xs_watch_event, list);
893+
if (event) {
894+
list_del(&event->list);
895+
event->handle->nr_pending--;
896+
}
886897
spin_unlock(&watch_events_lock);
887898

888-
if (ent != &watch_events) {
889-
event = list_entry(ent, struct xs_watch_event, list);
899+
if (event) {
890900
event->handle->callback(event->handle, event->path,
891901
event->token);
892902
kfree(event);

include/xen/xenbus.h

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,15 @@ struct xenbus_watch
6161
/* Path being watched. */
6262
const char *node;
6363

64+
unsigned int nr_pending;
65+
66+
/*
67+
* Called just before enqueing new event while a spinlock is held.
68+
* The event will be discarded if this callback returns false.
69+
*/
70+
bool (*will_handle)(struct xenbus_watch *,
71+
const char *path, const char *token);
72+
6473
/* Callback (executed in a process context with no locks held). */
6574
void (*callback)(struct xenbus_watch *,
6675
const char *path, const char *token);
@@ -197,10 +206,14 @@ void xenbus_probe(struct work_struct *);
197206

198207
int xenbus_watch_path(struct xenbus_device *dev, const char *path,
199208
struct xenbus_watch *watch,
209+
bool (*will_handle)(struct xenbus_watch *,
210+
const char *, const char *),
200211
void (*callback)(struct xenbus_watch *,
201212
const char *, const char *));
202-
__printf(4, 5)
213+
__printf(5, 6)
203214
int xenbus_watch_pathfmt(struct xenbus_device *dev, struct xenbus_watch *watch,
215+
bool (*will_handle)(struct xenbus_watch *,
216+
const char *, const char *),
204217
void (*callback)(struct xenbus_watch *,
205218
const char *, const char *),
206219
const char *pathfmt, ...);

0 commit comments

Comments
 (0)