Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 17 Nov 2020 21:20:11 +0000 (UTC)
From:      Conrad Meyer <cem@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r367778 - in head/sys: compat/linux kern sys
Message-ID:  <202011172120.0AHLKBQv068440@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: cem
Date: Tue Nov 17 21:20:11 2020
New Revision: 367778
URL: https://svnweb.freebsd.org/changeset/base/367778

Log:
  linux(4) clone(2): Correctly handle CLONE_FS and CLONE_FILES
  
  The two flags are distinct and it is impossible to correctly handle clone(2)
  without the assistance of fork1().  This change depends on the pwddesc split
  introduced in r367777.
  
  I've added a fork_req flag, FR2_SHARE_PATHS, which indicates that p_pd
  should be treated the opposite way p_fd is (based on RFFDG flag).  This is a
  little ugly, but the benefit is that existing RFFDG API is preserved.
  Holding FR2_SHARE_PATHS disabled, RFFDG indicates both p_fd and p_pd are
  copied, while !RFFDG indicates both should be cloned.
  
  In Chrome, clone(2) is used with CLONE_FS, without CLONE_FILES, and expects
  independent fd tables.
  
  The previous conflation of CLONE_FS and CLONE_FILES was introduced in
  r163371 (2006).
  
  Discussed with:	markj, trasz (earlier version)
  Differential Revision:	https://reviews.freebsd.org/D27016

Modified:
  head/sys/compat/linux/linux_fork.c
  head/sys/kern/kern_fork.c
  head/sys/sys/proc.h

Modified: head/sys/compat/linux/linux_fork.c
==============================================================================
--- head/sys/compat/linux/linux_fork.c	Tue Nov 17 21:14:13 2020	(r367777)
+++ head/sys/compat/linux/linux_fork.c	Tue Nov 17 21:20:11 2020	(r367778)
@@ -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
 		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
 
 	bzero(&fr, sizeof(fr));
 	fr.fr_flags = ff;
+	fr.fr_flags2 = f2;
 	fr.fr_procp = &p2;
 	error = fork1(td, &fr);
 	if (error)

Modified: head/sys/kern/kern_fork.c
==============================================================================
--- head/sys/kern/kern_fork.c	Tue Nov 17 21:14:13 2020	(r367777)
+++ head/sys/kern/kern_fork.c	Tue Nov 17 21:20:11 2020	(r367778)
@@ -414,11 +414,17 @@ do_fork(struct thread *td, struct fork_req *fr, struct
 		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,

Modified: head/sys/sys/proc.h
==============================================================================
--- head/sys/sys/proc.h	Tue Nov 17 21:14:13 2020	(r367777)
+++ head/sys/sys/proc.h	Tue Nov 17 21:20:11 2020	(r367778)
@@ -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 */
 };
 
 /*



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?202011172120.0AHLKBQv068440>