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 | ||
