diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2016-05-18 14:51:59 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2016-05-18 14:51:59 -0400 |
commit | 9e17632c0a146891c90a4353a160cfcf71f34b8f (patch) | |
tree | 9ab52130a11cdc9cac5f4727b773badf1279555f /fs | |
parent | 69370471d0b2fc3020c60f5473b1eef5977d165a (diff) | |
parent | 2c4cb04300fa160e9d78335c74184c4e66a56437 (diff) |
Merge branch 'work.misc' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs
Pull misc vfs cleanups from Al Viro:
"Assorted cleanups and fixes all over the place"
* 'work.misc' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs:
coredump: only charge written data against RLIMIT_CORE
coredump: get rid of coredump_params->written
ecryptfs_lookup(): try either only encrypted or plaintext name
ecryptfs: avoid multiple aliases for directories
bpf: reject invalid names right in ->lookup()
__d_alloc(): treat NULL name as QSTR("/", 1)
mtd: switch ubi_open_volume_path() to vfs_stat()
mtd: switch open_mtd_by_chdev() to use of vfs_stat()
Diffstat (limited to 'fs')
-rw-r--r-- | fs/binfmt_elf.c | 2 | ||||
-rw-r--r-- | fs/binfmt_elf_fdpic.c | 2 | ||||
-rw-r--r-- | fs/coredump.c | 5 | ||||
-rw-r--r-- | fs/dcache.c | 13 | ||||
-rw-r--r-- | fs/ecryptfs/inode.c | 85 |
5 files changed, 45 insertions, 62 deletions
diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c index 81381cc0dd17..56224ffa94d2 100644 --- a/fs/binfmt_elf.c +++ b/fs/binfmt_elf.c | |||
@@ -2273,7 +2273,7 @@ static int elf_core_dump(struct coredump_params *cprm) | |||
2273 | goto end_coredump; | 2273 | goto end_coredump; |
2274 | 2274 | ||
2275 | /* Align to page */ | 2275 | /* Align to page */ |
2276 | if (!dump_skip(cprm, dataoff - cprm->written)) | 2276 | if (!dump_skip(cprm, dataoff - cprm->file->f_pos)) |
2277 | goto end_coredump; | 2277 | goto end_coredump; |
2278 | 2278 | ||
2279 | for (i = 0, vma = first_vma(current, gate_vma); vma != NULL; | 2279 | for (i = 0, vma = first_vma(current, gate_vma); vma != NULL; |
diff --git a/fs/binfmt_elf_fdpic.c b/fs/binfmt_elf_fdpic.c index 083ea2bc60ab..71ade0e556b7 100644 --- a/fs/binfmt_elf_fdpic.c +++ b/fs/binfmt_elf_fdpic.c | |||
@@ -1787,7 +1787,7 @@ static int elf_fdpic_core_dump(struct coredump_params *cprm) | |||
1787 | goto end_coredump; | 1787 | goto end_coredump; |
1788 | } | 1788 | } |
1789 | 1789 | ||
1790 | if (!dump_skip(cprm, dataoff - cprm->written)) | 1790 | if (!dump_skip(cprm, dataoff - cprm->file->f_pos)) |
1791 | goto end_coredump; | 1791 | goto end_coredump; |
1792 | 1792 | ||
1793 | if (!elf_fdpic_dump_segments(cprm)) | 1793 | if (!elf_fdpic_dump_segments(cprm)) |
diff --git a/fs/coredump.c b/fs/coredump.c index 47c32c3bfa1d..492c2db25dc9 100644 --- a/fs/coredump.c +++ b/fs/coredump.c | |||
@@ -803,12 +803,9 @@ int dump_skip(struct coredump_params *cprm, size_t nr) | |||
803 | static char zeroes[PAGE_SIZE]; | 803 | static char zeroes[PAGE_SIZE]; |
804 | struct file *file = cprm->file; | 804 | struct file *file = cprm->file; |
805 | if (file->f_op->llseek && file->f_op->llseek != no_llseek) { | 805 | if (file->f_op->llseek && file->f_op->llseek != no_llseek) { |
806 | if (cprm->written + nr > cprm->limit) | ||
807 | return 0; | ||
808 | if (dump_interrupted() || | 806 | if (dump_interrupted() || |
809 | file->f_op->llseek(file, nr, SEEK_CUR) < 0) | 807 | file->f_op->llseek(file, nr, SEEK_CUR) < 0) |
810 | return 0; | 808 | return 0; |
811 | cprm->written += nr; | ||
812 | return 1; | 809 | return 1; |
813 | } else { | 810 | } else { |
814 | while (nr > PAGE_SIZE) { | 811 | while (nr > PAGE_SIZE) { |
@@ -823,7 +820,7 @@ EXPORT_SYMBOL(dump_skip); | |||
823 | 820 | ||
824 | int dump_align(struct coredump_params *cprm, int align) | 821 | int dump_align(struct coredump_params *cprm, int align) |
825 | { | 822 | { |
826 | unsigned mod = cprm->written & (align - 1); | 823 | unsigned mod = cprm->file->f_pos & (align - 1); |
827 | if (align & (align - 1)) | 824 | if (align & (align - 1)) |
828 | return 0; | 825 | return 0; |
829 | return mod ? dump_skip(cprm, align - mod) : 1; | 826 | return mod ? dump_skip(cprm, align - mod) : 1; |
diff --git a/fs/dcache.c b/fs/dcache.c index e49ba7d1b957..c622872c12c5 100644 --- a/fs/dcache.c +++ b/fs/dcache.c | |||
@@ -1571,7 +1571,11 @@ struct dentry *__d_alloc(struct super_block *sb, const struct qstr *name) | |||
1571 | * be overwriting an internal NUL character | 1571 | * be overwriting an internal NUL character |
1572 | */ | 1572 | */ |
1573 | dentry->d_iname[DNAME_INLINE_LEN-1] = 0; | 1573 | dentry->d_iname[DNAME_INLINE_LEN-1] = 0; |
1574 | if (name->len > DNAME_INLINE_LEN-1) { | 1574 | if (unlikely(!name)) { |
1575 | static const struct qstr anon = QSTR_INIT("/", 1); | ||
1576 | name = &anon; | ||
1577 | dname = dentry->d_iname; | ||
1578 | } else if (name->len > DNAME_INLINE_LEN-1) { | ||
1575 | size_t size = offsetof(struct external_name, name[1]); | 1579 | size_t size = offsetof(struct external_name, name[1]); |
1576 | struct external_name *p = kmalloc(size + name->len, | 1580 | struct external_name *p = kmalloc(size + name->len, |
1577 | GFP_KERNEL_ACCOUNT); | 1581 | GFP_KERNEL_ACCOUNT); |
@@ -1829,9 +1833,7 @@ struct dentry *d_make_root(struct inode *root_inode) | |||
1829 | struct dentry *res = NULL; | 1833 | struct dentry *res = NULL; |
1830 | 1834 | ||
1831 | if (root_inode) { | 1835 | if (root_inode) { |
1832 | static const struct qstr name = QSTR_INIT("/", 1); | 1836 | res = __d_alloc(root_inode->i_sb, NULL); |
1833 | |||
1834 | res = __d_alloc(root_inode->i_sb, &name); | ||
1835 | if (res) | 1837 | if (res) |
1836 | d_instantiate(res, root_inode); | 1838 | d_instantiate(res, root_inode); |
1837 | else | 1839 | else |
@@ -1872,7 +1874,6 @@ EXPORT_SYMBOL(d_find_any_alias); | |||
1872 | 1874 | ||
1873 | static struct dentry *__d_obtain_alias(struct inode *inode, int disconnected) | 1875 | static struct dentry *__d_obtain_alias(struct inode *inode, int disconnected) |
1874 | { | 1876 | { |
1875 | static const struct qstr anonstring = QSTR_INIT("/", 1); | ||
1876 | struct dentry *tmp; | 1877 | struct dentry *tmp; |
1877 | struct dentry *res; | 1878 | struct dentry *res; |
1878 | unsigned add_flags; | 1879 | unsigned add_flags; |
@@ -1886,7 +1887,7 @@ static struct dentry *__d_obtain_alias(struct inode *inode, int disconnected) | |||
1886 | if (res) | 1887 | if (res) |
1887 | goto out_iput; | 1888 | goto out_iput; |
1888 | 1889 | ||
1889 | tmp = __d_alloc(inode->i_sb, &anonstring); | 1890 | tmp = __d_alloc(inode->i_sb, NULL); |
1890 | if (!tmp) { | 1891 | if (!tmp) { |
1891 | res = ERR_PTR(-ENOMEM); | 1892 | res = ERR_PTR(-ENOMEM); |
1892 | goto out_iput; | 1893 | goto out_iput; |
diff --git a/fs/ecryptfs/inode.c b/fs/ecryptfs/inode.c index 9b022e906660..318b04689d76 100644 --- a/fs/ecryptfs/inode.c +++ b/fs/ecryptfs/inode.c | |||
@@ -324,9 +324,8 @@ static int ecryptfs_i_size_read(struct dentry *dentry, struct inode *inode) | |||
324 | /** | 324 | /** |
325 | * ecryptfs_lookup_interpose - Dentry interposition for a lookup | 325 | * ecryptfs_lookup_interpose - Dentry interposition for a lookup |
326 | */ | 326 | */ |
327 | static int ecryptfs_lookup_interpose(struct dentry *dentry, | 327 | static struct dentry *ecryptfs_lookup_interpose(struct dentry *dentry, |
328 | struct dentry *lower_dentry, | 328 | struct dentry *lower_dentry) |
329 | struct inode *dir_inode) | ||
330 | { | 329 | { |
331 | struct inode *inode, *lower_inode = d_inode(lower_dentry); | 330 | struct inode *inode, *lower_inode = d_inode(lower_dentry); |
332 | struct ecryptfs_dentry_info *dentry_info; | 331 | struct ecryptfs_dentry_info *dentry_info; |
@@ -339,11 +338,12 @@ static int ecryptfs_lookup_interpose(struct dentry *dentry, | |||
339 | "to allocate ecryptfs_dentry_info struct\n", | 338 | "to allocate ecryptfs_dentry_info struct\n", |
340 | __func__); | 339 | __func__); |
341 | dput(lower_dentry); | 340 | dput(lower_dentry); |
342 | return -ENOMEM; | 341 | return ERR_PTR(-ENOMEM); |
343 | } | 342 | } |
344 | 343 | ||
345 | lower_mnt = mntget(ecryptfs_dentry_to_lower_mnt(dentry->d_parent)); | 344 | lower_mnt = mntget(ecryptfs_dentry_to_lower_mnt(dentry->d_parent)); |
346 | fsstack_copy_attr_atime(dir_inode, d_inode(lower_dentry->d_parent)); | 345 | fsstack_copy_attr_atime(d_inode(dentry->d_parent), |
346 | d_inode(lower_dentry->d_parent)); | ||
347 | BUG_ON(!d_count(lower_dentry)); | 347 | BUG_ON(!d_count(lower_dentry)); |
348 | 348 | ||
349 | ecryptfs_set_dentry_private(dentry, dentry_info); | 349 | ecryptfs_set_dentry_private(dentry, dentry_info); |
@@ -353,27 +353,25 @@ static int ecryptfs_lookup_interpose(struct dentry *dentry, | |||
353 | if (d_really_is_negative(lower_dentry)) { | 353 | if (d_really_is_negative(lower_dentry)) { |
354 | /* We want to add because we couldn't find in lower */ | 354 | /* We want to add because we couldn't find in lower */ |
355 | d_add(dentry, NULL); | 355 | d_add(dentry, NULL); |
356 | return 0; | 356 | return NULL; |
357 | } | 357 | } |
358 | inode = __ecryptfs_get_inode(lower_inode, dir_inode->i_sb); | 358 | inode = __ecryptfs_get_inode(lower_inode, dentry->d_sb); |
359 | if (IS_ERR(inode)) { | 359 | if (IS_ERR(inode)) { |
360 | printk(KERN_ERR "%s: Error interposing; rc = [%ld]\n", | 360 | printk(KERN_ERR "%s: Error interposing; rc = [%ld]\n", |
361 | __func__, PTR_ERR(inode)); | 361 | __func__, PTR_ERR(inode)); |
362 | return PTR_ERR(inode); | 362 | return ERR_CAST(inode); |
363 | } | 363 | } |
364 | if (S_ISREG(inode->i_mode)) { | 364 | if (S_ISREG(inode->i_mode)) { |
365 | rc = ecryptfs_i_size_read(dentry, inode); | 365 | rc = ecryptfs_i_size_read(dentry, inode); |
366 | if (rc) { | 366 | if (rc) { |
367 | make_bad_inode(inode); | 367 | make_bad_inode(inode); |
368 | return rc; | 368 | return ERR_PTR(rc); |
369 | } | 369 | } |
370 | } | 370 | } |
371 | 371 | ||
372 | if (inode->i_state & I_NEW) | 372 | if (inode->i_state & I_NEW) |
373 | unlock_new_inode(inode); | 373 | unlock_new_inode(inode); |
374 | d_add(dentry, inode); | 374 | return d_splice_alias(inode, dentry); |
375 | |||
376 | return rc; | ||
377 | } | 375 | } |
378 | 376 | ||
379 | /** | 377 | /** |
@@ -390,55 +388,42 @@ static struct dentry *ecryptfs_lookup(struct inode *ecryptfs_dir_inode, | |||
390 | unsigned int flags) | 388 | unsigned int flags) |
391 | { | 389 | { |
392 | char *encrypted_and_encoded_name = NULL; | 390 | char *encrypted_and_encoded_name = NULL; |
393 | size_t encrypted_and_encoded_name_size; | 391 | struct ecryptfs_mount_crypt_stat *mount_crypt_stat; |
394 | struct ecryptfs_mount_crypt_stat *mount_crypt_stat = NULL; | ||
395 | struct dentry *lower_dir_dentry, *lower_dentry; | 392 | struct dentry *lower_dir_dentry, *lower_dentry; |
393 | const char *name = ecryptfs_dentry->d_name.name; | ||
394 | size_t len = ecryptfs_dentry->d_name.len; | ||
395 | struct dentry *res; | ||
396 | int rc = 0; | 396 | int rc = 0; |
397 | 397 | ||
398 | lower_dir_dentry = ecryptfs_dentry_to_lower(ecryptfs_dentry->d_parent); | 398 | lower_dir_dentry = ecryptfs_dentry_to_lower(ecryptfs_dentry->d_parent); |
399 | lower_dentry = lookup_one_len_unlocked(ecryptfs_dentry->d_name.name, | 399 | |
400 | lower_dir_dentry, | ||
401 | ecryptfs_dentry->d_name.len); | ||
402 | if (IS_ERR(lower_dentry)) { | ||
403 | rc = PTR_ERR(lower_dentry); | ||
404 | ecryptfs_printk(KERN_DEBUG, "%s: lookup_one_len() returned " | ||
405 | "[%d] on lower_dentry = [%pd]\n", __func__, rc, | ||
406 | ecryptfs_dentry); | ||
407 | goto out; | ||
408 | } | ||
409 | if (d_really_is_positive(lower_dentry)) | ||
410 | goto interpose; | ||
411 | mount_crypt_stat = &ecryptfs_superblock_to_private( | 400 | mount_crypt_stat = &ecryptfs_superblock_to_private( |
412 | ecryptfs_dentry->d_sb)->mount_crypt_stat; | 401 | ecryptfs_dentry->d_sb)->mount_crypt_stat; |
413 | if (!(mount_crypt_stat | 402 | if (mount_crypt_stat |
414 | && (mount_crypt_stat->flags & ECRYPTFS_GLOBAL_ENCRYPT_FILENAMES))) | 403 | && (mount_crypt_stat->flags & ECRYPTFS_GLOBAL_ENCRYPT_FILENAMES)) { |
415 | goto interpose; | 404 | rc = ecryptfs_encrypt_and_encode_filename( |
416 | dput(lower_dentry); | 405 | &encrypted_and_encoded_name, &len, |
417 | rc = ecryptfs_encrypt_and_encode_filename( | 406 | mount_crypt_stat, name, len); |
418 | &encrypted_and_encoded_name, &encrypted_and_encoded_name_size, | 407 | if (rc) { |
419 | mount_crypt_stat, ecryptfs_dentry->d_name.name, | 408 | printk(KERN_ERR "%s: Error attempting to encrypt and encode " |
420 | ecryptfs_dentry->d_name.len); | 409 | "filename; rc = [%d]\n", __func__, rc); |
421 | if (rc) { | 410 | return ERR_PTR(rc); |
422 | printk(KERN_ERR "%s: Error attempting to encrypt and encode " | 411 | } |
423 | "filename; rc = [%d]\n", __func__, rc); | 412 | name = encrypted_and_encoded_name; |
424 | goto out; | ||
425 | } | 413 | } |
426 | lower_dentry = lookup_one_len_unlocked(encrypted_and_encoded_name, | 414 | |
427 | lower_dir_dentry, | 415 | lower_dentry = lookup_one_len_unlocked(name, lower_dir_dentry, len); |
428 | encrypted_and_encoded_name_size); | ||
429 | if (IS_ERR(lower_dentry)) { | 416 | if (IS_ERR(lower_dentry)) { |
430 | rc = PTR_ERR(lower_dentry); | ||
431 | ecryptfs_printk(KERN_DEBUG, "%s: lookup_one_len() returned " | 417 | ecryptfs_printk(KERN_DEBUG, "%s: lookup_one_len() returned " |
432 | "[%d] on lower_dentry = [%s]\n", __func__, rc, | 418 | "[%ld] on lower_dentry = [%s]\n", __func__, |
433 | encrypted_and_encoded_name); | 419 | PTR_ERR(lower_dentry), |
434 | goto out; | 420 | name); |
421 | res = ERR_CAST(lower_dentry); | ||
422 | } else { | ||
423 | res = ecryptfs_lookup_interpose(ecryptfs_dentry, lower_dentry); | ||
435 | } | 424 | } |
436 | interpose: | ||
437 | rc = ecryptfs_lookup_interpose(ecryptfs_dentry, lower_dentry, | ||
438 | ecryptfs_dir_inode); | ||
439 | out: | ||
440 | kfree(encrypted_and_encoded_name); | 425 | kfree(encrypted_and_encoded_name); |
441 | return ERR_PTR(rc); | 426 | return res; |
442 | } | 427 | } |
443 | 428 | ||
444 | static int ecryptfs_link(struct dentry *old_dentry, struct inode *dir, | 429 | static int ecryptfs_link(struct dentry *old_dentry, struct inode *dir, |