xref: /linux/net/9p/protocol.c (revision 024b7d6a435a450819f112690052f2923fa5ffdd)
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