From owner-freebsd-bugs Tue Mar 26 19:30:11 1996 Return-Path: owner-bugs Received: (from root@localhost) by freefall.freebsd.org (8.7.3/8.7.3) id TAA10589 for bugs-outgoing; Tue, 26 Mar 1996 19:30:11 -0800 (PST) Received: (from gnats@localhost) by freefall.freebsd.org (8.7.3/8.7.3) id TAA10581 Tue, 26 Mar 1996 19:30:06 -0800 (PST) Resent-Date: Tue, 26 Mar 1996 19:30:06 -0800 (PST) Resent-Message-Id: <199603270330.TAA10581@freefall.freebsd.org> Resent-From: gnats (GNATS Management) Resent-To: freebsd-bugs Resent-Reply-To: FreeBSD-gnats@freefall.FreeBSD.org, smpatel@xi.dorm.umd.edu Received: from xi.dorm.umd.edu (xi.dorm.umd.edu [129.2.152.45]) by freefall.freebsd.org (8.7.3/8.7.3) with ESMTP id TAA10164 for ; Tue, 26 Mar 1996 19:27:49 -0800 (PST) Received: (from smpatel@localhost) by xi.dorm.umd.edu (8.7.4/8.6.12) id WAA00525; Tue, 26 Mar 1996 22:27:47 -0500 (EST) Message-Id: <199603270327.WAA00525@xi.dorm.umd.edu> Date: Tue, 26 Mar 1996 22:27:47 -0500 (EST) From: Sujal Patel Reply-To: smpatel@xi.dorm.umd.edu To: FreeBSD-gnats-submit@freebsd.org X-Send-Pr-Version: 3.2 Subject: kern/1102: Differentiation of FreeBSD & Linux ELF binaries [patch] Sender: owner-bugs@freebsd.org X-Loop: FreeBSD.org Precedence: bulk >Number: 1102 >Category: kern >Synopsis: Differentiation of FreeBSD & Linux ELF binaries [patch] >Confidential: no >Severity: serious >Priority: high >Responsible: freebsd-bugs >State: open >Class: change-request >Submitter-Id: current-users >Arrival-Date: Tue Mar 26 19:30:03 PST 1996 >Last-Modified: >Originator: Sujal Patel >Organization: Sujal >Release: FreeBSD 2.2-CURRENT i386 >Environment: -current >Description: Since the ELF format provides no way to tell the difference between FreeBSD, SysV, and Linux ELF binaries, we need to devise a way to set the correct compatibility sysvec for ELF binaries. Dynamic bins work fine, but static ELF binaries are always assumed to be FreeBSD (therefore Linux ELF binaries do not work in -current). I've heard / thought of 3 possible fixes: 1. Use a wrapper program that will pass in the sysvec to use when running a binary. I.E. you'd need to invoke a static ELF binary with something like "compat -linux linux.helloworld.elf.static". This is pretty messy IMO. 2. Use one of the unused bytes in the ELF e_ident to store an "OS Type". The problem with this is that you'd need to alter a Linux ELF binary to add the "OS Type". While this wouldn't break anything, it's very messy. 3. Follow the "interp" sections hints (current behavior) unless the environment variable COMPAT_SYSVEC exists. If the variable exists, it overrides the sysvec in the "interp" section. This means that we can now invoke Linux ELF binaries by: (export COMPAT_SYSVEC=linux; linux.helloworld.elf.static) I think solution #3 would be the cleanest way to do this... The patch below will implement this solution. It works great here. >How-To-Repeat: >Fix: This implements solution #3 from above. Valid values for the COMPAT_SYSVEC environment variable are currently "freebsd" and "linux". Don't forget to recompile the linux LKM since this edits a header file. diff -ur ./i386/linux/linux_sysvec.c /usr/src/sys/i386/linux/linux_sysvec.c --- ./i386/linux/linux_sysvec.c Tue Mar 26 21:58:57 1996 +++ /usr/src/sys/i386/linux/linux_sysvec.c Tue Mar 26 21:02:37 1996 @@ -405,6 +405,7 @@ Elf32_Interp_info linux_interp = { &elf_linux_sysvec, "/lib/ld-linux.so.1", + "linux", "/compat/linux" }; diff -ur ./kern/imgact_elf.c /usr/src/sys/kern/imgact_elf.c --- ./kern/imgact_elf.c Tue Mar 26 22:00:55 1996 +++ /usr/src/sys/kern/imgact_elf.c Tue Mar 26 21:54:35 1996 @@ -92,6 +92,7 @@ static Elf32_Interp_info freebsd_interp = { &elf_freebsd_sysvec, "/usr/libexec/ld-elf.so.1", + "freebsd", "" }; static Elf32_Interp_info *interp_list[MAX_INTERP] = { @@ -475,6 +476,8 @@ u_long addr, entry = 0, proghdr = 0; int error, i, header_size = 0, interp_len = 0; char *interp = NULL; + char path[MAXPATHLEN]; + char *sp; /* * Do we have a valid ELF header ? @@ -608,31 +611,67 @@ addr = 2*MAXDSIZ; /* May depend on OS type XXX */ - if (interp) { - char path[MAXPATHLEN]; + /* + * See if the user wants to override the sysvec with the sysvec + * in the COMPAT_SYSVEC environment variable + */ + sp = imgp->stringbase; + + for (i = 0; i < imgp->argc; i++) { + while (*sp++); /* Constructed by kernel, should be valid */ + } + + for (i = 0; i < imgp->envc; i++) { + while (*sp++); /* Constructed by kernel, should be valid */ + + if (bcmp (sp, "COMPAT_SYSVEC=", 13) == 0) { + sp += 14; /* sp points to the osname */ + break; + } + } + + if (*sp == NULL) + sp = NULL; + else + UPRINTF ("sysvec %s requested by user\n", sp); + + if (interp || sp) { /* * So which kind of ELF binary do we have at hand * FreeBSD, SVR4 or Linux ?? */ for (i=0; ipath)) { - imgp->proc->p_sysent = - interp_list[i]->sysvec; - strcpy(path, interp_list[i]->emul_path); - strcat(path, interp_list[i]->path); - UPRINTF("interpreter=<%s> %s\n", - interp_list[i]->path, - interp_list[i]->emul_path); - break; - } - } + if (interp_list[i] == NULL) + continue; + + /* User's sysvec always overrides the interp section */ + if (sp && (strcmp(sp, interp_list[i]->osname))) + continue; + + if (interp && (strcmp(interp, interp_list[i]->path))) + continue; + + imgp->proc->p_sysent = interp_list[i]->sysvec; + strcpy(path, interp_list[i]->emul_path); + strcat(path, interp_list[i]->path); + UPRINTF("interpreter=<%s> %s\n", interp_list[i]->path, + interp_list[i]->emul_path); + break; } if (i == MAX_INTERP) { - uprintf("ELF interpreter %s not known\n", interp); + if (sp == 0) { + uprintf("ELF interpreter %s not known\n", + interp); + } else { + uprintf("COMPAT_SYSVEC %s not known\n", + sp); + } error = ENOEXEC; goto fail; } + } + + if (interp) { if (error = elf_load_file(imgp->proc, path, &addr, /* XXX */ diff -ur ./sys/imgact_elf.h /usr/src/sys/sys/imgact_elf.h --- ./sys/imgact_elf.h Tue Mar 26 21:59:04 1996 +++ /usr/src/sys/sys/imgact_elf.h Tue Mar 26 21:01:30 1996 @@ -202,6 +202,7 @@ typedef struct { struct sysentvec *sysvec; char *path; + char *osname; /* OS name for user specified override */ char *emul_path; } Elf32_Interp_info; >Audit-Trail: >Unformatted: