74#include "opt_sysvipc.h"
78#include <sys/abi_compat.h>
79#include <sys/kernel.h>
80#include <sys/limits.h>
82#include <sys/sysctl.h>
85#include <sys/malloc.h>
87#include <sys/module.h>
90#include <sys/resourcevar.h>
91#include <sys/rwlock.h>
93#include <sys/syscall.h>
94#include <sys/syscallsubr.h>
95#include <sys/sysent.h>
96#include <sys/sysproto.h>
99#include <security/audit/audit.h>
100#include <security/mac/mac_framework.h>
103#include <vm/vm_param.h>
105#include <vm/vm_object.h>
106#include <vm/vm_map.h>
107#include <vm/vm_page.h>
108#include <vm/vm_pager.h>
110FEATURE(sysv_shm,
"System V shared memory segments support");
112static MALLOC_DEFINE(M_SHM,
"shm",
"SVID compatible shared memory segments");
114#define SHMSEG_FREE 0x0200
115#define SHMSEG_REMOVED 0x0400
116#define SHMSEG_ALLOCATED 0x0800
135 int mode,
int segnum);
145static void shm_remove(
struct shmid_kernel *,
int);
158#define SHMMAXPGS 131072
161#define SHMMAX (SHMMAXPGS*PAGE_SIZE)
173#define SHMALL (SHMMAXPGS)
188 "Maximum shared memory segment size");
190 "Minimum shared memory segment size");
192 "Number of shared memory identifiers");
194 "Number of segments per process");
196 "Maximum number of pages available for shared memory");
198 &
shm_use_phys, 0,
"Enable/Disable locking of shared memory pages in core");
201 "Enable/Disable attachment to attached segments marked for removal");
204 "Array of struct shmid_kernel for each potential shared memory segment");
207#define SYSVSHM_LOCK() sx_xlock(&sysvshmsx)
208#define SYSVSHM_UNLOCK() sx_xunlock(&sysvshmsx)
209#define SYSVSHM_ASSERT_LOCKED() sx_assert(&sysvshmsx, SA_XLOCKED)
220 shmsegs[i].u.shm_perm.key == key)
229static struct shmid_kernel *
232 struct shmid_kernel *shmseg;
235 segnum = is_shmid ? IPCID_TO_IX(arg) : arg;
242 (is_shmid && shmseg->u.shm_perm.seq != IPCID_TO_SEQ(arg)) ||
255 vm_object_deallocate(shmseg->object);
256 shmseg->object = NULL;
257 size = round_page(shmseg->u.shm_segsz);
262 mac_sysvshm_cleanup(shmseg);
264 racct_sub_cred(shmseg->cred, RACCT_NSHM, 1);
265 racct_sub_cred(shmseg->cred, RACCT_SHMSIZE, size);
273 struct shmid_kernel *shmseg;
278 segnum = IPCID_TO_IX(shmmap_s->
shmid);
280 (
"segnum %d shmalloced %d", segnum,
shmalloced));
283 size = round_page(shmseg->u.shm_segsz);
284 result = vm_map_remove(&vm->vm_map, shmmap_s->
va, shmmap_s->
va + size);
285 if (
result != KERN_SUCCESS)
287 shmmap_s->
shmid = -1;
289 if (--shmseg->u.shm_nattch == 0 &&
301 shmseg->u.shm_perm.key = IPC_PRIVATE;
303 if (shmseg->u.shm_nattch == 0) {
309static struct prison *
312 struct prison *
pr, *rpr;
314 pr = cred->cr_prison;
325 if (shmseg->cred == NULL ||
326 !(rpr == shmseg->cred->cr_prison ||
335 struct proc *p = td->td_proc;
345 shmmap_s = p->p_vmspace->vm_shm;
346 if (shmmap_s == NULL)
348 AUDIT_ARG_SVIPC_ID(shmmap_s->
shmid);
349 for (i = 0; i <
shminfo.shmseg; i++, shmmap_s++) {
350 if (shmmap_s->
shmid != -1 &&
351 shmmap_s->
va == (vm_offset_t)shmaddr) {
358 error = mac_sysvshm_check_shmdt(td->td_ucred,
366#ifndef _SYS_SYSPROTO_H_
387 struct proc *p = td->td_proc;
388 struct shmid_kernel *shmseg;
390 vm_offset_t attach_va;
393 int cow, error, find_space, i, rv;
395 AUDIT_ARG_SVIPC_ID(
shmid);
396 AUDIT_ARG_VALUE(shmflg);
402 shmmap_s = p->p_vmspace->vm_shm;
403 if (shmmap_s == NULL) {
406 for (i = 0; i <
shminfo.shmseg; i++)
407 shmmap_s[i].
shmid = -1;
408 KASSERT(p->p_vmspace->vm_shm == NULL, (
"raced"));
409 p->p_vmspace->vm_shm = shmmap_s;
414 error =
ipcperm(td, &shmseg->u.shm_perm,
415 (shmflg & SHM_RDONLY) ? IPC_R : IPC_R|IPC_W);
419 error = mac_sysvshm_check_shmat(td->td_ucred, shmseg, shmflg);
423 for (i = 0; i <
shminfo.shmseg; i++) {
424 if (shmmap_s->
shmid == -1)
430 size = round_page(shmseg->u.shm_segsz);
432 cow = MAP_INHERIT_SHARE | MAP_PREFAULT_PARTIAL;
433 if ((shmflg & SHM_RDONLY) == 0)
434 prot |= VM_PROT_WRITE;
435 if (shmaddr != NULL) {
436 if ((shmflg & SHM_RND) != 0)
437 attach_va = rounddown2((vm_offset_t)shmaddr, SHMLBA);
438 else if (((vm_offset_t)shmaddr & (SHMLBA-1)) == 0)
439 attach_va = (vm_offset_t)shmaddr;
442 if ((shmflg & SHM_REMAP) != 0)
444 find_space = VMFS_NO_SPACE;
450 attach_va = round_page((vm_offset_t)p->p_vmspace->vm_daddr +
452 find_space = VMFS_OPTIMAL_SPACE;
455 vm_object_reference(shmseg->object);
456 rv = vm_map_find(&p->p_vmspace->vm_map, shmseg->object, 0, &attach_va,
457 size, 0, find_space, prot, prot, cow);
458 if (rv != KERN_SUCCESS) {
459 vm_object_deallocate(shmseg->object);
463 shmmap_s->
va = attach_va;
465 shmseg->u.shm_lpid = p->p_pid;
467 shmseg->u.shm_nattch++;
468 td->td_retval[0] = attach_va;
483#ifndef _SYS_SYSPROTO_H_
502 struct shmid_kernel *shmseg;
503 struct shmid_ds *shmidp;
504 struct shm_info shm_info;
513 AUDIT_ARG_SVIPC_ID(shmid);
514 AUDIT_ARG_SVIPC_CMD(cmd);
534 shm_info.shm_rss = 0;
535 shm_info.shm_tot = 0;
536 shm_info.shm_swp = 0;
537 shm_info.swap_attempts = 0;
538 shm_info.swap_successes = 0;
539 memcpy(
buf, &shm_info,
sizeof(shm_info));
541 *bufsz =
sizeof(shm_info);
550 error = mac_sysvshm_check_shmctl(td->td_ucred, shmseg, cmd);
557 shmidp = (
struct shmid_ds *)
buf;
558 error =
ipcperm(td, &shmseg->u.shm_perm, IPC_R);
561 memcpy(shmidp, &shmseg->u,
sizeof(
struct shmid_ds));
562 if (td->td_ucred->cr_prison != shmseg->cred->cr_prison)
563 shmidp->shm_perm.key = IPC_PRIVATE;
565 *bufsz =
sizeof(
struct shmid_ds);
566 if (cmd == SHM_STAT) {
567 td->td_retval[0] = IXSEQ_TO_IPCID(shmid,
572 shmidp = (
struct shmid_ds *)
buf;
573 AUDIT_ARG_SVIPC_PERM(&shmidp->shm_perm);
574 error =
ipcperm(td, &shmseg->u.shm_perm, IPC_M);
577 shmseg->u.shm_perm.uid = shmidp->shm_perm.uid;
578 shmseg->u.shm_perm.gid = shmidp->shm_perm.gid;
579 shmseg->u.shm_perm.mode =
580 (shmseg->u.shm_perm.mode & ~ACCESSPERMS) |
581 (shmidp->shm_perm.mode & ACCESSPERMS);
585 error =
ipcperm(td, &shmseg->u.shm_perm, IPC_M);
612#ifndef _SYS_SYSPROTO_H_
631 if (uap->
cmd == IPC_INFO || uap->
cmd == SHM_INFO ||
632 uap->
cmd == SHM_STAT)
636 if (uap->
cmd == IPC_SET) {
637 if ((error = copyin(uap->
buf, &
buf,
sizeof(
struct shmid_ds))))
648 error = copyout(&
buf, uap->
buf, bufsz);
655 td->td_retval[0] = -1;
664 struct shmid_kernel *shmseg;
671 (
"segnum %d shmalloced %d", segnum,
shmalloced));
673 if ((shmflg & (IPC_CREAT | IPC_EXCL)) == (IPC_CREAT | IPC_EXCL))
676 error = mac_sysvshm_check_shmget(td->td_ucred, shmseg, shmflg);
680 if (size != 0 && size > shmseg->u.shm_segsz)
682 td->td_retval[0] = IXSEQ_TO_IPCID(segnum, shmseg->u.shm_perm);
689 struct ucred *cred = td->td_ucred;
690 struct shmid_kernel *shmseg;
691 vm_object_t shm_object;
696 if (size < shminfo.shmmin || size >
shminfo.shmmax)
700 size = round_page(size);
716 (
"segnum %d shmalloced %d", segnum,
shmalloced));
720 PROC_LOCK(td->td_proc);
721 if (racct_add(td->td_proc, RACCT_NSHM, 1)) {
722 PROC_UNLOCK(td->td_proc);
725 if (racct_add(td->td_proc, RACCT_SHMSIZE, size)) {
726 racct_sub(td->td_proc, RACCT_NSHM, 1);
727 PROC_UNLOCK(td->td_proc);
730 PROC_UNLOCK(td->td_proc);
738 shm_object = vm_pager_allocate(
shm_use_phys ? OBJT_PHYS : OBJT_SWAP,
739 0, size, VM_PROT_DEFAULT, 0, cred);
740 if (shm_object == NULL) {
743 PROC_LOCK(td->td_proc);
744 racct_sub(td->td_proc, RACCT_NSHM, 1);
745 racct_sub(td->td_proc, RACCT_SHMSIZE, size);
746 PROC_UNLOCK(td->td_proc);
752 shmseg->object = shm_object;
753 shmseg->u.shm_perm.cuid = shmseg->u.shm_perm.uid = cred->cr_uid;
754 shmseg->u.shm_perm.cgid = shmseg->u.shm_perm.gid = cred->cr_gid;
756 shmseg->u.shm_perm.key = key;
757 shmseg->u.shm_perm.seq = (shmseg->u.shm_perm.seq + 1) & 0x7fff;
758 shmseg->cred =
crhold(cred);
759 shmseg->u.shm_segsz = size;
760 shmseg->u.shm_cpid = td->td_proc->p_pid;
761 shmseg->u.shm_lpid = shmseg->u.shm_nattch = 0;
762 shmseg->u.shm_atime = shmseg->u.shm_dtime = 0;
764 mac_sysvshm_create(cred, shmseg);
769 td->td_retval[0] = IXSEQ_TO_IPCID(segnum, shmseg->u.shm_perm);
774#ifndef _SYS_SYSPROTO_H_
791 if (uap->
key == IPC_PRIVATE) {
799 else if ((uap->
shmflg & IPC_CREAT) == 0)
811shmfork(
struct proc *p1,
struct proc *p2)
823 shmmap_s =
malloc(size, M_SHM, M_WAITOK);
824 bcopy(p1->p_vmspace->vm_shm, shmmap_s, size);
825 p2->p_vmspace->vm_shm = shmmap_s;
826 for (i = 0; i <
shminfo.shmseg; i++, shmmap_s++) {
827 if (shmmap_s->
shmid != -1) {
828 KASSERT(IPCID_TO_IX(shmmap_s->
shmid) >= 0 &&
830 (
"segnum %d shmalloced %d",
853 for (i = 0, shm = base; i <
shminfo.shmseg; i++, shm++) {
854 if (shm->
shmid != -1)
865 struct shmid_kernel *newsegs;
876 bcopy(&
shmsegs[i], &newsegs[i],
sizeof(newsegs[0]));
877 for (; i <
shminfo.shmmni; i++) {
879 newsegs[i].u.shm_perm.seq = 0;
881 mac_sysvshm_init(&newsegs[i]);
890 SYSCALL_INIT_HELPER(shmat),
891 SYSCALL_INIT_HELPER(shmctl),
892 SYSCALL_INIT_HELPER(shmdt),
893 SYSCALL_INIT_HELPER(shmget),
894#if defined(COMPAT_FREEBSD4) || defined(COMPAT_FREEBSD5) || \
895 defined(COMPAT_FREEBSD6) || defined(COMPAT_FREEBSD7)
896 SYSCALL_INIT_HELPER_COMPAT(freebsd7_shmctl),
898#if defined(__i386__) && (defined(COMPAT_FREEBSD4) || defined(COMPAT_43))
899 SYSCALL_INIT_HELPER(shmsys),
904#ifdef COMPAT_FREEBSD32
905#include <compat/freebsd32/freebsd32.h>
906#include <compat/freebsd32/freebsd32_ipc.h>
907#include <compat/freebsd32/freebsd32_proto.h>
908#include <compat/freebsd32/freebsd32_signal.h>
909#include <compat/freebsd32/freebsd32_syscall.h>
910#include <compat/freebsd32/freebsd32_util.h>
912static struct syscall_helper_data shm32_syscalls[] = {
913 SYSCALL32_INIT_HELPER_COMPAT(shmat),
914 SYSCALL32_INIT_HELPER_COMPAT(shmdt),
915 SYSCALL32_INIT_HELPER_COMPAT(shmget),
916 SYSCALL32_INIT_HELPER(freebsd32_shmsys),
917 SYSCALL32_INIT_HELPER(freebsd32_shmctl),
918#if defined(COMPAT_FREEBSD4) || defined(COMPAT_FREEBSD5) || \
919 defined(COMPAT_FREEBSD6) || defined(COMPAT_FREEBSD7)
920 SYSCALL32_INIT_HELPER(freebsd7_freebsd32_shmctl),
932 osd_method_t methods[PR_MAXMETHOD] = {
940 if (TUNABLE_ULONG_FETCH(
"kern.ipc.shmmaxpgs", &
shminfo.shmall) != 0)
941 printf(
"kern.ipc.shmmaxpgs is now called kern.ipc.shmall!\n");
945 for (i = PAGE_SIZE; i != 0; i--) {
982 if (
pr->pr_allow & PR_ALLOW_SYSVIPC) {
996#ifdef COMPAT_FREEBSD32
997 error = syscall32_helper_register(shm32_syscalls, SY_THR_STATIC_KLD);
1012#ifdef COMPAT_FREEBSD32
1013 syscall32_helper_unregister(shm32_syscalls);
1021 mac_sysvshm_destroy(&
shmsegs[i]);
1029 vm_object_deallocate(
shmsegs[i].
object);
1043 struct shmid_kernel tshmseg;
1044#ifdef COMPAT_FREEBSD32
1045 struct shmid_kernel32 tshmseg32;
1047 struct prison *
pr, *rpr;
1053 pr = req->td->td_ucred->cr_prison;
1059 bzero(&tshmseg,
sizeof(tshmseg));
1063 if (tshmseg.cred->cr_prison !=
pr)
1064 tshmseg.u.shm_perm.key = IPC_PRIVATE;
1066#ifdef COMPAT_FREEBSD32
1067 if (SV_CURPROC_FLAG(SV_ILP32)) {
1068 bzero(&tshmseg32,
sizeof(tshmseg32));
1069 freebsd32_ipcperm_out(&tshmseg.u.shm_perm,
1070 &tshmseg32.u.shm_perm);
1071 CP(tshmseg, tshmseg32, u.shm_segsz);
1072 CP(tshmseg, tshmseg32, u.shm_lpid);
1073 CP(tshmseg, tshmseg32, u.shm_cpid);
1074 CP(tshmseg, tshmseg32, u.shm_nattch);
1075 CP(tshmseg, tshmseg32, u.shm_atime);
1076 CP(tshmseg, tshmseg32, u.shm_dtime);
1077 CP(tshmseg, tshmseg32, u.shm_ctime);
1079 outaddr = &tshmseg32;
1080 outsize =
sizeof(tshmseg32);
1084 tshmseg.object = NULL;
1085 tshmseg.label = NULL;
1086 tshmseg.cred = NULL;
1088 outsize =
sizeof(tshmseg);
1090 error = SYSCTL_OUT(req, outaddr, outsize);
1101 struct prison *
pr = obj;
1102 struct prison *prpr;
1103 struct vfsoptlist *opts =
data;
1110 error =
vfs_copyopt(opts,
"sysvshm", &jsys,
sizeof(jsys));
1111 if (error != ENOENT) {
1115 case JAIL_SYS_DISABLE:
1118 case JAIL_SYS_INHERIT:
1119 prison_lock(
pr->pr_parent);
1121 prison_unlock(
pr->pr_parent);
1136 struct prison *
pr = obj;
1137 struct prison *tpr, *orpr, *nrpr, *trpr;
1138 struct vfsoptlist *opts =
data;
1147 if (
vfs_copyopt(opts,
"sysvshm", &jsys,
sizeof(jsys)) == ENOENT)
1148 jsys =
vfs_flagopt(opts,
"allow.sysvipc", NULL, 0)
1153 if (jsys == JAIL_SYS_DISABLE) {
1163 FOREACH_PRISON_DESCENDANT(
pr, tpr, descend) {
1177 }
else if (jsys != -1) {
1178 if (jsys == JAIL_SYS_NEW)
1181 prison_lock(
pr->pr_parent);
1183 prison_unlock(
pr->pr_parent);
1199 FOREACH_PRISON_DESCENDANT(
pr, tpr, descend) {
1201 trpr = osd_jail_get(tpr,
1204 (void)osd_jail_set(tpr,
1224 struct prison *
pr = obj;
1226 struct vfsoptlist *opts =
data;
1233 jsys = rpr == NULL ? JAIL_SYS_DISABLE
1234 : rpr ==
pr ? JAIL_SYS_NEW : JAIL_SYS_INHERIT;
1235 error =
vfs_setopt(opts,
"sysvshm", &jsys,
sizeof(jsys));
1236 if (error == ENOENT)
1244 struct prison *
pr = obj;
1260 struct shmid_kernel *shmseg;
1267 shmseg->cred != NULL && shmseg->cred->cr_prison ==
pr) {
1275#if defined(__i386__) && (defined(COMPAT_FREEBSD4) || defined(COMPAT_43))
1277 struct ipc_perm_old shm_perm;
1288struct oshmctl_args {
1291 struct oshmid_ds *ubuf;
1295oshmctl(
struct thread *td,
struct oshmctl_args *uap)
1300 struct shmid_kernel *shmseg;
1301 struct oshmid_ds outbuf;
1306 if (uap->cmd != IPC_STAT) {
1307 return (freebsd7_shmctl(td,
1308 (
struct freebsd7_shmctl_args *)uap));
1312 if (shmseg == NULL) {
1316 error =
ipcperm(td, &shmseg->u.shm_perm, IPC_R);
1322 error = mac_sysvshm_check_shmctl(td->td_ucred, shmseg, uap->cmd);
1328 ipcperm_new2old(&shmseg->u.shm_perm, &outbuf.shm_perm);
1329 outbuf.shm_segsz = shmseg->u.shm_segsz;
1330 outbuf.shm_cpid = shmseg->u.shm_cpid;
1331 outbuf.shm_lpid = shmseg->u.shm_lpid;
1332 outbuf.shm_nattch = shmseg->u.shm_nattch;
1333 outbuf.shm_atime = shmseg->u.shm_atime;
1334 outbuf.shm_dtime = shmseg->u.shm_dtime;
1335 outbuf.shm_ctime = shmseg->u.shm_ctime;
1336 outbuf.shm_handle = shmseg->object;
1338 return (copyout(&outbuf, uap->ubuf,
sizeof(outbuf)));
1345static sy_call_t *shmcalls[] = {
1346 (sy_call_t *)
sys_shmat, (sy_call_t *)oshmctl,
1348 (sy_call_t *)freebsd7_shmctl
1351#ifndef _SYS_SYSPROTO_H_
1361sys_shmsys(
struct thread *td,
struct shmsys_args *uap)
1364 AUDIT_ARG_SVIPC_WHICH(uap->which);
1365 if (uap->which < 0 || uap->which >= nitems(shmcalls))
1367 return ((*shmcalls[uap->which])(td, &uap->a2));
1372#ifdef COMPAT_FREEBSD32
1375freebsd32_shmsys(
struct thread *td,
struct freebsd32_shmsys_args *uap)
1378#if defined(COMPAT_FREEBSD4) || defined(COMPAT_FREEBSD5) || \
1379 defined(COMPAT_FREEBSD6) || defined(COMPAT_FREEBSD7)
1380 AUDIT_ARG_SVIPC_WHICH(uap->which);
1381 switch (uap->which) {
1386 ap.shmaddr = PTRIN(uap->a3);
1387 ap.shmflg = uap->a4;
1388 return (
sysent[SYS_shmat].sy_call(td, &ap));
1394 return (
sysent[SYS_shmdt].sy_call(td, &ap));
1401 ap.shmflg = uap->a4;
1402 return (
sysent[SYS_shmget].sy_call(td, &ap));
1405 struct freebsd7_freebsd32_shmctl_args ap;
1409 ap.buf = PTRIN(uap->a4);
1410 return (freebsd7_freebsd32_shmctl(td, &ap));
1417 return (
nosys(td, NULL));
1421#if defined(COMPAT_FREEBSD4) || defined(COMPAT_FREEBSD5) || \
1422 defined(COMPAT_FREEBSD6) || defined(COMPAT_FREEBSD7)
1424freebsd7_freebsd32_shmctl(
struct thread *td,
1425 struct freebsd7_freebsd32_shmctl_args *uap)
1429 struct shmid_ds shmid_ds;
1430 struct shm_info shm_info;
1434 struct shmid_ds_old32 shmid_ds32;
1435 struct shm_info32 shm_info32;
1436 struct shminfo32 shminfo32;
1440 if (uap->cmd == IPC_SET) {
1441 if ((error = copyin(uap->buf, &u32.shmid_ds32,
1442 sizeof(u32.shmid_ds32))))
1444 freebsd32_ipcperm_old_in(&u32.shmid_ds32.shm_perm,
1445 &u.shmid_ds.shm_perm);
1446 CP(u32.shmid_ds32, u.shmid_ds, shm_segsz);
1447 CP(u32.shmid_ds32, u.shmid_ds, shm_lpid);
1448 CP(u32.shmid_ds32, u.shmid_ds, shm_cpid);
1449 CP(u32.shmid_ds32, u.shmid_ds, shm_nattch);
1450 CP(u32.shmid_ds32, u.shmid_ds, shm_atime);
1451 CP(u32.shmid_ds32, u.shmid_ds, shm_dtime);
1452 CP(u32.shmid_ds32, u.shmid_ds, shm_ctime);
1455 error =
kern_shmctl(td, uap->shmid, uap->cmd, (
void *)&u, &sz);
1462 CP(u.shminfo, u32.shminfo32, shmmax);
1463 CP(u.shminfo, u32.shminfo32, shmmin);
1464 CP(u.shminfo, u32.shminfo32, shmmni);
1465 CP(u.shminfo, u32.shminfo32, shmseg);
1466 CP(u.shminfo, u32.shminfo32, shmall);
1467 error = copyout(&u32.shminfo32, uap->buf,
1468 sizeof(u32.shminfo32));
1471 CP(u.shm_info, u32.shm_info32, used_ids);
1472 CP(u.shm_info, u32.shm_info32, shm_rss);
1473 CP(u.shm_info, u32.shm_info32, shm_tot);
1474 CP(u.shm_info, u32.shm_info32, shm_swp);
1475 CP(u.shm_info, u32.shm_info32, swap_attempts);
1476 CP(u.shm_info, u32.shm_info32, swap_successes);
1477 error = copyout(&u32.shm_info32, uap->buf,
1478 sizeof(u32.shm_info32));
1482 memset(&u32.shmid_ds32, 0,
sizeof(u32.shmid_ds32));
1483 freebsd32_ipcperm_old_out(&u.shmid_ds.shm_perm,
1484 &u32.shmid_ds32.shm_perm);
1485 if (u.shmid_ds.shm_segsz > INT32_MAX)
1486 u32.shmid_ds32.shm_segsz = INT32_MAX;
1488 CP(u.shmid_ds, u32.shmid_ds32, shm_segsz);
1489 CP(u.shmid_ds, u32.shmid_ds32, shm_lpid);
1490 CP(u.shmid_ds, u32.shmid_ds32, shm_cpid);
1491 CP(u.shmid_ds, u32.shmid_ds32, shm_nattch);
1492 CP(u.shmid_ds, u32.shmid_ds32, shm_atime);
1493 CP(u.shmid_ds, u32.shmid_ds32, shm_dtime);
1494 CP(u.shmid_ds, u32.shmid_ds32, shm_ctime);
1495 u32.shmid_ds32.shm_internal = 0;
1496 error = copyout(&u32.shmid_ds32, uap->buf,
1497 sizeof(u32.shmid_ds32));
1504 td->td_retval[0] = -1;
1511freebsd32_shmctl(
struct thread *td,
struct freebsd32_shmctl_args *uap)
1515 struct shmid_ds shmid_ds;
1516 struct shm_info shm_info;
1520 struct shmid_ds32 shmid_ds32;
1521 struct shm_info32 shm_info32;
1522 struct shminfo32 shminfo32;
1526 if (uap->cmd == IPC_SET) {
1527 if ((error = copyin(uap->buf, &u32.shmid_ds32,
1528 sizeof(u32.shmid_ds32))))
1530 freebsd32_ipcperm_in(&u32.shmid_ds32.shm_perm,
1531 &u.shmid_ds.shm_perm);
1532 CP(u32.shmid_ds32, u.shmid_ds, shm_segsz);
1533 CP(u32.shmid_ds32, u.shmid_ds, shm_lpid);
1534 CP(u32.shmid_ds32, u.shmid_ds, shm_cpid);
1535 CP(u32.shmid_ds32, u.shmid_ds, shm_nattch);
1536 CP(u32.shmid_ds32, u.shmid_ds, shm_atime);
1537 CP(u32.shmid_ds32, u.shmid_ds, shm_dtime);
1538 CP(u32.shmid_ds32, u.shmid_ds, shm_ctime);
1541 error =
kern_shmctl(td, uap->shmid, uap->cmd, (
void *)&u, &sz);
1548 CP(u.shminfo, u32.shminfo32, shmmax);
1549 CP(u.shminfo, u32.shminfo32, shmmin);
1550 CP(u.shminfo, u32.shminfo32, shmmni);
1551 CP(u.shminfo, u32.shminfo32, shmseg);
1552 CP(u.shminfo, u32.shminfo32, shmall);
1553 error = copyout(&u32.shminfo32, uap->buf,
1554 sizeof(u32.shminfo32));
1557 CP(u.shm_info, u32.shm_info32, used_ids);
1558 CP(u.shm_info, u32.shm_info32, shm_rss);
1559 CP(u.shm_info, u32.shm_info32, shm_tot);
1560 CP(u.shm_info, u32.shm_info32, shm_swp);
1561 CP(u.shm_info, u32.shm_info32, swap_attempts);
1562 CP(u.shm_info, u32.shm_info32, swap_successes);
1563 error = copyout(&u32.shm_info32, uap->buf,
1564 sizeof(u32.shm_info32));
1568 freebsd32_ipcperm_out(&u.shmid_ds.shm_perm,
1569 &u32.shmid_ds32.shm_perm);
1570 if (u.shmid_ds.shm_segsz > INT32_MAX)
1571 u32.shmid_ds32.shm_segsz = INT32_MAX;
1573 CP(u.shmid_ds, u32.shmid_ds32, shm_segsz);
1574 CP(u.shmid_ds, u32.shmid_ds32, shm_lpid);
1575 CP(u.shmid_ds, u32.shmid_ds32, shm_cpid);
1576 CP(u.shmid_ds, u32.shmid_ds32, shm_nattch);
1577 CP(u.shmid_ds, u32.shmid_ds32, shm_atime);
1578 CP(u.shmid_ds, u32.shmid_ds32, shm_dtime);
1579 CP(u.shmid_ds, u32.shmid_ds32, shm_ctime);
1580 error = copyout(&u32.shmid_ds32, uap->buf,
1581 sizeof(u32.shmid_ds32));
1588 td->td_retval[0] = -1;
1594#if defined(COMPAT_FREEBSD4) || defined(COMPAT_FREEBSD5) || \
1595 defined(COMPAT_FREEBSD6) || defined(COMPAT_FREEBSD7)
1597#ifndef _SYS_SYSPROTO_H_
1598struct freebsd7_shmctl_args {
1601 struct shmid_ds_old *
buf;
1605freebsd7_shmctl(
struct thread *td,
struct freebsd7_shmctl_args *uap)
1608 struct shmid_ds_old old;
1609 struct shmid_ds
buf;
1617 if (uap->cmd == IPC_INFO || uap->cmd == SHM_INFO ||
1618 uap->cmd == SHM_STAT)
1622 if (uap->cmd == IPC_SET) {
1623 if ((error = copyin(uap->buf, &old,
sizeof(old))))
1625 ipcperm_old2new(&old.shm_perm, &
buf.shm_perm);
1626 CP(old,
buf, shm_segsz);
1627 CP(old,
buf, shm_lpid);
1628 CP(old,
buf, shm_cpid);
1629 CP(old,
buf, shm_nattch);
1630 CP(old,
buf, shm_atime);
1631 CP(old,
buf, shm_dtime);
1632 CP(old,
buf, shm_ctime);
1635 error =
kern_shmctl(td, uap->shmid, uap->cmd, (
void *)&
buf, &bufsz);
1642 memset(&old, 0,
sizeof(old));
1643 ipcperm_new2old(&
buf.shm_perm, &old.shm_perm);
1644 if (
buf.shm_segsz > INT_MAX)
1645 old.shm_segsz = INT_MAX;
1647 CP(
buf, old, shm_segsz);
1648 CP(
buf, old, shm_lpid);
1649 CP(
buf, old, shm_cpid);
1650 if (
buf.shm_nattch > SHRT_MAX)
1651 old.shm_nattch = SHRT_MAX;
1653 CP(
buf, old, shm_nattch);
1654 CP(
buf, old, shm_atime);
1655 CP(
buf, old, shm_dtime);
1656 CP(
buf, old, shm_ctime);
1657 old.shm_internal = NULL;
1658 error = copyout(&old, uap->buf,
sizeof(old));
1665 td->td_retval[0] = -1;
int prison_ischild(struct prison *pr1, struct prison *pr2)
struct prisonlist allprison
void *() malloc(size_t size, struct malloc_type *mtp, int flags)
void free(void *addr, struct malloc_type *mtp)
void osd_free_reserved(void **rsv)
void ** osd_reserve(u_int slot)
static struct pollrec pr[POLL_LIST_LEN]
struct ucred * crhold(struct ucred *cr)
void crfree(struct ucred *cr)
rlim_t lim_max(struct thread *td, int which)
int nosys(struct thread *td, struct nosys_args *args)
void sx_destroy(struct sx *sx)
int syscall_helper_unregister(struct syscall_helper_data *sd)
int syscall_helper_register(struct syscall_helper_data *sd, int flags)
volatile time_t time_second
int printf(const char *fmt,...)
int ipcperm(struct thread *td, struct ipc_perm *perm, int acc_mode)
void shmexit(struct vmspace *vm)
void shmfork(struct proc *p1, struct proc *p2)
void(* shmexit_hook)(struct vmspace *)
void(* shmfork_hook)(struct proc *, struct proc *)
static struct shmid_kernel * shmsegs
static int sysvshm_modload(struct module *, int, void *)
static struct sx sysvshmsx
static int shm_delete_mapping(struct vmspace *vm, struct shmmap_state *)
static int shm_prison_get(void *, void *)
static int shm_prison_remove(void *, void *)
static int shmunload(void)
static int shm_prison_cansee(struct prison *, struct shmid_kernel *)
static void shmexit_myhook(struct vmspace *vm)
SYSCTL_PROC(_kern_ipc, OID_AUTO, shmsegs, CTLTYPE_OPAQUE|CTLFLAG_RD|CTLFLAG_MPSAFE, NULL, 0, sysctl_shmsegs, "", "Array of struct shmid_kernel for each potential shared memory segment")
static int shm_prison_set(void *, void *)
DECLARE_MODULE(sysvshm, sysvshm_mod, SI_SUB_SYSV_SHM, SI_ORDER_FIRST)
MODULE_VERSION(sysvshm, 1)
static void shm_prison_cleanup(struct prison *)
static int kern_shmat_locked(struct thread *td, int shmid, const void *shmaddr, int shmflg)
int sys_shmget(struct thread *td, struct shmget_args *uap)
static MALLOC_DEFINE(M_SHM, "shm", "SVID compatible shared memory segments")
static int shmget_existing(struct thread *td, size_t size, int shmflg, int mode, int segnum)
static void shmrealloc(void)
static void shmfork_myhook(struct proc *p1, struct proc *p2)
SYSCTL_INT(_kern_ipc, OID_AUTO, shm_use_phys, CTLFLAG_RWTUN, &shm_use_phys, 0, "Enable/Disable locking of shared memory pages in core")
SYSCTL_ULONG(_kern_ipc, OID_AUTO, shmmax, CTLFLAG_RWTUN, &shminfo.shmmax, 0, "Maximum shared memory segment size")
static void shm_remove(struct shmid_kernel *, int)
static int shm_find_segment_by_key(struct prison *, key_t)
int kern_shmat(struct thread *td, int shmid, const void *shmaddr, int shmflg)
static int shm_allow_removed
#define SYSVSHM_ASSERT_LOCKED()
int kern_shmctl(struct thread *td, int shmid, int cmd, void *buf, size_t *bufsz)
static int kern_shmctl_locked(struct thread *td, int shmid, int cmd, void *buf, size_t *bufsz)
static int shm_prison_check(void *, void *)
int sys_shmat(struct thread *td, struct shmat_args *uap)
static moduledata_t sysvshm_mod
static int sysctl_shmsegs(SYSCTL_HANDLER_ARGS)
static int kern_shmdt_locked(struct thread *td, const void *shmaddr)
static unsigned shm_prison_slot
static void shm_deallocate_segment(struct shmid_kernel *)
SYSCTL_JAIL_PARAM_SYS_NODE(sysvshm, CTLFLAG_RW, "SYSV shared memory")
int sys_shmctl(struct thread *td, struct shmctl_args *uap)
static struct syscall_helper_data shm_syscalls[]
FEATURE(sysv_shm, "System V shared memory segments support")
static struct prison * shm_find_prison(struct ucred *)
static int shmget_allocate_segment(struct thread *td, key_t key, size_t size, int mode)
int sys_shmdt(struct thread *td, struct shmdt_args *uap)
static struct shmid_kernel * shm_find_segment(struct prison *, int, bool)
int vfs_copyopt(struct vfsoptlist *opts, const char *name, void *dest, int len)
int vfs_flagopt(struct vfsoptlist *opts, const char *name, uint64_t *w, uint64_t val)
int vfs_setopt(struct vfsoptlist *opts, const char *name, void *value, int len)