Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F143468351
D9030.id23573.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
15 KB
Referenced Files
None
Subscribers
None
D9030.id23573.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/Symbol.map
===================================================================
--- lib/libc/sys/Symbol.map
+++ lib/libc/sys/Symbol.map
@@ -330,6 +330,7 @@
fchmodat;
fchownat;
fexecve;
+ fldexec;
fstatat;
futimesat;
jail_get;
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_offset_t offset,
caddr_t vmaddr, size_t memsz, size_t filsz, vm_prot_t prot,
size_t pagesize);
@@ -616,17 +618,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;
@@ -634,17 +634,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;
@@ -657,14 +647,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.
@@ -681,9 +664,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)
@@ -736,17 +719,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;
@@ -760,7 +773,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;
@@ -810,6 +823,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;
@@ -1007,12 +1024,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)
@@ -1021,13 +1058,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/init_sysent.c
===================================================================
--- sys/kern/init_sysent.c
+++ sys/kern/init_sysent.c
@@ -3,7 +3,7 @@
*
* DO NOT EDIT-- this file is automatically generated.
* $FreeBSD$
- * created from FreeBSD: head/sys/kern/syscalls.master 310638 2016-12-27 20:21:11Z jhb
+ * created fromFreeBSD$
*/
#include "opt_compat.h"
@@ -597,4 +597,5 @@
{ AS(numa_getaffinity_args), (sy_call_t *)sys_numa_getaffinity, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 548 = numa_getaffinity */
{ AS(numa_setaffinity_args), (sy_call_t *)sys_numa_setaffinity, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 549 = numa_setaffinity */
{ AS(fdatasync_args), (sy_call_t *)sys_fdatasync, AUE_FSYNC, NULL, 0, 0, 0, SY_THR_STATIC }, /* 550 = fdatasync */
+ { AS(fldexec_args), (sy_call_t *)sys_fldexec, AUE_NULL, NULL, 0, 0, SYF_CAPENABLED, SY_THR_STATIC }, /* 551 = fldexec */
};
Index: sys/kern/kern_exec.c
===================================================================
--- sys/kern/kern_exec.c
+++ sys/kern/kern_exec.c
@@ -249,6 +249,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;
@@ -1169,6 +1198,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.c
===================================================================
--- sys/kern/syscalls.c
+++ sys/kern/syscalls.c
@@ -3,7 +3,7 @@
*
* DO NOT EDIT-- this file is automatically generated.
* $FreeBSD$
- * created from FreeBSD: head/sys/kern/syscalls.master 310638 2016-12-27 20:21:11Z jhb
+ * created fromFreeBSD$
*/
const char *syscallnames[] = {
@@ -558,4 +558,5 @@
"numa_getaffinity", /* 548 = numa_getaffinity */
"numa_setaffinity", /* 549 = numa_setaffinity */
"fdatasync", /* 550 = fdatasync */
+ "fldexec", /* 551 = fldexec */
};
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/kern/systrace_args.c
===================================================================
--- sys/kern/systrace_args.c
+++ sys/kern/systrace_args.c
@@ -3324,6 +3324,16 @@
*n_args = 1;
break;
}
+ /* fldexec */
+ case 551: {
+ struct fldexec_args *p = params;
+ iarg[0] = p->interpreter; /* int */
+ iarg[1] = p->fd; /* int */
+ uarg[2] = (intptr_t) p->argv; /* char ** */
+ uarg[3] = (intptr_t) p->envv; /* char ** */
+ *n_args = 4;
+ break;
+ }
default:
*n_args = 0;
break;
@@ -8854,6 +8864,25 @@
break;
};
break;
+ /* fldexec */
+ case 551:
+ switch(ndx) {
+ case 0:
+ p = "int";
+ break;
+ case 1:
+ p = "int";
+ break;
+ case 2:
+ p = "userland char **";
+ break;
+ case 3:
+ p = "userland char **";
+ break;
+ default:
+ break;
+ };
+ break;
default:
break;
};
@@ -10770,6 +10799,11 @@
if (ndx == 0 || ndx == 1)
p = "int";
break;
+ /* fldexec */
+ case 551:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
default:
break;
};
Index: sys/sys/imgact.h
===================================================================
--- sys/sys/imgact.h
+++ sys/sys/imgact.h
@@ -50,6 +50,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 */
};
Index: sys/sys/syscall.h
===================================================================
--- sys/sys/syscall.h
+++ sys/sys/syscall.h
@@ -3,7 +3,7 @@
*
* DO NOT EDIT-- this file is automatically generated.
* $FreeBSD$
- * created from FreeBSD: head/sys/kern/syscalls.master 310638 2016-12-27 20:21:11Z jhb
+ * created fromFreeBSD$
*/
#define SYS_syscall 0
@@ -468,4 +468,5 @@
#define SYS_numa_getaffinity 548
#define SYS_numa_setaffinity 549
#define SYS_fdatasync 550
-#define SYS_MAXSYSCALL 551
+#define SYS_fldexec 551
+#define SYS_MAXSYSCALL 552
Index: sys/sys/syscall.mk
===================================================================
--- sys/sys/syscall.mk
+++ sys/sys/syscall.mk
@@ -1,7 +1,7 @@
# FreeBSD system call object files.
# DO NOT EDIT-- this file is automatically generated.
# $FreeBSD$
-# created from FreeBSD: head/sys/kern/syscalls.master 310638 2016-12-27 20:21:11Z jhb
+# created fromFreeBSD$
MIASM = \
syscall.o \
exit.o \
@@ -395,4 +395,5 @@
utimensat.o \
numa_getaffinity.o \
numa_setaffinity.o \
- fdatasync.o
+ fdatasync.o \
+ fldexec.o
Index: sys/sys/sysproto.h
===================================================================
--- sys/sys/sysproto.h
+++ sys/sys/sysproto.h
@@ -3,7 +3,7 @@
*
* DO NOT EDIT-- this file is automatically generated.
* $FreeBSD$
- * created from FreeBSD: head/sys/kern/syscalls.master 310638 2016-12-27 20:21:11Z jhb
+ * created fromFreeBSD$
*/
#ifndef _SYS_SYSPROTO_H_
@@ -1786,6 +1786,12 @@
struct fdatasync_args {
char fd_l_[PADL_(int)]; int fd; char fd_r_[PADR_(int)];
};
+struct fldexec_args {
+ char interpreter_l_[PADL_(int)]; int interpreter; char interpreter_r_[PADR_(int)];
+ char fd_l_[PADL_(int)]; int fd; char fd_r_[PADR_(int)];
+ char argv_l_[PADL_(char **)]; char ** argv; char argv_r_[PADR_(char **)];
+ char envv_l_[PADL_(char **)]; char ** envv; char envv_r_[PADR_(char **)];
+};
int nosys(struct thread *, struct nosys_args *);
void sys_sys_exit(struct thread *, struct sys_exit_args *);
int sys_fork(struct thread *, struct fork_args *);
@@ -2172,6 +2178,7 @@
int sys_numa_getaffinity(struct thread *, struct numa_getaffinity_args *);
int sys_numa_setaffinity(struct thread *, struct numa_setaffinity_args *);
int sys_fdatasync(struct thread *, struct fdatasync_args *);
+int sys_fldexec(struct thread *, struct fldexec_args *);
#ifdef COMPAT_43
@@ -2949,6 +2956,7 @@
#define SYS_AUE_numa_getaffinity AUE_NULL
#define SYS_AUE_numa_setaffinity AUE_NULL
#define SYS_AUE_fdatasync AUE_FSYNC
+#define SYS_AUE_fldexec AUE_NULL
#undef PAD_
#undef PADL_
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Sat, Jan 31, 4:43 PM (3 h, 33 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
28131495
Default Alt Text
D9030.id23573.diff (15 KB)
Attached To
Mode
D9030: Create new fexecve() variant with explicit interpreter
Attached
Detach File
Event Timeline
Log In to Comment