Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F101305615
D18837.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
6 KB
Referenced Files
None
Subscribers
None
D18837.diff
View Options
Index: head/contrib/netbsd-tests/kernel/t_sysv.c
===================================================================
--- head/contrib/netbsd-tests/kernel/t_sysv.c
+++ head/contrib/netbsd-tests/kernel/t_sysv.c
@@ -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_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 @@
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();
}
Index: head/lib/libc/sys/shmat.2
===================================================================
--- head/lib/libc/sys/shmat.2
+++ head/lib/libc/sys/shmat.2
@@ -25,7 +25,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd January 25, 2018
+.Dd January 14, 2019
.Dt SHMAT 2
.Os
.Sh NAME
@@ -64,17 +64,38 @@
.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 @@
.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
Index: head/sys/kern/sysv_shm.c
===================================================================
--- head/sys/kern/sysv_shm.c
+++ head/sys/kern/sysv_shm.c
@@ -388,7 +388,7 @@
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 @@
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 @@
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 @@
*/
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);
Index: head/sys/sys/shm.h
===================================================================
--- head/sys/sys/shm.h
+++ head/sys/sys/shm.h
@@ -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
Index: head/sys/vm/vm_map.h
===================================================================
--- head/sys/vm/vm_map.h
+++ head/sys/vm/vm_map.h
@@ -342,6 +342,7 @@
#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
Index: head/sys/vm/vm_map.c
===================================================================
--- head/sys/vm/vm_map.c
+++ head/sys/vm/vm_map.c
@@ -1565,6 +1565,8 @@
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 @@
}
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,
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Mon, Oct 28, 12:58 PM (21 h, 32 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
14368273
Default Alt Text
D18837.diff (6 KB)
Attached To
Mode
D18837: Implement shmat(2) flag SHM_REMAP.
Attached
Detach File
Event Timeline
Log In to Comment