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
_______________________________________________
svn-src-head@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to