From patchwork Sun Nov 25 13:43:50 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Amir Goldstein X-Patchwork-Id: 10696845 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 F213C17FE for ; Sun, 25 Nov 2018 13:44:26 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id DD8A12916A for ; Sun, 25 Nov 2018 13:44:26 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id C4B91291E8; Sun, 25 Nov 2018 13:44:26 +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 2BC132919A for ; Sun, 25 Nov 2018 13:44:26 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726447AbeKZAfb (ORCPT ); Sun, 25 Nov 2018 19:35:31 -0500 Received: from mail-wm1-f68.google.com ([209.85.128.68]:35638 "EHLO mail-wm1-f68.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726416AbeKZAfb (ORCPT ); Sun, 25 Nov 2018 19:35:31 -0500 Received: by mail-wm1-f68.google.com with SMTP id c126so15667998wmh.0 for ; Sun, 25 Nov 2018 05:44:23 -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=XzUycu8Zitpu2yM3zkr16AP/LtGOuOhSbMfs+7svqFQ=; b=LJEBayRG9njWKtYK5+hthcTmW6CsDANO4evP6ml2kG+kRUPjFMUSD/HjKocIMU9HCD NPs77LVY8qtxAaqcoK4+qcnJheq/akgNbJpAfvUvDABUVFlVWl4gJEp+gwUvFVHZVQse L3EJIVp+RxFs6aqLQs7qqA29yOrQIDYdk18IFscDhzuQlLEJHt1ySOycuhi4o86f9dDt 289cLbOJ8ULHFvg5rkESK+znhFXZuVlvhXRaQ7S0wlSZ6QO0ydfJGyYR+paFiuLgpavl Dcf/3LmFfp5vyck56FajFfOlAO3PLKO7GPIoL4+pvzDek0rVklMfuedbxBPcMl89TIob BTgg== 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=XzUycu8Zitpu2yM3zkr16AP/LtGOuOhSbMfs+7svqFQ=; b=EzZf3somth2ErIANkZPNiYfOJ49vlAVoFdNR9cjsNosVlaUuPAfjx0LY+gdNQ5rcFl bi9ZYxSvqGlyXy2WBm73K+lKNLGVNfDUQGJb/PNGvZQbfDUGrzW+8we6dIhlX3MP6IC+ afW2oA95q7flu+nKDHPPTfLSEI3OukeeI2qqogA1Lqvyx0ATDbLo4o2hq4QhyjZ0GrIl F7rWLrp6UY0vAQ/k1LYNzbIoGz6pLLeyAmAP7ATc/n2BWZx1C7SBXCVdU5BexSwBE4gT YE3ubXEJ0e8ra+taniqYLmJw65gIze+QXjLhhHHG/kosBv55YwMsQ3Fad1bmxGeW3iv2 0SYQ== X-Gm-Message-State: AA+aEWb8Y4vgjI60S60KVcvxRN8JBwoZ/fn2pHHwzfztSIukOI9NXhha RTHwowR7y2CAkCRDQEB7441jqi+7 X-Google-Smtp-Source: AFSGD/UziPKkm2AjGAztEVJ0SkzyBo+9+6f4Vp3PFtzoqZLiogGZJgBtzLFjQTaPtOhdCMzXymi2xA== X-Received: by 2002:a1c:110b:: with SMTP id 11mr19889447wmr.83.1543153462770; Sun, 25 Nov 2018 05:44:22 -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 125sm17354274wml.35.2018.11.25.05.44.21 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Sun, 25 Nov 2018 05:44:22 -0800 (PST) From: Amir Goldstein To: Jan Kara Cc: Matthew Bobrowski , linux-fsdevel@vger.kernel.org Subject: [PATCH v3 11/13] fanotify: support events with data type FSNOTIFY_EVENT_INODE Date: Sun, 25 Nov 2018 15:43:50 +0200 Message-Id: <20181125134352.21499-12-amir73il@gmail.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20181125134352.21499-1-amir73il@gmail.com> References: <20181125134352.21499-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 | 62 ++++++++++++++++++++---------- fs/notify/fanotify/fanotify.h | 2 +- fs/notify/fanotify/fanotify_user.c | 3 +- 3 files changed, 45 insertions(+), 22 deletions(-) diff --git a/fs/notify/fanotify/fanotify.c b/fs/notify/fanotify/fanotify.c index ef567d07f5a6..3e8b3abe4952 100644 --- a/fs/notify/fanotify/fanotify.c +++ b/fs/notify/fanotify/fanotify.c @@ -114,14 +114,11 @@ 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)) - return 0; + 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; + } fsnotify_foreach_obj_type(type) { if (!fsnotify_iter_should_report_type(iter_info, type)) @@ -155,7 +152,7 @@ static u32 fanotify_group_event_mask(struct fsnotify_iter_info *iter_info, ~marks_ignored_mask; } -static struct fanotify_event_fid *fanotify_alloc_fid(const struct path *path, +static struct fanotify_event_fid *fanotify_alloc_fid(struct inode *inode, gfp_t gfp) { struct fanotify_event_fid *fid = NULL; @@ -164,7 +161,7 @@ static struct fanotify_event_fid *fanotify_alloc_fid(const struct path *path, 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; @@ -174,8 +171,8 @@ static struct fanotify_event_fid *fanotify_alloc_fid(const struct path *path, if (!fid) return NULL; - type = exportfs_encode_fh(path->dentry, (struct fid *)fid->f_handle, - &dwords, 0); + type = exportfs_encode_inode_fh(inode, (struct fid *)fid->f_handle, + &dwords, NULL); err = -EINVAL; if (type == FILEID_INVALID || bytes != dwords << 2) goto out_err; @@ -186,20 +183,42 @@ static struct fanotify_event_fid *fanotify_alloc_fid(const struct path *path, return fid; out_err: - pr_warn_ratelimited("fanotify: failed to encode fid of %pd2 (bytes=%d, err=%i)\n", - path->dentry, bytes, err); + pr_warn_ratelimited("fanotify: failed to encode fid (ino=%lu, type=%d, bytes=%d, err=%i)\n", + inode->i_ino, type, bytes, err); kfree(fid); return ERR_PTR(err); } +/* + * 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); + else + 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; struct fanotify_event_fid *fid = 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 @@ -212,8 +231,8 @@ struct fanotify_event *fanotify_alloc_event(struct fsnotify_group *group, /* Whoever is interested in the event, pays for the allocation. */ memalloc_use_memcg(group->memcg); - if (path && fsid && FAN_GROUP_FLAG(group, FAN_REPORT_FID)) { - fid = fanotify_alloc_fid(path, gfp); + if (id && fsid && FAN_GROUP_FLAG(group, FAN_REPORT_FID)) { + fid = fanotify_alloc_fid(id, gfp); /* Treat failure to allocate fid as failure to allocate event */ if (!fid) goto out; @@ -245,8 +264,8 @@ init: __maybe_unused event->pid = get_pid(task_tgid(current)); if (FAN_GROUP_FLAG(group, FAN_REPORT_FID)) { fanotify_set_fid(event, fid); - } else if (path) { - event->path = *path; + } else if (data_type == FSNOTIFY_EVENT_PATH) { + event->path = *((struct path *)data); path_get(&event->path); } else { event->path.mnt = NULL; @@ -283,10 +302,13 @@ static int fanotify_handle_event(struct fsnotify_group *group, BUILD_BUG_ON(HWEIGHT32(ALL_FANOTIFY_EVENT_BITS) != 12); + /* Events without path data require FAN_REPORT_FID */ if (FAN_GROUP_FLAG(group, FAN_REPORT_FID)) { __fsid.val[0] = 0; __fsid.val[1] = 0; fsid = &__fsid; + } else if (data_type != FSNOTIFY_EVENT_PATH) { + return 0; } mask = fanotify_group_event_mask(iter_info, mask, data, data_type, @@ -306,7 +328,7 @@ static int fanotify_handle_event(struct fsnotify_group *group, return 0; } - 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 b9938626b2a3..3c21c9a1278d 100644 --- a/fs/notify/fanotify/fanotify.h +++ b/fs/notify/fanotify/fanotify.h @@ -100,5 +100,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 92afb297fdea..9479bd418c31 100644 --- a/fs/notify/fanotify/fanotify_user.c +++ b/fs/notify/fanotify/fanotify_user.c @@ -799,7 +799,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;