Author: kib
Date: Thu Sep 10 20:54:44 2020
New Revision: 365613
URL: https://svnweb.freebsd.org/changeset/base/365613

Log:
  Fix interaction between largepages and seals/writes.
  
  On write with SHM_GROW_ON_WRITE, use proper truncate.
  Do not allow to grow largepage shm if F_SEAL_GROW is set. Note that
  shrinks are not supported at all due to unmanaged mappings.
  Call to vm_pager_update_writecount() is only valid for swap objects,
  skip it for unmanaged largepages.
  Largepages cannot support write sealing.
  Do not writecnt largepage mappings.
  
  Reported by:  kevans
  Reviewed by:  kevans, markj
  Sponsored by: The FreeBSD Foundation
  MFC after:    1 week
  Differential revision:        https://reviews.freebsd.org/D26394

Modified:
  head/sys/kern/uipc_shm.c

Modified: head/sys/kern/uipc_shm.c
==============================================================================
--- head/sys/kern/uipc_shm.c    Thu Sep 10 20:46:16 2020        (r365612)
+++ head/sys/kern/uipc_shm.c    Thu Sep 10 20:54:44 2020        (r365613)
@@ -450,9 +450,7 @@ shm_write(struct file *fp, struct uio *uio, struct ucr
                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);
+                       error = shm_dotruncate_cookie(shmfd, size, rl_cookie);
                }
                if (error == 0)
                        error = uiomove_object(shmfd->shm_object,
@@ -767,6 +765,9 @@ shm_dotruncate_largepage(struct shmfd *shmfd, off_t le
 #endif
        }
 
+       if ((shmfd->shm_seals & F_SEAL_GROW) != 0)
+               return (EPERM);
+
        aflags = VM_ALLOC_NORMAL | VM_ALLOC_ZERO;
        if (shmfd->shm_lp_alloc_policy == SHM_LARGEPAGE_ALLOC_NOWAIT)
                aflags |= VM_ALLOC_WAITFAIL;
@@ -1416,7 +1417,7 @@ out:
 static int
 shm_mmap_large(struct shmfd *shmfd, vm_map_t map, vm_offset_t *addr,
     vm_size_t size, vm_prot_t prot, vm_prot_t max_prot, int flags,
-    vm_ooffset_t foff, bool writecounted, struct thread *td)
+    vm_ooffset_t foff, struct thread *td)
 {
        struct vmspace *vms;
        vm_map_entry_t next_entry, prev_entry;
@@ -1448,8 +1449,6 @@ shm_mmap_large(struct shmfd *shmfd, vm_map_t map, vm_o
        docow |= MAP_INHERIT_SHARE;
        if ((flags & MAP_NOCORE) != 0)
                docow |= MAP_DISABLE_COREDUMP;
-       if (writecounted)
-               docow |= MAP_WRITECOUNT;
 
        mask = pagesizes[shmfd->shm_lp_psind] - 1;
        if ((foff & mask) != 0)
@@ -1594,12 +1593,15 @@ shm_mmap(struct file *fp, vm_map_t map, vm_offset_t *a
        mtx_unlock(&shm_timestamp_lock);
        vm_object_reference(shmfd->shm_object);
 
-       if (writecnt)
-               vm_pager_update_writecount(shmfd->shm_object, 0, objsize);
        if (shm_largepage(shmfd)) {
+               writecnt = false;
                error = shm_mmap_large(shmfd, map, addr, objsize, prot,
-                   maxprot, flags, foff, writecnt, td);
+                   maxprot, flags, foff, td);
        } else {
+               if (writecnt) {
+                       vm_pager_update_writecount(shmfd->shm_object, 0,
+                           objsize);
+               }
                error = vm_mmap_object(map, addr, objsize, prot, maxprot, flags,
                    shmfd->shm_object, foff, writecnt, td);
        }
@@ -1838,6 +1840,11 @@ shm_add_seals(struct file *fp, int seals)
        }
        nseals = seals & ~shmfd->shm_seals;
        if ((nseals & F_SEAL_WRITE) != 0) {
+               if (shm_largepage(shmfd)) {
+                       error = ENOTSUP;
+                       goto out;
+               }
+
                /*
                 * The rangelock above prevents writable mappings from being
                 * added after we've started applying seals.  The RLOCK here
_______________________________________________
svn-src-all@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to