Page MenuHomeFreeBSD

D3079.id6998.diff
No OneTemporary

D3079.id6998.diff

Index: head/sys/compat/cloudabi/cloudabi_proc.c
===================================================================
--- head/sys/compat/cloudabi/cloudabi_proc.c
+++ head/sys/compat/cloudabi/cloudabi_proc.c
@@ -27,10 +27,12 @@
__FBSDID("$FreeBSD$");
#include <sys/param.h>
+#include <sys/imgact.h>
#include <sys/lock.h>
#include <sys/mutex.h>
#include <sys/proc.h>
#include <sys/signalvar.h>
+#include <sys/syscallsubr.h>
#include <compat/cloudabi/cloudabi_proto.h>
@@ -38,9 +40,16 @@
cloudabi_sys_proc_exec(struct thread *td,
struct cloudabi_sys_proc_exec_args *uap)
{
+ struct image_args args;
+ int error;
- /* Not implemented. */
- return (ENOSYS);
+ error = exec_copyin_data_fds(td, &args, uap->data, uap->datalen,
+ uap->fds, uap->fdslen);
+ if (error == 0) {
+ args.fd = uap->fd;
+ error = kern_execve(td, &args, NULL);
+ }
+ return (error);
}
int
Index: head/sys/kern/kern_descrip.c
===================================================================
--- head/sys/kern/kern_descrip.c
+++ head/sys/kern/kern_descrip.c
@@ -1921,6 +1921,14 @@
p->p_fd = tmp;
}
+void
+fdinstall_remapped(struct thread *td, struct filedesc *fdp)
+{
+
+ fdescfree(td);
+ td->td_proc->p_fd = fdp;
+}
+
/*
* Copy a filedesc structure. A NULL pointer in returns a NULL reference,
* this is to ease callers, not catch errors.
@@ -1960,6 +1968,65 @@
}
/*
+ * Copies a filedesc structure, while remapping all file descriptors
+ * stored inside using a translation table.
+ *
+ * File descriptors are copied over to the new file descriptor table,
+ * regardless of whether the close-on-exec flag is set.
+ */
+int
+fdcopy_remapped(struct filedesc *fdp, const int *fds, size_t nfds,
+ struct filedesc **ret)
+{
+ struct filedesc *newfdp;
+ struct filedescent *nfde, *ofde;
+ int error, i;
+
+ MPASS(fdp != NULL);
+
+ newfdp = fdinit(fdp, true);
+ if (nfds > fdp->fd_lastfile + 1) {
+ /* New table cannot be larger than the old one. */
+ error = E2BIG;
+ goto bad;
+ }
+ /* Copy all passable descriptors (i.e. not kqueue). */
+ newfdp->fd_freefile = nfds;
+ for (i = 0; i < nfds; ++i) {
+ if (fds[i] < 0 || fds[i] > fdp->fd_lastfile) {
+ /* File descriptor out of bounds. */
+ error = EBADF;
+ goto bad;
+ }
+ ofde = &fdp->fd_ofiles[fds[i]];
+ if (ofde->fde_file == NULL) {
+ /* Unused file descriptor. */
+ error = EBADF;
+ goto bad;
+ }
+ if ((ofde->fde_file->f_ops->fo_flags & DFLAG_PASSABLE) == 0) {
+ /* File descriptor cannot be passed. */
+ error = EINVAL;
+ goto bad;
+ }
+ nfde = &newfdp->fd_ofiles[i];
+ *nfde = *ofde;
+ filecaps_copy(&ofde->fde_caps, &nfde->fde_caps);
+ fhold(nfde->fde_file);
+ fdused_init(newfdp, i);
+ newfdp->fd_lastfile = i;
+ }
+ newfdp->fd_cmask = fdp->fd_cmask;
+ FILEDESC_SUNLOCK(fdp);
+ *ret = newfdp;
+ return (0);
+bad:
+ FILEDESC_SUNLOCK(fdp);
+ fdescfree_remapped(newfdp);
+ return (error);
+}
+
+/*
* Clear POSIX style locks. This is only used when fdp looses a reference (i.e.
* one of processes using it exits) and the table used to be shared.
*/
@@ -2114,6 +2181,42 @@
fddrop(fdp);
}
+void
+fdescfree_remapped(struct filedesc *fdp)
+{
+ struct filedesc0 *fdp0;
+ struct filedescent *fde;
+ struct file *fp;
+ struct freetable *ft, *tft;
+ int i;
+
+ for (i = 0; i <= fdp->fd_lastfile; i++) {
+ fde = &fdp->fd_ofiles[i];
+ fp = fde->fde_file;
+ if (fp != NULL) {
+ fdefree_last(fde);
+ (void) closef(fp, NULL);
+ }
+ }
+
+ if (NDSLOTS(fdp->fd_nfiles) > NDSLOTS(NDFILE))
+ free(fdp->fd_map, M_FILEDESC);
+ if (fdp->fd_nfiles > NDFILE)
+ free(fdp->fd_files, M_FILEDESC);
+
+ fdp0 = (struct filedesc0 *)fdp;
+ SLIST_FOREACH_SAFE(ft, &fdp0->fd_free, ft_next, tft)
+ free(ft->ft_table, M_FILEDESC);
+
+ if (fdp->fd_cdir != NULL)
+ vrele(fdp->fd_cdir);
+ if (fdp->fd_rdir != NULL)
+ vrele(fdp->fd_rdir);
+ if (fdp->fd_jdir != NULL)
+ vrele(fdp->fd_jdir);
+ fddrop(fdp);
+}
+
/*
* For setugid programs, we don't want to people to use that setugidness
* to generate error messages which write to a file which otherwise would
Index: head/sys/kern/kern_exec.c
===================================================================
--- head/sys/kern/kern_exec.c
+++ head/sys/kern/kern_exec.c
@@ -580,13 +580,20 @@
else
suword(--stack_base, imgp->args->argc);
- /*
- * For security and other reasons, the file descriptor table cannot
- * be shared after an exec.
- */
- fdunshare(td);
- /* close files on exec */
- fdcloseexec(td);
+ if (args->fdp != NULL) {
+ /* Install a brand new file descriptor table. */
+ fdinstall_remapped(td, args->fdp);
+ args->fdp = NULL;
+ } else {
+ /*
+ * Keep on using the existing file descriptor table. For
+ * security and other reasons, the file descriptor table
+ * cannot be shared after an exec.
+ */
+ fdunshare(td);
+ /* close files on exec */
+ fdcloseexec(td);
+ }
/*
* Malloc things before we need locks.
@@ -1197,6 +1204,71 @@
return (error);
}
+int
+exec_copyin_data_fds(struct thread *td, struct image_args *args,
+ const void *data, size_t datalen, const int *fds, size_t fdslen)
+{
+ struct filedesc *ofdp;
+ const char *p;
+ int *kfds;
+ int error;
+
+ memset(args, '\0', sizeof(*args));
+ ofdp = td->td_proc->p_fd;
+ if (datalen >= ARG_MAX || fdslen > ofdp->fd_lastfile + 1)
+ return (E2BIG);
+ error = exec_alloc_args(args);
+ if (error != 0)
+ return (error);
+
+ args->begin_argv = args->buf;
+ args->stringspace = ARG_MAX;
+
+ if (datalen > 0) {
+ /*
+ * Argument buffer has been provided. Copy it into the
+ * kernel as a single string and add a terminating null
+ * byte.
+ */
+ error = copyin(data, args->begin_argv, datalen);
+ if (error != 0)
+ goto err_exit;
+ args->begin_argv[datalen] = '\0';
+ args->endp = args->begin_argv + datalen + 1;
+ args->stringspace -= datalen + 1;
+
+ /*
+ * Traditional argument counting. Count the number of
+ * null bytes.
+ */
+ for (p = args->begin_argv; p < args->endp; ++p)
+ if (*p == '\0')
+ ++args->argc;
+ } else {
+ /* No argument buffer provided. */
+ args->endp = args->begin_argv;
+ }
+ /* There are no environment variables. */
+ args->begin_envv = args->endp;
+
+ /* Create new file descriptor table. */
+ kfds = malloc(fdslen * sizeof(int), M_TEMP, M_WAITOK);
+ error = copyin(fds, kfds, fdslen * sizeof(int));
+ if (error != 0) {
+ free(kfds, M_TEMP);
+ goto err_exit;
+ }
+ error = fdcopy_remapped(ofdp, kfds, fdslen, &args->fdp);
+ free(kfds, M_TEMP);
+ if (error != 0)
+ goto err_exit;
+
+ return (0);
+err_exit:
+ exec_free_args(args);
+ return (error);
+}
+
/*
* Allocate temporary demand-paged, zero-filled memory for the file name,
* argument, and environment strings. Returns zero if the allocation succeeds
@@ -1223,6 +1295,8 @@
free(args->fname_buf, M_TEMP);
args->fname_buf = NULL;
}
+ if (args->fdp != NULL)
+ fdescfree_remapped(args->fdp);
}
/*
Index: head/sys/sys/filedesc.h
===================================================================
--- head/sys/sys/filedesc.h
+++ head/sys/sys/filedesc.h
@@ -170,8 +170,12 @@
void fdcloseexec(struct thread *td);
void fdsetugidsafety(struct thread *td);
struct filedesc *fdcopy(struct filedesc *fdp);
+int fdcopy_remapped(struct filedesc *fdp, const int *fds, size_t nfds,
+ struct filedesc **newfdp);
+void fdinstall_remapped(struct thread *td, struct filedesc *fdp);
void fdunshare(struct thread *td);
void fdescfree(struct thread *td);
+void fdescfree_remapped(struct filedesc *fdp);
struct filedesc *fdinit(struct filedesc *fdp, bool prepfiles);
struct filedesc *fdshare(struct filedesc *fdp);
struct filedesc_to_leader *
Index: head/sys/sys/imgact.h
===================================================================
--- head/sys/sys/imgact.h
+++ head/sys/sys/imgact.h
@@ -49,6 +49,7 @@
int argc; /* count of argument strings */
int envc; /* count of environment strings */
int fd; /* file descriptor of the executable */
+ struct filedesc *fdp; /* new file descriptor table */
};
struct image_params {
@@ -99,6 +100,8 @@
int exec_shell_imgact(struct image_params *);
int exec_copyin_args(struct image_args *, char *, enum uio_seg,
char **, char **);
+int exec_copyin_data_fds(struct thread *, struct image_args *, const void *,
+ size_t, const int *, size_t);
int pre_execve(struct thread *td, struct vmspace **oldvmspace);
void post_execve(struct thread *td, int error, struct vmspace *oldvmspace);
#endif

File Metadata

Mime Type
text/plain
Expires
Tue, Oct 28, 3:02 PM (4 h, 49 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
24344785
Default Alt Text
D3079.id6998.diff (8 KB)

Event Timeline