protocol.c 14 KB

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