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 43static int 44p9pdu_writef(struct p9_fcall *pdu, int proto_version, const char *fmt, ...); 45 46void 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} 54EXPORT_SYMBOL(p9stat_free); 55 56size_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 64static 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 72static size_t 73pdu_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(&pdu->sdata[pdu->size], len, &i) != len) 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 101static int 102p9pdu_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 = -EFAULT; 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(sizeof(char *) * *nwname, 246 GFP_NOFS); 247 if (!*wnames) 248 errcode = -ENOMEM; 249 } 250 251 if (!errcode) { 252 int i; 253 254 for (i = 0; i < *nwname; i++) { 255 errcode = 256 p9pdu_readf(pdu, 257 proto_version, 258 "s", 259 &(*wnames)[i]); 260 if (errcode) 261 break; 262 } 263 } 264 265 if (errcode) { 266 if (*wnames) { 267 int i; 268 269 for (i = 0; i < *nwname; i++) 270 kfree((*wnames)[i]); 271 } 272 kfree(*wnames); 273 *wnames = NULL; 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(*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 } 569 570 return ret; 571} 572EXPORT_SYMBOL(p9stat_read); 573 574int p9pdu_prepare(struct p9_fcall *pdu, int16_t tag, int8_t type) 575{ 576 pdu->id = type; 577 return p9pdu_writef(pdu, 0, "dbw", 0, type, tag); 578} 579 580int p9pdu_finalize(struct p9_client *clnt, struct p9_fcall *pdu) 581{ 582 int size = pdu->size; 583 int err; 584 585 pdu->size = 0; 586 err = p9pdu_writef(pdu, 0, "d", size); 587 pdu->size = size; 588 589 trace_9p_protocol_dump(clnt, pdu); 590 p9_debug(P9_DEBUG_9P, ">>> size=%d type: %d tag: %d\n", 591 pdu->size, pdu->id, pdu->tag); 592 593 return err; 594} 595 596void p9pdu_reset(struct p9_fcall *pdu) 597{ 598 pdu->offset = 0; 599 pdu->size = 0; 600} 601 602int p9dirent_read(struct p9_client *clnt, char *buf, int len, 603 struct p9_dirent *dirent) 604{ 605 struct p9_fcall fake_pdu; 606 int ret; 607 char *nameptr; 608 609 fake_pdu.size = len; 610 fake_pdu.capacity = len; 611 fake_pdu.sdata = buf; 612 fake_pdu.offset = 0; 613 614 ret = p9pdu_readf(&fake_pdu, clnt->proto_version, "Qqbs", &dirent->qid, 615 &dirent->d_off, &dirent->d_type, &nameptr); 616 if (ret) { 617 p9_debug(P9_DEBUG_9P, "<<< p9dirent_read failed: %d\n", ret); 618 trace_9p_protocol_dump(clnt, &fake_pdu); 619 goto out; 620 } 621 622 strcpy(dirent->d_name, nameptr); 623 kfree(nameptr); 624 625out: 626 return fake_pdu.offset; 627} 628EXPORT_SYMBOL(p9dirent_read); 629