Commit 3cf984e9 authored by Amir Goldstein's avatar Amir Goldstein Committed by Jan Kara

fanotify: support secondary dir fh and name in fanotify_info

Allow storing a secondary dir fh and name tupple in fanotify_info.
This will be used to store the new parent and name information in
FAN_RENAME event.

Link: https://lore.kernel.org/r/20211129201537.1932819-8-amir73il@gmail.comSigned-off-by: default avatarAmir Goldstein <amir73il@gmail.com>
Signed-off-by: default avatarJan Kara <jack@suse.cz>
parent 1a9515ac
...@@ -76,8 +76,10 @@ static bool fanotify_info_equal(struct fanotify_info *info1, ...@@ -76,8 +76,10 @@ static bool fanotify_info_equal(struct fanotify_info *info1,
struct fanotify_info *info2) struct fanotify_info *info2)
{ {
if (info1->dir_fh_totlen != info2->dir_fh_totlen || if (info1->dir_fh_totlen != info2->dir_fh_totlen ||
info1->dir2_fh_totlen != info2->dir2_fh_totlen ||
info1->file_fh_totlen != info2->file_fh_totlen || info1->file_fh_totlen != info2->file_fh_totlen ||
info1->name_len != info2->name_len) info1->name_len != info2->name_len ||
info1->name2_len != info2->name2_len)
return false; return false;
if (info1->dir_fh_totlen && if (info1->dir_fh_totlen &&
...@@ -85,14 +87,24 @@ static bool fanotify_info_equal(struct fanotify_info *info1, ...@@ -85,14 +87,24 @@ static bool fanotify_info_equal(struct fanotify_info *info1,
fanotify_info_dir_fh(info2))) fanotify_info_dir_fh(info2)))
return false; return false;
if (info1->dir2_fh_totlen &&
!fanotify_fh_equal(fanotify_info_dir2_fh(info1),
fanotify_info_dir2_fh(info2)))
return false;
if (info1->file_fh_totlen && if (info1->file_fh_totlen &&
!fanotify_fh_equal(fanotify_info_file_fh(info1), !fanotify_fh_equal(fanotify_info_file_fh(info1),
fanotify_info_file_fh(info2))) fanotify_info_file_fh(info2)))
return false; return false;
return !info1->name_len || if (info1->name_len &&
!memcmp(fanotify_info_name(info1), fanotify_info_name(info2), memcmp(fanotify_info_name(info1), fanotify_info_name(info2),
info1->name_len); info1->name_len))
return false;
return !info1->name2_len ||
!memcmp(fanotify_info_name2(info1), fanotify_info_name2(info2),
info1->name2_len);
} }
static bool fanotify_name_event_equal(struct fanotify_name_event *fne1, static bool fanotify_name_event_equal(struct fanotify_name_event *fne1,
......
...@@ -40,31 +40,45 @@ struct fanotify_fh { ...@@ -40,31 +40,45 @@ struct fanotify_fh {
struct fanotify_info { struct fanotify_info {
/* size of dir_fh/file_fh including fanotify_fh hdr size */ /* size of dir_fh/file_fh including fanotify_fh hdr size */
u8 dir_fh_totlen; u8 dir_fh_totlen;
u8 dir2_fh_totlen;
u8 file_fh_totlen; u8 file_fh_totlen;
u8 name_len; u8 name_len;
u8 pad; u8 name2_len;
u8 pad[3];
unsigned char buf[]; unsigned char buf[];
/* /*
* (struct fanotify_fh) dir_fh starts at buf[0] * (struct fanotify_fh) dir_fh starts at buf[0]
* (optional) file_fh starts at buf[dir_fh_totlen] * (optional) dir2_fh starts at buf[dir_fh_totlen]
* name starts at buf[dir_fh_totlen + file_fh_totlen] * (optional) file_fh starts at buf[dir_fh_totlen + dir2_fh_totlen]
* name starts at buf[dir_fh_totlen + dir2_fh_totlen + file_fh_totlen]
* ...
*/ */
#define FANOTIFY_DIR_FH_SIZE(info) ((info)->dir_fh_totlen) #define FANOTIFY_DIR_FH_SIZE(info) ((info)->dir_fh_totlen)
#define FANOTIFY_DIR2_FH_SIZE(info) ((info)->dir2_fh_totlen)
#define FANOTIFY_FILE_FH_SIZE(info) ((info)->file_fh_totlen) #define FANOTIFY_FILE_FH_SIZE(info) ((info)->file_fh_totlen)
#define FANOTIFY_NAME_SIZE(info) ((info)->name_len + 1) #define FANOTIFY_NAME_SIZE(info) ((info)->name_len + 1)
#define FANOTIFY_NAME2_SIZE(info) ((info)->name2_len + 1)
#define FANOTIFY_DIR_FH_OFFSET(info) 0 #define FANOTIFY_DIR_FH_OFFSET(info) 0
#define FANOTIFY_FILE_FH_OFFSET(info) \ #define FANOTIFY_DIR2_FH_OFFSET(info) \
(FANOTIFY_DIR_FH_OFFSET(info) + FANOTIFY_DIR_FH_SIZE(info)) (FANOTIFY_DIR_FH_OFFSET(info) + FANOTIFY_DIR_FH_SIZE(info))
#define FANOTIFY_FILE_FH_OFFSET(info) \
(FANOTIFY_DIR2_FH_OFFSET(info) + FANOTIFY_DIR2_FH_SIZE(info))
#define FANOTIFY_NAME_OFFSET(info) \ #define FANOTIFY_NAME_OFFSET(info) \
(FANOTIFY_FILE_FH_OFFSET(info) + FANOTIFY_FILE_FH_SIZE(info)) (FANOTIFY_FILE_FH_OFFSET(info) + FANOTIFY_FILE_FH_SIZE(info))
#define FANOTIFY_NAME2_OFFSET(info) \
(FANOTIFY_NAME_OFFSET(info) + FANOTIFY_NAME_SIZE(info))
#define FANOTIFY_DIR_FH_BUF(info) \ #define FANOTIFY_DIR_FH_BUF(info) \
((info)->buf + FANOTIFY_DIR_FH_OFFSET(info)) ((info)->buf + FANOTIFY_DIR_FH_OFFSET(info))
#define FANOTIFY_DIR2_FH_BUF(info) \
((info)->buf + FANOTIFY_DIR2_FH_OFFSET(info))
#define FANOTIFY_FILE_FH_BUF(info) \ #define FANOTIFY_FILE_FH_BUF(info) \
((info)->buf + FANOTIFY_FILE_FH_OFFSET(info)) ((info)->buf + FANOTIFY_FILE_FH_OFFSET(info))
#define FANOTIFY_NAME_BUF(info) \ #define FANOTIFY_NAME_BUF(info) \
((info)->buf + FANOTIFY_NAME_OFFSET(info)) ((info)->buf + FANOTIFY_NAME_OFFSET(info))
#define FANOTIFY_NAME2_BUF(info) \
((info)->buf + FANOTIFY_NAME2_OFFSET(info))
} __aligned(4); } __aligned(4);
static inline bool fanotify_fh_has_ext_buf(struct fanotify_fh *fh) static inline bool fanotify_fh_has_ext_buf(struct fanotify_fh *fh)
...@@ -106,6 +120,20 @@ static inline struct fanotify_fh *fanotify_info_dir_fh(struct fanotify_info *inf ...@@ -106,6 +120,20 @@ static inline struct fanotify_fh *fanotify_info_dir_fh(struct fanotify_info *inf
return (struct fanotify_fh *)FANOTIFY_DIR_FH_BUF(info); return (struct fanotify_fh *)FANOTIFY_DIR_FH_BUF(info);
} }
static inline int fanotify_info_dir2_fh_len(struct fanotify_info *info)
{
if (!info->dir2_fh_totlen ||
WARN_ON_ONCE(info->dir2_fh_totlen < FANOTIFY_FH_HDR_LEN))
return 0;
return info->dir2_fh_totlen - FANOTIFY_FH_HDR_LEN;
}
static inline struct fanotify_fh *fanotify_info_dir2_fh(struct fanotify_info *info)
{
return (struct fanotify_fh *)FANOTIFY_DIR2_FH_BUF(info);
}
static inline int fanotify_info_file_fh_len(struct fanotify_info *info) static inline int fanotify_info_file_fh_len(struct fanotify_info *info)
{ {
if (!info->file_fh_totlen || if (!info->file_fh_totlen ||
...@@ -128,31 +156,55 @@ static inline char *fanotify_info_name(struct fanotify_info *info) ...@@ -128,31 +156,55 @@ static inline char *fanotify_info_name(struct fanotify_info *info)
return FANOTIFY_NAME_BUF(info); return FANOTIFY_NAME_BUF(info);
} }
static inline char *fanotify_info_name2(struct fanotify_info *info)
{
if (!info->name2_len)
return NULL;
return FANOTIFY_NAME2_BUF(info);
}
static inline void fanotify_info_init(struct fanotify_info *info) static inline void fanotify_info_init(struct fanotify_info *info)
{ {
BUILD_BUG_ON(FANOTIFY_FH_HDR_LEN + MAX_HANDLE_SZ > U8_MAX); BUILD_BUG_ON(FANOTIFY_FH_HDR_LEN + MAX_HANDLE_SZ > U8_MAX);
BUILD_BUG_ON(NAME_MAX > U8_MAX); BUILD_BUG_ON(NAME_MAX > U8_MAX);
info->dir_fh_totlen = 0; info->dir_fh_totlen = 0;
info->dir2_fh_totlen = 0;
info->file_fh_totlen = 0; info->file_fh_totlen = 0;
info->name_len = 0; info->name_len = 0;
info->name2_len = 0;
} }
/* These set/copy helpers MUST be called by order */ /* These set/copy helpers MUST be called by order */
static inline void fanotify_info_set_dir_fh(struct fanotify_info *info, static inline void fanotify_info_set_dir_fh(struct fanotify_info *info,
unsigned int totlen) unsigned int totlen)
{ {
if (WARN_ON_ONCE(info->file_fh_totlen > 0) || if (WARN_ON_ONCE(info->dir2_fh_totlen > 0) ||
WARN_ON_ONCE(info->name_len > 0)) WARN_ON_ONCE(info->file_fh_totlen > 0) ||
WARN_ON_ONCE(info->name_len > 0) ||
WARN_ON_ONCE(info->name2_len > 0))
return; return;
info->dir_fh_totlen = totlen; info->dir_fh_totlen = totlen;
} }
static inline void fanotify_info_set_dir2_fh(struct fanotify_info *info,
unsigned int totlen)
{
if (WARN_ON_ONCE(info->file_fh_totlen > 0) ||
WARN_ON_ONCE(info->name_len > 0) ||
WARN_ON_ONCE(info->name2_len > 0))
return;
info->dir2_fh_totlen = totlen;
}
static inline void fanotify_info_set_file_fh(struct fanotify_info *info, static inline void fanotify_info_set_file_fh(struct fanotify_info *info,
unsigned int totlen) unsigned int totlen)
{ {
if (WARN_ON_ONCE(info->name_len > 0)) if (WARN_ON_ONCE(info->name_len > 0) ||
WARN_ON_ONCE(info->name2_len > 0))
return; return;
info->file_fh_totlen = totlen; info->file_fh_totlen = totlen;
...@@ -161,13 +213,24 @@ static inline void fanotify_info_set_file_fh(struct fanotify_info *info, ...@@ -161,13 +213,24 @@ static inline void fanotify_info_set_file_fh(struct fanotify_info *info,
static inline void fanotify_info_copy_name(struct fanotify_info *info, static inline void fanotify_info_copy_name(struct fanotify_info *info,
const struct qstr *name) const struct qstr *name)
{ {
if (WARN_ON_ONCE(name->len > NAME_MAX)) if (WARN_ON_ONCE(name->len > NAME_MAX) ||
WARN_ON_ONCE(info->name2_len > 0))
return; return;
info->name_len = name->len; info->name_len = name->len;
strcpy(fanotify_info_name(info), name->name); strcpy(fanotify_info_name(info), name->name);
} }
static inline void fanotify_info_copy_name2(struct fanotify_info *info,
const struct qstr *name)
{
if (WARN_ON_ONCE(name->len > NAME_MAX))
return;
info->name2_len = name->len;
strcpy(fanotify_info_name2(info), name->name);
}
/* /*
* Common structure for fanotify events. Concrete structs are allocated in * Common structure for fanotify events. Concrete structs are allocated in
* fanotify_handle_event() and freed when the information is retrieved by * fanotify_handle_event() and freed when the information is retrieved by
......
...@@ -332,11 +332,10 @@ static int process_access_response(struct fsnotify_group *group, ...@@ -332,11 +332,10 @@ static int process_access_response(struct fsnotify_group *group,
static size_t copy_error_info_to_user(struct fanotify_event *event, static size_t copy_error_info_to_user(struct fanotify_event *event,
char __user *buf, int count) char __user *buf, int count)
{ {
struct fanotify_event_info_error info; struct fanotify_event_info_error info = { };
struct fanotify_error_event *fee = FANOTIFY_EE(event); struct fanotify_error_event *fee = FANOTIFY_EE(event);
info.hdr.info_type = FAN_EVENT_INFO_TYPE_ERROR; info.hdr.info_type = FAN_EVENT_INFO_TYPE_ERROR;
info.hdr.pad = 0;
info.hdr.len = FANOTIFY_ERROR_INFO_LEN; info.hdr.len = FANOTIFY_ERROR_INFO_LEN;
if (WARN_ON(count < info.hdr.len)) if (WARN_ON(count < info.hdr.len))
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment