Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 10 Jul 2020 00:43:45 +0000 (UTC)
From:      Kyle Evans <kevans@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r363065 - in head/sys: kern sys
Message-ID:  <202007100043.06A0hjo1093130@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: kevans
Date: Fri Jul 10 00:43:45 2020
New Revision: 363065
URL: https://svnweb.freebsd.org/changeset/base/363065

Log:
  shm_open2: Implement SHM_GROW_ON_WRITE
  
  Lack of SHM_GROW_ON_WRITE is actively breaking Python's memfd_create tests,
  so go ahead and implement it. A future change will make memfd_create always
  set SHM_GROW_ON_WRITE, to match Linux behavior and unbreak Python's tests
  on -CURRENT.
  
  Reviewed by:	kib
  Differential Revision:	https://reviews.freebsd.org/D25502

Modified:
  head/sys/kern/uipc_shm.c
  head/sys/sys/mman.h

Modified: head/sys/kern/uipc_shm.c
==============================================================================
--- head/sys/kern/uipc_shm.c	Fri Jul 10 00:24:42 2020	(r363064)
+++ head/sys/kern/uipc_shm.c	Fri Jul 10 00:43:45 2020	(r363065)
@@ -313,6 +313,7 @@ shm_write(struct file *fp, struct uio *uio, struct ucr
 	struct shmfd *shmfd;
 	void *rl_cookie;
 	int error;
+	off_t size;
 
 	shmfd = fp->f_data;
 #ifdef MAC
@@ -321,17 +322,42 @@ shm_write(struct file *fp, struct uio *uio, struct ucr
 		return (error);
 #endif
 	foffset_lock_uio(fp, uio, flags);
+	if (uio->uio_resid > OFF_MAX - uio->uio_offset) {
+		/*
+		 * Overflow is only an error if we're supposed to expand on
+		 * write.  Otherwise, we'll just truncate the write to the
+		 * size of the file, which can only grow up to OFF_MAX.
+		 */
+		if ((shmfd->shm_flags & SHM_GROW_ON_WRITE) != 0) {
+			foffset_unlock_uio(fp, uio, flags);
+			return (EFBIG);
+		}
+
+		size = shmfd->shm_size;
+	} else {
+		size = uio->uio_offset + uio->uio_resid;
+	}
 	if ((flags & FOF_OFFSET) == 0) {
 		rl_cookie = rangelock_wlock(&shmfd->shm_rl, 0, OFF_MAX,
 		    &shmfd->shm_mtx);
 	} else {
 		rl_cookie = rangelock_wlock(&shmfd->shm_rl, uio->uio_offset,
-		    uio->uio_offset + uio->uio_resid, &shmfd->shm_mtx);
+		    size, &shmfd->shm_mtx);
 	}
-	if ((shmfd->shm_seals & F_SEAL_WRITE) != 0)
+	if ((shmfd->shm_seals & F_SEAL_WRITE) != 0) {
 		error = EPERM;
-	else
-		error = uiomove_object(shmfd->shm_object, shmfd->shm_size, uio);
+	} else {
+		error = 0;
+		if ((shmfd->shm_flags & SHM_GROW_ON_WRITE) != 0 &&
+		    size > shmfd->shm_size) {
+			VM_OBJECT_WLOCK(shmfd->shm_object);
+			error = shm_dotruncate_locked(shmfd, size, rl_cookie);
+			VM_OBJECT_WUNLOCK(shmfd->shm_object);
+		}
+		if (error == 0)
+			error = uiomove_object(shmfd->shm_object,
+			    shmfd->shm_size, uio);
+	}
 	rangelock_unlock(&shmfd->shm_rl, rl_cookie, &shmfd->shm_mtx);
 	foffset_unlock_uio(fp, uio, flags);
 	return (error);
@@ -748,7 +774,7 @@ kern_shm_open2(struct thread *td, const char *userpath
 	mode_t cmode;
 	int error, fd, initial_seals;
 
-	if ((shmflags & ~SHM_ALLOW_SEALING) != 0)
+	if ((shmflags & ~(SHM_ALLOW_SEALING | SHM_GROW_ON_WRITE)) != 0)
 		return (EINVAL);
 
 	initial_seals = F_SEAL_SEAL;
@@ -921,6 +947,7 @@ kern_shm_open2(struct thread *td, const char *userpath
 		}
 	}
 
+	shmfd->shm_flags = shmflags;
 	finit(fp, FFLAGS(flags & O_ACCMODE), DTYPE_SHM, shmfd, &shm_ops);
 
 	td->td_retval[0] = fd;

Modified: head/sys/sys/mman.h
==============================================================================
--- head/sys/sys/mman.h	Fri Jul 10 00:24:42 2020	(r363064)
+++ head/sys/sys/mman.h	Fri Jul 10 00:43:45 2020	(r363065)
@@ -190,6 +190,7 @@
  * shmflags for shm_open2()
  */
 #define	SHM_ALLOW_SEALING		0x00000001
+#define	SHM_GROW_ON_WRITE		0x00000002
 
 /*
  * Flags for memfd_create().
@@ -278,6 +279,7 @@ struct shmfd {
 	struct rangelock shm_rl;
 	struct mtx	shm_mtx;
 
+	int		shm_flags;
 	int		shm_seals;
 };
 #endif



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