1 /* 2 * xenstore_dev.c 3 * 4 * Driver giving user-space access to the kernel's connection to the 5 * XenStore service. 6 * 7 * Copyright (c) 2005, Christian Limpach 8 * Copyright (c) 2005, Rusty Russell, IBM Corporation 9 * 10 * This file may be distributed separately from the Linux kernel, or 11 * incorporated into other software packages, subject to the following license: 12 * 13 * Permission is hereby granted, free of charge, to any person obtaining a copy 14 * of this source file (the "Software"), to deal in the Software without 15 * restriction, including without limitation the rights to use, copy, modify, 16 * merge, publish, distribute, sublicense, and/or sell copies of the Software, 17 * and to permit persons to whom the Software is furnished to do so, subject to 18 * the following conditions: 19 * 20 * The above copyright notice and this permission notice shall be included in 21 * all copies or substantial portions of the Software. 22 * 23 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 24 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 25 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 26 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 27 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 28 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 29 * IN THE SOFTWARE. 30 */ 31 32 33 #include <sys/cdefs.h> 34 __FBSDID("$FreeBSD$"); 35 36 #include <sys/types.h> 37 #include <sys/cdefs.h> 38 #include <sys/errno.h> 39 #include <sys/uio.h> 40 #include <sys/param.h> 41 #include <sys/systm.h> 42 #include <sys/proc.h> 43 #include <sys/kernel.h> 44 #include <sys/malloc.h> 45 #include <sys/conf.h> 46 #include <sys/module.h> 47 #include <sys/selinfo.h> 48 #include <sys/poll.h> 49 50 #include <xen/xen-os.h> 51 52 #include <xen/hypervisor.h> 53 #include <xen/xenstore/xenstorevar.h> 54 #include <xen/xenstore/xenstore_internal.h> 55 56 struct xs_dev_transaction { 57 LIST_ENTRY(xs_dev_transaction) list; 58 struct xs_transaction handle; 59 }; 60 61 struct xs_dev_watch { 62 LIST_ENTRY(xs_dev_watch) list; 63 struct xs_watch watch; 64 char *token; 65 struct xs_dev_data *user; 66 }; 67 68 struct xs_dev_data { 69 /* In-progress transaction. */ 70 LIST_HEAD(, xs_dev_transaction) transactions; 71 72 /* Active watches. */ 73 LIST_HEAD(, xs_dev_watch) watches; 74 75 /* Partial request. */ 76 unsigned int len; 77 union { 78 struct xsd_sockmsg msg; 79 char buffer[PAGE_SIZE]; 80 } u; 81 82 /* Response queue. */ 83 #define MASK_READ_IDX(idx) ((idx)&(PAGE_SIZE-1)) 84 char read_buffer[PAGE_SIZE]; 85 unsigned int read_cons, read_prod; 86 87 /* Serializes writes to the read buffer. */ 88 struct mtx lock; 89 90 /* Polling structure (for reads only ATM). */ 91 struct selinfo ev_rsel; 92 }; 93 94 static void 95 xs_queue_reply(struct xs_dev_data *u, const char *data, unsigned int len) 96 { 97 unsigned int i; 98 99 for (i = 0; i < len; i++, u->read_prod++) 100 u->read_buffer[MASK_READ_IDX(u->read_prod)] = data[i]; 101 102 KASSERT((u->read_prod - u->read_cons) <= sizeof(u->read_buffer), 103 ("xenstore reply too big")); 104 105 wakeup(u); 106 selwakeup(&u->ev_rsel); 107 } 108 109 static const char * 110 xs_dev_error_to_string(int error) 111 { 112 unsigned int i; 113 114 for (i = 0; i < nitems(xsd_errors); i++) 115 if (xsd_errors[i].errnum == error) 116 return (xsd_errors[i].errstring); 117 118 return (NULL); 119 } 120 121 static void 122 xs_dev_return_error(struct xs_dev_data *u, int error, int req_id, int tx_id) 123 { 124 struct xsd_sockmsg msg; 125 const char *payload; 126 127 msg.type = XS_ERROR; 128 msg.req_id = req_id; 129 msg.tx_id = tx_id; 130 payload = NULL; 131 132 133 payload = xs_dev_error_to_string(error); 134 if (payload == NULL) 135 payload = xs_dev_error_to_string(EINVAL); 136 KASSERT(payload != NULL, ("Unable to find string for EINVAL errno")); 137 138 msg.len = strlen(payload) + 1; 139 140 mtx_lock(&u->lock); 141 xs_queue_reply(u, (char *)&msg, sizeof(msg)); 142 xs_queue_reply(u, payload, msg.len); 143 mtx_unlock(&u->lock); 144 } 145 146 static int 147 xs_dev_watch_message_parse_string(const char **p, const char *end, 148 const char **string_r) 149 { 150 const char *nul; 151 152 nul = memchr(*p, 0, end - *p); 153 if (!nul) 154 return (EINVAL); 155 156 *string_r = *p; 157 *p = nul+1; 158 159 return (0); 160 } 161 162 static int 163 xs_dev_watch_message_parse(const struct xsd_sockmsg *msg, const char **path_r, 164 const char **token_r) 165 { 166 const char *p, *end; 167 int error; 168 169 p = (const char *)msg + sizeof(*msg); 170 end = p + msg->len; 171 KASSERT(p <= end, ("payload overflow")); 172 173 error = xs_dev_watch_message_parse_string(&p, end, path_r); 174 if (error) 175 return (error); 176 error = xs_dev_watch_message_parse_string(&p, end, token_r); 177 if (error) 178 return (error); 179 180 return (0); 181 } 182 183 static struct xs_dev_watch * 184 xs_dev_find_watch(struct xs_dev_data *u, const char *token) 185 { 186 struct xs_dev_watch *watch; 187 188 LIST_FOREACH(watch, &u->watches, list) 189 if (strcmp(watch->token, token) == 0) 190 return (watch); 191 192 return (NULL); 193 } 194 195 static void 196 xs_dev_watch_cb(struct xs_watch *watch, const char **vec, unsigned int len) 197 { 198 struct xs_dev_watch *dwatch; 199 struct xsd_sockmsg msg; 200 char *payload; 201 202 dwatch = (struct xs_dev_watch *)watch->callback_data; 203 msg.type = XS_WATCH_EVENT; 204 msg.req_id = msg.tx_id = 0; 205 msg.len = strlen(vec[XS_WATCH_PATH]) + strlen(dwatch->token) + 2; 206 207 payload = malloc(msg.len, M_XENSTORE, M_WAITOK); 208 strcpy(payload, vec[XS_WATCH_PATH]); 209 strcpy(&payload[strlen(vec[XS_WATCH_PATH]) + 1], dwatch->token); 210 mtx_lock(&dwatch->user->lock); 211 xs_queue_reply(dwatch->user, (char *)&msg, sizeof(msg)); 212 xs_queue_reply(dwatch->user, payload, msg.len); 213 mtx_unlock(&dwatch->user->lock); 214 free(payload, M_XENSTORE); 215 } 216 217 static struct xs_dev_transaction * 218 xs_dev_find_transaction(struct xs_dev_data *u, uint32_t tx_id) 219 { 220 struct xs_dev_transaction *trans; 221 222 LIST_FOREACH(trans, &u->transactions, list) 223 if (trans->handle.id == tx_id) 224 return (trans); 225 226 return (NULL); 227 } 228 229 static int 230 xs_dev_read(struct cdev *dev, struct uio *uio, int ioflag) 231 { 232 int error; 233 struct xs_dev_data *u; 234 235 error = devfs_get_cdevpriv((void **)&u); 236 if (error != 0) 237 return (error); 238 239 while (u->read_prod == u->read_cons) { 240 error = tsleep(u, PCATCH, "xsdread", hz/10); 241 if (error && error != EWOULDBLOCK) 242 return (error); 243 } 244 245 while (uio->uio_resid > 0) { 246 if (u->read_cons == u->read_prod) 247 break; 248 error = uiomove(&u->read_buffer[MASK_READ_IDX(u->read_cons)], 249 1, uio); 250 if (error) 251 return (error); 252 u->read_cons++; 253 } 254 return (0); 255 } 256 257 static int 258 xs_dev_write(struct cdev *dev, struct uio *uio, int ioflag) 259 { 260 int error; 261 const char *wpath, *wtoken; 262 struct xs_dev_data *u; 263 struct xs_dev_transaction *trans; 264 struct xs_dev_watch *watch; 265 void *reply; 266 static const char *ok = "OK"; 267 int len = uio->uio_resid; 268 269 error = devfs_get_cdevpriv((void **)&u); 270 if (error != 0) 271 return (error); 272 273 if ((len + u->len) > sizeof(u->u.buffer)) 274 return (EINVAL); 275 276 error = uiomove(u->u.buffer + u->len, len, uio); 277 if (error) 278 return (error); 279 280 u->len += len; 281 if (u->len < (sizeof(u->u.msg) + u->u.msg.len)) 282 return (0); 283 284 switch (u->u.msg.type) { 285 case XS_TRANSACTION_START: 286 case XS_TRANSACTION_END: 287 case XS_DIRECTORY: 288 case XS_READ: 289 case XS_GET_PERMS: 290 case XS_RELEASE: 291 case XS_GET_DOMAIN_PATH: 292 case XS_WRITE: 293 case XS_MKDIR: 294 case XS_RM: 295 case XS_SET_PERMS: 296 /* Check that this transaction id is not hijacked. */ 297 if (u->u.msg.tx_id != 0 && 298 xs_dev_find_transaction(u, u->u.msg.tx_id) == NULL) { 299 error = EINVAL; 300 break; 301 } 302 error = xs_dev_request_and_reply(&u->u.msg, &reply); 303 if (!error) { 304 if (u->u.msg.type == XS_TRANSACTION_START) { 305 trans = malloc(sizeof(*trans), M_XENSTORE, 306 M_WAITOK); 307 trans->handle.id = strtoul(reply, NULL, 0); 308 LIST_INSERT_HEAD(&u->transactions, trans, list); 309 } else if (u->u.msg.type == XS_TRANSACTION_END) { 310 trans = xs_dev_find_transaction(u, 311 u->u.msg.tx_id); 312 KASSERT(trans != NULL, 313 ("Unable to find transaction")); 314 LIST_REMOVE(trans, list); 315 free(trans, M_XENSTORE); 316 } 317 mtx_lock(&u->lock); 318 xs_queue_reply(u, (char *)&u->u.msg, sizeof(u->u.msg)); 319 xs_queue_reply(u, (char *)reply, u->u.msg.len); 320 mtx_unlock(&u->lock); 321 free(reply, M_XENSTORE); 322 } 323 break; 324 case XS_WATCH: 325 u->u.msg.tx_id = 0; 326 error = xs_dev_watch_message_parse(&u->u.msg, &wpath, &wtoken); 327 if (error) 328 break; 329 if (xs_dev_find_watch(u, wtoken) != NULL) { 330 error = EINVAL; 331 break; 332 } 333 334 watch = malloc(sizeof(*watch), M_XENSTORE, M_WAITOK); 335 watch->watch.node = strdup(wpath, M_XENSTORE); 336 watch->watch.callback = xs_dev_watch_cb; 337 watch->watch.callback_data = (uintptr_t)watch; 338 watch->token = strdup(wtoken, M_XENSTORE); 339 watch->user = u; 340 341 error = xs_register_watch(&watch->watch); 342 if (error != 0) { 343 free(watch->token, M_XENSTORE); 344 free(watch->watch.node, M_XENSTORE); 345 free(watch, M_XENSTORE); 346 break; 347 } 348 349 LIST_INSERT_HEAD(&u->watches, watch, list); 350 u->u.msg.len = sizeof(ok); 351 mtx_lock(&u->lock); 352 xs_queue_reply(u, (char *)&u->u.msg, sizeof(u->u.msg)); 353 xs_queue_reply(u, ok, sizeof(ok)); 354 mtx_unlock(&u->lock); 355 break; 356 case XS_UNWATCH: 357 u->u.msg.tx_id = 0; 358 error = xs_dev_watch_message_parse(&u->u.msg, &wpath, &wtoken); 359 if (error) 360 break; 361 watch = xs_dev_find_watch(u, wtoken); 362 if (watch == NULL) { 363 error = EINVAL; 364 break; 365 } 366 367 LIST_REMOVE(watch, list); 368 xs_unregister_watch(&watch->watch); 369 free(watch->watch.node, M_XENSTORE); 370 free(watch->token, M_XENSTORE); 371 free(watch, M_XENSTORE); 372 u->u.msg.len = sizeof(ok); 373 mtx_lock(&u->lock); 374 xs_queue_reply(u, (char *)&u->u.msg, sizeof(u->u.msg)); 375 xs_queue_reply(u, ok, sizeof(ok)); 376 mtx_unlock(&u->lock); 377 break; 378 default: 379 error = EINVAL; 380 break; 381 } 382 383 if (error != 0) 384 xs_dev_return_error(u, error, u->u.msg.req_id, u->u.msg.tx_id); 385 386 /* Reset the write buffer. */ 387 u->len = 0; 388 389 return (0); 390 } 391 392 static int 393 xs_dev_poll(struct cdev *dev, int events, struct thread *td) 394 { 395 struct xs_dev_data *u; 396 int error, mask; 397 398 error = devfs_get_cdevpriv((void **)&u); 399 if (error != 0) 400 return (POLLERR); 401 402 /* we can always write */ 403 mask = events & (POLLOUT | POLLWRNORM); 404 405 if (events & (POLLIN | POLLRDNORM)) { 406 if (u->read_cons != u->read_prod) { 407 mask |= events & (POLLIN | POLLRDNORM); 408 } else { 409 /* Record that someone is waiting */ 410 selrecord(td, &u->ev_rsel); 411 } 412 } 413 414 return (mask); 415 } 416 417 static void 418 xs_dev_dtor(void *arg) 419 { 420 struct xs_dev_data *u = arg; 421 struct xs_dev_transaction *trans, *tmpt; 422 struct xs_dev_watch *watch, *tmpw; 423 424 seldrain(&u->ev_rsel); 425 426 LIST_FOREACH_SAFE(trans, &u->transactions, list, tmpt) { 427 xs_transaction_end(trans->handle, 1); 428 LIST_REMOVE(trans, list); 429 free(trans, M_XENSTORE); 430 } 431 432 LIST_FOREACH_SAFE(watch, &u->watches, list, tmpw) { 433 LIST_REMOVE(watch, list); 434 xs_unregister_watch(&watch->watch); 435 free(watch->watch.node, M_XENSTORE); 436 free(watch->token, M_XENSTORE); 437 free(watch, M_XENSTORE); 438 } 439 mtx_destroy(&u->lock); 440 441 free(u, M_XENSTORE); 442 } 443 444 static int 445 xs_dev_open(struct cdev *dev, int oflags, int devtype, struct thread *td) 446 { 447 struct xs_dev_data *u; 448 int error; 449 450 u = malloc(sizeof(*u), M_XENSTORE, M_WAITOK|M_ZERO); 451 mtx_init(&u->lock, "xsdev_lock", NULL, MTX_DEF); 452 LIST_INIT(&u->transactions); 453 LIST_INIT(&u->watches); 454 error = devfs_set_cdevpriv(u, xs_dev_dtor); 455 if (error != 0) 456 free(u, M_XENSTORE); 457 458 return (error); 459 } 460 461 static struct cdevsw xs_dev_cdevsw = { 462 .d_version = D_VERSION, 463 .d_read = xs_dev_read, 464 .d_write = xs_dev_write, 465 .d_open = xs_dev_open, 466 .d_poll = xs_dev_poll, 467 .d_name = "xs_dev", 468 }; 469 470 /*------------------ Private Device Attachment Functions --------------------*/ 471 /** 472 * \brief Identify instances of this device type in the system. 473 * 474 * \param driver The driver performing this identify action. 475 * \param parent The NewBus parent device for any devices this method adds. 476 */ 477 static void 478 xs_dev_identify(driver_t *driver __unused, device_t parent) 479 { 480 /* 481 * A single device instance for our driver is always present 482 * in a system operating under Xen. 483 */ 484 BUS_ADD_CHILD(parent, 0, driver->name, 0); 485 } 486 487 /** 488 * \brief Probe for the existence of the Xenstore device 489 * 490 * \param dev NewBus device_t for this instance. 491 * 492 * \return Always returns 0 indicating success. 493 */ 494 static int 495 xs_dev_probe(device_t dev) 496 { 497 498 device_set_desc(dev, "Xenstore user-space device"); 499 return (0); 500 } 501 502 /** 503 * \brief Attach the Xenstore device. 504 * 505 * \param dev NewBus device_t for this instance. 506 * 507 * \return On success, 0. Otherwise an errno value indicating the 508 * type of failure. 509 */ 510 static int 511 xs_dev_attach(device_t dev) 512 { 513 struct cdev *xs_cdev; 514 515 xs_cdev = make_dev_credf(MAKEDEV_ETERNAL, &xs_dev_cdevsw, 0, NULL, 516 UID_ROOT, GID_WHEEL, 0400, "xen/xenstore"); 517 if (xs_cdev == NULL) 518 return (EINVAL); 519 520 return (0); 521 } 522 523 /*-------------------- Private Device Attachment Data -----------------------*/ 524 static device_method_t xs_dev_methods[] = { 525 /* Device interface */ 526 DEVMETHOD(device_identify, xs_dev_identify), 527 DEVMETHOD(device_probe, xs_dev_probe), 528 DEVMETHOD(device_attach, xs_dev_attach), 529 530 DEVMETHOD_END 531 }; 532 533 DEFINE_CLASS_0(xs_dev, xs_dev_driver, xs_dev_methods, 0); 534 devclass_t xs_dev_devclass; 535 536 DRIVER_MODULE(xs_dev, xenstore, xs_dev_driver, xs_dev_devclass, 537 NULL, NULL); 538