diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2018-04-20 12:01:26 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2018-04-20 12:01:26 -0400 |
commit | 0d9cf33b4aabd8de03f80659ceae967ba2b3ba30 (patch) | |
tree | 2e3ed6e9d9e1a43742714f472480eddc313ee906 | |
parent | 4d1890531413a19d63cb980fee6d9d3ff86d97ad (diff) | |
parent | 44f06ba8297c7e9dfd0e49b40cbe119113cca094 (diff) |
Merge tag 'for_v4.17-rc2' of git://git.kernel.org/pub/scm/linux/kernel/git/jack/linux-fs
- isofs memory leak fix
- two fsnotify fixes of event mask handling
- udf fix of UTF-16 handling
- couple other smaller cleanups
* tag 'for_v4.17-rc2' of git://git.kernel.org/pub/scm/linux/kernel/git/jack/linux-fs:
udf: Fix leak of UTF-16 surrogates into encoded strings
fs: ext2: Adding new return type vm_fault_t
isofs: fix potential memory leak in mount option parsing
MAINTAINERS: add an entry for FSNOTIFY infrastructure
fsnotify: fix typo in a comment about mark->g_list
fsnotify: fix ignore mask logic in send_to_group()
isofs compress: Remove VLA usage
fs: quota: Replace GFP_ATOMIC with GFP_KERNEL in dquot_init
fanotify: fix logic of events on child
-rw-r--r-- | MAINTAINERS | 8 | ||||
-rw-r--r-- | fs/ext2/file.c | 4 | ||||
-rw-r--r-- | fs/isofs/compress.c | 19 | ||||
-rw-r--r-- | fs/isofs/inode.c | 3 | ||||
-rw-r--r-- | fs/notify/fanotify/fanotify.c | 34 | ||||
-rw-r--r-- | fs/notify/fsnotify.c | 25 | ||||
-rw-r--r-- | fs/quota/dquot.c | 2 | ||||
-rw-r--r-- | fs/udf/unicode.c | 6 | ||||
-rw-r--r-- | include/linux/fsnotify_backend.h | 2 |
9 files changed, 63 insertions, 40 deletions
diff --git a/MAINTAINERS b/MAINTAINERS index 0a1410d5a621..39412b02defe 100644 --- a/MAINTAINERS +++ b/MAINTAINERS | |||
@@ -5784,6 +5784,14 @@ F: fs/crypto/ | |||
5784 | F: include/linux/fscrypt*.h | 5784 | F: include/linux/fscrypt*.h |
5785 | F: Documentation/filesystems/fscrypt.rst | 5785 | F: Documentation/filesystems/fscrypt.rst |
5786 | 5786 | ||
5787 | FSNOTIFY: FILESYSTEM NOTIFICATION INFRASTRUCTURE | ||
5788 | M: Jan Kara <jack@suse.cz> | ||
5789 | R: Amir Goldstein <amir73il@gmail.com> | ||
5790 | L: linux-fsdevel@vger.kernel.org | ||
5791 | S: Maintained | ||
5792 | F: fs/notify/ | ||
5793 | F: include/linux/fsnotify*.h | ||
5794 | |||
5787 | FUJITSU LAPTOP EXTRAS | 5795 | FUJITSU LAPTOP EXTRAS |
5788 | M: Jonathan Woithe <jwoithe@just42.net> | 5796 | M: Jonathan Woithe <jwoithe@just42.net> |
5789 | L: platform-driver-x86@vger.kernel.org | 5797 | L: platform-driver-x86@vger.kernel.org |
diff --git a/fs/ext2/file.c b/fs/ext2/file.c index 09640220fda8..047c327a6b23 100644 --- a/fs/ext2/file.c +++ b/fs/ext2/file.c | |||
@@ -88,11 +88,11 @@ out_unlock: | |||
88 | * The default page_lock and i_size verification done by non-DAX fault paths | 88 | * The default page_lock and i_size verification done by non-DAX fault paths |
89 | * is sufficient because ext2 doesn't support hole punching. | 89 | * is sufficient because ext2 doesn't support hole punching. |
90 | */ | 90 | */ |
91 | static int ext2_dax_fault(struct vm_fault *vmf) | 91 | static vm_fault_t ext2_dax_fault(struct vm_fault *vmf) |
92 | { | 92 | { |
93 | struct inode *inode = file_inode(vmf->vma->vm_file); | 93 | struct inode *inode = file_inode(vmf->vma->vm_file); |
94 | struct ext2_inode_info *ei = EXT2_I(inode); | 94 | struct ext2_inode_info *ei = EXT2_I(inode); |
95 | int ret; | 95 | vm_fault_t ret; |
96 | 96 | ||
97 | if (vmf->flags & FAULT_FLAG_WRITE) { | 97 | if (vmf->flags & FAULT_FLAG_WRITE) { |
98 | sb_start_pagefault(inode->i_sb); | 98 | sb_start_pagefault(inode->i_sb); |
diff --git a/fs/isofs/compress.c b/fs/isofs/compress.c index 9bb2fe35799d..10205ececc27 100644 --- a/fs/isofs/compress.c +++ b/fs/isofs/compress.c | |||
@@ -20,6 +20,7 @@ | |||
20 | #include <linux/init.h> | 20 | #include <linux/init.h> |
21 | #include <linux/bio.h> | 21 | #include <linux/bio.h> |
22 | 22 | ||
23 | #include <linux/slab.h> | ||
23 | #include <linux/vmalloc.h> | 24 | #include <linux/vmalloc.h> |
24 | #include <linux/zlib.h> | 25 | #include <linux/zlib.h> |
25 | 26 | ||
@@ -59,7 +60,7 @@ static loff_t zisofs_uncompress_block(struct inode *inode, loff_t block_start, | |||
59 | >> bufshift; | 60 | >> bufshift; |
60 | int haveblocks; | 61 | int haveblocks; |
61 | blkcnt_t blocknum; | 62 | blkcnt_t blocknum; |
62 | struct buffer_head *bhs[needblocks + 1]; | 63 | struct buffer_head **bhs; |
63 | int curbh, curpage; | 64 | int curbh, curpage; |
64 | 65 | ||
65 | if (block_size > deflateBound(1UL << zisofs_block_shift)) { | 66 | if (block_size > deflateBound(1UL << zisofs_block_shift)) { |
@@ -80,7 +81,11 @@ static loff_t zisofs_uncompress_block(struct inode *inode, loff_t block_start, | |||
80 | 81 | ||
81 | /* Because zlib is not thread-safe, do all the I/O at the top. */ | 82 | /* Because zlib is not thread-safe, do all the I/O at the top. */ |
82 | blocknum = block_start >> bufshift; | 83 | blocknum = block_start >> bufshift; |
83 | memset(bhs, 0, (needblocks + 1) * sizeof(struct buffer_head *)); | 84 | bhs = kcalloc(needblocks + 1, sizeof(*bhs), GFP_KERNEL); |
85 | if (!bhs) { | ||
86 | *errp = -ENOMEM; | ||
87 | return 0; | ||
88 | } | ||
84 | haveblocks = isofs_get_blocks(inode, blocknum, bhs, needblocks); | 89 | haveblocks = isofs_get_blocks(inode, blocknum, bhs, needblocks); |
85 | ll_rw_block(REQ_OP_READ, 0, haveblocks, bhs); | 90 | ll_rw_block(REQ_OP_READ, 0, haveblocks, bhs); |
86 | 91 | ||
@@ -190,6 +195,7 @@ z_eio: | |||
190 | b_eio: | 195 | b_eio: |
191 | for (i = 0; i < haveblocks; i++) | 196 | for (i = 0; i < haveblocks; i++) |
192 | brelse(bhs[i]); | 197 | brelse(bhs[i]); |
198 | kfree(bhs); | ||
193 | return stream.total_out; | 199 | return stream.total_out; |
194 | } | 200 | } |
195 | 201 | ||
@@ -305,7 +311,7 @@ static int zisofs_readpage(struct file *file, struct page *page) | |||
305 | unsigned int zisofs_pages_per_cblock = | 311 | unsigned int zisofs_pages_per_cblock = |
306 | PAGE_SHIFT <= zisofs_block_shift ? | 312 | PAGE_SHIFT <= zisofs_block_shift ? |
307 | (1 << (zisofs_block_shift - PAGE_SHIFT)) : 0; | 313 | (1 << (zisofs_block_shift - PAGE_SHIFT)) : 0; |
308 | struct page *pages[max_t(unsigned, zisofs_pages_per_cblock, 1)]; | 314 | struct page **pages; |
309 | pgoff_t index = page->index, end_index; | 315 | pgoff_t index = page->index, end_index; |
310 | 316 | ||
311 | end_index = (inode->i_size + PAGE_SIZE - 1) >> PAGE_SHIFT; | 317 | end_index = (inode->i_size + PAGE_SIZE - 1) >> PAGE_SHIFT; |
@@ -330,6 +336,12 @@ static int zisofs_readpage(struct file *file, struct page *page) | |||
330 | full_page = 0; | 336 | full_page = 0; |
331 | pcount = 1; | 337 | pcount = 1; |
332 | } | 338 | } |
339 | pages = kcalloc(max_t(unsigned int, zisofs_pages_per_cblock, 1), | ||
340 | sizeof(*pages), GFP_KERNEL); | ||
341 | if (!pages) { | ||
342 | unlock_page(page); | ||
343 | return -ENOMEM; | ||
344 | } | ||
333 | pages[full_page] = page; | 345 | pages[full_page] = page; |
334 | 346 | ||
335 | for (i = 0; i < pcount; i++, index++) { | 347 | for (i = 0; i < pcount; i++, index++) { |
@@ -357,6 +369,7 @@ static int zisofs_readpage(struct file *file, struct page *page) | |||
357 | } | 369 | } |
358 | 370 | ||
359 | /* At this point, err contains 0 or -EIO depending on the "critical" page */ | 371 | /* At this point, err contains 0 or -EIO depending on the "critical" page */ |
372 | kfree(pages); | ||
360 | return err; | 373 | return err; |
361 | } | 374 | } |
362 | 375 | ||
diff --git a/fs/isofs/inode.c b/fs/isofs/inode.c index bc258a4402f6..ec3fba7d492f 100644 --- a/fs/isofs/inode.c +++ b/fs/isofs/inode.c | |||
@@ -394,7 +394,10 @@ static int parse_options(char *options, struct iso9660_options *popt) | |||
394 | break; | 394 | break; |
395 | #ifdef CONFIG_JOLIET | 395 | #ifdef CONFIG_JOLIET |
396 | case Opt_iocharset: | 396 | case Opt_iocharset: |
397 | kfree(popt->iocharset); | ||
397 | popt->iocharset = match_strdup(&args[0]); | 398 | popt->iocharset = match_strdup(&args[0]); |
399 | if (!popt->iocharset) | ||
400 | return 0; | ||
398 | break; | 401 | break; |
399 | #endif | 402 | #endif |
400 | case Opt_map_a: | 403 | case Opt_map_a: |
diff --git a/fs/notify/fanotify/fanotify.c b/fs/notify/fanotify/fanotify.c index d51e1bb781cf..d94e8031fe5f 100644 --- a/fs/notify/fanotify/fanotify.c +++ b/fs/notify/fanotify/fanotify.c | |||
@@ -92,7 +92,7 @@ static bool fanotify_should_send_event(struct fsnotify_mark *inode_mark, | |||
92 | u32 event_mask, | 92 | u32 event_mask, |
93 | const void *data, int data_type) | 93 | const void *data, int data_type) |
94 | { | 94 | { |
95 | __u32 marks_mask, marks_ignored_mask; | 95 | __u32 marks_mask = 0, marks_ignored_mask = 0; |
96 | const struct path *path = data; | 96 | const struct path *path = data; |
97 | 97 | ||
98 | pr_debug("%s: inode_mark=%p vfsmnt_mark=%p mask=%x data=%p" | 98 | pr_debug("%s: inode_mark=%p vfsmnt_mark=%p mask=%x data=%p" |
@@ -108,24 +108,20 @@ static bool fanotify_should_send_event(struct fsnotify_mark *inode_mark, | |||
108 | !d_can_lookup(path->dentry)) | 108 | !d_can_lookup(path->dentry)) |
109 | return false; | 109 | return false; |
110 | 110 | ||
111 | if (inode_mark && vfsmnt_mark) { | 111 | /* |
112 | marks_mask = (vfsmnt_mark->mask | inode_mark->mask); | 112 | * if the event is for a child and this inode doesn't care about |
113 | marks_ignored_mask = (vfsmnt_mark->ignored_mask | inode_mark->ignored_mask); | 113 | * events on the child, don't send it! |
114 | } else if (inode_mark) { | 114 | */ |
115 | /* | 115 | if (inode_mark && |
116 | * if the event is for a child and this inode doesn't care about | 116 | (!(event_mask & FS_EVENT_ON_CHILD) || |
117 | * events on the child, don't send it! | 117 | (inode_mark->mask & FS_EVENT_ON_CHILD))) { |
118 | */ | 118 | marks_mask |= inode_mark->mask; |
119 | if ((event_mask & FS_EVENT_ON_CHILD) && | 119 | marks_ignored_mask |= inode_mark->ignored_mask; |
120 | !(inode_mark->mask & FS_EVENT_ON_CHILD)) | 120 | } |
121 | return false; | 121 | |
122 | marks_mask = inode_mark->mask; | 122 | if (vfsmnt_mark) { |
123 | marks_ignored_mask = inode_mark->ignored_mask; | 123 | marks_mask |= vfsmnt_mark->mask; |
124 | } else if (vfsmnt_mark) { | 124 | marks_ignored_mask |= vfsmnt_mark->ignored_mask; |
125 | marks_mask = vfsmnt_mark->mask; | ||
126 | marks_ignored_mask = vfsmnt_mark->ignored_mask; | ||
127 | } else { | ||
128 | BUG(); | ||
129 | } | 125 | } |
130 | 126 | ||
131 | if (d_is_dir(path->dentry) && | 127 | if (d_is_dir(path->dentry) && |
diff --git a/fs/notify/fsnotify.c b/fs/notify/fsnotify.c index 219b269c737e..613ec7e5a465 100644 --- a/fs/notify/fsnotify.c +++ b/fs/notify/fsnotify.c | |||
@@ -192,8 +192,9 @@ static int send_to_group(struct inode *to_tell, | |||
192 | struct fsnotify_iter_info *iter_info) | 192 | struct fsnotify_iter_info *iter_info) |
193 | { | 193 | { |
194 | struct fsnotify_group *group = NULL; | 194 | struct fsnotify_group *group = NULL; |
195 | __u32 inode_test_mask = 0; | 195 | __u32 test_mask = (mask & ~FS_EVENT_ON_CHILD); |
196 | __u32 vfsmount_test_mask = 0; | 196 | __u32 marks_mask = 0; |
197 | __u32 marks_ignored_mask = 0; | ||
197 | 198 | ||
198 | if (unlikely(!inode_mark && !vfsmount_mark)) { | 199 | if (unlikely(!inode_mark && !vfsmount_mark)) { |
199 | BUG(); | 200 | BUG(); |
@@ -213,29 +214,25 @@ static int send_to_group(struct inode *to_tell, | |||
213 | /* does the inode mark tell us to do something? */ | 214 | /* does the inode mark tell us to do something? */ |
214 | if (inode_mark) { | 215 | if (inode_mark) { |
215 | group = inode_mark->group; | 216 | group = inode_mark->group; |
216 | inode_test_mask = (mask & ~FS_EVENT_ON_CHILD); | 217 | marks_mask |= inode_mark->mask; |
217 | inode_test_mask &= inode_mark->mask; | 218 | marks_ignored_mask |= inode_mark->ignored_mask; |
218 | inode_test_mask &= ~inode_mark->ignored_mask; | ||
219 | } | 219 | } |
220 | 220 | ||
221 | /* does the vfsmount_mark tell us to do something? */ | 221 | /* does the vfsmount_mark tell us to do something? */ |
222 | if (vfsmount_mark) { | 222 | if (vfsmount_mark) { |
223 | vfsmount_test_mask = (mask & ~FS_EVENT_ON_CHILD); | ||
224 | group = vfsmount_mark->group; | 223 | group = vfsmount_mark->group; |
225 | vfsmount_test_mask &= vfsmount_mark->mask; | 224 | marks_mask |= vfsmount_mark->mask; |
226 | vfsmount_test_mask &= ~vfsmount_mark->ignored_mask; | 225 | marks_ignored_mask |= vfsmount_mark->ignored_mask; |
227 | if (inode_mark) | ||
228 | vfsmount_test_mask &= ~inode_mark->ignored_mask; | ||
229 | } | 226 | } |
230 | 227 | ||
231 | pr_debug("%s: group=%p to_tell=%p mask=%x inode_mark=%p" | 228 | pr_debug("%s: group=%p to_tell=%p mask=%x inode_mark=%p" |
232 | " inode_test_mask=%x vfsmount_mark=%p vfsmount_test_mask=%x" | 229 | " vfsmount_mark=%p marks_mask=%x marks_ignored_mask=%x" |
233 | " data=%p data_is=%d cookie=%d\n", | 230 | " data=%p data_is=%d cookie=%d\n", |
234 | __func__, group, to_tell, mask, inode_mark, | 231 | __func__, group, to_tell, mask, inode_mark, vfsmount_mark, |
235 | inode_test_mask, vfsmount_mark, vfsmount_test_mask, data, | 232 | marks_mask, marks_ignored_mask, data, |
236 | data_is, cookie); | 233 | data_is, cookie); |
237 | 234 | ||
238 | if (!inode_test_mask && !vfsmount_test_mask) | 235 | if (!(test_mask & marks_mask & ~marks_ignored_mask)) |
239 | return 0; | 236 | return 0; |
240 | 237 | ||
241 | return group->ops->handle_event(group, to_tell, inode_mark, | 238 | return group->ops->handle_event(group, to_tell, inode_mark, |
diff --git a/fs/quota/dquot.c b/fs/quota/dquot.c index 020c597ef9b6..d88231e3b2be 100644 --- a/fs/quota/dquot.c +++ b/fs/quota/dquot.c | |||
@@ -2966,7 +2966,7 @@ static int __init dquot_init(void) | |||
2966 | NULL); | 2966 | NULL); |
2967 | 2967 | ||
2968 | order = 0; | 2968 | order = 0; |
2969 | dquot_hash = (struct hlist_head *)__get_free_pages(GFP_ATOMIC, order); | 2969 | dquot_hash = (struct hlist_head *)__get_free_pages(GFP_KERNEL, order); |
2970 | if (!dquot_hash) | 2970 | if (!dquot_hash) |
2971 | panic("Cannot create dquot hash table"); | 2971 | panic("Cannot create dquot hash table"); |
2972 | 2972 | ||
diff --git a/fs/udf/unicode.c b/fs/udf/unicode.c index f897e55f2cd0..16a8ad21b77e 100644 --- a/fs/udf/unicode.c +++ b/fs/udf/unicode.c | |||
@@ -28,6 +28,9 @@ | |||
28 | 28 | ||
29 | #include "udf_sb.h" | 29 | #include "udf_sb.h" |
30 | 30 | ||
31 | #define SURROGATE_MASK 0xfffff800 | ||
32 | #define SURROGATE_PAIR 0x0000d800 | ||
33 | |||
31 | static int udf_uni2char_utf8(wchar_t uni, | 34 | static int udf_uni2char_utf8(wchar_t uni, |
32 | unsigned char *out, | 35 | unsigned char *out, |
33 | int boundlen) | 36 | int boundlen) |
@@ -37,6 +40,9 @@ static int udf_uni2char_utf8(wchar_t uni, | |||
37 | if (boundlen <= 0) | 40 | if (boundlen <= 0) |
38 | return -ENAMETOOLONG; | 41 | return -ENAMETOOLONG; |
39 | 42 | ||
43 | if ((uni & SURROGATE_MASK) == SURROGATE_PAIR) | ||
44 | return -EINVAL; | ||
45 | |||
40 | if (uni < 0x80) { | 46 | if (uni < 0x80) { |
41 | out[u_len++] = (unsigned char)uni; | 47 | out[u_len++] = (unsigned char)uni; |
42 | } else if (uni < 0x800) { | 48 | } else if (uni < 0x800) { |
diff --git a/include/linux/fsnotify_backend.h b/include/linux/fsnotify_backend.h index 9f1edb92c97e..e0c95c9f1e29 100644 --- a/include/linux/fsnotify_backend.h +++ b/include/linux/fsnotify_backend.h | |||
@@ -248,7 +248,7 @@ struct fsnotify_mark { | |||
248 | /* Group this mark is for. Set on mark creation, stable until last ref | 248 | /* Group this mark is for. Set on mark creation, stable until last ref |
249 | * is dropped */ | 249 | * is dropped */ |
250 | struct fsnotify_group *group; | 250 | struct fsnotify_group *group; |
251 | /* List of marks by group->i_fsnotify_marks. Also reused for queueing | 251 | /* List of marks by group->marks_list. Also reused for queueing |
252 | * mark into destroy_list when it's waiting for the end of SRCU period | 252 | * mark into destroy_list when it's waiting for the end of SRCU period |
253 | * before it can be freed. [group->mark_mutex] */ | 253 | * before it can be freed. [group->mark_mutex] */ |
254 | struct list_head g_list; | 254 | struct list_head g_list; |