Subject: kern/6962: FreeBSD 3.x and "-current" ELF binaries are not supported
To: None <gnats-bugs@gnats.netbsd.org>
From: None <paul@plectere.com>
List: netbsd-bugs
Date: 02/07/1999 15:04:32
>Number:         6962
>Category:       kern
>Synopsis:       FreeBSD 3.x and "-current" ELF binaries are not supported
>Confidential:   no
>Severity:       critical
>Priority:       medium
>Responsible:    kern-bug-people (Kernel Bug People)
>State:          open
>Class:          change-request
>Submitter-Id:   net
>Arrival-Date:   Sun Feb  7 15:35:00 1999
>Last-Modified:
>Originator:     Paul Shupak
>Organization:
>Release:        NetBSD-current Sun Feb 6 1999
>Environment:
System: NetBSD cobalt 1.3I NetBSD 1.3I (COBALT) #135: Sun Feb 7 04:52:49 PST 1999 root@:/usr/src/sys/arch/i386/compile/COBALT i386


>Description:
	FreeBSD 3.x and current use ELF object and executables.
>How-To-Repeat:
	Attempt to execute any FreeBSD ELF binary.
>Fix:
	The following patches allow FreeBSD ELF to be executed ( e.g.
chroot'ed ELF "make world" completes ); tested only on i386, not Alpha.

*** arch/i386/i386/trap.c-ORIG	Wed Nov 11 04:16:17 1998
--- arch/i386/i386/trap.c	Sat Feb  6 15:29:13 1999
***************
*** 143,149 ****
--- 143,154 ----
  #endif /* !COMPAT_LINUX */
  
  #ifdef COMPAT_FREEBSD
+ #ifdef EXEC_AOUT
  extern struct emul emul_freebsd;
+ #endif /* EXEC_AOUT */
+ #ifdef EXEC_ELF32
+ extern struct emul emul_freebsd_elf32;
+ #endif /* EXEC_ELF32 */
  #endif
  
  #include "npx.h"
***************
*** 727,740 ****
  		 * Like syscall, but code is a quad, so as to maintain
  		 * quad alignment for the rest of the arguments.
  		 */
- #ifdef COMPAT_FREEBSD
  		/* FreeBSD has a same function in SYS___syscall */
! 		if (callp != sysent && p->p_emul != &emul_freebsd)
! 			break;
! #else
! 		if (callp != sysent)
! 			break;
  #endif /* COMPAT_FREEBSD */
  		code = fuword(params + _QUAD_LOWWORD * sizeof(int));
  		params += sizeof(quad_t);
  		break;
--- 732,749 ----
  		 * Like syscall, but code is a quad, so as to maintain
  		 * quad alignment for the rest of the arguments.
  		 */
  		/* FreeBSD has a same function in SYS___syscall */
! 		if (callp != sysent
! #ifdef COMPAT_FREEBSD
! #ifdef EXEC_AOUT
! 		  && p->p_emul != &emul_freebsd
! #endif /* EXEC_AOUT */
! #ifdef EXEC_ELF32
! 		  && p->p_emul != &emul_freebsd_elf32
! #endif /* EXEC_ELF32 */
  #endif /* COMPAT_FREEBSD */
+ 		   )
+ 			break;
  		code = fuword(params + _QUAD_LOWWORD * sizeof(int));
  		params += sizeof(quad_t);
  		break;
*** compat/freebsd/freebsd_exec.c-ORIG	Sun Jan 24 02:48:11 1999
--- compat/freebsd/freebsd_exec.c	Tue Jan 26 03:21:05 1999
***************
*** 30,52 ****
   * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   */
  
  #include <sys/param.h>
  #include <sys/systm.h>
  #include <sys/proc.h>
  #include <sys/malloc.h>
  #include <sys/vnode.h>
  #include <sys/exec.h>
  #include <sys/resourcevar.h>
  #include <vm/vm.h>
  
  #include <machine/freebsd_machdep.h>
  
- #include <compat/freebsd/freebsd_syscall.h>
  #include <compat/freebsd/freebsd_exec.h>
  
  extern struct sysent freebsd_sysent[];
  extern char *freebsd_syscallnames[];
  
  struct emul emul_freebsd = {
  	"freebsd",
  	NULL,
--- 30,66 ----
   * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   */
  
+ #include "opt_execfmt.h"
+ 
  #include <sys/param.h>
  #include <sys/systm.h>
  #include <sys/proc.h>
  #include <sys/malloc.h>
  #include <sys/vnode.h>
  #include <sys/exec.h>
+ #ifdef EXEC_ELF32
+ #ifndef ELFSIZE
+ #define ELFSIZE 32
+ #endif /* #ifndef ELFSIZE */
+ #include <sys/exec_elf.h>
+ #endif /* #ifdef EXEC_ELF32 */
  #include <sys/resourcevar.h>
  #include <vm/vm.h>
  
+ #include <machine/cpu.h>
+ #include <machine/reg.h>
+ 
  #include <machine/freebsd_machdep.h>
  
  #include <compat/freebsd/freebsd_exec.h>
+ #include <compat/freebsd/freebsd_util.h>
+ 
+ #include <compat/freebsd/freebsd_syscall.h>
  
  extern struct sysent freebsd_sysent[];
  extern char *freebsd_syscallnames[];
  
+ #ifdef EXEC_AOUT
  struct emul emul_freebsd = {
  	"freebsd",
  	NULL,
***************
*** 110,112 ****
--- 124,227 ----
  
  	return error;
  }
+ #endif /* #ifdef EXEC_AOUT */
+ 
+ #ifdef EXEC_ELF32
+ 
+ struct emul ELFNAMEEND(emul_freebsd) = {
+ 	"freebsd",
+ 	NULL,
+ 	freebsd_sendsig,
+ 	FREEBSD_SYS_syscall,
+ 	FREEBSD_SYS_MAXSYSCALL,
+ 	freebsd_sysent,
+ 	freebsd_syscallnames,
+ 	FREEBSD_ELF_AUX_ARGSIZ,
+ 	ELFNAME(copyargs),
+ 	freebsd_setregs,
+ 	freebsd_sigcode,
+ 	freebsd_esigcode,
+ };
+ 
+ int
+ ELFNAME2(freebsd,probe)(p, epp, eh, itp, pos)
+ 	struct proc *p;
+ 	struct exec_package *epp;
+ 	Elf_Ehdr *eh;
+ 	char *itp;
+ 	Elf_Addr *pos;
+ {
+ 	int error;
+ 	size_t i;
+ 	size_t phsize;
+ 	Elf_Phdr *ph;
+ 	Elf_Phdr *ephp;
+ 	Elf_Note *np;
+ 	char *bp;
+ 
+         static const char wantBrand[] = FREEBSD_ELF_BRAND_STRING;
+         static const char wantInterp[] = FREEBSD_ELF_INTERP_PREFIX_STRING;
+ 
+         /* Insist that the executable have a brand, and that it be "FreeBSD" */
+ #ifndef EI_BRAND
+ #define EI_BRAND 8
+ #endif
+         if (eh->e_ident[EI_BRAND] == '\0'
+ 	  || strcmp(&eh->e_ident[EI_BRAND], wantBrand))
+ 		return ENOEXEC;
+ 
+ 	i = eh->e_phnum;
+ 	if (i != 0) {
+ 		phsize = i * sizeof(Elf_Phdr);
+ 		ph = (Elf_Phdr *) malloc(phsize, M_TEMP, M_WAITOK);
+ 		if ((error = ELFNAME(read_from)(p, epp->ep_vp, eh->e_phoff,
+ 						(caddr_t) ph, phsize)) == 0) {
+ 			ephp = &ph[0];
+ 			do {
+ 				if (ephp->p_type == Elf_pt_interp) {
+ 					/* Check for "legal" intepreter name. */
+ 					if (ephp->p_filesz < sizeof wantInterp)
+ 						error = ENOEXEC;
+ 					else {
+ 						np = (Elf_Note *)
+ 							malloc(ephp->p_filesz+1,
+ 						       M_TEMP, M_WAITOK);
+ 						if (((error =
+ 						      ELFNAME(read_from)(p,
+ 								epp->ep_vp,
+ 								ephp->p_offset,
+ 								(caddr_t)np,
+ 							ephp->p_filesz)) == 0))
+ 							if (strncmp((char *) np,
+ 								    wantInterp,
+ 						    sizeof wantInterp - 1))
+ 								error = ENOEXEC;
+ 						free(np, M_TEMP);
+ 					}
+ 					break;
+ 				}
+ 				ephp++;
+ 			} while ( --i );
+ 		}
+ 		free(ph, M_TEMP);
+ 
+ 		if (error)
+ 			return error;
+ 	}
+ 
+ 	if (itp[0]) {
+ 		if ((error = emul_find(p, NULL, freebsd_emul_path,
+ 				       itp, &bp, 0)))
+ 			return error;
+ 		if ((error = copystr(bp, itp, MAXPATHLEN, &i)))
+ 			return error;
+ 		free(bp, M_TEMP);
+ 	}
+ 	epp->ep_emul = &ELFNAMEEND(emul_freebsd);
+ 	*pos = ELF_NO_ADDR;
+ #ifdef DEBUG_FREEBSD_ELF
+ 	printf("freebsd_elf32_probe: returning 0\n");
+ #endif
+ 	return 0;
+ }
+ #endif /* #ifdef EXEC_ELF32 */
*** compat/freebsd/freebsd_exec.h-ORIG	Sat Jan 24 04:54:01 1998
--- compat/freebsd/freebsd_exec.h	Sun Jan 24 04:38:00 1999
***************
*** 99,102 ****
--- 99,112 ----
  
  extern char freebsd_sigcode[], freebsd_esigcode[];
  
+ #ifdef EXEC_ELF32
+ #define FREEBSD_ELF_AUX_ARGSIZ (sizeof(AuxInfo) * 8 / sizeof(char *))
+ 
+ #define FREEBSD_ELF_BRAND_STRING "FreeBSD"
+ #define FREEBSD_ELF_INTERP_PREFIX_STRING "/usr/libexec/ld-elf.so"
+ 
+ int freebsd_elf32_probe __P((struct proc *, struct exec_package *, Elf32_Ehdr *,
+     char *, Elf32_Addr *));
+ #endif /* #ifdef EXEC_ELF32 */
+ 
  #endif /* !_FREEBSD_EXEC_H */
*** compat/freebsd/syscalls.master-ORIG	Fri Dec 11 04:16:35 1998
--- compat/freebsd/syscalls.master	Sun Jan 24 03:42:13 1999
***************
*** 136,142 ****
  			    struct sigaltstack13 *oss); }
  54	STD		{ int freebsd_sys_ioctl(int fd, u_long com, \
  			    caddr_t data); }
! 55	NOARGS		{ int sys_reboot(int opt); }
  56	STD		{ int freebsd_sys_revoke(char *path); }
  57	STD		{ int freebsd_sys_symlink(char *path, char *link); }
  58	STD		{ int freebsd_sys_readlink(char *path, char *buf, \
--- 136,142 ----
  			    struct sigaltstack13 *oss); }
  54	STD		{ int freebsd_sys_ioctl(int fd, u_long com, \
  			    caddr_t data); }
! 55	NOARGS		{ int sys_reboot(int opt); } oreboot
  56	STD		{ int freebsd_sys_revoke(char *path); }
  57	STD		{ int freebsd_sys_symlink(char *path, char *link); }
  58	STD		{ int freebsd_sys_readlink(char *path, char *buf, \
***************
*** 393,402 ****
  #else
  205	UNIMPL
  #endif
! 206	UNIMPL
! 207	UNIMPL
! 208	UNIMPL
! 209	UNIMPL
  ;
  ; Syscalls 210-219 are reserved for dynamically loaded syscalls
  ;
--- 393,407 ----
  #else
  205	UNIMPL
  #endif
! 206	NOARGS		{ int sys_futimes(int fd, const struct timeval *tptr); }
! 207	NOARGS		{ pid_t sys_getpgid(pid_t pid); }
! #if 0
! 208	NOARGS		{ int sys_reboot(int opt, char *bootstr); }
! #else
! 208	UNIMPL		newreboot
! #endif
! 209	NOARGS		{ int sys_poll(struct pollfd *fds, u_int nfds, \
! 			    int timeout); }
  ;
  ; Syscalls 210-219 are reserved for dynamically loaded syscalls
  ;
***************
*** 413,439 ****
  ;
  ; Syscalls 220-239 are reserved for syscalls imported from NetBSD
  ;
! 220	UNIMPL
! 221	UNIMPL
! 222	UNIMPL
! 223	UNIMPL
! 224	UNIMPL
! 225	UNIMPL
! 226	UNIMPL
! 227	UNIMPL
! 228	UNIMPL
! 229	UNIMPL
! 230	UNIMPL
! 231	UNIMPL
! 232	UNIMPL
! 233	UNIMPL
! 234	UNIMPL
! 235	UNIMPL
! 236	UNIMPL
! 237	UNIMPL
! 238	UNIMPL
! 239	UNIMPL
! 240	UNIMPL
  241	UNIMPL
  242	UNIMPL
  243	UNIMPL
--- 418,477 ----
  ;
  ; Syscalls 220-239 are reserved for syscalls imported from NetBSD
  ;
! #ifdef SYSVSEM
! 220	NOARGS		{ int sys___semctl(int semid, int semnum, int cmd, \
! 			    union semun *arg); }
! 221	NOARGS		{ int sys_semget(key_t key, int nsems, int semflg); }
! 222	NOARGS		{ int sys_semop(int semid, struct sembuf *sops, \
! 			    u_int nsops); }
! 223	NOARGS		{ int sys_semconfig(int flag); }
! #else
! 220	UNIMPL		semctl
! 221	UNIMPL		semget
! 222	UNIMPL		semop
! 223	UNIMPL		semconfig
! #endif
! #ifdef SYSVMSG
! 224	NOARGS		{ int sys_msgctl(int msqid, int cmd, \
! 			    struct msqid_ds *buf); }
! 225	NOARGS		{ int sys_msgget(key_t key, int msgflg); }
! 226	NOARGS		{ int sys_msgsnd(int msqid, void *msgp, size_t msgsz, \
! 			    int msgflg); }
! 227	NOARGS		{ int sys_msgrcv(int msqid, void *msgp, size_t msgsz, \
! 			    long msgtyp, int msgflg); }
! #else
! 224	UNIMPL		msgctl
! 225	UNIMPL		msgget
! 226	UNIMPL		msgsnd
! 227	UNIMPL		msgrcv
! #endif
! #ifdef SYSVSHM
! 228	NOARGS		{ int sys_shmat(int shmid, void *shmaddr, int shmflg); }
! 229	NOARGS		{ int sys_shmctl(int shmid, int cmd, \
! 			    struct shmid_ds *buf); }
! 230	NOARGS		{ int sys_shmdt(void *shmaddr); }
! 231	NOARGS		{ int sys_shmget(key_t key, int size, int shmflg); }
! #else
! 228	UNIMPL		shmat
! 229	UNIMPL		shmctl
! 230	UNIMPL		shmdt
! 231	UNIMPL		shmget
! #endif
! ;
! ; XXXX
! 232	NOARGS		{ int sys_clock_gettime(clockid_t clock_id, \
! 			    struct timespec *tp); }
! 233	NOARGS		{ int sys_clock_settime(clockid_t clock_id, \
! 			    const struct timespec *tp); }
! 234	NOARGS		{ int sys_clock_getres(clockid_t clock_id, \
! 			    struct timespec *tp); }
! 235	UNIMPL		timer_create
! 236	UNIMPL		timer_delete
! 237	UNIMPL		timer_settime
! 238	UNIMPL		timer_gettime
! 239	UNIMPL		timer_getoverrun
! 240	NOARGS		{ int sys_nanosleep(const struct timespec *rqtp, \
! 			    struct timespec *rmtp); }
  241	UNIMPL
  242	UNIMPL
  243	UNIMPL
***************
*** 443,451 ****
  247	UNIMPL
  248	UNIMPL
  249	UNIMPL
! 250	UNIMPL
! 251	UNIMPL
! 252	UNIMPL
  253	STD		{ int freebsd_sys_issetugid(void); }
  254	STD		{ int freebsd_sys_lchown(char *path, int uid, \
  			    int gid); }
--- 481,576 ----
  247	UNIMPL
  248	UNIMPL
  249	UNIMPL
! ; syscall numbers initially used in OpenBSD
! 250	UNIMPL		minherit
! 251	UNIMPL		rfork
! 252	UNIMPL		openbsd_poll
  253	STD		{ int freebsd_sys_issetugid(void); }
  254	STD		{ int freebsd_sys_lchown(char *path, int uid, \
  			    int gid); }
+ 255	UNIMPL
+ 256	UNIMPL
+ 257	UNIMPL
+ 258	UNIMPL
+ 259	UNIMPL
+ 260	UNIMPL
+ 261	UNIMPL
+ 262	UNIMPL
+ 263	UNIMPL
+ 264	UNIMPL
+ 265	UNIMPL
+ 266	UNIMPL
+ 267	UNIMPL
+ 268	UNIMPL
+ 269	UNIMPL
+ 270	UNIMPL
+ 271	UNIMPL
+ 272	NOARGS		{ int sys_getdents(int fd, char *buf, size_t count); }
+ 273	UNIMPL
+ 274	NOARGS		{ int sys_lchmod(const char *path, mode_t mode); }
+ 275	NOARGS		{ int sys_lchown(const char *path, uid_t uid, \
+ 			    gid_t gid); } netbsd_lchown
+ 276	NOARGS		{ int sys_lutimes(const char *path, \
+ 			    const struct timeval *tptr); }
+ 277	NOARGS		{ int sys___msync13(void *addr, size_t len, int flags); }
+ 278	NOARGS		{ int sys___stat13(const char *path, struct stat *ub); }
+ 279	NOARGS		{ int sys___fstat13(int fd, struct stat *sb); }
+ 280	NOARGS		{ int sys___lstat13(const char *path, struct stat *ub);}
+ 281	UNIMPL
+ 282	UNIMPL
+ 283	UNIMPL
+ 284	UNIMPL
+ 285	UNIMPL
+ 286	UNIMPL
+ 287	UNIMPL
+ 288	UNIMPL
+ 289	UNIMPL
+ 290	UNIMPL
+ 291	UNIMPL
+ 292	UNIMPL
+ 293	UNIMPL
+ 294	UNIMPL
+ 295	UNIMPL
+ 296	UNIMPL
+ 297	UNIMPL
+ 298	UNIMPL
+ 299	UNIMPL
+ ; syscall numbers for FreeBSD
+ 300	UNIMPL		modnext
+ 301	UNIMPL		modstat
+ 302	UNIMPL		modfnext
+ 303	UNIMPL		modfind
+ 304	UNIMPL		kldload
+ 305	UNIMPL		kldunload
+ 306	UNIMPL		kldfind
+ 307	UNIMPL		kldnext
+ 308	UNIMPL		kldstat
+ 309	UNIMPL		kldfirstmod
+ 310	UNIMPL		getsid
+ 311	UNIMPL		setresuid
+ 312	UNIMPL		setresgid
+ 313	UNIMPL		signanosleep
+ 314	UNIMPL		aio_return
+ 315	UNIMPL		aio_suspend
+ 316	UNIMPL		aio_cancel
+ 317	UNIMPL		aio_error
+ 318	UNIMPL		aio_read
+ 319	UNIMPL		aio_write
+ 320	UNIMPL		lio_listio
+ 321	UNIMPL		yield
+ 322	UNIMPL		thr_sleep
+ 323	UNIMPL		thr_wakeup
+ 324	UNIMPL		mlockall
+ 325	UNIMPL		munlockall
+ 326	UNIMPL		__getcwd
+ 327	UNIMPL		sched_setparam
+ 328	UNIMPL		sched_getparam
+ 329	UNIMPL		sched_setscheduler
+ 330	UNIMPL		sched_getscheduler
+ 331	UNIMPL		sched_yield
+ 332	UNIMPL		sched_get_priority_max
+ 333	UNIMPL		sched_get_priority_min
+ 334	UNIMPL		sched_rr_get_interval
+ 335	UNIMPL		utrace
+ 336	UNIMPL		sendfile
+ 337	UNIMPL		kldsym
*** kern/exec_elf32.c-ORIG	Wed Jan  6 04:21:29 1999
--- kern/exec_elf32.c	Sun Jan 24 02:44:51 1999
***************
*** 71,76 ****
--- 71,77 ----
  #include "opt_compat_linux.h"
  #include "opt_compat_ibcs2.h"
  #include "opt_compat_svr4.h"
+ #include "opt_compat_freebsd.h"
  
  #include <sys/param.h>
  #include <sys/systm.h>
***************
*** 107,112 ****
--- 108,117 ----
  #include <compat/ibcs2/ibcs2_exec.h>
  #endif
  
+ #ifdef COMPAT_FREEBSD
+ #include <compat/freebsd/freebsd_exec.h>
+ #endif
+ 
  int	ELFNAME(check_header) __P((Elf_Ehdr *, int));
  int	ELFNAME(load_file) __P((struct proc *, struct exec_package *, char *,
  	    struct exec_vmcmd_set *, u_long *, struct elf_args *, Elf_Addr *));
***************
*** 145,150 ****
--- 150,158 ----
  int (*ELFNAME(probe_funcs)[]) __P((struct proc *, struct exec_package *,
      Elf_Ehdr *, char *, Elf_Addr *)) = {
  	ELFNAME2(netbsd,probe),
+ #if defined(COMPAT_FREEBSD) && (ELFSIZE == 32)
+ 	ELFNAME2(freebsd,probe),		/* XXX not 64-bit safe */
+ #endif
  #if defined(COMPAT_LINUX)
  	ELFNAME2(linux,probe),
  #endif
>Audit-Trail:
>Unformatted: