Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F108616489
D9030.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
13 KB
Referenced Files
None
Subscribers
None
D9030.diff
View Options
Index: include/unistd.h
===================================================================
--- include/unistd.h
+++ include/unistd.h
@@ -431,6 +431,7 @@
int faccessat(int, const char *, int, int);
int fchownat(int, const char *, uid_t, gid_t, int);
int fexecve(int, char *const [], char *const []);
+int ffexecve(int, int, char *const [], char *const []);
int linkat(int, const char *, int, const char *, int);
ssize_t readlinkat(int, const char * __restrict, char * __restrict, size_t);
int symlinkat(const char *, int, const char *);
Index: lib/libc/sys/Makefile.inc
===================================================================
--- lib/libc/sys/Makefile.inc
+++ lib/libc/sys/Makefile.inc
@@ -366,7 +366,8 @@
cpuset.2 cpuset_setid.2
MLINKS+=cpuset_getaffinity.2 cpuset_setaffinity.2
MLINKS+=dup.2 dup2.2
-MLINKS+=execve.2 fexecve.2
+MLINKS+=execve.2 fexecve.2 \
+ execve.2 ffexecve.2
MLINKS+=extattr_get_file.2 extattr.2 \
extattr_get_file.2 extattr_delete_fd.2 \
extattr_get_file.2 extattr_delete_file.2 \
Index: lib/libc/sys/execve.2
===================================================================
--- lib/libc/sys/execve.2
+++ lib/libc/sys/execve.2
@@ -33,7 +33,8 @@
.Os
.Sh NAME
.Nm execve ,
-.Nm fexecve
+.Nm fexecve,
+.Nm ffexecve
.Nd execute a file
.Sh LIBRARY
.Lb libc
@@ -43,6 +44,8 @@
.Fn execve "const char *path" "char *const argv[]" "char *const envp[]"
.Ft int
.Fn fexecve "int fd" "char *const argv[]" "char *const envp[]"
+.Ft int
+.Fn ffexecve "int interp" "int fd" "char *const argv[]" "char *const envp[]"
.Sh DESCRIPTION
The
.Fn execve
@@ -62,6 +65,15 @@
.Fa fd
instead of a
.Fa path .
+The
+.Fn ffexecve
+system call is equivalent to
+.Fn fexecve
+except that the run-time linker for the file is specified explicitly
+by the file descriptor
+.Fa interp
+instead of implicitly via the kernel's default logic
+(e.g., using the run-time linker specified in an ELF program header).
This file is either an executable object file,
or a file of data for an interpreter.
An executable object file consists of an identifying header,
Index: sys/compat/freebsd32/syscalls.master
===================================================================
--- sys/compat/freebsd32/syscalls.master
+++ sys/compat/freebsd32/syscalls.master
@@ -1084,3 +1084,5 @@
id_t id, \
const struct vm_domain_policy *policy); }
550 AUE_FSYNC NOPROTO { int fdatasync(int fd); }
+551 AUE_NULL STD { int ffexecve(int rtld, int bin, char **argv, \
+ char **envv); }
Index: sys/kern/capabilities.conf
===================================================================
--- sys/kern/capabilities.conf
+++ sys/kern/capabilities.conf
@@ -176,6 +176,7 @@
## such as disallowing privilege escalation.
##
fexecve
+ffexecve
##
## Allow flock(2), subject to capability rights.
Index: sys/kern/imgact_aout.c
===================================================================
--- sys/kern/imgact_aout.c
+++ sys/kern/imgact_aout.c
@@ -166,6 +166,14 @@
int error;
/*
+ * The a.out image activator doesn't support an explicit interpreter
+ * (or any interpreter, for that matter).
+ */
+ if (imgp->args->interpreter != -1) {
+ return (ENOEXEC);
+ }
+
+ /*
* Linux and *BSD binaries look very much alike,
* only the machine id is different:
* 0x64 for Linux, 0x86 for *BSD, 0x00 for BSDI.
Index: sys/kern/imgact_binmisc.c
===================================================================
--- sys/kern/imgact_binmisc.c
+++ sys/kern/imgact_binmisc.c
@@ -583,6 +583,13 @@
struct sbuf *sname;
char *s, *d;
+ /*
+ * This image activator doesn't support an explicit interpreter.
+ */
+ if (imgp->args->interpreter != -1) {
+ return (EINVAL);
+ }
+
/* Do we have an interpreter for the given image header? */
sx_slock(&interp_list_sx);
if ((ibe = imgact_binmisc_find_interpreter(image_header)) == NULL) {
Index: sys/kern/imgact_elf.c
===================================================================
--- sys/kern/imgact_elf.c
+++ sys/kern/imgact_elf.c
@@ -89,8 +89,10 @@
static int __elfN(check_header)(const Elf_Ehdr *hdr);
static Elf_Brandinfo *__elfN(get_brandinfo)(struct image_params *imgp,
const char *interp, int interp_name_len, int32_t *osrel);
-static int __elfN(load_file)(struct proc *p, const char *file, u_long *addr,
+static int __elfN(load_file)(struct proc *p, struct vnode *vp, u_long *addr,
u_long *entry, size_t pagesize);
+static int __elfN(load_path)(struct proc *p, const char *path, u_long *addr,
+ u_long *entry, size_t pagesize);
static int __elfN(load_section)(struct image_params *imgp, vm_ooffset_t offset,
caddr_t vmaddr, size_t memsz, size_t filsz, vm_prot_t prot,
size_t pagesize);
@@ -642,17 +644,15 @@
* the entry point for the loaded file.
*/
static int
-__elfN(load_file)(struct proc *p, const char *file, u_long *addr,
+__elfN(load_file)(struct proc *p, struct vnode *vp, u_long *addr,
u_long *entry, size_t pagesize)
{
struct {
- struct nameidata nd;
struct vattr attr;
struct image_params image_params;
} *tempdata;
const Elf_Ehdr *hdr = NULL;
const Elf_Phdr *phdr = NULL;
- struct nameidata *nd;
struct vattr *attr;
struct image_params *imgp;
vm_prot_t prot;
@@ -660,17 +660,7 @@
u_long base_addr = 0;
int error, i, numsegs;
-#ifdef CAPABILITY_MODE
- /*
- * XXXJA: This check can go away once we are sufficiently confident
- * that the checks in namei() are correct.
- */
- if (IN_CAPABILITY_MODE(curthread))
- return (ECAPMODE);
-#endif
-
tempdata = malloc(sizeof(*tempdata), M_TEMP, M_WAITOK);
- nd = &tempdata->nd;
attr = &tempdata->attr;
imgp = &tempdata->image_params;
@@ -683,14 +673,7 @@
imgp->image_header = NULL;
imgp->object = NULL;
imgp->execlabel = NULL;
-
- NDINIT(nd, LOOKUP, LOCKLEAF | FOLLOW, UIO_SYSSPACE, file, curthread);
- if ((error = namei(nd)) != 0) {
- nd->ni_vp = NULL;
- goto fail;
- }
- NDFREE(nd, NDF_ONLY_PNBUF);
- imgp->vp = nd->ni_vp;
+ imgp->vp = vp;
/*
* Check permissions, modes, uid, etc on the file, and "open" it.
@@ -707,9 +690,9 @@
* Also make certain that the interpreter stays the same, so set
* its VV_TEXT flag, too.
*/
- VOP_SET_TEXT(nd->ni_vp);
+ VOP_SET_TEXT(vp);
- imgp->object = nd->ni_vp->v_object;
+ imgp->object = vp->v_object;
hdr = (const Elf_Ehdr *)imgp->image_header;
if ((error = __elfN(check_header)(hdr)) != 0)
@@ -762,17 +745,47 @@
if (imgp->firstpage)
exec_unmap_first_page(imgp);
- if (nd->ni_vp)
- vput(nd->ni_vp);
-
+ vput(vp);
free(tempdata, M_TEMP);
return (error);
}
+/*
+ * Load a file into memory as specified by a path.
+ */
+static int
+__elfN(load_path)(struct proc *p, const char *path, u_long *addr,
+ u_long *entry, size_t pagesize)
+{
+ struct nameidata nd;
+ struct vnode *vp = NULL;
+ int error;
+
+#ifdef CAPABILITY_MODE
+ /*
+ * XXXJA: This check can go away once we are sufficiently confident
+ * that the checks in namei() are correct.
+ */
+ if (IN_CAPABILITY_MODE(curthread))
+ return (ECAPMODE);
+#endif
+
+ NDINIT(&nd, LOOKUP, LOCKLEAF | FOLLOW, UIO_SYSSPACE, path, curthread);
+ error = namei(&nd);
+ vp = nd.ni_vp;
+ NDFREE(&nd, NDF_ONLY_PNBUF);
+ if (error != 0) {
+ return (error);
+ }
+
+ return __elfN(load_file)(p, vp, addr, entry, pagesize);
+}
+
static int
__CONCAT(exec_, __elfN(imgact))(struct image_params *imgp)
{
+ cap_rights_t rights;
struct thread *td;
const Elf_Ehdr *hdr;
const Elf_Phdr *phdr;
@@ -786,7 +799,7 @@
u_long text_size, data_size, total_size, text_addr, data_addr;
u_long seg_size, seg_addr, addr, baddr, et_dyn_addr, entry, proghdr;
int32_t osrel;
- int error, i, n, interp_name_len, have_interp;
+ int error, i, n, interp_fd, interp_name_len, have_interp;
hdr = (const Elf_Ehdr *)imgp->image_header;
@@ -836,6 +849,10 @@
break;
case PT_INTERP:
/* Path to interpreter */
+ if (interp != NULL) {
+ /* ffexecve() is overriding the interpreter */
+ break;
+ }
if (phdr[i].p_filesz > MAXPATHLEN) {
uprintf("Invalid PT_INTERP\n");
error = ENOEXEC;
@@ -1031,12 +1048,32 @@
if (interp != NULL) {
have_interp = FALSE;
VOP_UNLOCK(imgp->vp, 0);
- if (brand_info->emul_path != NULL &&
+ if ((interp_fd = imgp->args->interpreter) != -1) {
+ /* ffexecve() is overriding the interpreter */
+ error = fgetvp_exec(td, interp_fd,
+ cap_rights_init(&rights, CAP_FEXECVE), &imgp->vp);
+ if (error) {
+ uprintf("failed getting interpreter from FD %d",
+ interp_fd);
+ goto ret;
+ }
+
+ error = vn_lock(imgp->vp, LK_SHARED | LK_RETRY);
+ if (error) {
+ goto ret;
+ }
+
+ error = __elfN(load_file)(imgp->proc, imgp->vp, &addr,
+ &imgp->entry_addr, sv->sv_pagesize);
+ if (error == 0)
+ have_interp = TRUE;
+ }
+ if (!have_interp && brand_info->emul_path != NULL &&
brand_info->emul_path[0] != '\0') {
path = malloc(MAXPATHLEN, M_TEMP, M_WAITOK);
snprintf(path, MAXPATHLEN, "%s%s",
brand_info->emul_path, interp);
- error = __elfN(load_file)(imgp->proc, path, &addr,
+ error = __elfN(load_path)(imgp->proc, path, &addr,
&imgp->entry_addr, sv->sv_pagesize);
free(path, M_TEMP);
if (error == 0)
@@ -1045,13 +1082,13 @@
if (!have_interp && newinterp != NULL &&
(brand_info->interp_path == NULL ||
strcmp(interp, brand_info->interp_path) == 0)) {
- error = __elfN(load_file)(imgp->proc, newinterp, &addr,
+ error = __elfN(load_path)(imgp->proc, newinterp, &addr,
&imgp->entry_addr, sv->sv_pagesize);
if (error == 0)
have_interp = TRUE;
}
if (!have_interp) {
- error = __elfN(load_file)(imgp->proc, interp, &addr,
+ error = __elfN(load_path)(imgp->proc, interp, &addr,
&imgp->entry_addr, sv->sv_pagesize);
}
vn_lock(imgp->vp, LK_EXCLUSIVE | LK_RETRY);
Index: sys/kern/imgact_gzip.c
===================================================================
--- sys/kern/imgact_gzip.c
+++ sys/kern/imgact_gzip.c
@@ -76,6 +76,13 @@
struct inflate infl;
struct vmspace *vmspace;
+ /*
+ * This image activator doesn't support an explicit interpreter.
+ */
+ if (imgp->args->interpreter != -1) {
+ return (EINVAL);
+ }
+
/* If these four are not OK, it isn't a gzip file */
if (p[0] != 0x1f)
return -1; /* 0 Simply magic */
Index: sys/kern/imgact_shell.c
===================================================================
--- sys/kern/imgact_shell.c
+++ sys/kern/imgact_shell.c
@@ -107,6 +107,14 @@
struct vattr vattr;
struct sbuf *sname;
+ /*
+ * This image activator doesn't support an explicit interpreter.
+ * TODO(JA): consider adding support for an explicit shell interpreter
+ */
+ if (imgp->args->interpreter != -1) {
+ return (EINVAL);
+ }
+
/* a shell script? */
if (((const short *)image_header)[0] != SHELLMAGIC)
return (-1);
Index: sys/kern/kern_exec.c
===================================================================
--- sys/kern/kern_exec.c
+++ sys/kern/kern_exec.c
@@ -252,6 +252,35 @@
}
#ifndef _SYS_SYSPROTO_H_
+struct ffexecve_args {
+ int interpreter;
+ int fd;
+ char **argv;
+ char **envv;
+}
+#endif
+int
+sys_ffexecve(struct thread *td, struct ffexecve_args *uap)
+{
+ struct image_args args;
+ struct vmspace *oldvmspace;
+ int error;
+
+ error = pre_execve(td, &oldvmspace);
+ if (error != 0)
+ return (error);
+ error = exec_copyin_args(&args, NULL, UIO_SYSSPACE,
+ uap->argv, uap->envv);
+ if (error == 0) {
+ args.interpreter = uap->interpreter;
+ args.fd = uap->fd;
+ error = kern_execve(td, &args, NULL);
+ }
+ post_execve(td, error, oldvmspace);
+ return (error);
+}
+
+#ifndef _SYS_SYSPROTO_H_
struct __mac_execve_args {
char *fname;
char **argv;
@@ -498,7 +527,8 @@
* so that it can be used by process_exec handlers to determine
* credential/setid changes.
*
- * Don't honor setuid/setgid if the filesystem prohibits it or if
+ * Don't honor setuid/setgid if the filesystem prohibits it, if
+ * employing a user-specified run-time interpreter or if
* the process is being traced.
*
* We disable setuid/setgid/etc in capability mode on the basis
@@ -523,6 +553,7 @@
#endif
if (credential_changing &&
+ (imgp->args->interpreter == -1) &&
#ifdef CAPABILITY_MODE
((oldcred->cr_flags & CRED_FLAG_CAPMODE) == 0) &&
#endif
@@ -1172,6 +1203,11 @@
return (EFAULT);
/*
+ * Don't override the imgact-specified interpreter by default.
+ */
+ args->interpreter = -1;
+
+ /*
* Allocate demand-paged memory for the file name, argument, and
* environment strings.
*/
Index: sys/kern/syscalls.master
===================================================================
--- sys/kern/syscalls.master
+++ sys/kern/syscalls.master
@@ -997,6 +997,8 @@
id_t id, const struct \
vm_domain_policy_entry *policy); }
550 AUE_FSYNC STD { int fdatasync(int fd); }
+551 AUE_NULL STD { int ffexecve(int interpreter, int fd, \
+ char **argv, char **envv); }
; Please copy any additions and changes to the following compatability tables:
; sys/compat/freebsd32/syscalls.master
Index: sys/sys/imgact.h
===================================================================
--- sys/sys/imgact.h
+++ sys/sys/imgact.h
@@ -51,6 +51,7 @@
int stringspace; /* space left in arg & env buffer */
int argc; /* count of argument strings */
int envc; /* count of environment strings */
+ int interpreter; /* descriptor of interpreter to override with */
int fd; /* file descriptor of the executable */
struct filedesc *fdp; /* new file descriptor table */
};
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Mon, Jan 27, 10:06 PM (8 h, 31 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
16216067
Default Alt Text
D9030.diff (13 KB)
Attached To
Mode
D9030: Create new fexecve() variant with explicit interpreter
Attached
Detach File
Event Timeline
Log In to Comment