From 3f49387707bb221fd1ff64b8bb73f0a5d9cec1ae Mon Sep 17 00:00:00 2001 From: Nikolay Sturm Date: Tue, 29 May 2007 10:44:30 +0000 Subject: adapt from netbsd: fold sys_shmat1() back into sys_shmat(), instead add flag for shmget(2) to specify that later shmat(2) for the shared memory segment should succeed even if the segment would be marked removed; use this to implement the Linux-compatible semantics of shmat(2) this fixes current opera with shm ok millert --- sys/compat/linux/linux_ipc.c | 6 ++++-- sys/kern/sysv_shm.c | 24 +++++++++++------------- sys/sys/shm.h | 6 ++++-- 3 files changed, 19 insertions(+), 17 deletions(-) (limited to 'sys') diff --git a/sys/compat/linux/linux_ipc.c b/sys/compat/linux/linux_ipc.c index 03be16c7dbd..f3a16bb0171 100644 --- a/sys/compat/linux/linux_ipc.c +++ b/sys/compat/linux/linux_ipc.c @@ -1,4 +1,4 @@ -/* $OpenBSD: linux_ipc.c,v 1.9 2003/10/12 23:44:39 millert Exp $ */ +/* $OpenBSD: linux_ipc.c,v 1.10 2007/05/29 10:44:29 sturm Exp $ */ /* $NetBSD: linux_ipc.c,v 1.10 1996/04/05 00:01:44 christos Exp $ */ /* @@ -538,7 +538,7 @@ linux_shmat(p, v, retval) SCARG(&bsa, shmaddr) = SCARG(uap, ptr); SCARG(&bsa, shmflg) = SCARG(uap, a2); - if ((error = sys_shmat1(p, &bsa, retval, 1))) + if ((error = sys_shmat(p, &bsa, retval))) return error; if ((error = copyout(&retval[0], (caddr_t) SCARG(uap, a3), @@ -595,6 +595,8 @@ linux_shmget(p, v, retval) SCARG(&bsa, size) = SCARG(uap, a2); SCARG(&bsa, shmflg) = SCARG(uap, a3); + SCARG(&bsa, shmflg) |= _SHM_RMLINGER; + return sys_shmget(p, &bsa, retval); } diff --git a/sys/kern/sysv_shm.c b/sys/kern/sysv_shm.c index c7292abcaa0..4475cc91d9e 100644 --- a/sys/kern/sysv_shm.c +++ b/sys/kern/sysv_shm.c @@ -1,4 +1,4 @@ -/* $OpenBSD: sysv_shm.c,v 1.46 2004/07/15 11:24:46 millert Exp $ */ +/* $OpenBSD: sysv_shm.c,v 1.47 2007/05/29 10:44:28 sturm Exp $ */ /* $NetBSD: sysv_shm.c,v 1.50 1998/10/21 22:24:29 tron Exp $ */ /* @@ -73,7 +73,7 @@ struct shmid_ds **shmsegs; /* linear mapping of shmid -> shmseg */ struct pool shm_pool; unsigned short *shmseqs; /* array of shm sequence numbers */ -struct shmid_ds *shm_find_segment_by_shmid(int, int); +struct shmid_ds *shm_find_segment_by_shmid(int); /* * Provides the following externally accessible functions: @@ -89,6 +89,7 @@ struct shmid_ds *shm_find_segment_by_shmid(int, int); */ #define SHMSEG_REMOVED 0x0200 /* can't overlap ACCESSPERMS */ +#define SHMSEG_RMLINGER 0x0400 int shm_last_free, shm_nused, shm_committed; @@ -129,7 +130,7 @@ shm_find_segment_by_key(key_t key) } struct shmid_ds * -shm_find_segment_by_shmid(int shmid, int findremoved) +shm_find_segment_by_shmid(int shmid) { int segnum; struct shmid_ds *shmseg; @@ -139,7 +140,7 @@ shm_find_segment_by_shmid(int shmid, int findremoved) (shmseg = shmsegs[segnum]) == NULL || shmseg->shm_perm.seq != IPCID_TO_SEQ(shmid)) return (NULL); - if (!findremoved && (shmseg->shm_perm.mode & SHMSEG_REMOVED)) + if ((shmseg->shm_perm.mode & (SHMSEG_REMOVED|SHMSEG_RMLINGER)) == SHMSEG_REMOVED) return (NULL); return (shmseg); } @@ -208,12 +209,6 @@ sys_shmdt(struct proc *p, void *v, register_t *retval) int sys_shmat(struct proc *p, void *v, register_t *retval) -{ - return (sys_shmat1(p, v, retval, 0)); -} - -int -sys_shmat1(struct proc *p, void *v, register_t *retval, int findremoved) { struct sys_shmat_args /* { syscallarg(int) shmid; @@ -241,7 +236,7 @@ sys_shmat1(struct proc *p, void *v, register_t *retval, int findremoved) shmmap_s->shmid = -1; p->p_vmspace->vm_shm = (caddr_t)shmmap_h; } - shmseg = shm_find_segment_by_shmid(SCARG(uap, shmid), findremoved); + shmseg = shm_find_segment_by_shmid(SCARG(uap, shmid)); if (shmseg == NULL) return (EINVAL); error = ipcperm(cred, &shmseg->shm_perm, @@ -314,7 +309,7 @@ shmctl1(struct proc *p, int shmid, int cmd, caddr_t buf, struct shmid_ds inbuf, *shmseg; int error; - shmseg = shm_find_segment_by_shmid(shmid, 1); + shmseg = shm_find_segment_by_shmid(shmid); if (shmseg == NULL) return (EINVAL); switch (cmd) { @@ -446,7 +441,7 @@ shmget_allocate_segment(struct proc *p, shmseg->shm_perm.cuid = shmseg->shm_perm.uid = cred->cr_uid; shmseg->shm_perm.cgid = shmseg->shm_perm.gid = cred->cr_gid; - shmseg->shm_perm.mode = (mode & ACCESSPERMS); + shmseg->shm_perm.mode = (mode & (ACCESSPERMS|SHMSEG_RMLINGER)); shmseg->shm_perm.seq = shmseqs[segnum] = (shmseqs[segnum] + 1) & 0x7fff; shmseg->shm_perm.key = key; shmseg->shm_segsz = SCARG(uap, size); @@ -471,6 +466,9 @@ sys_shmget(struct proc *p, void *v, register_t *retval) int segnum, mode, error; mode = SCARG(uap, shmflg) & ACCESSPERMS; + if (SCARG(uap, shmflg) & _SHM_RMLINGER) + mode |= SHMSEG_RMLINGER; + if (SCARG(uap, key) != IPC_PRIVATE) { again: segnum = shm_find_segment_by_key(SCARG(uap, key)); diff --git a/sys/sys/shm.h b/sys/sys/shm.h index 2dad3ed281a..ad1f9a77d7a 100644 --- a/sys/sys/shm.h +++ b/sys/sys/shm.h @@ -1,4 +1,4 @@ -/* $OpenBSD: shm.h,v 1.20 2005/12/13 00:35:23 millert Exp $ */ +/* $OpenBSD: shm.h,v 1.21 2007/05/29 10:44:28 sturm Exp $ */ /* $NetBSD: shm.h,v 1.20 1996/04/09 20:55:35 cgd Exp $ */ /* @@ -77,6 +77,9 @@ */ #define SHM_RDONLY 010000 /* Attach read-only (else read-write) */ #define SHM_RND 020000 /* Round attach address to SHMLBA */ +#ifdef _KERNEL +#define _SHM_RMLINGER 040000 /* Attach even if segment removed */ +#endif /* * Shared memory specific control commands for shmctl(). @@ -169,7 +172,6 @@ void shminit(void); void shmfork(struct vmspace *, struct vmspace *); void shmexit(struct vmspace *); int sysctl_sysvshm(int *, u_int, void *, size_t *, void *, size_t); -int sys_shmat1(struct proc *, void *, register_t *, int); int shmctl1(struct proc *, int, int, caddr_t, int (*)(const void *, void *, size_t), int (*)(const void *, void *, size_t)); -- cgit v1.2.3