~ubuntu-branches/ubuntu/precise/linux-ti-omap4/precise

« back to all changes in this revision

Viewing changes to fs/compat.c

  • Committer: Bazaar Package Importer
  • Author(s): Paolo Pisati
  • Date: 2011-06-29 15:23:51 UTC
  • mfrom: (26.1.1 natty-proposed)
  • Revision ID: james.westby@ubuntu.com-20110629152351-xs96tm303d95rpbk
Tags: 3.0.0-1200.2
* Rebased against 3.0.0-6.7
* BSP from TI based on 3.0.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
50
50
#include <linux/fs_struct.h>
51
51
#include <linux/slab.h>
52
52
#include <linux/pagemap.h>
53
 
#include <trace/fs.h>
54
53
 
55
54
#include <asm/uaccess.h>
56
55
#include <asm/mmu_context.h>
263
262
 */
264
263
asmlinkage long compat_sys_statfs(const char __user *pathname, struct compat_statfs __user *buf)
265
264
{
266
 
        struct path path;
267
 
        int error;
268
 
 
269
 
        error = user_path(pathname, &path);
270
 
        if (!error) {
271
 
                struct kstatfs tmp;
272
 
                error = vfs_statfs(&path, &tmp);
273
 
                if (!error)
274
 
                        error = put_compat_statfs(buf, &tmp);
275
 
                path_put(&path);
276
 
        }
 
265
        struct kstatfs tmp;
 
266
        int error = user_statfs(pathname, &tmp);
 
267
        if (!error)
 
268
                error = put_compat_statfs(buf, &tmp);
277
269
        return error;
278
270
}
279
271
 
280
272
asmlinkage long compat_sys_fstatfs(unsigned int fd, struct compat_statfs __user *buf)
281
273
{
282
 
        struct file * file;
283
274
        struct kstatfs tmp;
284
 
        int error;
285
 
 
286
 
        error = -EBADF;
287
 
        file = fget(fd);
288
 
        if (!file)
289
 
                goto out;
290
 
        error = vfs_statfs(&file->f_path, &tmp);
 
275
        int error = fd_statfs(fd, &tmp);
291
276
        if (!error)
292
277
                error = put_compat_statfs(buf, &tmp);
293
 
        fput(file);
294
 
out:
295
278
        return error;
296
279
}
297
280
 
330
313
 
331
314
asmlinkage long compat_sys_statfs64(const char __user *pathname, compat_size_t sz, struct compat_statfs64 __user *buf)
332
315
{
333
 
        struct path path;
 
316
        struct kstatfs tmp;
334
317
        int error;
335
318
 
336
319
        if (sz != sizeof(*buf))
337
320
                return -EINVAL;
338
321
 
339
 
        error = user_path(pathname, &path);
340
 
        if (!error) {
341
 
                struct kstatfs tmp;
342
 
                error = vfs_statfs(&path, &tmp);
343
 
                if (!error)
344
 
                        error = put_compat_statfs64(buf, &tmp);
345
 
                path_put(&path);
346
 
        }
 
322
        error = user_statfs(pathname, &tmp);
 
323
        if (!error)
 
324
                error = put_compat_statfs64(buf, &tmp);
347
325
        return error;
348
326
}
349
327
 
350
328
asmlinkage long compat_sys_fstatfs64(unsigned int fd, compat_size_t sz, struct compat_statfs64 __user *buf)
351
329
{
352
 
        struct file * file;
353
330
        struct kstatfs tmp;
354
331
        int error;
355
332
 
356
333
        if (sz != sizeof(*buf))
357
334
                return -EINVAL;
358
335
 
359
 
        error = -EBADF;
360
 
        file = fget(fd);
361
 
        if (!file)
362
 
                goto out;
363
 
        error = vfs_statfs(&file->f_path, &tmp);
 
336
        error = fd_statfs(fd, &tmp);
364
337
        if (!error)
365
338
                error = put_compat_statfs64(buf, &tmp);
366
 
        fput(file);
367
 
out:
368
339
        return error;
369
340
}
370
341
 
1335
1306
        return do_sys_open(dfd, filename, flags, mode);
1336
1307
}
1337
1308
 
1338
 
/*
1339
 
 * compat_count() counts the number of arguments/envelopes. It is basically
1340
 
 * a copy of count() from fs/exec.c, except that it works with 32 bit argv
1341
 
 * and envp pointers.
1342
 
 */
1343
 
static int compat_count(compat_uptr_t __user *argv, int max)
1344
 
{
1345
 
        int i = 0;
1346
 
 
1347
 
        if (argv != NULL) {
1348
 
                for (;;) {
1349
 
                        compat_uptr_t p;
1350
 
 
1351
 
                        if (get_user(p, argv))
1352
 
                                return -EFAULT;
1353
 
                        if (!p)
1354
 
                                break;
1355
 
                        argv++;
1356
 
                        if (i++ >= max)
1357
 
                                return -E2BIG;
1358
 
 
1359
 
                        if (fatal_signal_pending(current))
1360
 
                                return -ERESTARTNOHAND;
1361
 
                        cond_resched();
1362
 
                }
1363
 
        }
1364
 
        return i;
1365
 
}
1366
 
 
1367
 
/*
1368
 
 * compat_copy_strings() is basically a copy of copy_strings() from fs/exec.c
1369
 
 * except that it works with 32 bit argv and envp pointers.
1370
 
 */
1371
 
static int compat_copy_strings(int argc, compat_uptr_t __user *argv,
1372
 
                                struct linux_binprm *bprm)
1373
 
{
1374
 
        struct page *kmapped_page = NULL;
1375
 
        char *kaddr = NULL;
1376
 
        unsigned long kpos = 0;
1377
 
        int ret;
1378
 
 
1379
 
        while (argc-- > 0) {
1380
 
                compat_uptr_t str;
1381
 
                int len;
1382
 
                unsigned long pos;
1383
 
 
1384
 
                if (get_user(str, argv+argc) ||
1385
 
                    !(len = strnlen_user(compat_ptr(str), MAX_ARG_STRLEN))) {
1386
 
                        ret = -EFAULT;
1387
 
                        goto out;
1388
 
                }
1389
 
 
1390
 
                if (len > MAX_ARG_STRLEN) {
1391
 
                        ret = -E2BIG;
1392
 
                        goto out;
1393
 
                }
1394
 
 
1395
 
                /* We're going to work our way backwords. */
1396
 
                pos = bprm->p;
1397
 
                str += len;
1398
 
                bprm->p -= len;
1399
 
 
1400
 
                while (len > 0) {
1401
 
                        int offset, bytes_to_copy;
1402
 
 
1403
 
                        if (fatal_signal_pending(current)) {
1404
 
                                ret = -ERESTARTNOHAND;
1405
 
                                goto out;
1406
 
                        }
1407
 
                        cond_resched();
1408
 
 
1409
 
                        offset = pos % PAGE_SIZE;
1410
 
                        if (offset == 0)
1411
 
                                offset = PAGE_SIZE;
1412
 
 
1413
 
                        bytes_to_copy = offset;
1414
 
                        if (bytes_to_copy > len)
1415
 
                                bytes_to_copy = len;
1416
 
 
1417
 
                        offset -= bytes_to_copy;
1418
 
                        pos -= bytes_to_copy;
1419
 
                        str -= bytes_to_copy;
1420
 
                        len -= bytes_to_copy;
1421
 
 
1422
 
                        if (!kmapped_page || kpos != (pos & PAGE_MASK)) {
1423
 
                                struct page *page;
1424
 
 
1425
 
                                page = get_arg_page(bprm, pos, 1);
1426
 
                                if (!page) {
1427
 
                                        ret = -E2BIG;
1428
 
                                        goto out;
1429
 
                                }
1430
 
 
1431
 
                                if (kmapped_page) {
1432
 
                                        flush_kernel_dcache_page(kmapped_page);
1433
 
                                        kunmap(kmapped_page);
1434
 
                                        put_page(kmapped_page);
1435
 
                                }
1436
 
                                kmapped_page = page;
1437
 
                                kaddr = kmap(kmapped_page);
1438
 
                                kpos = pos & PAGE_MASK;
1439
 
                                flush_cache_page(bprm->vma, kpos,
1440
 
                                                 page_to_pfn(kmapped_page));
1441
 
                        }
1442
 
                        if (copy_from_user(kaddr+offset, compat_ptr(str),
1443
 
                                                bytes_to_copy)) {
1444
 
                                ret = -EFAULT;
1445
 
                                goto out;
1446
 
                        }
1447
 
                }
1448
 
        }
1449
 
        ret = 0;
1450
 
out:
1451
 
        if (kmapped_page) {
1452
 
                flush_kernel_dcache_page(kmapped_page);
1453
 
                kunmap(kmapped_page);
1454
 
                put_page(kmapped_page);
1455
 
        }
1456
 
        return ret;
1457
 
}
1458
 
 
1459
 
/*
1460
 
 * compat_do_execve() is mostly a copy of do_execve(), with the exception
1461
 
 * that it processes 32 bit argv and envp pointers.
1462
 
 */
1463
 
int compat_do_execve(char * filename,
1464
 
        compat_uptr_t __user *argv,
1465
 
        compat_uptr_t __user *envp,
1466
 
        struct pt_regs * regs)
1467
 
{
1468
 
        struct linux_binprm *bprm;
1469
 
        struct file *file;
1470
 
        struct files_struct *displaced;
1471
 
        bool clear_in_exec;
1472
 
        int retval;
1473
 
 
1474
 
        retval = unshare_files(&displaced);
1475
 
        if (retval)
1476
 
                goto out_ret;
1477
 
 
1478
 
        retval = -ENOMEM;
1479
 
        bprm = kzalloc(sizeof(*bprm), GFP_KERNEL);
1480
 
        if (!bprm)
1481
 
                goto out_files;
1482
 
 
1483
 
        retval = prepare_bprm_creds(bprm);
1484
 
        if (retval)
1485
 
                goto out_free;
1486
 
 
1487
 
        retval = check_unsafe_exec(bprm);
1488
 
        if (retval < 0)
1489
 
                goto out_free;
1490
 
        clear_in_exec = retval;
1491
 
        current->in_execve = 1;
1492
 
 
1493
 
        file = open_exec(filename);
1494
 
        retval = PTR_ERR(file);
1495
 
        if (IS_ERR(file))
1496
 
                goto out_unmark;
1497
 
 
1498
 
        sched_exec();
1499
 
 
1500
 
        bprm->file = file;
1501
 
        bprm->filename = filename;
1502
 
        bprm->interp = filename;
1503
 
 
1504
 
        retval = bprm_mm_init(bprm);
1505
 
        if (retval)
1506
 
                goto out_file;
1507
 
 
1508
 
        bprm->argc = compat_count(argv, MAX_ARG_STRINGS);
1509
 
        if ((retval = bprm->argc) < 0)
1510
 
                goto out;
1511
 
 
1512
 
        bprm->envc = compat_count(envp, MAX_ARG_STRINGS);
1513
 
        if ((retval = bprm->envc) < 0)
1514
 
                goto out;
1515
 
 
1516
 
        retval = prepare_binprm(bprm);
1517
 
        if (retval < 0)
1518
 
                goto out;
1519
 
 
1520
 
        retval = copy_strings_kernel(1, &bprm->filename, bprm);
1521
 
        if (retval < 0)
1522
 
                goto out;
1523
 
 
1524
 
        bprm->exec = bprm->p;
1525
 
        retval = compat_copy_strings(bprm->envc, envp, bprm);
1526
 
        if (retval < 0)
1527
 
                goto out;
1528
 
 
1529
 
        retval = compat_copy_strings(bprm->argc, argv, bprm);
1530
 
        if (retval < 0)
1531
 
                goto out;
1532
 
 
1533
 
        retval = search_binary_handler(bprm, regs);
1534
 
        if (retval < 0)
1535
 
                goto out;
1536
 
 
1537
 
        trace_fs_exec(filename);
1538
 
        /* execve succeeded */
1539
 
        current->fs->in_exec = 0;
1540
 
        current->in_execve = 0;
1541
 
        acct_update_integrals(current);
1542
 
        free_bprm(bprm);
1543
 
        if (displaced)
1544
 
                put_files_struct(displaced);
1545
 
        return retval;
1546
 
 
1547
 
out:
1548
 
        if (bprm->mm) {
1549
 
                acct_arg_size(bprm, 0);
1550
 
                mmput(bprm->mm);
1551
 
        }
1552
 
 
1553
 
out_file:
1554
 
        if (bprm->file) {
1555
 
                allow_write_access(bprm->file);
1556
 
                fput(bprm->file);
1557
 
        }
1558
 
 
1559
 
out_unmark:
1560
 
        if (clear_in_exec)
1561
 
                current->fs->in_exec = 0;
1562
 
        current->in_execve = 0;
1563
 
 
1564
 
out_free:
1565
 
        free_bprm(bprm);
1566
 
 
1567
 
out_files:
1568
 
        if (displaced)
1569
 
                reset_files_struct(displaced);
1570
 
out_ret:
1571
 
        return retval;
1572
 
}
1573
 
 
1574
1309
#define __COMPAT_NFDBITS       (8 * sizeof(compat_ulong_t))
1575
1310
 
1576
1311
static int poll_select_copy_remaining(struct timespec *end_time, void __user *p,
1701
1436
 * Update: ERESTARTSYS breaks at least the xview clock binary, so
1702
1437
 * I'm trying ERESTARTNOHAND which restart only when you want to.
1703
1438
 */
1704
 
#define MAX_SELECT_SECONDS \
1705
 
        ((unsigned long) (MAX_SCHEDULE_TIMEOUT / HZ)-1)
1706
 
 
1707
1439
int compat_core_sys_select(int n, compat_ulong_t __user *inp,
1708
1440
        compat_ulong_t __user *outp, compat_ulong_t __user *exp,
1709
1441
        struct timespec *end_time)
2314
2046
}
2315
2047
 
2316
2048
#endif /* CONFIG_TIMERFD */
 
2049
 
 
2050
#ifdef CONFIG_FHANDLE
 
2051
/*
 
2052
 * Exactly like fs/open.c:sys_open_by_handle_at(), except that it
 
2053
 * doesn't set the O_LARGEFILE flag.
 
2054
 */
 
2055
asmlinkage long
 
2056
compat_sys_open_by_handle_at(int mountdirfd,
 
2057
                             struct file_handle __user *handle, int flags)
 
2058
{
 
2059
        return do_handle_open(mountdirfd, handle, flags);
 
2060
}
 
2061
#endif