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