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