1 /* 2 * net/9p/protocol.c 3 * 4 * 9P Protocol Support Code 5 * 6 * Copyright (C) 2008 by Eric Van Hensbergen <ericvh@gmail.com> 7 * 8 * Base on code from Anthony Liguori <aliguori@us.ibm.com> 9 * Copyright (C) 2008 by IBM, Corp. 10 * 11 * This program is free software; you can redistribute it and/or modify 12 * it under the terms of the GNU General Public License version 2 13 * as published by the Free Software Foundation. 14 * 15 * This program is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU General Public License for more details. 19 * 20 * You should have received a copy of the GNU General Public License 21 * along with this program; if not, write to: 22 * Free Software Foundation 23 * 51 Franklin Street, Fifth Floor 24 * Boston, MA 02111-1301 USA 25 * 26 */ 27 28 #include <linux/module.h> 29 #include <linux/errno.h> 30 #include <linux/kernel.h> 31 #include <linux/uaccess.h> 32 #include <linux/slab.h> 33 #include <linux/sched.h> 34 #include <linux/stddef.h> 35 #include <linux/types.h> 36 #include <linux/uio.h> 37 #include <net/9p/9p.h> 38 #include <net/9p/client.h> 39 #include "protocol.h" 40 41 #include <trace/events/9p.h> 42 43 static int 44 p9pdu_writef(struct p9_fcall *pdu, int proto_version, const char *fmt, ...); 45 46 void p9stat_free(struct p9_wstat *stbuf) 47 { 48 kfree(stbuf->name); 49 kfree(stbuf->uid); 50 kfree(stbuf->gid); 51 kfree(stbuf->muid); 52 kfree(stbuf->extension); 53 } 54 EXPORT_SYMBOL(p9stat_free); 55 56 size_t pdu_read(struct p9_fcall *pdu, void *data, size_t size) 57 { 58 size_t len = min(pdu->size - pdu->offset, size); 59 memcpy(data, &pdu->sdata[pdu->offset], len); 60 pdu->offset += len; 61 return size - len; 62 } 63 64 static size_t pdu_write(struct p9_fcall *pdu, const void *data, size_t size) 65 { 66 size_t len = min(pdu->capacity - pdu->size, size); 67 memcpy(&pdu->sdata[pdu->size], data, len); 68 pdu->size += len; 69 return size - len; 70 } 71 72 static size_t 73 pdu_write_u(struct p9_fcall *pdu, struct iov_iter *from, size_t size) 74 { 75 size_t len = min(pdu->capacity - pdu->size, size); 76 struct iov_iter i = *from; 77 if (!copy_from_iter_full(&pdu->sdata[pdu->size], len, &i)) 78 len = 0; 79 80 pdu->size += len; 81 return size - len; 82 } 83 84 /* 85 b - int8_t 86 w - int16_t 87 d - int32_t 88 q - int64_t 89 s - string 90 u - numeric uid 91 g - numeric gid 92 S - stat 93 Q - qid 94 D - data blob (int32_t size followed by void *, results are not freed) 95 T - array of strings (int16_t count, followed by strings) 96 R - array of qids (int16_t count, followed by qids) 97 A - stat for 9p2000.L (p9_stat_dotl) 98 ? - if optional = 1, continue parsing 99 */ 100 101 static int 102 p9pdu_vreadf(struct p9_fcall *pdu, int proto_version, const char *fmt, 103 va_list ap) 104 { 105 const char *ptr; 106 int errcode = 0; 107 108 for (ptr = fmt; *ptr; ptr++) { 109 switch (*ptr) { 110 case 'b':{ 111 int8_t *val = va_arg(ap, int8_t *); 112 if (pdu_read(pdu, val, sizeof(*val))) { 113 errcode = -EFAULT; 114 break; 115 } 116 } 117 break; 118 case 'w':{ 119 int16_t *val = va_arg(ap, int16_t *); 120 __le16 le_val; 121 if (pdu_read(pdu, &le_val, sizeof(le_val))) { 122 errcode = -EFAULT; 123 break; 124 } 125 *val = le16_to_cpu(le_val); 126 } 127 break; 128 case 'd':{ 129 int32_t *val = va_arg(ap, int32_t *); 130 __le32 le_val; 131 if (pdu_read(pdu, &le_val, sizeof(le_val))) { 132 errcode = -EFAULT; 133 break; 134 } 135 *val = le32_to_cpu(le_val); 136 } 137 break; 138 case 'q':{ 139 int64_t *val = va_arg(ap, int64_t *); 140 __le64 le_val; 141 if (pdu_read(pdu, &le_val, sizeof(le_val))) { 142 errcode = -EFAULT; 143 break; 144 } 145 *val = le64_to_cpu(le_val); 146 } 147 break; 148 case 's':{ 149 char **sptr = va_arg(ap, char **); 150 uint16_t len; 151 152 errcode = p9pdu_readf(pdu, proto_version, 153 "w", &len); 154 if (errcode) 155 break; 156 157 *sptr = kmalloc(len + 1, GFP_NOFS); 158 if (*sptr == NULL) { 159 errcode = -ENOMEM; 160 break; 161 } 162 if (pdu_read(pdu, *sptr, len)) { 163 errcode = -EFAULT; 164 kfree(*sptr); 165 *sptr = NULL; 166 } else 167 (*sptr)[len] = 0; 168 } 169 break; 170 case 'u': { 171 kuid_t *uid = va_arg(ap, kuid_t *); 172 __le32 le_val; 173 if (pdu_read(pdu, &le_val, sizeof(le_val))) { 174 errcode = -EFAULT; 175 break; 176 } 177 *uid = make_kuid(&init_user_ns, 178 le32_to_cpu(le_val)); 179 } break; 180 case 'g': { 181 kgid_t *gid = va_arg(ap, kgid_t *); 182 __le32 le_val; 183 if (pdu_read(pdu, &le_val, sizeof(le_val))) { 184 errcode = -EFAULT; 185 break; 186 } 187 *gid = make_kgid(&init_user_ns, 188 le32_to_cpu(le_val)); 189 } break; 190 case 'Q':{ 191 struct p9_qid *qid = 192 va_arg(ap, struct p9_qid *); 193 194 errcode = p9pdu_readf(pdu, proto_version, "bdq", 195 &qid->type, &qid->version, 196 &qid->path); 197 } 198 break; 199 case 'S':{ 200 struct p9_wstat *stbuf = 201 va_arg(ap, struct p9_wstat *); 202 203 memset(stbuf, 0, sizeof(struct p9_wstat)); 204 stbuf->n_uid = stbuf->n_muid = INVALID_UID; 205 stbuf->n_gid = INVALID_GID; 206 207 errcode = 208 p9pdu_readf(pdu, proto_version, 209 "wwdQdddqssss?sugu", 210 &stbuf->size, &stbuf->type, 211 &stbuf->dev, &stbuf->qid, 212 &stbuf->mode, &stbuf->atime, 213 &stbuf->mtime, &stbuf->length, 214 &stbuf->name, &stbuf->uid, 215 &stbuf->gid, &stbuf->muid, 216 &stbuf->extension, 217 &stbuf->n_uid, &stbuf->n_gid, 218 &stbuf->n_muid); 219 if (errcode) 220 p9stat_free(stbuf); 221 } 222 break; 223 case 'D':{ 224 uint32_t *count = va_arg(ap, uint32_t *); 225 void **data = va_arg(ap, void **); 226 227 errcode = 228 p9pdu_readf(pdu, proto_version, "d", count); 229 if (!errcode) { 230 *count = 231 min_t(uint32_t, *count, 232 pdu->size - pdu->offset); 233 *data = &pdu->sdata[pdu->offset]; 234 } 235 } 236 break; 237 case 'T':{ 238 uint16_t *nwname = va_arg(ap, uint16_t *); 239 char ***wnames = va_arg(ap, char ***); 240 241 errcode = p9pdu_readf(pdu, proto_version, 242 "w", nwname); 243 if (!errcode) { 244 *wnames = 245 kmalloc_array(*nwname, 246 sizeof(char *), 247 GFP_NOFS); 248 if (!*wnames) 249 errcode = -ENOMEM; 250 } 251 252 if (!errcode) { 253 int i; 254 255 for (i = 0; i < *nwname; i++) { 256 errcode = 257 p9pdu_readf(pdu, 258 proto_version, 259 "s", 260 &(*wnames)[i]); 261 if (errcode) 262 break; 263 } 264 } 265 266 if (errcode) { 267 if (*wnames) { 268 int i; 269 270 for (i = 0; i < *nwname; i++) 271 kfree((*wnames)[i]); 272 } 273 kfree(*wnames); 274 *wnames = NULL; 275 } 276 } 277 break; 278 case 'R':{ 279 uint16_t *nwqid = va_arg(ap, uint16_t *); 280 struct p9_qid **wqids = 281 va_arg(ap, struct p9_qid **); 282 283 *wqids = NULL; 284 285 errcode = 286 p9pdu_readf(pdu, proto_version, "w", nwqid); 287 if (!errcode) { 288 *wqids = 289 kmalloc_array(*nwqid, 290 sizeof(struct p9_qid), 291 GFP_NOFS); 292 if (*wqids == NULL) 293 errcode = -ENOMEM; 294 } 295 296 if (!errcode) { 297 int i; 298 299 for (i = 0; i < *nwqid; i++) { 300 errcode = 301 p9pdu_readf(pdu, 302 proto_version, 303 "Q", 304 &(*wqids)[i]); 305 if (errcode) 306 break; 307 } 308 } 309 310 if (errcode) { 311 kfree(*wqids); 312 *wqids = NULL; 313 } 314 } 315 break; 316 case 'A': { 317 struct p9_stat_dotl *stbuf = 318 va_arg(ap, struct p9_stat_dotl *); 319 320 memset(stbuf, 0, sizeof(struct p9_stat_dotl)); 321 errcode = 322 p9pdu_readf(pdu, proto_version, 323 "qQdugqqqqqqqqqqqqqqq", 324 &stbuf->st_result_mask, 325 &stbuf->qid, 326 &stbuf->st_mode, 327 &stbuf->st_uid, &stbuf->st_gid, 328 &stbuf->st_nlink, 329 &stbuf->st_rdev, &stbuf->st_size, 330 &stbuf->st_blksize, &stbuf->st_blocks, 331 &stbuf->st_atime_sec, 332 &stbuf->st_atime_nsec, 333 &stbuf->st_mtime_sec, 334 &stbuf->st_mtime_nsec, 335 &stbuf->st_ctime_sec, 336 &stbuf->st_ctime_nsec, 337 &stbuf->st_btime_sec, 338 &stbuf->st_btime_nsec, 339 &stbuf->st_gen, 340 &stbuf->st_data_version); 341 } 342 break; 343 case '?': 344 if ((proto_version != p9_proto_2000u) && 345 (proto_version != p9_proto_2000L)) 346 return 0; 347 break; 348 default: 349 BUG(); 350 break; 351 } 352 353 if (errcode) 354 break; 355 } 356 357 return errcode; 358 } 359 360 int 361 p9pdu_vwritef(struct p9_fcall *pdu, int proto_version, const char *fmt, 362 va_list ap) 363 { 364 const char *ptr; 365 int errcode = 0; 366 367 for (ptr = fmt; *ptr; ptr++) { 368 switch (*ptr) { 369 case 'b':{ 370 int8_t val = va_arg(ap, int); 371 if (pdu_write(pdu, &val, sizeof(val))) 372 errcode = -EFAULT; 373 } 374 break; 375 case 'w':{ 376 __le16 val = cpu_to_le16(va_arg(ap, int)); 377 if (pdu_write(pdu, &val, sizeof(val))) 378 errcode = -EFAULT; 379 } 380 break; 381 case 'd':{ 382 __le32 val = cpu_to_le32(va_arg(ap, int32_t)); 383 if (pdu_write(pdu, &val, sizeof(val))) 384 errcode = -EFAULT; 385 } 386 break; 387 case 'q':{ 388 __le64 val = cpu_to_le64(va_arg(ap, int64_t)); 389 if (pdu_write(pdu, &val, sizeof(val))) 390 errcode = -EFAULT; 391 } 392 break; 393 case 's':{ 394 const char *sptr = va_arg(ap, const char *); 395 uint16_t len = 0; 396 if (sptr) 397 len = min_t(size_t, strlen(sptr), 398 USHRT_MAX); 399 400 errcode = p9pdu_writef(pdu, proto_version, 401 "w", len); 402 if (!errcode && pdu_write(pdu, sptr, len)) 403 errcode = -EFAULT; 404 } 405 break; 406 case 'u': { 407 kuid_t uid = va_arg(ap, kuid_t); 408 __le32 val = cpu_to_le32( 409 from_kuid(&init_user_ns, uid)); 410 if (pdu_write(pdu, &val, sizeof(val))) 411 errcode = -EFAULT; 412 } break; 413 case 'g': { 414 kgid_t gid = va_arg(ap, kgid_t); 415 __le32 val = cpu_to_le32( 416 from_kgid(&init_user_ns, gid)); 417 if (pdu_write(pdu, &val, sizeof(val))) 418 errcode = -EFAULT; 419 } break; 420 case 'Q':{ 421 const struct p9_qid *qid = 422 va_arg(ap, const struct p9_qid *); 423 errcode = 424 p9pdu_writef(pdu, proto_version, "bdq", 425 qid->type, qid->version, 426 qid->path); 427 } break; 428 case 'S':{ 429 const struct p9_wstat *stbuf = 430 va_arg(ap, const struct p9_wstat *); 431 errcode = 432 p9pdu_writef(pdu, proto_version, 433 "wwdQdddqssss?sugu", 434 stbuf->size, stbuf->type, 435 stbuf->dev, &stbuf->qid, 436 stbuf->mode, stbuf->atime, 437 stbuf->mtime, stbuf->length, 438 stbuf->name, stbuf->uid, 439 stbuf->gid, stbuf->muid, 440 stbuf->extension, stbuf->n_uid, 441 stbuf->n_gid, stbuf->n_muid); 442 } break; 443 case 'V':{ 444 uint32_t count = va_arg(ap, uint32_t); 445 struct iov_iter *from = 446 va_arg(ap, struct iov_iter *); 447 errcode = p9pdu_writef(pdu, proto_version, "d", 448 count); 449 if (!errcode && pdu_write_u(pdu, from, count)) 450 errcode = -EFAULT; 451 } 452 break; 453 case 'T':{ 454 uint16_t nwname = va_arg(ap, int); 455 const char **wnames = va_arg(ap, const char **); 456 457 errcode = p9pdu_writef(pdu, proto_version, "w", 458 nwname); 459 if (!errcode) { 460 int i; 461 462 for (i = 0; i < nwname; i++) { 463 errcode = 464 p9pdu_writef(pdu, 465 proto_version, 466 "s", 467 wnames[i]); 468 if (errcode) 469 break; 470 } 471 } 472 } 473 break; 474 case 'R':{ 475 uint16_t nwqid = va_arg(ap, int); 476 struct p9_qid *wqids = 477 va_arg(ap, struct p9_qid *); 478 479 errcode = p9pdu_writef(pdu, proto_version, "w", 480 nwqid); 481 if (!errcode) { 482 int i; 483 484 for (i = 0; i < nwqid; i++) { 485 errcode = 486 p9pdu_writef(pdu, 487 proto_version, 488 "Q", 489 &wqids[i]); 490 if (errcode) 491 break; 492 } 493 } 494 } 495 break; 496 case 'I':{ 497 struct p9_iattr_dotl *p9attr = va_arg(ap, 498 struct p9_iattr_dotl *); 499 500 errcode = p9pdu_writef(pdu, proto_version, 501 "ddugqqqqq", 502 p9attr->valid, 503 p9attr->mode, 504 p9attr->uid, 505 p9attr->gid, 506 p9attr->size, 507 p9attr->atime_sec, 508 p9attr->atime_nsec, 509 p9attr->mtime_sec, 510 p9attr->mtime_nsec); 511 } 512 break; 513 case '?': 514 if ((proto_version != p9_proto_2000u) && 515 (proto_version != p9_proto_2000L)) 516 return 0; 517 break; 518 default: 519 BUG(); 520 break; 521 } 522 523 if (errcode) 524 break; 525 } 526 527 return errcode; 528 } 529 530 int p9pdu_readf(struct p9_fcall *pdu, int proto_version, const char *fmt, ...) 531 { 532 va_list ap; 533 int ret; 534 535 va_start(ap, fmt); 536 ret = p9pdu_vreadf(pdu, proto_version, fmt, ap); 537 va_end(ap); 538 539 return ret; 540 } 541 542 static int 543 p9pdu_writef(struct p9_fcall *pdu, int proto_version, const char *fmt, ...) 544 { 545 va_list ap; 546 int ret; 547 548 va_start(ap, fmt); 549 ret = p9pdu_vwritef(pdu, proto_version, fmt, ap); 550 va_end(ap); 551 552 return ret; 553 } 554 555 int p9stat_read(struct p9_client *clnt, char *buf, int len, struct p9_wstat *st) 556 { 557 struct p9_fcall fake_pdu; 558 int ret; 559 560 fake_pdu.size = len; 561 fake_pdu.capacity = len; 562 fake_pdu.sdata = buf; 563 fake_pdu.offset = 0; 564 565 ret = p9pdu_readf(&fake_pdu, clnt->proto_version, "S", st); 566 if (ret) { 567 p9_debug(P9_DEBUG_9P, "<<< p9stat_read failed: %d\n", ret); 568 trace_9p_protocol_dump(clnt, &fake_pdu); 569 } 570 571 return ret; 572 } 573 EXPORT_SYMBOL(p9stat_read); 574 575 int p9pdu_prepare(struct p9_fcall *pdu, int16_t tag, int8_t type) 576 { 577 pdu->id = type; 578 return p9pdu_writef(pdu, 0, "dbw", 0, type, tag); 579 } 580 581 int p9pdu_finalize(struct p9_client *clnt, struct p9_fcall *pdu) 582 { 583 int size = pdu->size; 584 int err; 585 586 pdu->size = 0; 587 err = p9pdu_writef(pdu, 0, "d", size); 588 pdu->size = size; 589 590 trace_9p_protocol_dump(clnt, pdu); 591 p9_debug(P9_DEBUG_9P, ">>> size=%d type: %d tag: %d\n", 592 pdu->size, pdu->id, pdu->tag); 593 594 return err; 595 } 596 597 void p9pdu_reset(struct p9_fcall *pdu) 598 { 599 pdu->offset = 0; 600 pdu->size = 0; 601 } 602 603 int p9dirent_read(struct p9_client *clnt, char *buf, int len, 604 struct p9_dirent *dirent) 605 { 606 struct p9_fcall fake_pdu; 607 int ret; 608 char *nameptr; 609 610 fake_pdu.size = len; 611 fake_pdu.capacity = len; 612 fake_pdu.sdata = buf; 613 fake_pdu.offset = 0; 614 615 ret = p9pdu_readf(&fake_pdu, clnt->proto_version, "Qqbs", &dirent->qid, 616 &dirent->d_off, &dirent->d_type, &nameptr); 617 if (ret) { 618 p9_debug(P9_DEBUG_9P, "<<< p9dirent_read failed: %d\n", ret); 619 trace_9p_protocol_dump(clnt, &fake_pdu); 620 goto out; 621 } 622 623 strcpy(dirent->d_name, nameptr); 624 kfree(nameptr); 625 626 out: 627 return fake_pdu.offset; 628 } 629 EXPORT_SYMBOL(p9dirent_read); 630