From patchwork Thu Jan 10 17:04:35 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Amir Goldstein X-Patchwork-Id: 10756277 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 986E913B4 for ; Thu, 10 Jan 2019 17:05:08 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 8494129B55 for ; Thu, 10 Jan 2019 17:05:08 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 7629629AC2; Thu, 10 Jan 2019 17:05:08 +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 D014929AC2 for ; Thu, 10 Jan 2019 17:05:07 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729161AbfAJRFG (ORCPT ); Thu, 10 Jan 2019 12:05:06 -0500 Received: from mail-wr1-f68.google.com ([209.85.221.68]:40874 "EHLO mail-wr1-f68.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1729014AbfAJRFF (ORCPT ); Thu, 10 Jan 2019 12:05:05 -0500 Received: by mail-wr1-f68.google.com with SMTP id p4so12227802wrt.7; Thu, 10 Jan 2019 09:05:03 -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=TbsKielCxTPPC/9Y965tIpBTh5Y7ixaS+LQJvKrfj5Y=; b=hyUveTaOqNf3saJhlznfDFSXmB95Tj5ZOSmJdUaHP6e3vjiNYCXoA4FB3p9N578Oqi FezAibI5gRuZergUgDF2wcuv5GmUUriJG7yJruzAuGl85zF/M1oHQ9xLrcJRpySGPj3V UxkMVNq29dNCzVZH29xnPFWgKBIBUEzQyQgkncLad/BHNJTuVwvQqqOdBY4jBtOqY7OG ZwkyxMZD5mnc+msGp/LT5vXdGuy/efcDmWyMFHLPHlWhmIIGjsQgU8xr5MBswlXJFePn msXW4+2QCH5x+CQwM9+dUqhNA+NPqoBtIlQjXj+JGdAU7UcUbucUmixAQ6AzHeaWMYPL g6Yw== 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=TbsKielCxTPPC/9Y965tIpBTh5Y7ixaS+LQJvKrfj5Y=; b=LWQ5lm/f3PjwG3rdQSUHcS21h4T0M9bPtDFflNYzF+CbZmIEwFkNywRDjy6/mOw/eI VH8QsRdVWRIJktZCDPJ+KgMxMjGOVPL2DNMmXxGt8vIlLdDuejOb9MJCXwbxWnEHsQ9x cKYnd9SbumUWXOg6oLTG+tMaeX+T7TPBttjTW0IdQ3twwFDZv6aF9/B5yaIKl4DnLGGS 1ehRwyrEgbHPe2VzgN47jJy6hZgLLDgBeF97R+amI9W4iuiTL9ijjjTLxW71J+PMhA0K INEpy0BgNQveiaeAtIHA7nPC4T5BAYjB9rar7vY/WDvnqabjjxE8HbmEcAtym1K5CwgD gqvA== X-Gm-Message-State: AJcUukeMEPmigOtRlcK+zVOkEi6bGexcmxsFgALHQi5Oy4HrG3z2SJgr zd+LLGKb/JrkrmBCHjd2LW+8aq95 X-Google-Smtp-Source: ALg8bN7jR8ibSpn+TvSAzRYK8X1W2UWEQc8OsKtlJPBXWTlo/DY5oextRSPjYBwzE/95A9YlgZPzGw== X-Received: by 2002:adf:9422:: with SMTP id 31mr10783464wrq.106.1547139902728; Thu, 10 Jan 2019 09:05:02 -0800 (PST) Received: from amir-VirtualBox.ctera.local ([188.120.129.201]) by smtp.gmail.com with ESMTPSA id m4sm5725868wmi.3.2019.01.10.09.05.01 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 10 Jan 2019 09:05:01 -0800 (PST) From: Amir Goldstein To: Jan Kara Cc: Matthew Bobrowski , linux-fsdevel@vger.kernel.org, linux-api@vger.kernel.org Subject: [PATCH v5 08/17] fanotify: copy event fid info to user Date: Thu, 10 Jan 2019 19:04:35 +0200 Message-Id: <20190110170444.30616-9-amir73il@gmail.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20190110170444.30616-1-amir73il@gmail.com> References: <20190110170444.30616-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 If group requested FAN_REPORT_FID and event has file identifier, copy that information to user reading the event after event metadata. fid information is formatted as struct fanotify_event_info_fid that includes a generic header struct fanotify_event_info_header, so that other info types could be defined in the future using the same header. metadata->event_len includes the length of the fid information. The fid information includes the filesystem's fsid (see statfs(2)) followed by an NFS file handle of the file that could be passed as an argument to open_by_handle_at(2). Cc: Signed-off-by: Amir Goldstein --- fs/notify/fanotify/fanotify.h | 5 ++ fs/notify/fanotify/fanotify_user.c | 82 ++++++++++++++++++++++++++++-- include/uapi/linux/fanotify.h | 20 ++++++++ 3 files changed, 102 insertions(+), 5 deletions(-) diff --git a/fs/notify/fanotify/fanotify.h b/fs/notify/fanotify/fanotify.h index 271482fb9611..4aafc7144c3d 100644 --- a/fs/notify/fanotify/fanotify.h +++ b/fs/notify/fanotify/fanotify.h @@ -95,6 +95,11 @@ static inline bool fanotify_event_has_ext_fh(struct fanotify_event *event) event->fh_len > FANOTIFY_INLINE_FH_LEN; } +static inline void *fanotify_event_fh(struct fanotify_event *event) +{ + return fanotify_fid_fh(&event->fid, event->fh_len); +} + /* * Structure for permission fanotify events. It gets allocated and freed in * fanotify_handle_event() since we wait there for user response. When the diff --git a/fs/notify/fanotify/fanotify_user.c b/fs/notify/fanotify/fanotify_user.c index 68a1cb18ddd8..bd42e681a052 100644 --- a/fs/notify/fanotify/fanotify_user.c +++ b/fs/notify/fanotify/fanotify_user.c @@ -47,6 +47,18 @@ struct kmem_cache *fanotify_mark_cache __read_mostly; struct kmem_cache *fanotify_event_cachep __read_mostly; struct kmem_cache *fanotify_perm_event_cachep __read_mostly; +#define FANOTIFY_EVENT_ALIGN (sizeof(struct fanotify_event_info_header)) + +static int fanotify_event_info_len(struct fanotify_event *event) +{ + if (!fanotify_event_has_fid(event)) + return 0; + + return roundup(sizeof(struct fanotify_event_info_fid) + + sizeof(struct file_handle) + event->fh_len, + FANOTIFY_EVENT_ALIGN); +} + /* * Get an fsnotify notification event if one exists and is small * enough to fit in "count". Return an error pointer if the count @@ -57,6 +69,9 @@ struct kmem_cache *fanotify_perm_event_cachep __read_mostly; static struct fsnotify_event *get_one_event(struct fsnotify_group *group, size_t count) { + size_t event_size = FAN_EVENT_METADATA_LEN; + struct fanotify_event *event; + assert_spin_locked(&group->notification_lock); pr_debug("%s: group=%p count=%zd\n", __func__, group, count); @@ -64,11 +79,18 @@ static struct fsnotify_event *get_one_event(struct fsnotify_group *group, if (fsnotify_notify_queue_is_empty(group)) return NULL; - if (FAN_EVENT_METADATA_LEN > count) + if (FAN_GROUP_FLAG(group, FAN_REPORT_FID)) { + event = FANOTIFY_E(fsnotify_peek_first_event(group)); + event_size += fanotify_event_info_len(event); + } + + if (event_size > count) return ERR_PTR(-EINVAL); - /* held the notification_lock the whole time, so this is the - * same event we peeked above */ + /* + * Held the notification_lock the whole time, so this is the + * same event we peeked above + */ return fsnotify_remove_first_event(group); } @@ -174,6 +196,48 @@ static int process_access_response(struct fsnotify_group *group, return 0; } +static int copy_fid_to_user(struct fanotify_event *event, char __user *buf) +{ + struct fanotify_event_info_fid info = { }; + struct file_handle handle = { }; + size_t fh_len = event->fh_len; + size_t len = fanotify_event_info_len(event); + + if (!len) + return 0; + + if (WARN_ON_ONCE(len < sizeof(info) + sizeof(handle) + fh_len)) + return -EFAULT; + + /* Copy event info fid header followed by vaiable sized file handle */ + info.hdr.info_type = FAN_EVENT_INFO_TYPE_FID; + info.hdr.len = len; + info.fsid = event->fid.fsid; + if (copy_to_user(buf, &info, sizeof(info))) + return -EFAULT; + + buf += sizeof(info); + len -= sizeof(info); + handle.handle_type = event->fh_type; + handle.handle_bytes = fh_len; + if (copy_to_user(buf, &handle, sizeof(handle))) + return -EFAULT; + + buf += sizeof(handle); + len -= sizeof(handle); + if (copy_to_user(buf, fanotify_event_fh(event), fh_len)) + return -EFAULT; + + /* Pad with 0's */ + buf += fh_len; + len -= fh_len; + WARN_ON_ONCE(len < 0 || len >= FANOTIFY_EVENT_ALIGN); + if (len > 0 && clear_user(buf, len)) + return -EFAULT; + + return 0; +} + static ssize_t copy_event_to_user(struct fsnotify_group *group, struct fsnotify_event *fsn_event, char __user *buf, size_t count) @@ -197,6 +261,8 @@ static ssize_t copy_event_to_user(struct fsnotify_group *group, fd = create_fd(group, event, &f); if (fd < 0) return fd; + } else if (fanotify_event_has_fid(event)) { + metadata.event_len += fanotify_event_info_len(event); } metadata.fd = fd; @@ -208,14 +274,20 @@ static ssize_t copy_event_to_user(struct fsnotify_group *group, if (WARN_ON_ONCE(metadata.event_len > count)) goto out_close_fd; - if (copy_to_user(buf, &metadata, metadata.event_len)) + if (copy_to_user(buf, &metadata, FAN_EVENT_METADATA_LEN)) goto out_close_fd; if (fanotify_is_perm_event(event->mask)) FANOTIFY_PE(fsn_event)->fd = fd; - if (fd != FAN_NOFD) + if (fanotify_event_has_path(event)) { fd_install(fd, f); + } else if (fanotify_event_has_fid(event)) { + ret = copy_fid_to_user(event, buf + FAN_EVENT_METADATA_LEN); + if (ret < 0) + return ret; + } + return metadata.event_len; out_close_fd: diff --git a/include/uapi/linux/fanotify.h b/include/uapi/linux/fanotify.h index d07f3cbc2786..959ae2bdc7ca 100644 --- a/include/uapi/linux/fanotify.h +++ b/include/uapi/linux/fanotify.h @@ -107,6 +107,26 @@ struct fanotify_event_metadata { __s32 pid; }; +#define FAN_EVENT_INFO_TYPE_FID 1 + +/* Variable length info record following event metadata */ +struct fanotify_event_info_header { + __u8 info_type; + __u8 pad; + __u16 len; +}; + +/* Unique file identifier info record */ +struct fanotify_event_info_fid { + struct fanotify_event_info_header hdr; + __kernel_fsid_t fsid; + /* + * Following is an opaque struct file_handle that can be passed as + * an argument to open_by_handle_at(2). + */ + unsigned char handle[0]; +}; + struct fanotify_response { __s32 fd; __u32 response;