aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sys/compat/linux/linux_fork.c18
-rw-r--r--sys/kern/kern_fork.c10
-rw-r--r--sys/sys/proc.h3
3 files changed, 20 insertions, 11 deletions
diff --git a/sys/compat/linux/linux_fork.c b/sys/compat/linux/linux_fork.c
index d81e95d9e84d..3ba40fc2705e 100644
--- a/sys/compat/linux/linux_fork.c
+++ b/sys/compat/linux/linux_fork.c
@@ -131,12 +131,13 @@ static int
linux_clone_proc(struct thread *td, struct linux_clone_args *args)
{
struct fork_req fr;
- int error, ff = RFPROC | RFSTOPPED;
+ int error, ff = RFPROC | RFSTOPPED, f2;
struct proc *p2;
struct thread *td2;
int exit_signal;
struct linux_emuldata *em;
+ f2 = 0;
exit_signal = args->flags & 0x000000ff;
if (LINUX_SIG_VALID(exit_signal)) {
exit_signal = linux_to_bsd_signal(exit_signal);
@@ -147,14 +148,14 @@ linux_clone_proc(struct thread *td, struct linux_clone_args *args)
ff |= RFMEM;
if (args->flags & LINUX_CLONE_SIGHAND)
ff |= RFSIGSHARE;
- /*
- * XXX: In Linux, sharing of fs info (chroot/cwd/umask)
- * and open files is independent. In FreeBSD, its in one
- * structure but in reality it does not cause any problems
- * because both of these flags are usually set together.
- */
- if (!(args->flags & (LINUX_CLONE_FILES | LINUX_CLONE_FS)))
+ if (args->flags & LINUX_CLONE_FILES) {
+ if (!(args->flags & LINUX_CLONE_FS))
+ f2 |= FR2_SHARE_PATHS;
+ } else {
ff |= RFFDG;
+ if (args->flags & LINUX_CLONE_FS)
+ f2 |= FR2_SHARE_PATHS;
+ }
if (args->flags & LINUX_CLONE_PARENT_SETTID)
if (args->parent_tidptr == NULL)
@@ -165,6 +166,7 @@ linux_clone_proc(struct thread *td, struct linux_clone_args *args)
bzero(&fr, sizeof(fr));
fr.fr_flags = ff;
+ fr.fr_flags2 = f2;
fr.fr_procp = &p2;
error = fork1(td, &fr);
if (error)
diff --git a/sys/kern/kern_fork.c b/sys/kern/kern_fork.c
index 25b6132e3511..5bdf5054863d 100644
--- a/sys/kern/kern_fork.c
+++ b/sys/kern/kern_fork.c
@@ -414,11 +414,17 @@ do_fork(struct thread *td, struct fork_req *fr, struct proc *p2, struct thread *
fd = fdinit(p1->p_fd, false, NULL);
fdtol = NULL;
} else if (fr->fr_flags & RFFDG) {
- pd = pdcopy(p1->p_pd);
+ if (fr->fr_flags2 & FR2_SHARE_PATHS)
+ pd = pdshare(p1->p_pd);
+ else
+ pd = pdcopy(p1->p_pd);
fd = fdcopy(p1->p_fd);
fdtol = NULL;
} else {
- pd = pdshare(p1->p_pd);
+ if (fr->fr_flags2 & FR2_SHARE_PATHS)
+ pd = pdcopy(p1->p_pd);
+ else
+ pd = pdshare(p1->p_pd);
fd = fdshare(p1->p_fd);
if (p1->p_fdtol == NULL)
p1->p_fdtol = filedesc_to_leader_alloc(NULL, NULL,
diff --git a/sys/sys/proc.h b/sys/sys/proc.h
index 0b41b84c08ab..c593b500599c 100644
--- a/sys/sys/proc.h
+++ b/sys/sys/proc.h
@@ -1017,7 +1017,8 @@ struct fork_req {
int fr_pd_flags;
struct filecaps *fr_pd_fcaps;
int fr_flags2;
-#define FR2_DROPSIG_CAUGHT 0x00001 /* Drop caught non-DFL signals */
+#define FR2_DROPSIG_CAUGHT 0x00000001 /* Drop caught non-DFL signals */
+#define FR2_SHARE_PATHS 0x00000002 /* Invert sense of RFFDG for paths */
};
/*