Skip to content

Commit 1a9515a

Browse files
amir73iljankara
authored andcommitted
fanotify: use helpers to parcel fanotify_info buffer
fanotify_info buffer is parceled into variable sized records, so the records must be written in order: dir_fh, file_fh, name. Use helpers to assert that order and make fanotify_alloc_name_event() a bit more generic to allow empty dir_fh record and to allow expanding to more records (i.e. name2) soon. Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Amir Goldstein <[email protected]> Signed-off-by: Jan Kara <[email protected]>
1 parent 2d9374f commit 1a9515a

File tree

2 files changed

+39
-16
lines changed

2 files changed

+39
-16
lines changed

fs/notify/fanotify/fanotify.c

Lines changed: 19 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -576,7 +576,7 @@ static struct fanotify_event *fanotify_alloc_fid_event(struct inode *id,
576576
return &ffe->fae;
577577
}
578578

579-
static struct fanotify_event *fanotify_alloc_name_event(struct inode *id,
579+
static struct fanotify_event *fanotify_alloc_name_event(struct inode *dir,
580580
__kernel_fsid_t *fsid,
581581
const struct qstr *name,
582582
struct inode *child,
@@ -586,15 +586,17 @@ static struct fanotify_event *fanotify_alloc_name_event(struct inode *id,
586586
struct fanotify_name_event *fne;
587587
struct fanotify_info *info;
588588
struct fanotify_fh *dfh, *ffh;
589-
unsigned int dir_fh_len = fanotify_encode_fh_len(id);
589+
unsigned int dir_fh_len = fanotify_encode_fh_len(dir);
590590
unsigned int child_fh_len = fanotify_encode_fh_len(child);
591-
unsigned int size;
591+
unsigned long name_len = name ? name->len : 0;
592+
unsigned int len, size;
592593

593-
size = sizeof(*fne) + FANOTIFY_FH_HDR_LEN + dir_fh_len;
594+
/* Reserve terminating null byte even for empty name */
595+
size = sizeof(*fne) + name_len + 1;
596+
if (dir_fh_len)
597+
size += FANOTIFY_FH_HDR_LEN + dir_fh_len;
594598
if (child_fh_len)
595599
size += FANOTIFY_FH_HDR_LEN + child_fh_len;
596-
if (name)
597-
size += name->len + 1;
598600
fne = kmalloc(size, gfp);
599601
if (!fne)
600602
return NULL;
@@ -604,22 +606,23 @@ static struct fanotify_event *fanotify_alloc_name_event(struct inode *id,
604606
*hash ^= fanotify_hash_fsid(fsid);
605607
info = &fne->info;
606608
fanotify_info_init(info);
607-
dfh = fanotify_info_dir_fh(info);
608-
info->dir_fh_totlen = fanotify_encode_fh(dfh, id, dir_fh_len, hash, 0);
609+
if (dir_fh_len) {
610+
dfh = fanotify_info_dir_fh(info);
611+
len = fanotify_encode_fh(dfh, dir, dir_fh_len, hash, 0);
612+
fanotify_info_set_dir_fh(info, len);
613+
}
609614
if (child_fh_len) {
610615
ffh = fanotify_info_file_fh(info);
611-
info->file_fh_totlen = fanotify_encode_fh(ffh, child,
612-
child_fh_len, hash, 0);
616+
len = fanotify_encode_fh(ffh, child, child_fh_len, hash, 0);
617+
fanotify_info_set_file_fh(info, len);
613618
}
614-
if (name) {
615-
long salt = name->len;
616-
619+
if (name_len) {
617620
fanotify_info_copy_name(info, name);
618-
*hash ^= full_name_hash((void *)salt, name->name, name->len);
621+
*hash ^= full_name_hash((void *)name_len, name->name, name_len);
619622
}
620623

621-
pr_debug("%s: ino=%lu size=%u dir_fh_len=%u child_fh_len=%u name_len=%u name='%.*s'\n",
622-
__func__, id->i_ino, size, dir_fh_len, child_fh_len,
624+
pr_debug("%s: size=%u dir_fh_len=%u child_fh_len=%u name_len=%u name='%.*s'\n",
625+
__func__, size, dir_fh_len, child_fh_len,
623626
info->name_len, info->name_len, fanotify_info_name(info));
624627

625628
return &fne->fae;

fs/notify/fanotify/fanotify.h

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,26 @@ static inline void fanotify_info_init(struct fanotify_info *info)
138138
info->name_len = 0;
139139
}
140140

141+
/* These set/copy helpers MUST be called by order */
142+
static inline void fanotify_info_set_dir_fh(struct fanotify_info *info,
143+
unsigned int totlen)
144+
{
145+
if (WARN_ON_ONCE(info->file_fh_totlen > 0) ||
146+
WARN_ON_ONCE(info->name_len > 0))
147+
return;
148+
149+
info->dir_fh_totlen = totlen;
150+
}
151+
152+
static inline void fanotify_info_set_file_fh(struct fanotify_info *info,
153+
unsigned int totlen)
154+
{
155+
if (WARN_ON_ONCE(info->name_len > 0))
156+
return;
157+
158+
info->file_fh_totlen = totlen;
159+
}
160+
141161
static inline void fanotify_info_copy_name(struct fanotify_info *info,
142162
const struct qstr *name)
143163
{

0 commit comments

Comments
 (0)