1// SPDX-License-Identifier: GPL-2.0-only 2/* 3 * net/9p/protocol.c 4 * 5 * 9P Protocol Support Code 6 * 7 * Copyright (C) 2008 by Eric Van Hensbergen <ericvh@gmail.com> 8 * 9 * Base on code from Anthony Liguori <aliguori@us.ibm.com> 10 * Copyright (C) 2008 by IBM, Corp. 11 */ 12 13#include <linux/module.h> 14#include <linux/errno.h> 15#include <linux/kernel.h> 16#include <linux/uaccess.h> 17#include <linux/slab.h> 18#include <linux/sched.h> 19#include <linux/stddef.h> 20#include <linux/types.h> 21#include <linux/uio.h> 22#include <net/9p/9p.h> 23#include <net/9p/client.h> 24#include "protocol.h" 25 26#include <trace/events/9p.h> 27 28static int 29p9pdu_writef(struct p9_fcall *pdu, int proto_version, const char *fmt, ...); 30 31void p9stat_free(struct p9_wstat *stbuf) 32{ 33 kfree(stbuf->name); 34 stbuf->name = NULL; 35 kfree(stbuf->uid); 36 stbuf->uid = NULL; 37 kfree(stbuf->gid); 38 stbuf->gid = NULL; 39 kfree(stbuf->muid); 40 stbuf->muid = NULL; 41 kfree(stbuf->extension); 42 stbuf->extension = NULL; 43} 44EXPORT_SYMBOL(p9stat_free); 45 46size_t pdu_read(struct p9_fcall *pdu, void *data, size_t size) 47{ 48 size_t len = min(pdu->size - pdu->offset, size); 49 memcpy(data, &pdu->sdata[pdu->offset], len); 50 pdu->offset += len; 51 return size - len; 52} 53 54static size_t pdu_write(struct p9_fcall *pdu, const void *data, size_t size) 55{ 56 size_t len = min(pdu->capacity - pdu->size, size); 57 memcpy(&pdu->sdata[pdu->size], data, len); 58 pdu->size += len; 59 return size - len; 60} 61 62static size_t 63pdu_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 if (!copy_from_iter_full(&pdu->sdata[pdu->size], len, &i)) 68 len = 0; 69 70 pdu->size += len; 71 return size - len; 72} 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 91static int 92p9pdu_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 *wnames = NULL; 232 233 errcode = p9pdu_readf(pdu, proto_version, 234 "w", nwname); 235 if (!errcode) { 236 *wnames = 237 kmalloc_array(*nwname, 238 sizeof(char *), 239 GFP_NOFS); 240 if (!*wnames) 241 errcode = -ENOMEM; 242 else 243 (*wnames)[0] = NULL; 244 } 245 246 if (!errcode) { 247 int i; 248 249 for (i = 0; i < *nwname; i++) { 250 errcode = 251 p9pdu_readf(pdu, 252 proto_version, 253 "s", 254 &(*wnames)[i]); 255 if (errcode) { 256 (*wnames)[i] = NULL; 257 break; 258 } 259 } 260 } 261 262 if (errcode) { 263 if (*wnames) { 264 int i; 265 266 for (i = 0; i < *nwname; i++) { 267 if (!(*wnames)[i]) 268 break; 269 kfree((*wnames)[i]); 270 } 271 kfree(*wnames); 272 *wnames = NULL; 273 } 274 } 275 } 276 break; 277 case 'R':{ 278 uint16_t *nwqid = va_arg(ap, uint16_t *); 279 struct p9_qid **wqids = 280 va_arg(ap, struct p9_qid **); 281 282 *wqids = NULL; 283 284 errcode = 285 p9pdu_readf(pdu, proto_version, "w", nwqid); 286 if (!errcode) { 287 *wqids = 288 kmalloc_array(*nwqid, 289 sizeof(struct p9_qid), 290 GFP_NOFS); 291 if (*wqids == NULL) 292 errcode = -ENOMEM; 293 } 294 295 if (!errcode) { 296 int i; 297 298 for (i = 0; i < *nwqid; i++) { 299 errcode = 300 p9pdu_readf(pdu, 301 proto_version, 302 "Q", 303 &(*wqids)[i]); 304 if (errcode) 305 break; 306 } 307 } 308 309 if (errcode) { 310 kfree(*wqids); 311 *wqids = NULL; 312 } 313 } 314 break; 315 case 'A': { 316 struct p9_stat_dotl *stbuf = 317 va_arg(ap, struct p9_stat_dotl *); 318 319 memset(stbuf, 0, sizeof(struct p9_stat_dotl)); 320 errcode = 321 p9pdu_readf(pdu, proto_version, 322 "qQdugqqqqqqqqqqqqqqq", 323 &stbuf->st_result_mask, 324 &stbuf->qid, 325 &stbuf->st_mode, 326 &stbuf->st_uid, &stbuf->st_gid, 327 &stbuf->st_nlink, 328 &stbuf->st_rdev, &stbuf->st_size, 329 &stbuf->st_blksize, &stbuf->st_blocks, 330 &stbuf->st_atime_sec, 331 &stbuf->st_atime_nsec, 332 &stbuf->st_mtime_sec, 333 &stbuf->st_mtime_nsec, 334 &stbuf->st_ctime_sec, 335 &stbuf->st_ctime_nsec, 336 &stbuf->st_btime_sec, 337 &stbuf->st_btime_nsec, 338 &stbuf->st_gen, 339 &stbuf->st_data_version); 340 } 341 break; 342 case '?': 343 if ((proto_version != p9_proto_2000u) && 344 (proto_version != p9_proto_2000L)) 345 return 0; 346 break; 347 default: 348 BUG(); 349 break; 350 } 351 352 if (errcode) 353 break; 354 } 355 356 return errcode; 357} 358 359int 360p9pdu_vwritef(struct p9_fcall *pdu, int proto_version, const char *fmt, 361 va_list ap) 362{ 363 const char *ptr; 364 int errcode = 0; 365 366 for (ptr = fmt; *ptr; ptr++) { 367 switch (*ptr) { 368 case 'b':{ 369 int8_t val = va_arg(ap, int); 370 if (pdu_write(pdu, &val, sizeof(val))) 371 errcode = -EFAULT; 372 } 373 break; 374 case 'w':{ 375 __le16 val = cpu_to_le16(va_arg(ap, int)); 376 if (pdu_write(pdu, &val, sizeof(val))) 377 errcode = -EFAULT; 378 } 379 break; 380 case 'd':{ 381 __le32 val = cpu_to_le32(va_arg(ap, int32_t)); 382 if (pdu_write(pdu, &val, sizeof(val))) 383 errcode = -EFAULT; 384 } 385 break; 386 case 'q':{ 387 __le64 val = cpu_to_le64(va_arg(ap, int64_t)); 388 if (pdu_write(pdu, &val, sizeof(val))) 389 errcode = -EFAULT; 390 } 391 break; 392 case 's':{ 393 const char *sptr = va_arg(ap, const char *); 394 uint16_t len = 0; 395 if (sptr) 396 len = min_t(size_t, strlen(sptr), 397 USHRT_MAX); 398 399 errcode = p9pdu_writef(pdu, proto_version, 400 "w", len); 401 if (!errcode && pdu_write(pdu, sptr, len)) 402 errcode = -EFAULT; 403 } 404 break; 405 case 'u': { 406 kuid_t uid = va_arg(ap, kuid_t); 407 __le32 val = cpu_to_le32( 408 from_kuid(&init_user_ns, uid)); 409 if (pdu_write(pdu, &val, sizeof(val))) 410 errcode = -EFAULT; 411 } break; 412 case 'g': { 413 kgid_t gid = va_arg(ap, kgid_t); 414 __le32 val = cpu_to_le32( 415 from_kgid(&init_user_ns, gid)); 416 if (pdu_write(pdu, &val, sizeof(val))) 417 errcode = -EFAULT; 418 } break; 419 case 'Q':{ 420 const struct p9_qid *qid = 421 va_arg(ap, const struct p9_qid *); 422 errcode = 423 p9pdu_writef(pdu, proto_version, "bdq", 424 qid->type, qid->version, 425 qid->path); 426 } break; 427 case 'S':{ 428 const struct p9_wstat *stbuf = 429 va_arg(ap, const struct p9_wstat *); 430 errcode = 431 p9pdu_writef(pdu, proto_version, 432 "wwdQdddqssss?sugu", 433 stbuf->size, stbuf->type, 434 stbuf->dev, &stbuf->qid, 435 stbuf->mode, stbuf->atime, 436 stbuf->mtime, stbuf->length, 437 stbuf->name, stbuf->uid, 438 stbuf->gid, stbuf->muid, 439 stbuf->extension, stbuf->n_uid, 440 stbuf->n_gid, stbuf->n_muid); 441 } break; 442 case 'V':{ 443 uint32_t count = va_arg(ap, uint32_t); 444 struct iov_iter *from = 445 va_arg(ap, struct iov_iter *); 446 errcode = p9pdu_writef(pdu, proto_version, "d", 447 count); 448 if (!errcode && pdu_write_u(pdu, from, count)) 449 errcode = -EFAULT; 450 } 451 break; 452 case 'T':{ 453 uint16_t nwname = va_arg(ap, int); 454 const char **wnames = va_arg(ap, const char **); 455 456 errcode = p9pdu_writef(pdu, proto_version, "w", 457 nwname); 458 if (!errcode) { 459 int i; 460 461 for (i = 0; i < nwname; i++) { 462 errcode = 463 p9pdu_writef(pdu, 464 proto_version, 465 "s", 466 wnames[i]); 467 if (errcode) 468 break; 469 } 470 } 471 } 472 break; 473 case 'R':{ 474 uint16_t nwqid = va_arg(ap, int); 475 struct p9_qid *wqids = 476 va_arg(ap, struct p9_qid *); 477 478 errcode = p9pdu_writef(pdu, proto_version, "w", 479 nwqid); 480 if (!errcode) { 481 int i; 482 483 for (i = 0; i < nwqid; i++) { 484 errcode = 485 p9pdu_writef(pdu, 486 proto_version, 487 "Q", 488 &wqids[i]); 489 if (errcode) 490 break; 491 } 492 } 493 } 494 break; 495 case 'I':{ 496 struct p9_iattr_dotl *p9attr = va_arg(ap, 497 struct p9_iattr_dotl *); 498 499 errcode = p9pdu_writef(pdu, proto_version, 500 "ddugqqqqq", 501 p9attr->valid, 502 p9attr->mode, 503 p9attr->uid, 504 p9attr->gid, 505 p9attr->size, 506 p9attr->atime_sec, 507 p9attr->atime_nsec, 508 p9attr->mtime_sec, 509 p9attr->mtime_nsec); 510 } 511 break; 512 case '?': 513 if ((proto_version != p9_proto_2000u) && 514 (proto_version != p9_proto_2000L)) 515 return 0; 516 break; 517 default: 518 BUG(); 519 break; 520 } 521 522 if (errcode) 523 break; 524 } 525 526 return errcode; 527} 528 529int p9pdu_readf(struct p9_fcall *pdu, int proto_version, const char *fmt, ...) 530{ 531 va_list ap; 532 int ret; 533 534 va_start(ap, fmt); 535 ret = p9pdu_vreadf(pdu, proto_version, fmt, ap); 536 va_end(ap); 537 538 return ret; 539} 540 541static int 542p9pdu_writef(struct p9_fcall *pdu, int proto_version, const char *fmt, ...) 543{ 544 va_list ap; 545 int ret; 546 547 va_start(ap, fmt); 548 ret = p9pdu_vwritef(pdu, proto_version, fmt, ap); 549 va_end(ap); 550 551 return ret; 552} 553 554int p9stat_read(struct p9_client *clnt, char *buf, int len, struct p9_wstat *st) 555{ 556 struct p9_fcall fake_pdu; 557 int ret; 558 559 fake_pdu.size = len; 560 fake_pdu.capacity = len; 561 fake_pdu.sdata = buf; 562 fake_pdu.offset = 0; 563 564 ret = p9pdu_readf(&fake_pdu, clnt->proto_version, "S", st); 565 if (ret) { 566 p9_debug(P9_DEBUG_9P, "<<< p9stat_read failed: %d\n", ret); 567 trace_9p_protocol_dump(clnt, &fake_pdu); 568 return ret; 569 } 570 571 return fake_pdu.offset; 572} 573EXPORT_SYMBOL(p9stat_read); 574 575int 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 581int 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 597void p9pdu_reset(struct p9_fcall *pdu) 598{ 599 pdu->offset = 0; 600 pdu->size = 0; 601} 602 603int 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 return ret; 621 } 622 623 ret = strscpy(dirent->d_name, nameptr, sizeof(dirent->d_name)); 624 if (ret < 0) { 625 p9_debug(P9_DEBUG_ERROR, 626 "On the wire dirent name too long: %s\n", 627 nameptr); 628 kfree(nameptr); 629 return ret; 630 } 631 kfree(nameptr); 632 633 return fake_pdu.offset; 634} 635EXPORT_SYMBOL(p9dirent_read); 636