Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F133688685
D3079.id6998.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
8 KB
Referenced Files
None
Subscribers
None
D3079.id6998.diff
View Options
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
Details
Attached
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)
Attached To
Mode
D3079: Implement CloudABI's exec() call.
Attached
Detach File
Event Timeline
Log In to Comment