ipc: move compat shmctl to native

Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>

Al Viro 553f770e 9ba720c1

+231 -235
+3 -230
ipc/compat.c
··· 39 39 char mtext[1]; 40 40 }; 41 41 42 - struct compat_ipc_perm { 43 - key_t key; 44 - __compat_uid_t uid; 45 - __compat_gid_t gid; 46 - __compat_uid_t cuid; 47 - __compat_gid_t cgid; 48 - compat_mode_t mode; 49 - unsigned short seq; 50 - }; 51 - 52 42 struct compat_semid_ds { 53 43 struct compat_ipc_perm sem_perm; 54 44 compat_time_t sem_otime; ··· 66 76 compat_ipc_pid_t msg_lrpid; 67 77 }; 68 78 69 - struct compat_shmid_ds { 70 - struct compat_ipc_perm shm_perm; 71 - int shm_segsz; 72 - compat_time_t shm_atime; 73 - compat_time_t shm_dtime; 74 - compat_time_t shm_ctime; 75 - compat_ipc_pid_t shm_cpid; 76 - compat_ipc_pid_t shm_lpid; 77 - unsigned short shm_nattch; 78 - unsigned short shm_unused; 79 - compat_uptr_t shm_unused2; 80 - compat_uptr_t shm_unused3; 81 - }; 82 - 83 79 struct compat_ipc_kludge { 84 80 compat_uptr_t msgp; 85 81 compat_long_t msgtyp; 86 82 }; 87 83 88 - struct compat_shminfo64 { 89 - compat_ulong_t shmmax; 90 - compat_ulong_t shmmin; 91 - compat_ulong_t shmmni; 92 - compat_ulong_t shmseg; 93 - compat_ulong_t shmall; 94 - compat_ulong_t __unused1; 95 - compat_ulong_t __unused2; 96 - compat_ulong_t __unused3; 97 - compat_ulong_t __unused4; 98 - }; 99 - 100 - struct compat_shm_info { 101 - compat_int_t used_ids; 102 - compat_ulong_t shm_tot, shm_rss, shm_swp; 103 - compat_ulong_t swap_attempts, swap_successes; 104 - }; 105 - 106 - static inline int compat_ipc_parse_version(int *cmd) 84 + static inline int __compat_ipc_parse_version(int *cmd) 107 85 { 108 86 #ifdef CONFIG_ARCH_WANT_COMPAT_IPC_PARSE_VERSION 109 87 int version = *cmd & IPC_64; ··· 199 241 int err, err2; 200 242 struct semid64_ds sem64; 201 243 struct semid64_ds __user *up64; 202 - int version = compat_ipc_parse_version(&third); 244 + int version = __compat_ipc_parse_version(&third); 203 245 204 246 memset(&sem64, 0, sizeof(sem64)); 205 247 ··· 457 499 { 458 500 int err, err2; 459 501 struct msqid64_ds m64; 460 - int version = compat_ipc_parse_version(&second); 502 + int version = __compat_ipc_parse_version(&second); 461 503 void __user *p; 462 504 463 505 memset(&m64, 0, sizeof(m64)); ··· 517 559 return err; 518 560 force_successful_syscall_return(); 519 561 return (long)ret; 520 - } 521 - 522 - static inline int get_compat_shmid64_ds(struct shmid64_ds *sem64, 523 - struct compat_shmid64_ds __user *up64) 524 - { 525 - if (!access_ok(VERIFY_READ, up64, sizeof(*up64))) 526 - return -EFAULT; 527 - return __get_compat_ipc64_perm(&sem64->shm_perm, &up64->shm_perm); 528 - } 529 - 530 - static inline int get_compat_shmid_ds(struct shmid64_ds *s, 531 - struct compat_shmid_ds __user *up) 532 - { 533 - if (!access_ok(VERIFY_READ, up, sizeof(*up))) 534 - return -EFAULT; 535 - return __get_compat_ipc_perm(&s->shm_perm, &up->shm_perm); 536 - } 537 - 538 - static inline int put_compat_shmid64_ds(struct shmid64_ds *sem64, 539 - struct compat_shmid64_ds __user *up64) 540 - { 541 - int err; 542 - 543 - if (!access_ok(VERIFY_WRITE, up64, sizeof(*up64))) 544 - return -EFAULT; 545 - err = __put_compat_ipc64_perm(&sem64->shm_perm, &up64->shm_perm); 546 - err |= __put_user(sem64->shm_atime, &up64->shm_atime); 547 - err |= __put_user(sem64->shm_dtime, &up64->shm_dtime); 548 - err |= __put_user(sem64->shm_ctime, &up64->shm_ctime); 549 - err |= __put_user(sem64->shm_segsz, &up64->shm_segsz); 550 - err |= __put_user(sem64->shm_nattch, &up64->shm_nattch); 551 - err |= __put_user(sem64->shm_cpid, &up64->shm_cpid); 552 - err |= __put_user(sem64->shm_lpid, &up64->shm_lpid); 553 - return err; 554 - } 555 - 556 - static inline int put_compat_shmid_ds(struct shmid64_ds *s, 557 - struct compat_shmid_ds __user *up) 558 - { 559 - int err; 560 - 561 - if (!access_ok(VERIFY_WRITE, up, sizeof(*up))) 562 - return -EFAULT; 563 - err = __put_compat_ipc_perm(&s->shm_perm, &up->shm_perm); 564 - err |= __put_user(s->shm_atime, &up->shm_atime); 565 - err |= __put_user(s->shm_dtime, &up->shm_dtime); 566 - err |= __put_user(s->shm_ctime, &up->shm_ctime); 567 - err |= __put_user(s->shm_segsz, &up->shm_segsz); 568 - err |= __put_user(s->shm_nattch, &up->shm_nattch); 569 - err |= __put_user(s->shm_cpid, &up->shm_cpid); 570 - err |= __put_user(s->shm_lpid, &up->shm_lpid); 571 - return err; 572 - } 573 - 574 - static inline int put_compat_shminfo64(struct shminfo64 *smi, 575 - struct compat_shminfo64 __user *up64) 576 - { 577 - int err; 578 - 579 - if (!access_ok(VERIFY_WRITE, up64, sizeof(*up64))) 580 - return -EFAULT; 581 - if (smi->shmmax > INT_MAX) 582 - smi->shmmax = INT_MAX; 583 - err = __put_user(smi->shmmax, &up64->shmmax); 584 - err |= __put_user(smi->shmmin, &up64->shmmin); 585 - err |= __put_user(smi->shmmni, &up64->shmmni); 586 - err |= __put_user(smi->shmseg, &up64->shmseg); 587 - err |= __put_user(smi->shmall, &up64->shmall); 588 - return err; 589 - } 590 - 591 - static inline int put_compat_shminfo(struct shminfo64 *smi, 592 - struct shminfo __user *up) 593 - { 594 - int err; 595 - 596 - if (!access_ok(VERIFY_WRITE, up, sizeof(*up))) 597 - return -EFAULT; 598 - if (smi->shmmax > INT_MAX) 599 - smi->shmmax = INT_MAX; 600 - err = __put_user(smi->shmmax, &up->shmmax); 601 - err |= __put_user(smi->shmmin, &up->shmmin); 602 - err |= __put_user(smi->shmmni, &up->shmmni); 603 - err |= __put_user(smi->shmseg, &up->shmseg); 604 - err |= __put_user(smi->shmall, &up->shmall); 605 - return err; 606 - } 607 - 608 - static inline int put_compat_shm_info(struct shm_info __user *ip, 609 - struct compat_shm_info __user *uip) 610 - { 611 - int err; 612 - struct shm_info si; 613 - 614 - if (!access_ok(VERIFY_WRITE, uip, sizeof(*uip)) || 615 - copy_from_user(&si, ip, sizeof(si))) 616 - return -EFAULT; 617 - err = __put_user(si.used_ids, &uip->used_ids); 618 - err |= __put_user(si.shm_tot, &uip->shm_tot); 619 - err |= __put_user(si.shm_rss, &uip->shm_rss); 620 - err |= __put_user(si.shm_swp, &uip->shm_swp); 621 - err |= __put_user(si.swap_attempts, &uip->swap_attempts); 622 - err |= __put_user(si.swap_successes, &uip->swap_successes); 623 - return err; 624 - } 625 - 626 - COMPAT_SYSCALL_DEFINE3(shmctl, int, first, int, second, void __user *, uptr) 627 - { 628 - void __user *p; 629 - struct shmid64_ds sem64; 630 - struct shminfo64 smi; 631 - int err, err2; 632 - int version = compat_ipc_parse_version(&second); 633 - 634 - memset(&sem64, 0, sizeof(sem64)); 635 - 636 - switch (second & (~IPC_64)) { 637 - case IPC_RMID: 638 - case SHM_LOCK: 639 - case SHM_UNLOCK: 640 - err = sys_shmctl(first, second, uptr); 641 - break; 642 - 643 - case IPC_INFO: 644 - p = compat_alloc_user_space(sizeof(smi)); 645 - err = sys_shmctl(first, second, p); 646 - if (err < 0) 647 - break; 648 - if (copy_from_user(&smi, p, sizeof(smi))) 649 - err2 = -EFAULT; 650 - else if (version == IPC_64) 651 - err2 = put_compat_shminfo64(&smi, uptr); 652 - else 653 - err2 = put_compat_shminfo(&smi, uptr); 654 - if (err2) 655 - err = -EFAULT; 656 - break; 657 - 658 - 659 - case IPC_SET: 660 - if (version == IPC_64) 661 - err = get_compat_shmid64_ds(&sem64, uptr); 662 - else 663 - err = get_compat_shmid_ds(&sem64, uptr); 664 - 665 - if (err) 666 - break; 667 - p = compat_alloc_user_space(sizeof(sem64)); 668 - if (copy_to_user(p, &sem64, sizeof(sem64))) 669 - err = -EFAULT; 670 - else 671 - err = sys_shmctl(first, second, p); 672 - break; 673 - 674 - case IPC_STAT: 675 - case SHM_STAT: 676 - p = compat_alloc_user_space(sizeof(sem64)); 677 - err = sys_shmctl(first, second, p); 678 - if (err < 0) 679 - break; 680 - if (copy_from_user(&sem64, p, sizeof(sem64))) 681 - err2 = -EFAULT; 682 - else if (version == IPC_64) 683 - err2 = put_compat_shmid64_ds(&sem64, uptr); 684 - else 685 - err2 = put_compat_shmid_ds(&sem64, uptr); 686 - if (err2) 687 - err = -EFAULT; 688 - break; 689 - 690 - case SHM_INFO: 691 - p = compat_alloc_user_space(sizeof(struct shm_info)); 692 - err = sys_shmctl(first, second, p); 693 - if (err < 0) 694 - break; 695 - err2 = put_compat_shm_info(p, uptr); 696 - if (err2) 697 - err = -EFAULT; 698 - break; 699 - 700 - default: 701 - err = -EINVAL; 702 - break; 703 - } 704 - return err; 705 562 } 706 563 707 564 COMPAT_SYSCALL_DEFINE4(semtimedop, int, semid, struct sembuf __user *, tsems,
+204 -5
ipc/shm.c
··· 1030 1030 { 1031 1031 int err, version; 1032 1032 struct ipc_namespace *ns; 1033 - struct shmid64_ds tbuf; 1033 + struct shmid64_ds sem64; 1034 1034 1035 1035 if (cmd < 0 || shmid < 0) 1036 1036 return -EINVAL; ··· 1059 1059 } 1060 1060 case SHM_STAT: 1061 1061 case IPC_STAT: { 1062 - err = shmctl_stat(ns, shmid, cmd, &tbuf); 1062 + err = shmctl_stat(ns, shmid, cmd, &sem64); 1063 1063 if (err < 0) 1064 1064 return err; 1065 - if (copy_shmid_to_user(buf, &tbuf, version)) 1065 + if (copy_shmid_to_user(buf, &sem64, version)) 1066 1066 err = -EFAULT; 1067 1067 return err; 1068 1068 } 1069 1069 case IPC_SET: 1070 - if (copy_shmid_from_user(&tbuf, buf, version)) 1070 + if (copy_shmid_from_user(&sem64, buf, version)) 1071 1071 return -EFAULT; 1072 + /* fallthru */ 1072 1073 case IPC_RMID: 1073 - return shmctl_down(ns, shmid, cmd, &tbuf); 1074 + return shmctl_down(ns, shmid, cmd, &sem64); 1074 1075 case SHM_LOCK: 1075 1076 case SHM_UNLOCK: 1076 1077 return shmctl_do_lock(ns, shmid, cmd); ··· 1079 1078 return -EINVAL; 1080 1079 } 1081 1080 } 1081 + 1082 + #ifdef CONFIG_COMPAT 1083 + 1084 + struct compat_shmid_ds { 1085 + struct compat_ipc_perm shm_perm; 1086 + int shm_segsz; 1087 + compat_time_t shm_atime; 1088 + compat_time_t shm_dtime; 1089 + compat_time_t shm_ctime; 1090 + compat_ipc_pid_t shm_cpid; 1091 + compat_ipc_pid_t shm_lpid; 1092 + unsigned short shm_nattch; 1093 + unsigned short shm_unused; 1094 + compat_uptr_t shm_unused2; 1095 + compat_uptr_t shm_unused3; 1096 + }; 1097 + 1098 + struct compat_shminfo64 { 1099 + compat_ulong_t shmmax; 1100 + compat_ulong_t shmmin; 1101 + compat_ulong_t shmmni; 1102 + compat_ulong_t shmseg; 1103 + compat_ulong_t shmall; 1104 + compat_ulong_t __unused1; 1105 + compat_ulong_t __unused2; 1106 + compat_ulong_t __unused3; 1107 + compat_ulong_t __unused4; 1108 + }; 1109 + 1110 + struct compat_shm_info { 1111 + compat_int_t used_ids; 1112 + compat_ulong_t shm_tot, shm_rss, shm_swp; 1113 + compat_ulong_t swap_attempts, swap_successes; 1114 + }; 1115 + 1116 + static int copy_compat_shminfo_to_user(void __user *buf, struct shminfo64 *in, 1117 + int version) 1118 + { 1119 + if (in->shmmax > INT_MAX) 1120 + in->shmmax = INT_MAX; 1121 + if (version == IPC_64) { 1122 + struct compat_shminfo64 info; 1123 + memset(&info, 0, sizeof(info)); 1124 + info.shmmax = in->shmmax; 1125 + info.shmmin = in->shmmin; 1126 + info.shmmni = in->shmmni; 1127 + info.shmseg = in->shmseg; 1128 + info.shmall = in->shmall; 1129 + return copy_to_user(buf, &info, sizeof(info)); 1130 + } else { 1131 + struct shminfo info; 1132 + memset(&info, 0, sizeof(info)); 1133 + info.shmmax = in->shmmax; 1134 + info.shmmin = in->shmmin; 1135 + info.shmmni = in->shmmni; 1136 + info.shmseg = in->shmseg; 1137 + info.shmall = in->shmall; 1138 + return copy_to_user(buf, &info, sizeof(info)); 1139 + } 1140 + } 1141 + 1142 + static int put_compat_shm_info(struct shm_info *ip, 1143 + struct compat_shm_info __user *uip) 1144 + { 1145 + struct compat_shm_info info; 1146 + 1147 + memset(&info, 0, sizeof(info)); 1148 + info.used_ids = ip->used_ids; 1149 + info.shm_tot = ip->shm_tot; 1150 + info.shm_rss = ip->shm_rss; 1151 + info.shm_swp = ip->shm_swp; 1152 + info.swap_attempts = ip->swap_attempts; 1153 + info.swap_successes = ip->swap_successes; 1154 + return copy_to_user(up, &info, sizeof(info)); 1155 + } 1156 + 1157 + static int copy_compat_shmid_to_user(void __user *buf, struct shmid64_ds *in, 1158 + int version) 1159 + { 1160 + if (version == IPC_64) { 1161 + struct compat_shmid64_ds v; 1162 + memset(&v, 0, sizeof(v)); 1163 + v.shm_perm.key = in->shm_perm.key; 1164 + v.shm_perm.uid = in->shm_perm.uid; 1165 + v.shm_perm.gid = in->shm_perm.gid; 1166 + v.shm_perm.cuid = in->shm_perm.cuid; 1167 + v.shm_perm.cgid = in->shm_perm.cgid; 1168 + v.shm_perm.mode = in->shm_perm.mode; 1169 + v.shm_perm.seq = in->shm_perm.seq; 1170 + v.shm_atime = in->shm_atime; 1171 + v.shm_dtime = in->shm_dtime; 1172 + v.shm_ctime = in->shm_ctime; 1173 + v.shm_segsz = in->shm_segsz; 1174 + v.shm_nattch = in->shm_nattch; 1175 + v.shm_cpid = in->shm_cpid; 1176 + v.shm_lpid = in->shm_lpid; 1177 + return copy_to_user(buf, &v, sizeof(v)); 1178 + } else { 1179 + struct compat_shmid_ds v; 1180 + memset(&v, 0, sizeof(v)); 1181 + v.shm_perm.key = in->shm_perm.key; 1182 + SET_UID(v.shm_perm.uid, in->shm_perm.uid); 1183 + SET_GID(v.shm_perm.gid, in->shm_perm.gid); 1184 + SET_UID(v.shm_perm.cuid, in->shm_perm.cuid); 1185 + SET_GID(v.shm_perm.cgid, in->shm_perm.cgid); 1186 + v.shm_perm.mode = in->shm_perm.mode; 1187 + v.shm_perm.seq = in->shm_perm.seq; 1188 + v.shm_atime = in->shm_atime; 1189 + v.shm_dtime = in->shm_dtime; 1190 + v.shm_ctime = in->shm_ctime; 1191 + v.shm_segsz = in->shm_segsz; 1192 + v.shm_nattch = in->shm_nattch; 1193 + v.shm_cpid = in->shm_cpid; 1194 + v.shm_lpid = in->shm_lpid; 1195 + return copy_to_user(buf, &v, sizeof(v)); 1196 + } 1197 + } 1198 + 1199 + static int copy_compat_shmid_from_user(struct shmid64_ds *out, void __user *buf, 1200 + int version) 1201 + { 1202 + memset(out, 0, sizeof(*out)); 1203 + if (version == IPC_64) { 1204 + struct compat_shmid64_ds *p = buf; 1205 + struct compat_ipc64_perm v; 1206 + if (copy_from_user(&v, &p->shm_perm, sizeof(v))) 1207 + return -EFAULT; 1208 + out->shm_perm.uid = v.uid; 1209 + out->shm_perm.gid = v.gid; 1210 + out->shm_perm.mode = v.mode; 1211 + } else { 1212 + struct compat_shmid_ds *p = buf; 1213 + struct compat_ipc_perm v; 1214 + if (copy_from_user(&v, &p->shm_perm, sizeof(v))) 1215 + return -EFAULT; 1216 + out->shm_perm.uid = v.uid; 1217 + out->shm_perm.gid = v.gid; 1218 + out->shm_perm.mode = v.mode; 1219 + } 1220 + return 0; 1221 + } 1222 + 1223 + COMPAT_SYSCALL_DEFINE3(shmctl, int, shmid, int, cmd, void __user *, uptr) 1224 + { 1225 + struct ipc_namespace *ns; 1226 + struct shmid64_ds sem64; 1227 + int version = compat_ipc_parse_version(&cmd); 1228 + int err; 1229 + 1230 + ns = current->nsproxy->ipc_ns; 1231 + 1232 + if (cmd < 0 || shmid < 0) 1233 + return -EINVAL; 1234 + 1235 + switch (cmd) { 1236 + case IPC_INFO: { 1237 + struct shminfo64 shminfo; 1238 + err = shmctl_ipc_info(ns, &shminfo); 1239 + if (err < 0) 1240 + return err; 1241 + if (copy_compat_shminfo_to_user(uptr, &shminfo, version)) 1242 + err = -EFAULT; 1243 + return err; 1244 + } 1245 + case SHM_INFO: { 1246 + struct shm_info shm_info; 1247 + err = shmctl_shm_info(ns, &shm_info); 1248 + if (err < 0) 1249 + return err; 1250 + if (put_compat_shm_info(&shm_info, uptr)) 1251 + err = -EFAULT; 1252 + return err; 1253 + } 1254 + case IPC_STAT: 1255 + case SHM_STAT: 1256 + err = shmctl_stat(ns, shmid, cmd, &sem64); 1257 + if (err < 0) 1258 + return err; 1259 + if (copy_compat_shmid_to_user(&sem64, uptr, version)) 1260 + err = -EFAULT; 1261 + return err; 1262 + 1263 + case IPC_SET: 1264 + if (copy_compat_shmid_from_user(&sem64, uptr, version)) 1265 + return -EFAULT; 1266 + /* fallthru */ 1267 + case IPC_RMID: 1268 + return shmctl_down(ns, shmid, cmd, &sem64); 1269 + case SHM_LOCK: 1270 + case SHM_UNLOCK: 1271 + return shmctl_do_lock(ns, shmid, cmd); 1272 + break; 1273 + default: 1274 + return -EINVAL; 1275 + } 1276 + return err; 1277 + } 1278 + #endif 1082 1279 1083 1280 /* 1084 1281 * Fix shmaddr, allocate descriptor, map shm, add attach descriptor to lists.
+24
ipc/util.h
··· 191 191 const struct ipc_ops *ops, struct ipc_params *params); 192 192 void free_ipcs(struct ipc_namespace *ns, struct ipc_ids *ids, 193 193 void (*free)(struct ipc_namespace *, struct kern_ipc_perm *)); 194 + 195 + #ifdef CONFIG_COMPAT 196 + #include <linux/compat.h> 197 + struct compat_ipc_perm { 198 + key_t key; 199 + __compat_uid_t uid; 200 + __compat_gid_t gid; 201 + __compat_uid_t cuid; 202 + __compat_gid_t cgid; 203 + compat_mode_t mode; 204 + unsigned short seq; 205 + }; 206 + 207 + static inline int compat_ipc_parse_version(int *cmd) 208 + { 209 + #ifdef CONFIG_ARCH_WANT_COMPAT_IPC_PARSE_VERSION 210 + int version = *cmd & IPC_64; 211 + *cmd &= ~IPC_64; 212 + return version; 213 + #else 214 + return IPC_64; 215 + #endif 216 + } 217 + #endif 194 218 #endif