summaryrefslogtreecommitdiffstats
path: root/sys
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
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')
-rw-r--r--sys/compat/freebsd32/freebsd32_ipc.h78
-rw-r--r--sys/compat/freebsd32/freebsd32_misc.c289
-rw-r--r--sys/compat/freebsd32/syscalls.master16
-rw-r--r--sys/compat/linux/linux_ipc.c24
-rw-r--r--sys/compat/svr4/svr4_ipc.c33
-rw-r--r--sys/i386/ibcs2/ibcs2_ipc.c6
-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
-rw-r--r--sys/sys/ipc.h24
-rw-r--r--sys/sys/msg.h25
-rw-r--r--sys/sys/sem.h27
-rw-r--r--sys/sys/shm.h21
15 files changed, 733 insertions, 120 deletions
diff --git a/sys/compat/freebsd32/freebsd32_ipc.h b/sys/compat/freebsd32/freebsd32_ipc.h
index 93b5409..2b07494 100644
--- a/sys/compat/freebsd32/freebsd32_ipc.h
+++ b/sys/compat/freebsd32/freebsd32_ipc.h
@@ -30,11 +30,11 @@
#define _COMPAT_FREEBSD32_FREEBSD32_IPC_H_
struct ipc_perm32 {
- uint16_t cuid;
- uint16_t cgid;
- uint16_t uid;
- uint16_t gid;
- uint16_t mode;
+ uid_t cuid;
+ gid_t cgid;
+ uid_t uid;
+ gid_t gid;
+ mode_t mode;
uint16_t seq;
uint32_t key;
};
@@ -44,10 +44,7 @@ struct semid_ds32 {
uint32_t sem_base;
unsigned short sem_nsems;
int32_t sem_otime;
- int32_t sem_pad1;
int32_t sem_ctime;
- int32_t sem_pad2;
- int32_t sem_pad3[4];
};
union semun32 {
@@ -66,24 +63,19 @@ struct msqid_ds32 {
pid_t msg_lspid;
pid_t msg_lrpid;
int32_t msg_stime;
- int32_t msg_pad1;
int32_t msg_rtime;
- int32_t msg_pad2;
int32_t msg_ctime;
- int32_t msg_pad3;
- int32_t msg_pad4[4];
};
struct shmid_ds32 {
struct ipc_perm32 shm_perm;
int32_t shm_segsz;
- int32_t shm_lpid;
- int32_t shm_cpid;
- int16_t shm_nattch;
+ pid_t shm_lpid;
+ pid_t shm_cpid;
+ int shm_nattch;
int32_t shm_atime;
int32_t shm_dtime;
int32_t shm_ctime;
- uint32_t shm_internal;
};
struct shm_info32 {
@@ -103,4 +95,58 @@ struct shminfo32 {
uint32_t shmall;
};
+#if defined(COMPAT_FREEBSD4) || defined(COMPAT_FREEBSD5) || \
+ defined(COMPAT_FREEBSD6) || defined(COMPAT_FREEBSD7)
+struct ipc_perm32_old {
+ uint16_t cuid;
+ uint16_t cgid;
+ uint16_t uid;
+ uint16_t gid;
+ uint16_t mode;
+ uint16_t seq;
+ uint32_t key;
+};
+
+struct semid_ds32_old {
+ struct ipc_perm32_old sem_perm;
+ uint32_t sem_base;
+ unsigned short sem_nsems;
+ int32_t sem_otime;
+ int32_t sem_pad1;
+ int32_t sem_ctime;
+ int32_t sem_pad2;
+ int32_t sem_pad3[4];
+};
+
+struct msqid_ds32_old {
+ struct ipc_perm32_old msg_perm;
+ uint32_t msg_first;
+ uint32_t msg_last;
+ uint32_t msg_cbytes;
+ uint32_t msg_qnum;
+ uint32_t msg_qbytes;
+ pid_t msg_lspid;
+ pid_t msg_lrpid;
+ int32_t msg_stime;
+ int32_t msg_pad1;
+ int32_t msg_rtime;
+ int32_t msg_pad2;
+ int32_t msg_ctime;
+ int32_t msg_pad3;
+ int32_t msg_pad4[4];
+};
+
+struct shmid_ds32_old {
+ struct ipc_perm32_old shm_perm;
+ int32_t shm_segsz;
+ pid_t shm_lpid;
+ pid_t shm_cpid;
+ int16_t shm_nattch;
+ int32_t shm_atime;
+ int32_t shm_dtime;
+ int32_t shm_ctime;
+ uint32_t shm_internal;
+};
+#endif
+
#endif /* !_COMPAT_FREEBSD32_FREEBSD32_IPC_H_ */
diff --git a/sys/compat/freebsd32/freebsd32_misc.c b/sys/compat/freebsd32/freebsd32_misc.c
index 9301b8d..7509c45 100644
--- a/sys/compat/freebsd32/freebsd32_misc.c
+++ b/sys/compat/freebsd32/freebsd32_misc.c
@@ -1353,6 +1353,35 @@ freebsd4_freebsd32_fhstatfs(struct thread *td, struct freebsd4_freebsd32_fhstatf
}
#endif
+#if defined(COMPAT_FREEBSD4) || defined(COMPAT_FREEBSD5) || \
+ defined(COMPAT_FREEBSD6) || defined(COMPAT_FREEBSD7)
+static void
+freebsd32_ipcperm_old_in(struct ipc_perm32_old *ip32, struct ipc_perm *ip)
+{
+
+ CP(*ip32, *ip, cuid);
+ CP(*ip32, *ip, cgid);
+ CP(*ip32, *ip, uid);
+ CP(*ip32, *ip, gid);
+ CP(*ip32, *ip, mode);
+ CP(*ip32, *ip, seq);
+ CP(*ip32, *ip, key);
+}
+
+static void
+freebsd32_ipcperm_old_out(struct ipc_perm *ip, struct ipc_perm32_old *ip32)
+{
+
+ CP(*ip, *ip32, cuid);
+ CP(*ip, *ip32, cgid);
+ CP(*ip, *ip32, uid);
+ CP(*ip, *ip32, gid);
+ CP(*ip, *ip32, mode);
+ CP(*ip, *ip32, seq);
+ CP(*ip, *ip32, key);
+}
+#endif
+
static void
freebsd32_ipcperm_in(struct ipc_perm32 *ip32, struct ipc_perm *ip)
{
@@ -1383,6 +1412,8 @@ int
freebsd32_semsys(struct thread *td, struct freebsd32_semsys_args *uap)
{
+#if defined(COMPAT_FREEBSD4) || defined(COMPAT_FREEBSD5) || \
+ defined(COMPAT_FREEBSD6) || defined(COMPAT_FREEBSD7)
switch (uap->which) {
case 0:
return (freebsd32_semctl(td,
@@ -1390,7 +1421,85 @@ freebsd32_semsys(struct thread *td, struct freebsd32_semsys_args *uap)
default:
return (semsys(td, (struct semsys_args *)uap));
}
+#else
+ return (nosys(td, NULL));
+#endif
+}
+
+#if defined(COMPAT_FREEBSD4) || defined(COMPAT_FREEBSD5) || \
+ defined(COMPAT_FREEBSD6) || defined(COMPAT_FREEBSD7)
+int
+freebsd7_freebsd32_semctl(struct thread *td,
+ struct freebsd7_freebsd32_semctl_args *uap)
+{
+ struct semid_ds32_old dsbuf32;
+ struct semid_ds dsbuf;
+ union semun semun;
+ union semun32 arg;
+ 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(PTRIN(arg.buf), &dsbuf32, sizeof(dsbuf32));
+ if (error)
+ return (error);
+ freebsd32_ipcperm_old_in(&dsbuf32.sem_perm, &dsbuf.sem_perm);
+ PTRIN_CP(dsbuf32, dsbuf, sem_base);
+ CP(dsbuf32, dsbuf, sem_nsems);
+ CP(dsbuf32, dsbuf, sem_otime);
+ CP(dsbuf32, dsbuf, sem_ctime);
+ semun.buf = &dsbuf;
+ break;
+ case GETALL:
+ case SETALL:
+ semun.array = PTRIN(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(&dsbuf32, sizeof(dsbuf32));
+ freebsd32_ipcperm_old_out(&dsbuf.sem_perm, &dsbuf32.sem_perm);
+ PTROUT_CP(dsbuf, dsbuf32, sem_base);
+ CP(dsbuf, dsbuf32, sem_nsems);
+ CP(dsbuf, dsbuf32, sem_otime);
+ CP(dsbuf, dsbuf32, sem_ctime);
+ error = copyout(&dsbuf32, PTRIN(arg.buf), sizeof(dsbuf32));
+ break;
+ }
+
+ if (error == 0)
+ td->td_retval[0] = rval;
+ return (error);
}
+#endif
int
freebsd32_semctl(struct thread *td, struct freebsd32_semctl_args *uap)
@@ -1428,13 +1537,7 @@ freebsd32_semctl(struct thread *td, struct freebsd32_semctl_args *uap)
PTRIN_CP(dsbuf32, dsbuf, sem_base);
CP(dsbuf32, dsbuf, sem_nsems);
CP(dsbuf32, dsbuf, sem_otime);
- CP(dsbuf32, dsbuf, sem_pad1);
CP(dsbuf32, dsbuf, sem_ctime);
- CP(dsbuf32, dsbuf, sem_pad2);
- CP(dsbuf32, dsbuf, sem_pad3[0]);
- CP(dsbuf32, dsbuf, sem_pad3[1]);
- CP(dsbuf32, dsbuf, sem_pad3[2]);
- CP(dsbuf32, dsbuf, sem_pad3[3]);
semun.buf = &dsbuf;
break;
case GETALL:
@@ -1454,17 +1557,12 @@ freebsd32_semctl(struct thread *td, struct freebsd32_semctl_args *uap)
switch (uap->cmd) {
case SEM_STAT:
case IPC_STAT:
+ bzero(&dsbuf32, sizeof(dsbuf32));
freebsd32_ipcperm_out(&dsbuf.sem_perm, &dsbuf32.sem_perm);
PTROUT_CP(dsbuf, dsbuf32, sem_base);
CP(dsbuf, dsbuf32, sem_nsems);
CP(dsbuf, dsbuf32, sem_otime);
- CP(dsbuf, dsbuf32, sem_pad1);
CP(dsbuf, dsbuf32, sem_ctime);
- CP(dsbuf, dsbuf32, sem_pad2);
- CP(dsbuf, dsbuf32, sem_pad3[0]);
- CP(dsbuf, dsbuf32, sem_pad3[1]);
- CP(dsbuf, dsbuf32, sem_pad3[2]);
- CP(dsbuf, dsbuf32, sem_pad3[3]);
error = copyout(&dsbuf32, PTRIN(arg.buf), sizeof(dsbuf32));
break;
}
@@ -1478,6 +1576,8 @@ int
freebsd32_msgsys(struct thread *td, struct freebsd32_msgsys_args *uap)
{
+#if defined(COMPAT_FREEBSD4) || defined(COMPAT_FREEBSD5) || \
+ defined(COMPAT_FREEBSD6) || defined(COMPAT_FREEBSD7)
switch (uap->which) {
case 0:
return (freebsd32_msgctl(td,
@@ -1491,8 +1591,59 @@ freebsd32_msgsys(struct thread *td, struct freebsd32_msgsys_args *uap)
default:
return (msgsys(td, (struct msgsys_args *)uap));
}
+#else
+ return (nosys(td, NULL));
+#endif
}
+#if defined(COMPAT_FREEBSD4) || defined(COMPAT_FREEBSD5) || \
+ defined(COMPAT_FREEBSD6) || defined(COMPAT_FREEBSD7)
+int
+freebsd7_freebsd32_msgctl(struct thread *td,
+ struct freebsd7_freebsd32_msgctl_args *uap)
+{
+ struct msqid_ds msqbuf;
+ struct msqid_ds32_old msqbuf32;
+ int error;
+
+ if (uap->cmd == IPC_SET) {
+ error = copyin(uap->buf, &msqbuf32, sizeof(msqbuf32));
+ if (error)
+ return (error);
+ freebsd32_ipcperm_old_in(&msqbuf32.msg_perm, &msqbuf.msg_perm);
+ PTRIN_CP(msqbuf32, msqbuf, msg_first);
+ PTRIN_CP(msqbuf32, msqbuf, msg_last);
+ CP(msqbuf32, msqbuf, msg_cbytes);
+ CP(msqbuf32, msqbuf, msg_qnum);
+ CP(msqbuf32, msqbuf, msg_qbytes);
+ CP(msqbuf32, msqbuf, msg_lspid);
+ CP(msqbuf32, msqbuf, msg_lrpid);
+ CP(msqbuf32, msqbuf, msg_stime);
+ CP(msqbuf32, msqbuf, msg_rtime);
+ CP(msqbuf32, msqbuf, msg_ctime);
+ }
+ error = kern_msgctl(td, uap->msqid, uap->cmd, &msqbuf);
+ if (error)
+ return (error);
+ if (uap->cmd == IPC_STAT) {
+ bzero(&msqbuf32, sizeof(msqbuf32));
+ freebsd32_ipcperm_old_out(&msqbuf.msg_perm, &msqbuf32.msg_perm);
+ PTROUT_CP(msqbuf, msqbuf32, msg_first);
+ PTROUT_CP(msqbuf, msqbuf32, msg_last);
+ CP(msqbuf, msqbuf32, msg_cbytes);
+ CP(msqbuf, msqbuf32, msg_qnum);
+ CP(msqbuf, msqbuf32, msg_qbytes);
+ CP(msqbuf, msqbuf32, msg_lspid);
+ CP(msqbuf, msqbuf32, msg_lrpid);
+ CP(msqbuf, msqbuf32, msg_stime);
+ CP(msqbuf, msqbuf32, msg_rtime);
+ CP(msqbuf, msqbuf32, msg_ctime);
+ error = copyout(&msqbuf32, uap->buf, sizeof(struct msqid_ds32));
+ }
+ return (error);
+}
+#endif
+
int
freebsd32_msgctl(struct thread *td, struct freebsd32_msgctl_args *uap)
{
@@ -1513,15 +1664,8 @@ freebsd32_msgctl(struct thread *td, struct freebsd32_msgctl_args *uap)
CP(msqbuf32, msqbuf, msg_lspid);
CP(msqbuf32, msqbuf, msg_lrpid);
CP(msqbuf32, msqbuf, msg_stime);
- CP(msqbuf32, msqbuf, msg_pad1);
CP(msqbuf32, msqbuf, msg_rtime);
- CP(msqbuf32, msqbuf, msg_pad2);
CP(msqbuf32, msqbuf, msg_ctime);
- CP(msqbuf32, msqbuf, msg_pad3);
- CP(msqbuf32, msqbuf, msg_pad4[0]);
- CP(msqbuf32, msqbuf, msg_pad4[1]);
- CP(msqbuf32, msqbuf, msg_pad4[2]);
- CP(msqbuf32, msqbuf, msg_pad4[3]);
}
error = kern_msgctl(td, uap->msqid, uap->cmd, &msqbuf);
if (error)
@@ -1536,15 +1680,8 @@ freebsd32_msgctl(struct thread *td, struct freebsd32_msgctl_args *uap)
CP(msqbuf, msqbuf32, msg_lspid);
CP(msqbuf, msqbuf32, msg_lrpid);
CP(msqbuf, msqbuf32, msg_stime);
- CP(msqbuf, msqbuf32, msg_pad1);
CP(msqbuf, msqbuf32, msg_rtime);
- CP(msqbuf, msqbuf32, msg_pad2);
CP(msqbuf, msqbuf32, msg_ctime);
- CP(msqbuf, msqbuf32, msg_pad3);
- CP(msqbuf, msqbuf32, msg_pad4[0]);
- CP(msqbuf, msqbuf32, msg_pad4[1]);
- CP(msqbuf, msqbuf32, msg_pad4[2]);
- CP(msqbuf, msqbuf32, msg_pad4[3]);
error = copyout(&msqbuf32, uap->buf, sizeof(struct msqid_ds32));
}
return (error);
@@ -1588,6 +1725,8 @@ int
freebsd32_shmsys(struct thread *td, struct freebsd32_shmsys_args *uap)
{
+#if defined(COMPAT_FREEBSD4) || defined(COMPAT_FREEBSD5) || \
+ defined(COMPAT_FREEBSD6) || defined(COMPAT_FREEBSD7)
switch (uap->which) {
case 0: { /* shmat */
struct shmat_args ap;
@@ -1623,8 +1762,99 @@ freebsd32_shmsys(struct thread *td, struct freebsd32_shmsys_args *uap)
default:
return (EINVAL);
}
+#else
+ return (nosys(td, NULL));
+#endif
}
+#if defined(COMPAT_FREEBSD4) || defined(COMPAT_FREEBSD5) || \
+ defined(COMPAT_FREEBSD6) || defined(COMPAT_FREEBSD7)
+int
+freebsd7_freebsd32_shmctl(struct thread *td,
+ struct freebsd7_freebsd32_shmctl_args *uap)
+{
+ int error = 0;
+ union {
+ struct shmid_ds shmid_ds;
+ struct shm_info shm_info;
+ struct shminfo shminfo;
+ } u;
+ union {
+ struct shmid_ds32_old shmid_ds32;
+ struct shm_info32 shm_info32;
+ struct shminfo32 shminfo32;
+ } u32;
+ size_t sz;
+
+ if (uap->cmd == IPC_SET) {
+ if ((error = copyin(uap->buf, &u32.shmid_ds32,
+ sizeof(u32.shmid_ds32))))
+ goto done;
+ freebsd32_ipcperm_old_in(&u32.shmid_ds32.shm_perm,
+ &u.shmid_ds.shm_perm);
+ CP(u32.shmid_ds32, u.shmid_ds, shm_segsz);
+ CP(u32.shmid_ds32, u.shmid_ds, shm_lpid);
+ CP(u32.shmid_ds32, u.shmid_ds, shm_cpid);
+ CP(u32.shmid_ds32, u.shmid_ds, shm_nattch);
+ CP(u32.shmid_ds32, u.shmid_ds, shm_atime);
+ CP(u32.shmid_ds32, u.shmid_ds, shm_dtime);
+ CP(u32.shmid_ds32, u.shmid_ds, shm_ctime);
+ }
+
+ error = kern_shmctl(td, uap->shmid, uap->cmd, (void *)&u, &sz);
+ if (error)
+ goto done;
+
+ /* Cases in which we need to copyout */
+ switch (uap->cmd) {
+ case IPC_INFO:
+ CP(u.shminfo, u32.shminfo32, shmmax);
+ CP(u.shminfo, u32.shminfo32, shmmin);
+ CP(u.shminfo, u32.shminfo32, shmmni);
+ CP(u.shminfo, u32.shminfo32, shmseg);
+ CP(u.shminfo, u32.shminfo32, shmall);
+ error = copyout(&u32.shminfo32, uap->buf,
+ sizeof(u32.shminfo32));
+ break;
+ case SHM_INFO:
+ CP(u.shm_info, u32.shm_info32, used_ids);
+ CP(u.shm_info, u32.shm_info32, shm_rss);
+ CP(u.shm_info, u32.shm_info32, shm_tot);
+ CP(u.shm_info, u32.shm_info32, shm_swp);
+ CP(u.shm_info, u32.shm_info32, swap_attempts);
+ CP(u.shm_info, u32.shm_info32, swap_successes);
+ error = copyout(&u32.shm_info32, uap->buf,
+ sizeof(u32.shm_info32));
+ break;
+ case SHM_STAT:
+ case IPC_STAT:
+ freebsd32_ipcperm_old_out(&u.shmid_ds.shm_perm,
+ &u32.shmid_ds32.shm_perm);
+ if (u.shmid_ds.shm_segsz > INT32_MAX)
+ u32.shmid_ds32.shm_segsz = INT32_MAX;
+ else
+ CP(u.shmid_ds, u32.shmid_ds32, shm_segsz);
+ CP(u.shmid_ds, u32.shmid_ds32, shm_lpid);
+ CP(u.shmid_ds, u32.shmid_ds32, shm_cpid);
+ CP(u.shmid_ds, u32.shmid_ds32, shm_nattch);
+ CP(u.shmid_ds, u32.shmid_ds32, shm_atime);
+ CP(u.shmid_ds, u32.shmid_ds32, shm_dtime);
+ CP(u.shmid_ds, u32.shmid_ds32, shm_ctime);
+ u32.shmid_ds32.shm_internal = 0;
+ error = copyout(&u32.shmid_ds32, uap->buf,
+ sizeof(u32.shmid_ds32));
+ break;
+ }
+
+done:
+ if (error) {
+ /* Invalidate the return value */
+ td->td_retval[0] = -1;
+ }
+ return (error);
+}
+#endif
+
int
freebsd32_shmctl(struct thread *td, struct freebsd32_shmctl_args *uap)
{
@@ -1654,7 +1884,6 @@ freebsd32_shmctl(struct thread *td, struct freebsd32_shmctl_args *uap)
CP(u32.shmid_ds32, u.shmid_ds, shm_atime);
CP(u32.shmid_ds32, u.shmid_ds, shm_dtime);
CP(u32.shmid_ds32, u.shmid_ds, shm_ctime);
- PTRIN_CP(u32.shmid_ds32, u.shmid_ds, shm_internal);
}
error = kern_shmctl(td, uap->shmid, uap->cmd, (void *)&u, &sz);
@@ -1686,14 +1915,16 @@ freebsd32_shmctl(struct thread *td, struct freebsd32_shmctl_args *uap)
case IPC_STAT:
freebsd32_ipcperm_out(&u.shmid_ds.shm_perm,
&u32.shmid_ds32.shm_perm);
- CP(u.shmid_ds, u32.shmid_ds32, shm_segsz);
+ if (u.shmid_ds.shm_segsz > INT32_MAX)
+ u32.shmid_ds32.shm_segsz = INT32_MAX;
+ else
+ CP(u.shmid_ds, u32.shmid_ds32, shm_segsz);
CP(u.shmid_ds, u32.shmid_ds32, shm_lpid);
CP(u.shmid_ds, u32.shmid_ds32, shm_cpid);
CP(u.shmid_ds, u32.shmid_ds32, shm_nattch);
CP(u.shmid_ds, u32.shmid_ds32, shm_atime);
CP(u.shmid_ds, u32.shmid_ds32, shm_dtime);
CP(u.shmid_ds, u32.shmid_ds32, shm_ctime);
- PTROUT_CP(u.shmid_ds, u32.shmid_ds32, shm_internal);
error = copyout(&u32.shmid_ds32, uap->buf,
sizeof(u32.shmid_ds32));
break;
diff --git a/sys/compat/freebsd32/syscalls.master b/sys/compat/freebsd32/syscalls.master
index 5b3fd9f..6e0f886 100644
--- a/sys/compat/freebsd32/syscalls.master
+++ b/sys/compat/freebsd32/syscalls.master
@@ -405,15 +405,15 @@
; The following were introduced with NetBSD/4.4Lite-2
; They are initialized by thier respective modules/sysinits
; XXX PROBLEM!!
-220 AUE_SEMCTL STD { int freebsd32_semctl(int semid, int semnum, \
+220 AUE_SEMCTL COMPAT7 { int freebsd32_semctl(int semid, int semnum, \
int cmd, union semun32 *arg); }
221 AUE_SEMGET NOPROTO { int semget(key_t key, int nsems, \
int semflg); }
222 AUE_SEMOP NOPROTO { int semop(int semid, struct sembuf *sops, \
u_int nsops); }
223 AUE_NULL UNIMPL semconfig
-224 AUE_MSGCTL STD { int freebsd32_msgctl(int msqid, int cmd, \
- struct msqid_ds32 *buf); }
+224 AUE_MSGCTL COMPAT7 { int freebsd32_msgctl(int msqid, int cmd, \
+ struct msqid_ds32_old *buf); }
225 AUE_MSGGET NOPROTO { int msgget(key_t key, int msgflg); }
226 AUE_MSGSND STD { int freebsd32_msgsnd(int msqid, void *msgp, \
size_t msgsz, int msgflg); }
@@ -421,8 +421,8 @@
size_t msgsz, long msgtyp, int msgflg); }
228 AUE_SHMAT NOPROTO { int shmat(int shmid, void *shmaddr, \
int shmflg); }
-229 AUE_SHMCTL STD { int freebsd32_shmctl(int shmid, int cmd, \
- struct shmid_ds *buf); }
+229 AUE_SHMCTL COMPAT7 { int freebsd32_shmctl(int shmid, int cmd, \
+ struct shmid_ds32_old *buf); }
230 AUE_SHMDT NOPROTO { int shmdt(void *shmaddr); }
231 AUE_SHMGET NOPROTO { int shmget(key_t key, int size, \
int shmflg); }
@@ -894,3 +894,9 @@
unsigned int iovcnt, int flags); }
508 AUE_NULL NOPROTO { int jail_remove(int jid); }
509 AUE_CLOSEFROM NOPROTO { int closefrom(int lowfd); }
+510 AUE_SEMCTL STD { int freebsd32_semctl(int semid, int semnum, \
+ int cmd, union semun32 *arg); }
+511 AUE_MSGCTL STD { int freebsd32_msgctl(int msqid, int cmd, \
+ struct msqid_ds32 *buf); }
+512 AUE_SHMCTL STD { int freebsd32_shmctl(int shmid, int cmd, \
+ struct shmid_ds32 *buf); }
diff --git a/sys/compat/linux/linux_ipc.c b/sys/compat/linux/linux_ipc.c
index 273c2f7..0a46a05 100644
--- a/sys/compat/linux/linux_ipc.c
+++ b/sys/compat/linux/linux_ipc.c
@@ -230,23 +230,26 @@ linux_to_bsd_shmid_ds(struct l_shmid_ds *lsp, struct shmid_ds *bsp)
bsp->shm_atime = lsp->shm_atime;
bsp->shm_dtime = lsp->shm_dtime;
bsp->shm_ctime = lsp->shm_ctime;
- /* this goes (yet) SOS */
- bsp->shm_internal = PTRIN(lsp->private3);
}
static void
bsd_to_linux_shmid_ds(struct shmid_ds *bsp, struct l_shmid_ds *lsp)
{
bsd_to_linux_ipc_perm(&bsp->shm_perm, &lsp->shm_perm);
- lsp->shm_segsz = bsp->shm_segsz;
+ if (bsp->shm_segsz > INT_MAX)
+ lsp->shm_segsz = INT_MAX;
+ else
+ lsp->shm_segsz = bsp->shm_segsz;
lsp->shm_lpid = bsp->shm_lpid;
lsp->shm_cpid = bsp->shm_cpid;
- lsp->shm_nattch = bsp->shm_nattch;
+ if (bsp->shm_nattch > SHRT_MAX)
+ lsp->shm_nattch = SHRT_MAX;
+ else
+ lsp->shm_nattch = bsp->shm_nattch;
lsp->shm_atime = bsp->shm_atime;
lsp->shm_dtime = bsp->shm_dtime;
lsp->shm_ctime = bsp->shm_ctime;
- /* this goes (yet) SOS */
- lsp->private3 = PTROUT(bsp->shm_internal);
+ lsp->private3 = 0;
}
static void
@@ -424,6 +427,15 @@ linux_shmid_pushdown(l_int ver, struct l_shmid_ds *linux_shmid, caddr_t uaddr)
{
struct l_shmid64_ds linux_shmid64;
+ /*
+ * XXX: This is backwards and loses information in shm_nattch
+ * and shm_segsz. We should probably either expose the BSD
+ * shmid structure directly and convert it to either the
+ * non-64 or 64 variant directly or the code should always
+ * convert to the 64 variant and then truncate values into the
+ * non-64 variant if needed since the 64 variant has more
+ * precision.
+ */
if (ver == LINUX_IPC_64) {
bzero(&linux_shmid64, sizeof(linux_shmid64));
diff --git a/sys/compat/svr4/svr4_ipc.c b/sys/compat/svr4/svr4_ipc.c
index 317239c..658c6d6 100644
--- a/sys/compat/svr4/svr4_ipc.c
+++ b/sys/compat/svr4/svr4_ipc.c
@@ -169,13 +169,12 @@ bsd_to_svr4_semid_ds(bds, sds)
const struct semid_ds *bds;
struct svr4_semid_ds *sds;
{
+ bzero(sds, sizeof(*sds));
bsd_to_svr4_ipc_perm(&bds->sem_perm, &sds->sem_perm);
sds->sem_base = (struct svr4_sem *) bds->sem_base;
sds->sem_nsems = bds->sem_nsems;
sds->sem_otime = bds->sem_otime;
- sds->sem_pad1 = bds->sem_pad1;
sds->sem_ctime = bds->sem_ctime;
- sds->sem_pad2 = bds->sem_pad2;
}
static void
@@ -187,9 +186,7 @@ svr4_to_bsd_semid_ds(sds, bds)
bds->sem_base = (struct sem *) bds->sem_base;
bds->sem_nsems = sds->sem_nsems;
bds->sem_otime = sds->sem_otime;
- bds->sem_pad1 = sds->sem_pad1;
bds->sem_ctime = sds->sem_ctime;
- bds->sem_pad2 = sds->sem_pad2;
}
struct svr4_sys_semctl_args {
@@ -350,6 +347,7 @@ bsd_to_svr4_msqid_ds(bds, sds)
const struct msqid_ds *bds;
struct svr4_msqid_ds *sds;
{
+ bzero(sds, sizeof(*sds));
bsd_to_svr4_ipc_perm(&bds->msg_perm, &sds->msg_perm);
sds->msg_first = (struct svr4_msg *) bds->msg_first;
sds->msg_last = (struct svr4_msg *) bds->msg_last;
@@ -359,18 +357,8 @@ bsd_to_svr4_msqid_ds(bds, sds)
sds->msg_lspid = bds->msg_lspid;
sds->msg_lrpid = bds->msg_lrpid;
sds->msg_stime = bds->msg_stime;
- sds->msg_pad1 = bds->msg_pad1;
sds->msg_rtime = bds->msg_rtime;
- sds->msg_pad2 = bds->msg_pad2;
sds->msg_ctime = bds->msg_ctime;
- sds->msg_pad3 = bds->msg_pad3;
-
- /* use the padding for the rest of the fields */
- {
- const short *pad = (const short *) bds->msg_pad4;
- sds->msg_cv = pad[0];
- sds->msg_qnum_cv = pad[1];
- }
}
static void
@@ -387,18 +375,8 @@ svr4_to_bsd_msqid_ds(sds, bds)
bds->msg_lspid = sds->msg_lspid;
bds->msg_lrpid = sds->msg_lrpid;
bds->msg_stime = sds->msg_stime;
- bds->msg_pad1 = sds->msg_pad1;
bds->msg_rtime = sds->msg_rtime;
- bds->msg_pad2 = sds->msg_pad2;
bds->msg_ctime = sds->msg_ctime;
- bds->msg_pad3 = sds->msg_pad3;
-
- /* use the padding for the rest of the fields */
- {
- short *pad = (short *) bds->msg_pad4;
- pad[0] = sds->msg_cv;
- pad[1] = sds->msg_qnum_cv;
- }
}
struct svr4_sys_msgsnd_args {
@@ -543,20 +521,18 @@ bsd_to_svr4_shmid_ds(bds, sds)
const struct shmid_ds *bds;
struct svr4_shmid_ds *sds;
{
+ bzero(sds, sizeof(*sds));
bsd_to_svr4_ipc_perm(&bds->shm_perm, &sds->shm_perm);
sds->shm_segsz = bds->shm_segsz;
sds->shm_lkcnt = 0;
sds->shm_lpid = bds->shm_lpid;
sds->shm_cpid = bds->shm_cpid;
- sds->shm_amp = bds->shm_internal;
+ sds->shm_amp = 0;
sds->shm_nattch = bds->shm_nattch;
sds->shm_cnattch = 0;
sds->shm_atime = bds->shm_atime;
- sds->shm_pad1 = 0;
sds->shm_dtime = bds->shm_dtime;
- sds->shm_pad2 = 0;
sds->shm_ctime = bds->shm_ctime;
- sds->shm_pad3 = 0;
}
static void
@@ -568,7 +544,6 @@ svr4_to_bsd_shmid_ds(sds, bds)
bds->shm_segsz = sds->shm_segsz;
bds->shm_lpid = sds->shm_lpid;
bds->shm_cpid = sds->shm_cpid;
- bds->shm_internal = sds->shm_amp;
bds->shm_nattch = sds->shm_nattch;
bds->shm_atime = sds->shm_atime;
bds->shm_dtime = sds->shm_dtime;
diff --git a/sys/i386/ibcs2/ibcs2_ipc.c b/sys/i386/ibcs2/ibcs2_ipc.c
index 5b6342a..f606c1b 100644
--- a/sys/i386/ibcs2/ibcs2_ipc.c
+++ b/sys/i386/ibcs2/ibcs2_ipc.c
@@ -415,7 +415,10 @@ struct ibcs2_shmid_ds *ibp;
ibp->shm_segsz = bp->shm_segsz;
ibp->shm_lpid = bp->shm_lpid;
ibp->shm_cpid = bp->shm_cpid;
- ibp->shm_nattch = bp->shm_nattch;
+ if (bp->shm_nattch > SHRT_MAX)
+ ibp->shm_nattch = SHRT_MAX;
+ else
+ ibp->shm_nattch = bp->shm_nattch;
ibp->shm_cnattch = 0; /* ignored anyway */
ibp->shm_atime = bp->shm_atime;
ibp->shm_dtime = bp->shm_dtime;
@@ -436,7 +439,6 @@ struct shmid_ds *bp;
bp->shm_atime = ibp->shm_atime;
bp->shm_dtime = ibp->shm_dtime;
bp->shm_ctime = ibp->shm_ctime;
- bp->shm_internal = (void *)0; /* ignored anyway */
return;
}
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)
{
diff --git a/sys/sys/ipc.h b/sys/sys/ipc.h
index 139b103..c72d913 100644
--- a/sys/sys/ipc.h
+++ b/sys/sys/ipc.h
@@ -69,10 +69,9 @@ typedef __uid_t uid_t;
#define _UID_T_DECLARED
#endif
-/*
- * XXX almost all members have wrong types.
- */
-struct ipc_perm {
+#if defined(COMPAT_FREEBSD4) || defined(COMPAT_FREEBSD5) || \
+ defined(COMPAT_FREEBSD6) || defined(COMPAT_FREEBSD7)
+struct ipc_perm_old {
unsigned short cuid; /* creator user id */
unsigned short cgid; /* creator group id */
unsigned short uid; /* user id */
@@ -81,6 +80,17 @@ struct ipc_perm {
unsigned short seq; /* sequence # (to generate unique ipcid) */
key_t key; /* user specified msg/sem/shm key */
};
+#endif
+
+struct ipc_perm {
+ uid_t cuid; /* creator user id */
+ gid_t cgid; /* creator group id */
+ uid_t uid; /* user id */
+ gid_t gid; /* group id */
+ mode_t mode; /* r/w permission */
+ unsigned short seq; /* sequence # (to generate unique ipcid) */
+ key_t key; /* user specified msg/sem/shm key */
+};
#if __BSD_VISIBLE
/* common mode bits */
@@ -116,6 +126,12 @@ struct thread;
struct proc;
struct vmspace;
+#if defined(COMPAT_FREEBSD4) || defined(COMPAT_FREEBSD5) || \
+ defined(COMPAT_FREEBSD6) || defined(COMPAT_FREEBSD7)
+void ipcperm_old2new(struct ipc_perm_old *, struct ipc_perm *);
+void ipcperm_new2old(struct ipc_perm *, struct ipc_perm_old *);
+#endif
+
int ipcperm(struct thread *, struct ipc_perm *, int);
extern void (*shmfork_hook)(struct proc *, struct proc *);
extern void (*shmexit_hook)(struct vmspace *);
diff --git a/sys/sys/msg.h b/sys/sys/msg.h
index 325df93..e4edd09 100644
--- a/sys/sys/msg.h
+++ b/sys/sys/msg.h
@@ -57,6 +57,27 @@ typedef __time_t time_t;
#define _TIME_T_DECLARED
#endif
+#if defined(COMPAT_FREEBSD4) || defined(COMPAT_FREEBSD5) || \
+ defined(COMPAT_FREEBSD6) || defined(COMPAT_FREEBSD7)
+struct msqid_ds_old {
+ struct ipc_perm_old msg_perm; /* msg queue permission bits */
+ struct msg *msg_first; /* first message in the queue */
+ struct msg *msg_last; /* last message in the queue */
+ msglen_t msg_cbytes; /* number of bytes in use on the queue */
+ msgqnum_t msg_qnum; /* number of msgs in the queue */
+ msglen_t msg_qbytes; /* max # of bytes on the queue */
+ pid_t msg_lspid; /* pid of last msgsnd() */
+ pid_t msg_lrpid; /* pid of last msgrcv() */
+ time_t msg_stime; /* time of last msgsnd() */
+ long msg_pad1;
+ time_t msg_rtime; /* time of last msgrcv() */
+ long msg_pad2;
+ time_t msg_ctime; /* time of last msgctl() */
+ long msg_pad3;
+ long msg_pad4[4];
+};
+#endif
+
/*
* XXX there seems to be no prefix reserved for this header, so the name
* "msg" in "struct msg" and the names of all of the nonstandard members
@@ -73,12 +94,8 @@ struct msqid_ds {
pid_t msg_lspid; /* pid of last msgsnd() */
pid_t msg_lrpid; /* pid of last msgrcv() */
time_t msg_stime; /* time of last msgsnd() */
- long msg_pad1;
time_t msg_rtime; /* time of last msgrcv() */
- long msg_pad2;
time_t msg_ctime; /* time of last msgctl() */
- long msg_pad3;
- long msg_pad4[4];
};
#if __BSD_VISIBLE
diff --git a/sys/sys/sem.h b/sys/sys/sem.h
index d8d6e92..458ffb9 100644
--- a/sys/sys/sem.h
+++ b/sys/sys/sem.h
@@ -27,8 +27,10 @@ typedef __time_t time_t;
#define _TIME_T_DECLARED
#endif
-struct semid_ds {
- struct ipc_perm sem_perm; /* operation permission struct */
+#if defined(COMPAT_FREEBSD4) || defined(COMPAT_FREEBSD5) || \
+ defined(COMPAT_FREEBSD6) || defined(COMPAT_FREEBSD7)
+struct semid_ds_old {
+ struct ipc_perm_old sem_perm; /* operation permission struct */
struct sem *sem_base; /* pointer to first semaphore in set */
unsigned short sem_nsems; /* number of sems in set */
time_t sem_otime; /* last operation time */
@@ -39,6 +41,17 @@ struct semid_ds {
long sem_pad2; /* SVABI/386 says I need this here */
long sem_pad3[4]; /* SVABI/386 says I need this here */
};
+#endif
+
+struct semid_ds {
+ struct ipc_perm sem_perm; /* operation permission struct */
+ struct sem *sem_base; /* pointer to first semaphore in set */
+ unsigned short sem_nsems; /* number of sems in set */
+ time_t sem_otime; /* last operation time */
+ time_t sem_ctime; /* last change time */
+ /* Times measured in secs since */
+ /* 00:00:00 GMT, Jan. 1, 1970 */
+};
/*
* semop's sops parameter structure
@@ -50,6 +63,16 @@ struct sembuf {
};
#define SEM_UNDO 010000
+#if defined(COMPAT_FREEBSD4) || defined(COMPAT_FREEBSD5) || \
+ defined(COMPAT_FREEBSD6) || defined(COMPAT_FREEBSD7) || \
+ defined(_WANT_SEMUN_OLD)
+union semun_old {
+ int val; /* value for SETVAL */
+ struct semid_ds_old *buf; /* buffer for IPC_STAT & IPC_SET */
+ unsigned short *array; /* array for GETALL & SETALL */
+};
+#endif
+
/*
* semctl's arg parameter structure
*/
diff --git a/sys/sys/shm.h b/sys/sys/shm.h
index e6f2f76..7fe3dae 100644
--- a/sys/sys/shm.h
+++ b/sys/sys/shm.h
@@ -75,8 +75,10 @@ typedef __size_t size_t;
#define _SIZE_T_DECLARED
#endif
-struct shmid_ds {
- struct ipc_perm shm_perm; /* operation permission structure */
+#if defined(COMPAT_FREEBSD4) || defined(COMPAT_FREEBSD5) || \
+ defined(COMPAT_FREEBSD6) || defined(COMPAT_FREEBSD7)
+struct shmid_ds_old {
+ struct ipc_perm_old shm_perm; /* operation permission structure */
int shm_segsz; /* size of segment in bytes */
pid_t shm_lpid; /* process ID of last shared memory op */
pid_t shm_cpid; /* process ID of creator */
@@ -86,8 +88,21 @@ struct shmid_ds {
time_t shm_ctime; /* time of last change by shmctl() */
void *shm_internal; /* sysv stupidity */
};
+#endif
+
+struct shmid_ds {
+ struct ipc_perm shm_perm; /* operation permission structure */
+ size_t shm_segsz; /* size of segment in bytes */
+ pid_t shm_lpid; /* process ID of last shared memory op */
+ pid_t shm_cpid; /* process ID of creator */
+ int shm_nattch; /* number of current attaches */
+ time_t shm_atime; /* time of last shmat() */
+ time_t shm_dtime; /* time of last shmdt() */
+ time_t shm_ctime; /* time of last change by shmctl() */
+};
#ifdef _KERNEL
+#include <vm/vm.h>
/*
* System 5 style catch-all structure for shared memory constants that
@@ -107,8 +122,8 @@ struct shminfo {
*/
struct shmid_kernel {
struct shmid_ds u;
+ vm_object_t object;
struct label *label; /* MAC label */
- size_t shm_bsegsz;
};
extern struct shminfo shminfo;
OpenPOWER on IntegriCloud