aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2018-04-20 12:01:26 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2018-04-20 12:01:26 -0400
commit0d9cf33b4aabd8de03f80659ceae967ba2b3ba30 (patch)
tree2e3ed6e9d9e1a43742714f472480eddc313ee906
parent4d1890531413a19d63cb980fee6d9d3ff86d97ad (diff)
parent44f06ba8297c7e9dfd0e49b40cbe119113cca094 (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--MAINTAINERS8
-rw-r--r--fs/ext2/file.c4
-rw-r--r--fs/isofs/compress.c19
-rw-r--r--fs/isofs/inode.c3
-rw-r--r--fs/notify/fanotify/fanotify.c34
-rw-r--r--fs/notify/fsnotify.c25
-rw-r--r--fs/quota/dquot.c2
-rw-r--r--fs/udf/unicode.c6
-rw-r--r--include/linux/fsnotify_backend.h2
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/
5784F: include/linux/fscrypt*.h 5784F: include/linux/fscrypt*.h
5785F: Documentation/filesystems/fscrypt.rst 5785F: Documentation/filesystems/fscrypt.rst
5786 5786
5787FSNOTIFY: FILESYSTEM NOTIFICATION INFRASTRUCTURE
5788M: Jan Kara <jack@suse.cz>
5789R: Amir Goldstein <amir73il@gmail.com>
5790L: linux-fsdevel@vger.kernel.org
5791S: Maintained
5792F: fs/notify/
5793F: include/linux/fsnotify*.h
5794
5787FUJITSU LAPTOP EXTRAS 5795FUJITSU LAPTOP EXTRAS
5788M: Jonathan Woithe <jwoithe@just42.net> 5796M: Jonathan Woithe <jwoithe@just42.net>
5789L: platform-driver-x86@vger.kernel.org 5797L: 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 */
91static int ext2_dax_fault(struct vm_fault *vmf) 91static 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:
190b_eio: 195b_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
31static int udf_uni2char_utf8(wchar_t uni, 34static 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;