linux_ipc.c 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763
  1. /* $OpenBSD: linux_ipc.c,v 1.18 2014/09/14 14:17:23 jsg Exp $ */
  2. /* $NetBSD: linux_ipc.c,v 1.10 1996/04/05 00:01:44 christos Exp $ */
  3. /*
  4. * Copyright (c) 1995 Frank van der Linden
  5. * All rights reserved.
  6. *
  7. * Redistribution and use in source and binary forms, with or without
  8. * modification, are permitted provided that the following conditions
  9. * are met:
  10. * 1. Redistributions of source code must retain the above copyright
  11. * notice, this list of conditions and the following disclaimer.
  12. * 2. Redistributions in binary form must reproduce the above copyright
  13. * notice, this list of conditions and the following disclaimer in the
  14. * documentation and/or other materials provided with the distribution.
  15. * 3. All advertising materials mentioning features or use of this software
  16. * must display the following acknowledgement:
  17. * This product includes software developed for the NetBSD Project
  18. * by Frank van der Linden
  19. * 4. The name of the author may not be used to endorse or promote products
  20. * derived from this software without specific prior written permission
  21. *
  22. * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
  23. * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  24. * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
  25. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
  26. * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  27. * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  28. * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  29. * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  30. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  31. * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  32. */
  33. #include <sys/types.h>
  34. #include <sys/param.h>
  35. #include <sys/kernel.h>
  36. #include <sys/shm.h>
  37. #include <sys/sem.h>
  38. #include <sys/msg.h>
  39. #include <sys/uio.h>
  40. #include <sys/time.h>
  41. #include <sys/malloc.h>
  42. #include <sys/mman.h>
  43. #include <sys/systm.h>
  44. #include <sys/stat.h>
  45. #include <sys/mount.h>
  46. #include <sys/syscallargs.h>
  47. #include <compat/linux/linux_types.h>
  48. #include <compat/linux/linux_signal.h>
  49. #include <compat/linux/linux_syscallargs.h>
  50. #include <compat/linux/linux_util.h>
  51. #include <compat/linux/linux_ipc.h>
  52. #include <compat/linux/linux_msg.h>
  53. #include <compat/linux/linux_shm.h>
  54. #include <compat/linux/linux_sem.h>
  55. #include <compat/linux/linux_ipccall.h>
  56. /*
  57. * Stuff to deal with the SysV ipc/shm/semaphore interface in Linux.
  58. * The main difference is, that Linux handles it all via one
  59. * system call, which has the usual maximum amount of 5 arguments.
  60. * This results in a kludge for calls that take 6 of them.
  61. *
  62. * The SYSVXXXX options have to be enabled to get the appropriate
  63. * functions to work.
  64. */
  65. #ifdef SYSVSEM
  66. int linux_semop(struct proc *, void *, register_t *);
  67. int linux_semget(struct proc *, void *, register_t *);
  68. int linux_semctl(struct proc *, void *, register_t *);
  69. int bsd_to_linux_semid_ds(struct semid_ds *, struct linux_semid_ds *);
  70. void linux_to_bsd_semid_ds(struct linux_semid_ds *, struct semid_ds *);
  71. #endif
  72. #ifdef SYSVMSG
  73. int linux_msgsnd(struct proc *, void *, register_t *);
  74. int linux_msgrcv(struct proc *, void *, register_t *);
  75. int linux_msgget(struct proc *, void *, register_t *);
  76. int linux_msgctl(struct proc *, void *, register_t *);
  77. void linux_to_bsd_msqid_ds(struct linux_msqid_ds *, struct msqid_ds *);
  78. int bsd_to_linux_msqid_ds(struct msqid_ds *, struct linux_msqid_ds *);
  79. #endif
  80. #ifdef SYSVSHM
  81. int linux_shmat(struct proc *, void *, register_t *);
  82. int linux_shmdt(struct proc *, void *, register_t *);
  83. int linux_shmget(struct proc *, void *, register_t *);
  84. int linux_shmctl(struct proc *, void *, register_t *);
  85. void linux_to_bsd_shmid_ds(struct linux_shmid_ds *, struct shmid_ds *);
  86. int bsd_to_linux_shmid_ds(struct shmid_ds *, struct linux_shmid_ds *);
  87. #endif
  88. #if defined(SYSVMSG) || defined(SYSVSEM) || defined(SYSVSHM)
  89. void linux_to_bsd_ipc_perm(struct linux_ipc_perm *, struct ipc_perm *);
  90. void bsd_to_linux_ipc_perm(struct ipc_perm *, struct linux_ipc_perm *);
  91. #endif
  92. int
  93. linux_sys_ipc(p, v, retval)
  94. struct proc *p;
  95. void *v;
  96. register_t *retval;
  97. {
  98. struct linux_sys_ipc_args /* {
  99. syscallarg(int) what;
  100. syscallarg(int) a1;
  101. syscallarg(int) a2;
  102. syscallarg(int) a3;
  103. syscallarg(caddr_t) ptr;
  104. } */ *uap = v;
  105. switch (SCARG(uap, what)) {
  106. #ifdef SYSVSEM
  107. case LINUX_SYS_semop:
  108. return linux_semop(p, uap, retval);
  109. case LINUX_SYS_semget:
  110. return linux_semget(p, uap, retval);
  111. case LINUX_SYS_semctl:
  112. return linux_semctl(p, uap, retval);
  113. #endif
  114. #ifdef SYSVMSG
  115. case LINUX_SYS_msgsnd:
  116. return linux_msgsnd(p, uap, retval);
  117. case LINUX_SYS_msgrcv:
  118. return linux_msgrcv(p, uap, retval);
  119. case LINUX_SYS_msgget:
  120. return linux_msgget(p, uap, retval);
  121. case LINUX_SYS_msgctl:
  122. return linux_msgctl(p, uap, retval);
  123. #endif
  124. #ifdef SYSVSHM
  125. case LINUX_SYS_shmat:
  126. return linux_shmat(p, uap, retval);
  127. case LINUX_SYS_shmdt:
  128. return linux_shmdt(p, uap, retval);
  129. case LINUX_SYS_shmget:
  130. return linux_shmget(p, uap, retval);
  131. case LINUX_SYS_shmctl:
  132. return linux_shmctl(p, uap, retval);
  133. #endif
  134. default:
  135. return ENOSYS;
  136. }
  137. }
  138. #if defined(SYSVMSG) || defined(SYSVSEM) || defined(SYSVSHM)
  139. /*
  140. * Convert between Linux and OpenBSD ipc_perm structures. Only the
  141. * order of the fields is different.
  142. */
  143. void
  144. linux_to_bsd_ipc_perm(lpp, bpp)
  145. struct linux_ipc_perm *lpp;
  146. struct ipc_perm *bpp;
  147. {
  148. bpp->key = lpp->l_key;
  149. bpp->uid = lpp->l_uid;
  150. bpp->gid = lpp->l_gid;
  151. bpp->cuid = lpp->l_cuid;
  152. bpp->cgid = lpp->l_cgid;
  153. bpp->mode = lpp->l_mode;
  154. bpp->seq = lpp->l_seq;
  155. }
  156. void
  157. bsd_to_linux_ipc_perm(bpp, lpp)
  158. struct ipc_perm *bpp;
  159. struct linux_ipc_perm *lpp;
  160. {
  161. lpp->l_key = bpp->key;
  162. lpp->l_uid = bpp->uid;
  163. lpp->l_gid = bpp->gid;
  164. lpp->l_cuid = bpp->cuid;
  165. lpp->l_cgid = bpp->cgid;
  166. lpp->l_mode = bpp->mode;
  167. lpp->l_seq = bpp->seq;
  168. }
  169. #endif
  170. #ifdef SYSVSEM
  171. /*
  172. * Semaphore operations. Most constants and structures are the same on
  173. * both systems. Only semctl() needs some extra work.
  174. */
  175. /*
  176. * Convert between Linux and OpenBSD semid_ds structures.
  177. */
  178. int
  179. bsd_to_linux_semid_ds(bs, ls)
  180. struct semid_ds *bs;
  181. struct linux_semid_ds *ls;
  182. {
  183. bsd_to_linux_ipc_perm(&bs->sem_perm, &ls->l_sem_perm);
  184. if (bs->sem_otime > LINUX_TIME_MAX)
  185. return EOVERFLOW;
  186. ls->l_sem_otime = (linux_time_t)bs->sem_otime;
  187. if (bs->sem_ctime > LINUX_TIME_MAX)
  188. return EOVERFLOW;
  189. ls->l_sem_ctime = (linux_time_t)bs->sem_ctime;
  190. ls->l_sem_nsems = bs->sem_nsems;
  191. ls->l_sem_base = bs->sem_base;
  192. return 0;
  193. }
  194. void
  195. linux_to_bsd_semid_ds(ls, bs)
  196. struct linux_semid_ds *ls;
  197. struct semid_ds *bs;
  198. {
  199. linux_to_bsd_ipc_perm(&ls->l_sem_perm, &bs->sem_perm);
  200. bs->sem_otime = ls->l_sem_otime;
  201. bs->sem_ctime = ls->l_sem_ctime;
  202. bs->sem_nsems = ls->l_sem_nsems;
  203. bs->sem_base = ls->l_sem_base;
  204. }
  205. int
  206. linux_semop(p, v, retval)
  207. struct proc *p;
  208. void *v;
  209. register_t *retval;
  210. {
  211. struct linux_sys_ipc_args /* {
  212. syscallarg(int) what;
  213. syscallarg(int) a1;
  214. syscallarg(int) a2;
  215. syscallarg(int) a3;
  216. syscallarg(caddr_t) ptr;
  217. } */ *uap = v;
  218. struct sys_semop_args bsa;
  219. SCARG(&bsa, semid) = SCARG(uap, a1);
  220. SCARG(&bsa, sops) = (struct sembuf *)SCARG(uap, ptr);
  221. SCARG(&bsa, nsops) = SCARG(uap, a2);
  222. return sys_semop(p, &bsa, retval);
  223. }
  224. int
  225. linux_semget(p, v, retval)
  226. struct proc *p;
  227. void *v;
  228. register_t *retval;
  229. {
  230. struct linux_sys_ipc_args /* {
  231. syscallarg(int) what;
  232. syscallarg(int) a1;
  233. syscallarg(int) a2;
  234. syscallarg(int) a3;
  235. syscallarg(caddr_t) ptr;
  236. } */ *uap = v;
  237. struct sys_semget_args bsa;
  238. SCARG(&bsa, key) = (key_t)SCARG(uap, a1);
  239. SCARG(&bsa, nsems) = SCARG(uap, a2);
  240. SCARG(&bsa, semflg) = SCARG(uap, a3);
  241. return sys_semget(p, &bsa, retval);
  242. }
  243. /*
  244. * Most of this can be handled by directly passing the arguments on,
  245. * buf IPC_* require a lot of copy{in,out} because of the extra indirection
  246. * (we are passed a pointer to a union cointaining a pointer to a semid_ds
  247. * structure.
  248. */
  249. int
  250. linux_semctl(p, v, retval)
  251. struct proc *p;
  252. void *v;
  253. register_t *retval;
  254. {
  255. struct linux_sys_ipc_args /* {
  256. syscallarg(int) what;
  257. syscallarg(int) a1;
  258. syscallarg(int) a2;
  259. syscallarg(int) a3;
  260. syscallarg(caddr_t) ptr;
  261. } */ *uap = v;
  262. caddr_t sg, unptr, dsp, ldsp;
  263. int error, cmd;
  264. struct sys___semctl_args bsa;
  265. struct linux_semid_ds lm;
  266. struct semid_ds bm;
  267. SCARG(&bsa, semid) = SCARG(uap, a1);
  268. SCARG(&bsa, semnum) = SCARG(uap, a2);
  269. SCARG(&bsa, cmd) = SCARG(uap, a3);
  270. SCARG(&bsa, arg) = (union semun *)SCARG(uap, ptr);
  271. switch(SCARG(uap, a3)) {
  272. case LINUX_GETVAL:
  273. cmd = GETVAL;
  274. break;
  275. case LINUX_GETPID:
  276. cmd = GETPID;
  277. break;
  278. case LINUX_GETNCNT:
  279. cmd = GETNCNT;
  280. break;
  281. case LINUX_GETZCNT:
  282. cmd = GETZCNT;
  283. break;
  284. case LINUX_SETVAL:
  285. cmd = SETVAL;
  286. break;
  287. case LINUX_IPC_RMID:
  288. cmd = IPC_RMID;
  289. break;
  290. case LINUX_IPC_SET:
  291. if ((error = copyin(SCARG(uap, ptr), &ldsp, sizeof ldsp)))
  292. return error;
  293. if ((error = copyin(ldsp, (caddr_t)&lm, sizeof lm)))
  294. return error;
  295. linux_to_bsd_semid_ds(&lm, &bm);
  296. sg = stackgap_init(p);
  297. unptr = stackgap_alloc(&sg, sizeof (union semun));
  298. dsp = stackgap_alloc(&sg, sizeof (struct semid_ds));
  299. if ((error = copyout((caddr_t)&bm, dsp, sizeof bm)))
  300. return error;
  301. if ((error = copyout((caddr_t)&dsp, unptr, sizeof dsp)))
  302. return error;
  303. SCARG(&bsa, arg) = (union semun *)unptr;
  304. return sys___semctl(p, &bsa, retval);
  305. case LINUX_IPC_STAT:
  306. sg = stackgap_init(p);
  307. unptr = stackgap_alloc(&sg, sizeof (union semun));
  308. dsp = stackgap_alloc(&sg, sizeof (struct semid_ds));
  309. if ((error = copyout((caddr_t)&dsp, unptr, sizeof dsp)))
  310. return error;
  311. SCARG(&bsa, arg) = (union semun *)unptr;
  312. if ((error = sys___semctl(p, &bsa, retval)))
  313. return error;
  314. if ((error = copyin(dsp, (caddr_t)&bm, sizeof bm)))
  315. return error;
  316. if ((error = bsd_to_linux_semid_ds(&bm, &lm)))
  317. return error;
  318. if ((error = copyin(SCARG(uap, ptr), &ldsp, sizeof ldsp)))
  319. return error;
  320. return copyout((caddr_t)&lm, ldsp, sizeof lm);
  321. default:
  322. return EINVAL;
  323. }
  324. SCARG(&bsa, cmd) = cmd;
  325. return sys___semctl(p, &bsa, retval);
  326. }
  327. #endif /* SYSVSEM */
  328. #ifdef SYSVMSG
  329. void
  330. linux_to_bsd_msqid_ds(lmp, bmp)
  331. struct linux_msqid_ds *lmp;
  332. struct msqid_ds *bmp;
  333. {
  334. linux_to_bsd_ipc_perm(&lmp->l_msg_perm, &bmp->msg_perm);
  335. bmp->msg_first = lmp->l_msg_first;
  336. bmp->msg_last = lmp->l_msg_last;
  337. bmp->msg_cbytes = lmp->l_msg_cbytes;
  338. bmp->msg_qnum = lmp->l_msg_qnum;
  339. bmp->msg_qbytes = lmp->l_msg_qbytes;
  340. bmp->msg_lspid = lmp->l_msg_lspid;
  341. bmp->msg_lrpid = lmp->l_msg_lrpid;
  342. bmp->msg_stime = lmp->l_msg_stime;
  343. bmp->msg_rtime = lmp->l_msg_rtime;
  344. bmp->msg_ctime = lmp->l_msg_ctime;
  345. }
  346. int
  347. bsd_to_linux_msqid_ds(bmp, lmp)
  348. struct msqid_ds *bmp;
  349. struct linux_msqid_ds *lmp;
  350. {
  351. bsd_to_linux_ipc_perm(&bmp->msg_perm, &lmp->l_msg_perm);
  352. lmp->l_msg_first = bmp->msg_first;
  353. lmp->l_msg_last = bmp->msg_last;
  354. lmp->l_msg_cbytes = bmp->msg_cbytes;
  355. lmp->l_msg_qnum = bmp->msg_qnum;
  356. lmp->l_msg_qbytes = bmp->msg_qbytes;
  357. lmp->l_msg_lspid = bmp->msg_lspid;
  358. lmp->l_msg_lrpid = bmp->msg_lrpid;
  359. if (bmp->msg_stime > LINUX_TIME_MAX)
  360. return EOVERFLOW;
  361. lmp->l_msg_stime = (linux_time_t)bmp->msg_stime;
  362. if (bmp->msg_rtime > LINUX_TIME_MAX)
  363. return EOVERFLOW;
  364. lmp->l_msg_rtime = (linux_time_t)bmp->msg_rtime;
  365. if (bmp->msg_ctime > LINUX_TIME_MAX)
  366. return EOVERFLOW;
  367. lmp->l_msg_ctime = (linux_time_t)bmp->msg_ctime;
  368. return 0;
  369. }
  370. int
  371. linux_msgsnd(p, v, retval)
  372. struct proc *p;
  373. void *v;
  374. register_t *retval;
  375. {
  376. struct linux_sys_ipc_args /* {
  377. syscallarg(int) what;
  378. syscallarg(int) a1;
  379. syscallarg(int) a2;
  380. syscallarg(int) a3;
  381. syscallarg(caddr_t) ptr;
  382. } */ *uap = v;
  383. struct sys_msgsnd_args bma;
  384. SCARG(&bma, msqid) = SCARG(uap, a1);
  385. SCARG(&bma, msgp) = SCARG(uap, ptr);
  386. SCARG(&bma, msgsz) = SCARG(uap, a2);
  387. SCARG(&bma, msgflg) = SCARG(uap, a3);
  388. return sys_msgsnd(p, &bma, retval);
  389. }
  390. int
  391. linux_msgrcv(p, v, retval)
  392. struct proc *p;
  393. void *v;
  394. register_t *retval;
  395. {
  396. struct linux_sys_ipc_args /* {
  397. syscallarg(int) what;
  398. syscallarg(int) a1;
  399. syscallarg(int) a2;
  400. syscallarg(int) a3;
  401. syscallarg(caddr_t) ptr;
  402. } */ *uap = v;
  403. struct sys_msgrcv_args bma;
  404. struct linux_msgrcv_msgarg kluge;
  405. int error;
  406. if ((error = copyin(SCARG(uap, ptr), &kluge, sizeof kluge)))
  407. return error;
  408. SCARG(&bma, msqid) = SCARG(uap, a1);
  409. SCARG(&bma, msgp) = kluge.msg;
  410. SCARG(&bma, msgsz) = SCARG(uap, a2);
  411. SCARG(&bma, msgtyp) = kluge.type;
  412. SCARG(&bma, msgflg) = SCARG(uap, a3);
  413. return sys_msgrcv(p, &bma, retval);
  414. }
  415. int
  416. linux_msgget(p, v, retval)
  417. struct proc *p;
  418. void *v;
  419. register_t *retval;
  420. {
  421. struct linux_sys_ipc_args /* {
  422. syscallarg(int) what;
  423. syscallarg(int) a1;
  424. syscallarg(int) a2;
  425. syscallarg(int) a3;
  426. syscallarg(caddr_t) ptr;
  427. } */ *uap = v;
  428. struct sys_msgget_args bma;
  429. SCARG(&bma, key) = (key_t)SCARG(uap, a1);
  430. SCARG(&bma, msgflg) = SCARG(uap, a2);
  431. return sys_msgget(p, &bma, retval);
  432. }
  433. int
  434. linux_msgctl(p, v, retval)
  435. struct proc *p;
  436. void *v;
  437. register_t *retval;
  438. {
  439. struct linux_sys_ipc_args /* {
  440. syscallarg(int) what;
  441. syscallarg(int) a1;
  442. syscallarg(int) a2;
  443. syscallarg(int) a3;
  444. syscallarg(caddr_t) ptr;
  445. } */ *uap = v;
  446. struct sys_msgctl_args bma;
  447. caddr_t umsgptr, sg;
  448. struct linux_msqid_ds lm;
  449. struct msqid_ds bm;
  450. int error;
  451. SCARG(&bma, msqid) = SCARG(uap, a1);
  452. SCARG(&bma, cmd) = SCARG(uap, a2);
  453. switch (SCARG(uap, a2)) {
  454. case LINUX_IPC_RMID:
  455. return sys_msgctl(p, &bma, retval);
  456. case LINUX_IPC_SET:
  457. if ((error = copyin(SCARG(uap, ptr), (caddr_t)&lm, sizeof lm)))
  458. return error;
  459. linux_to_bsd_msqid_ds(&lm, &bm);
  460. sg = stackgap_init(p);
  461. umsgptr = stackgap_alloc(&sg, sizeof bm);
  462. if ((error = copyout((caddr_t)&bm, umsgptr, sizeof bm)))
  463. return error;
  464. SCARG(&bma, buf) = (struct msqid_ds *)umsgptr;
  465. return sys_msgctl(p, &bma, retval);
  466. case LINUX_IPC_STAT:
  467. sg = stackgap_init(p);
  468. umsgptr = stackgap_alloc(&sg, sizeof (struct msqid_ds));
  469. SCARG(&bma, buf) = (struct msqid_ds *)umsgptr;
  470. if ((error = sys_msgctl(p, &bma, retval)))
  471. return error;
  472. if ((error = copyin(umsgptr, (caddr_t)&bm, sizeof bm)))
  473. return error;
  474. if ((error = bsd_to_linux_msqid_ds(&bm, &lm)))
  475. return error;
  476. return copyout((caddr_t)&lm, SCARG(uap, ptr), sizeof lm);
  477. }
  478. return EINVAL;
  479. }
  480. #endif /* SYSVMSG */
  481. #ifdef SYSVSHM
  482. /*
  483. * shmat(2). Very straightforward, except that Linux passes a pointer
  484. * in which the return value is to be passed. This is subsequently
  485. * handled by libc, apparently.
  486. */
  487. int
  488. linux_shmat(p, v, retval)
  489. struct proc *p;
  490. void *v;
  491. register_t *retval;
  492. {
  493. struct linux_sys_ipc_args /* {
  494. syscallarg(int) what;
  495. syscallarg(int) a1;
  496. syscallarg(int) a2;
  497. syscallarg(int) a3;
  498. syscallarg(caddr_t) ptr;
  499. } */ *uap = v;
  500. struct sys_shmat_args bsa;
  501. int error;
  502. SCARG(&bsa, shmid) = SCARG(uap, a1);
  503. SCARG(&bsa, shmaddr) = SCARG(uap, ptr);
  504. SCARG(&bsa, shmflg) = SCARG(uap, a2);
  505. if ((error = sys_shmat(p, &bsa, retval)))
  506. return error;
  507. if ((error = copyout(&retval[0], (caddr_t) SCARG(uap, a3),
  508. sizeof retval[0])))
  509. return error;
  510. retval[0] = 0;
  511. return 0;
  512. }
  513. /*
  514. * shmdt(): this could have been mapped directly, if it wasn't for
  515. * the extra indirection by the linux_ipc system call.
  516. */
  517. int
  518. linux_shmdt(p, v, retval)
  519. struct proc *p;
  520. void *v;
  521. register_t *retval;
  522. {
  523. struct linux_sys_ipc_args /* {
  524. syscallarg(int) what;
  525. syscallarg(int) a1;
  526. syscallarg(int) a2;
  527. syscallarg(int) a3;
  528. syscallarg(caddr_t) ptr;
  529. } */ *uap = v;
  530. struct sys_shmdt_args bsa;
  531. SCARG(&bsa, shmaddr) = SCARG(uap, ptr);
  532. return sys_shmdt(p, &bsa, retval);
  533. }
  534. /*
  535. * Same story as shmdt.
  536. */
  537. int
  538. linux_shmget(p, v, retval)
  539. struct proc *p;
  540. void *v;
  541. register_t *retval;
  542. {
  543. struct linux_sys_ipc_args /* {
  544. syscallarg(int) what;
  545. syscallarg(int) a1;
  546. syscallarg(int) a2;
  547. syscallarg(int) a3;
  548. syscallarg(caddr_t) ptr;
  549. } */ *uap = v;
  550. struct sys_shmget_args bsa;
  551. SCARG(&bsa, key) = SCARG(uap, a1);
  552. SCARG(&bsa, size) = SCARG(uap, a2);
  553. SCARG(&bsa, shmflg) = SCARG(uap, a3);
  554. return sys_shmget(p, &bsa, retval);
  555. }
  556. /*
  557. * Convert between Linux and OpenBSD shmid_ds structures.
  558. * The order of the fields is once again the difference, and
  559. * we also need a place to store the internal data pointer
  560. * in, which is unfortunately stored in this structure.
  561. *
  562. * We abuse a Linux internal field for that.
  563. */
  564. void
  565. linux_to_bsd_shmid_ds(lsp, bsp)
  566. struct linux_shmid_ds *lsp;
  567. struct shmid_ds *bsp;
  568. {
  569. linux_to_bsd_ipc_perm(&lsp->l_shm_perm, &bsp->shm_perm);
  570. bsp->shm_segsz = lsp->l_shm_segsz;
  571. bsp->shm_lpid = lsp->l_shm_lpid;
  572. bsp->shm_cpid = lsp->l_shm_cpid;
  573. bsp->shm_nattch = lsp->l_shm_nattch;
  574. bsp->shm_atime = lsp->l_shm_atime;
  575. bsp->shm_dtime = lsp->l_shm_dtime;
  576. bsp->shm_ctime = lsp->l_shm_ctime;
  577. bsp->shm_internal = lsp->l_private2; /* XXX Oh well. */
  578. }
  579. int
  580. bsd_to_linux_shmid_ds(bsp, lsp)
  581. struct shmid_ds *bsp;
  582. struct linux_shmid_ds *lsp;
  583. {
  584. bsd_to_linux_ipc_perm(&bsp->shm_perm, &lsp->l_shm_perm);
  585. lsp->l_shm_segsz = bsp->shm_segsz;
  586. lsp->l_shm_lpid = bsp->shm_lpid;
  587. lsp->l_shm_cpid = bsp->shm_cpid;
  588. lsp->l_shm_nattch = bsp->shm_nattch;
  589. if (bsp->shm_atime > LINUX_TIME_MAX)
  590. return EOVERFLOW;
  591. lsp->l_shm_atime = (linux_time_t)bsp->shm_atime;
  592. if (bsp->shm_dtime > LINUX_TIME_MAX)
  593. return EOVERFLOW;
  594. lsp->l_shm_dtime = (linux_time_t)bsp->shm_dtime;
  595. if (bsp->shm_ctime > LINUX_TIME_MAX)
  596. return EOVERFLOW;
  597. lsp->l_shm_ctime = (linux_time_t)bsp->shm_ctime;
  598. lsp->l_private2 = bsp->shm_internal; /* XXX */
  599. return 0;
  600. }
  601. /*
  602. * shmctl. Not implemented (for now): IPC_INFO, SHM_INFO, SHM_STAT
  603. * SHM_LOCK and SHM_UNLOCK are passed on, but currently not implemented
  604. * by OpenBSD itself.
  605. *
  606. * The usual structure conversion and massaging is done.
  607. */
  608. int
  609. linux_shmctl(p, v, retval)
  610. struct proc *p;
  611. void *v;
  612. register_t *retval;
  613. {
  614. struct linux_sys_ipc_args /* {
  615. syscallarg(int) what;
  616. syscallarg(int) a1;
  617. syscallarg(int) a2;
  618. syscallarg(int) a3;
  619. syscallarg(caddr_t) ptr;
  620. } */ *uap = v;
  621. int error;
  622. caddr_t sg;
  623. struct sys_shmctl_args bsa;
  624. struct shmid_ds *bsp, bs;
  625. struct linux_shmid_ds lseg;
  626. switch (SCARG(uap, a2)) {
  627. case LINUX_IPC_STAT:
  628. sg = stackgap_init(p);
  629. bsp = stackgap_alloc(&sg, sizeof (struct shmid_ds));
  630. SCARG(&bsa, shmid) = SCARG(uap, a1);
  631. SCARG(&bsa, cmd) = IPC_STAT;
  632. SCARG(&bsa, buf) = bsp;
  633. if ((error = sys_shmctl(p, &bsa, retval)))
  634. return error;
  635. if ((error = copyin((caddr_t) bsp, (caddr_t) &bs, sizeof bs)))
  636. return error;
  637. if ((error = bsd_to_linux_shmid_ds(&bs, &lseg)))
  638. return error;
  639. return copyout((caddr_t) &lseg, SCARG(uap, ptr), sizeof lseg);
  640. case LINUX_IPC_SET:
  641. if ((error = copyin(SCARG(uap, ptr), (caddr_t) &lseg,
  642. sizeof lseg)))
  643. return error;
  644. linux_to_bsd_shmid_ds(&lseg, &bs);
  645. sg = stackgap_init(p);
  646. bsp = stackgap_alloc(&sg, sizeof (struct shmid_ds));
  647. if ((error = copyout((caddr_t) &bs, (caddr_t) bsp, sizeof bs)))
  648. return error;
  649. SCARG(&bsa, shmid) = SCARG(uap, a1);
  650. SCARG(&bsa, cmd) = IPC_SET;
  651. SCARG(&bsa, buf) = bsp;
  652. return sys_shmctl(p, &bsa, retval);
  653. case LINUX_IPC_RMID:
  654. case LINUX_SHM_LOCK:
  655. case LINUX_SHM_UNLOCK:
  656. SCARG(&bsa, shmid) = SCARG(uap, a1);
  657. switch (SCARG(uap, a2)) {
  658. case LINUX_IPC_RMID:
  659. SCARG(&bsa, cmd) = IPC_RMID;
  660. break;
  661. case LINUX_SHM_LOCK:
  662. SCARG(&bsa, cmd) = SHM_LOCK;
  663. break;
  664. case LINUX_SHM_UNLOCK:
  665. SCARG(&bsa, cmd) = SHM_UNLOCK;
  666. break;
  667. }
  668. SCARG(&bsa, buf) = NULL;
  669. return sys_shmctl(p, &bsa, retval);
  670. case LINUX_IPC_INFO:
  671. case LINUX_SHM_STAT:
  672. case LINUX_SHM_INFO:
  673. default:
  674. return EINVAL;
  675. }
  676. }
  677. #endif /* SYSVSHM */
  678. int
  679. linux_sys_pipe2(struct proc *p, void *v, register_t *retval)
  680. {
  681. struct linux_sys_pipe2_args *uap = v;
  682. struct sys_pipe_args pargs;
  683. /*
  684. * We don't really support pipe2, but glibc falls back to pipe
  685. * if we signal that.
  686. */
  687. if (SCARG(uap, flags) != 0)
  688. return ENOSYS;
  689. /* If no flag is set then this is a plain pipe call. */
  690. SCARG(&pargs, fdp) = SCARG(uap, fdp);
  691. return sys_pipe(p, &pargs, retval);
  692. }