diff options
Diffstat (limited to 'fs/compat.c')
-rw-r--r-- | fs/compat.c | 105 |
1 files changed, 89 insertions, 16 deletions
diff --git a/fs/compat.c b/fs/compat.c index 55efdfebdf5a..1c859dae758f 100644 --- a/fs/compat.c +++ b/fs/compat.c | |||
@@ -51,6 +51,7 @@ | |||
51 | #include <linux/poll.h> | 51 | #include <linux/poll.h> |
52 | #include <linux/mm.h> | 52 | #include <linux/mm.h> |
53 | #include <linux/eventpoll.h> | 53 | #include <linux/eventpoll.h> |
54 | #include <linux/fs_struct.h> | ||
54 | 55 | ||
55 | #include <asm/uaccess.h> | 56 | #include <asm/uaccess.h> |
56 | #include <asm/mmu_context.h> | 57 | #include <asm/mmu_context.h> |
@@ -1195,16 +1196,12 @@ out: | |||
1195 | return ret; | 1196 | return ret; |
1196 | } | 1197 | } |
1197 | 1198 | ||
1198 | asmlinkage ssize_t | 1199 | static size_t compat_readv(struct file *file, |
1199 | 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) | ||
1200 | { | 1202 | { |
1201 | struct file *file; | ||
1202 | ssize_t ret = -EBADF; | 1203 | ssize_t ret = -EBADF; |
1203 | 1204 | ||
1204 | file = fget(fd); | ||
1205 | if (!file) | ||
1206 | return -EBADF; | ||
1207 | |||
1208 | if (!(file->f_mode & FMODE_READ)) | 1205 | if (!(file->f_mode & FMODE_READ)) |
1209 | goto out; | 1206 | goto out; |
1210 | 1207 | ||
@@ -1212,25 +1209,56 @@ compat_sys_readv(unsigned long fd, const struct compat_iovec __user *vec, unsign | |||
1212 | 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)) |
1213 | goto out; | 1210 | goto out; |
1214 | 1211 | ||
1215 | ret = compat_do_readv_writev(READ, file, vec, vlen, &file->f_pos); | 1212 | ret = compat_do_readv_writev(READ, file, vec, vlen, pos); |
1216 | 1213 | ||
1217 | out: | 1214 | out: |
1218 | if (ret > 0) | 1215 | if (ret > 0) |
1219 | add_rchar(current, ret); | 1216 | add_rchar(current, ret); |
1220 | inc_syscr(current); | 1217 | inc_syscr(current); |
1221 | fput(file); | ||
1222 | return ret; | 1218 | return ret; |
1223 | } | 1219 | } |
1224 | 1220 | ||
1225 | asmlinkage ssize_t | 1221 | asmlinkage ssize_t |
1226 | 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) | ||
1227 | { | 1224 | { |
1228 | struct file *file; | 1225 | struct file *file; |
1229 | ssize_t ret = -EBADF; | 1226 | int fput_needed; |
1227 | ssize_t ret; | ||
1230 | 1228 | ||
1231 | file = fget(fd); | 1229 | file = fget_light(fd, &fput_needed); |
1232 | if (!file) | 1230 | if (!file) |
1233 | 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 | |||
1234 | if (!(file->f_mode & FMODE_WRITE)) | 1262 | if (!(file->f_mode & FMODE_WRITE)) |
1235 | goto out; | 1263 | goto out; |
1236 | 1264 | ||
@@ -1238,13 +1266,47 @@ compat_sys_writev(unsigned long fd, const struct compat_iovec __user *vec, unsig | |||
1238 | 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)) |
1239 | goto out; | 1267 | goto out; |
1240 | 1268 | ||
1241 | ret = compat_do_readv_writev(WRITE, file, vec, vlen, &file->f_pos); | 1269 | ret = compat_do_readv_writev(WRITE, file, vec, vlen, pos); |
1242 | 1270 | ||
1243 | out: | 1271 | out: |
1244 | if (ret > 0) | 1272 | if (ret > 0) |
1245 | add_wchar(current, ret); | 1273 | add_wchar(current, ret); |
1246 | inc_syscw(current); | 1274 | inc_syscw(current); |
1247 | 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); | ||
1248 | return ret; | 1310 | return ret; |
1249 | } | 1311 | } |
1250 | 1312 | ||
@@ -1441,12 +1503,15 @@ int compat_do_execve(char * filename, | |||
1441 | bprm->cred = prepare_exec_creds(); | 1503 | bprm->cred = prepare_exec_creds(); |
1442 | if (!bprm->cred) | 1504 | if (!bprm->cred) |
1443 | goto out_unlock; | 1505 | goto out_unlock; |
1444 | check_unsafe_exec(bprm); | 1506 | |
1507 | retval = check_unsafe_exec(bprm); | ||
1508 | if (retval) | ||
1509 | goto out_unlock; | ||
1445 | 1510 | ||
1446 | file = open_exec(filename); | 1511 | file = open_exec(filename); |
1447 | retval = PTR_ERR(file); | 1512 | retval = PTR_ERR(file); |
1448 | if (IS_ERR(file)) | 1513 | if (IS_ERR(file)) |
1449 | goto out_unlock; | 1514 | goto out_unmark; |
1450 | 1515 | ||
1451 | sched_exec(); | 1516 | sched_exec(); |
1452 | 1517 | ||
@@ -1488,6 +1553,9 @@ int compat_do_execve(char * filename, | |||
1488 | goto out; | 1553 | goto out; |
1489 | 1554 | ||
1490 | /* execve succeeded */ | 1555 | /* execve succeeded */ |
1556 | write_lock(¤t->fs->lock); | ||
1557 | current->fs->in_exec = 0; | ||
1558 | write_unlock(¤t->fs->lock); | ||
1491 | current->in_execve = 0; | 1559 | current->in_execve = 0; |
1492 | mutex_unlock(¤t->cred_exec_mutex); | 1560 | mutex_unlock(¤t->cred_exec_mutex); |
1493 | acct_update_integrals(current); | 1561 | acct_update_integrals(current); |
@@ -1506,6 +1574,11 @@ out_file: | |||
1506 | fput(bprm->file); | 1574 | fput(bprm->file); |
1507 | } | 1575 | } |
1508 | 1576 | ||
1577 | out_unmark: | ||
1578 | write_lock(¤t->fs->lock); | ||
1579 | current->fs->in_exec = 0; | ||
1580 | write_unlock(¤t->fs->lock); | ||
1581 | |||
1509 | out_unlock: | 1582 | out_unlock: |
1510 | current->in_execve = 0; | 1583 | current->in_execve = 0; |
1511 | mutex_unlock(¤t->cred_exec_mutex); | 1584 | mutex_unlock(¤t->cred_exec_mutex); |