aboutsummaryrefslogtreecommitdiffstats
path: root/fs/compat.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/compat.c')
-rw-r--r--fs/compat.c110
1 files changed, 64 insertions, 46 deletions
diff --git a/fs/compat.c b/fs/compat.c
index 6161255fac45..b7a24d0ca30d 100644
--- a/fs/compat.c
+++ b/fs/compat.c
@@ -870,22 +870,20 @@ asmlinkage long compat_sys_old_readdir(unsigned int fd,
870 struct compat_old_linux_dirent __user *dirent, unsigned int count) 870 struct compat_old_linux_dirent __user *dirent, unsigned int count)
871{ 871{
872 int error; 872 int error;
873 struct file *file; 873 struct fd f = fdget(fd);
874 int fput_needed;
875 struct compat_readdir_callback buf; 874 struct compat_readdir_callback buf;
876 875
877 file = fget_light(fd, &fput_needed); 876 if (!f.file)
878 if (!file)
879 return -EBADF; 877 return -EBADF;
880 878
881 buf.result = 0; 879 buf.result = 0;
882 buf.dirent = dirent; 880 buf.dirent = dirent;
883 881
884 error = vfs_readdir(file, compat_fillonedir, &buf); 882 error = vfs_readdir(f.file, compat_fillonedir, &buf);
885 if (buf.result) 883 if (buf.result)
886 error = buf.result; 884 error = buf.result;
887 885
888 fput_light(file, fput_needed); 886 fdput(f);
889 return error; 887 return error;
890} 888}
891 889
@@ -949,17 +947,16 @@ efault:
949asmlinkage long compat_sys_getdents(unsigned int fd, 947asmlinkage long compat_sys_getdents(unsigned int fd,
950 struct compat_linux_dirent __user *dirent, unsigned int count) 948 struct compat_linux_dirent __user *dirent, unsigned int count)
951{ 949{
952 struct file * file; 950 struct fd f;
953 struct compat_linux_dirent __user * lastdirent; 951 struct compat_linux_dirent __user * lastdirent;
954 struct compat_getdents_callback buf; 952 struct compat_getdents_callback buf;
955 int fput_needed;
956 int error; 953 int error;
957 954
958 if (!access_ok(VERIFY_WRITE, dirent, count)) 955 if (!access_ok(VERIFY_WRITE, dirent, count))
959 return -EFAULT; 956 return -EFAULT;
960 957
961 file = fget_light(fd, &fput_needed); 958 f = fdget(fd);
962 if (!file) 959 if (!f.file)
963 return -EBADF; 960 return -EBADF;
964 961
965 buf.current_dir = dirent; 962 buf.current_dir = dirent;
@@ -967,17 +964,17 @@ asmlinkage long compat_sys_getdents(unsigned int fd,
967 buf.count = count; 964 buf.count = count;
968 buf.error = 0; 965 buf.error = 0;
969 966
970 error = vfs_readdir(file, compat_filldir, &buf); 967 error = vfs_readdir(f.file, compat_filldir, &buf);
971 if (error >= 0) 968 if (error >= 0)
972 error = buf.error; 969 error = buf.error;
973 lastdirent = buf.previous; 970 lastdirent = buf.previous;
974 if (lastdirent) { 971 if (lastdirent) {
975 if (put_user(file->f_pos, &lastdirent->d_off)) 972 if (put_user(f.file->f_pos, &lastdirent->d_off))
976 error = -EFAULT; 973 error = -EFAULT;
977 else 974 else
978 error = count - buf.count; 975 error = count - buf.count;
979 } 976 }
980 fput_light(file, fput_needed); 977 fdput(f);
981 return error; 978 return error;
982} 979}
983 980
@@ -1035,17 +1032,16 @@ efault:
1035asmlinkage long compat_sys_getdents64(unsigned int fd, 1032asmlinkage long compat_sys_getdents64(unsigned int fd,
1036 struct linux_dirent64 __user * dirent, unsigned int count) 1033 struct linux_dirent64 __user * dirent, unsigned int count)
1037{ 1034{
1038 struct file * file; 1035 struct fd f;
1039 struct linux_dirent64 __user * lastdirent; 1036 struct linux_dirent64 __user * lastdirent;
1040 struct compat_getdents_callback64 buf; 1037 struct compat_getdents_callback64 buf;
1041 int fput_needed;
1042 int error; 1038 int error;
1043 1039
1044 if (!access_ok(VERIFY_WRITE, dirent, count)) 1040 if (!access_ok(VERIFY_WRITE, dirent, count))
1045 return -EFAULT; 1041 return -EFAULT;
1046 1042
1047 file = fget_light(fd, &fput_needed); 1043 f = fdget(fd);
1048 if (!file) 1044 if (!f.file)
1049 return -EBADF; 1045 return -EBADF;
1050 1046
1051 buf.current_dir = dirent; 1047 buf.current_dir = dirent;
@@ -1053,18 +1049,18 @@ asmlinkage long compat_sys_getdents64(unsigned int fd,
1053 buf.count = count; 1049 buf.count = count;
1054 buf.error = 0; 1050 buf.error = 0;
1055 1051
1056 error = vfs_readdir(file, compat_filldir64, &buf); 1052 error = vfs_readdir(f.file, compat_filldir64, &buf);
1057 if (error >= 0) 1053 if (error >= 0)
1058 error = buf.error; 1054 error = buf.error;
1059 lastdirent = buf.previous; 1055 lastdirent = buf.previous;
1060 if (lastdirent) { 1056 if (lastdirent) {
1061 typeof(lastdirent->d_off) d_off = file->f_pos; 1057 typeof(lastdirent->d_off) d_off = f.file->f_pos;
1062 if (__put_user_unaligned(d_off, &lastdirent->d_off)) 1058 if (__put_user_unaligned(d_off, &lastdirent->d_off))
1063 error = -EFAULT; 1059 error = -EFAULT;
1064 else 1060 else
1065 error = count - buf.count; 1061 error = count - buf.count;
1066 } 1062 }
1067 fput_light(file, fput_needed); 1063 fdput(f);
1068 return error; 1064 return error;
1069} 1065}
1070#endif /* ! __ARCH_OMIT_COMPAT_SYS_GETDENTS64 */ 1066#endif /* ! __ARCH_OMIT_COMPAT_SYS_GETDENTS64 */
@@ -1152,15 +1148,16 @@ asmlinkage ssize_t
1152compat_sys_readv(unsigned long fd, const struct compat_iovec __user *vec, 1148compat_sys_readv(unsigned long fd, const struct compat_iovec __user *vec,
1153 unsigned long vlen) 1149 unsigned long vlen)
1154{ 1150{
1155 struct file *file; 1151 struct fd f = fdget(fd);
1156 int fput_needed;
1157 ssize_t ret; 1152 ssize_t ret;
1153 loff_t pos;
1158 1154
1159 file = fget_light(fd, &fput_needed); 1155 if (!f.file)
1160 if (!file)
1161 return -EBADF; 1156 return -EBADF;
1162 ret = compat_readv(file, vec, vlen, &file->f_pos); 1157 pos = f.file->f_pos;
1163 fput_light(file, fput_needed); 1158 ret = compat_readv(f.file, vec, vlen, &pos);
1159 f.file->f_pos = pos;
1160 fdput(f);
1164 return ret; 1161 return ret;
1165} 1162}
1166 1163
@@ -1168,19 +1165,18 @@ asmlinkage ssize_t
1168compat_sys_preadv64(unsigned long fd, const struct compat_iovec __user *vec, 1165compat_sys_preadv64(unsigned long fd, const struct compat_iovec __user *vec,
1169 unsigned long vlen, loff_t pos) 1166 unsigned long vlen, loff_t pos)
1170{ 1167{
1171 struct file *file; 1168 struct fd f;
1172 int fput_needed;
1173 ssize_t ret; 1169 ssize_t ret;
1174 1170
1175 if (pos < 0) 1171 if (pos < 0)
1176 return -EINVAL; 1172 return -EINVAL;
1177 file = fget_light(fd, &fput_needed); 1173 f = fdget(fd);
1178 if (!file) 1174 if (!f.file)
1179 return -EBADF; 1175 return -EBADF;
1180 ret = -ESPIPE; 1176 ret = -ESPIPE;
1181 if (file->f_mode & FMODE_PREAD) 1177 if (f.file->f_mode & FMODE_PREAD)
1182 ret = compat_readv(file, vec, vlen, &pos); 1178 ret = compat_readv(f.file, vec, vlen, &pos);
1183 fput_light(file, fput_needed); 1179 fdput(f);
1184 return ret; 1180 return ret;
1185} 1181}
1186 1182
@@ -1218,15 +1214,16 @@ asmlinkage ssize_t
1218compat_sys_writev(unsigned long fd, const struct compat_iovec __user *vec, 1214compat_sys_writev(unsigned long fd, const struct compat_iovec __user *vec,
1219 unsigned long vlen) 1215 unsigned long vlen)
1220{ 1216{
1221 struct file *file; 1217 struct fd f = fdget(fd);
1222 int fput_needed;
1223 ssize_t ret; 1218 ssize_t ret;
1219 loff_t pos;
1224 1220
1225 file = fget_light(fd, &fput_needed); 1221 if (!f.file)
1226 if (!file)
1227 return -EBADF; 1222 return -EBADF;
1228 ret = compat_writev(file, vec, vlen, &file->f_pos); 1223 pos = f.file->f_pos;
1229 fput_light(file, fput_needed); 1224 ret = compat_writev(f.file, vec, vlen, &pos);
1225 f.file->f_pos = pos;
1226 fdput(f);
1230 return ret; 1227 return ret;
1231} 1228}
1232 1229
@@ -1234,19 +1231,18 @@ asmlinkage ssize_t
1234compat_sys_pwritev64(unsigned long fd, const struct compat_iovec __user *vec, 1231compat_sys_pwritev64(unsigned long fd, const struct compat_iovec __user *vec,
1235 unsigned long vlen, loff_t pos) 1232 unsigned long vlen, loff_t pos)
1236{ 1233{
1237 struct file *file; 1234 struct fd f;
1238 int fput_needed;
1239 ssize_t ret; 1235 ssize_t ret;
1240 1236
1241 if (pos < 0) 1237 if (pos < 0)
1242 return -EINVAL; 1238 return -EINVAL;
1243 file = fget_light(fd, &fput_needed); 1239 f = fdget(fd);
1244 if (!file) 1240 if (!f.file)
1245 return -EBADF; 1241 return -EBADF;
1246 ret = -ESPIPE; 1242 ret = -ESPIPE;
1247 if (file->f_mode & FMODE_PWRITE) 1243 if (f.file->f_mode & FMODE_PWRITE)
1248 ret = compat_writev(file, vec, vlen, &pos); 1244 ret = compat_writev(f.file, vec, vlen, &pos);
1249 fput_light(file, fput_needed); 1245 fdput(f);
1250 return ret; 1246 return ret;
1251} 1247}
1252 1248
@@ -1796,3 +1792,25 @@ compat_sys_open_by_handle_at(int mountdirfd,
1796 return do_handle_open(mountdirfd, handle, flags); 1792 return do_handle_open(mountdirfd, handle, flags);
1797} 1793}
1798#endif 1794#endif
1795
1796#ifdef __ARCH_WANT_COMPAT_SYS_SENDFILE
1797asmlinkage long compat_sys_sendfile(int out_fd, int in_fd,
1798 compat_off_t __user *offset, compat_size_t count)
1799{
1800 loff_t pos;
1801 off_t off;
1802 ssize_t ret;
1803
1804 if (offset) {
1805 if (unlikely(get_user(off, offset)))
1806 return -EFAULT;
1807 pos = off;
1808 ret = do_sendfile(out_fd, in_fd, &pos, count, MAX_NON_LFS);
1809 if (unlikely(put_user(pos, offset)))
1810 return -EFAULT;
1811 return ret;
1812 }
1813
1814 return do_sendfile(out_fd, in_fd, NULL, count, 0);
1815}
1816#endif /* __ARCH_WANT_COMPAT_SYS_SENDFILE */