1 /* 2 * arch/arm/kernel/sys_oabi-compat.c 3 * 4 * Compatibility wrappers for syscalls that are used from 5 * old ABI user space binaries with an EABI kernel. 6 * 7 * Author: Nicolas Pitre 8 * Created: Oct 7, 2005 9 * Copyright: MontaVista Software, Inc. 10 * 11 * This program is free software; you can redistribute it and/or modify 12 * it under the terms of the GNU General Public License version 2 as 13 * published by the Free Software Foundation. 14 */ 15 16 /* 17 * The legacy ABI and the new ARM EABI have different rules making some 18 * syscalls incompatible especially with structure arguments. 19 * Most notably, Eabi says 64-bit members should be 64-bit aligned instead of 20 * simply word aligned. EABI also pads structures to the size of the largest 21 * member it contains instead of the invariant 32-bit. 22 * 23 * The following syscalls are affected: 24 * 25 * sys_stat64: 26 * sys_lstat64: 27 * sys_fstat64: 28 * 29 * struct stat64 has different sizes and some members are shifted 30 * Compatibility wrappers are needed for them and provided below. 31 * 32 * sys_fcntl64: 33 * 34 * struct flock64 has different sizes and some members are shifted 35 * A compatibility wrapper is needed and provided below. 36 * 37 * sys_statfs64: 38 * sys_fstatfs64: 39 * 40 * struct statfs64 has extra padding with EABI growing its size from 41 * 84 to 88. This struct is now __attribute__((packed,aligned(4))) 42 * with a small assembly wrapper to force the sz argument to 84 if it is 88 43 * to avoid copying the extra padding over user space unexpecting it. 44 * 45 * sys_newuname: 46 * 47 * struct new_utsname has no padding with EABI. No problem there. 48 * 49 * sys_epoll_ctl: 50 * sys_epoll_wait: 51 * 52 * struct epoll_event has its second member shifted also affecting the 53 * structure size. Compatibility wrappers are needed and provided below. 54 * 55 * sys_ipc: 56 * sys_semop: 57 * sys_semtimedop: 58 * 59 * struct sembuf loses its padding with EABI. Since arrays of them are 60 * used they have to be copyed to remove the padding. Compatibility wrappers 61 * provided below. 62 * 63 * sys_bind: 64 * sys_connect: 65 * sys_sendmsg: 66 * sys_sendto: 67 * sys_socketcall: 68 * 69 * struct sockaddr_un loses its padding with EABI. Since the size of the 70 * structure is used as a validation test in unix_mkname(), we need to 71 * change the length argument to 110 whenever it is 112. Compatibility 72 * wrappers provided below. 73 */ 74 75 #include <linux/syscalls.h> 76 #include <linux/errno.h> 77 #include <linux/fs.h> 78 #include <linux/fcntl.h> 79 #include <linux/eventpoll.h> 80 #include <linux/sem.h> 81 #include <linux/socket.h> 82 #include <linux/net.h> 83 #include <linux/ipc.h> 84 #include <asm/uaccess.h> 85 86 struct oldabi_stat64 { 87 unsigned long long st_dev; 88 unsigned int __pad1; 89 unsigned long __st_ino; 90 unsigned int st_mode; 91 unsigned int st_nlink; 92 93 unsigned long st_uid; 94 unsigned long st_gid; 95 96 unsigned long long st_rdev; 97 unsigned int __pad2; 98 99 long long st_size; 100 unsigned long st_blksize; 101 unsigned long long st_blocks; 102 103 unsigned long st_atime; 104 unsigned long st_atime_nsec; 105 106 unsigned long st_mtime; 107 unsigned long st_mtime_nsec; 108 109 unsigned long st_ctime; 110 unsigned long st_ctime_nsec; 111 112 unsigned long long st_ino; 113 } __attribute__ ((packed,aligned(4))); 114 115 static long cp_oldabi_stat64(struct kstat *stat, 116 struct oldabi_stat64 __user *statbuf) 117 { 118 struct oldabi_stat64 tmp; 119 120 tmp.st_dev = huge_encode_dev(stat->dev); 121 tmp.__pad1 = 0; 122 tmp.__st_ino = stat->ino; 123 tmp.st_mode = stat->mode; 124 tmp.st_nlink = stat->nlink; 125 tmp.st_uid = stat->uid; 126 tmp.st_gid = stat->gid; 127 tmp.st_rdev = huge_encode_dev(stat->rdev); 128 tmp.st_size = stat->size; 129 tmp.st_blocks = stat->blocks; 130 tmp.__pad2 = 0; 131 tmp.st_blksize = stat->blksize; 132 tmp.st_atime = stat->atime.tv_sec; 133 tmp.st_atime_nsec = stat->atime.tv_nsec; 134 tmp.st_mtime = stat->mtime.tv_sec; 135 tmp.st_mtime_nsec = stat->mtime.tv_nsec; 136 tmp.st_ctime = stat->ctime.tv_sec; 137 tmp.st_ctime_nsec = stat->ctime.tv_nsec; 138 tmp.st_ino = stat->ino; 139 return copy_to_user(statbuf,&tmp,sizeof(tmp)) ? -EFAULT : 0; 140 } 141 142 asmlinkage long sys_oabi_stat64(char __user * filename, 143 struct oldabi_stat64 __user * statbuf) 144 { 145 struct kstat stat; 146 int error = vfs_stat(filename, &stat); 147 if (!error) 148 error = cp_oldabi_stat64(&stat, statbuf); 149 return error; 150 } 151 152 asmlinkage long sys_oabi_lstat64(char __user * filename, 153 struct oldabi_stat64 __user * statbuf) 154 { 155 struct kstat stat; 156 int error = vfs_lstat(filename, &stat); 157 if (!error) 158 error = cp_oldabi_stat64(&stat, statbuf); 159 return error; 160 } 161 162 asmlinkage long sys_oabi_fstat64(unsigned long fd, 163 struct oldabi_stat64 __user * statbuf) 164 { 165 struct kstat stat; 166 int error = vfs_fstat(fd, &stat); 167 if (!error) 168 error = cp_oldabi_stat64(&stat, statbuf); 169 return error; 170 } 171 172 struct oabi_flock64 { 173 short l_type; 174 short l_whence; 175 loff_t l_start; 176 loff_t l_len; 177 pid_t l_pid; 178 } __attribute__ ((packed,aligned(4))); 179 180 asmlinkage long sys_oabi_fcntl64(unsigned int fd, unsigned int cmd, 181 unsigned long arg) 182 { 183 struct oabi_flock64 user; 184 struct flock64 kernel; 185 mm_segment_t fs = USER_DS; /* initialized to kill a warning */ 186 unsigned long local_arg = arg; 187 int ret; 188 189 switch (cmd) { 190 case F_GETLK64: 191 case F_SETLK64: 192 case F_SETLKW64: 193 if (copy_from_user(&user, (struct oabi_flock64 __user *)arg, 194 sizeof(user))) 195 return -EFAULT; 196 kernel.l_type = user.l_type; 197 kernel.l_whence = user.l_whence; 198 kernel.l_start = user.l_start; 199 kernel.l_len = user.l_len; 200 kernel.l_pid = user.l_pid; 201 local_arg = (unsigned long)&kernel; 202 fs = get_fs(); 203 set_fs(KERNEL_DS); 204 } 205 206 ret = sys_fcntl64(fd, cmd, local_arg); 207 208 switch (cmd) { 209 case F_GETLK64: 210 if (!ret) { 211 user.l_type = kernel.l_type; 212 user.l_whence = kernel.l_whence; 213 user.l_start = kernel.l_start; 214 user.l_len = kernel.l_len; 215 user.l_pid = kernel.l_pid; 216 if (copy_to_user((struct oabi_flock64 __user *)arg, 217 &user, sizeof(user))) 218 ret = -EFAULT; 219 } 220 case F_SETLK64: 221 case F_SETLKW64: 222 set_fs(fs); 223 } 224 225 return ret; 226 } 227 228 struct oabi_epoll_event { 229 __u32 events; 230 __u64 data; 231 } __attribute__ ((packed,aligned(4))); 232 233 asmlinkage long sys_oabi_epoll_ctl(int epfd, int op, int fd, 234 struct oabi_epoll_event __user *event) 235 { 236 struct oabi_epoll_event user; 237 struct epoll_event kernel; 238 mm_segment_t fs; 239 long ret; 240 241 if (op == EPOLL_CTL_DEL) 242 return sys_epoll_ctl(epfd, op, fd, NULL); 243 if (copy_from_user(&user, event, sizeof(user))) 244 return -EFAULT; 245 kernel.events = user.events; 246 kernel.data = user.data; 247 fs = get_fs(); 248 set_fs(KERNEL_DS); 249 ret = sys_epoll_ctl(epfd, op, fd, &kernel); 250 set_fs(fs); 251 return ret; 252 } 253 254 asmlinkage long sys_oabi_epoll_wait(int epfd, 255 struct oabi_epoll_event __user *events, 256 int maxevents, int timeout) 257 { 258 struct epoll_event *kbuf; 259 mm_segment_t fs; 260 long ret, err, i; 261 262 if (maxevents <= 0 || maxevents > (INT_MAX/sizeof(struct epoll_event))) 263 return -EINVAL; 264 kbuf = kmalloc(sizeof(*kbuf) * maxevents, GFP_KERNEL); 265 if (!kbuf) 266 return -ENOMEM; 267 fs = get_fs(); 268 set_fs(KERNEL_DS); 269 ret = sys_epoll_wait(epfd, kbuf, maxevents, timeout); 270 set_fs(fs); 271 err = 0; 272 for (i = 0; i < ret; i++) { 273 __put_user_error(kbuf[i].events, &events->events, err); 274 __put_user_error(kbuf[i].data, &events->data, err); 275 events++; 276 } 277 kfree(kbuf); 278 return err ? -EFAULT : ret; 279 } 280 281 struct oabi_sembuf { 282 unsigned short sem_num; 283 short sem_op; 284 short sem_flg; 285 unsigned short __pad; 286 }; 287 288 asmlinkage long sys_oabi_semtimedop(int semid, 289 struct oabi_sembuf __user *tsops, 290 unsigned nsops, 291 const struct timespec __user *timeout) 292 { 293 struct sembuf *sops; 294 struct timespec local_timeout; 295 long err; 296 int i; 297 298 if (nsops < 1) 299 return -EINVAL; 300 sops = kmalloc(sizeof(*sops) * nsops, GFP_KERNEL); 301 if (!sops) 302 return -ENOMEM; 303 err = 0; 304 for (i = 0; i < nsops; i++) { 305 __get_user_error(sops[i].sem_num, &tsops->sem_num, err); 306 __get_user_error(sops[i].sem_op, &tsops->sem_op, err); 307 __get_user_error(sops[i].sem_flg, &tsops->sem_flg, err); 308 tsops++; 309 } 310 if (timeout) { 311 /* copy this as well before changing domain protection */ 312 err |= copy_from_user(&local_timeout, timeout, sizeof(*timeout)); 313 timeout = &local_timeout; 314 } 315 if (err) { 316 err = -EFAULT; 317 } else { 318 mm_segment_t fs = get_fs(); 319 set_fs(KERNEL_DS); 320 err = sys_semtimedop(semid, sops, nsops, timeout); 321 set_fs(fs); 322 } 323 kfree(sops); 324 return err; 325 } 326 327 asmlinkage long sys_oabi_semop(int semid, struct oabi_sembuf __user *tsops, 328 unsigned nsops) 329 { 330 return sys_oabi_semtimedop(semid, tsops, nsops, NULL); 331 } 332 333 extern asmlinkage int sys_ipc(uint call, int first, int second, int third, 334 void __user *ptr, long fifth); 335 336 asmlinkage int sys_oabi_ipc(uint call, int first, int second, int third, 337 void __user *ptr, long fifth) 338 { 339 switch (call & 0xffff) { 340 case SEMOP: 341 return sys_oabi_semtimedop(first, 342 (struct oabi_sembuf __user *)ptr, 343 second, NULL); 344 case SEMTIMEDOP: 345 return sys_oabi_semtimedop(first, 346 (struct oabi_sembuf __user *)ptr, 347 second, 348 (const struct timespec __user *)fifth); 349 default: 350 return sys_ipc(call, first, second, third, ptr, fifth); 351 } 352 } 353 354 asmlinkage long sys_oabi_bind(int fd, struct sockaddr __user *addr, int addrlen) 355 { 356 sa_family_t sa_family; 357 if (addrlen == 112 && 358 get_user(sa_family, &addr->sa_family) == 0 && 359 sa_family == AF_UNIX) 360 addrlen = 110; 361 return sys_bind(fd, addr, addrlen); 362 } 363 364 asmlinkage long sys_oabi_connect(int fd, struct sockaddr __user *addr, int addrlen) 365 { 366 sa_family_t sa_family; 367 if (addrlen == 112 && 368 get_user(sa_family, &addr->sa_family) == 0 && 369 sa_family == AF_UNIX) 370 addrlen = 110; 371 return sys_connect(fd, addr, addrlen); 372 } 373 374 asmlinkage long sys_oabi_sendto(int fd, void __user *buff, 375 size_t len, unsigned flags, 376 struct sockaddr __user *addr, 377 int addrlen) 378 { 379 sa_family_t sa_family; 380 if (addrlen == 112 && 381 get_user(sa_family, &addr->sa_family) == 0 && 382 sa_family == AF_UNIX) 383 addrlen = 110; 384 return sys_sendto(fd, buff, len, flags, addr, addrlen); 385 } 386 387 asmlinkage long sys_oabi_sendmsg(int fd, struct msghdr __user *msg, unsigned flags) 388 { 389 struct sockaddr __user *addr; 390 int msg_namelen; 391 sa_family_t sa_family; 392 if (msg && 393 get_user(msg_namelen, &msg->msg_namelen) == 0 && 394 msg_namelen == 112 && 395 get_user(addr, &msg->msg_name) == 0 && 396 get_user(sa_family, &addr->sa_family) == 0 && 397 sa_family == AF_UNIX) 398 { 399 /* 400 * HACK ALERT: there is a limit to how much backward bending 401 * we should do for what is actually a transitional 402 * compatibility layer. This already has known flaws with 403 * a few ioctls that we don't intend to fix. Therefore 404 * consider this blatent hack as another one... and take care 405 * to run for cover. In most cases it will "just work fine". 406 * If it doesn't, well, tough. 407 */ 408 put_user(110, &msg->msg_namelen); 409 } 410 return sys_sendmsg(fd, msg, flags); 411 } 412 413 asmlinkage long sys_oabi_socketcall(int call, unsigned long __user *args) 414 { 415 unsigned long r = -EFAULT, a[6]; 416 417 switch (call) { 418 case SYS_BIND: 419 if (copy_from_user(a, args, 3 * sizeof(long)) == 0) 420 r = sys_oabi_bind(a[0], (struct sockaddr __user *)a[1], a[2]); 421 break; 422 case SYS_CONNECT: 423 if (copy_from_user(a, args, 3 * sizeof(long)) == 0) 424 r = sys_oabi_connect(a[0], (struct sockaddr __user *)a[1], a[2]); 425 break; 426 case SYS_SENDTO: 427 if (copy_from_user(a, args, 6 * sizeof(long)) == 0) 428 r = sys_oabi_sendto(a[0], (void __user *)a[1], a[2], a[3], 429 (struct sockaddr __user *)a[4], a[5]); 430 break; 431 case SYS_SENDMSG: 432 if (copy_from_user(a, args, 3 * sizeof(long)) == 0) 433 r = sys_oabi_sendmsg(a[0], (struct msghdr __user *)a[1], a[2]); 434 break; 435 default: 436 r = sys_socketcall(call, args); 437 } 438 439 return r; 440 } 441