Home | History | Annotate | Line # | Download | only in puffs
puffs_compat.c revision 1.2.24.1
      1 /*	$NetBSD: puffs_compat.c,v 1.2.24.1 2017/12/03 11:38:43 jdolecek Exp $	*/
      2 
      3 /*
      4  * Copyright (c) 2010 Antti Kantee.  All Rights Reserved.
      5  *
      6  * Redistribution and use in source and binary forms, with or without
      7  * modification, are permitted provided that the following conditions
      8  * are met:
      9  * 1. Redistributions of source code must retain the above copyright
     10  *    notice, this list of conditions and the following disclaimer.
     11  * 2. Redistributions in binary form must reproduce the above copyright
     12  *    notice, this list of conditions and the following disclaimer in the
     13  *    documentation and/or other materials provided with the distribution.
     14  *
     15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
     16  * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
     17  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
     18  * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
     19  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     20  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
     21  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     22  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     23  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     24  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     25  * SUCH DAMAGE.
     26  */
     27 
     28 /*
     29  * This file handles puffs PDUs so that they are compatible between
     30  * 32bit<->64bit time_t/dev_t.  It enables running a -current kernel
     31  * against a 5.0 userland (assuming the protocol otherwise matches!).
     32  */
     33 
     34 #include <sys/cdefs.h>
     35 __KERNEL_RCSID(0, "$NetBSD: puffs_compat.c,v 1.2.24.1 2017/12/03 11:38:43 jdolecek Exp $");
     36 
     37 #include <sys/param.h>
     38 #include <sys/atomic.h>
     39 #include <sys/kmem.h>
     40 #include <sys/kthread.h>
     41 #include <sys/lock.h>
     42 #include <sys/mount.h>
     43 #include <sys/namei.h>
     44 #include <sys/proc.h>
     45 #include <sys/vnode.h>
     46 #include <sys/atomic.h>
     47 
     48 #include <dev/putter/putter_sys.h>
     49 
     50 #include <fs/puffs/puffs_msgif.h>
     51 #include <fs/puffs/puffs_sys.h>
     52 
     53 #include <compat/sys/time.h>
     54 
     55 /*
     56  * compat types
     57  */
     58 struct vattr50 {
     59 	enum vtype		va_type;
     60 	mode_t			va_mode;
     61 	nlink_t			va_nlink;
     62 	uid_t			va_uid;
     63 	gid_t			va_gid;
     64 	uint32_t		va_fsid;
     65 	ino_t			va_fileid;
     66 	u_quad_t		va_size;
     67 	long			va_blocksize;
     68 	struct timespec50	va_atime;
     69 	struct timespec50	va_mtime;
     70 	struct timespec50	va_ctime;
     71 	struct timespec50	va_birthtime;
     72 	u_long			va_gen;
     73 	u_long			va_flags;
     74 	uint32_t		va_rdev;
     75 	u_quad_t		va_bytes;
     76 	u_quad_t		va_filerev;
     77 	u_int			va_vaflags;
     78 	long			va_spare;
     79 };
     80 
     81 struct puffs50_vfsmsg_fhtonode {
     82 	struct puffs_req	pvfsr_pr;
     83 
     84 	void			*pvfsr_fhcookie;	/* IN   */
     85 	enum vtype		pvfsr_vtype;		/* IN   */
     86 	voff_t			pvfsr_size;		/* IN   */
     87 	uint32_t		pvfsr_rdev;		/* IN   */
     88 
     89 	size_t			pvfsr_dsize;		/* OUT */
     90 	uint8_t			pvfsr_data[0]		/* OUT, XXX */
     91 					__aligned(ALIGNBYTES+1);
     92 };
     93 
     94 struct puffs50_vnmsg_lookup {
     95 	struct puffs_req	pvn_pr;
     96 
     97 	struct puffs_kcn	pvnr_cn;		/* OUT	*/
     98 	struct puffs_kcred	pvnr_cn_cred;		/* OUT	*/
     99 
    100 	puffs_cookie_t		pvnr_newnode;		/* IN	*/
    101 	enum vtype		pvnr_vtype;		/* IN	*/
    102 	voff_t			pvnr_size;		/* IN	*/
    103 	uint32_t		pvnr_rdev;		/* IN	*/
    104 };
    105 
    106 struct puffs50_vnmsg_create {
    107 	struct puffs_req	pvn_pr;
    108 
    109 	struct puffs_kcn	pvnr_cn;		/* OUT	*/
    110 	struct puffs_kcred	pvnr_cn_cred;		/* OUT	*/
    111 
    112 	struct vattr50		pvnr_va;		/* OUT	*/
    113 	puffs_cookie_t		pvnr_newnode;		/* IN	*/
    114 };
    115 
    116 struct puffs50_vnmsg_mknod {
    117 	struct puffs_req	pvn_pr;
    118 
    119 	struct puffs_kcn	pvnr_cn;		/* OUT	*/
    120 	struct puffs_kcred	pvnr_cn_cred;		/* OUT	*/
    121 
    122 	struct vattr50		pvnr_va;		/* OUT	*/
    123 	puffs_cookie_t		pvnr_newnode;		/* IN	*/
    124 };
    125 
    126 #define puffs50_vnmsg_setattr puffs50_vnmsg_setgetattr
    127 #define puffs50_vnmsg_getattr puffs50_vnmsg_setgetattr
    128 struct puffs50_vnmsg_setgetattr {
    129 	struct puffs_req	pvn_pr;
    130 
    131 	struct puffs_kcred	pvnr_cred;		/* OUT	*/
    132 	struct vattr50		pvnr_va;		/* IN/OUT (op depend) */
    133 };
    134 
    135 struct puffs50_vnmsg_mkdir {
    136 	struct puffs_req	pvn_pr;
    137 
    138 	struct puffs_kcn	pvnr_cn;		/* OUT	*/
    139 	struct puffs_kcred	pvnr_cn_cred;		/* OUT	*/
    140 
    141 	struct vattr50		pvnr_va;		/* OUT	*/
    142 	puffs_cookie_t		pvnr_newnode;		/* IN	*/
    143 };
    144 
    145 struct puffs50_vnmsg_symlink {
    146 	struct puffs_req	pvn_pr;
    147 
    148 	struct puffs_kcn	pvnr_cn;		/* OUT	*/
    149 	struct puffs_kcred	pvnr_cn_cred;		/* OUT	*/
    150 
    151 	struct vattr50		pvnr_va;		/* OUT	*/
    152 	puffs_cookie_t		pvnr_newnode;		/* IN	*/
    153 	char			pvnr_link[MAXPATHLEN];	/* OUT	*/
    154 };
    155 
    156 /*
    157  * vattr translation routines
    158  */
    159 
    160 #ifdef COMPAT_50
    161 static void
    162 vattr_to_50(const struct vattr *va, struct vattr50 *va50)
    163 {
    164 
    165 	va50->va_type = va->va_type;
    166 	va50->va_mode = va->va_mode;
    167 	va50->va_nlink = va->va_nlink;
    168 	va50->va_uid = va->va_uid;
    169 	va50->va_gid = va->va_gid;
    170 	va50->va_fsid = (uint64_t)va->va_fsid;
    171 	va50->va_fileid = va->va_fileid;
    172 	va50->va_size = va->va_size;
    173 	va50->va_blocksize = va->va_blocksize;
    174 	timespec_to_timespec50(&va->va_atime, &va50->va_atime);
    175 	timespec_to_timespec50(&va->va_ctime, &va50->va_ctime);
    176 	timespec_to_timespec50(&va->va_mtime, &va50->va_mtime);
    177 	timespec_to_timespec50(&va->va_birthtime, &va50->va_birthtime);
    178 	va50->va_gen = va->va_gen;
    179 	va50->va_flags = va->va_flags;
    180 	va50->va_rdev = (int32_t)va->va_rdev;
    181 	va50->va_bytes = va->va_bytes;
    182 	va50->va_filerev = va->va_filerev;
    183 	va50->va_vaflags = va->va_flags;
    184 }
    185 
    186 static void
    187 vattr_from_50(const struct vattr50 *va50, struct vattr *va)
    188 {
    189 
    190 	va->va_type = va50->va_type;
    191 	va->va_mode = va50->va_mode;
    192 	va->va_nlink = va50->va_nlink;
    193 	va->va_uid = va50->va_uid;
    194 	va->va_gid = va50->va_gid;
    195 	va->va_fsid = (uint32_t)va50->va_fsid;
    196 	va->va_fileid = va50->va_fileid;
    197 	va->va_size = va50->va_size;
    198 	va->va_blocksize = va50->va_blocksize;
    199 	timespec50_to_timespec(&va50->va_atime, &va->va_atime);
    200 	timespec50_to_timespec(&va50->va_ctime, &va->va_ctime);
    201 	timespec50_to_timespec(&va50->va_mtime, &va->va_mtime);
    202 	timespec50_to_timespec(&va50->va_birthtime, &va->va_birthtime);
    203 	va->va_gen = va50->va_gen;
    204 	va->va_flags = va50->va_flags;
    205 	va->va_rdev = (uint32_t)va50->va_rdev;
    206 	va->va_bytes = va50->va_bytes;
    207 	va->va_filerev = va50->va_filerev;
    208 	va->va_vaflags = va50->va_flags;
    209 }
    210 #endif /* COMPAT_50 */
    211 
    212 /*
    213  * XXX: cannot assert that sleeping is possible
    214  * (this always a valid assumption for now)
    215  */
    216 #define INIT(name, extra)						\
    217 	struct puffs50_##name *cmsg;					\
    218 	struct puffs_##name *omsg;					\
    219 	creq =kmem_zalloc(sizeof(struct puffs50_##name)+extra,KM_SLEEP);\
    220 	cmsg = (struct puffs50_##name *)creq;				\
    221 	omsg = (struct puffs_##name *)oreq;				\
    222 	delta = sizeof(struct puffs50_##name)-sizeof(struct puffs_##name);
    223 #define ASSIGN(field)							\
    224 	cmsg->field = omsg->field;
    225 
    226 bool
    227 puffs_compat_outgoing(struct puffs_req *oreq,
    228 	struct puffs_req **creqp, ssize_t *deltap)
    229 {
    230 	bool rv = false;
    231 #ifdef COMPAT_50
    232 	struct puffs_req *creq = NULL;
    233 	ssize_t delta = 0;
    234 
    235 	if (PUFFSOP_OPCLASS(oreq->preq_opclass) == PUFFSOP_VFS
    236 	    && oreq->preq_optype == PUFFS_VFS_FHTOVP) {
    237 		INIT(vfsmsg_fhtonode,
    238 		    ((struct puffs_vfsmsg_fhtonode *)oreq)->pvfsr_dsize);
    239 
    240 		ASSIGN(pvfsr_pr);
    241 		ASSIGN(pvfsr_dsize);
    242 		memcpy(cmsg->pvfsr_data, omsg->pvfsr_data, cmsg->pvfsr_dsize);
    243 	} else if (PUFFSOP_OPCLASS(oreq->preq_opclass) == PUFFSOP_VN) {
    244 		switch (oreq->preq_optype) {
    245 		case PUFFS_VN_LOOKUP:
    246 		{
    247 			INIT(vnmsg_lookup, 0);
    248 
    249 			ASSIGN(pvn_pr);
    250 			ASSIGN(pvnr_cn);
    251 			ASSIGN(pvnr_cn_cred);
    252 
    253 			break;
    254 		}
    255 
    256 		case PUFFS_VN_CREATE:
    257 		{
    258 			INIT(vnmsg_create, 0);
    259 
    260 			ASSIGN(pvn_pr);
    261 			ASSIGN(pvnr_cn);
    262 			ASSIGN(pvnr_cn_cred);
    263 			vattr_to_50(&omsg->pvnr_va, &cmsg->pvnr_va);
    264 
    265 			break;
    266 		}
    267 
    268 		case PUFFS_VN_MKNOD:
    269 		{
    270 			INIT(vnmsg_mknod, 0);
    271 
    272 			ASSIGN(pvn_pr);
    273 			ASSIGN(pvnr_cn);
    274 			ASSIGN(pvnr_cn_cred);
    275 			vattr_to_50(&omsg->pvnr_va, &cmsg->pvnr_va);
    276 
    277 			break;
    278 		}
    279 
    280 		case PUFFS_VN_MKDIR:
    281 		{
    282 			INIT(vnmsg_mkdir, 0);
    283 
    284 			ASSIGN(pvn_pr);
    285 			ASSIGN(pvnr_cn);
    286 			ASSIGN(pvnr_cn_cred);
    287 			vattr_to_50(&omsg->pvnr_va, &cmsg->pvnr_va);
    288 
    289 			break;
    290 		}
    291 
    292 		case PUFFS_VN_SYMLINK:
    293 		{
    294 			INIT(vnmsg_symlink, 0);
    295 
    296 			ASSIGN(pvn_pr);
    297 			ASSIGN(pvnr_cn);
    298 			ASSIGN(pvnr_cn_cred);
    299 			vattr_to_50(&omsg->pvnr_va, &cmsg->pvnr_va);
    300 			memcpy(cmsg->pvnr_link, omsg->pvnr_link,
    301 			    sizeof(cmsg->pvnr_link));
    302 
    303 			break;
    304 		}
    305 
    306 		case PUFFS_VN_SETATTR:
    307 		{
    308 			INIT(vnmsg_setattr, 0);
    309 
    310 			ASSIGN(pvn_pr);
    311 			ASSIGN(pvnr_cred);
    312 			vattr_to_50(&omsg->pvnr_va, &cmsg->pvnr_va);
    313 
    314 			break;
    315 		}
    316 		case PUFFS_VN_GETATTR:
    317 		{
    318 			INIT(vnmsg_getattr, 0);
    319 
    320 			ASSIGN(pvn_pr);
    321 			ASSIGN(pvnr_cred);
    322 
    323 			break;
    324 		}
    325 
    326 		default:
    327 			break;
    328 		}
    329 	}
    330 
    331 	if (creq) {
    332 		*creqp = creq;
    333 		*deltap = delta;
    334 		rv = true;
    335 	}
    336 #endif
    337 
    338 	return rv;
    339 }
    340 #undef INIT
    341 #undef ASSIGN
    342 
    343 #define INIT(name)							\
    344 	struct puffs50_##name *cmsg = (void *)preq;			\
    345 	struct puffs_##name *omsg = (void *)creq;
    346 #define ASSIGN(field)							\
    347 	omsg->field = cmsg->field;
    348 
    349 void
    350 puffs_compat_incoming(struct puffs_req *preq, struct puffs_req *creq)
    351 {
    352 
    353 #ifdef COMPAT_50
    354 	if (PUFFSOP_OPCLASS(preq->preq_opclass) == PUFFSOP_VFS
    355 	    && preq->preq_optype == PUFFS_VFS_FHTOVP) {
    356 		INIT(vfsmsg_fhtonode);
    357 
    358 		ASSIGN(pvfsr_pr);
    359 
    360 		ASSIGN(pvfsr_fhcookie);
    361 		ASSIGN(pvfsr_vtype);
    362 		ASSIGN(pvfsr_size);
    363 		ASSIGN(pvfsr_rdev);
    364 	} else if (PUFFSOP_OPCLASS(preq->preq_opclass) == PUFFSOP_VN) {
    365 		switch (preq->preq_optype) {
    366 		case PUFFS_VN_LOOKUP:
    367 		{
    368 			INIT(vnmsg_lookup);
    369 
    370 			ASSIGN(pvn_pr);
    371 			ASSIGN(pvnr_newnode);
    372 			ASSIGN(pvnr_vtype);
    373 			ASSIGN(pvnr_size);
    374 			ASSIGN(pvnr_rdev);
    375 
    376 			break;
    377 		}
    378 
    379 		case PUFFS_VN_CREATE:
    380 		{
    381 			INIT(vnmsg_create);
    382 
    383 			ASSIGN(pvn_pr);
    384 			ASSIGN(pvnr_newnode);
    385 
    386 			break;
    387 		}
    388 
    389 		case PUFFS_VN_MKNOD:
    390 		{
    391 			INIT(vnmsg_mknod);
    392 
    393 			ASSIGN(pvn_pr);
    394 			ASSIGN(pvnr_newnode);
    395 
    396 			break;
    397 		}
    398 
    399 		case PUFFS_VN_MKDIR:
    400 		{
    401 			INIT(vnmsg_mkdir);
    402 
    403 			ASSIGN(pvn_pr);
    404 			ASSIGN(pvnr_newnode);
    405 
    406 			break;
    407 		}
    408 
    409 		case PUFFS_VN_SYMLINK:
    410 		{
    411 			INIT(vnmsg_symlink);
    412 
    413 			ASSIGN(pvn_pr);
    414 			ASSIGN(pvnr_newnode);
    415 
    416 			break;
    417 		}
    418 
    419 		case PUFFS_VN_SETATTR:
    420 		{
    421 			INIT(vnmsg_setattr);
    422 
    423 			ASSIGN(pvn_pr);
    424 
    425 			break;
    426 		}
    427 		case PUFFS_VN_GETATTR:
    428 		{
    429 			INIT(vnmsg_getattr);
    430 
    431 			ASSIGN(pvn_pr);
    432 			vattr_from_50(&cmsg->pvnr_va, &omsg->pvnr_va);
    433 
    434 			break;
    435 		}
    436 
    437 		default:
    438 			panic("puffs compat ops come in pairs");
    439 		}
    440 	}
    441 #endif /* COMPAT_50 */
    442 }
    443