summaryrefslogtreecommitdiffstats
path: root/sys/compat/linux/linux_ipc.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/compat/linux/linux_ipc.c')
-rw-r--r--sys/compat/linux/linux_ipc.c133
1 files changed, 73 insertions, 60 deletions
diff --git a/sys/compat/linux/linux_ipc.c b/sys/compat/linux/linux_ipc.c
index 92fa13d..4f95277 100644
--- a/sys/compat/linux/linux_ipc.c
+++ b/sys/compat/linux/linux_ipc.c
@@ -30,6 +30,7 @@
#include <sys/param.h>
#include <sys/systm.h>
+#include <sys/syscallsubr.h>
#include <sys/sysproto.h>
#include <sys/proc.h>
#include <sys/limits.h>
@@ -703,81 +704,93 @@ linux_shmctl(struct thread *td, struct linux_shmctl_args *args)
struct l_shmid_ds linux_shmid;
struct l_shminfo linux_shminfo;
struct l_shm_info linux_shm_info;
- struct shmctl_args /* {
- int shmid;
- int cmd;
- struct shmid_ds *buf;
- } */ bsd_args;
+ struct shmid_ds bsd_shmid;
+ size_t bufsz;
int error;
- caddr_t sg = stackgap_init();
switch (args->cmd & ~LINUX_IPC_64) {
- case LINUX_IPC_INFO:
- bsd_args.shmid = args->shmid;
- bsd_args.cmd = IPC_INFO;
- bsd_args.buf = (struct shmid_ds*)stackgap_alloc(&sg, sizeof(struct shminfo));
- if ((error = shmctl(td, &bsd_args)))
+ case LINUX_IPC_INFO: {
+ struct shminfo bsd_shminfo;
+
+ /* Perform shmctl wanting removed segments lookup */
+ error = kern_shmctl(td, args->shmid, IPC_INFO,
+ (void *)&bsd_shminfo, &bufsz, 1);
+ if (error)
return error;
- bsd_to_linux_shminfo( (struct shminfo *)bsd_args.buf, &linux_shminfo );
- return (linux_shminfo_pushdown(args->cmd & LINUX_IPC_64,
- &linux_shminfo, (caddr_t)args->buf));
-
- case LINUX_SHM_INFO:
- bsd_args.shmid = args->shmid;
- bsd_args.cmd = SHM_INFO;
- bsd_args.buf = (struct shmid_ds*)stackgap_alloc(&sg, sizeof(struct shm_info));
- if ((error = shmctl(td, &bsd_args)))
- return error;
- bsd_to_linux_shm_info( (struct shm_info *)bsd_args.buf, &linux_shm_info );
- return copyout(&linux_shm_info, (caddr_t)args->buf, sizeof(struct shm_info));
-
- case LINUX_IPC_STAT:
- bsd_args.shmid = args->shmid;
- bsd_args.cmd = IPC_STAT;
- bsd_args.buf = (struct shmid_ds*)stackgap_alloc(&sg, sizeof(struct shmid_ds));
- if ((error = shmctl(td, &bsd_args)))
- return error;
- bsd_to_linux_shmid_ds(bsd_args.buf, &linux_shmid);
- return (linux_shmid_pushdown(args->cmd & LINUX_IPC_64,
- &linux_shmid, (caddr_t)args->buf));
+
+ bsd_to_linux_shminfo(&bsd_shminfo, &linux_shminfo);
- case LINUX_SHM_STAT:
- bsd_args.shmid = args->shmid;
- bsd_args.cmd = SHM_STAT;
- bsd_args.buf = (struct shmid_ds*)stackgap_alloc(&sg, sizeof(struct shmid_ds));
- if ((error = shmctl(td, &bsd_args))) {
- return error;
+ return (linux_shminfo_pushdown(args->cmd & LINUX_IPC_64,
+ &linux_shminfo, (caddr_t)args->buf));
}
- bsd_to_linux_shmid_ds(bsd_args.buf, &linux_shmid);
- return (linux_shmid_pushdown(args->cmd & LINUX_IPC_64,
+
+ case LINUX_SHM_INFO: {
+ struct shm_info bsd_shm_info;
+
+ /* Perform shmctl wanting removed segments lookup */
+ error = kern_shmctl(td, args->shmid, SHM_INFO,
+ (void *)&bsd_shm_info, &bufsz, 1);
+ if (error)
+ return error;
+
+ bsd_to_linux_shm_info(&bsd_shm_info, &linux_shm_info);
+
+ return copyout(&linux_shm_info, (caddr_t)args->buf,
+ sizeof(struct l_shm_info));
+ }
+
+ case LINUX_IPC_STAT:
+ /* Perform shmctl wanting removed segments lookup */
+ error = kern_shmctl(td, args->shmid, IPC_STAT,
+ (void *)&bsd_shmid, &bufsz, 1);
+ if (error)
+ return error;
+
+ bsd_to_linux_shmid_ds(&bsd_shmid, &linux_shmid);
+
+ return (linux_shmid_pushdown(args->cmd & LINUX_IPC_64,
&linux_shmid, (caddr_t)args->buf));
+ case LINUX_SHM_STAT:
+ /* Perform shmctl wanting removed segments lookup */
+ error = kern_shmctl(td, args->shmid, IPC_STAT,
+ (void *)&bsd_shmid, &bufsz, 1);
+ if (error)
+ return error;
+
+ bsd_to_linux_shmid_ds(&bsd_shmid, &linux_shmid);
+
+ return (linux_shmid_pushdown(args->cmd & LINUX_IPC_64,
+ &linux_shmid, (caddr_t)args->buf));
+
case LINUX_IPC_SET:
error = linux_shmid_pullup(args->cmd & LINUX_IPC_64,
&linux_shmid, (caddr_t)args->buf);
- if (error != 0)
- return error;
- bsd_args.buf = (struct shmid_ds*)stackgap_alloc(&sg, sizeof(struct shmid_ds));
- linux_to_bsd_shmid_ds(&linux_shmid, bsd_args.buf);
- bsd_args.shmid = args->shmid;
- bsd_args.cmd = IPC_SET;
- return shmctl(td, &bsd_args);
-
- case LINUX_IPC_RMID:
- bsd_args.shmid = args->shmid;
- bsd_args.cmd = IPC_RMID;
+ if (error)
+ return error;
+
+ linux_to_bsd_shmid_ds(&linux_shmid, &bsd_shmid);
+
+ /* Perform shmctl wanting removed segments lookup */
+ return kern_shmctl(td, args->shmid, IPC_SET,
+ (void *)&bsd_shmid, &bufsz, 1);
+
+ case LINUX_IPC_RMID: {
+ void *buf;
+
if (args->buf == NULL)
- bsd_args.buf = NULL;
+ buf = NULL;
else {
- error = linux_shmid_pullup(args->cmd & LINUX_IPC_64,
- &linux_shmid, (caddr_t)args->buf);
- if (error != 0)
- return error;
- bsd_args.buf = (struct shmid_ds*)stackgap_alloc(&sg, sizeof(struct shmid_ds));
- linux_to_bsd_shmid_ds(&linux_shmid, bsd_args.buf);
+ error = linux_shmid_pullup(args->cmd & LINUX_IPC_64,
+ &linux_shmid, (caddr_t)args->buf);
+ if (error)
+ return error;
+ linux_to_bsd_shmid_ds(&linux_shmid, &bsd_shmid);
+ buf = (void *)&bsd_shmid;
}
- return shmctl(td, &bsd_args);
+ return kern_shmctl(td, args->shmid, IPC_RMID, buf, &bufsz, 1);
+ }
case LINUX_SHM_LOCK:
case LINUX_SHM_UNLOCK:
OpenPOWER on IntegriCloud