0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018 #include <linux/kernel.h>
0019 #include <linux/sched.h>
0020 #include <linux/fs.h>
0021 #include <linux/mm.h>
0022 #include <linux/file.h>
0023 #include <linux/signal.h>
0024 #include <linux/resource.h>
0025 #include <linux/times.h>
0026 #include <linux/smp.h>
0027 #include <linux/sem.h>
0028 #include <linux/msg.h>
0029 #include <linux/shm.h>
0030 #include <linux/uio.h>
0031 #include <linux/quota.h>
0032 #include <linux/poll.h>
0033 #include <linux/personality.h>
0034 #include <linux/stat.h>
0035 #include <linux/filter.h>
0036 #include <linux/highmem.h>
0037 #include <linux/mman.h>
0038 #include <linux/ipv6.h>
0039 #include <linux/in.h>
0040 #include <linux/icmpv6.h>
0041 #include <linux/syscalls.h>
0042 #include <linux/sysctl.h>
0043 #include <linux/binfmts.h>
0044 #include <linux/capability.h>
0045 #include <linux/compat.h>
0046 #include <linux/vfs.h>
0047 #include <linux/ptrace.h>
0048 #include <linux/fadvise.h>
0049 #include <linux/ipc.h>
0050 #include <linux/slab.h>
0051
0052 #include <asm/types.h>
0053 #include <linux/uaccess.h>
0054
0055 #include <net/scm.h>
0056 #include <net/sock.h>
0057
0058 #include "compat_linux.h"
0059
0060 #ifdef CONFIG_SYSVIPC
0061 COMPAT_SYSCALL_DEFINE5(s390_ipc, uint, call, int, first, compat_ulong_t, second,
0062 compat_ulong_t, third, compat_uptr_t, ptr)
0063 {
0064 if (call >> 16)
0065 return -EINVAL;
0066 return compat_ksys_ipc(call, first, second, third, ptr, third);
0067 }
0068 #endif
0069
0070 COMPAT_SYSCALL_DEFINE3(s390_truncate64, const char __user *, path, u32, high, u32, low)
0071 {
0072 return ksys_truncate(path, (unsigned long)high << 32 | low);
0073 }
0074
0075 COMPAT_SYSCALL_DEFINE3(s390_ftruncate64, unsigned int, fd, u32, high, u32, low)
0076 {
0077 return ksys_ftruncate(fd, (unsigned long)high << 32 | low);
0078 }
0079
0080 COMPAT_SYSCALL_DEFINE5(s390_pread64, unsigned int, fd, char __user *, ubuf,
0081 compat_size_t, count, u32, high, u32, low)
0082 {
0083 if ((compat_ssize_t) count < 0)
0084 return -EINVAL;
0085 return ksys_pread64(fd, ubuf, count, (unsigned long)high << 32 | low);
0086 }
0087
0088 COMPAT_SYSCALL_DEFINE5(s390_pwrite64, unsigned int, fd, const char __user *, ubuf,
0089 compat_size_t, count, u32, high, u32, low)
0090 {
0091 if ((compat_ssize_t) count < 0)
0092 return -EINVAL;
0093 return ksys_pwrite64(fd, ubuf, count, (unsigned long)high << 32 | low);
0094 }
0095
0096 COMPAT_SYSCALL_DEFINE4(s390_readahead, int, fd, u32, high, u32, low, s32, count)
0097 {
0098 return ksys_readahead(fd, (unsigned long)high << 32 | low, count);
0099 }
0100
0101 struct stat64_emu31 {
0102 unsigned long long st_dev;
0103 unsigned int __pad1;
0104 #define STAT64_HAS_BROKEN_ST_INO 1
0105 u32 __st_ino;
0106 unsigned int st_mode;
0107 unsigned int st_nlink;
0108 u32 st_uid;
0109 u32 st_gid;
0110 unsigned long long st_rdev;
0111 unsigned int __pad3;
0112 long st_size;
0113 u32 st_blksize;
0114 unsigned char __pad4[4];
0115 u32 __pad5;
0116 u32 st_blocks;
0117 u32 st_atime;
0118 u32 __pad6;
0119 u32 st_mtime;
0120 u32 __pad7;
0121 u32 st_ctime;
0122 u32 __pad8;
0123 unsigned long st_ino;
0124 };
0125
0126 static int cp_stat64(struct stat64_emu31 __user *ubuf, struct kstat *stat)
0127 {
0128 struct stat64_emu31 tmp;
0129
0130 memset(&tmp, 0, sizeof(tmp));
0131
0132 tmp.st_dev = huge_encode_dev(stat->dev);
0133 tmp.st_ino = stat->ino;
0134 tmp.__st_ino = (u32)stat->ino;
0135 tmp.st_mode = stat->mode;
0136 tmp.st_nlink = (unsigned int)stat->nlink;
0137 tmp.st_uid = from_kuid_munged(current_user_ns(), stat->uid);
0138 tmp.st_gid = from_kgid_munged(current_user_ns(), stat->gid);
0139 tmp.st_rdev = huge_encode_dev(stat->rdev);
0140 tmp.st_size = stat->size;
0141 tmp.st_blksize = (u32)stat->blksize;
0142 tmp.st_blocks = (u32)stat->blocks;
0143 tmp.st_atime = (u32)stat->atime.tv_sec;
0144 tmp.st_mtime = (u32)stat->mtime.tv_sec;
0145 tmp.st_ctime = (u32)stat->ctime.tv_sec;
0146
0147 return copy_to_user(ubuf,&tmp,sizeof(tmp)) ? -EFAULT : 0;
0148 }
0149
0150 COMPAT_SYSCALL_DEFINE2(s390_stat64, const char __user *, filename, struct stat64_emu31 __user *, statbuf)
0151 {
0152 struct kstat stat;
0153 int ret = vfs_stat(filename, &stat);
0154 if (!ret)
0155 ret = cp_stat64(statbuf, &stat);
0156 return ret;
0157 }
0158
0159 COMPAT_SYSCALL_DEFINE2(s390_lstat64, const char __user *, filename, struct stat64_emu31 __user *, statbuf)
0160 {
0161 struct kstat stat;
0162 int ret = vfs_lstat(filename, &stat);
0163 if (!ret)
0164 ret = cp_stat64(statbuf, &stat);
0165 return ret;
0166 }
0167
0168 COMPAT_SYSCALL_DEFINE2(s390_fstat64, unsigned int, fd, struct stat64_emu31 __user *, statbuf)
0169 {
0170 struct kstat stat;
0171 int ret = vfs_fstat(fd, &stat);
0172 if (!ret)
0173 ret = cp_stat64(statbuf, &stat);
0174 return ret;
0175 }
0176
0177 COMPAT_SYSCALL_DEFINE4(s390_fstatat64, unsigned int, dfd, const char __user *, filename,
0178 struct stat64_emu31 __user *, statbuf, int, flag)
0179 {
0180 struct kstat stat;
0181 int error;
0182
0183 error = vfs_fstatat(dfd, filename, &stat, flag);
0184 if (error)
0185 return error;
0186 return cp_stat64(statbuf, &stat);
0187 }
0188
0189
0190
0191
0192
0193
0194
0195 struct mmap_arg_struct_emu31 {
0196 compat_ulong_t addr;
0197 compat_ulong_t len;
0198 compat_ulong_t prot;
0199 compat_ulong_t flags;
0200 compat_ulong_t fd;
0201 compat_ulong_t offset;
0202 };
0203
0204 COMPAT_SYSCALL_DEFINE1(s390_old_mmap, struct mmap_arg_struct_emu31 __user *, arg)
0205 {
0206 struct mmap_arg_struct_emu31 a;
0207
0208 if (copy_from_user(&a, arg, sizeof(a)))
0209 return -EFAULT;
0210 if (a.offset & ~PAGE_MASK)
0211 return -EINVAL;
0212 return ksys_mmap_pgoff(a.addr, a.len, a.prot, a.flags, a.fd,
0213 a.offset >> PAGE_SHIFT);
0214 }
0215
0216 COMPAT_SYSCALL_DEFINE1(s390_mmap2, struct mmap_arg_struct_emu31 __user *, arg)
0217 {
0218 struct mmap_arg_struct_emu31 a;
0219
0220 if (copy_from_user(&a, arg, sizeof(a)))
0221 return -EFAULT;
0222 return ksys_mmap_pgoff(a.addr, a.len, a.prot, a.flags, a.fd, a.offset);
0223 }
0224
0225 COMPAT_SYSCALL_DEFINE3(s390_read, unsigned int, fd, char __user *, buf, compat_size_t, count)
0226 {
0227 if ((compat_ssize_t) count < 0)
0228 return -EINVAL;
0229
0230 return ksys_read(fd, buf, count);
0231 }
0232
0233 COMPAT_SYSCALL_DEFINE3(s390_write, unsigned int, fd, const char __user *, buf, compat_size_t, count)
0234 {
0235 if ((compat_ssize_t) count < 0)
0236 return -EINVAL;
0237
0238 return ksys_write(fd, buf, count);
0239 }
0240
0241
0242
0243
0244
0245
0246
0247 COMPAT_SYSCALL_DEFINE5(s390_fadvise64, int, fd, u32, high, u32, low, compat_size_t, len, int, advise)
0248 {
0249 if (advise == 4)
0250 advise = POSIX_FADV_DONTNEED;
0251 else if (advise == 5)
0252 advise = POSIX_FADV_NOREUSE;
0253 return ksys_fadvise64_64(fd, (unsigned long)high << 32 | low, len,
0254 advise);
0255 }
0256
0257 struct fadvise64_64_args {
0258 int fd;
0259 long long offset;
0260 long long len;
0261 int advice;
0262 };
0263
0264 COMPAT_SYSCALL_DEFINE1(s390_fadvise64_64, struct fadvise64_64_args __user *, args)
0265 {
0266 struct fadvise64_64_args a;
0267
0268 if ( copy_from_user(&a, args, sizeof(a)) )
0269 return -EFAULT;
0270 if (a.advice == 4)
0271 a.advice = POSIX_FADV_DONTNEED;
0272 else if (a.advice == 5)
0273 a.advice = POSIX_FADV_NOREUSE;
0274 return ksys_fadvise64_64(a.fd, a.offset, a.len, a.advice);
0275 }
0276
0277 COMPAT_SYSCALL_DEFINE6(s390_sync_file_range, int, fd, u32, offhigh, u32, offlow,
0278 u32, nhigh, u32, nlow, unsigned int, flags)
0279 {
0280 return ksys_sync_file_range(fd, ((loff_t)offhigh << 32) + offlow,
0281 ((u64)nhigh << 32) + nlow, flags);
0282 }
0283
0284 COMPAT_SYSCALL_DEFINE6(s390_fallocate, int, fd, int, mode, u32, offhigh, u32, offlow,
0285 u32, lenhigh, u32, lenlow)
0286 {
0287 return ksys_fallocate(fd, mode, ((loff_t)offhigh << 32) + offlow,
0288 ((u64)lenhigh << 32) + lenlow);
0289 }