Author: kib
Date: Wed Jan 23 20:34:22 2019
New Revision: 343356
URL: https://svnweb.freebsd.org/changeset/base/343356

Log:
  MFC r343082:
  Implement shmat(2) flag SHM_REMAP.

Modified:
  stable/12/contrib/netbsd-tests/kernel/t_sysv.c
  stable/12/lib/libc/sys/shmat.2
  stable/12/sys/kern/sysv_shm.c
  stable/12/sys/sys/shm.h
  stable/12/sys/vm/vm_map.c
  stable/12/sys/vm/vm_map.h
Directory Properties:
  stable/12/   (props changed)

Modified: stable/12/contrib/netbsd-tests/kernel/t_sysv.c
==============================================================================
--- stable/12/contrib/netbsd-tests/kernel/t_sysv.c      Wed Jan 23 20:31:24 
2019        (r343355)
+++ stable/12/contrib/netbsd-tests/kernel/t_sysv.c      Wed Jan 23 20:34:22 
2019        (r343356)
@@ -47,6 +47,7 @@
 #include <unistd.h>
 
 #include <sys/ipc.h>
+#include <sys/mman.h>
 #include <sys/msg.h>
 #include <sys/param.h>
 #include <sys/sem.h>
@@ -772,19 +773,27 @@ ATF_TC_BODY(shm, tc)
                atf_tc_fail("sender: received unexpected signal");
 }
 
-ATF_TC_CLEANUP(shm, tc)
+static void
+shmid_cleanup(const char *name)
 {
-       int sender_shmid;
+       int shmid;
 
        /*
         * Remove the shared memory area if it exists.
         */
-       sender_shmid = read_int("sender_shmid");
-       if (sender_shmid != -1)
-               if (shmctl(sender_shmid, IPC_RMID, NULL) == -1)
+       shmid = read_int(name);
+       if (shmid != -1) {
+               if (shmctl(shmid, IPC_RMID, NULL) == -1)
                        err(1, "shmctl IPC_RMID");
+       }
 }
 
+ATF_TC_CLEANUP(shm, tc)
+{
+
+       shmid_cleanup("sender_shmid");
+}
+
 void
 print_shmid_ds(struct shmid_ds *sp, mode_t mode)
 {
@@ -837,12 +846,53 @@ sharer(void)
        exit(0);
 }
 
+#ifdef SHM_REMAP
+ATF_TC_WITH_CLEANUP(shm_remap);
+ATF_TC_HEAD(shm_remap, tc)
+{
+
+       atf_tc_set_md_var(tc, "descr", "Checks SHM_REMAP");
+}
+
+ATF_TC_BODY(shm_remap, tc)
+{
+       char *shm_buf;
+       int shmid_remap;
+
+       pgsize = sysconf(_SC_PAGESIZE);
+
+       shmkey = get_ftok(4160);
+       ATF_REQUIRE_MSG(shmkey != (key_t)-1, "get_ftok failed");
+
+       ATF_REQUIRE_MSG((shmid_remap = shmget(shmkey, pgsize,
+           IPC_CREAT | 0640)) != -1, "shmget: %d", errno);
+       write_int("shmid_remap", shmid_remap);
+
+       ATF_REQUIRE_MSG((shm_buf = mmap(NULL, pgsize, PROT_READ | PROT_WRITE,
+           MAP_ANON | MAP_PRIVATE, -1, 0)) != MAP_FAILED, "mmap: %d", errno);
+
+       ATF_REQUIRE_MSG(shmat(shmid_remap, shm_buf, 0) == (void *)-1,
+           "shmat without MAP_REMAP succeeded");
+       ATF_REQUIRE_MSG(shmat(shmid_remap, shm_buf, SHM_REMAP) == shm_buf,
+           "shmat(SHM_REMAP): %d", errno);
+}
+
+ATF_TC_CLEANUP(shm_remap, tc)
+{
+
+       shmid_cleanup("shmid_remap");
+}
+#endif /* SHM_REMAP */
+
 ATF_TP_ADD_TCS(tp)
 {
 
        ATF_TP_ADD_TC(tp, msg);
        ATF_TP_ADD_TC(tp, sem);
        ATF_TP_ADD_TC(tp, shm);
+#ifdef SHM_REMAP
+       ATF_TP_ADD_TC(tp, shm_remap);
+#endif
 
        return atf_no_error();
 }

Modified: stable/12/lib/libc/sys/shmat.2
==============================================================================
--- stable/12/lib/libc/sys/shmat.2      Wed Jan 23 20:31:24 2019        
(r343355)
+++ stable/12/lib/libc/sys/shmat.2      Wed Jan 23 20:34:22 2019        
(r343356)
@@ -25,7 +25,7 @@
 .\"
 .\" $FreeBSD$
 .\"
-.Dd January 25, 2018
+.Dd January 14, 2019
 .Dt SHMAT 2
 .Os
 .Sh NAME
@@ -64,17 +64,38 @@ kernel.
 .It
 If
 .Fa addr
-is nonzero and SHM_RND is not specified in
+is nonzero and
+.Va SHM_RND
+is not specified in
 .Fa flag ,
 the segment is attached the specified address.
 .It
 If
 .Fa addr
-is specified and SHM_RND is specified,
+is specified and
+.Va SHM_RND
+is specified,
 .Fa addr
 is rounded down to the nearest multiple of SHMLBA.
 .El
 .Pp
+If the
+.Va SHM_REMAP
+flag is specified and the passed
+.Fa addr
+is not
+.Dv NULL ,
+any existing mappings in the virtual addresses range are
+cleared before the segment is attached.
+If the flag is not specified,
+.Fa addr
+is not
+.Dv NULL ,
+and the virtual address range contains
+some pre-existing mappings, the
+.Fn shmat
+call fails.
+.Pp
 The
 .Fn shmdt
 system call
@@ -104,6 +125,14 @@ The
 .Fa addr
 argument
 was not an acceptable address.
+.It Bq Er ENOMEM
+The specified
+.Fa addr
+cannot be used for mapping, for instance due to the amount of available
+space being smaller than the segment size,
+or because pre-existing mappings are in the range and no
+.Va SHM_REMAP
+flag was provided.
 .It Bq Er EMFILE
 Failed to attach the shared memory segment because the per-process
 .Va kern.ipc.shmseg

Modified: stable/12/sys/kern/sysv_shm.c
==============================================================================
--- stable/12/sys/kern/sysv_shm.c       Wed Jan 23 20:31:24 2019        
(r343355)
+++ stable/12/sys/kern/sysv_shm.c       Wed Jan 23 20:34:22 2019        
(r343356)
@@ -388,7 +388,7 @@ kern_shmat_locked(struct thread *td, int shmid, const 
        vm_offset_t attach_va;
        vm_prot_t prot;
        vm_size_t size;
-       int error, i, rv;
+       int cow, error, find_space, i, rv;
 
        AUDIT_ARG_SVIPC_ID(shmid);
        AUDIT_ARG_VALUE(shmflg);
@@ -427,6 +427,7 @@ kern_shmat_locked(struct thread *td, int shmid, const 
                return (EMFILE);
        size = round_page(shmseg->u.shm_segsz);
        prot = VM_PROT_READ;
+       cow = MAP_INHERIT_SHARE | MAP_PREFAULT_PARTIAL;
        if ((shmflg & SHM_RDONLY) == 0)
                prot |= VM_PROT_WRITE;
        if (shmaddr != NULL) {
@@ -436,6 +437,9 @@ kern_shmat_locked(struct thread *td, int shmid, const 
                        attach_va = (vm_offset_t)shmaddr;
                else
                        return (EINVAL);
+               if ((shmflg & SHM_REMAP) != 0)
+                       cow |= MAP_REMAP;
+               find_space = VMFS_NO_SPACE;
        } else {
                /*
                 * This is just a hint to vm_map_find() about where to
@@ -443,12 +447,12 @@ kern_shmat_locked(struct thread *td, int shmid, const 
                 */
                attach_va = round_page((vm_offset_t)p->p_vmspace->vm_daddr +
                    lim_max(td, RLIMIT_DATA));
+               find_space = VMFS_OPTIMAL_SPACE;
        }
 
        vm_object_reference(shmseg->object);
        rv = vm_map_find(&p->p_vmspace->vm_map, shmseg->object, 0, &attach_va,
-           size, 0, shmaddr != NULL ? VMFS_NO_SPACE : VMFS_OPTIMAL_SPACE,
-           prot, prot, MAP_INHERIT_SHARE | MAP_PREFAULT_PARTIAL);
+           size, 0, find_space, prot, prot, cow);
        if (rv != KERN_SUCCESS) {
                vm_object_deallocate(shmseg->object);
                return (ENOMEM);

Modified: stable/12/sys/sys/shm.h
==============================================================================
--- stable/12/sys/sys/shm.h     Wed Jan 23 20:31:24 2019        (r343355)
+++ stable/12/sys/sys/shm.h     Wed Jan 23 20:34:22 2019        (r343356)
@@ -52,6 +52,7 @@
 
 #define SHM_RDONLY  010000  /* Attach read-only (else read-write) */
 #define SHM_RND     020000  /* Round attach address to SHMLBA */
+#define        SHM_REMAP   030000  /* Unmap before mapping */
 #define SHMLBA      PAGE_SIZE /* Segment low boundary address multiple */
 
 /* "official" access mode definitions; somewhat braindead since you have

Modified: stable/12/sys/vm/vm_map.c
==============================================================================
--- stable/12/sys/vm/vm_map.c   Wed Jan 23 20:31:24 2019        (r343355)
+++ stable/12/sys/vm/vm_map.c   Wed Jan 23 20:34:22 2019        (r343356)
@@ -1565,6 +1565,8 @@ vm_map_find(vm_map_t map, vm_object_t object, vm_ooffs
        KASSERT((cow & (MAP_STACK_GROWS_DOWN | MAP_STACK_GROWS_UP)) == 0 ||
            object == NULL,
            ("vm_map_find: non-NULL backing object for stack"));
+       MPASS((cow & MAP_REMAP) == 0 || (find_space == VMFS_NO_SPACE &&
+           (cow & (MAP_STACK_GROWS_DOWN | MAP_STACK_GROWS_UP)) == 0));
        if (find_space == VMFS_OPTIMAL_SPACE && (object == NULL ||
            (object->flags & OBJ_COLORED) == 0))
                find_space = VMFS_ANY_SPACE;
@@ -1595,6 +1597,14 @@ again:
                        }
                        goto done;
                }
+       } else if ((cow & MAP_REMAP) != 0) {
+               if (*addr < vm_map_min(map) ||
+                   *addr + length > vm_map_max(map) ||
+                   *addr + length <= length) {
+                       rv = KERN_INVALID_ADDRESS;
+                       goto done;
+               }
+               vm_map_delete(map, *addr, *addr + length);
        }
        if ((cow & (MAP_STACK_GROWS_DOWN | MAP_STACK_GROWS_UP)) != 0) {
                rv = vm_map_stack_locked(map, *addr, length, sgrowsiz, prot,

Modified: stable/12/sys/vm/vm_map.h
==============================================================================
--- stable/12/sys/vm/vm_map.h   Wed Jan 23 20:31:24 2019        (r343355)
+++ stable/12/sys/vm/vm_map.h   Wed Jan 23 20:34:22 2019        (r343356)
@@ -342,6 +342,7 @@ long vmspace_resident_count(struct vmspace *vmspace);
 #define MAP_DISABLE_COREDUMP   0x0100
 #define MAP_PREFAULT_MADVISE   0x0200  /* from (user) madvise request */
 #define        MAP_VN_WRITECOUNT       0x0400
+#define        MAP_REMAP               0x0800
 #define        MAP_STACK_GROWS_DOWN    0x1000
 #define        MAP_STACK_GROWS_UP      0x2000
 #define        MAP_ACC_CHARGED         0x4000
_______________________________________________
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