Skip to content

Commit 236f453

Browse files
committed
Merge branch 'work.misc' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs
Pull misc vfs updates from Al Viro: - bmap series from cmaiolino - getting rid of convolutions in copy_mount_options() (use a couple of copy_from_user() instead of the __get_user() crap) * 'work.misc' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs: saner copy_mount_options() fibmap: Reject negative block numbers fibmap: Use bmap instead of ->bmap method in ioctl_fibmap ecryptfs: drop direct calls to ->bmap cachefiles: drop direct usage of ->bmap method. fs: Enable bmap() function to properly return errors
2 parents 9959333 + 12efec5 commit 236f453

File tree

10 files changed

+119
-111
lines changed

10 files changed

+119
-111
lines changed

drivers/md/md-bitmap.c

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -364,7 +364,7 @@ static int read_page(struct file *file, unsigned long index,
364364
int ret = 0;
365365
struct inode *inode = file_inode(file);
366366
struct buffer_head *bh;
367-
sector_t block;
367+
sector_t block, blk_cur;
368368

369369
pr_debug("read bitmap file (%dB @ %llu)\n", (int)PAGE_SIZE,
370370
(unsigned long long)index << PAGE_SHIFT);
@@ -375,17 +375,21 @@ static int read_page(struct file *file, unsigned long index,
375375
goto out;
376376
}
377377
attach_page_buffers(page, bh);
378-
block = index << (PAGE_SHIFT - inode->i_blkbits);
378+
blk_cur = index << (PAGE_SHIFT - inode->i_blkbits);
379379
while (bh) {
380+
block = blk_cur;
381+
380382
if (count == 0)
381383
bh->b_blocknr = 0;
382384
else {
383-
bh->b_blocknr = bmap(inode, block);
384-
if (bh->b_blocknr == 0) {
385-
/* Cannot use this file! */
385+
ret = bmap(inode, &block);
386+
if (ret || !block) {
386387
ret = -EINVAL;
388+
bh->b_blocknr = 0;
387389
goto out;
388390
}
391+
392+
bh->b_blocknr = block;
389393
bh->b_bdev = inode->i_sb->s_bdev;
390394
if (count < (1<<inode->i_blkbits))
391395
count = 0;
@@ -399,7 +403,7 @@ static int read_page(struct file *file, unsigned long index,
399403
set_buffer_mapped(bh);
400404
submit_bh(REQ_OP_READ, 0, bh);
401405
}
402-
block++;
406+
blk_cur++;
403407
bh = bh->b_this_page;
404408
}
405409
page->index = index;

fs/cachefiles/rdwr.c

Lines changed: 14 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -396,7 +396,7 @@ int cachefiles_read_or_alloc_page(struct fscache_retrieval *op,
396396
struct cachefiles_object *object;
397397
struct cachefiles_cache *cache;
398398
struct inode *inode;
399-
sector_t block0, block;
399+
sector_t block;
400400
unsigned shift;
401401
int ret;
402402

@@ -412,7 +412,6 @@ int cachefiles_read_or_alloc_page(struct fscache_retrieval *op,
412412

413413
inode = d_backing_inode(object->backer);
414414
ASSERT(S_ISREG(inode->i_mode));
415-
ASSERT(inode->i_mapping->a_ops->bmap);
416415
ASSERT(inode->i_mapping->a_ops->readpages);
417416

418417
/* calculate the shift required to use bmap */
@@ -428,12 +427,14 @@ int cachefiles_read_or_alloc_page(struct fscache_retrieval *op,
428427
* enough for this as it doesn't indicate errors, but it's all we've
429428
* got for the moment
430429
*/
431-
block0 = page->index;
432-
block0 <<= shift;
430+
block = page->index;
431+
block <<= shift;
432+
433+
ret = bmap(inode, &block);
434+
ASSERT(ret < 0);
433435

434-
block = inode->i_mapping->a_ops->bmap(inode->i_mapping, block0);
435436
_debug("%llx -> %llx",
436-
(unsigned long long) block0,
437+
(unsigned long long) (page->index << shift),
437438
(unsigned long long) block);
438439

439440
if (block) {
@@ -711,7 +712,6 @@ int cachefiles_read_or_alloc_pages(struct fscache_retrieval *op,
711712

712713
inode = d_backing_inode(object->backer);
713714
ASSERT(S_ISREG(inode->i_mode));
714-
ASSERT(inode->i_mapping->a_ops->bmap);
715715
ASSERT(inode->i_mapping->a_ops->readpages);
716716

717717
/* calculate the shift required to use bmap */
@@ -728,21 +728,22 @@ int cachefiles_read_or_alloc_pages(struct fscache_retrieval *op,
728728

729729
ret = space ? -ENODATA : -ENOBUFS;
730730
list_for_each_entry_safe(page, _n, pages, lru) {
731-
sector_t block0, block;
731+
sector_t block;
732732

733733
/* we assume the absence or presence of the first block is a
734734
* good enough indication for the page as a whole
735735
* - TODO: don't use bmap() for this as it is _not_ actually
736736
* good enough for this as it doesn't indicate errors, but
737737
* it's all we've got for the moment
738738
*/
739-
block0 = page->index;
740-
block0 <<= shift;
739+
block = page->index;
740+
block <<= shift;
741+
742+
ret = bmap(inode, &block);
743+
ASSERT(!ret);
741744

742-
block = inode->i_mapping->a_ops->bmap(inode->i_mapping,
743-
block0);
744745
_debug("%llx -> %llx",
745-
(unsigned long long) block0,
746+
(unsigned long long) (page->index << shift),
746747
(unsigned long long) block);
747748

748749
if (block) {

fs/ecryptfs/mmap.c

Lines changed: 6 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -524,16 +524,12 @@ static int ecryptfs_write_end(struct file *file,
524524

525525
static sector_t ecryptfs_bmap(struct address_space *mapping, sector_t block)
526526
{
527-
int rc = 0;
528-
struct inode *inode;
529-
struct inode *lower_inode;
530-
531-
inode = (struct inode *)mapping->host;
532-
lower_inode = ecryptfs_inode_to_lower(inode);
533-
if (lower_inode->i_mapping->a_ops->bmap)
534-
rc = lower_inode->i_mapping->a_ops->bmap(lower_inode->i_mapping,
535-
block);
536-
return rc;
527+
struct inode *lower_inode = ecryptfs_inode_to_lower(mapping->host);
528+
int ret = bmap(lower_inode, &block);
529+
530+
if (ret)
531+
return 0;
532+
return block;
537533
}
538534

539535
const struct address_space_operations ecryptfs_aops = {

fs/f2fs/data.c

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3666,12 +3666,16 @@ static int check_swap_activate(struct swap_info_struct *sis,
36663666
page_no < sis->max) {
36673667
unsigned block_in_page;
36683668
sector_t first_block;
3669+
sector_t block = 0;
3670+
int err = 0;
36693671

36703672
cond_resched();
36713673

3672-
first_block = bmap(inode, probe_block);
3673-
if (first_block == 0)
3674+
block = probe_block;
3675+
err = bmap(inode, &block);
3676+
if (err || !block)
36743677
goto bad_bmap;
3678+
first_block = block;
36753679

36763680
/*
36773681
* It must be PAGE_SIZE aligned on-disk
@@ -3683,11 +3687,13 @@ static int check_swap_activate(struct swap_info_struct *sis,
36833687

36843688
for (block_in_page = 1; block_in_page < blocks_per_page;
36853689
block_in_page++) {
3686-
sector_t block;
36873690

3688-
block = bmap(inode, probe_block + block_in_page);
3689-
if (block == 0)
3691+
block = probe_block + block_in_page;
3692+
err = bmap(inode, &block);
3693+
3694+
if (err || !block)
36903695
goto bad_bmap;
3696+
36913697
if (block != first_block + block_in_page) {
36923698
/* Discontiguity */
36933699
probe_block++;

fs/inode.c

Lines changed: 19 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1599,25 +1599,31 @@ void iput(struct inode *inode)
15991599
}
16001600
EXPORT_SYMBOL(iput);
16011601

1602+
#ifdef CONFIG_BLOCK
16021603
/**
16031604
* bmap - find a block number in a file
1604-
* @inode: inode of file
1605-
* @block: block to find
1606-
*
1607-
* Returns the block number on the device holding the inode that
1608-
* is the disk block number for the block of the file requested.
1609-
* That is, asked for block 4 of inode 1 the function will return the
1610-
* disk block relative to the disk start that holds that block of the
1611-
* file.
1605+
* @inode: inode owning the block number being requested
1606+
* @block: pointer containing the block to find
1607+
*
1608+
* Replaces the value in *block with the block number on the device holding
1609+
* corresponding to the requested block number in the file.
1610+
* That is, asked for block 4 of inode 1 the function will replace the
1611+
* 4 in *block, with disk block relative to the disk start that holds that
1612+
* block of the file.
1613+
*
1614+
* Returns -EINVAL in case of error, 0 otherwise. If mapping falls into a
1615+
* hole, returns 0 and *block is also set to 0.
16121616
*/
1613-
sector_t bmap(struct inode *inode, sector_t block)
1617+
int bmap(struct inode *inode, sector_t *block)
16141618
{
1615-
sector_t res = 0;
1616-
if (inode->i_mapping->a_ops->bmap)
1617-
res = inode->i_mapping->a_ops->bmap(inode->i_mapping, block);
1618-
return res;
1619+
if (!inode->i_mapping->a_ops->bmap)
1620+
return -EINVAL;
1621+
1622+
*block = inode->i_mapping->a_ops->bmap(inode->i_mapping, *block);
1623+
return 0;
16191624
}
16201625
EXPORT_SYMBOL(bmap);
1626+
#endif
16211627

16221628
/*
16231629
* With relative atime, only update atime if the previous atime is

fs/ioctl.c

Lines changed: 23 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -54,19 +54,32 @@ EXPORT_SYMBOL(vfs_ioctl);
5454

5555
static int ioctl_fibmap(struct file *filp, int __user *p)
5656
{
57-
struct address_space *mapping = filp->f_mapping;
58-
int res, block;
57+
struct inode *inode = file_inode(filp);
58+
int error, ur_block;
59+
sector_t block;
5960

60-
/* do we support this mess? */
61-
if (!mapping->a_ops->bmap)
62-
return -EINVAL;
6361
if (!capable(CAP_SYS_RAWIO))
6462
return -EPERM;
65-
res = get_user(block, p);
66-
if (res)
67-
return res;
68-
res = mapping->a_ops->bmap(mapping, block);
69-
return put_user(res, p);
63+
64+
error = get_user(ur_block, p);
65+
if (error)
66+
return error;
67+
68+
if (ur_block < 0)
69+
return -EINVAL;
70+
71+
block = ur_block;
72+
error = bmap(inode, &block);
73+
74+
if (error)
75+
ur_block = 0;
76+
else
77+
ur_block = block;
78+
79+
if (put_user(ur_block, p))
80+
error = -EFAULT;
81+
82+
return error;
7083
}
7184

7285
/**

fs/jbd2/journal.c

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -794,18 +794,22 @@ int jbd2_journal_bmap(journal_t *journal, unsigned long blocknr,
794794
{
795795
int err = 0;
796796
unsigned long long ret;
797+
sector_t block = 0;
797798

798799
if (journal->j_inode) {
799-
ret = bmap(journal->j_inode, blocknr);
800-
if (ret)
801-
*retp = ret;
802-
else {
800+
block = blocknr;
801+
ret = bmap(journal->j_inode, &block);
802+
803+
if (ret || !block) {
803804
printk(KERN_ALERT "%s: journal block not found "
804805
"at offset %lu on %s\n",
805806
__func__, blocknr, journal->j_devname);
806807
err = -EIO;
807808
jbd2_journal_abort(journal, err);
809+
} else {
810+
*retp = block;
808811
}
812+
809813
} else {
810814
*retp = blocknr; /* +journal->j_blk_offset */
811815
}
@@ -1243,11 +1247,14 @@ journal_t *jbd2_journal_init_dev(struct block_device *bdev,
12431247
journal_t *jbd2_journal_init_inode(struct inode *inode)
12441248
{
12451249
journal_t *journal;
1250+
sector_t blocknr;
12461251
char *p;
1247-
unsigned long long blocknr;
1252+
int err = 0;
1253+
1254+
blocknr = 0;
1255+
err = bmap(inode, &blocknr);
12481256

1249-
blocknr = bmap(inode, 0);
1250-
if (!blocknr) {
1257+
if (err || !blocknr) {
12511258
pr_err("%s: Cannot locate journal superblock\n",
12521259
__func__);
12531260
return NULL;

fs/namespace.c

Lines changed: 7 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -2979,39 +2979,10 @@ static void shrink_submounts(struct mount *mnt)
29792979
}
29802980
}
29812981

2982-
/*
2983-
* Some copy_from_user() implementations do not return the exact number of
2984-
* bytes remaining to copy on a fault. But copy_mount_options() requires that.
2985-
* Note that this function differs from copy_from_user() in that it will oops
2986-
* on bad values of `to', rather than returning a short copy.
2987-
*/
2988-
static long exact_copy_from_user(void *to, const void __user * from,
2989-
unsigned long n)
2990-
{
2991-
char *t = to;
2992-
const char __user *f = from;
2993-
char c;
2994-
2995-
if (!access_ok(from, n))
2996-
return n;
2997-
2998-
while (n) {
2999-
if (__get_user(c, f)) {
3000-
memset(t, 0, n);
3001-
break;
3002-
}
3003-
*t++ = c;
3004-
f++;
3005-
n--;
3006-
}
3007-
return n;
3008-
}
3009-
30102982
void *copy_mount_options(const void __user * data)
30112983
{
3012-
int i;
3013-
unsigned long size;
30142984
char *copy;
2985+
unsigned size;
30152986

30162987
if (!data)
30172988
return NULL;
@@ -3020,22 +2991,16 @@ void *copy_mount_options(const void __user * data)
30202991
if (!copy)
30212992
return ERR_PTR(-ENOMEM);
30222993

3023-
/* We only care that *some* data at the address the user
3024-
* gave us is valid. Just in case, we'll zero
3025-
* the remainder of the page.
3026-
*/
3027-
/* copy_from_user cannot cross TASK_SIZE ! */
3028-
size = TASK_SIZE - (unsigned long)untagged_addr(data);
3029-
if (size > PAGE_SIZE)
3030-
size = PAGE_SIZE;
2994+
size = PAGE_SIZE - offset_in_page(data);
30312995

3032-
i = size - exact_copy_from_user(copy, data, size);
3033-
if (!i) {
2996+
if (copy_from_user(copy, data, size)) {
30342997
kfree(copy);
30352998
return ERR_PTR(-EFAULT);
30362999
}
3037-
if (i != PAGE_SIZE)
3038-
memset(copy + i, 0, PAGE_SIZE - i);
3000+
if (size != PAGE_SIZE) {
3001+
if (copy_from_user(copy + size, data + size, PAGE_SIZE - size))
3002+
memset(copy + size, 0, PAGE_SIZE - size);
3003+
}
30393004
return copy;
30403005
}
30413006

include/linux/fs.h

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2876,9 +2876,16 @@ static inline ssize_t generic_write_sync(struct kiocb *iocb, ssize_t count)
28762876

28772877
extern void emergency_sync(void);
28782878
extern void emergency_remount(void);
2879+
28792880
#ifdef CONFIG_BLOCK
2880-
extern sector_t bmap(struct inode *, sector_t);
2881+
extern int bmap(struct inode *inode, sector_t *block);
2882+
#else
2883+
static inline int bmap(struct inode *inode, sector_t *block)
2884+
{
2885+
return -EINVAL;
2886+
}
28812887
#endif
2888+
28822889
extern int notify_change(struct dentry *, struct iattr *, struct inode **);
28832890
extern int inode_permission(struct inode *, int);
28842891
extern int generic_permission(struct inode *, int);

0 commit comments

Comments
 (0)