xref: /netbsd-src/sys/compat/common/compat_util.c (revision d91f98a8715141154279122ae81737cb65179572)
1*d91f98a8Spgoyette /* 	$NetBSD: compat_util.c,v 1.47 2019/01/27 02:08:39 pgoyette Exp $	*/
28fb507a3Schristos 
38fb507a3Schristos /*-
48fb507a3Schristos  * Copyright (c) 1994 The NetBSD Foundation, Inc.
58fb507a3Schristos  * All rights reserved.
68fb507a3Schristos  *
78fb507a3Schristos  * This code is derived from software contributed to The NetBSD Foundation
8192330fdSfvdl  * by Christos Zoulas and Frank van der Linden.
98fb507a3Schristos  *
108fb507a3Schristos  * Redistribution and use in source and binary forms, with or without
118fb507a3Schristos  * modification, are permitted provided that the following conditions
128fb507a3Schristos  * are met:
138fb507a3Schristos  * 1. Redistributions of source code must retain the above copyright
148fb507a3Schristos  *    notice, this list of conditions and the following disclaimer.
158fb507a3Schristos  * 2. Redistributions in binary form must reproduce the above copyright
168fb507a3Schristos  *    notice, this list of conditions and the following disclaimer in the
178fb507a3Schristos  *    documentation and/or other materials provided with the distribution.
188fb507a3Schristos  *
198fb507a3Schristos  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
208fb507a3Schristos  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
218fb507a3Schristos  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
228fb507a3Schristos  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
238fb507a3Schristos  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
248fb507a3Schristos  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
258fb507a3Schristos  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
268fb507a3Schristos  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
278fb507a3Schristos  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
288fb507a3Schristos  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
298fb507a3Schristos  * POSSIBILITY OF SUCH DAMAGE.
308fb507a3Schristos  */
31dcb2a50bSchristos 
3297c80e8fSmrg /*
3397c80e8fSmrg  * Copyright (c) 2008, 2009 Matthew R. Green
3497c80e8fSmrg  * All rights reserved.
3597c80e8fSmrg  *
3697c80e8fSmrg  * Redistribution and use in source and binary forms, with or without
3797c80e8fSmrg  * modification, are permitted provided that the following conditions
3897c80e8fSmrg  * are met:
3997c80e8fSmrg  * 1. Redistributions of source code must retain the above copyright
4097c80e8fSmrg  *    notice, this list of conditions and the following disclaimer.
4197c80e8fSmrg  * 2. Redistributions in binary form must reproduce the above copyright
4297c80e8fSmrg  *    notice, this list of conditions and the following disclaimer in the
4397c80e8fSmrg  *    documentation and/or other materials provided with the distribution.
4497c80e8fSmrg  * 3. The name of the author may not be used to endorse or promote products
4597c80e8fSmrg  *    derived from this software without specific prior written permission.
4697c80e8fSmrg  *
4797c80e8fSmrg  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
4897c80e8fSmrg  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
4997c80e8fSmrg  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
5097c80e8fSmrg  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
5197c80e8fSmrg  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
5297c80e8fSmrg  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
5397c80e8fSmrg  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
5497c80e8fSmrg  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
5597c80e8fSmrg  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
5697c80e8fSmrg  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
5797c80e8fSmrg  * SUCH DAMAGE.
5897c80e8fSmrg  */
5997c80e8fSmrg 
60dab6ef8bSlukem #include <sys/cdefs.h>
61*d91f98a8Spgoyette __KERNEL_RCSID(0, "$NetBSD: compat_util.c,v 1.47 2019/01/27 02:08:39 pgoyette Exp $");
62*d91f98a8Spgoyette 
63*d91f98a8Spgoyette #if defined(_KERNEL_OPT)
64*d91f98a8Spgoyette #include "opt_compat_netbsd.h"
65*d91f98a8Spgoyette #endif
66dab6ef8bSlukem 
67dcb2a50bSchristos #include <sys/param.h>
68dcb2a50bSchristos #include <sys/systm.h>
69dcb2a50bSchristos #include <sys/namei.h>
70dcb2a50bSchristos #include <sys/proc.h>
71dcb2a50bSchristos #include <sys/file.h>
72dcb2a50bSchristos #include <sys/stat.h>
73dcb2a50bSchristos #include <sys/filedesc.h>
74bddeb302Sthorpej #include <sys/exec.h>
75dcb2a50bSchristos #include <sys/ioctl.h>
76dcb2a50bSchristos #include <sys/kernel.h>
77dcb2a50bSchristos #include <sys/vnode.h>
78811fbe17Sfvdl #include <sys/syslog.h>
79811fbe17Sfvdl #include <sys/mount.h>
80*d91f98a8Spgoyette #include <sys/module.h>
81dcb2a50bSchristos 
82dcb2a50bSchristos #include <compat/common/compat_util.h>
83dcb2a50bSchristos 
84302af6f0Sjdolecek /*
855b217baeScgd  * Translate one set of flags to another, based on the entries in
865b217baeScgd  * the given table.  If 'leftover' is specified, it is filled in
875b217baeScgd  * with any flags which could not be translated.
885b217baeScgd  */
895b217baeScgd unsigned long
emul_flags_translate(const struct emul_flags_xtab * tab,unsigned long in,unsigned long * leftover)905b217baeScgd emul_flags_translate(const struct emul_flags_xtab *tab,
915b217baeScgd 		     unsigned long in, unsigned long *leftover)
925b217baeScgd {
935b217baeScgd 	unsigned long out;
945b217baeScgd 
955b217baeScgd 	for (out = 0; tab->omask != 0; tab++) {
965b217baeScgd 		if ((in & tab->omask) == tab->oval) {
975b217baeScgd 			in &= ~tab->omask;
985b217baeScgd 			out |= tab->nval;
995b217baeScgd 		}
1005b217baeScgd 	}
1015b217baeScgd 	if (leftover != NULL)
1025b217baeScgd 		*leftover = in;
1035b217baeScgd 	return (out);
1045b217baeScgd }
1055b217baeScgd 
106811fbe17Sfvdl void
compat_offseterr(struct vnode * vp,const char * msg)10728bae79bSdsl compat_offseterr(struct vnode *vp, const char *msg)
108811fbe17Sfvdl {
109811fbe17Sfvdl 	struct mount *mp;
110811fbe17Sfvdl 
111811fbe17Sfvdl 	mp = vp->v_mount;
112811fbe17Sfvdl 
113811fbe17Sfvdl 	log(LOG_ERR, "%s: dir offset too large on fs %s (mounted from %s)\n",
114811fbe17Sfvdl 	    msg, mp->mnt_stat.f_mntonname, mp->mnt_stat.f_mntfromname);
115811fbe17Sfvdl 	uprintf("%s: dir offset too large for emulated program\n", msg);
116811fbe17Sfvdl }
11797c80e8fSmrg 
11897c80e8fSmrg /*
11997c80e8fSmrg  * Look for native NetBSD compatibility libraries, usually interp-ABI.
12097c80e8fSmrg  * It returns 0 if it changed the interpreter, otherwise it returns
12197c80e8fSmrg  * the error from namei().  Callers should not try any more processing
12297c80e8fSmrg  * if this returns 0, and probably should just ignore the return value.
12397c80e8fSmrg  */
12497c80e8fSmrg int
compat_elf_check_interp(struct exec_package * epp,char * interp,const char * interp_suffix)12597c80e8fSmrg compat_elf_check_interp(struct exec_package *epp,
12697c80e8fSmrg 			char *interp,
12797c80e8fSmrg 			const char *interp_suffix)
12897c80e8fSmrg {
12997c80e8fSmrg 	int error = 0;
13097c80e8fSmrg 
13197c80e8fSmrg 	/*
13297c80e8fSmrg 	 * Don't look for something else, if someone has already found and
13397c80e8fSmrg 	 * setup the ep_interp already.
13497c80e8fSmrg 	 */
13597c80e8fSmrg 	if (interp && epp->ep_interp == NULL) {
13697c80e8fSmrg 		/*
13797c80e8fSmrg 		 * If the path is exactly "/usr/libexec/ld.elf_so", first
13897c80e8fSmrg 		 * try to see if "/usr/libexec/ld.elf_so-<abi>" exists
13997c80e8fSmrg 		 * and if so, use that instead.
14097c80e8fSmrg 		 */
14197c80e8fSmrg 		if (strcmp(interp, "/usr/libexec/ld.elf_so") == 0 ||
14297c80e8fSmrg 		    strcmp(interp, "/libexec/ld.elf_so") == 0) {
14397c80e8fSmrg 			struct vnode *vp;
14497c80e8fSmrg 			char *path;
14597c80e8fSmrg 
14697c80e8fSmrg 			path = PNBUF_GET();
14797c80e8fSmrg 			snprintf(path, MAXPATHLEN, "%s-%s", interp, interp_suffix);
14897c80e8fSmrg 			error = namei_simple_kernel(path,
14997c80e8fSmrg 					NSM_FOLLOW_NOEMULROOT, &vp);
15097c80e8fSmrg 			/*
15197c80e8fSmrg 			 * If that worked, replace interpreter in case we
15297c80e8fSmrg 			 * actually need to load it.
15397c80e8fSmrg 			 */
15497c80e8fSmrg 			if (error == 0) {
15597c80e8fSmrg 				epp->ep_interp = vp;
15697c80e8fSmrg 				snprintf(interp, MAXPATHLEN, "%s", path);
15797c80e8fSmrg 			}
15897c80e8fSmrg 			PNBUF_PUT(path);
15997c80e8fSmrg 		}
16097c80e8fSmrg 	}
16197c80e8fSmrg 	return error;
16297c80e8fSmrg }
163*d91f98a8Spgoyette 
164*d91f98a8Spgoyette MODULE(MODULE_CLASS_MISC, compat_util, NULL);
165*d91f98a8Spgoyette 
166*d91f98a8Spgoyette int
compat_util_modcmd(modcmd_t cmd,void * arg)167*d91f98a8Spgoyette compat_util_modcmd(modcmd_t cmd, void *arg)
168*d91f98a8Spgoyette {
169*d91f98a8Spgoyette 
170*d91f98a8Spgoyette 	switch (cmd) {
171*d91f98a8Spgoyette 	case MODULE_CMD_INIT:
172*d91f98a8Spgoyette 	case MODULE_CMD_FINI:
173*d91f98a8Spgoyette 		return 0;
174*d91f98a8Spgoyette 	default:
175*d91f98a8Spgoyette 		return ENOTTY;
176*d91f98a8Spgoyette 	}
177*d91f98a8Spgoyette }
178