diff options
author | David Herrmann <dh.herrmann@gmail.com> | 2014-08-08 17:25:25 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2014-08-08 18:57:31 -0400 |
commit | 4bb5f5d9395bc112d93a134d8f5b05611eddc9c0 (patch) | |
tree | 68af5a8a8cc65375c51c25bff678d0f9825d86af /include/linux/fs.h | |
parent | 935e9f02e798051d2923d59f6025cd74f59aa0e1 (diff) |
mm: allow drivers to prevent new writable mappings
This patch (of 6):
The i_mmap_writable field counts existing writable mappings of an
address_space. To allow drivers to prevent new writable mappings, make
this counter signed and prevent new writable mappings if it is negative.
This is modelled after i_writecount and DENYWRITE.
This will be required by the shmem-sealing infrastructure to prevent any
new writable mappings after the WRITE seal has been set. In case there
exists a writable mapping, this operation will fail with EBUSY.
Note that we rely on the fact that iff you already own a writable mapping,
you can increase the counter without using the helpers. This is the same
that we do for i_writecount.
Signed-off-by: David Herrmann <dh.herrmann@gmail.com>
Acked-by: Hugh Dickins <hughd@google.com>
Cc: Michael Kerrisk <mtk.manpages@gmail.com>
Cc: Ryan Lortie <desrt@desrt.ca>
Cc: Lennart Poettering <lennart@poettering.net>
Cc: Daniel Mack <zonque@gmail.com>
Cc: Andy Lutomirski <luto@amacapital.net>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'include/linux/fs.h')
-rw-r--r-- | include/linux/fs.h | 29 |
1 files changed, 27 insertions, 2 deletions
diff --git a/include/linux/fs.h b/include/linux/fs.h index 1ab6c6913040..f0890e4a7c25 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h | |||
@@ -387,7 +387,7 @@ struct address_space { | |||
387 | struct inode *host; /* owner: inode, block_device */ | 387 | struct inode *host; /* owner: inode, block_device */ |
388 | struct radix_tree_root page_tree; /* radix tree of all pages */ | 388 | struct radix_tree_root page_tree; /* radix tree of all pages */ |
389 | spinlock_t tree_lock; /* and lock protecting it */ | 389 | spinlock_t tree_lock; /* and lock protecting it */ |
390 | unsigned int i_mmap_writable;/* count VM_SHARED mappings */ | 390 | atomic_t i_mmap_writable;/* count VM_SHARED mappings */ |
391 | struct rb_root i_mmap; /* tree of private and shared mappings */ | 391 | struct rb_root i_mmap; /* tree of private and shared mappings */ |
392 | struct list_head i_mmap_nonlinear;/*list VM_NONLINEAR mappings */ | 392 | struct list_head i_mmap_nonlinear;/*list VM_NONLINEAR mappings */ |
393 | struct mutex i_mmap_mutex; /* protect tree, count, list */ | 393 | struct mutex i_mmap_mutex; /* protect tree, count, list */ |
@@ -470,10 +470,35 @@ static inline int mapping_mapped(struct address_space *mapping) | |||
470 | * Note that i_mmap_writable counts all VM_SHARED vmas: do_mmap_pgoff | 470 | * Note that i_mmap_writable counts all VM_SHARED vmas: do_mmap_pgoff |
471 | * marks vma as VM_SHARED if it is shared, and the file was opened for | 471 | * marks vma as VM_SHARED if it is shared, and the file was opened for |
472 | * writing i.e. vma may be mprotected writable even if now readonly. | 472 | * writing i.e. vma may be mprotected writable even if now readonly. |
473 | * | ||
474 | * If i_mmap_writable is negative, no new writable mappings are allowed. You | ||
475 | * can only deny writable mappings, if none exists right now. | ||
473 | */ | 476 | */ |
474 | static inline int mapping_writably_mapped(struct address_space *mapping) | 477 | static inline int mapping_writably_mapped(struct address_space *mapping) |
475 | { | 478 | { |
476 | return mapping->i_mmap_writable != 0; | 479 | return atomic_read(&mapping->i_mmap_writable) > 0; |
480 | } | ||
481 | |||
482 | static inline int mapping_map_writable(struct address_space *mapping) | ||
483 | { | ||
484 | return atomic_inc_unless_negative(&mapping->i_mmap_writable) ? | ||
485 | 0 : -EPERM; | ||
486 | } | ||
487 | |||
488 | static inline void mapping_unmap_writable(struct address_space *mapping) | ||
489 | { | ||
490 | atomic_dec(&mapping->i_mmap_writable); | ||
491 | } | ||
492 | |||
493 | static inline int mapping_deny_writable(struct address_space *mapping) | ||
494 | { | ||
495 | return atomic_dec_unless_positive(&mapping->i_mmap_writable) ? | ||
496 | 0 : -EBUSY; | ||
497 | } | ||
498 | |||
499 | static inline void mapping_allow_writable(struct address_space *mapping) | ||
500 | { | ||
501 | atomic_inc(&mapping->i_mmap_writable); | ||
477 | } | 502 | } |
478 | 503 | ||
479 | /* | 504 | /* |