]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/blame - releases/5.15.154/fanotify-use-helpers-to-parcel-fanotify_info-buffer.patch
Linux 5.15.154
[thirdparty/kernel/stable-queue.git] / releases / 5.15.154 / fanotify-use-helpers-to-parcel-fanotify_info-buffer.patch
CommitLineData
52761858
SL
1From d081712cdf4b7a4274fb883bac202ddb596238c2 Mon Sep 17 00:00:00 2001
2From: Sasha Levin <sashal@kernel.org>
3Date: Mon, 29 Nov 2021 22:15:32 +0200
4Subject: fanotify: use helpers to parcel fanotify_info buffer
5
6From: Amir Goldstein <amir73il@gmail.com>
7
8[ Upstream commit 1a9515ac9e55e68d733bab81bd408463ab1e25b1 ]
9
10fanotify_info buffer is parceled into variable sized records, so the
11records must be written in order: dir_fh, file_fh, name.
12
13Use helpers to assert that order and make fanotify_alloc_name_event()
14a bit more generic to allow empty dir_fh record and to allow expanding
15to more records (i.e. name2) soon.
16
17Link: https://lore.kernel.org/r/20211129201537.1932819-7-amir73il@gmail.com
18Signed-off-by: Amir Goldstein <amir73il@gmail.com>
19Signed-off-by: Jan Kara <jack@suse.cz>
20Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
21---
22 fs/notify/fanotify/fanotify.c | 35 +++++++++++++++++++----------------
23 fs/notify/fanotify/fanotify.h | 20 ++++++++++++++++++++
24 2 files changed, 39 insertions(+), 16 deletions(-)
25
26diff --git a/fs/notify/fanotify/fanotify.c b/fs/notify/fanotify/fanotify.c
27index ffad224be0149..2b13c79cebc62 100644
28--- a/fs/notify/fanotify/fanotify.c
29+++ b/fs/notify/fanotify/fanotify.c
30@@ -576,7 +576,7 @@ static struct fanotify_event *fanotify_alloc_fid_event(struct inode *id,
31 return &ffe->fae;
32 }
33
34-static struct fanotify_event *fanotify_alloc_name_event(struct inode *id,
35+static struct fanotify_event *fanotify_alloc_name_event(struct inode *dir,
36 __kernel_fsid_t *fsid,
37 const struct qstr *name,
38 struct inode *child,
39@@ -586,15 +586,17 @@ static struct fanotify_event *fanotify_alloc_name_event(struct inode *id,
40 struct fanotify_name_event *fne;
41 struct fanotify_info *info;
42 struct fanotify_fh *dfh, *ffh;
43- unsigned int dir_fh_len = fanotify_encode_fh_len(id);
44+ unsigned int dir_fh_len = fanotify_encode_fh_len(dir);
45 unsigned int child_fh_len = fanotify_encode_fh_len(child);
46- unsigned int size;
47+ unsigned long name_len = name ? name->len : 0;
48+ unsigned int len, size;
49
50- size = sizeof(*fne) + FANOTIFY_FH_HDR_LEN + dir_fh_len;
51+ /* Reserve terminating null byte even for empty name */
52+ size = sizeof(*fne) + name_len + 1;
53+ if (dir_fh_len)
54+ size += FANOTIFY_FH_HDR_LEN + dir_fh_len;
55 if (child_fh_len)
56 size += FANOTIFY_FH_HDR_LEN + child_fh_len;
57- if (name)
58- size += name->len + 1;
59 fne = kmalloc(size, gfp);
60 if (!fne)
61 return NULL;
62@@ -604,22 +606,23 @@ static struct fanotify_event *fanotify_alloc_name_event(struct inode *id,
63 *hash ^= fanotify_hash_fsid(fsid);
64 info = &fne->info;
65 fanotify_info_init(info);
66- dfh = fanotify_info_dir_fh(info);
67- info->dir_fh_totlen = fanotify_encode_fh(dfh, id, dir_fh_len, hash, 0);
68+ if (dir_fh_len) {
69+ dfh = fanotify_info_dir_fh(info);
70+ len = fanotify_encode_fh(dfh, dir, dir_fh_len, hash, 0);
71+ fanotify_info_set_dir_fh(info, len);
72+ }
73 if (child_fh_len) {
74 ffh = fanotify_info_file_fh(info);
75- info->file_fh_totlen = fanotify_encode_fh(ffh, child,
76- child_fh_len, hash, 0);
77+ len = fanotify_encode_fh(ffh, child, child_fh_len, hash, 0);
78+ fanotify_info_set_file_fh(info, len);
79 }
80- if (name) {
81- long salt = name->len;
82-
83+ if (name_len) {
84 fanotify_info_copy_name(info, name);
85- *hash ^= full_name_hash((void *)salt, name->name, name->len);
86+ *hash ^= full_name_hash((void *)name_len, name->name, name_len);
87 }
88
89- pr_debug("%s: ino=%lu size=%u dir_fh_len=%u child_fh_len=%u name_len=%u name='%.*s'\n",
90- __func__, id->i_ino, size, dir_fh_len, child_fh_len,
91+ pr_debug("%s: size=%u dir_fh_len=%u child_fh_len=%u name_len=%u name='%.*s'\n",
92+ __func__, size, dir_fh_len, child_fh_len,
93 info->name_len, info->name_len, fanotify_info_name(info));
94
95 return &fne->fae;
96diff --git a/fs/notify/fanotify/fanotify.h b/fs/notify/fanotify/fanotify.h
97index dd23ba659e76b..7ac6f9f1e4148 100644
98--- a/fs/notify/fanotify/fanotify.h
99+++ b/fs/notify/fanotify/fanotify.h
100@@ -138,6 +138,26 @@ static inline void fanotify_info_init(struct fanotify_info *info)
101 info->name_len = 0;
102 }
103
104+/* These set/copy helpers MUST be called by order */
105+static inline void fanotify_info_set_dir_fh(struct fanotify_info *info,
106+ unsigned int totlen)
107+{
108+ if (WARN_ON_ONCE(info->file_fh_totlen > 0) ||
109+ WARN_ON_ONCE(info->name_len > 0))
110+ return;
111+
112+ info->dir_fh_totlen = totlen;
113+}
114+
115+static inline void fanotify_info_set_file_fh(struct fanotify_info *info,
116+ unsigned int totlen)
117+{
118+ if (WARN_ON_ONCE(info->name_len > 0))
119+ return;
120+
121+ info->file_fh_totlen = totlen;
122+}
123+
124 static inline void fanotify_info_copy_name(struct fanotify_info *info,
125 const struct qstr *name)
126 {
127--
1282.43.0
129