Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F137923510
D9030.id26361.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
9 KB
Referenced Files
None
Subscribers
None
D9030.id26361.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 fldexec(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
@@ -364,7 +364,7 @@
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 fldexec.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 fldexec
.Nd execute a file
.Sh LIBRARY
.Lb libc
Index: sys/compat/freebsd32/syscalls.master
===================================================================
--- sys/compat/freebsd32/syscalls.master
+++ sys/compat/freebsd32/syscalls.master
@@ -1081,3 +1081,5 @@
id_t id, \
const struct vm_domain_policy *policy); }
550 AUE_FSYNC NOPROTO { int fdatasync(int fd); }
+551 AUE_NULL STD { int fldexec(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
+fldexec
##
## Allow flock(2), subject to capability rights.
Index: sys/kern/imgact_elf.c
===================================================================
--- sys/kern/imgact_elf.c
+++ sys/kern/imgact_elf.c
@@ -87,8 +87,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);
@@ -624,17 +626,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;
@@ -642,17 +642,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;
@@ -665,14 +655,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.
@@ -689,9 +672,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)
@@ -744,17 +727,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;
@@ -768,7 +781,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;
@@ -818,6 +831,10 @@
break;
case PT_INTERP:
/* Path to interpreter */
+ if (interp != NULL) {
+ /* fldexec() is overriding the interpreter */
+ break;
+ }
if (phdr[i].p_filesz > MAXPATHLEN) {
uprintf("Invalid PT_INTERP\n");
error = ENOEXEC;
@@ -1013,12 +1030,32 @@
if (interp != NULL) {
have_interp = FALSE;
VOP_UNLOCK(imgp->vp, 0);
+ if ((interp_fd = imgp->args->interpreter) != -1) {
+ /* fldexec() 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 (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)
@@ -1027,13 +1064,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/kern_exec.c
===================================================================
--- sys/kern/kern_exec.c
+++ sys/kern/kern_exec.c
@@ -252,6 +252,35 @@
}
#ifndef _SYS_SYSPROTO_H_
+struct fldexec_args {
+ int interpreter;
+ int fd;
+ char **argv;
+ char **envv;
+}
+#endif
+int
+sys_fldexec(struct thread *td, struct fldexec_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;
@@ -1172,6 +1201,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
@@ -995,6 +995,8 @@
id_t id, const struct \
vm_domain_policy_entry *policy); }
550 AUE_FSYNC STD { int fdatasync(int fd); }
+551 AUE_NULL STD { int fldexec(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
Fri, Nov 28, 7:21 AM (22 h, 56 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
26277209
Default Alt Text
D9030.id26361.diff (9 KB)
Attached To
Mode
D9030: Create new fexecve() variant with explicit interpreter
Attached
Detach File
Event Timeline
Log In to Comment