ipc32.c
上传用户:jlfgdled
上传日期:2013-04-10
资源大小:33168k
文件大小:18k
源码类别:

Linux/Unix编程

开发平台:

Unix_Linux

  1. #include <linux/kernel.h>
  2. #include <linux/sched.h>
  3. #include <linux/fs.h> 
  4. #include <linux/file.h> 
  5. #include <linux/sem.h>
  6. #include <linux/msg.h>
  7. #include <linux/mm.h>
  8. #include <linux/shm.h>
  9. #include <linux/slab.h>
  10. #include <linux/ipc.h>
  11. #include <asm/mman.h>
  12. #include <asm/types.h>
  13. #include <asm/uaccess.h>
  14. #include <asm/semaphore.h>
  15. #include <asm/ipc.h>
  16. #include <asm/ia32.h>
  17. /*
  18.  * sys32_ipc() is the de-multiplexer for the SysV IPC calls in 32bit emulation..
  19.  *
  20.  * This is really horribly ugly.
  21.  */
  22. struct msgbuf32 { 
  23. s32 mtype; 
  24. char mtext[1]; 
  25. };
  26. struct ipc_perm32 {
  27. int key;
  28. __kernel_uid_t32 uid;
  29. __kernel_gid_t32 gid;
  30. __kernel_uid_t32 cuid;
  31. __kernel_gid_t32 cgid;
  32. unsigned short mode;
  33. unsigned short seq;
  34. };
  35. struct ipc64_perm32 {
  36.         unsigned key;
  37. __kernel_uid32_t32 uid;
  38. __kernel_gid32_t32 gid;
  39. __kernel_uid32_t32 cuid;
  40. __kernel_gid32_t32 cgid;
  41. unsigned short mode;
  42. unsigned short __pad1;
  43. unsigned short seq;
  44. unsigned short __pad2;
  45. unsigned int unused1;
  46. unsigned int unused2;
  47. };
  48. struct semid_ds32 {
  49. struct ipc_perm32 sem_perm;               /* permissions .. see ipc.h */
  50. __kernel_time_t32 sem_otime;              /* last semop time */
  51. __kernel_time_t32 sem_ctime;              /* last change time */
  52. u32 sem_base;              /* ptr to first semaphore in array */
  53. u32 sem_pending;          /* pending operations to be processed */
  54. u32 sem_pending_last;    /* last pending operation */
  55. u32 undo;                  /* undo requests on this array */
  56. unsigned short  sem_nsems;              /* no. of semaphores in array */
  57. };
  58. struct semid64_ds32 {
  59. struct ipc64_perm32 sem_perm;
  60. __kernel_time_t32 sem_otime;
  61. unsigned int __unused1;
  62. __kernel_time_t32 sem_ctime;
  63. unsigned int __unused2;
  64. unsigned int sem_nsems;
  65. unsigned int __unused3;
  66. unsigned int __unused4;
  67. };
  68. struct msqid_ds32 {
  69. struct ipc_perm32 msg_perm;
  70. u32 msg_first;
  71. u32 msg_last;
  72. __kernel_time_t32 msg_stime;
  73. __kernel_time_t32 msg_rtime;
  74. __kernel_time_t32 msg_ctime;
  75. u32 wwait;
  76. u32 rwait;
  77. unsigned short msg_cbytes;
  78. unsigned short msg_qnum;
  79. unsigned short msg_qbytes;
  80. __kernel_ipc_pid_t32 msg_lspid;
  81. __kernel_ipc_pid_t32 msg_lrpid;
  82. };
  83. struct msqid64_ds32 {
  84. struct ipc64_perm32 msg_perm;
  85. __kernel_time_t32 msg_stime;
  86. unsigned int __unused1;
  87. __kernel_time_t32 msg_rtime;
  88. unsigned int __unused2;
  89. __kernel_time_t32 msg_ctime;
  90. unsigned int __unused3;
  91. unsigned int msg_cbytes;
  92. unsigned int msg_qnum;
  93. unsigned int msg_qbytes;
  94. __kernel_pid_t32 msg_lspid;
  95. __kernel_pid_t32 msg_lrpid;
  96. unsigned int __unused4;
  97. unsigned int __unused5;
  98. };
  99. struct shmid_ds32 {
  100. struct ipc_perm32 shm_perm;
  101. int shm_segsz;
  102. __kernel_time_t32 shm_atime;
  103. __kernel_time_t32 shm_dtime;
  104. __kernel_time_t32 shm_ctime;
  105. __kernel_ipc_pid_t32 shm_cpid;
  106. __kernel_ipc_pid_t32 shm_lpid;
  107. unsigned short shm_nattch;
  108. };
  109. struct shmid64_ds32 {
  110. struct ipc64_perm32 shm_perm;
  111. __kernel_size_t32 shm_segsz;
  112. __kernel_time_t32 shm_atime;
  113. unsigned int __unused1;
  114. __kernel_time_t32 shm_dtime;
  115. unsigned int __unused2;
  116. __kernel_time_t32 shm_ctime;
  117. unsigned int __unused3;
  118. __kernel_pid_t32 shm_cpid;
  119. __kernel_pid_t32 shm_lpid;
  120. unsigned int shm_nattch;
  121. unsigned int __unused4;
  122. unsigned int __unused5;
  123. };
  124. struct shminfo64_32 {
  125. unsigned int shmmax;
  126. unsigned int shmmin;
  127. unsigned int shmmni;
  128. unsigned int shmseg;
  129. unsigned int shmall;
  130. unsigned int __unused1;
  131. unsigned int __unused2;
  132. unsigned int __unused3;
  133. unsigned int __unused4;
  134. };
  135. struct shm_info32 {
  136. int used_ids;
  137. u32 shm_tot, shm_rss, shm_swp;
  138. u32 swap_attempts, swap_successes;
  139. };
  140. struct ipc_kludge {
  141. u32 msgp;
  142. s32 msgtyp;
  143. };
  144. #define A(__x) ((unsigned long)(__x))
  145. #define AA(__x) ((unsigned long)(__x))
  146. #define SEMOP  1
  147. #define SEMGET  2
  148. #define SEMCTL  3
  149. #define MSGSND 11
  150. #define MSGRCV 12
  151. #define MSGGET 13
  152. #define MSGCTL 14
  153. #define SHMAT 21
  154. #define SHMDT 22
  155. #define SHMGET 23
  156. #define SHMCTL 24
  157. #define IPCOP_MASK(__x) (1UL << (__x))
  158. static int
  159. ipc_parse_version32 (int *cmd)
  160. {
  161. if (*cmd & IPC_64) {
  162. *cmd ^= IPC_64;
  163. return IPC_64;
  164. } else {
  165. return IPC_OLD;
  166. }
  167. }
  168. static int
  169. semctl32 (int first, int second, int third, void *uptr)
  170. {
  171. union semun fourth;
  172. u32 pad;
  173. int err = 0, err2;
  174. struct semid64_ds s;
  175. mm_segment_t old_fs;
  176. int version = ipc_parse_version32(&third);
  177. if (!uptr)
  178. return -EINVAL;
  179. if (get_user(pad, (u32 *)uptr))
  180. return -EFAULT;
  181. if (third == SETVAL)
  182. fourth.val = (int)pad;
  183. else
  184. fourth.__pad = (void *)A(pad);
  185. switch (third) {
  186.       case IPC_INFO:
  187.       case IPC_RMID:
  188.       case IPC_SET:
  189.       case SEM_INFO:
  190.       case GETVAL:
  191.       case GETPID:
  192.       case GETNCNT:
  193.       case GETZCNT:
  194.       case GETALL:
  195.       case SETVAL:
  196.       case SETALL:
  197. err = sys_semctl(first, second, third, fourth);
  198. break;
  199.       case IPC_STAT:
  200.       case SEM_STAT:
  201. fourth.__pad = &s;
  202. old_fs = get_fs();
  203. set_fs(KERNEL_DS);
  204. err = sys_semctl(first, second|IPC_64, third, fourth);
  205. set_fs(old_fs);
  206. if (version == IPC_64) {
  207. struct semid64_ds32 *usp64 = (struct semid64_ds32 *) A(pad);
  208. if (!access_ok(VERIFY_WRITE, usp64, sizeof(*usp64))) {
  209. err = -EFAULT;
  210. break;
  211. }
  212. err2 = __put_user(s.sem_perm.key, &usp64->sem_perm.key);
  213. err2 |= __put_user(s.sem_perm.uid, &usp64->sem_perm.uid);
  214. err2 |= __put_user(s.sem_perm.gid, &usp64->sem_perm.gid);
  215. err2 |= __put_user(s.sem_perm.cuid, &usp64->sem_perm.cuid);
  216. err2 |= __put_user(s.sem_perm.cgid, &usp64->sem_perm.cgid);
  217. err2 |= __put_user(s.sem_perm.mode, &usp64->sem_perm.mode);
  218. err2 |= __put_user(s.sem_perm.seq, &usp64->sem_perm.seq);
  219. err2 |= __put_user(s.sem_otime, &usp64->sem_otime);
  220. err2 |= __put_user(s.sem_ctime, &usp64->sem_ctime);
  221. err2 |= __put_user(s.sem_nsems, &usp64->sem_nsems);
  222. } else {
  223. struct semid_ds32 *usp32 = (struct semid_ds32 *) A(pad);
  224. if (!access_ok(VERIFY_WRITE, usp32, sizeof(*usp32))) {
  225. err = -EFAULT;
  226. break;
  227. }
  228. err2 = __put_user(s.sem_perm.key, &usp32->sem_perm.key);
  229. err2 |= __put_user(s.sem_perm.uid, &usp32->sem_perm.uid);
  230. err2 |= __put_user(s.sem_perm.gid, &usp32->sem_perm.gid);
  231. err2 |= __put_user(s.sem_perm.cuid, &usp32->sem_perm.cuid);
  232. err2 |= __put_user(s.sem_perm.cgid, &usp32->sem_perm.cgid);
  233. err2 |= __put_user(s.sem_perm.mode, &usp32->sem_perm.mode);
  234. err2 |= __put_user(s.sem_perm.seq, &usp32->sem_perm.seq);
  235. err2 |= __put_user(s.sem_otime, &usp32->sem_otime);
  236. err2 |= __put_user(s.sem_ctime, &usp32->sem_ctime);
  237. err2 |= __put_user(s.sem_nsems, &usp32->sem_nsems);
  238. }
  239. if (err2)
  240.     err = -EFAULT;
  241. break;
  242. }
  243. return err;
  244. }
  245. #define MAXBUF (64*1024)
  246. static int
  247. do_sys32_msgsnd (int first, int second, int third, void *uptr)
  248. {
  249. struct msgbuf *p;
  250. struct msgbuf32 *up = (struct msgbuf32 *)uptr;
  251. mm_segment_t old_fs;
  252. int err;
  253. if (second >= MAXBUF-sizeof(struct msgbuf))
  254. return -EINVAL; 
  255. p = kmalloc(second + sizeof(struct msgbuf), GFP_USER);
  256. if (!p)
  257. return -ENOMEM;
  258. err = get_user(p->mtype, &up->mtype);
  259. err |= copy_from_user(p->mtext, &up->mtext, second);
  260. if (err)
  261. goto out;
  262. old_fs = get_fs();
  263. set_fs(KERNEL_DS);
  264. err = sys_msgsnd(first, p, second, third);
  265. set_fs(old_fs);
  266.   out:
  267. kfree(p);
  268. return err;
  269. }
  270. static int
  271. do_sys32_msgrcv (int first, int second, int msgtyp, int third, int version, void *uptr)
  272. {
  273. struct msgbuf32 *up;
  274. struct msgbuf *p;
  275. mm_segment_t old_fs;
  276. int err;
  277. if (!version) {
  278. struct ipc_kludge *uipck = (struct ipc_kludge *)uptr;
  279. struct ipc_kludge ipck;
  280. err = -EINVAL;
  281. if (!uptr)
  282. goto out;
  283. err = -EFAULT;
  284. if (copy_from_user(&ipck, uipck, sizeof(struct ipc_kludge)))
  285. goto out;
  286. uptr = (void *)A(ipck.msgp);
  287. msgtyp = ipck.msgtyp;
  288. }
  289. if (second >= MAXBUF-sizeof(struct msgbuf)) 
  290. return -EINVAL; 
  291. err = -ENOMEM;
  292. p = kmalloc(second + sizeof(struct msgbuf), GFP_USER);
  293. if (!p)
  294. goto out;
  295. old_fs = get_fs();
  296. set_fs(KERNEL_DS);
  297. err = sys_msgrcv(first, p, second, msgtyp, third);
  298. set_fs(old_fs);
  299. if (err < 0)
  300. goto free_then_out;
  301. up = (struct msgbuf32 *)uptr;
  302. if (put_user(p->mtype, &up->mtype) || copy_to_user(&up->mtext, p->mtext, err))
  303. err = -EFAULT;
  304. free_then_out:
  305. kfree(p);
  306. out:
  307. return err;
  308. }
  309. static int
  310. msgctl32 (int first, int second, void *uptr)
  311. {
  312. int err = -EINVAL, err2;
  313. struct msqid_ds m;
  314. struct msqid64_ds m64;
  315. struct msqid_ds32 *up32 = (struct msqid_ds32 *)uptr;
  316. struct msqid64_ds32 *up64 = (struct msqid64_ds32 *)uptr;
  317. mm_segment_t old_fs;
  318. int version = ipc_parse_version32(&second);
  319. switch (second) {
  320.       case IPC_INFO:
  321.       case IPC_RMID:
  322.       case MSG_INFO:
  323. err = sys_msgctl(first, second, (struct msqid_ds *)uptr);
  324. break;
  325.       case IPC_SET:
  326. if (version == IPC_64) {
  327. err = get_user(m.msg_perm.uid, &up64->msg_perm.uid);
  328. err |= get_user(m.msg_perm.gid, &up64->msg_perm.gid);
  329. err |= get_user(m.msg_perm.mode, &up64->msg_perm.mode);
  330. err |= get_user(m.msg_qbytes, &up64->msg_qbytes);
  331. } else {
  332. err = get_user(m.msg_perm.uid, &up32->msg_perm.uid);
  333. err |= get_user(m.msg_perm.gid, &up32->msg_perm.gid);
  334. err |= get_user(m.msg_perm.mode, &up32->msg_perm.mode);
  335. err |= get_user(m.msg_qbytes, &up32->msg_qbytes);
  336. }
  337. if (err)
  338. break;
  339. old_fs = get_fs();
  340. set_fs(KERNEL_DS);
  341. err = sys_msgctl(first, second, &m);
  342. set_fs(old_fs);
  343. break;
  344.       case IPC_STAT:
  345.       case MSG_STAT:
  346. old_fs = get_fs();
  347. set_fs(KERNEL_DS);
  348. err = sys_msgctl(first, second|IPC_64, (void *) &m64);
  349. set_fs(old_fs);
  350. if (version == IPC_64) {
  351. if (!access_ok(VERIFY_WRITE, up64, sizeof(*up64))) {
  352. err = -EFAULT;
  353. break;
  354. }
  355. err2 = __put_user(m64.msg_perm.key, &up64->msg_perm.key);
  356. err2 |= __put_user(m64.msg_perm.uid, &up64->msg_perm.uid);
  357. err2 |= __put_user(m64.msg_perm.gid, &up64->msg_perm.gid);
  358. err2 |= __put_user(m64.msg_perm.cuid, &up64->msg_perm.cuid);
  359. err2 |= __put_user(m64.msg_perm.cgid, &up64->msg_perm.cgid);
  360. err2 |= __put_user(m64.msg_perm.mode, &up64->msg_perm.mode);
  361. err2 |= __put_user(m64.msg_perm.seq, &up64->msg_perm.seq);
  362. err2 |= __put_user(m64.msg_stime, &up64->msg_stime);
  363. err2 |= __put_user(m64.msg_rtime, &up64->msg_rtime);
  364. err2 |= __put_user(m64.msg_ctime, &up64->msg_ctime);
  365. err2 |= __put_user(m64.msg_cbytes, &up64->msg_cbytes);
  366. err2 |= __put_user(m64.msg_qnum, &up64->msg_qnum);
  367. err2 |= __put_user(m64.msg_qbytes, &up64->msg_qbytes);
  368. err2 |= __put_user(m64.msg_lspid, &up64->msg_lspid);
  369. err2 |= __put_user(m64.msg_lrpid, &up64->msg_lrpid);
  370. if (err2)
  371. err = -EFAULT;
  372. } else {
  373. if (!access_ok(VERIFY_WRITE, up32, sizeof(*up32))) {
  374. err = -EFAULT;
  375. break;
  376. }
  377. err2 = __put_user(m64.msg_perm.key, &up32->msg_perm.key);
  378. err2 |= __put_user(m64.msg_perm.uid, &up32->msg_perm.uid);
  379. err2 |= __put_user(m64.msg_perm.gid, &up32->msg_perm.gid);
  380. err2 |= __put_user(m64.msg_perm.cuid, &up32->msg_perm.cuid);
  381. err2 |= __put_user(m64.msg_perm.cgid, &up32->msg_perm.cgid);
  382. err2 |= __put_user(m64.msg_perm.mode, &up32->msg_perm.mode);
  383. err2 |= __put_user(m64.msg_perm.seq, &up32->msg_perm.seq);
  384. err2 |= __put_user(m64.msg_stime, &up32->msg_stime);
  385. err2 |= __put_user(m64.msg_rtime, &up32->msg_rtime);
  386. err2 |= __put_user(m64.msg_ctime, &up32->msg_ctime);
  387. err2 |= __put_user(m64.msg_cbytes, &up32->msg_cbytes);
  388. err2 |= __put_user(m64.msg_qnum, &up32->msg_qnum);
  389. err2 |= __put_user(m64.msg_qbytes, &up32->msg_qbytes);
  390. err2 |= __put_user(m64.msg_lspid, &up32->msg_lspid);
  391. err2 |= __put_user(m64.msg_lrpid, &up32->msg_lrpid);
  392. if (err2)
  393. err = -EFAULT;
  394. }
  395. break;
  396. }
  397. return err;
  398. }
  399. static int
  400. shmat32 (int first, int second, int third, int version, void *uptr)
  401. {
  402. unsigned long raddr;
  403. u32 *uaddr = (u32 *)A((u32)third);
  404. int err;
  405. if (version == 1)
  406. return -EINVAL; /* iBCS2 emulator entry point: unsupported */
  407. err = sys_shmat(first, uptr, second, &raddr);
  408. if (err)
  409. return err;
  410. return put_user(raddr, uaddr);
  411. }
  412. static int put_shmid64(struct shmid64_ds *s64p, void *uptr, int version) 
  413. int err2; 
  414. #define s64 (*s64p)
  415. if (version == IPC_64) {
  416. struct shmid64_ds32 *up64 = (struct shmid64_ds32 *)uptr;
  417. if (!access_ok(VERIFY_WRITE, up64, sizeof(*up64)))
  418. return -EFAULT;
  419. err2 = __put_user(s64.shm_perm.key, &up64->shm_perm.key);
  420. err2 |= __put_user(s64.shm_perm.uid, &up64->shm_perm.uid);
  421. err2 |= __put_user(s64.shm_perm.gid, &up64->shm_perm.gid);
  422. err2 |= __put_user(s64.shm_perm.cuid, &up64->shm_perm.cuid);
  423. err2 |= __put_user(s64.shm_perm.cgid, &up64->shm_perm.cgid);
  424. err2 |= __put_user(s64.shm_perm.mode, &up64->shm_perm.mode);
  425. err2 |= __put_user(s64.shm_perm.seq, &up64->shm_perm.seq);
  426. err2 |= __put_user(s64.shm_atime, &up64->shm_atime);
  427. err2 |= __put_user(s64.shm_dtime, &up64->shm_dtime);
  428. err2 |= __put_user(s64.shm_ctime, &up64->shm_ctime);
  429. err2 |= __put_user(s64.shm_segsz, &up64->shm_segsz);
  430. err2 |= __put_user(s64.shm_nattch, &up64->shm_nattch);
  431. err2 |= __put_user(s64.shm_cpid, &up64->shm_cpid);
  432. err2 |= __put_user(s64.shm_lpid, &up64->shm_lpid);
  433. } else {
  434. struct shmid_ds32 *up32 = (struct shmid_ds32 *)uptr;
  435. if (!access_ok(VERIFY_WRITE, up32, sizeof(*up32))) 
  436. return -EFAULT;
  437. err2 = __put_user(s64.shm_perm.key, &up32->shm_perm.key);
  438. err2 |= __put_user(s64.shm_perm.uid, &up32->shm_perm.uid);
  439. err2 |= __put_user(s64.shm_perm.gid, &up32->shm_perm.gid);
  440. err2 |= __put_user(s64.shm_perm.cuid, &up32->shm_perm.cuid);
  441. err2 |= __put_user(s64.shm_perm.cgid, &up32->shm_perm.cgid);
  442. err2 |= __put_user(s64.shm_perm.mode, &up32->shm_perm.mode);
  443. err2 |= __put_user(s64.shm_perm.seq, &up32->shm_perm.seq);
  444. err2 |= __put_user(s64.shm_atime, &up32->shm_atime);
  445. err2 |= __put_user(s64.shm_dtime, &up32->shm_dtime);
  446. err2 |= __put_user(s64.shm_ctime, &up32->shm_ctime);
  447. err2 |= __put_user(s64.shm_segsz, &up32->shm_segsz);
  448. err2 |= __put_user(s64.shm_nattch, &up32->shm_nattch);
  449. err2 |= __put_user(s64.shm_cpid, &up32->shm_cpid);
  450. err2 |= __put_user(s64.shm_lpid, &up32->shm_lpid);
  451. }
  452. #undef s64
  453. return err2 ? -EFAULT : 0;
  454. }
  455. static int
  456. shmctl32 (int first, int second, void *uptr)
  457. {
  458. int err = -EFAULT, err2;
  459. struct shmid_ds s;
  460. struct shmid64_ds s64;
  461. mm_segment_t old_fs;
  462. struct shm_info32 *uip = (struct shm_info32 *)uptr;
  463. struct shm_info si;
  464. int version = ipc_parse_version32(&second);
  465. struct shminfo64 smi;
  466. struct shminfo *usi32 = (struct shminfo *) uptr;
  467. struct shminfo64_32 *usi64 = (struct shminfo64_32 *) uptr;
  468. switch (second) {
  469.       case IPC_INFO:
  470. old_fs = get_fs();
  471. set_fs(KERNEL_DS);
  472. err = sys_shmctl(first, second|IPC_64, (struct shmid_ds *)&smi);
  473. set_fs(old_fs);
  474. if (version == IPC_64) {
  475. if (!access_ok(VERIFY_WRITE, usi64, sizeof(*usi64))) {
  476. err = -EFAULT;
  477. break;
  478. }
  479. err2 = __put_user(smi.shmmax, &usi64->shmmax);
  480. err2 |= __put_user(smi.shmmin, &usi64->shmmin);
  481. err2 |= __put_user(smi.shmmni, &usi64->shmmni);
  482. err2 |= __put_user(smi.shmseg, &usi64->shmseg);
  483. err2 |= __put_user(smi.shmall, &usi64->shmall);
  484. } else {
  485. if (!access_ok(VERIFY_WRITE, usi32, sizeof(*usi32))) {
  486. err = -EFAULT;
  487. break;
  488. }
  489. err2 = __put_user(smi.shmmax, &usi32->shmmax);
  490. err2 |= __put_user(smi.shmmin, &usi32->shmmin);
  491. err2 |= __put_user(smi.shmmni, &usi32->shmmni);
  492. err2 |= __put_user(smi.shmseg, &usi32->shmseg);
  493. err2 |= __put_user(smi.shmall, &usi32->shmall);
  494. }
  495. if (err2)
  496. err = -EFAULT;
  497. break;
  498.       case IPC_RMID:
  499.       case SHM_LOCK:
  500.       case SHM_UNLOCK:
  501. err = sys_shmctl(first, second, (struct shmid_ds *)uptr);
  502. break;
  503.       case IPC_SET: 
  504. if (version == IPC_64) {
  505. struct shmid64_ds32 *up64 = (struct shmid64_ds32 *)uptr;
  506. err = get_user(s.shm_perm.uid, &up64->shm_perm.uid);
  507. err |= get_user(s.shm_perm.gid, &up64->shm_perm.gid);
  508. err |= get_user(s.shm_perm.mode, &up64->shm_perm.mode);
  509. } else {
  510. struct shmid_ds32 *up32 = (struct shmid_ds32 *)uptr;
  511. err = get_user(s.shm_perm.uid, &up32->shm_perm.uid);
  512. err |= get_user(s.shm_perm.gid, &up32->shm_perm.gid);
  513. err |= get_user(s.shm_perm.mode, &up32->shm_perm.mode);
  514. }
  515. if (err)
  516. break;
  517. old_fs = get_fs();
  518. set_fs(KERNEL_DS);
  519. err = sys_shmctl(first, second, &s);
  520. set_fs(old_fs);
  521. break;
  522.       case IPC_STAT:
  523.       case SHM_STAT:
  524. old_fs = get_fs();
  525. set_fs(KERNEL_DS);
  526. err = sys_shmctl(first, second|IPC_64, (void *) &s64);
  527. set_fs(old_fs);
  528. if (err < 0)
  529. break;
  530.         err2 = put_shmid64(&s64, uptr, version); 
  531. if (err2) 
  532. err = err2;
  533. break;
  534.       case SHM_INFO:
  535. old_fs = get_fs();
  536. set_fs(KERNEL_DS);
  537. err = sys_shmctl(first, second, (void *)&si);
  538. set_fs(old_fs);
  539. if (err < 0)
  540. break;
  541. if (!access_ok(VERIFY_WRITE, uip, sizeof(*uip))) {
  542. err = -EFAULT;
  543. break;
  544. }
  545. err2 = __put_user(si.used_ids, &uip->used_ids);
  546. err2 |= __put_user(si.shm_tot, &uip->shm_tot);
  547. err2 |= __put_user(si.shm_rss, &uip->shm_rss);
  548. err2 |= __put_user(si.shm_swp, &uip->shm_swp);
  549. err2 |= __put_user(si.swap_attempts, &uip->swap_attempts);
  550. err2 |= __put_user(si.swap_successes, &uip->swap_successes);
  551. if (err2)
  552. err = -EFAULT;
  553. break;
  554. }
  555. return err;
  556. }
  557. asmlinkage long
  558. sys32_ipc (u32 call, int first, int second, int third, u32 ptr, u32 fifth)
  559. {
  560. int version;
  561. version = call >> 16; /* hack for backward compatibility */
  562. call &= 0xffff;
  563. switch (call) {
  564.       case SEMOP:
  565. /* struct sembuf is the same on 32 and 64bit :)) */
  566. return sys_semop(first, (struct sembuf *)AA(ptr), second);
  567.       case SEMGET:
  568. return sys_semget(first, second, third);
  569.       case SEMCTL:
  570. return semctl32(first, second, third, (void *)AA(ptr));
  571.       case MSGSND:
  572. return do_sys32_msgsnd(first, second, third, (void *)AA(ptr));
  573.       case MSGRCV:
  574. return do_sys32_msgrcv(first, second, fifth, third, version, (void *)AA(ptr));
  575.       case MSGGET:
  576. return sys_msgget((key_t) first, second);
  577.       case MSGCTL:
  578. return msgctl32(first, second, (void *)AA(ptr));
  579.       case SHMAT:
  580. return shmat32(first, second, third, version, (void *)AA(ptr));
  581. break;
  582.       case SHMDT:
  583. return sys_shmdt((char *)AA(ptr));
  584.       case SHMGET:
  585. return sys_shmget(first, second, third);
  586.       case SHMCTL:
  587. return shmctl32(first, second, (void *)AA(ptr));
  588.       default:
  589. return -EINVAL;
  590. }
  591. return -EINVAL;
  592. }