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: