aboutsummaryrefslogtreecommitdiffstats
path: root/fs/compat.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/compat.c')
-rw-r--r--fs/compat.c148
1 files changed, 131 insertions, 17 deletions
diff --git a/fs/compat.c b/fs/compat.c
index d0145ca27572..3f84d5f15889 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>
@@ -378,6 +379,34 @@ out:
378 return error; 379 return error;
379} 380}
380 381
382/*
383 * This is a copy of sys_ustat, just dealing with a structure layout.
384 * Given how simple this syscall is that apporach is more maintainable
385 * than the various conversion hacks.
386 */
387asmlinkage long compat_sys_ustat(unsigned dev, struct compat_ustat __user *u)
388{
389 struct super_block *sb;
390 struct compat_ustat tmp;
391 struct kstatfs sbuf;
392 int err;
393
394 sb = user_get_super(new_decode_dev(dev));
395 if (!sb)
396 return -EINVAL;
397 err = vfs_statfs(sb->s_root, &sbuf);
398 drop_super(sb);
399 if (err)
400 return err;
401
402 memset(&tmp, 0, sizeof(struct compat_ustat));
403 tmp.f_tfree = sbuf.f_bfree;
404 tmp.f_tinode = sbuf.f_ffree;
405 if (copy_to_user(u, &tmp, sizeof(struct compat_ustat)))
406 return -EFAULT;
407 return 0;
408}
409
381static int get_compat_flock(struct flock *kfl, struct compat_flock __user *ufl) 410static int get_compat_flock(struct flock *kfl, struct compat_flock __user *ufl)
382{ 411{
383 if (!access_ok(VERIFY_READ, ufl, sizeof(*ufl)) || 412 if (!access_ok(VERIFY_READ, ufl, sizeof(*ufl)) ||
@@ -1167,16 +1196,12 @@ out:
1167 return ret; 1196 return ret;
1168} 1197}
1169 1198
1170asmlinkage ssize_t 1199static size_t compat_readv(struct file *file,
1171compat_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)
1172{ 1202{
1173 struct file *file;
1174 ssize_t ret = -EBADF; 1203 ssize_t ret = -EBADF;
1175 1204
1176 file = fget(fd);
1177 if (!file)
1178 return -EBADF;
1179
1180 if (!(file->f_mode & FMODE_READ)) 1205 if (!(file->f_mode & FMODE_READ))
1181 goto out; 1206 goto out;
1182 1207
@@ -1184,25 +1209,56 @@ compat_sys_readv(unsigned long fd, const struct compat_iovec __user *vec, unsign
1184 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))
1185 goto out; 1210 goto out;
1186 1211
1187 ret = compat_do_readv_writev(READ, file, vec, vlen, &file->f_pos); 1212 ret = compat_do_readv_writev(READ, file, vec, vlen, pos);
1188 1213
1189out: 1214out:
1190 if (ret > 0) 1215 if (ret > 0)
1191 add_rchar(current, ret); 1216 add_rchar(current, ret);
1192 inc_syscr(current); 1217 inc_syscr(current);
1193 fput(file);
1194 return ret; 1218 return ret;
1195} 1219}
1196 1220
1197asmlinkage ssize_t 1221asmlinkage ssize_t
1198compat_sys_writev(unsigned long fd, const struct compat_iovec __user *vec, unsigned long vlen) 1222compat_sys_readv(unsigned long fd, const struct compat_iovec __user *vec,
1223 unsigned long vlen)
1199{ 1224{
1200 struct file *file; 1225 struct file *file;
1201 ssize_t ret = -EBADF; 1226 int fput_needed;
1227 ssize_t ret;
1202 1228
1203 file = fget(fd); 1229 file = fget_light(fd, &fput_needed);
1204 if (!file) 1230 if (!file)
1205 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
1237asmlinkage ssize_t
1238compat_sys_preadv(unsigned long fd, const struct compat_iovec __user *vec,
1239 unsigned long vlen, u32 pos_low, u32 pos_high)
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
1256static 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
1206 if (!(file->f_mode & FMODE_WRITE)) 1262 if (!(file->f_mode & FMODE_WRITE))
1207 goto out; 1263 goto out;
1208 1264
@@ -1210,13 +1266,47 @@ compat_sys_writev(unsigned long fd, const struct compat_iovec __user *vec, unsig
1210 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))
1211 goto out; 1267 goto out;
1212 1268
1213 ret = compat_do_readv_writev(WRITE, file, vec, vlen, &file->f_pos); 1269 ret = compat_do_readv_writev(WRITE, file, vec, vlen, pos);
1214 1270
1215out: 1271out:
1216 if (ret > 0) 1272 if (ret > 0)
1217 add_wchar(current, ret); 1273 add_wchar(current, ret);
1218 inc_syscw(current); 1274 inc_syscw(current);
1219 fput(file); 1275 return ret;
1276}
1277
1278asmlinkage ssize_t
1279compat_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
1294asmlinkage ssize_t
1295compat_sys_pwritev(unsigned long fd, const struct compat_iovec __user *vec,
1296 unsigned long vlen, u32 pos_low, u32 pos_high)
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);
1220 return ret; 1310 return ret;
1221} 1311}
1222 1312
@@ -1392,27 +1482,36 @@ int compat_do_execve(char * filename,
1392{ 1482{
1393 struct linux_binprm *bprm; 1483 struct linux_binprm *bprm;
1394 struct file *file; 1484 struct file *file;
1485 struct files_struct *displaced;
1395 int retval; 1486 int retval;
1396 1487
1488 retval = unshare_files(&displaced);
1489 if (retval)
1490 goto out_ret;
1491
1397 retval = -ENOMEM; 1492 retval = -ENOMEM;
1398 bprm = kzalloc(sizeof(*bprm), GFP_KERNEL); 1493 bprm = kzalloc(sizeof(*bprm), GFP_KERNEL);
1399 if (!bprm) 1494 if (!bprm)
1400 goto out_ret; 1495 goto out_files;
1401 1496
1402 retval = mutex_lock_interruptible(&current->cred_exec_mutex); 1497 retval = mutex_lock_interruptible(&current->cred_exec_mutex);
1403 if (retval < 0) 1498 if (retval < 0)
1404 goto out_free; 1499 goto out_free;
1500 current->in_execve = 1;
1405 1501
1406 retval = -ENOMEM; 1502 retval = -ENOMEM;
1407 bprm->cred = prepare_exec_creds(); 1503 bprm->cred = prepare_exec_creds();
1408 if (!bprm->cred) 1504 if (!bprm->cred)
1409 goto out_unlock; 1505 goto out_unlock;
1410 check_unsafe_exec(bprm, current->files); 1506
1507 retval = check_unsafe_exec(bprm);
1508 if (retval)
1509 goto out_unlock;
1411 1510
1412 file = open_exec(filename); 1511 file = open_exec(filename);
1413 retval = PTR_ERR(file); 1512 retval = PTR_ERR(file);
1414 if (IS_ERR(file)) 1513 if (IS_ERR(file))
1415 goto out_unlock; 1514 goto out_unmark;
1416 1515
1417 sched_exec(); 1516 sched_exec();
1418 1517
@@ -1454,9 +1553,15 @@ int compat_do_execve(char * filename,
1454 goto out; 1553 goto out;
1455 1554
1456 /* execve succeeded */ 1555 /* execve succeeded */
1556 write_lock(&current->fs->lock);
1557 current->fs->in_exec = 0;
1558 write_unlock(&current->fs->lock);
1559 current->in_execve = 0;
1457 mutex_unlock(&current->cred_exec_mutex); 1560 mutex_unlock(&current->cred_exec_mutex);
1458 acct_update_integrals(current); 1561 acct_update_integrals(current);
1459 free_bprm(bprm); 1562 free_bprm(bprm);
1563 if (displaced)
1564 put_files_struct(displaced);
1460 return retval; 1565 return retval;
1461 1566
1462out: 1567out:
@@ -1469,12 +1574,21 @@ out_file:
1469 fput(bprm->file); 1574 fput(bprm->file);
1470 } 1575 }
1471 1576
1577out_unmark:
1578 write_lock(&current->fs->lock);
1579 current->fs->in_exec = 0;
1580 write_unlock(&current->fs->lock);
1581
1472out_unlock: 1582out_unlock:
1583 current->in_execve = 0;
1473 mutex_unlock(&current->cred_exec_mutex); 1584 mutex_unlock(&current->cred_exec_mutex);
1474 1585
1475out_free: 1586out_free:
1476 free_bprm(bprm); 1587 free_bprm(bprm);
1477 1588
1589out_files:
1590 if (displaced)
1591 reset_files_struct(displaced);
1478out_ret: 1592out_ret:
1479 return retval; 1593 return retval;
1480} 1594}