diff options
Diffstat (limited to 'fs/compat.c')
-rw-r--r-- | fs/compat.c | 110 |
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: | |||
949 | asmlinkage long compat_sys_getdents(unsigned int fd, | 947 | asmlinkage 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: | |||
1035 | asmlinkage long compat_sys_getdents64(unsigned int fd, | 1032 | asmlinkage 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 | |||
1152 | compat_sys_readv(unsigned long fd, const struct compat_iovec __user *vec, | 1148 | compat_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 | |||
1168 | compat_sys_preadv64(unsigned long fd, const struct compat_iovec __user *vec, | 1165 | compat_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 | |||
1218 | compat_sys_writev(unsigned long fd, const struct compat_iovec __user *vec, | 1214 | compat_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 | |||
1234 | compat_sys_pwritev64(unsigned long fd, const struct compat_iovec __user *vec, | 1231 | compat_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 | ||
1797 | asmlinkage 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 */ | ||