diff options
Diffstat (limited to 'fs/compat.c')
-rw-r--r-- | fs/compat.c | 89 |
1 files changed, 75 insertions, 14 deletions
diff --git a/fs/compat.c b/fs/compat.c index baabf203b847..1c859dae758f 100644 --- a/fs/compat.c +++ b/fs/compat.c | |||
@@ -1196,16 +1196,12 @@ out: | |||
1196 | return ret; | 1196 | return ret; |
1197 | } | 1197 | } |
1198 | 1198 | ||
1199 | asmlinkage ssize_t | 1199 | static size_t compat_readv(struct file *file, |
1200 | compat_sys_readv(unsigned long fd, const struct compat_iovec __user *vec, unsigned long vlen) | 1200 | const struct compat_iovec __user *vec, |
1201 | unsigned long vlen, loff_t *pos) | ||
1201 | { | 1202 | { |
1202 | struct file *file; | ||
1203 | ssize_t ret = -EBADF; | 1203 | ssize_t ret = -EBADF; |
1204 | 1204 | ||
1205 | file = fget(fd); | ||
1206 | if (!file) | ||
1207 | return -EBADF; | ||
1208 | |||
1209 | if (!(file->f_mode & FMODE_READ)) | 1205 | if (!(file->f_mode & FMODE_READ)) |
1210 | goto out; | 1206 | goto out; |
1211 | 1207 | ||
@@ -1213,25 +1209,56 @@ compat_sys_readv(unsigned long fd, const struct compat_iovec __user *vec, unsign | |||
1213 | if (!file->f_op || (!file->f_op->aio_read && !file->f_op->read)) | 1209 | if (!file->f_op || (!file->f_op->aio_read && !file->f_op->read)) |
1214 | goto out; | 1210 | goto out; |
1215 | 1211 | ||
1216 | ret = compat_do_readv_writev(READ, file, vec, vlen, &file->f_pos); | 1212 | ret = compat_do_readv_writev(READ, file, vec, vlen, pos); |
1217 | 1213 | ||
1218 | out: | 1214 | out: |
1219 | if (ret > 0) | 1215 | if (ret > 0) |
1220 | add_rchar(current, ret); | 1216 | add_rchar(current, ret); |
1221 | inc_syscr(current); | 1217 | inc_syscr(current); |
1222 | fput(file); | ||
1223 | return ret; | 1218 | return ret; |
1224 | } | 1219 | } |
1225 | 1220 | ||
1226 | asmlinkage ssize_t | 1221 | asmlinkage ssize_t |
1227 | compat_sys_writev(unsigned long fd, const struct compat_iovec __user *vec, unsigned long vlen) | 1222 | compat_sys_readv(unsigned long fd, const struct compat_iovec __user *vec, |
1223 | unsigned long vlen) | ||
1228 | { | 1224 | { |
1229 | struct file *file; | 1225 | struct file *file; |
1230 | ssize_t ret = -EBADF; | 1226 | int fput_needed; |
1227 | ssize_t ret; | ||
1231 | 1228 | ||
1232 | file = fget(fd); | 1229 | file = fget_light(fd, &fput_needed); |
1233 | if (!file) | 1230 | if (!file) |
1234 | return -EBADF; | 1231 | return -EBADF; |
1232 | ret = compat_readv(file, vec, vlen, &file->f_pos); | ||
1233 | fput_light(file, fput_needed); | ||
1234 | return ret; | ||
1235 | } | ||
1236 | |||
1237 | asmlinkage ssize_t | ||
1238 | compat_sys_preadv(unsigned long fd, const struct compat_iovec __user *vec, | ||
1239 | unsigned long vlen, u32 pos_high, u32 pos_low) | ||
1240 | { | ||
1241 | loff_t pos = ((loff_t)pos_high << 32) | pos_low; | ||
1242 | struct file *file; | ||
1243 | int fput_needed; | ||
1244 | ssize_t ret; | ||
1245 | |||
1246 | if (pos < 0) | ||
1247 | return -EINVAL; | ||
1248 | file = fget_light(fd, &fput_needed); | ||
1249 | if (!file) | ||
1250 | return -EBADF; | ||
1251 | ret = compat_readv(file, vec, vlen, &pos); | ||
1252 | fput_light(file, fput_needed); | ||
1253 | return ret; | ||
1254 | } | ||
1255 | |||
1256 | static size_t compat_writev(struct file *file, | ||
1257 | const struct compat_iovec __user *vec, | ||
1258 | unsigned long vlen, loff_t *pos) | ||
1259 | { | ||
1260 | ssize_t ret = -EBADF; | ||
1261 | |||
1235 | if (!(file->f_mode & FMODE_WRITE)) | 1262 | if (!(file->f_mode & FMODE_WRITE)) |
1236 | goto out; | 1263 | goto out; |
1237 | 1264 | ||
@@ -1239,13 +1266,47 @@ compat_sys_writev(unsigned long fd, const struct compat_iovec __user *vec, unsig | |||
1239 | if (!file->f_op || (!file->f_op->aio_write && !file->f_op->write)) | 1266 | if (!file->f_op || (!file->f_op->aio_write && !file->f_op->write)) |
1240 | goto out; | 1267 | goto out; |
1241 | 1268 | ||
1242 | ret = compat_do_readv_writev(WRITE, file, vec, vlen, &file->f_pos); | 1269 | ret = compat_do_readv_writev(WRITE, file, vec, vlen, pos); |
1243 | 1270 | ||
1244 | out: | 1271 | out: |
1245 | if (ret > 0) | 1272 | if (ret > 0) |
1246 | add_wchar(current, ret); | 1273 | add_wchar(current, ret); |
1247 | inc_syscw(current); | 1274 | inc_syscw(current); |
1248 | fput(file); | 1275 | return ret; |
1276 | } | ||
1277 | |||
1278 | asmlinkage ssize_t | ||
1279 | compat_sys_writev(unsigned long fd, const struct compat_iovec __user *vec, | ||
1280 | unsigned long vlen) | ||
1281 | { | ||
1282 | struct file *file; | ||
1283 | int fput_needed; | ||
1284 | ssize_t ret; | ||
1285 | |||
1286 | file = fget_light(fd, &fput_needed); | ||
1287 | if (!file) | ||
1288 | return -EBADF; | ||
1289 | ret = compat_writev(file, vec, vlen, &file->f_pos); | ||
1290 | fput_light(file, fput_needed); | ||
1291 | return ret; | ||
1292 | } | ||
1293 | |||
1294 | asmlinkage ssize_t | ||
1295 | compat_sys_pwritev(unsigned long fd, const struct compat_iovec __user *vec, | ||
1296 | unsigned long vlen, u32 pos_high, u32 pos_low) | ||
1297 | { | ||
1298 | loff_t pos = ((loff_t)pos_high << 32) | pos_low; | ||
1299 | struct file *file; | ||
1300 | int fput_needed; | ||
1301 | ssize_t ret; | ||
1302 | |||
1303 | if (pos < 0) | ||
1304 | return -EINVAL; | ||
1305 | file = fget_light(fd, &fput_needed); | ||
1306 | if (!file) | ||
1307 | return -EBADF; | ||
1308 | ret = compat_writev(file, vec, vlen, &pos); | ||
1309 | fput_light(file, fput_needed); | ||
1249 | return ret; | 1310 | return ret; |
1250 | } | 1311 | } |
1251 | 1312 | ||