From patchwork Sun Dec 2 11:38:24 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Amir Goldstein X-Patchwork-Id: 10707989 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id DB04416B1 for ; Sun, 2 Dec 2018 11:38:57 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id CB1FC2AEB6 for ; Sun, 2 Dec 2018 11:38:57 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id BF62F2AEBF; Sun, 2 Dec 2018 11:38:57 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-8.0 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,FREEMAIL_FROM,MAILING_LIST_MULTI,RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 216892AEB6 for ; Sun, 2 Dec 2018 11:38:57 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1725872AbeLBLi7 (ORCPT ); Sun, 2 Dec 2018 06:38:59 -0500 Received: from mail-wm1-f65.google.com ([209.85.128.65]:38971 "EHLO mail-wm1-f65.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1725829AbeLBLi6 (ORCPT ); Sun, 2 Dec 2018 06:38:58 -0500 Received: by mail-wm1-f65.google.com with SMTP id f81so559500wmd.4 for ; Sun, 02 Dec 2018 03:38:53 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=dwd0AwAigm3ysWORFOKtRcv4q4QCCnF496d317MvCps=; b=aUeVA+CwFY5ICQ/UydpfkJfc3B9inZYsueshdWA/ZUAJgZuXYF/VWV4VXoBNm4zNMU TPUytIedtzeT7ZM7QFsoL6askrXRvBYOcmxBNNwbOOLbFLwevZOSFBVWOMEM9JbQqDYa LyvG4fTxSp8g7i2UgHbPE0gKdBwyARTaq6vabJaRuIx6NEcyd9vM/UkCafiZgZ6ipx2t c6wOspH04jjAf0eBZlRoBu4k1/ze3bW+5rqI9IJ372LZps1fo81ElPt9aMeRmytEvrNE l1SrzgdSY1DuPPrINbGjvQweAoHMLtgSkBL9OgWKQ21wqJBpiqKpg12qGjx5+ovRnAfT w+Lw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=dwd0AwAigm3ysWORFOKtRcv4q4QCCnF496d317MvCps=; b=TqDf1ch6sluWeAkWGJfpvXmGP/75S7fqdJPKo5/sb01g/udwXMEQ65/no5yS7MhJSX xo1rnoJFa7ZIeJZpMlgzB0XpoBNYfA16PZikMkDc2xorskMUfaHFdRGHMM86ND8TTghp dXMNayeMx9yUCB6pW2sQmrbPThfMcFuuOsoGuSX5DSDNkZjgkfrt1L1eiur8e9T2NJA7 /kpgOXdUpr92URV3LVgcc27uB3cjjNCNE2PuA/SJKlhRbQMoiRMwEDj3Ap3CiRwiAqHr TAPE+ji/++Wpjx1XKf+4RAVvPJTRDTneYsoVNnMPC3cKO3/sxdFGxz+Pt5S8QtImsT8v lZMA== X-Gm-Message-State: AA+aEWabmXPo2c7FV1edSQqEr02JENRUtApJawsw6FeyeOMZYSvG1pIP Q53UHmN1FF0joLz1oFP+8PJk7j8f X-Google-Smtp-Source: AFSGD/XU94987JLo8UJ7sEPYbbD3ufiynlOZN+5PLr+EU5+oD2yKXrgo7V1vnc6+hDwnvyvgxOe2zA== X-Received: by 2002:a1c:770c:: with SMTP id t12mr4826404wmi.101.1543750732914; Sun, 02 Dec 2018 03:38:52 -0800 (PST) Received: from localhost.localdomain (bzq-166-168-31-246.red.bezeqint.net. [31.168.166.246]) by smtp.gmail.com with ESMTPSA id c3-v6sm3448672wmb.46.2018.12.02.03.38.51 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Sun, 02 Dec 2018 03:38:52 -0800 (PST) From: Amir Goldstein To: Jan Kara Cc: Matthew Bobrowski , linux-fsdevel@vger.kernel.org Subject: [PATCH v4 13/15] fanotify: support events with data type FSNOTIFY_EVENT_INODE Date: Sun, 2 Dec 2018 13:38:24 +0200 Message-Id: <20181202113826.32133-14-amir73il@gmail.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20181202113826.32133-1-amir73il@gmail.com> References: <20181202113826.32133-1-amir73il@gmail.com> Sender: linux-fsdevel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-fsdevel@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP When event data type is FSNOTIFY_EVENT_INODE, we don't have a refernece to the mount, so we will not be able to open a file descriptor when user reads the event. However, if the listener has enabled reporting file identifier with the FAN_REPORT_FID init flag, we allow repoting those events and we use an indentifier inode to encode fid. The inode to use as indetifier when reporting fid depedns on the event. For dirent modification events, we report the modified directory inode and we report the "victim" inode otherwise. For example: FS_ATTRIB reports the child inode even if reported on a watched parent. FS_CREATE reports the modified dir inode and not the created inode. Signed-off-by: Amir Goldstein --- fs/notify/fanotify/fanotify.c | 67 ++++++++++++++++++++---------- fs/notify/fanotify/fanotify.h | 2 +- fs/notify/fanotify/fanotify_user.c | 3 +- 3 files changed, 48 insertions(+), 24 deletions(-) diff --git a/fs/notify/fanotify/fanotify.c b/fs/notify/fanotify/fanotify.c index 5a958b1d0cb6..5f157dee2089 100644 --- a/fs/notify/fanotify/fanotify.c +++ b/fs/notify/fanotify/fanotify.c @@ -96,7 +96,7 @@ static int fanotify_get_response(struct fsnotify_group *group, pr_debug("%s: group=%p event=%p about to return ret=%d\n", __func__, group, event, ret); - + return ret; } @@ -106,9 +106,10 @@ static int fanotify_get_response(struct fsnotify_group *group, * been included within the event mask, but have not been explicitly * requested by the user, will not be present in the returned mask. */ -static u32 fanotify_group_event_mask(struct fsnotify_iter_info *iter_info, - u32 event_mask, const void *data, - int data_type) +static u32 fanotify_group_event_mask(struct fsnotify_group *group, + struct fsnotify_iter_info *iter_info, + u32 event_mask, const void *data, + int data_type) { __u32 marks_mask = 0, marks_ignored_mask = 0; const struct path *path = data; @@ -118,14 +119,14 @@ static u32 fanotify_group_event_mask(struct fsnotify_iter_info *iter_info, pr_debug("%s: report_mask=%x mask=%x data=%p data_type=%d\n", __func__, iter_info->report_mask, event_mask, data, data_type); - /* If we don't have enough info to send an event to userspace say no */ - if (data_type != FSNOTIFY_EVENT_PATH) - return 0; - - /* Sorry, fanotify only gives a damn about files and dirs */ - if (!d_is_reg(path->dentry) && - !d_can_lookup(path->dentry)) + if (data_type == FSNOTIFY_EVENT_PATH) { + /* Path type events are only relevant for files and dirs */ + if (!d_is_reg(path->dentry) && !d_can_lookup(path->dentry)) + return 0; + } else if (!FAN_GROUP_FLAG(group, FAN_REPORT_FID)) { + /* Events without path data require FAN_REPORT_FID */ return 0; + } fsnotify_foreach_obj_type(type) { if (!fsnotify_iter_should_report_type(iter_info, type)) @@ -153,7 +154,7 @@ static u32 fanotify_group_event_mask(struct fsnotify_iter_info *iter_info, } static int fanotify_encode_fid(struct fanotify_event *event, - const struct path *path, gfp_t gfp, + struct inode *inode, gfp_t gfp, __kernel_fsid_t *fsid) { struct fanotify_fid *fid = &event->fid; @@ -166,7 +167,7 @@ static int fanotify_encode_fid(struct fanotify_event *event, fid->ext_fh = NULL; dwords = 0; err = -ENOENT; - type = exportfs_encode_fh(path->dentry, NULL, &dwords, 0); + type = exportfs_encode_inode_fh(inode, NULL, &dwords, NULL); if (!dwords) goto out_err; @@ -179,8 +180,8 @@ static int fanotify_encode_fid(struct fanotify_event *event, goto out_err; } - type = exportfs_encode_fh(path->dentry, fanotify_fid_fh(fid, bytes), - &dwords, 0); + type = exportfs_encode_inode_fh(inode, fanotify_fid_fh(fid, bytes), + &dwords, NULL); err = -EINVAL; if (!type || type == FILEID_INVALID || bytes != dwords << 2) goto out_err; @@ -201,13 +202,34 @@ static int fanotify_encode_fid(struct fanotify_event *event, return FILEID_INVALID; } +/* + * The inode to use as indetifier when reporting fid depedns on the event. + * Report the modified directory inode on dirent modification events. + * Report the "victim" inode otherwise. + * For example: + * FS_ATTRIB reports the child inode even if reported on a watched parent. + * FS_CREATE reports the modified dir inode and not the created inode. + */ +static struct inode *fanotify_report_id(struct inode *to_tell, u32 event_mask, + const void *data, int data_type) +{ + if (event_mask & ALL_FSNOTIFY_DIRENT_EVENTS) + return to_tell; + else if (data_type == FSNOTIFY_EVENT_INODE) + return (struct inode *)data; + else if (data_type == FSNOTIFY_EVENT_PATH) + return d_inode(((struct path *)data)->dentry); + return NULL; +} + struct fanotify_event *fanotify_alloc_event(struct fsnotify_group *group, struct inode *inode, u32 mask, - const struct path *path, + const void *data, int data_type, __kernel_fsid_t *fsid) { struct fanotify_event *event = NULL; gfp_t gfp = GFP_KERNEL_ACCOUNT; + struct inode *id = fanotify_report_id(inode, mask, data, data_type); /* * For queues with unlimited length lost events are not expected and @@ -241,12 +263,12 @@ init: __maybe_unused else event->pid = get_pid(task_tgid(current)); event->fh_len = 0; - if (path && FAN_GROUP_FLAG(group, FAN_REPORT_FID)) { + if (id && FAN_GROUP_FLAG(group, FAN_REPORT_FID)) { /* Report the event without a file identifier on encode error */ - event->fh_type = fanotify_encode_fid(event, path, gfp, fsid); - } else if (path) { + event->fh_type = fanotify_encode_fid(event, id, gfp, fsid); + } else if (data_type == FSNOTIFY_EVENT_PATH) { event->fh_type = 0; - event->path = *path; + event->path = *((struct path *)data); path_get(&event->path); } else { event->fh_type = FILEID_INVALID; @@ -306,7 +328,8 @@ static int fanotify_handle_event(struct fsnotify_group *group, BUILD_BUG_ON(HWEIGHT32(ALL_FANOTIFY_EVENT_BITS) != 12); - mask = fanotify_group_event_mask(iter_info, mask, data, data_type); + mask = fanotify_group_event_mask(group, iter_info, mask, data, + data_type); if (!mask) return 0; @@ -325,7 +348,7 @@ static int fanotify_handle_event(struct fsnotify_group *group, if (FAN_GROUP_FLAG(group, FAN_REPORT_FID)) fsid = fanotify_get_fsid(iter_info, &__fsid); - event = fanotify_alloc_event(group, inode, mask, data, fsid); + event = fanotify_alloc_event(group, inode, mask, data, data_type, fsid); ret = -ENOMEM; if (unlikely(!event)) { /* diff --git a/fs/notify/fanotify/fanotify.h b/fs/notify/fanotify/fanotify.h index 06b93cf227a2..3fd74949a26d 100644 --- a/fs/notify/fanotify/fanotify.h +++ b/fs/notify/fanotify/fanotify.h @@ -136,5 +136,5 @@ static inline struct fanotify_event *FANOTIFY_E(struct fsnotify_event *fse) struct fanotify_event *fanotify_alloc_event(struct fsnotify_group *group, struct inode *inode, u32 mask, - const struct path *path, + const void *data, int data_type, __kernel_fsid_t *fsid); diff --git a/fs/notify/fanotify/fanotify_user.c b/fs/notify/fanotify/fanotify_user.c index 8ecd9db8931c..8bbcf6157927 100644 --- a/fs/notify/fanotify/fanotify_user.c +++ b/fs/notify/fanotify/fanotify_user.c @@ -792,7 +792,8 @@ SYSCALL_DEFINE2(fanotify_init, unsigned int, flags, unsigned int, event_f_flags) atomic_inc(&user->fanotify_listeners); group->memcg = get_mem_cgroup_from_mm(current->mm); - oevent = fanotify_alloc_event(group, NULL, FS_Q_OVERFLOW, NULL, NULL); + oevent = fanotify_alloc_event(group, NULL, FS_Q_OVERFLOW, NULL, + FSNOTIFY_EVENT_NONE, NULL); if (unlikely(!oevent)) { fd = -ENOMEM; goto out_destroy_group;