summaryrefslogtreecommitdiffstats
path: root/sys/kern
diff options
context:
space:
mode:
authorjhb <jhb@FreeBSD.org>2009-06-24 21:10:52 +0000
committerjhb <jhb@FreeBSD.org>2009-06-24 21:10:52 +0000
commit6f52fe78fb1fc421bc6abb38286a4483aac9cdc0 (patch)
tree9bcf2215ae277f261cc7bf33f2dde8db38fe41c4 /sys/kern
parentce189363a0ec4e65f27076207a88142a8554bfbb (diff)
downloadFreeBSD-src-6f52fe78fb1fc421bc6abb38286a4483aac9cdc0.zip
FreeBSD-src-6f52fe78fb1fc421bc6abb38286a4483aac9cdc0.tar.gz
Change the ABI of some of the structures used by the SYSV IPC API:
- The uid/cuid members of struct ipc_perm are now uid_t instead of unsigned short. - The gid/cgid members of struct ipc_perm are now gid_t instead of unsigned short. - The mode member of struct ipc_perm is now mode_t instead of unsigned short (this is merely a style bug). - The rather dubious padding fields for ABI compat with SV/I386 have been removed from struct msqid_ds and struct semid_ds. - The shm_segsz member of struct shmid_ds is now a size_t instead of an int. This removes the need for the shm_bsegsz member in struct shmid_kernel and should allow for complete support of SYSV SHM regions >= 2GB. - The shm_nattch member of struct shmid_ds is now an int instead of a short. - The shm_internal member of struct shmid_ds is now gone. The internal VM object pointer for SHM regions has been moved into struct shmid_kernel. - The existing __semctl(), msgctl(), and shmctl() system call entries are now marked COMPAT7 and new versions of those system calls which support the new ABI are now present. - The new system calls are assigned to the FBSD-1.1 version in libc. The FBSD-1.0 symbols in libc now refer to the old COMPAT7 system calls. - A simplistic framework for tagging system calls with compatibility symbol versions has been added to libc. Version tags are added to system calls by adding an appropriate __sym_compat() entry to src/lib/libc/incldue/compat.h. [1] PR: kern/16195 kern/113218 bin/129855 Reviewed by: arch@, rwatson Discussed with: kan, kib [1]
Diffstat (limited to 'sys/kern')
-rw-r--r--sys/kern/syscalls.master18
-rw-r--r--sys/kern/sysv_ipc.c31
-rw-r--r--sys/kern/sysv_msg.c63
-rw-r--r--sys/kern/sysv_sem.c87
-rw-r--r--sys/kern/sysv_shm.c111
5 files changed, 290 insertions, 20 deletions
diff --git a/sys/kern/syscalls.master b/sys/kern/syscalls.master
index 204e7da..940f13d 100644
--- a/sys/kern/syscalls.master
+++ b/sys/kern/syscalls.master
@@ -417,15 +417,15 @@
;
; The following were introduced with NetBSD/4.4Lite-2
-220 AUE_SEMCTL NOSTD { int __semctl(int semid, int semnum, \
- int cmd, union semun *arg); }
+220 AUE_SEMCTL COMPAT7|NOSTD { int __semctl(int semid, int semnum, \
+ int cmd, union semun_old *arg); }
221 AUE_SEMGET NOSTD { int semget(key_t key, int nsems, \
int semflg); }
222 AUE_SEMOP NOSTD { int semop(int semid, struct sembuf *sops, \
size_t nsops); }
223 AUE_NULL UNIMPL semconfig
-224 AUE_MSGCTL NOSTD { int msgctl(int msqid, int cmd, \
- struct msqid_ds *buf); }
+224 AUE_MSGCTL COMPAT7|NOSTD { int msgctl(int msqid, int cmd, \
+ struct msqid_ds_old *buf); }
225 AUE_MSGGET NOSTD { int msgget(key_t key, int msgflg); }
226 AUE_MSGSND NOSTD { int msgsnd(int msqid, const void *msgp, \
size_t msgsz, int msgflg); }
@@ -433,8 +433,8 @@
size_t msgsz, long msgtyp, int msgflg); }
228 AUE_SHMAT NOSTD { int shmat(int shmid, const void *shmaddr, \
int shmflg); }
-229 AUE_SHMCTL NOSTD { int shmctl(int shmid, int cmd, \
- struct shmid_ds *buf); }
+229 AUE_SHMCTL COMPAT7|NOSTD { int shmctl(int shmid, int cmd, \
+ struct shmid_ds_old *buf); }
230 AUE_SHMDT NOSTD { int shmdt(const void *shmaddr); }
231 AUE_SHMGET NOSTD { int shmget(key_t key, size_t size, \
int shmflg); }
@@ -904,5 +904,11 @@
unsigned int iovcnt, int flags); }
508 AUE_NULL STD { int jail_remove(int jid); }
509 AUE_CLOSEFROM STD { int closefrom(int lowfd); }
+510 AUE_SEMCTL NOSTD { int __semctl(int semid, int semnum, \
+ int cmd, union semun *arg); }
+511 AUE_MSGCTL NOSTD { int msgctl(int msqid, int cmd, \
+ struct msqid_ds *buf); }
+512 AUE_SHMCTL NOSTD { int shmctl(int shmid, int cmd, \
+ struct shmid_ds *buf); }
; Please copy any additions and changes to the following compatability tables:
; sys/compat/freebsd32/syscalls.master
diff --git a/sys/kern/sysv_ipc.c b/sys/kern/sysv_ipc.c
index 0cbb4bb..d33fdb0 100644
--- a/sys/kern/sysv_ipc.c
+++ b/sys/kern/sysv_ipc.c
@@ -36,6 +36,7 @@
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
+#include "opt_compat.h"
#include "opt_sysvipc.h"
#include <sys/param.h>
@@ -147,3 +148,33 @@ ipcperm(struct thread *td, struct ipc_perm *perm, int acc_mode)
else
return (EACCES);
}
+
+#if defined(COMPAT_FREEBSD4) || defined(COMPAT_FREEBSD5) || \
+ defined(COMPAT_FREEBSD6) || defined(COMPAT_FREEBSD7)
+void
+ipcperm_old2new(struct ipc_perm_old *old, struct ipc_perm *new)
+{
+
+ new->cuid = old->cuid;
+ new->cgid = old->cgid;
+ new->uid = old->uid;
+ new->gid = old->gid;
+ new->mode = old->mode;
+ new->seq = old->seq;
+ new->key = old->key;
+}
+
+void
+ipcperm_new2old(struct ipc_perm *new, struct ipc_perm_old *old)
+{
+
+ /* XXX: How to handle ID's > USHORT_MAX? */
+ old->cuid = new->cuid;
+ old->cgid = new->cgid;
+ old->uid = new->uid;
+ old->gid = new->gid;
+ old->mode = new->mode;
+ old->seq = new->seq;
+ old->key = new->key;
+}
+#endif
diff --git a/sys/kern/sysv_msg.c b/sys/kern/sysv_msg.c
index e2f0c5d..c7c67d4 100644
--- a/sys/kern/sysv_msg.c
+++ b/sys/kern/sysv_msg.c
@@ -1260,10 +1260,11 @@ SYSCTL_PROC(_kern_ipc, OID_AUTO, msqids, CTLFLAG_RD,
#if defined(COMPAT_FREEBSD4) || defined(COMPAT_FREEBSD5) || \
defined(COMPAT_FREEBSD6) || defined(COMPAT_FREEBSD7)
SYSCALL_MODULE_HELPER(msgsys);
+SYSCALL_MODULE_HELPER(freebsd7_msgctl);
/* XXX casting to (sy_call_t *) is bogus, as usual. */
static sy_call_t *msgcalls[] = {
- (sy_call_t *)msgctl, (sy_call_t *)msgget,
+ (sy_call_t *)freebsd7_msgctl, (sy_call_t *)msgget,
(sy_call_t *)msgsnd, (sy_call_t *)msgrcv
};
@@ -1293,5 +1294,65 @@ msgsys(td, uap)
error = (*msgcalls[uap->which])(td, &uap->a2);
return (error);
}
+
+#define CP(src, dst, fld) do { (dst).fld = (src).fld; } while (0)
+
+#ifndef _SYS_SYSPROTO_H_
+struct freebsd7_msgctl_args {
+ int msqid;
+ int cmd;
+ struct msqid_ds_old *buf;
+};
+#endif
+int
+freebsd7_msgctl(td, uap)
+ struct thread *td;
+ struct freebsd7_msgctl_args *uap;
+{
+ struct msqid_ds_old msqold;
+ struct msqid_ds msqbuf;
+ int error;
+
+ DPRINTF(("call to freebsd7_msgctl(%d, %d, %p)\n", uap->msqid, uap->cmd,
+ uap->buf));
+ if (uap->cmd == IPC_SET) {
+ error = copyin(uap->buf, &msqold, sizeof(msqold));
+ if (error)
+ return (error);
+ ipcperm_old2new(&msqold.msg_perm, &msqbuf.msg_perm);
+ CP(msqold, msqbuf, msg_first);
+ CP(msqold, msqbuf, msg_last);
+ CP(msqold, msqbuf, msg_cbytes);
+ CP(msqold, msqbuf, msg_qnum);
+ CP(msqold, msqbuf, msg_qbytes);
+ CP(msqold, msqbuf, msg_lspid);
+ CP(msqold, msqbuf, msg_lrpid);
+ CP(msqold, msqbuf, msg_stime);
+ CP(msqold, msqbuf, msg_rtime);
+ CP(msqold, msqbuf, msg_ctime);
+ }
+ error = kern_msgctl(td, uap->msqid, uap->cmd, &msqbuf);
+ if (error)
+ return (error);
+ if (uap->cmd == IPC_STAT) {
+ bzero(&msqold, sizeof(msqold));
+ ipcperm_new2old(&msqbuf.msg_perm, &msqold.msg_perm);
+ CP(msqbuf, msqold, msg_first);
+ CP(msqbuf, msqold, msg_last);
+ CP(msqbuf, msqold, msg_cbytes);
+ CP(msqbuf, msqold, msg_qnum);
+ CP(msqbuf, msqold, msg_qbytes);
+ CP(msqbuf, msqold, msg_lspid);
+ CP(msqbuf, msqold, msg_lrpid);
+ CP(msqbuf, msqold, msg_stime);
+ CP(msqbuf, msqold, msg_rtime);
+ CP(msqbuf, msqold, msg_ctime);
+ error = copyout(&msqold, uap->buf, sizeof(struct msqid_ds_old));
+ }
+ return (error);
+}
+
+#undef CP
+
#endif /* COMPAT_FREEBSD4 || COMPAT_FREEBSD5 || COMPAT_FREEBSD6 ||
COMPAT_FREEBSD7 */
diff --git a/sys/kern/sysv_sem.c b/sys/kern/sysv_sem.c
index 719295d..2f2b528 100644
--- a/sys/kern/sysv_sem.c
+++ b/sys/kern/sysv_sem.c
@@ -1317,10 +1317,11 @@ sysctl_sema(SYSCTL_HANDLER_ARGS)
#if defined(COMPAT_FREEBSD4) || defined(COMPAT_FREEBSD5) || \
defined(COMPAT_FREEBSD6) || defined(COMPAT_FREEBSD7)
SYSCALL_MODULE_HELPER(semsys);
+SYSCALL_MODULE_HELPER(freebsd7___semctl);
/* XXX casting to (sy_call_t *) is bogus, as usual. */
static sy_call_t *semcalls[] = {
- (sy_call_t *)__semctl, (sy_call_t *)semget,
+ (sy_call_t *)freebsd7___semctl, (sy_call_t *)semget,
(sy_call_t *)semop
};
@@ -1349,5 +1350,89 @@ semsys(td, uap)
error = (*semcalls[uap->which])(td, &uap->a2);
return (error);
}
+
+#define CP(src, dst, fld) do { (dst).fld = (src).fld; } while (0)
+
+#ifndef _SYS_SYSPROTO_H_
+struct freebsd7___semctl_args {
+ int semid;
+ int semnum;
+ int cmd;
+ union semun_old *arg;
+};
+#endif
+int
+freebsd7___semctl(struct thread *td, struct freebsd7___semctl_args *uap)
+{
+ struct semid_ds_old dsold;
+ struct semid_ds dsbuf;
+ union semun_old arg;
+ union semun semun;
+ register_t rval;
+ int error;
+
+ switch (uap->cmd) {
+ case SEM_STAT:
+ case IPC_SET:
+ case IPC_STAT:
+ case GETALL:
+ case SETVAL:
+ case SETALL:
+ error = copyin(uap->arg, &arg, sizeof(arg));
+ if (error)
+ return (error);
+ break;
+ }
+
+ switch (uap->cmd) {
+ case SEM_STAT:
+ case IPC_STAT:
+ semun.buf = &dsbuf;
+ break;
+ case IPC_SET:
+ error = copyin(arg.buf, &dsold, sizeof(dsold));
+ if (error)
+ return (error);
+ ipcperm_old2new(&dsold.sem_perm, &dsbuf.sem_perm);
+ CP(dsold, dsbuf, sem_base);
+ CP(dsold, dsbuf, sem_nsems);
+ CP(dsold, dsbuf, sem_otime);
+ CP(dsold, dsbuf, sem_ctime);
+ semun.buf = &dsbuf;
+ break;
+ case GETALL:
+ case SETALL:
+ semun.array = arg.array;
+ break;
+ case SETVAL:
+ semun.val = arg.val;
+ break;
+ }
+
+ error = kern_semctl(td, uap->semid, uap->semnum, uap->cmd, &semun,
+ &rval);
+ if (error)
+ return (error);
+
+ switch (uap->cmd) {
+ case SEM_STAT:
+ case IPC_STAT:
+ bzero(&dsold, sizeof(dsold));
+ ipcperm_new2old(&dsbuf.sem_perm, &dsold.sem_perm);
+ CP(dsbuf, dsold, sem_base);
+ CP(dsbuf, dsold, sem_nsems);
+ CP(dsbuf, dsold, sem_otime);
+ CP(dsbuf, dsold, sem_ctime);
+ error = copyout(&dsold, arg.buf, sizeof(dsold));
+ break;
+ }
+
+ if (error == 0)
+ td->td_retval[0] = rval;
+ return (error);
+}
+
+#undef CP
+
#endif /* COMPAT_FREEBSD4 || COMPAT_FREEBSD5 || COMPAT_FREEBSD6 ||
COMPAT_FREEBSD7 */
diff --git a/sys/kern/sysv_shm.c b/sys/kern/sysv_shm.c
index 2ea9830..bfcbebf 100644
--- a/sys/kern/sysv_shm.c
+++ b/sys/kern/sysv_shm.c
@@ -68,6 +68,7 @@ __FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/kernel.h>
+#include <sys/limits.h>
#include <sys/lock.h>
#include <sys/sysctl.h>
#include <sys/shm.h>
@@ -234,9 +235,9 @@ shm_deallocate_segment(shmseg)
GIANT_REQUIRED;
- vm_object_deallocate(shmseg->u.shm_internal);
- shmseg->u.shm_internal = NULL;
- size = round_page(shmseg->shm_bsegsz);
+ vm_object_deallocate(shmseg->object);
+ shmseg->object = NULL;
+ size = round_page(shmseg->u.shm_segsz);
shm_committed -= btoc(size);
shm_nused--;
shmseg->u.shm_perm.mode = SHMSEG_FREE;
@@ -256,7 +257,7 @@ shm_delete_mapping(struct vmspace *vm, struct shmmap_state *shmmap_s)
segnum = IPCID_TO_IX(shmmap_s->shmid);
shmseg = &shmsegs[segnum];
- size = round_page(shmseg->shm_bsegsz);
+ size = round_page(shmseg->u.shm_segsz);
result = vm_map_remove(&vm->vm_map, shmmap_s->va, shmmap_s->va + size);
if (result != KERN_SUCCESS)
return (EINVAL);
@@ -376,7 +377,7 @@ kern_shmat(td, shmid, shmaddr, shmflg)
error = EMFILE;
goto done2;
}
- size = round_page(shmseg->shm_bsegsz);
+ size = round_page(shmseg->u.shm_segsz);
prot = VM_PROT_READ;
if ((shmflg & SHM_RDONLY) == 0)
prot |= VM_PROT_WRITE;
@@ -402,12 +403,12 @@ kern_shmat(td, shmid, shmaddr, shmflg)
PROC_UNLOCK(p);
}
- vm_object_reference(shmseg->u.shm_internal);
- rv = vm_map_find(&p->p_vmspace->vm_map, shmseg->u.shm_internal,
+ vm_object_reference(shmseg->object);
+ rv = vm_map_find(&p->p_vmspace->vm_map, shmseg->object,
0, &attach_va, size, (flags & MAP_FIXED) ? VMFS_NO_SPACE :
VMFS_ANY_SPACE, prot, prot, 0);
if (rv != KERN_SUCCESS) {
- vm_object_deallocate(shmseg->u.shm_internal);
+ vm_object_deallocate(shmseg->object);
error = ENOMEM;
goto done2;
}
@@ -624,7 +625,7 @@ shmget_existing(td, uap, mode, segnum)
if (error != 0)
return (error);
#endif
- if (uap->size != 0 && uap->size > shmseg->shm_bsegsz)
+ if (uap->size != 0 && uap->size > shmseg->u.shm_segsz)
return (EINVAL);
td->td_retval[0] = IXSEQ_TO_IPCID(segnum, shmseg->u.shm_perm);
return (0);
@@ -686,13 +687,12 @@ shmget_allocate_segment(td, uap, mode)
vm_object_set_flag(shm_object, OBJ_NOSPLIT);
VM_OBJECT_UNLOCK(shm_object);
- shmseg->u.shm_internal = shm_object;
+ shmseg->object = shm_object;
shmseg->u.shm_perm.cuid = shmseg->u.shm_perm.uid = cred->cr_uid;
shmseg->u.shm_perm.cgid = shmseg->u.shm_perm.gid = cred->cr_gid;
shmseg->u.shm_perm.mode = (shmseg->u.shm_perm.mode & SHMSEG_WANTED) |
(mode & ACCESSPERMS) | SHMSEG_ALLOCATED;
shmseg->u.shm_segsz = uap->size;
- shmseg->shm_bsegsz = uap->size;
shmseg->u.shm_cpid = td->td_proc->p_pid;
shmseg->u.shm_lpid = shmseg->u.shm_nattch = 0;
shmseg->u.shm_atime = shmseg->u.shm_dtime = 0;
@@ -953,7 +953,7 @@ done2:
static sy_call_t *shmcalls[] = {
(sy_call_t *)shmat, (sy_call_t *)oshmctl,
(sy_call_t *)shmdt, (sy_call_t *)shmget,
- (sy_call_t *)shmctl
+ (sy_call_t *)freebsd7_shmctl
};
int
@@ -983,6 +983,93 @@ shmsys(td, uap)
SYSCALL_MODULE_HELPER(shmsys);
#endif /* i386 && (COMPAT_FREEBSD4 || COMPAT_43) */
+#if defined(COMPAT_FREEBSD4) || defined(COMPAT_FREEBSD5) || \
+ defined(COMPAT_FREEBSD6) || defined(COMPAT_FREEBSD7)
+
+#define CP(src, dst, fld) do { (dst).fld = (src).fld; } while (0)
+
+
+#ifndef _SYS_SYSPROTO_H_
+struct freebsd7_shmctl_args {
+ int shmid;
+ int cmd;
+ struct shmid_ds_old *buf;
+};
+#endif
+int
+freebsd7_shmctl(td, uap)
+ struct thread *td;
+ struct freebsd7_shmctl_args *uap;
+{
+ int error = 0;
+ struct shmid_ds_old old;
+ struct shmid_ds buf;
+ size_t bufsz;
+
+ /*
+ * The only reason IPC_INFO, SHM_INFO, SHM_STAT exists is to support
+ * Linux binaries. If we see the call come through the FreeBSD ABI,
+ * return an error back to the user since we do not to support this.
+ */
+ if (uap->cmd == IPC_INFO || uap->cmd == SHM_INFO ||
+ uap->cmd == SHM_STAT)
+ return (EINVAL);
+
+ /* IPC_SET needs to copyin the buffer before calling kern_shmctl */
+ if (uap->cmd == IPC_SET) {
+ if ((error = copyin(uap->buf, &old, sizeof(old))))
+ goto done;
+ ipcperm_old2new(&old.shm_perm, &buf.shm_perm);
+ CP(old, buf, shm_segsz);
+ CP(old, buf, shm_lpid);
+ CP(old, buf, shm_cpid);
+ CP(old, buf, shm_nattch);
+ CP(old, buf, shm_atime);
+ CP(old, buf, shm_dtime);
+ CP(old, buf, shm_ctime);
+ }
+
+ error = kern_shmctl(td, uap->shmid, uap->cmd, (void *)&buf, &bufsz);
+ if (error)
+ goto done;
+
+ /* Cases in which we need to copyout */
+ switch (uap->cmd) {
+ case IPC_STAT:
+ ipcperm_new2old(&buf.shm_perm, &old.shm_perm);
+ if (buf.shm_segsz > INT_MAX)
+ old.shm_segsz = INT_MAX;
+ else
+ CP(buf, old, shm_segsz);
+ CP(buf, old, shm_lpid);
+ CP(buf, old, shm_cpid);
+ if (buf.shm_nattch > SHRT_MAX)
+ old.shm_nattch = SHRT_MAX;
+ else
+ CP(buf, old, shm_nattch);
+ CP(buf, old, shm_atime);
+ CP(buf, old, shm_dtime);
+ CP(buf, old, shm_ctime);
+ old.shm_internal = NULL;
+ error = copyout(&old, uap->buf, sizeof(old));
+ break;
+ }
+
+done:
+ if (error) {
+ /* Invalidate the return value */
+ td->td_retval[0] = -1;
+ }
+ return (error);
+}
+
+SYSCALL_MODULE_HELPER(freebsd7_shmctl);
+
+#undef CP
+
+#endif /* COMPAT_FREEBSD4 || COMPAT_FREEBSD5 || COMPAT_FREEBSD6 ||
+ COMPAT_FREEBSD7 */
+
static int
sysvshm_modload(struct module *module, int cmd, void *arg)
{
OpenPOWER on IntegriCloud