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