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