AT_SUN_EXECNAME support

. vfs: pass execname in aux vectors
	. ld.elf_so: use this to expand $ORIGIN
	. this requires the executable to reserve more
	  space at exec() calling time
This commit is contained in:
Ben Gras 2012-04-18 16:32:38 +02:00
parent b41df2eb0d
commit 755102d67f
6 changed files with 50 additions and 16 deletions

View file

@ -546,7 +546,9 @@
#define PMEXEC_FLAGS m1_i3 /* PMEF_* */
#define PMEF_AUXVECTORS 20
#define PMEF_EXECNAMELEN1 256
#define PMEF_AUXVECTORSPACE 0x01 /* space for PMEF_AUXVECTORS on stack */
#define PMEF_EXECNAMESPACE1 0x02 /* space for PMEF_EXECNAMELEN1 execname */
/* Flags for PR_FORK_FLAGS. */
#define PFF_VMINHIBIT 0x01 /* Don't schedule until release by VM. */

View file

@ -24,6 +24,7 @@ int execve(const char *path, char * const *argv, char * const *envp)
char **vp;
char *sp;
size_t argc;
int extra;
int vectors;
size_t frame_size;
size_t string_off;
@ -63,8 +64,9 @@ int execve(const char *path, char * const *argv, char * const *envp)
*/
vectors = sizeof(argc) + sizeof(*ap) + sizeof(*ep) +
sizeof(AuxInfo) * PMEF_AUXVECTORS;
frame_size+= vectors;
string_off+= vectors;
extra = vectors + PMEF_EXECNAMELEN1;
frame_size+= extra;
string_off+= extra;
/* Align. */
frame_size= (frame_size + sizeof(char *) - 1) & ~(sizeof(char *) - 1);
@ -116,8 +118,10 @@ int execve(const char *path, char * const *argv, char * const *envp)
m.m1_p1 = (char *) __UNCONST(path);
m.m1_p2 = frame;
/* Tell PM/VFS we have left space for the aux vectors */
m.PMEXEC_FLAGS = PMEF_AUXVECTORSPACE;
/* Tell PM/VFS we have left space for the aux vectors
* and executable name
*/
m.PMEXEC_FLAGS = PMEF_AUXVECTORSPACE | PMEF_EXECNAMESPACE1;
(void) _syscall(PM_PROC_NR, EXEC, &m);

View file

@ -73,9 +73,6 @@ static int mib[3][2] = {
static size_t
expand(char *buf, const char *execname, int what, size_t bl)
{
#ifdef __minix
return 0;
#else
const char *p, *ep;
char *bp = buf;
size_t len;
@ -93,6 +90,7 @@ expand(char *buf, const char *execname, int what, size_t bl)
xerr(1, "bad execname `%s' in AUX vector", execname);
break;
#ifndef __minix
case 3: /* OSNAME */
case 4: /* OSREL */
case 5: /* PLATFORM */
@ -103,6 +101,7 @@ expand(char *buf, const char *execname, int what, size_t bl)
}
ep = (p = name) + len - 1;
break;
#endif
default:
return 0;
}
@ -111,7 +110,6 @@ expand(char *buf, const char *execname, int what, size_t bl)
*bp++ = *p++, bl--;
return bp - buf;
#endif
}

View file

@ -58,7 +58,7 @@ static int read_seg(struct vnode *vp, off_t off, int proc_e, int seg,
static int load_aout(struct exec_info *execi);
static int load_elf(struct exec_info *execi);
static int stack_prepare_elf(struct exec_info *execi,
char *curstack, size_t *frame_len, int *extrabase);
char *curstack, size_t *frame_len, vir_bytes *vsp, int *extrabase);
static int map_header(struct exec_info *execi);
#define PTRSIZE sizeof(char *) /* Size of pointers in argv[] and envp[]. */
@ -66,7 +66,7 @@ static int map_header(struct exec_info *execi);
/* Array of loaders for different object file formats */
typedef int (*exechook_t)(struct exec_info *execpackage);
typedef int (*stackhook_t)(struct exec_info *execi, char *curstack,
size_t *frame_len, int *extrabase);
size_t *frame_len, vir_bytes *, int *extrabase);
struct exec_loaders {
exechook_t load_object; /* load executable into memory */
stackhook_t setup_stack; /* prepare stack before argc and argv push */
@ -283,6 +283,9 @@ int pm_exec(endpoint_t proc_e, vir_bytes path, size_t path_len,
FAILCHECK(r);
}
/* Remember it */
strcpy(execi.execname, finalexec);
/* The executable we need to execute first (loader)
* is in elf_interpreter, and has to be in fullpath to
* be looked up
@ -306,11 +309,10 @@ int pm_exec(endpoint_t proc_e, vir_bytes path, size_t path_len,
*pc = execi.pc;
/* call a stack-setup function if this executable type wants it */
vsp = execi.stack_top;
if(makestack) FAILCHECK(makestack(&execi, mbuf, &frame_len, &extrabase));
vsp = execi.stack_top - frame_len;
if(makestack) FAILCHECK(makestack(&execi, mbuf, &frame_len, &vsp, &extrabase));
/* Patch up stack and copy it from VFS to new core image. */
vsp -= frame_len;
patch_ptr(mbuf, vsp + extrabase);
FAILCHECK(sys_datacopy(SELF, (vir_bytes) mbuf, proc_e, (vir_bytes) vsp,
(phys_bytes)frame_len));
@ -390,9 +392,10 @@ static int load_aout(struct exec_info *execi)
return(r);
}
static int stack_prepare_elf(struct exec_info *execi, char *frame, size_t *framelen, int *extrabase)
static int stack_prepare_elf(struct exec_info *execi, char *frame, size_t *framelen,
vir_bytes *newsp, int *extrabase)
{
AuxInfo *a;
AuxInfo *a, *term;
Elf_Ehdr *elf_header;
int nulls;
char **mysp = (char **) frame,
@ -438,6 +441,7 @@ static int stack_prepare_elf(struct exec_info *execi, char *frame, size_t *frame
if(*framelen + extrabytes >= ARG_MAX)
return ENOMEM;
*framelen += extrabytes;
*newsp -= extrabytes;
*extrabase += extrabytes;
memmove(f+extrabytes, f, remain);
memset(f, 0, extrabytes);
@ -457,9 +461,34 @@ static int stack_prepare_elf(struct exec_info *execi, char *frame, size_t *frame
AUXINFO(AT_PAGESZ, PAGE_SIZE);
AUXINFO(AT_EXECFD, execi->elf_main_fd);
/* This is where we add the AT_NULL */
term = a;
/* Always terminate with AT_NULL */
AUXINFO(AT_NULL, 0);
/* Empty space starts here, if any. */
if((execi->userflags & PMEF_EXECNAMESPACE1)
&& strlen(execi->execname) < PMEF_EXECNAMELEN1) {
char *spacestart;
vir_bytes userp;
/* Make space for the real closing AT_NULL entry. */
AUXINFO(AT_NULL, 0);
/* Empty space starts here; we can put the name here. */
spacestart = (char *) a;
strcpy(spacestart, execi->execname);
/* What will the address of the string for the user be */
userp = *newsp + (spacestart-frame);
/* Move back to where the AT_NULL is */
a = term;
AUXINFO(AT_SUN_EXECNAME, userp);
AUXINFO(AT_NULL, 0);
}
return OK;
}

View file

@ -23,6 +23,7 @@ struct exec_info {
vir_bytes elf_phdr; /* Program header location */
vir_bytes elf_base; /* Userland addr load address */
int elf_main_fd; /* Dyn: FD of main program execuatble */
char execname[PATH_MAX]; /* Full executable invocation */
};
#endif /* !_VFS_EXEC_H_ */

View file

@ -807,7 +807,7 @@ static void service_pm_postponed(void)
stack_frame_len = (size_t) job_m_in.PM_FRAME_LEN;
r = pm_exec(proc_e, exec_path, exec_path_len, stack_frame,
stack_frame_len, &pc, &newsp, m_in.PM_EXECFLAGS);
stack_frame_len, &pc, &newsp, job_m_in.PM_EXECFLAGS);
/* Reply status to PM */
m_out.m_type = PM_EXEC_REPLY;